30#include "llvm/ADT/ArrayRef.h"
31#include "llvm/ADT/SmallSet.h"
32#include "llvm/ADT/SmallVector.h"
33#include "llvm/ADT/StringExtras.h"
34#include "llvm/Bitcode/BitcodeReader.h"
35#include "llvm/IR/Constants.h"
36#include "llvm/IR/DerivedTypes.h"
37#include "llvm/IR/GlobalValue.h"
38#include "llvm/IR/InstrTypes.h"
39#include "llvm/IR/Value.h"
40#include "llvm/Support/AtomicOrdering.h"
41#include "llvm/Support/raw_ostream.h"
49using namespace llvm::omp;
56 enum CGOpenMPRegionKind {
59 ParallelOutlinedRegion,
69 CGOpenMPRegionInfo(
const CapturedStmt &CS,
70 const CGOpenMPRegionKind RegionKind,
73 : CGCapturedStmtInfo(CS,
CR_OpenMP), RegionKind(RegionKind),
74 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
76 CGOpenMPRegionInfo(
const CGOpenMPRegionKind RegionKind,
79 : CGCapturedStmtInfo(
CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
80 Kind(Kind), HasCancel(HasCancel) {}
84 virtual const VarDecl *getThreadIDVariable()
const = 0;
87 void EmitBody(CodeGenFunction &CGF,
const Stmt *S)
override;
91 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
93 virtual void emitUntiedSwitch(CodeGenFunction & ) {}
95 CGOpenMPRegionKind getRegionKind()
const {
return RegionKind; }
99 bool hasCancel()
const {
return HasCancel; }
101 static bool classof(
const CGCapturedStmtInfo *Info) {
105 ~CGOpenMPRegionInfo()
override =
default;
108 CGOpenMPRegionKind RegionKind;
109 RegionCodeGenTy CodeGen;
115class CGOpenMPOutlinedRegionInfo final :
public CGOpenMPRegionInfo {
117 CGOpenMPOutlinedRegionInfo(
const CapturedStmt &CS,
const VarDecl *ThreadIDVar,
118 const RegionCodeGenTy &CodeGen,
120 StringRef HelperName)
121 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen,
Kind,
123 ThreadIDVar(ThreadIDVar), HelperName(HelperName) {
124 assert(ThreadIDVar !=
nullptr &&
"No ThreadID in OpenMP region.");
129 const VarDecl *getThreadIDVariable()
const override {
return ThreadIDVar; }
132 StringRef getHelperName()
const override {
return HelperName; }
134 static bool classof(
const CGCapturedStmtInfo *Info) {
135 return CGOpenMPRegionInfo::classof(Info) &&
137 ParallelOutlinedRegion;
143 const VarDecl *ThreadIDVar;
144 StringRef HelperName;
148class CGOpenMPTaskOutlinedRegionInfo final :
public CGOpenMPRegionInfo {
150 class UntiedTaskActionTy final :
public PrePostActionTy {
152 const VarDecl *PartIDVar;
153 const RegionCodeGenTy UntiedCodeGen;
154 llvm::SwitchInst *UntiedSwitch =
nullptr;
157 UntiedTaskActionTy(
bool Tied,
const VarDecl *PartIDVar,
158 const RegionCodeGenTy &UntiedCodeGen)
159 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
160 void Enter(CodeGenFunction &CGF)
override {
165 PartIDVar->
getType()->castAs<PointerType>());
169 UntiedSwitch = CGF.
Builder.CreateSwitch(Res, DoneBB);
173 UntiedSwitch->addCase(CGF.
Builder.getInt32(0),
175 emitUntiedSwitch(CGF);
178 void emitUntiedSwitch(CodeGenFunction &CGF)
const {
182 PartIDVar->
getType()->castAs<PointerType>());
186 CodeGenFunction::JumpDest CurPoint =
190 UntiedSwitch->addCase(CGF.
Builder.getInt32(UntiedSwitch->getNumCases()),
196 unsigned getNumberOfParts()
const {
return UntiedSwitch->getNumCases(); }
198 CGOpenMPTaskOutlinedRegionInfo(
const CapturedStmt &CS,
199 const VarDecl *ThreadIDVar,
200 const RegionCodeGenTy &CodeGen,
202 const UntiedTaskActionTy &Action)
203 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen,
Kind, HasCancel),
204 ThreadIDVar(ThreadIDVar), Action(Action) {
205 assert(ThreadIDVar !=
nullptr &&
"No ThreadID in OpenMP region.");
210 const VarDecl *getThreadIDVariable()
const override {
return ThreadIDVar; }
213 LValue getThreadIDVariableLValue(CodeGenFunction &CGF)
override;
216 StringRef getHelperName()
const override {
return ".omp_outlined."; }
218 void emitUntiedSwitch(CodeGenFunction &CGF)
override {
219 Action.emitUntiedSwitch(CGF);
222 static bool classof(
const CGCapturedStmtInfo *Info) {
223 return CGOpenMPRegionInfo::classof(Info) &&
231 const VarDecl *ThreadIDVar;
233 const UntiedTaskActionTy &Action;
238class CGOpenMPInlinedRegionInfo :
public CGOpenMPRegionInfo {
240 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
241 const RegionCodeGenTy &CodeGen,
243 : CGOpenMPRegionInfo(InlinedRegion, CodeGen,
Kind, HasCancel),
245 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
248 llvm::Value *getContextValue()
const override {
250 return OuterRegionInfo->getContextValue();
251 llvm_unreachable(
"No context value for inlined OpenMP region");
254 void setContextValue(llvm::Value *
V)
override {
255 if (OuterRegionInfo) {
256 OuterRegionInfo->setContextValue(
V);
259 llvm_unreachable(
"No context value for inlined OpenMP region");
263 const FieldDecl *lookup(
const VarDecl *VD)
const override {
265 return OuterRegionInfo->lookup(VD);
271 FieldDecl *getThisFieldDecl()
const override {
273 return OuterRegionInfo->getThisFieldDecl();
279 const VarDecl *getThreadIDVariable()
const override {
281 return OuterRegionInfo->getThreadIDVariable();
286 LValue getThreadIDVariableLValue(CodeGenFunction &CGF)
override {
288 return OuterRegionInfo->getThreadIDVariableLValue(CGF);
289 llvm_unreachable(
"No LValue for inlined OpenMP construct");
293 StringRef getHelperName()
const override {
294 if (
auto *OuterRegionInfo = getOldCSI())
295 return OuterRegionInfo->getHelperName();
296 llvm_unreachable(
"No helper name for inlined OpenMP construct");
299 void emitUntiedSwitch(CodeGenFunction &CGF)
override {
301 OuterRegionInfo->emitUntiedSwitch(CGF);
304 CodeGenFunction::CGCapturedStmtInfo *getOldCSI()
const {
return OldCSI; }
306 static bool classof(
const CGCapturedStmtInfo *Info) {
307 return CGOpenMPRegionInfo::classof(Info) &&
311 ~CGOpenMPInlinedRegionInfo()
override =
default;
315 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
316 CGOpenMPRegionInfo *OuterRegionInfo;
324class CGOpenMPTargetRegionInfo final :
public CGOpenMPRegionInfo {
326 CGOpenMPTargetRegionInfo(
const CapturedStmt &CS,
327 const RegionCodeGenTy &CodeGen, StringRef HelperName)
328 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
330 HelperName(HelperName) {}
334 const VarDecl *getThreadIDVariable()
const override {
return nullptr; }
337 StringRef getHelperName()
const override {
return HelperName; }
339 static bool classof(
const CGCapturedStmtInfo *Info) {
340 return CGOpenMPRegionInfo::classof(Info) &&
345 StringRef HelperName;
349 llvm_unreachable(
"No codegen for expressions");
353class CGOpenMPInnerExprInfo final :
public CGOpenMPInlinedRegionInfo {
355 CGOpenMPInnerExprInfo(CodeGenFunction &CGF,
const CapturedStmt &CS)
356 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
364 if (!C.capturesVariable() && !C.capturesVariableByCopy())
367 const VarDecl *VD = C.getCapturedVar();
368 if (VD->isLocalVarDeclOrParm())
371 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
373 VD->getType().getNonReferenceType(), VK_LValue,
375 PrivScope.addPrivate(VD, CGF.EmitLValue(&DRE).getAddress());
377 (
void)PrivScope.Privatize();
381 const FieldDecl *lookup(
const VarDecl *VD)
const override {
382 if (
const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
388 void EmitBody(CodeGenFunction &CGF,
const Stmt *S)
override {
389 llvm_unreachable(
"No body for expressions");
394 const VarDecl *getThreadIDVariable()
const override {
395 llvm_unreachable(
"No thread id for expressions");
399 StringRef getHelperName()
const override {
400 llvm_unreachable(
"No helper name for expressions");
403 static bool classof(
const CGCapturedStmtInfo *Info) {
return false; }
407 CodeGenFunction::OMPPrivateScope PrivScope;
411class InlinedOpenMPRegionRAII {
412 CodeGenFunction &CGF;
413 llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
414 FieldDecl *LambdaThisCaptureField =
nullptr;
415 const CodeGen::CGBlockInfo *BlockInfo =
nullptr;
416 bool NoInheritance =
false;
423 InlinedOpenMPRegionRAII(CodeGenFunction &CGF,
const RegionCodeGenTy &CodeGen,
425 bool NoInheritance =
true)
426 : CGF(CGF), NoInheritance(NoInheritance) {
428 CGF.CapturedStmtInfo =
new CGOpenMPInlinedRegionInfo(
429 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
431 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
432 LambdaThisCaptureField = CGF.LambdaThisCaptureField;
433 CGF.LambdaThisCaptureField =
nullptr;
434 BlockInfo = CGF.BlockInfo;
435 CGF.BlockInfo =
nullptr;
439 ~InlinedOpenMPRegionRAII() {
443 delete CGF.CapturedStmtInfo;
444 CGF.CapturedStmtInfo = OldCSI;
446 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
447 CGF.LambdaThisCaptureField = LambdaThisCaptureField;
448 CGF.BlockInfo = BlockInfo;
456enum OpenMPLocationFlags :
unsigned {
458 OMP_IDENT_IMD = 0x01,
460 OMP_IDENT_KMPC = 0x02,
462 OMP_ATOMIC_REDUCE = 0x10,
464 OMP_IDENT_BARRIER_EXPL = 0x20,
466 OMP_IDENT_BARRIER_IMPL = 0x40,
468 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
470 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
472 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140,
474 OMP_IDENT_WORK_LOOP = 0x200,
476 OMP_IDENT_WORK_SECTIONS = 0x400,
478 OMP_IDENT_WORK_DISTRIBUTE = 0x800,
508enum IdentFieldIndex {
510 IdentField_Reserved_1,
514 IdentField_Reserved_2,
516 IdentField_Reserved_3,
525enum OpenMPSchedType {
528 OMP_sch_static_chunked = 33,
530 OMP_sch_dynamic_chunked = 35,
531 OMP_sch_guided_chunked = 36,
532 OMP_sch_runtime = 37,
535 OMP_sch_static_balanced_chunked = 45,
538 OMP_ord_static_chunked = 65,
540 OMP_ord_dynamic_chunked = 67,
541 OMP_ord_guided_chunked = 68,
542 OMP_ord_runtime = 69,
544 OMP_sch_default = OMP_sch_static,
546 OMP_dist_sch_static_chunked = 91,
547 OMP_dist_sch_static = 92,
550 OMP_sch_modifier_monotonic = (1 << 29),
552 OMP_sch_modifier_nonmonotonic = (1 << 30),
557class CleanupTy final :
public EHScopeStack::Cleanup {
558 PrePostActionTy *Action;
561 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
562 void Emit(CodeGenFunction &CGF, Flags )
override {
575 Callback(CodeGen, CGF, *PrePostAction);
578 Callback(CodeGen, CGF, Action);
586 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
587 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
588 if (
const auto *DRE =
589 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
590 if (
const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
601 std::pair<llvm::Function *, llvm::Function *>
Reduction =
621 auto *GV =
new llvm::GlobalVariable(
623 llvm::GlobalValue::PrivateLinkage,
Init, Name);
664 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, DestAddr);
668 llvm::Value *SrcBegin =
nullptr;
670 SrcBegin = SrcAddr.emitRawPointer(CGF);
673 llvm::Value *DestEnd =
678 llvm::Value *IsEmpty =
679 CGF.
Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arrayinit.isempty");
680 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
683 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
688 llvm::PHINode *SrcElementPHI =
nullptr;
691 SrcElementPHI = CGF.
Builder.CreatePHI(SrcBegin->getType(), 2,
692 "omp.arraycpy.srcElementPast");
693 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
695 Address(SrcElementPHI, SrcAddr.getElementType(),
696 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
698 llvm::PHINode *DestElementPHI = CGF.
Builder.CreatePHI(
699 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
700 DestElementPHI->addIncoming(DestBegin, EntryBB);
708 if (EmitDeclareReductionInit) {
710 SrcElementCurrent, ElementTy);
718 llvm::Value *SrcElementNext = CGF.
Builder.CreateConstGEP1_32(
719 SrcAddr.getElementType(), SrcElementPHI, 1,
720 "omp.arraycpy.dest.element");
721 SrcElementPHI->addIncoming(SrcElementNext, CGF.
Builder.GetInsertBlock());
725 llvm::Value *DestElementNext = CGF.
Builder.CreateConstGEP1_32(
727 "omp.arraycpy.dest.element");
730 CGF.
Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
731 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
732 DestElementPHI->addIncoming(DestElementNext, CGF.
Builder.GetInsertBlock());
744 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(E))
749void ReductionCodeGen::emitAggregateInitialization(
751 const OMPDeclareReductionDecl *DRD) {
755 const auto *PrivateVD =
757 bool EmitDeclareReductionInit =
760 EmitDeclareReductionInit,
761 EmitDeclareReductionInit ? ClausesData[N].ReductionOp
762 : PrivateVD->getInit(),
770 ClausesData.reserve(Shareds.size());
771 SharedAddresses.reserve(Shareds.size());
772 Sizes.reserve(Shareds.size());
773 BaseDecls.reserve(Shareds.size());
774 const auto *IOrig = Origs.begin();
775 const auto *IPriv = Privates.begin();
776 const auto *IRed = ReductionOps.begin();
777 for (
const Expr *Ref : Shareds) {
778 ClausesData.emplace_back(Ref, *IOrig, *IPriv, *IRed);
779 std::advance(IOrig, 1);
780 std::advance(IPriv, 1);
781 std::advance(IRed, 1);
786 assert(SharedAddresses.size() == N && OrigAddresses.size() == N &&
787 "Number of generated lvalues must be exactly N.");
788 LValue First = emitSharedLValue(CGF, ClausesData[N].Shared);
789 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Shared);
790 SharedAddresses.emplace_back(
First, Second);
791 if (ClausesData[N].Shared == ClausesData[N].Ref) {
792 OrigAddresses.emplace_back(
First, Second);
794 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref);
795 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref);
796 OrigAddresses.emplace_back(
First, Second);
805 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()),
810 llvm::Value *SizeInChars;
811 auto *ElemType = OrigAddresses[N].first.getAddress().getElementType();
812 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType);
813 if (AsArraySection) {
814 Size = CGF.
Builder.CreatePtrDiff(ElemType,
815 OrigAddresses[N].second.getPointer(CGF),
816 OrigAddresses[N].first.getPointer(CGF));
817 Size = CGF.
Builder.CreateNUWAdd(
818 Size, llvm::ConstantInt::get(Size->getType(), 1));
819 SizeInChars = CGF.
Builder.CreateNUWMul(Size, ElemSizeOf);
822 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType());
823 Size = CGF.
Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
825 Sizes.emplace_back(SizeInChars, Size);
838 assert(!Size && !Sizes[N].second &&
839 "Size should be nullptr for non-variably modified reduction "
854 assert(SharedAddresses.size() > N &&
"No variable was generated");
855 const auto *PrivateVD =
861 (void)DefaultInit(CGF);
862 emitAggregateInitialization(CGF, N, PrivateAddr, SharedAddr, DRD);
863 }
else if (DRD && (DRD->
getInitializer() || !PrivateVD->hasInit())) {
864 (void)DefaultInit(CGF);
865 QualType SharedType = SharedAddresses[N].first.getType();
867 PrivateAddr, SharedAddr, SharedType);
868 }
else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&
871 PrivateVD->
getType().getQualifiers(),
889 CGF.
pushDestroy(DTorKind, PrivateAddr, PrivateType);
908 BaseLV.getType(), BaseLV.getBaseInfo(),
942 const VarDecl *OrigVD =
nullptr;
943 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(Ref)) {
944 const Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
945 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
946 Base = TempOASE->getBase()->IgnoreParenImpCasts();
947 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
948 Base = TempASE->getBase()->IgnoreParenImpCasts();
951 }
else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
952 const Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
953 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
954 Base = TempASE->getBase()->IgnoreParenImpCasts();
965 BaseDecls.emplace_back(OrigVD);
968 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
970 Address SharedAddr = SharedAddresses[N].first.getAddress();
971 llvm::Value *Adjustment = CGF.
Builder.CreatePtrDiff(
974 llvm::Value *PrivatePointer =
980 SharedAddresses[N].first.getType(),
983 BaseDecls.emplace_back(
997 getThreadIDVariable()->
getType()->castAs<PointerType>());
1015LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1018 getThreadIDVariable()->
getType(),
1036 llvm::OpenMPIRBuilderConfig Config(
1037 CGM.getLangOpts().OpenMPIsTargetDevice,
isGPU(),
1038 CGM.getLangOpts().OpenMPOffloadMandatory,
1041 Config.setDefaultTargetAS(
1043 Config.setRuntimeCC(
CGM.getRuntimeCC());
1048 CGM.getLangOpts().OpenMPIsTargetDevice
1049 ?
CGM.getLangOpts().OMPHostIRFile
1054 if (
CGM.getLangOpts().OpenMPForceUSM) {
1056 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
1064 if (!
Data.getValue().pointsToAliveValue())
1066 auto *GV = dyn_cast<llvm::GlobalVariable>(
Data.getValue());
1069 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1071 GV->eraseFromParent();
1076 return OMPBuilder.createPlatformSpecificName(Parts);
1079static llvm::Function *
1081 const Expr *CombinerInitializer,
const VarDecl *In,
1082 const VarDecl *Out,
bool IsCombiner) {
1085 QualType PtrTy =
C.getPointerType(Ty).withRestrict();
1091 Args.push_back(&OmpOutParm);
1092 Args.push_back(&OmpInParm);
1097 {IsCombiner ?
"omp_combiner" :
"omp_initializer",
""});
1098 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1102 Fn->removeFnAttr(llvm::Attribute::NoInline);
1103 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1104 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1110 Out->getLocation());
1120 (void)
Scope.Privatize();
1121 if (!IsCombiner && Out->hasInit() &&
1124 Out->getType().getQualifiers(),
1127 if (CombinerInitializer)
1129 Scope.ForceCleanup();
1158std::pair<llvm::Function *, llvm::Function *>
1170struct PushAndPopStackRAII {
1171 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder,
CodeGenFunction &CGF,
1172 bool HasCancel, llvm::omp::Directive Kind)
1173 : OMPBuilder(OMPBuilder) {
1189 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) {
1190 assert(IP.getBlock()->end() == IP.getPoint() &&
1191 "Clang CG should cause non-terminated block!");
1192 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1197 return llvm::Error::success();
1202 llvm::OpenMPIRBuilder::FinalizationInfo FI({FiniCB, Kind, HasCancel});
1203 OMPBuilder->pushFinalizationCB(std::move(FI));
1205 ~PushAndPopStackRAII() {
1207 OMPBuilder->popFinalizationCB();
1209 llvm::OpenMPIRBuilder *OMPBuilder;
1218 "thread id variable must be of type kmp_int32 *");
1220 bool HasCancel =
false;
1221 if (
const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
1222 HasCancel = OPD->hasCancel();
1223 else if (
const auto *OPD = dyn_cast<OMPTargetParallelDirective>(&D))
1224 HasCancel = OPD->hasCancel();
1225 else if (
const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
1226 HasCancel = OPSD->hasCancel();
1227 else if (
const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
1228 HasCancel = OPFD->hasCancel();
1229 else if (
const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
1230 HasCancel = OPFD->hasCancel();
1231 else if (
const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
1232 HasCancel = OPFD->hasCancel();
1233 else if (
const auto *OPFD =
1234 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
1235 HasCancel = OPFD->hasCancel();
1236 else if (
const auto *OPFD =
1237 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
1238 HasCancel = OPFD->hasCancel();
1243 PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel, InnermostKind);
1244 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar,
CodeGen, InnermostKind,
1245 HasCancel, OutlinedHelperName);
1251 std::string Suffix =
getName({
"omp_outlined"});
1252 return (Name + Suffix).str();
1260 std::string Suffix =
getName({
"omp",
"reduction",
"reduction_func"});
1261 return (Name + Suffix).str();
1268 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
1278 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
1288 bool Tied,
unsigned &NumberOfParts) {
1291 llvm::Value *ThreadID =
getThreadID(CGF, D.getBeginLoc());
1293 llvm::Value *TaskArgs[] = {
1295 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1298 CGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(
1299 CGM.getModule(), OMPRTL___kmpc_omp_task),
1302 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1306 "thread id variable must be of type kmp_int32 for tasks");
1311 bool HasCancel =
false;
1312 if (
const auto *TD = dyn_cast<OMPTaskDirective>(&D))
1313 HasCancel = TD->hasCancel();
1314 else if (
const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D))
1315 HasCancel = TD->hasCancel();
1316 else if (
const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D))
1317 HasCancel = TD->hasCancel();
1318 else if (
const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D))
1319 HasCancel = TD->hasCancel();
1322 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar,
CodeGen,
1323 InnermostKind, HasCancel, Action);
1325 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
1327 NumberOfParts = Action.getNumberOfParts();
1332 bool AtCurrentPoint) {
1334 assert(!Elem.ServiceInsertPt &&
"Insert point is set already.");
1336 llvm::Value *Undef = llvm::UndefValue::get(CGF.
Int32Ty);
1337 if (AtCurrentPoint) {
1338 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt",
1339 CGF.
Builder.GetInsertBlock());
1341 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt");
1342 Elem.ServiceInsertPt->insertAfter(CGF.
AllocaInsertPt->getIterator());
1348 if (Elem.ServiceInsertPt) {
1349 llvm::Instruction *Ptr = Elem.ServiceInsertPt;
1350 Elem.ServiceInsertPt =
nullptr;
1351 Ptr->eraseFromParent();
1358 llvm::raw_svector_ostream OS(Buffer);
1367 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1368 OS << FD->getQualifiedNameAsString();
1375 unsigned Flags,
bool EmitLoc) {
1376 uint32_t SrcLocStrSize;
1377 llvm::Constant *SrcLocStr;
1378 if ((!EmitLoc &&
CGM.getCodeGenOpts().getDebugInfo() ==
1379 llvm::codegenoptions::NoDebugInfo) ||
1381 SrcLocStr =
OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
1383 std::string FunctionName;
1385 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1386 FunctionName = FD->getQualifiedNameAsString();
1399 SrcLocStr, SrcLocStrSize, llvm::omp::IdentFlag(Flags), Reserved2Flags);
1404 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1407 if (
CGM.getLangOpts().OpenMPIRBuilder) {
1410 uint32_t SrcLocStrSize;
1411 auto *SrcLocStr =
OMPBuilder.getOrCreateSrcLocStr(
1414 OMPBuilder.getOrCreateIdent(SrcLocStr, SrcLocStrSize));
1417 llvm::Value *ThreadID =
nullptr;
1422 ThreadID = I->second.ThreadID;
1423 if (ThreadID !=
nullptr)
1427 if (
auto *OMPRegionInfo =
1429 if (OMPRegionInfo->getThreadIDVariable()) {
1431 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
1435 CGF.
Builder.GetInsertBlock() == TopBlock ||
1440 CGF.
Builder.GetInsertBlock()) {
1444 if (CGF.
Builder.GetInsertBlock() == TopBlock)
1456 if (!Elem.ServiceInsertPt)
1458 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1459 CGF.
Builder.SetInsertPoint(Elem.ServiceInsertPt);
1463 OMPRTL___kmpc_global_thread_num),
1466 Elem.ThreadID =
Call;
1471 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1477 for (
const auto *D : I->second)
1482 for (
const auto *D : I->second)
1494static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind
1496 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
1497 OMPDeclareTargetDeclAttr::getDeviceType(VD);
1499 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1501 switch ((
int)*DevTy) {
1502 case OMPDeclareTargetDeclAttr::DT_Host:
1503 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseHost;
1505 case OMPDeclareTargetDeclAttr::DT_NoHost:
1506 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNoHost;
1508 case OMPDeclareTargetDeclAttr::DT_Any:
1509 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny;
1512 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1517static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind
1519 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapType =
1520 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
1522 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1523 switch ((
int)*MapType) {
1524 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_To:
1525 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
1527 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Enter:
1528 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
1530 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Link:
1531 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
1534 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1543 auto FileInfoCallBack = [&]() {
1548 PLoc =
SM.getPresumedLoc(BeginLoc,
false);
1553 return OMPBuilder.getTargetEntryUniqueInfo(FileInfoCallBack,
1558 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
1560 auto LinkageForVariable = [&VD,
this]() {
1561 return CGM.getLLVMLinkageVarDefinition(VD);
1564 std::vector<llvm::GlobalVariable *> GeneratedRefs;
1566 llvm::Type *LlvmPtrTy =
CGM.getTypes().ConvertTypeForMem(
1567 CGM.getContext().getPointerType(VD->
getType()));
1568 llvm::Constant *addr =
OMPBuilder.getAddrOfDeclareTargetVar(
1574 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
1575 CGM.getLangOpts().OMPTargetTriples, LlvmPtrTy, AddrOfGlobal,
1576 LinkageForVariable);
1585 assert(!
CGM.getLangOpts().OpenMPUseTLS ||
1586 !
CGM.getContext().getTargetInfo().isTLSSupported());
1588 std::string Suffix =
getName({
"cache",
""});
1589 return OMPBuilder.getOrCreateInternalVariable(
1590 CGM.Int8PtrPtrTy, Twine(
CGM.getMangledName(VD)).concat(Suffix).str());
1597 if (
CGM.getLangOpts().OpenMPUseTLS &&
1598 CGM.getContext().getTargetInfo().isTLSSupported())
1602 llvm::Value *Args[] = {
1605 CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy)),
1610 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1622 CGM.getModule(), OMPRTL___kmpc_global_thread_num),
1626 llvm::Value *Args[] = {
1629 Ctor, CopyCtor, Dtor};
1632 CGM.getModule(), OMPRTL___kmpc_threadprivate_register),
1639 if (
CGM.getLangOpts().OpenMPUseTLS &&
1640 CGM.getContext().getTargetInfo().isTLSSupported())
1647 llvm::Value *Ctor =
nullptr, *CopyCtor =
nullptr, *Dtor =
nullptr;
1649 if (
CGM.getLangOpts().CPlusPlus && PerformInit) {
1655 nullptr,
CGM.getContext().VoidPtrTy,
1657 Args.push_back(&Dst);
1659 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1660 CGM.getContext().VoidPtrTy, Args);
1661 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1662 std::string Name =
getName({
"__kmpc_global_ctor_",
""});
1663 llvm::Function *Fn =
1664 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1687 nullptr,
CGM.getContext().VoidPtrTy,
1689 Args.push_back(&Dst);
1691 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1692 CGM.getContext().VoidTy, Args);
1693 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1694 std::string Name =
getName({
"__kmpc_global_dtor_",
""});
1695 llvm::Function *Fn =
1696 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1719 CopyCtor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1720 if (Ctor ==
nullptr) {
1721 Ctor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1723 if (Dtor ==
nullptr) {
1724 Dtor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1727 auto *InitFunctionTy =
1728 llvm::FunctionType::get(
CGM.VoidTy,
false);
1729 std::string Name =
getName({
"__omp_threadprivate_init_",
""});
1730 llvm::Function *InitFunction =
CGM.CreateGlobalInitOrCleanUpFunction(
1731 InitFunctionTy, Name,
CGM.getTypes().arrangeNullaryFunction());
1735 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1739 return InitFunction;
1747 llvm::GlobalValue *GV) {
1748 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
1749 OMPDeclareTargetDeclAttr::getActiveAttr(FD);
1752 if (!ActiveAttr || !(*ActiveAttr)->getIndirect())
1759 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(Name, EntryInfo);
1765 llvm::GlobalValue *
Addr = GV;
1766 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
1767 llvm::PointerType *FnPtrTy = llvm::PointerType::get(
1768 CGM.getLLVMContext(),
1769 CGM.getModule().getDataLayout().getProgramAddressSpace());
1770 Addr =
new llvm::GlobalVariable(
1771 CGM.getModule(), FnPtrTy,
1772 true, llvm::GlobalValue::ExternalLinkage, GV, Name,
1773 nullptr, llvm::GlobalValue::NotThreadLocal,
1774 CGM.getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1775 Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1778 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1779 Name,
Addr,
CGM.GetTargetTypeStoreSize(
CGM.VoidPtrTy).getQuantity(),
1780 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirect,
1781 llvm::GlobalValue::WeakODRLinkage);
1787 std::string Suffix =
getName({
"artificial",
""});
1789 llvm::GlobalVariable *GAddr =
OMPBuilder.getOrCreateInternalVariable(
1790 VarLVType, Twine(Name).concat(Suffix).str());
1791 if (
CGM.getLangOpts().OpenMP &&
CGM.getLangOpts().OpenMPUseTLS &&
1792 CGM.getTarget().isTLSSupported()) {
1793 GAddr->setThreadLocal(
true);
1794 return Address(GAddr, GAddr->getValueType(),
1795 CGM.getContext().getTypeAlignInChars(VarType));
1797 std::string CacheSuffix =
getName({
"cache",
""});
1798 llvm::Value *Args[] = {
1806 Twine(Name).concat(Suffix).concat(CacheSuffix).str())};
1811 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1814 VarLVType,
CGM.getContext().getTypeAlignInChars(VarType));
1864 auto &M =
CGM.getModule();
1865 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc,
1868 llvm::Value *Args[] = {
1870 CGF.
Builder.getInt32(CapturedVars.size()),
1873 RealArgs.append(std::begin(Args), std::end(Args));
1874 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
1876 llvm::FunctionCallee RTLFn =
1877 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call);
1880 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc, Loc,
1886 llvm::Value *Args[] = {RTLoc, ThreadID};
1888 M, OMPRTL___kmpc_serialized_parallel),
1895 ".bound.zero.addr");
1900 OutlinedFnArgs.push_back(ZeroAddrBound.
getPointer());
1901 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
1909 OutlinedFn->removeFnAttr(llvm::Attribute::AlwaysInline);
1910 OutlinedFn->addFnAttr(llvm::Attribute::NoInline);
1916 M, OMPRTL___kmpc_end_serialized_parallel),
1935 if (
auto *OMPRegionInfo =
1937 if (OMPRegionInfo->getThreadIDVariable())
1938 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
1947 return ThreadIDTemp;
1951 std::string Prefix = Twine(
"gomp_critical_user_", CriticalName).str();
1952 std::string Name =
getName({Prefix,
"var"});
1959 llvm::FunctionCallee EnterCallee;
1961 llvm::FunctionCallee ExitCallee;
1964 llvm::BasicBlock *ContBlock =
nullptr;
1967 CommonActionTy(llvm::FunctionCallee EnterCallee,
1969 llvm::FunctionCallee ExitCallee,
1971 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
1976 llvm::Value *CallBool = CGF.
Builder.CreateIsNotNull(EnterRes);
1980 CGF.
Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
1984 void Done(CodeGenFunction &CGF) {
1989 void Exit(CodeGenFunction &CGF)
override {
1996 StringRef CriticalName,
2005 llvm::FunctionCallee RuntimeFcn =
OMPBuilder.getOrCreateRuntimeFunction(
2007 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical);
2009 unsigned LockVarArgIdx = 2;
2011 RuntimeFcn.getFunctionType()
2012 ->getParamType(LockVarArgIdx)
2013 ->getPointerAddressSpace())
2015 LockVar, RuntimeFcn.getFunctionType()->getParamType(LockVarArgIdx));
2021 EnterArgs.push_back(CGF.
Builder.CreateIntCast(
2024 CommonActionTy Action(RuntimeFcn, EnterArgs,
2026 CGM.getModule(), OMPRTL___kmpc_end_critical),
2043 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2044 CGM.getModule(), OMPRTL___kmpc_master),
2047 CGM.getModule(), OMPRTL___kmpc_end_master),
2065 llvm::Value *FilterVal = Filter
2067 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
2072 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2073 CGM.getModule(), OMPRTL___kmpc_masked),
2076 CGM.getModule(), OMPRTL___kmpc_end_masked),
2092 llvm::Value *Args[] = {
2094 llvm::ConstantInt::get(
CGM.IntTy, 0,
true)};
2096 CGM.getModule(), OMPRTL___kmpc_omp_taskyield),
2100 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
2101 Region->emitUntiedSwitch(CGF);
2114 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2115 CGM.getModule(), OMPRTL___kmpc_taskgroup),
2118 CGM.getModule(), OMPRTL___kmpc_end_taskgroup),
2127 unsigned Index,
const VarDecl *Var) {
2148 Args.push_back(&LHSArg);
2149 Args.push_back(&RHSArg);
2155 llvm::GlobalValue::InternalLinkage, Name,
2158 Fn->setDoesNotRecurse();
2175 for (
unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
2176 const auto *DestVar =
2180 const auto *SrcVar =
2186 CGF.
EmitOMPCopy(
Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
2201 assert(CopyprivateVars.size() == SrcExprs.size() &&
2202 CopyprivateVars.size() == DstExprs.size() &&
2203 CopyprivateVars.size() == AssignmentOps.size());
2215 if (!CopyprivateVars.empty()) {
2218 C.getIntTypeForBitwidth(32, 1);
2219 DidIt = CGF.
CreateMemTemp(KmpInt32Ty,
".omp.copyprivate.did_it");
2224 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2225 CGM.getModule(), OMPRTL___kmpc_single),
2228 CGM.getModule(), OMPRTL___kmpc_end_single),
2241 llvm::APInt ArraySize(32, CopyprivateVars.size());
2242 QualType CopyprivateArrayTy =
C.getConstantArrayType(
2247 CGF.
CreateMemTemp(CopyprivateArrayTy,
".omp.copyprivate.cpr_list");
2248 for (
unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
2260 SrcExprs, DstExprs, AssignmentOps, Loc);
2261 llvm::Value *BufSize = CGF.
getTypeSize(CopyprivateArrayTy);
2265 llvm::Value *Args[] = {
2269 CL.emitRawPointer(CGF),
2274 CGM.getModule(), OMPRTL___kmpc_copyprivate),
2290 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2291 CGM.getModule(), OMPRTL___kmpc_ordered),
2294 CGM.getModule(), OMPRTL___kmpc_end_ordered),
2305 if (Kind == OMPD_for)
2306 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2307 else if (Kind == OMPD_sections)
2308 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2309 else if (Kind == OMPD_single)
2310 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2311 else if (Kind == OMPD_barrier)
2312 Flags = OMP_IDENT_BARRIER_EXPL;
2314 Flags = OMP_IDENT_BARRIER_IMPL;
2326 ScheduleKind = OMPC_SCHEDULE_static;
2328 llvm::APInt ChunkSize(32, 1);
2338 bool ForceSimpleCall) {
2340 auto *OMPRegionInfo =
2343 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2346 CGF.
Builder.restoreIP(AfterIP);
2359 if (OMPRegionInfo) {
2360 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
2363 OMPRTL___kmpc_cancel_barrier),
2372 CGF.
Builder.CreateCondBr(Cmp, ExitBB, ContBB);
2384 CGM.getModule(), OMPRTL___kmpc_barrier),
2389 Expr *ME,
bool IsFatal) {
2391 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2394 llvm::Value *Args[] = {
2396 llvm::ConstantInt::get(
CGM.Int32Ty, IsFatal ? 2 : 1),
2397 CGF.
Builder.CreatePointerCast(MVL,
CGM.Int8PtrTy)};
2399 CGM.getModule(), OMPRTL___kmpc_error),
2405 bool Chunked,
bool Ordered) {
2406 switch (ScheduleKind) {
2407 case OMPC_SCHEDULE_static:
2408 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2409 : (Ordered ? OMP_ord_static : OMP_sch_static);
2410 case OMPC_SCHEDULE_dynamic:
2411 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
2412 case OMPC_SCHEDULE_guided:
2413 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
2414 case OMPC_SCHEDULE_runtime:
2415 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2416 case OMPC_SCHEDULE_auto:
2417 return Ordered ? OMP_ord_auto : OMP_sch_auto;
2419 assert(!Chunked &&
"chunk was specified but schedule kind not known");
2420 return Ordered ? OMP_ord_static : OMP_sch_static;
2422 llvm_unreachable(
"Unexpected runtime schedule");
2426static OpenMPSchedType
2429 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2433 bool Chunked)
const {
2434 OpenMPSchedType Schedule =
2436 return Schedule == OMP_sch_static;
2442 return Schedule == OMP_dist_sch_static;
2446 bool Chunked)
const {
2447 OpenMPSchedType Schedule =
2449 return Schedule == OMP_sch_static_chunked;
2455 return Schedule == OMP_dist_sch_static_chunked;
2459 OpenMPSchedType Schedule =
2461 assert(Schedule != OMP_sch_static_chunked &&
"cannot be chunked here");
2462 return Schedule != OMP_sch_static;
2470 case OMPC_SCHEDULE_MODIFIER_monotonic:
2471 Modifier = OMP_sch_modifier_monotonic;
2473 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2474 Modifier = OMP_sch_modifier_nonmonotonic;
2476 case OMPC_SCHEDULE_MODIFIER_simd:
2477 if (Schedule == OMP_sch_static_chunked)
2478 Schedule = OMP_sch_static_balanced_chunked;
2485 case OMPC_SCHEDULE_MODIFIER_monotonic:
2486 Modifier = OMP_sch_modifier_monotonic;
2488 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2489 Modifier = OMP_sch_modifier_nonmonotonic;
2491 case OMPC_SCHEDULE_MODIFIER_simd:
2492 if (Schedule == OMP_sch_static_chunked)
2493 Schedule = OMP_sch_static_balanced_chunked;
2505 if (CGM.
getLangOpts().OpenMP >= 50 && Modifier == 0) {
2506 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
2507 Schedule == OMP_sch_static_balanced_chunked ||
2508 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
2509 Schedule == OMP_dist_sch_static_chunked ||
2510 Schedule == OMP_dist_sch_static))
2511 Modifier = OMP_sch_modifier_nonmonotonic;
2513 return Schedule | Modifier;
2523 ScheduleKind.
Schedule, DispatchValues.
Chunk !=
nullptr, Ordered);
2525 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
2526 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
2527 Schedule != OMP_sch_static_balanced_chunked));
2534 llvm::Value *Chunk = DispatchValues.
Chunk ? DispatchValues.
Chunk
2535 : CGF.
Builder.getIntN(IVSize, 1);
2536 llvm::Value *Args[] = {
2540 CGM, Schedule, ScheduleKind.
M1, ScheduleKind.
M2)),
2543 CGF.
Builder.getIntN(IVSize, 1),
2560 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
2561 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
2568 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2569 Schedule == OMP_sch_static_balanced_chunked ||
2570 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
2571 Schedule == OMP_dist_sch_static ||
2572 Schedule == OMP_dist_sch_static_chunked);
2579 llvm::Value *Chunk = Values.
Chunk;
2580 if (Chunk ==
nullptr) {
2581 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
2582 Schedule == OMP_dist_sch_static) &&
2583 "expected static non-chunked schedule");
2587 assert((Schedule == OMP_sch_static_chunked ||
2588 Schedule == OMP_sch_static_balanced_chunked ||
2589 Schedule == OMP_ord_static_chunked ||
2590 Schedule == OMP_dist_sch_static_chunked) &&
2591 "expected static chunked schedule");
2593 llvm::Value *Args[] = {
2616 "Expected loop-based or sections-based directive.");
2619 ? OMP_IDENT_WORK_LOOP
2620 : OMP_IDENT_WORK_SECTIONS);
2622 llvm::FunctionCallee StaticInitFunction =
2627 ScheduleNum, ScheduleKind.
M1, ScheduleKind.
M2, Values);
2634 OpenMPSchedType ScheduleNum =
2636 llvm::Value *UpdatedLocation =
2639 llvm::FunctionCallee StaticInitFunction;
2640 bool isGPUDistribute =
2641 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU();
2642 StaticInitFunction =
OMPBuilder.createForStaticInitFunction(
2653 assert((DKind == OMPD_distribute || DKind == OMPD_for ||
2654 DKind == OMPD_sections) &&
2655 "Expected distribute, for, or sections directive kind");
2659 llvm::Value *Args[] = {
2662 (DKind == OMPD_target_teams_loop)
2663 ? OMP_IDENT_WORK_DISTRIBUTE
2665 ? OMP_IDENT_WORK_LOOP
2666 : OMP_IDENT_WORK_SECTIONS),
2670 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU())
2673 CGM.getModule(), OMPRTL___kmpc_distribute_static_fini),
2677 CGM.getModule(), OMPRTL___kmpc_for_static_fini),
2702 llvm::Value *Args[] = {
2710 OMPBuilder.createDispatchNextFunction(IVSize, IVSigned), Args);
2717 const Expr *Message,
2720 return llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2729 return llvm::ConstantInt::get(
CGM.Int32Ty,
2730 Severity == OMPC_SEVERITY_warning ? 1 : 2);
2746 RuntimeFunction FnID = OMPRTL___kmpc_push_num_threads;
2747 if (Modifier == OMPC_NUMTHREADS_strict) {
2748 FnID = OMPRTL___kmpc_push_num_threads_strict;
2753 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args);
2757 ProcBindKind ProcBind,
2761 assert(ProcBind != OMP_PROC_BIND_unknown &&
"Unsupported proc_bind value.");
2763 llvm::Value *Args[] = {
2765 llvm::ConstantInt::get(
CGM.IntTy,
unsigned(ProcBind),
true)};
2767 CGM.getModule(), OMPRTL___kmpc_push_proc_bind),
2780 CGM.getModule(), OMPRTL___kmpc_flush),
2787enum KmpTaskTFields {
2814 if (
CGM.getLangOpts().OpenMPSimd ||
OMPBuilder.OffloadInfoManager.empty())
2817 llvm::OpenMPIRBuilder::EmitMetadataErrorReportFunctionTy &&ErrorReportFn =
2818 [
this](llvm::OpenMPIRBuilder::EmitMetadataErrorKind Kind,
2819 const llvm::TargetRegionEntryInfo &EntryInfo) ->
void {
2821 if (Kind != llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR) {
2822 for (
auto I =
CGM.getContext().getSourceManager().fileinfo_begin(),
2823 E =
CGM.getContext().getSourceManager().fileinfo_end();
2825 if (I->getFirst().getUniqueID().getDevice() == EntryInfo.DeviceID &&
2826 I->getFirst().getUniqueID().getFile() == EntryInfo.FileID) {
2827 Loc =
CGM.getContext().getSourceManager().translateFileLineCol(
2828 I->getFirst(), EntryInfo.Line, 1);
2834 case llvm::OpenMPIRBuilder::EMIT_MD_TARGET_REGION_ERROR: {
2835 unsigned DiagID =
CGM.getDiags().getCustomDiagID(
2837 "%0 is incorrect: either the "
2838 "address or the ID is invalid.");
2839 CGM.getDiags().Report(Loc, DiagID) << EntryInfo.ParentName;
2841 case llvm::OpenMPIRBuilder::EMIT_MD_DECLARE_TARGET_ERROR: {
2842 unsigned DiagID =
CGM.getDiags().getCustomDiagID(
2844 "variable %0 is incorrect: the "
2845 "address is invalid.");
2846 CGM.getDiags().Report(Loc, DiagID) << EntryInfo.ParentName;
2848 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR: {
2849 unsigned DiagID =
CGM.getDiags().getCustomDiagID(
2851 "Offloading entry for declare target variable is incorrect: the "
2852 "address is invalid.");
2853 CGM.getDiags().Report(DiagID);
2858 OMPBuilder.createOffloadEntriesAndInfoMetadata(ErrorReportFn);
2865 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty,
C.VoidPtrTy};
2868 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
2874struct PrivateHelpersTy {
2875 PrivateHelpersTy(
const Expr *OriginalRef,
const VarDecl *Original,
2877 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy),
2878 PrivateElemInit(PrivateElemInit) {}
2879 PrivateHelpersTy(
const VarDecl *Original) : Original(Original) {}
2880 const Expr *OriginalRef =
nullptr;
2881 const VarDecl *Original =
nullptr;
2882 const VarDecl *PrivateCopy =
nullptr;
2883 const VarDecl *PrivateElemInit =
nullptr;
2884 bool isLocalPrivate()
const {
2885 return !OriginalRef && !PrivateCopy && !PrivateElemInit;
2888typedef std::pair<CharUnits , PrivateHelpersTy> PrivateDataTy;
2893 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
2895 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
2897 return !(AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
2898 !AA->getAllocator());
2903 if (!Privates.empty()) {
2908 RecordDecl *RD =
C.buildImplicitRecord(
".kmp_privates.t");
2910 for (
const auto &Pair : Privates) {
2911 const VarDecl *VD = Pair.second.Original;
2915 if (Pair.second.isLocalPrivate()) {
2938 QualType KmpRoutineEntryPointerQTy) {
2958 CanQualType KmpCmplrdataTy =
C.getCanonicalTagType(UD);
2959 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t");
2989 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t_with_privates");
3009static llvm::Function *
3012 QualType KmpTaskTWithPrivatesPtrQTy,
3014 QualType SharedsPtrTy, llvm::Function *TaskFunction,
3015 llvm::Value *TaskPrivatesMap) {
3023 Args.push_back(&GtidArg);
3024 Args.push_back(&TaskTypeArg);
3025 const auto &TaskEntryFnInfo =
3027 llvm::FunctionType *TaskEntryTy =
3030 auto *TaskEntry = llvm::Function::Create(
3031 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3033 TaskEntry->setDoesNotRecurse();
3048 const auto *KmpTaskTWithPrivatesQTyRD =
3053 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3055 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF);
3057 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3063 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3064 llvm::Value *PrivatesParam;
3065 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3068 PrivatesLVal.getPointer(CGF), CGF.
VoidPtrTy);
3070 PrivatesParam = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
3073 llvm::Value *CommonArgs[] = {
3074 GtidParam, PartidParam, PrivatesParam, TaskPrivatesMap,
3080 std::end(CommonArgs));
3082 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
3085 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
3088 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
3091 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3094 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
3097 CallArgs.push_back(LBParam);
3098 CallArgs.push_back(UBParam);
3099 CallArgs.push_back(StParam);
3100 CallArgs.push_back(LIParam);
3101 CallArgs.push_back(RParam);
3103 CallArgs.push_back(SharedsParam);
3116 QualType KmpTaskTWithPrivatesPtrQTy,
3117 QualType KmpTaskTWithPrivatesQTy) {
3125 Args.push_back(&GtidArg);
3126 Args.push_back(&TaskTypeArg);
3127 const auto &DestructorFnInfo =
3129 llvm::FunctionType *DestructorFnTy =
3133 auto *DestructorFn =
3134 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3138 DestructorFn->setDoesNotRecurse();
3146 const auto *KmpTaskTWithPrivatesQTyRD =
3148 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3150 for (
const auto *Field : FI->getType()->castAsRecordDecl()->fields()) {
3152 Field->getType().isDestructedType()) {
3154 CGF.
pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
3158 return DestructorFn;
3178 C,
nullptr, Loc,
nullptr,
3179 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
3181 Args.push_back(&TaskPrivatesArg);
3182 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
unsigned> PrivateVarsPos;
3183 unsigned Counter = 1;
3184 for (
const Expr *E :
Data.PrivateVars) {
3186 C,
nullptr, Loc,
nullptr,
3187 C.getPointerType(
C.getPointerType(E->
getType()))
3192 PrivateVarsPos[VD] = Counter;
3195 for (
const Expr *E :
Data.FirstprivateVars) {
3197 C,
nullptr, Loc,
nullptr,
3198 C.getPointerType(
C.getPointerType(E->
getType()))
3203 PrivateVarsPos[VD] = Counter;
3206 for (
const Expr *E :
Data.LastprivateVars) {
3208 C,
nullptr, Loc,
nullptr,
3209 C.getPointerType(
C.getPointerType(E->
getType()))
3214 PrivateVarsPos[VD] = Counter;
3220 Ty =
C.getPointerType(Ty);
3222 Ty =
C.getPointerType(Ty);
3224 C,
nullptr, Loc,
nullptr,
3225 C.getPointerType(
C.getPointerType(Ty)).withConst().withRestrict(),
3227 PrivateVarsPos[VD] = Counter;
3230 const auto &TaskPrivatesMapFnInfo =
3232 llvm::FunctionType *TaskPrivatesMapTy =
3236 auto *TaskPrivatesMap = llvm::Function::Create(
3237 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
3240 TaskPrivatesMapFnInfo);
3242 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
3243 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
3244 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
3248 TaskPrivatesMapFnInfo, Args, Loc, Loc);
3256 for (
const FieldDecl *Field : PrivatesQTyRD->fields()) {
3258 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
3262 RefLVal.getAddress(), RefLVal.getType()->castAs<
PointerType>());
3267 return TaskPrivatesMap;
3273 Address KmpTaskSharedsPtr, LValue TDBase,
3279 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3293 if ((!IsTargetTask && !
Data.FirstprivateVars.empty() && ForDup) ||
3294 (IsTargetTask && KmpTaskSharedsPtr.
isValid())) {
3301 FI = FI->getType()->castAsRecordDecl()->field_begin();
3302 for (
const PrivateDataTy &Pair : Privates) {
3304 if (Pair.second.isLocalPrivate()) {
3308 const VarDecl *VD = Pair.second.PrivateCopy;
3313 if (
const VarDecl *Elem = Pair.second.PrivateElemInit) {
3314 const VarDecl *OriginalVD = Pair.second.Original;
3317 LValue SharedRefLValue;
3320 if (IsTargetTask && !SharedField) {
3324 ->getNumParams() == 0 &&
3327 ->getDeclContext()) &&
3328 "Expected artificial target data variable.");
3331 }
else if (ForDup) {
3334 SharedRefLValue.getAddress().withAlignment(
3335 C.getDeclAlign(OriginalVD)),
3337 SharedRefLValue.getTBAAInfo());
3339 Pair.second.Original->getCanonicalDecl()) > 0 ||
3341 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3344 InlinedOpenMPRegionRAII Region(
3347 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3358 PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Type,
3359 [&CGF, Elem,
Init, &CapturesInfo](
Address DestElement,
3362 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3363 InitScope.addPrivate(Elem, SrcElement);
3364 (void)InitScope.Privatize();
3366 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3367 CGF, &CapturesInfo);
3368 CGF.EmitAnyExprToMem(Init, DestElement,
3369 Init->getType().getQualifiers(),
3375 InitScope.addPrivate(Elem, SharedRefLValue.getAddress());
3376 (void)InitScope.Privatize();
3392 bool InitRequired =
false;
3393 for (
const PrivateDataTy &Pair : Privates) {
3394 if (Pair.second.isLocalPrivate())
3396 const VarDecl *VD = Pair.second.PrivateCopy;
3398 InitRequired = InitRequired || (isa_and_nonnull<CXXConstructExpr>(
Init) &&
3403 return InitRequired;
3420 QualType KmpTaskTWithPrivatesPtrQTy,
3428 KmpTaskTWithPrivatesPtrQTy,
3431 KmpTaskTWithPrivatesPtrQTy,
3435 Args.push_back(&DstArg);
3436 Args.push_back(&SrcArg);
3437 Args.push_back(&LastprivArg);
3438 const auto &TaskDupFnInfo =
3442 auto *TaskDup = llvm::Function::Create(
3443 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3445 TaskDup->setDoesNotRecurse();
3455 auto LIFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTLastIter);
3457 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3465 assert(!Privates.empty());
3467 if (!
Data.FirstprivateVars.empty()) {
3472 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3480 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
3481 SharedsTy, SharedsPtrTy,
Data, Privates,
true);
3491 for (
const PrivateDataTy &P : Privates) {
3492 if (P.second.isLocalPrivate())
3494 QualType Ty = P.second.Original->getType().getNonReferenceType();
3503class OMPIteratorGeneratorScope final
3505 CodeGenFunction &CGF;
3506 const OMPIteratorExpr *E =
nullptr;
3507 SmallVector<CodeGenFunction::JumpDest, 4> ContDests;
3508 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests;
3509 OMPIteratorGeneratorScope() =
delete;
3510 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) =
delete;
3513 OMPIteratorGeneratorScope(CodeGenFunction &CGF,
const OMPIteratorExpr *E)
3514 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) {
3517 SmallVector<llvm::Value *, 4> Uppers;
3519 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper));
3520 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I));
3521 addPrivate(VD, CGF.CreateMemTemp(VD->getType(), VD->getName()));
3522 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3524 HelperData.CounterVD,
3525 CGF.CreateMemTemp(HelperData.CounterVD->getType(),
"counter.addr"));
3530 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3532 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD),
3533 HelperData.CounterVD->getType());
3535 CGF.EmitStoreOfScalar(
3536 llvm::ConstantInt::get(CLVal.getAddress().getElementType(), 0),
3538 CodeGenFunction::JumpDest &ContDest =
3539 ContDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.cont"));
3540 CodeGenFunction::JumpDest &ExitDest =
3541 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.exit"));
3543 llvm::Value *N = Uppers[I];
3546 CGF.EmitBlock(ContDest.getBlock());
3548 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation());
3550 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType()
3551 ? CGF.Builder.CreateICmpSLT(CVal, N)
3552 : CGF.Builder.CreateICmpULT(CVal, N);
3553 llvm::BasicBlock *BodyBB = CGF.createBasicBlock(
"iter.body");
3554 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock());
3556 CGF.EmitBlock(BodyBB);
3558 CGF.EmitIgnoredExpr(HelperData.Update);
3561 ~OMPIteratorGeneratorScope() {
3566 const OMPIteratorHelperData &HelperData = E->
getHelper(I - 1);
3571 CGF.
EmitBlock(ExitDests[I - 1].getBlock(), I == 1);
3577static std::pair<llvm::Value *, llvm::Value *>
3579 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E);
3582 const Expr *
Base = OASE->getBase();
3587 llvm::Value *SizeVal;
3590 SizeVal = CGF.
getTypeSize(OASE->getBase()->getType()->getPointeeType());
3591 for (
const Expr *SE : OASE->getDimensions()) {
3595 SizeVal = CGF.
Builder.CreateNUWMul(SizeVal, Sz);
3597 }
else if (
const auto *ASE =
3600 Address UpAddrAddress = UpAddrLVal.getAddress();
3601 llvm::Value *UpAddr = CGF.
Builder.CreateConstGEP1_32(
3605 llvm::Value *UpIntPtr = CGF.
Builder.CreatePtrToInt(UpAddr, CGF.
SizeTy);
3606 SizeVal = CGF.
Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
3610 return std::make_pair(
Addr, SizeVal);
3615 QualType FlagsTy =
C.getIntTypeForBitwidth(32,
false);
3616 if (KmpTaskAffinityInfoTy.
isNull()) {
3618 C.buildImplicitRecord(
"kmp_task_affinity_info_t");
3624 KmpTaskAffinityInfoTy =
C.getCanonicalTagType(KmpAffinityInfoRD);
3631 llvm::Function *TaskFunction,
QualType SharedsTy,
3636 const auto *I =
Data.PrivateCopies.begin();
3637 for (
const Expr *E :
Data.PrivateVars) {
3639 Privates.emplace_back(
3645 I =
Data.FirstprivateCopies.begin();
3646 const auto *IElemInitRef =
Data.FirstprivateInits.begin();
3647 for (
const Expr *E :
Data.FirstprivateVars) {
3649 Privates.emplace_back(
3657 I =
Data.LastprivateCopies.begin();
3658 for (
const Expr *E :
Data.LastprivateVars) {
3660 Privates.emplace_back(
3668 Privates.emplace_back(
CGM.getPointerAlign(), PrivateHelpersTy(VD));
3670 Privates.emplace_back(
C.getDeclAlign(VD), PrivateHelpersTy(VD));
3672 llvm::stable_sort(Privates,
3673 [](
const PrivateDataTy &L,
const PrivateDataTy &R) {
3674 return L.first > R.first;
3676 QualType KmpInt32Ty =
C.getIntTypeForBitwidth(32, 1);
3687 assert((D.getDirectiveKind() == OMPD_task ||
3690 "Expected taskloop, task or target directive");
3697 const auto *KmpTaskTQTyRD =
KmpTaskTQTy->castAsRecordDecl();
3699 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
3702 C.getCanonicalTagType(KmpTaskTWithPrivatesQTyRD);
3703 QualType KmpTaskTWithPrivatesPtrQTy =
3704 C.getPointerType(KmpTaskTWithPrivatesQTy);
3705 llvm::Type *KmpTaskTWithPrivatesPtrTy = CGF.
Builder.getPtrTy(0);
3706 llvm::Value *KmpTaskTWithPrivatesTySize =
3708 QualType SharedsPtrTy =
C.getPointerType(SharedsTy);
3711 llvm::Value *TaskPrivatesMap =
nullptr;
3712 llvm::Type *TaskPrivatesMapTy =
3713 std::next(TaskFunction->arg_begin(), 3)->getType();
3714 if (!Privates.empty()) {
3715 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3719 TaskPrivatesMap, TaskPrivatesMapTy);
3721 TaskPrivatesMap = llvm::ConstantPointerNull::get(
3727 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
3728 KmpTaskTWithPrivatesQTy,
KmpTaskTQTy, SharedsPtrTy, TaskFunction,
3740 DestructorsFlag = 0x8,
3741 PriorityFlag = 0x20,
3742 DetachableFlag = 0x40,
3743 FreeAgentFlag = 0x80,
3745 unsigned Flags =
Data.Tied ? TiedFlag : 0;
3746 bool NeedsCleanup =
false;
3747 if (!Privates.empty()) {
3751 Flags = Flags | DestructorsFlag;
3755 if (Kind == OMPC_THREADSET_omp_pool)
3756 Flags = Flags | FreeAgentFlag;
3758 if (
Data.Priority.getInt())
3759 Flags = Flags | PriorityFlag;
3761 Flags = Flags | DetachableFlag;
3762 llvm::Value *TaskFlags =
3763 Data.Final.getPointer()
3764 ? CGF.
Builder.CreateSelect(
Data.Final.getPointer(),
3765 CGF.
Builder.getInt32(FinalFlag),
3767 : CGF.
Builder.getInt32(
Data.Final.getInt() ? FinalFlag : 0);
3768 TaskFlags = CGF.
Builder.CreateOr(TaskFlags, CGF.
Builder.getInt32(Flags));
3769 llvm::Value *SharedsSize =
CGM.getSize(
C.getTypeSizeInChars(SharedsTy));
3771 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
3774 llvm::Value *NewTask;
3781 llvm::Value *DeviceID;
3786 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
3787 AllocArgs.push_back(DeviceID);
3790 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc),
3795 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc),
3808 llvm::Value *Tid =
getThreadID(CGF, DC->getBeginLoc());
3809 Tid = CGF.
Builder.CreateIntCast(Tid, CGF.
IntTy,
false);
3812 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event),
3813 {Loc, Tid, NewTask});
3824 llvm::Value *NumOfElements =
nullptr;
3825 unsigned NumAffinities = 0;
3827 if (
const Expr *Modifier =
C->getModifier()) {
3829 for (
unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
3833 NumOfElements ? CGF.
Builder.CreateNUWMul(NumOfElements, Sz) : Sz;
3836 NumAffinities +=
C->varlist_size();
3841 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags };
3843 QualType KmpTaskAffinityInfoArrayTy;
3844 if (NumOfElements) {
3845 NumOfElements = CGF.
Builder.CreateNUWAdd(
3846 llvm::ConstantInt::get(CGF.
SizeTy, NumAffinities), NumOfElements);
3849 C.getIntTypeForBitwidth(
C.getTypeSize(
C.getSizeType()), 0),
3853 KmpTaskAffinityInfoArrayTy =
C.getVariableArrayType(
3861 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
3864 KmpTaskAffinityInfoArrayTy =
C.getConstantArrayType(
3866 llvm::APInt(
C.getTypeSize(
C.getSizeType()), NumAffinities),
nullptr,
3869 CGF.
CreateMemTemp(KmpTaskAffinityInfoArrayTy,
".affs.arr.addr");
3871 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumAffinities,
3878 bool HasIterator =
false;
3880 if (
C->getModifier()) {
3884 for (
const Expr *E :
C->varlist()) {
3893 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
3898 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
3912 const Expr *Modifier =
C->getModifier();
3915 OMPIteratorGeneratorScope IteratorScope(
3917 for (
const Expr *E :
C->varlist()) {
3927 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
3932 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
3934 Idx = CGF.
Builder.CreateNUWAdd(
3935 Idx, llvm::ConstantInt::get(Idx->getType(), 1));
3950 CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity),
3951 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr});
3953 llvm::Value *NewTaskNewTaskTTy =
3955 NewTask, KmpTaskTWithPrivatesPtrTy);
3957 KmpTaskTWithPrivatesQTy);
3968 *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)),
3970 CGF.
Int8Ty,
CGM.getNaturalTypeAlignment(SharedsTy));
3977 if (!Privates.empty()) {
3979 SharedsTy, SharedsPtrTy,
Data, Privates,
3984 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
3985 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy,
Data, Privates,
3986 !
Data.LastprivateVars.empty());
3990 enum { Priority = 0, Destructors = 1 };
3992 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
3993 const auto *KmpCmplrdataUD = (*FI)->getType()->castAsRecordDecl();
3994 assert(KmpCmplrdataUD->isUnion());
3997 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
3998 KmpTaskTWithPrivatesQTy);
4001 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
4007 if (
Data.Priority.getInt()) {
4009 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
4011 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
4014 Result.NewTask = NewTask;
4015 Result.TaskEntry = TaskEntry;
4016 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
4018 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
4024 RTLDependenceKindTy DepKind;
4026 case OMPC_DEPEND_in:
4027 DepKind = RTLDependenceKindTy::DepIn;
4030 case OMPC_DEPEND_out:
4031 case OMPC_DEPEND_inout:
4032 DepKind = RTLDependenceKindTy::DepInOut;
4034 case OMPC_DEPEND_mutexinoutset:
4035 DepKind = RTLDependenceKindTy::DepMutexInOutSet;
4037 case OMPC_DEPEND_inoutset:
4038 DepKind = RTLDependenceKindTy::DepInOutSet;
4040 case OMPC_DEPEND_outallmemory:
4041 DepKind = RTLDependenceKindTy::DepOmpAllMem;
4043 case OMPC_DEPEND_source:
4044 case OMPC_DEPEND_sink:
4045 case OMPC_DEPEND_depobj:
4046 case OMPC_DEPEND_inoutallmemory:
4048 llvm_unreachable(
"Unknown task dependence type");
4056 FlagsTy =
C.getIntTypeForBitwidth(
C.getTypeSize(
C.BoolTy),
false);
4057 if (KmpDependInfoTy.
isNull()) {
4058 RecordDecl *KmpDependInfoRD =
C.buildImplicitRecord(
"kmp_depend_info");
4064 KmpDependInfoTy =
C.getCanonicalTagType(KmpDependInfoRD);
4068std::pair<llvm::Value *, LValue>
4081 CGF,
Base.getAddress(),
4082 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4088 *std::next(KmpDependInfoRD->field_begin(),
4089 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4091 return std::make_pair(NumDeps,
Base);
4095 llvm::PointerUnion<unsigned *, LValue *> Pos,
4105 OMPIteratorGeneratorScope IteratorScope(
4106 CGF, cast_or_null<OMPIteratorExpr>(
4107 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4109 for (
const Expr *E :
Data.DepExprs) {
4119 Size = llvm::ConstantInt::get(CGF.
SizeTy, 0);
4122 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4126 assert(E &&
"Expected a non-null expression");
4135 *std::next(KmpDependInfoRD->field_begin(),
4136 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4140 Base, *std::next(KmpDependInfoRD->field_begin(),
4141 static_cast<unsigned int>(RTLDependInfoFields::Len)));
4147 *std::next(KmpDependInfoRD->field_begin(),
4148 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4150 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4152 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4157 Idx = CGF.
Builder.CreateNUWAdd(Idx,
4158 llvm::ConstantInt::get(Idx->getType(), 1));
4167 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4168 "Expected depobj dependency kind.");
4173 OMPIteratorGeneratorScope IteratorScope(
4174 CGF, cast_or_null<OMPIteratorExpr>(
4175 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4177 for (
const Expr *E :
Data.DepExprs) {
4178 llvm::Value *NumDeps;
4181 std::tie(NumDeps,
Base) =
4185 C.getUIntPtrType());
4189 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(PrevVal, NumDeps);
4191 SizeLVals.push_back(NumLVal);
4194 for (
unsigned I = 0, E = SizeLVals.size(); I < E; ++I) {
4197 Sizes.push_back(Size);
4207 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4208 "Expected depobj dependency kind.");
4211 OMPIteratorGeneratorScope IteratorScope(
4212 CGF, cast_or_null<OMPIteratorExpr>(
4213 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4215 for (
const Expr *E :
Data.DepExprs) {
4216 llvm::Value *NumDeps;
4219 std::tie(NumDeps,
Base) =
4223 llvm::Value *Size = CGF.
Builder.CreateNUWMul(
4232 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(Pos, NumDeps);
4248 llvm::Value *NumOfElements =
nullptr;
4249 unsigned NumDependencies = std::accumulate(
4250 Dependencies.begin(), Dependencies.end(), 0,
4252 return D.DepKind == OMPC_DEPEND_depobj
4254 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size()));
4258 bool HasDepobjDeps =
false;
4259 bool HasRegularWithIterators =
false;
4260 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4261 llvm::Value *NumOfRegularWithIterators =
4262 llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4266 if (D.
DepKind == OMPC_DEPEND_depobj) {
4269 for (llvm::Value *Size : Sizes) {
4270 NumOfDepobjElements =
4271 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, Size);
4273 HasDepobjDeps =
true;
4278 if (
const auto *IE = cast_or_null<OMPIteratorExpr>(D.
IteratorExpr)) {
4279 llvm::Value *ClauseIteratorSpace =
4280 llvm::ConstantInt::get(CGF.
IntPtrTy, 1);
4284 ClauseIteratorSpace = CGF.
Builder.CreateNUWMul(Sz, ClauseIteratorSpace);
4286 llvm::Value *NumClauseDeps = CGF.
Builder.CreateNUWMul(
4287 ClauseIteratorSpace,
4289 NumOfRegularWithIterators =
4290 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumClauseDeps);
4291 HasRegularWithIterators =
true;
4297 if (HasDepobjDeps || HasRegularWithIterators) {
4298 NumOfElements = llvm::ConstantInt::get(
CGM.IntPtrTy, NumDependencies,
4300 if (HasDepobjDeps) {
4302 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements);
4304 if (HasRegularWithIterators) {
4306 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements);
4309 Loc,
C.getIntTypeForBitwidth(64, 0),
4313 KmpDependInfoArrayTy =
4322 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4325 KmpDependInfoArrayTy =
C.getConstantArrayType(
4331 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumDependencies,
4336 if (Dep.DepKind == OMPC_DEPEND_depobj || Dep.IteratorExpr)
4342 CGF.
CreateMemTemp(
C.getSizeType(),
"dep.counter.addr"),
C.getSizeType());
4345 if (Dep.DepKind == OMPC_DEPEND_depobj || !Dep.IteratorExpr)
4350 if (HasDepobjDeps) {
4352 if (Dep.DepKind != OMPC_DEPEND_depobj)
4359 return std::make_pair(NumOfElements, DependenciesArray);
4370 unsigned NumDependencies = Dependencies.
DepExprs.size();
4380 llvm::Value *NumDepsVal;
4382 if (
const auto *IE =
4383 cast_or_null<OMPIteratorExpr>(Dependencies.
IteratorExpr)) {
4384 NumDepsVal = llvm::ConstantInt::get(CGF.
SizeTy, 1);
4388 NumDepsVal = CGF.
Builder.CreateNUWMul(NumDepsVal, Sz);
4390 Size = CGF.
Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.
SizeTy, 1),
4394 llvm::Value *RecSize =
CGM.getSize(SizeInBytes);
4395 Size = CGF.
Builder.CreateNUWMul(Size, RecSize);
4399 QualType KmpDependInfoArrayTy =
C.getConstantArrayType(
4402 CharUnits Sz =
C.getTypeSizeInChars(KmpDependInfoArrayTy);
4404 NumDepsVal = llvm::ConstantInt::get(CGF.
IntPtrTy, NumDependencies);
4409 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4410 llvm::Value *Args[] = {ThreadID, Size, Allocator};
4414 CGM.getModule(), OMPRTL___kmpc_alloc),
4415 Args,
".dep.arr.addr");
4419 DependenciesArray =
Address(
Addr, KmpDependInfoLlvmTy, Align);
4425 *std::next(KmpDependInfoRD->field_begin(),
4426 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4428 llvm::PointerUnion<unsigned *, LValue *> Pos;
4445 return DependenciesArray;
4460 Addr.getElementType(),
Addr.emitRawPointer(CGF),
4461 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4466 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4467 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator};
4471 CGM.getModule(), OMPRTL___kmpc_free),
4483 llvm::Value *NumDeps;
4494 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4496 llvm::PHINode *ElementPHI =
4501 Base.getTBAAInfo());
4505 Base, *std::next(KmpDependInfoRD->field_begin(),
4506 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4508 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4512 llvm::Value *ElementNext =
4515 ElementPHI->addIncoming(ElementNext, CGF.
Builder.GetInsertBlock());
4516 llvm::Value *IsEmpty =
4517 CGF.
Builder.CreateICmpEQ(ElementNext, End,
"omp.isempty");
4518 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4525 llvm::Function *TaskFunction,
4534 llvm::Value *NewTask =
Result.NewTask;
4535 llvm::Function *TaskEntry =
Result.TaskEntry;
4536 llvm::Value *NewTaskNewTaskTTy =
Result.NewTaskNewTaskTTy;
4541 llvm::Value *NumOfElements;
4542 std::tie(NumOfElements, DependenciesArray) =
4553 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
4554 llvm::Value *DepTaskArgs[7];
4555 if (!
Data.Dependences.empty()) {
4556 DepTaskArgs[0] = UpLoc;
4557 DepTaskArgs[1] = ThreadID;
4558 DepTaskArgs[2] = NewTask;
4559 DepTaskArgs[3] = NumOfElements;
4561 DepTaskArgs[5] = CGF.
Builder.getInt32(0);
4562 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4564 auto &&ThenCodeGen = [
this, &
Data, TDBase, KmpTaskTQTyRD, &TaskArgs,
4567 auto PartIdFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTPartId);
4571 if (!
Data.Dependences.empty()) {
4574 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps),
4578 CGM.getModule(), OMPRTL___kmpc_omp_task),
4584 Region->emitUntiedSwitch(CGF);
4587 llvm::Value *DepWaitTaskArgs[7];
4588 if (!
Data.Dependences.empty()) {
4589 DepWaitTaskArgs[0] = UpLoc;
4590 DepWaitTaskArgs[1] = ThreadID;
4591 DepWaitTaskArgs[2] = NumOfElements;
4593 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
4594 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4595 DepWaitTaskArgs[6] =
4596 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
4598 auto &M =
CGM.getModule();
4599 auto &&ElseCodeGen = [
this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy,
4600 TaskEntry, &
Data, &DepWaitTaskArgs,
4607 if (!
Data.Dependences.empty())
4609 M, OMPRTL___kmpc_omp_taskwait_deps_51),
4612 auto &&
CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
4615 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
4616 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
4625 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
4626 M, OMPRTL___kmpc_omp_task_begin_if0),
4629 M, OMPRTL___kmpc_omp_task_complete_if0),
4645 llvm::Function *TaskFunction,
4665 IfVal = llvm::ConstantInt::getSigned(CGF.
IntTy, 1);
4670 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
4677 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
4684 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
4692 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
4693 if (
Data.Reductions) {
4699 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
4708 llvm::ConstantInt::getSigned(
4710 llvm::ConstantInt::getSigned(
4712 ?
Data.Schedule.getInt() ? NumTasks : Grainsize
4714 Data.Schedule.getPointer()
4717 : llvm::ConstantInt::get(CGF.
Int64Ty, 0)};
4718 if (
Data.HasModifier)
4719 TaskArgs.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 1));
4721 TaskArgs.push_back(
Result.TaskDupFn
4724 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy));
4726 CGM.getModule(),
Data.HasModifier
4727 ? OMPRTL___kmpc_taskloop_5
4728 : OMPRTL___kmpc_taskloop),
4745 const Expr *,
const Expr *)> &RedOpGen,
4746 const Expr *XExpr =
nullptr,
const Expr *EExpr =
nullptr,
4747 const Expr *UpExpr =
nullptr) {
4755 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, LHSAddr);
4760 llvm::Value *LHSEnd =
4765 llvm::Value *IsEmpty =
4766 CGF.
Builder.CreateICmpEQ(LHSBegin, LHSEnd,
"omp.arraycpy.isempty");
4767 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4770 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4775 llvm::PHINode *RHSElementPHI = CGF.
Builder.CreatePHI(
4776 RHSBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
4777 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
4782 llvm::PHINode *LHSElementPHI = CGF.
Builder.CreatePHI(
4783 LHSBegin->getType(), 2,
"omp.arraycpy.destElementPast");
4784 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
4791 Scope.addPrivate(LHSVar, LHSElementCurrent);
4792 Scope.addPrivate(RHSVar, RHSElementCurrent);
4794 RedOpGen(CGF, XExpr, EExpr, UpExpr);
4795 Scope.ForceCleanup();
4798 llvm::Value *LHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4800 "omp.arraycpy.dest.element");
4801 llvm::Value *RHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4803 "omp.arraycpy.src.element");
4806 CGF.
Builder.CreateICmpEQ(LHSElementNext, LHSEnd,
"omp.arraycpy.done");
4807 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
4808 LHSElementPHI->addIncoming(LHSElementNext, CGF.
Builder.GetInsertBlock());
4809 RHSElementPHI->addIncoming(RHSElementNext, CGF.
Builder.GetInsertBlock());
4819 const Expr *ReductionOp) {
4820 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
4821 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
4822 if (
const auto *DRE =
4823 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
4824 if (
const auto *DRD =
4825 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
4826 std::pair<llvm::Function *, llvm::Function *>
Reduction =
4837 StringRef ReducerName,
SourceLocation Loc, llvm::Type *ArgsElemType,
4848 Args.push_back(&LHSArg);
4849 Args.push_back(&RHSArg);
4851 CGM.getTypes().arrangeBuiltinFunctionDeclaration(
C.VoidTy, Args);
4853 auto *Fn = llvm::Function::Create(
CGM.getTypes().GetFunctionType(CGFI),
4854 llvm::GlobalValue::InternalLinkage, Name,
4857 Fn->setDoesNotRecurse();
4876 const auto *IPriv = Privates.begin();
4878 for (
unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
4879 const auto *RHSVar =
4882 const auto *LHSVar =
4885 QualType PrivTy = (*IPriv)->getType();
4900 IPriv = Privates.begin();
4901 const auto *ILHS = LHSExprs.begin();
4902 const auto *IRHS = RHSExprs.begin();
4903 for (
const Expr *E : ReductionOps) {
4904 if ((*IPriv)->getType()->isArrayType()) {
4909 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
4911 emitReductionCombiner(CGF, E);
4921 Scope.ForceCleanup();
4927 const Expr *ReductionOp,
4928 const Expr *PrivateRef,
4936 CGF, PrivateRef->
getType(), LHSVar, RHSVar,
4938 emitReductionCombiner(CGF, ReductionOp);
4947 llvm::StringRef Prefix,
const Expr *Ref);
4951 const Expr *LHSExprs,
const Expr *RHSExprs,
const Expr *ReductionOps) {
4978 std::string ReductionVarNameStr;
4980 ReductionVarNameStr =
4983 ReductionVarNameStr =
"unnamed_priv_var";
4986 std::string SharedName =
4987 CGM.getOpenMPRuntime().getName({
"internal_pivate_", ReductionVarNameStr});
4988 llvm::GlobalVariable *SharedVar =
OMPBuilder.getOrCreateInternalVariable(
4989 LLVMType,
".omp.reduction." + SharedName);
4991 SharedVar->setAlignment(
4999 llvm::Value *BarrierArgs[] = {BarrierLoc, ThreadId};
5004 llvm::Value *IsWorker = CGF.
Builder.CreateICmpEQ(
5005 ThreadId, llvm::ConstantInt::get(ThreadId->getType(), 0));
5006 CGF.
Builder.CreateCondBr(IsWorker, InitBB, InitEndBB);
5010 auto EmitSharedInit = [&]() {
5013 std::pair<llvm::Function *, llvm::Function *> FnPair =
5015 llvm::Function *InitializerFn = FnPair.second;
5016 if (InitializerFn) {
5017 if (
const auto *CE =
5018 dyn_cast<CallExpr>(UDRInitExpr->IgnoreParenImpCasts())) {
5025 LocalScope.addPrivate(OutVD, SharedResult);
5027 (void)LocalScope.Privatize();
5028 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(
5029 CE->getCallee()->IgnoreParenImpCasts())) {
5055 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Privates)) {
5056 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
5067 CGF.
Builder.CreateBr(InitEndBB);
5071 CGM.getModule(), OMPRTL___kmpc_barrier),
5074 const Expr *ReductionOp = ReductionOps;
5079 auto EmitCriticalReduction = [&](
auto ReductionGen) {
5080 std::string CriticalName =
getName({
"reduction_critical"});
5088 std::pair<llvm::Function *, llvm::Function *> FnPair =
5091 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp)) {
5103 (void)LocalScope.Privatize();
5108 EmitCriticalReduction(ReductionGen);
5113 if (
const auto *Cleanup = dyn_cast<ExprWithCleanups>(ReductionClauseExpr))
5116 const Expr *AssignRHS =
nullptr;
5117 if (
const auto *BinOp = dyn_cast<BinaryOperator>(ReductionClauseExpr)) {
5118 if (BinOp->getOpcode() == BO_Assign)
5119 AssignRHS = BinOp->getRHS();
5120 }
else if (
const auto *OpCall =
5121 dyn_cast<CXXOperatorCallExpr>(ReductionClauseExpr)) {
5122 if (OpCall->getOperator() == OO_Equal)
5123 AssignRHS = OpCall->getArg(1);
5127 "Private Variable Reduction : Invalid ReductionOp expression");
5132 const auto *OmpOutDRE =
5134 const auto *OmpInDRE =
5137 OmpOutDRE && OmpInDRE &&
5138 "Private Variable Reduction : LHSExpr/RHSExpr must be DeclRefExprs");
5142 LocalScope.addPrivate(OmpOutVD, SharedLV.
getAddress());
5143 LocalScope.addPrivate(OmpInVD, LHSLV.
getAddress());
5144 (void)LocalScope.Privatize();
5148 EmitCriticalReduction(ReductionGen);
5152 CGM.getModule(), OMPRTL___kmpc_barrier),
5158 llvm::Value *FinalResultVal =
nullptr;
5162 FinalResultAddr = SharedResult;
5176 CGM.getModule(), OMPRTL___kmpc_barrier),
5187 EmitCriticalReduction(OriginalListCombiner);
5239 if (SimpleReduction) {
5241 const auto *IPriv = OrgPrivates.begin();
5242 const auto *ILHS = OrgLHSExprs.begin();
5243 const auto *IRHS = OrgRHSExprs.begin();
5244 for (
const Expr *E : OrgReductionOps) {
5257 FilteredRHSExprs, FilteredReductionOps;
5258 for (
unsigned I : llvm::seq<unsigned>(
5259 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5261 FilteredPrivates.emplace_back(OrgPrivates[I]);
5262 FilteredLHSExprs.emplace_back(OrgLHSExprs[I]);
5263 FilteredRHSExprs.emplace_back(OrgRHSExprs[I]);
5264 FilteredReductionOps.emplace_back(OrgReductionOps[I]);
5276 auto Size = RHSExprs.size();
5277 for (
const Expr *E : Privates) {
5282 llvm::APInt ArraySize(32, Size);
5283 QualType ReductionArrayTy =
C.getConstantArrayType(
5287 CGF.
CreateMemTemp(ReductionArrayTy,
".omp.reduction.red_list");
5288 const auto *IPriv = Privates.begin();
5290 for (
unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
5296 if ((*IPriv)->getType()->isVariablyModifiedType()) {
5300 llvm::Value *Size = CGF.
Builder.CreateIntCast(
5313 Privates, LHSExprs, RHSExprs, ReductionOps);
5316 std::string Name =
getName({
"reduction"});
5323 llvm::Value *ReductionArrayTySize = CGF.
getTypeSize(ReductionArrayTy);
5326 llvm::Value *Args[] = {
5329 CGF.
Builder.getInt32(RHSExprs.size()),
5330 ReductionArrayTySize,
5338 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce),
5342 llvm::BasicBlock *DefaultBB = CGF.
createBasicBlock(
".omp.reduction.default");
5343 llvm::SwitchInst *SwInst =
5344 CGF.
Builder.CreateSwitch(Res, DefaultBB, 2);
5353 SwInst->addCase(CGF.
Builder.getInt32(1), Case1BB);
5357 llvm::Value *EndArgs[] = {
5362 auto &&
CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps](
5365 const auto *IPriv = Privates.begin();
5366 const auto *ILHS = LHSExprs.begin();
5367 const auto *IRHS = RHSExprs.begin();
5368 for (
const Expr *E : ReductionOps) {
5377 CommonActionTy Action(
5380 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait
5381 : OMPRTL___kmpc_end_reduce),
5394 SwInst->addCase(CGF.
Builder.getInt32(2), Case2BB);
5397 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps](
5399 const auto *ILHS = LHSExprs.begin();
5400 const auto *IRHS = RHSExprs.begin();
5401 const auto *IPriv = Privates.begin();
5402 for (
const Expr *E : ReductionOps) {
5403 const Expr *XExpr =
nullptr;
5404 const Expr *EExpr =
nullptr;
5405 const Expr *UpExpr =
nullptr;
5407 if (
const auto *BO = dyn_cast<BinaryOperator>(E)) {
5408 if (BO->getOpcode() == BO_Assign) {
5409 XExpr = BO->getLHS();
5410 UpExpr = BO->getRHS();
5414 const Expr *RHSExpr = UpExpr;
5417 if (
const auto *ACO = dyn_cast<AbstractConditionalOperator>(
5421 RHSExpr = ACO->getCond();
5423 if (
const auto *BORHS =
5425 EExpr = BORHS->getRHS();
5426 BO = BORHS->getOpcode();
5431 auto &&AtomicRedGen = [BO, VD,
5433 const Expr *EExpr,
const Expr *UpExpr) {
5434 LValue X = CGF.EmitLValue(XExpr);
5437 E = CGF.EmitAnyExpr(EExpr);
5438 CGF.EmitOMPAtomicSimpleUpdateExpr(
5440 llvm::AtomicOrdering::Monotonic, Loc,
5441 [&CGF, UpExpr, VD, Loc](
RValue XRValue) {
5443 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5444 CGF.emitOMPSimpleStore(
5445 CGF.MakeAddrLValue(LHSTemp, VD->
getType()), XRValue,
5446 VD->getType().getNonReferenceType(), Loc);
5449 return CGF.EmitAnyExpr(UpExpr);
5452 if ((*IPriv)->getType()->isArrayType()) {
5454 const auto *RHSVar =
5457 AtomicRedGen, XExpr, EExpr, UpExpr);
5460 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
5467 std::string Name = RT.
getName({
"atomic_reduction"});
5476 if ((*IPriv)->getType()->isArrayType()) {
5477 const auto *LHSVar =
5479 const auto *RHSVar =
5484 CritRedGen(CGF,
nullptr,
nullptr,
nullptr);
5495 llvm::Value *EndArgs[] = {
5500 CommonActionTy Action(
nullptr, {},
5502 CGM.getModule(), OMPRTL___kmpc_end_reduce),
5512 assert(OrgLHSExprs.size() == OrgPrivates.size() &&
5513 "PrivateVarReduction: Privates size mismatch");
5514 assert(OrgLHSExprs.size() == OrgReductionOps.size() &&
5515 "PrivateVarReduction: ReductionOps size mismatch");
5516 for (
unsigned I : llvm::seq<unsigned>(
5517 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5520 OrgRHSExprs[I], OrgReductionOps[I]);
5529 llvm::raw_svector_ostream Out(Buffer);
5537 Out << Prefix << Name <<
"_"
5539 return std::string(Out.str());
5561 Args.emplace_back(&Param);
5562 Args.emplace_back(&ParamOrig);
5563 const auto &FnInfo =
5567 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5570 Fn->setDoesNotRecurse();
5577 llvm::Value *Size =
nullptr;
5620 const Expr *ReductionOp,
5622 const Expr *PrivateRef) {
5631 Args.emplace_back(&ParamInOut);
5632 Args.emplace_back(&ParamIn);
5633 const auto &FnInfo =
5637 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5640 Fn->setDoesNotRecurse();
5643 llvm::Value *Size =
nullptr;
5664 C.getPointerType(LHSVD->getType())->castAs<
PointerType>()));
5671 C.getPointerType(RHSVD->getType())->castAs<
PointerType>()));
5700 Args.emplace_back(&Param);
5701 const auto &FnInfo =
5705 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5708 Fn->setDoesNotRecurse();
5713 llvm::Value *Size =
nullptr;
5748 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_taskred_input_t");
5757 C, RD,
C.getIntTypeForBitwidth(32,
false));
5760 unsigned Size =
Data.ReductionVars.size();
5761 llvm::APInt ArraySize(64, Size);
5763 C.getConstantArrayType(RDType, ArraySize,
nullptr,
5768 Data.ReductionCopies,
Data.ReductionOps);
5769 for (
unsigned Cnt = 0; Cnt < Size; ++Cnt) {
5771 llvm::Value *Idxs[] = {llvm::ConstantInt::get(
CGM.SizeTy, 0),
5772 llvm::ConstantInt::get(
CGM.SizeTy, Cnt)};
5788 llvm::Value *SizeValInChars;
5789 llvm::Value *SizeVal;
5790 std::tie(SizeValInChars, SizeVal) = RCG.
getSizes(Cnt);
5796 bool DelayedCreation = !!SizeVal;
5797 SizeValInChars = CGF.
Builder.CreateIntCast(SizeValInChars,
CGM.SizeTy,
5808 llvm::Value *FiniAddr =
5809 Fini ? Fini : llvm::ConstantPointerNull::get(
CGM.VoidPtrTy);
5814 CGM, Loc, RCG, Cnt,
Data.ReductionOps[Cnt], LHSExprs[Cnt],
5815 RHSExprs[Cnt],
Data.ReductionCopies[Cnt]);
5819 if (DelayedCreation) {
5821 llvm::ConstantInt::get(
CGM.Int32Ty, 1,
true),
5826 if (
Data.IsReductionWithTaskMod) {
5832 llvm::Value *Args[] = {
5834 llvm::ConstantInt::get(
CGM.IntTy,
Data.IsWorksharingReduction ? 1 : 0,
5836 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
5841 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init),
5845 llvm::Value *Args[] = {
5848 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
5852 CGM.getModule(), OMPRTL___kmpc_taskred_init),
5858 bool IsWorksharingReduction) {
5864 llvm::Value *Args[] = {IdentTLoc, GTid,
5865 llvm::ConstantInt::get(
CGM.IntTy,
5866 IsWorksharingReduction ? 1 : 0,
5870 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini),
5882 llvm::Value *SizeVal = CGF.
Builder.CreateIntCast(Sizes.second,
CGM.SizeTy,
5885 CGF,
CGM.getContext().getSizeType(),
5893 llvm::Value *ReductionsPtr,
5906 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data),
5922 auto &M =
CGM.getModule();
5924 llvm::Value *NumOfElements;
5925 std::tie(NumOfElements, DependenciesArray) =
5927 if (!
Data.Dependences.empty()) {
5928 llvm::Value *DepWaitTaskArgs[7];
5929 DepWaitTaskArgs[0] = UpLoc;
5930 DepWaitTaskArgs[1] = ThreadID;
5931 DepWaitTaskArgs[2] = NumOfElements;
5933 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
5934 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
5935 DepWaitTaskArgs[6] =
5936 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
5945 M, OMPRTL___kmpc_omp_taskwait_deps_51),
5952 llvm::Value *Args[] = {UpLoc, ThreadID};
5955 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_taskwait),
5960 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
5961 Region->emitUntiedSwitch(CGF);
5970 InlinedOpenMPRegionRAII Region(CGF,
CodeGen, InnerKind, HasCancel,
5971 InnerKind != OMPD_critical &&
5972 InnerKind != OMPD_master &&
5973 InnerKind != OMPD_masked);
5988 RTCancelKind CancelKind = CancelNoreq;
5989 if (CancelRegion == OMPD_parallel)
5990 CancelKind = CancelParallel;
5991 else if (CancelRegion == OMPD_for)
5992 CancelKind = CancelLoop;
5993 else if (CancelRegion == OMPD_sections)
5994 CancelKind = CancelSections;
5996 assert(CancelRegion == OMPD_taskgroup);
5997 CancelKind = CancelTaskgroup;
6009 if (
auto *OMPRegionInfo =
6013 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
6014 llvm::Value *Args[] = {
6020 CGM.getModule(), OMPRTL___kmpc_cancellationpoint),
6029 CGF.
Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6031 if (CancelRegion == OMPD_parallel)
6049 auto &M =
CGM.getModule();
6050 if (
auto *OMPRegionInfo =
6052 auto &&ThenGen = [
this, &M, Loc, CancelRegion,
6055 llvm::Value *Args[] = {
6059 llvm::Value *
Result = CGF.EmitRuntimeCall(
6060 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args);
6065 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".cancel.exit");
6066 llvm::BasicBlock *ContBB = CGF.createBasicBlock(
".cancel.continue");
6067 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(
Result);
6068 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6069 CGF.EmitBlock(ExitBB);
6070 if (CancelRegion == OMPD_parallel)
6074 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6075 CGF.EmitBranchThroughCleanup(CancelDest);
6076 CGF.EmitBlock(ContBB,
true);
6094 OMPUsesAllocatorsActionTy(
6095 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators)
6096 : Allocators(Allocators) {}
6100 for (
const auto &AllocatorData : Allocators) {
6102 CGF, AllocatorData.first, AllocatorData.second);
6105 void Exit(CodeGenFunction &CGF)
override {
6108 for (
const auto &AllocatorData : Allocators) {
6110 AllocatorData.first);
6118 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6120 assert(!ParentName.empty() &&
"Invalid target entry parent name!");
6124 for (
unsigned I = 0, E =
C->getNumberOfAllocators(); I < E; ++I) {
6131 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators);
6132 CodeGen.setAction(UsesAllocatorAction);
6138 const Expr *Allocator,
6139 const Expr *AllocatorTraits) {
6141 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6143 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6144 llvm::Value *NumTraits = llvm::ConstantInt::get(
6148 .getLimitedValue());
6155 llvm::Value *Traits =
Addr.emitRawPointer(CGF);
6157 llvm::Value *AllocatorVal =
6159 CGM.getModule(), OMPRTL___kmpc_init_allocator),
6160 {ThreadId, MemSpaceHandle, NumTraits, Traits});
6172 const Expr *Allocator) {
6174 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6176 llvm::Value *AllocatorVal =
6183 OMPRTL___kmpc_destroy_allocator),
6184 {ThreadId, AllocatorVal});
6189 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs) {
6190 assert(Attrs.MaxTeams.size() == 1 && Attrs.MaxThreads.size() == 1 &&
6191 "invalid default attrs structure");
6192 int32_t &MaxTeamsVal = Attrs.MaxTeams.front();
6193 int32_t &MaxThreadsVal = Attrs.MaxThreads.front();
6200 for (
auto *A :
C->getAttrs()) {
6201 int32_t AttrMinThreadsVal = 1, AttrMaxThreadsVal = -1;
6202 int32_t AttrMinBlocksVal = 1, AttrMaxBlocksVal = -1;
6203 if (
auto *
Attr = dyn_cast<CUDALaunchBoundsAttr>(A))
6204 CGM.handleCUDALaunchBoundsAttr(
nullptr,
Attr, &AttrMaxThreadsVal,
6205 &AttrMinBlocksVal, &AttrMaxBlocksVal);
6206 else if (
auto *
Attr = dyn_cast<AMDGPUFlatWorkGroupSizeAttr>(A))
6207 CGM.handleAMDGPUFlatWorkGroupSizeAttr(
6208 nullptr,
Attr,
nullptr, &AttrMinThreadsVal,
6209 &AttrMaxThreadsVal);
6213 Attrs.MinThreads = std::max(Attrs.MinThreads, AttrMinThreadsVal);
6214 if (AttrMaxThreadsVal > 0)
6215 MaxThreadsVal = MaxThreadsVal > 0
6216 ? std::min(MaxThreadsVal, AttrMaxThreadsVal)
6217 : AttrMaxThreadsVal;
6218 Attrs.MinTeams = std::max(Attrs.MinTeams, AttrMinBlocksVal);
6219 if (AttrMaxBlocksVal > 0)
6220 MaxTeamsVal = MaxTeamsVal > 0 ? std::min(MaxTeamsVal, AttrMaxBlocksVal)
6228 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6231 llvm::TargetRegionEntryInfo EntryInfo =
6235 llvm::OpenMPIRBuilder::FunctionGenCallback &&GenerateOutlinedFunction =
6236 [&CGF, &D, &
CodeGen](StringRef EntryFnName) {
6237 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
6239 CGOpenMPTargetRegionInfo CGInfo(CS,
CodeGen, EntryFnName);
6244 cantFail(
OMPBuilder.emitTargetRegionFunction(
6245 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
6251 CGM.getTargetCodeGenInfo().setTargetAttributes(
nullptr, OutlinedFn,
CGM);
6254 for (
auto *A :
C->getAttrs()) {
6255 if (
auto *
Attr = dyn_cast<AMDGPUWavesPerEUAttr>(A))
6256 CGM.handleAMDGPUWavesPerEUAttr(OutlinedFn,
Attr);
6274 while (
const auto *
C = dyn_cast_or_null<CompoundStmt>(Child)) {
6276 for (
const Stmt *S :
C->body()) {
6277 if (
const auto *E = dyn_cast<Expr>(S)) {
6286 if (
const auto *DS = dyn_cast<DeclStmt>(S)) {
6287 if (llvm::all_of(DS->decls(), [](
const Decl *D) {
6288 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6289 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6290 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6291 isa<UsingDirectiveDecl>(D) ||
6292 isa<OMPDeclareReductionDecl>(D) ||
6293 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6295 const auto *VD = dyn_cast<VarDecl>(D);
6298 return VD->hasGlobalStorage() || !VD->isUsed();
6308 Child = Child->IgnoreContainers();
6315 int32_t &MaxTeamsVal) {
6319 "Expected target-based executable directive.");
6320 switch (DirectiveKind) {
6322 const auto *CS = D.getInnermostCapturedStmt();
6325 const Stmt *ChildStmt =
6327 if (
const auto *NestedDir =
6328 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6337 MinTeamsVal = MaxTeamsVal = Constant->getExtValue();
6340 MinTeamsVal = MaxTeamsVal = 0;
6343 MinTeamsVal = MaxTeamsVal = 1;
6347 MinTeamsVal = MaxTeamsVal = -1;
6350 case OMPD_target_teams_loop:
6351 case OMPD_target_teams:
6352 case OMPD_target_teams_distribute:
6353 case OMPD_target_teams_distribute_simd:
6354 case OMPD_target_teams_distribute_parallel_for:
6355 case OMPD_target_teams_distribute_parallel_for_simd: {
6357 const Expr *NumTeams =
6361 MinTeamsVal = MaxTeamsVal = Constant->getExtValue();
6364 MinTeamsVal = MaxTeamsVal = 0;
6367 case OMPD_target_parallel:
6368 case OMPD_target_parallel_for:
6369 case OMPD_target_parallel_for_simd:
6370 case OMPD_target_parallel_loop:
6371 case OMPD_target_simd:
6372 MinTeamsVal = MaxTeamsVal = 1;
6376 case OMPD_parallel_for:
6377 case OMPD_parallel_loop:
6378 case OMPD_parallel_master:
6379 case OMPD_parallel_sections:
6381 case OMPD_parallel_for_simd:
6383 case OMPD_cancellation_point:
6385 case OMPD_threadprivate:
6396 case OMPD_taskyield:
6399 case OMPD_taskgroup:
6405 case OMPD_target_data:
6406 case OMPD_target_exit_data:
6407 case OMPD_target_enter_data:
6408 case OMPD_distribute:
6409 case OMPD_distribute_simd:
6410 case OMPD_distribute_parallel_for:
6411 case OMPD_distribute_parallel_for_simd:
6412 case OMPD_teams_distribute:
6413 case OMPD_teams_distribute_simd:
6414 case OMPD_teams_distribute_parallel_for:
6415 case OMPD_teams_distribute_parallel_for_simd:
6416 case OMPD_target_update:
6417 case OMPD_declare_simd:
6418 case OMPD_declare_variant:
6419 case OMPD_begin_declare_variant:
6420 case OMPD_end_declare_variant:
6421 case OMPD_declare_target:
6422 case OMPD_end_declare_target:
6423 case OMPD_declare_reduction:
6424 case OMPD_declare_mapper:
6426 case OMPD_taskloop_simd:
6427 case OMPD_master_taskloop:
6428 case OMPD_master_taskloop_simd:
6429 case OMPD_parallel_master_taskloop:
6430 case OMPD_parallel_master_taskloop_simd:
6432 case OMPD_metadirective:
6438 llvm_unreachable(
"Unexpected directive kind.");
6444 "Clauses associated with the teams directive expected to be emitted "
6445 "only for the host!");
6447 int32_t MinNT = -1, MaxNT = -1;
6448 const Expr *NumTeams =
6450 if (NumTeams !=
nullptr) {
6453 switch (DirectiveKind) {
6455 const auto *CS = D.getInnermostCapturedStmt();
6456 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6460 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6463 case OMPD_target_teams:
6464 case OMPD_target_teams_distribute:
6465 case OMPD_target_teams_distribute_simd:
6466 case OMPD_target_teams_distribute_parallel_for:
6467 case OMPD_target_teams_distribute_parallel_for_simd: {
6471 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6479 assert(MinNT == MaxNT &&
"Num threads ranges require handling here.");
6480 return llvm::ConstantInt::get(CGF.
Int32Ty, MinNT);
6488 const Expr **E, int32_t &UpperBound,
6489 bool UpperBoundOnly, llvm::Value **CondVal) {
6492 const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6499 if (CondVal && Dir->hasClausesOfKind<
OMPIfClause>()) {
6500 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6503 for (
const auto *
C : Dir->getClausesOfKind<
OMPIfClause>()) {
6504 if (
C->getNameModifier() == OMPD_unknown ||
6505 C->getNameModifier() == OMPD_parallel) {
6520 if (
const auto *PreInit =
6522 for (
const auto *I : PreInit->decls()) {
6523 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6539 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6541 const auto *NumThreadsClause =
6543 const Expr *NTExpr = NumThreadsClause->getNumThreads();
6544 if (NTExpr->isIntegerConstantExpr(CGF.
getContext()))
6545 if (
auto Constant = NTExpr->getIntegerConstantExpr(CGF.
getContext()))
6548 ? Constant->getZExtValue()
6549 : std::min(UpperBound,
6550 static_cast<int32_t
>(Constant->getZExtValue()));
6553 if (UpperBound == -1)
6558 if (
const auto *PreInit =
6559 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6560 for (
const auto *I : PreInit->decls()) {
6561 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6580 bool UpperBoundOnly, llvm::Value **CondVal,
const Expr **ThreadLimitExpr) {
6581 assert((!CGF.
getLangOpts().OpenMPIsTargetDevice || UpperBoundOnly) &&
6582 "Clauses associated with the teams directive expected to be emitted "
6583 "only for the host!");
6586 "Expected target-based executable directive.");
6588 const Expr *NT =
nullptr;
6589 const Expr **NTPtr = UpperBoundOnly ?
nullptr : &NT;
6591 auto CheckForConstExpr = [&](
const Expr *E,
const Expr **EPtr) {
6594 UpperBound = UpperBound ? Constant->getZExtValue()
6595 : std::min(UpperBound,
6596 int32_t(Constant->getZExtValue()));
6600 if (UpperBound == -1)
6606 auto ReturnSequential = [&]() {
6611 switch (DirectiveKind) {
6614 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6620 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6622 ThreadLimitClause = TLC;
6623 if (ThreadLimitExpr) {
6624 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6628 ThreadLimitClause->getThreadLimit().front()->getSourceRange());
6629 if (
const auto *PreInit =
6630 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6631 for (
const auto *I : PreInit->decls()) {
6632 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6644 if (ThreadLimitClause)
6645 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6647 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6650 CS = Dir->getInnermostCapturedStmt();
6653 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6656 CS = Dir->getInnermostCapturedStmt();
6657 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6659 return ReturnSequential();
6663 case OMPD_target_teams: {
6667 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6671 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6674 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6675 if (Dir->getDirectiveKind() == OMPD_distribute) {
6676 CS = Dir->getInnermostCapturedStmt();
6677 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6682 case OMPD_target_teams_distribute:
6686 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6689 getNumThreads(CGF, D.getInnermostCapturedStmt(), NTPtr, UpperBound,
6690 UpperBoundOnly, CondVal);
6692 case OMPD_target_teams_loop:
6693 case OMPD_target_parallel_loop:
6694 case OMPD_target_parallel:
6695 case OMPD_target_parallel_for:
6696 case OMPD_target_parallel_for_simd:
6697 case OMPD_target_teams_distribute_parallel_for:
6698 case OMPD_target_teams_distribute_parallel_for_simd: {
6699 if (CondVal && D.hasClausesOfKind<
OMPIfClause>()) {
6701 for (
const auto *
C : D.getClausesOfKind<
OMPIfClause>()) {
6702 if (
C->getNameModifier() == OMPD_unknown ||
6703 C->getNameModifier() == OMPD_parallel) {
6713 return ReturnSequential();
6723 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6729 CheckForConstExpr(NumThreadsClause->getNumThreads(),
nullptr);
6730 return NumThreadsClause->getNumThreads();
6734 case OMPD_target_teams_distribute_simd:
6735 case OMPD_target_simd:
6736 return ReturnSequential();
6740 llvm_unreachable(
"Unsupported directive kind.");
6745 llvm::Value *NumThreadsVal =
nullptr;
6746 llvm::Value *CondVal =
nullptr;
6747 llvm::Value *ThreadLimitVal =
nullptr;
6748 const Expr *ThreadLimitExpr =
nullptr;
6749 int32_t UpperBound = -1;
6752 CGF, D, UpperBound,
false, &CondVal,
6756 if (ThreadLimitExpr) {
6759 ThreadLimitVal = CGF.
Builder.CreateIntCast(ThreadLimitVal, CGF.
Int32Ty,
6764 if (UpperBound == 1) {
6765 NumThreadsVal = CGF.
Builder.getInt32(UpperBound);
6768 NumThreadsVal = CGF.
Builder.CreateIntCast(NumThreadsVal, CGF.
Int32Ty,
6770 }
else if (ThreadLimitVal) {
6773 NumThreadsVal = ThreadLimitVal;
6774 ThreadLimitVal =
nullptr;
6777 assert(!ThreadLimitVal &&
"Default not applicable with thread limit value");
6778 NumThreadsVal = CGF.
Builder.getInt32(0);
6785 NumThreadsVal = CGF.
Builder.CreateSelect(CondVal, NumThreadsVal,
6791 if (ThreadLimitVal) {
6792 NumThreadsVal = CGF.
Builder.CreateSelect(
6793 CGF.
Builder.CreateICmpULT(ThreadLimitVal, NumThreadsVal),
6794 ThreadLimitVal, NumThreadsVal);
6797 return NumThreadsVal;
6807class MappableExprsHandler {
6813 struct AttachPtrExprComparator {
6814 const MappableExprsHandler &Handler;
6816 mutable llvm::DenseMap<std::pair<const Expr *, const Expr *>,
bool>
6817 CachedEqualityComparisons;
6819 AttachPtrExprComparator(
const MappableExprsHandler &H) : Handler(H) {}
6820 AttachPtrExprComparator() =
delete;
6823 bool operator()(
const Expr *LHS,
const Expr *RHS)
const {
6828 const auto ItLHS = Handler.AttachPtrComponentDepthMap.find(LHS);
6829 const auto ItRHS = Handler.AttachPtrComponentDepthMap.find(RHS);
6831 std::optional<size_t> DepthLHS =
6832 (ItLHS != Handler.AttachPtrComponentDepthMap.end()) ? ItLHS->second
6834 std::optional<size_t> DepthRHS =
6835 (ItRHS != Handler.AttachPtrComponentDepthMap.end()) ? ItRHS->second
6839 if (!DepthLHS.has_value() && !DepthRHS.has_value()) {
6841 if (areEqual(LHS, RHS))
6844 return wasComputedBefore(LHS, RHS);
6846 if (!DepthLHS.has_value())
6848 if (!DepthRHS.has_value())
6852 if (DepthLHS.value() != DepthRHS.value())
6853 return DepthLHS.value() < DepthRHS.value();
6856 if (areEqual(LHS, RHS))
6859 return wasComputedBefore(LHS, RHS);
6865 bool areEqual(
const Expr *LHS,
const Expr *RHS)
const {
6867 const auto CachedResultIt = CachedEqualityComparisons.find({LHS, RHS});
6868 if (CachedResultIt != CachedEqualityComparisons.end())
6869 return CachedResultIt->second;
6883 bool wasComputedBefore(
const Expr *LHS,
const Expr *RHS)
const {
6884 const size_t &OrderLHS = Handler.AttachPtrComputationOrderMap.at(LHS);
6885 const size_t &OrderRHS = Handler.AttachPtrComputationOrderMap.at(RHS);
6887 return OrderLHS < OrderRHS;
6896 bool areSemanticallyEqual(
const Expr *LHS,
const Expr *RHS)
const {
6918 if (
const auto *LD = dyn_cast<DeclRefExpr>(LHS)) {
6919 const auto *RD = dyn_cast<DeclRefExpr>(RHS);
6922 return LD->getDecl()->getCanonicalDecl() ==
6923 RD->getDecl()->getCanonicalDecl();
6927 if (
const auto *LA = dyn_cast<ArraySubscriptExpr>(LHS)) {
6928 const auto *RA = dyn_cast<ArraySubscriptExpr>(RHS);
6931 return areSemanticallyEqual(LA->getBase(), RA->getBase()) &&
6932 areSemanticallyEqual(LA->getIdx(), RA->getIdx());
6936 if (
const auto *LM = dyn_cast<MemberExpr>(LHS)) {
6937 const auto *RM = dyn_cast<MemberExpr>(RHS);
6940 if (LM->getMemberDecl()->getCanonicalDecl() !=
6941 RM->getMemberDecl()->getCanonicalDecl())
6943 return areSemanticallyEqual(LM->getBase(), RM->getBase());
6947 if (
const auto *LU = dyn_cast<UnaryOperator>(LHS)) {
6948 const auto *RU = dyn_cast<UnaryOperator>(RHS);
6951 if (LU->getOpcode() != RU->getOpcode())
6953 return areSemanticallyEqual(LU->getSubExpr(), RU->getSubExpr());
6957 if (
const auto *LB = dyn_cast<BinaryOperator>(LHS)) {
6958 const auto *RB = dyn_cast<BinaryOperator>(RHS);
6961 if (LB->getOpcode() != RB->getOpcode())
6963 return areSemanticallyEqual(LB->getLHS(), RB->getLHS()) &&
6964 areSemanticallyEqual(LB->getRHS(), RB->getRHS());
6970 if (
const auto *LAS = dyn_cast<ArraySectionExpr>(LHS)) {
6971 const auto *RAS = dyn_cast<ArraySectionExpr>(RHS);
6974 return areSemanticallyEqual(LAS->getBase(), RAS->getBase()) &&
6975 areSemanticallyEqual(LAS->getLowerBound(),
6976 RAS->getLowerBound()) &&
6977 areSemanticallyEqual(LAS->getLength(), RAS->getLength());
6981 if (
const auto *LC = dyn_cast<CastExpr>(LHS)) {
6982 const auto *RC = dyn_cast<CastExpr>(RHS);
6985 if (LC->getCastKind() != RC->getCastKind())
6987 return areSemanticallyEqual(LC->getSubExpr(), RC->getSubExpr());
6995 if (
const auto *LI = dyn_cast<IntegerLiteral>(LHS)) {
6996 const auto *RI = dyn_cast<IntegerLiteral>(RHS);
6999 return LI->getValue() == RI->getValue();
7003 if (
const auto *LC = dyn_cast<CharacterLiteral>(LHS)) {
7004 const auto *RC = dyn_cast<CharacterLiteral>(RHS);
7007 return LC->getValue() == RC->getValue();
7011 if (
const auto *LF = dyn_cast<FloatingLiteral>(LHS)) {
7012 const auto *RF = dyn_cast<FloatingLiteral>(RHS);
7016 return LF->getValue().bitwiseIsEqual(RF->getValue());
7020 if (
const auto *LS = dyn_cast<StringLiteral>(LHS)) {
7021 const auto *RS = dyn_cast<StringLiteral>(RHS);
7024 return LS->getString() == RS->getString();
7032 if (
const auto *LB = dyn_cast<CXXBoolLiteralExpr>(LHS)) {
7033 const auto *RB = dyn_cast<CXXBoolLiteralExpr>(RHS);
7036 return LB->getValue() == RB->getValue();
7045 static unsigned getFlagMemberOffset() {
7046 unsigned Offset = 0;
7047 for (uint64_t Remain =
7048 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
7049 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
7050 !(Remain & 1); Remain = Remain >> 1)
7057 class MappingExprInfo {
7059 const ValueDecl *MapDecl =
nullptr;
7062 const Expr *MapExpr =
nullptr;
7065 MappingExprInfo(
const ValueDecl *MapDecl,
const Expr *MapExpr =
nullptr)
7066 : MapDecl(MapDecl), MapExpr(MapExpr) {}
7068 const ValueDecl *getMapDecl()
const {
return MapDecl; }
7069 const Expr *getMapExpr()
const {
return MapExpr; }
7072 using DeviceInfoTy = llvm::OpenMPIRBuilder::DeviceInfoTy;
7073 using MapBaseValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7074 using MapValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7075 using MapFlagsArrayTy = llvm::OpenMPIRBuilder::MapFlagsArrayTy;
7076 using MapDimArrayTy = llvm::OpenMPIRBuilder::MapDimArrayTy;
7077 using MapNonContiguousArrayTy =
7078 llvm::OpenMPIRBuilder::MapNonContiguousArrayTy;
7079 using MapExprsArrayTy = SmallVector<MappingExprInfo, 4>;
7080 using MapValueDeclsArrayTy = SmallVector<const ValueDecl *, 4>;
7084 bool ,
const ValueDecl *,
const Expr *>;
7085 using MapDataArrayTy = SmallVector<MapData, 4>;
7090 struct MapCombinedInfoTy : llvm::OpenMPIRBuilder::MapInfosTy {
7091 MapExprsArrayTy Exprs;
7092 MapValueDeclsArrayTy Mappers;
7093 MapValueDeclsArrayTy DevicePtrDecls;
7096 void append(MapCombinedInfoTy &CurInfo) {
7097 Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end());
7098 DevicePtrDecls.append(CurInfo.DevicePtrDecls.begin(),
7099 CurInfo.DevicePtrDecls.end());
7100 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end());
7101 llvm::OpenMPIRBuilder::MapInfosTy::append(CurInfo);
7109 struct StructRangeInfoTy {
7110 MapCombinedInfoTy PreliminaryMapData;
7111 std::pair<
unsigned , Address > LowestElem = {
7113 std::pair<
unsigned , Address > HighestElem = {
7117 bool IsArraySection =
false;
7118 bool HasCompleteRecord =
false;
7123 struct AttachInfoTy {
7126 const ValueDecl *AttachPtrDecl =
nullptr;
7127 const Expr *AttachMapExpr =
nullptr;
7129 bool isValid()
const {
7136 bool hasAttachEntryForCapturedVar(
const ValueDecl *VD)
const {
7137 for (
const auto &AttachEntry : AttachPtrExprMap) {
7138 if (AttachEntry.second) {
7141 if (
const auto *DRE = dyn_cast<DeclRefExpr>(AttachEntry.second))
7142 if (DRE->getDecl() == VD)
7150 const Expr *getAttachPtrExpr(
7153 const auto It = AttachPtrExprMap.find(Components);
7154 if (It != AttachPtrExprMap.end())
7165 ArrayRef<OpenMPMapModifierKind> MapModifiers;
7166 ArrayRef<OpenMPMotionModifierKind> MotionModifiers;
7167 bool ReturnDevicePointer =
false;
7168 bool IsImplicit =
false;
7169 const ValueDecl *Mapper =
nullptr;
7170 const Expr *VarRef =
nullptr;
7171 bool ForDeviceAddr =
false;
7173 MapInfo() =
default;
7177 ArrayRef<OpenMPMapModifierKind> MapModifiers,
7178 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7179 bool ReturnDevicePointer,
bool IsImplicit,
7180 const ValueDecl *Mapper =
nullptr,
const Expr *VarRef =
nullptr,
7181 bool ForDeviceAddr =
false)
7182 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
7183 MotionModifiers(MotionModifiers),
7184 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit),
7185 Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr) {}
7191 struct DeferredDevicePtrEntryTy {
7192 const Expr *IE =
nullptr;
7193 const ValueDecl *VD =
nullptr;
7194 bool ForDeviceAddr =
false;
7196 DeferredDevicePtrEntryTy(
const Expr *IE,
const ValueDecl *VD,
7198 : IE(IE), VD(VD), ForDeviceAddr(ForDeviceAddr) {}
7203 llvm::PointerUnion<
const OMPExecutableDirective *,
7204 const OMPDeclareMapperDecl *>
7208 CodeGenFunction &CGF;
7213 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
bool> FirstPrivateDecls;
7216 llvm::SmallSet<OpenMPDefaultmapClauseKind, 4> DefaultmapFirstprivateKinds;
7222 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7229 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7233 llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap;
7248 llvm::DenseMap<const Expr *, std::optional<size_t>>
7249 AttachPtrComponentDepthMap = {{
nullptr, std::nullopt}};
7253 llvm::DenseMap<const Expr *, size_t> AttachPtrComputationOrderMap = {
7258 AttachPtrExprComparator AttachPtrComparator;
7260 llvm::Value *getExprTypeSize(
const Expr *E)
const {
7264 if (
const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) {
7266 CGF.
getTypeSize(OAE->getBase()->getType()->getPointeeType());
7267 for (
const Expr *SE : OAE->getDimensions()) {
7278 if (
const auto *RefTy = ExprTy->
getAs<ReferenceType>())
7284 if (
const auto *OAE = dyn_cast<ArraySectionExpr>(E)) {
7286 OAE->getBase()->IgnoreParenImpCasts())
7292 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7293 !OAE->getLowerBound())
7296 llvm::Value *ElemSize;
7297 if (
const auto *PTy = BaseTy->
getAs<PointerType>()) {
7298 ElemSize = CGF.
getTypeSize(PTy->getPointeeType().getCanonicalType());
7301 assert(ATy &&
"Expecting array type if not a pointer type.");
7302 ElemSize = CGF.
getTypeSize(ATy->getElementType().getCanonicalType());
7307 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
7310 if (
const Expr *LenExpr = OAE->getLength()) {
7314 LenExpr->getExprLoc());
7315 return CGF.
Builder.CreateNUWMul(LengthVal, ElemSize);
7317 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7318 OAE->getLowerBound() &&
"expected array_section[lb:].");
7324 OAE->getLowerBound()->getExprLoc());
7325 LBVal = CGF.
Builder.CreateNUWMul(LBVal, ElemSize);
7326 llvm::Value *Cmp = CGF.
Builder.CreateICmpUGT(LengthVal, LBVal);
7327 llvm::Value *TrueVal = CGF.
Builder.CreateNUWSub(LengthVal, LBVal);
7328 LengthVal = CGF.
Builder.CreateSelect(
7329 Cmp, TrueVal, llvm::ConstantInt::get(CGF.
SizeTy, 0));
7339 OpenMPOffloadMappingFlags getMapTypeBits(
7341 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
bool IsImplicit,
7342 bool AddPtrFlag,
bool AddIsTargetParamFlag,
bool IsNonContiguous)
const {
7343 OpenMPOffloadMappingFlags Bits =
7344 IsImplicit ? OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT
7345 : OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7347 case OMPC_MAP_alloc:
7348 case OMPC_MAP_release:
7355 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO;
7358 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7360 case OMPC_MAP_tofrom:
7361 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO |
7362 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7364 case OMPC_MAP_delete:
7365 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
7368 llvm_unreachable(
"Unexpected map type!");
7371 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
7372 if (AddIsTargetParamFlag)
7373 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7374 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_always))
7375 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7376 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_close))
7377 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
7378 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_present) ||
7379 llvm::is_contained(MotionModifiers, OMPC_MOTION_MODIFIER_present))
7380 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
7381 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold))
7382 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
7383 if (IsNonContiguous)
7384 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG;
7390 bool isFinalArraySectionExpression(
const Expr *E)
const {
7391 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
7398 if (OASE->getColonLocFirst().isInvalid())
7401 const Expr *Length = OASE->getLength();
7408 OASE->getBase()->IgnoreParenImpCasts())
7410 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
7411 return ATy->getSExtSize() != 1;
7423 llvm::APSInt ConstLength =
Result.Val.getInt();
7424 return ConstLength.getSExtValue() != 1;
7431 class CopyOverlappedEntryGaps {
7432 CodeGenFunction &CGF;
7433 MapCombinedInfoTy &CombinedInfo;
7434 OpenMPOffloadMappingFlags Flags = OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7435 const ValueDecl *MapDecl =
nullptr;
7436 const Expr *MapExpr =
nullptr;
7438 bool IsNonContiguous =
false;
7442 const RecordDecl *LastParent =
nullptr;
7444 unsigned LastIndex = -1u;
7448 CopyOverlappedEntryGaps(CodeGenFunction &CGF,
7449 MapCombinedInfoTy &CombinedInfo,
7450 OpenMPOffloadMappingFlags Flags,
7451 const ValueDecl *MapDecl,
const Expr *MapExpr,
7452 Address BP, Address LB,
bool IsNonContiguous,
7454 : CGF(CGF), CombinedInfo(CombinedInfo), Flags(Flags), MapDecl(MapDecl),
7455 MapExpr(MapExpr), BP(BP), IsNonContiguous(IsNonContiguous),
7456 DimSize(DimSize), LB(LB) {}
7459 const OMPClauseMappableExprCommon::MappableComponent &MC,
7460 const FieldDecl *FD,
7461 llvm::function_ref<LValue(CodeGenFunction &,
const MemberExpr *)>
7462 EmitMemberExprBase) {
7472 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
7484 copyUntilField(FD, ComponentLB);
7487 if (((int64_t)FieldOffset - (int64_t)Cursor) > 0)
7488 copyUntilField(FD, ComponentLB);
7490 Cursor = FieldOffset + FieldSize;
7495 void copyUntilField(
const FieldDecl *FD, Address ComponentLB) {
7499 CGF.
Builder.CreatePtrDiff(CGF.
Int8Ty, ComponentLBPtr, LBPtr);
7500 copySizedChunk(LBPtr, Size);
7503 void copyUntilEnd(Address HB) {
7505 const ASTRecordLayout &RL =
7514 copySizedChunk(LBPtr, Size);
7517 void copySizedChunk(llvm::Value *Base, llvm::Value *Size) {
7518 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7520 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7521 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7522 CombinedInfo.Pointers.push_back(Base);
7523 CombinedInfo.Sizes.push_back(
7525 CombinedInfo.Types.push_back(Flags);
7526 CombinedInfo.Mappers.push_back(
nullptr);
7527 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1);
7536 void generateInfoForComponentList(
7538 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7540 MapCombinedInfoTy &CombinedInfo,
7541 MapCombinedInfoTy &StructBaseCombinedInfo,
7542 StructRangeInfoTy &PartialStruct,
bool IsFirstComponentList,
7543 bool IsImplicit,
bool GenerateAllInfoForClauses,
7544 const ValueDecl *Mapper =
nullptr,
bool ForDeviceAddr =
false,
7545 const ValueDecl *BaseDecl =
nullptr,
const Expr *MapExpr =
nullptr,
7546 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7547 OverlappedElements = {},
7548 bool AreBothBasePtrAndPteeMapped =
false)
const {
7730 bool IsCaptureFirstInfo = IsFirstComponentList;
7734 bool RequiresReference =
false;
7737 auto CI = Components.rbegin();
7738 auto CE = Components.rend();
7743 bool IsExpressionFirstInfo =
true;
7744 bool FirstPointerInComplexData =
false;
7746 const Expr *AssocExpr = I->getAssociatedExpression();
7747 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7748 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
7749 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
7751 if (AreBothBasePtrAndPteeMapped && std::next(I) == CE)
7757 }
else if ((AE &&
isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7771 if (
const auto *VD =
7772 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7773 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
7774 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7775 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7776 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
7777 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
7779 RequiresReference =
true;
7789 I->getAssociatedDeclaration()->
getType().getNonReferenceType();
7794 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
7795 if (!AreBothBasePtrAndPteeMapped &&
7797 !VD || VD->hasLocalStorage()))
7800 FirstPointerInComplexData =
true;
7819 bool ShouldBeMemberOf =
false;
7828 const MemberExpr *EncounteredME =
nullptr;
7840 bool IsNonContiguous =
7841 CombinedInfo.NonContigInfo.IsNonContiguous ||
7842 any_of(Components, [&](
const auto &Component) {
7844 dyn_cast<ArraySectionExpr>(Component.getAssociatedExpression());
7848 const Expr *StrideExpr = OASE->getStride();
7852 const auto Constant =
7857 return !Constant->isOne();
7860 bool IsPrevMemberReference =
false;
7862 bool IsPartialMapped =
7863 !PartialStruct.PreliminaryMapData.BasePointers.empty();
7870 bool IsMappingWholeStruct =
true;
7871 if (!GenerateAllInfoForClauses) {
7872 IsMappingWholeStruct =
false;
7874 for (
auto TempI = I; TempI != CE; ++TempI) {
7875 const MemberExpr *PossibleME =
7876 dyn_cast<MemberExpr>(TempI->getAssociatedExpression());
7878 IsMappingWholeStruct =
false;
7884 for (; I != CE; ++I) {
7886 if (!EncounteredME) {
7887 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
7890 if (EncounteredME) {
7891 ShouldBeMemberOf =
true;
7894 if (FirstPointerInComplexData) {
7895 QualType Ty = std::prev(I)
7896 ->getAssociatedDeclaration()
7898 .getNonReferenceType();
7900 FirstPointerInComplexData =
false;
7905 auto Next = std::next(I);
7915 bool IsFinalArraySection =
7917 isFinalArraySectionExpression(I->getAssociatedExpression());
7921 const ValueDecl *MapDecl = (I->getAssociatedDeclaration())
7922 ? I->getAssociatedDeclaration()
7924 MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression()
7931 dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
7933 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
7934 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
7935 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
7941 I->getAssociatedExpression()->getType()->isAnyPointerType();
7942 bool IsMemberReference =
isa<MemberExpr>(I->getAssociatedExpression()) &&
7945 bool IsNonDerefPointer = IsPointer &&
7946 !(UO && UO->getOpcode() != UO_Deref) && !BO &&
7952 if (
Next == CE || IsMemberReference || IsNonDerefPointer ||
7953 IsFinalArraySection) {
7956 assert((
Next == CE ||
7963 "Unexpected expression");
7967 auto &&EmitMemberExprBase = [](CodeGenFunction &CGF,
7968 const MemberExpr *E) {
7969 const Expr *BaseExpr = E->getBase();
7974 LValueBaseInfo BaseInfo;
7975 TBAAAccessInfo TBAAInfo;
7989 OAShE->getBase()->getType()->getPointeeType()),
7991 OAShE->getBase()->getType()));
7992 }
else if (IsMemberReference) {
7994 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
8009 bool IsMemberPointerOrAddr =
8011 (((IsPointer || ForDeviceAddr) &&
8012 I->getAssociatedExpression() == EncounteredME) ||
8013 (IsPrevMemberReference && !IsPointer) ||
8014 (IsMemberReference &&
Next != CE &&
8015 !
Next->getAssociatedExpression()->getType()->isPointerType()));
8016 if (!OverlappedElements.empty() &&
Next == CE) {
8018 assert(!PartialStruct.Base.isValid() &&
"The base element is set.");
8019 assert(!IsPointer &&
8020 "Unexpected base element with the pointer type.");
8023 PartialStruct.LowestElem = {0, LowestElem};
8025 I->getAssociatedExpression()->getType());
8030 PartialStruct.HighestElem = {
8031 std::numeric_limits<
decltype(
8032 PartialStruct.HighestElem.first)>
::max(),
8034 PartialStruct.Base = BP;
8035 PartialStruct.LB = LB;
8037 PartialStruct.PreliminaryMapData.BasePointers.empty() &&
8038 "Overlapped elements must be used only once for the variable.");
8039 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo);
8041 OpenMPOffloadMappingFlags Flags =
8042 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8043 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
8045 false, IsNonContiguous);
8046 CopyOverlappedEntryGaps CopyGaps(CGF, CombinedInfo, Flags, MapDecl,
8047 MapExpr, BP, LB, IsNonContiguous,
8051 Component : OverlappedElements) {
8052 for (
const OMPClauseMappableExprCommon::MappableComponent &MC :
8055 if (
const auto *FD = dyn_cast<FieldDecl>(VD)) {
8056 CopyGaps.processField(MC, FD, EmitMemberExprBase);
8061 CopyGaps.copyUntilEnd(HB);
8064 llvm::Value *
Size = getExprTypeSize(I->getAssociatedExpression());
8071 if ((!IsMemberPointerOrAddr && !IsPartialMapped) ||
8073 if (!IsMappingWholeStruct) {
8074 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8076 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8077 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8079 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8081 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
8084 StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8085 StructBaseCombinedInfo.BasePointers.push_back(
8087 StructBaseCombinedInfo.DevicePtrDecls.push_back(
nullptr);
8088 StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8089 StructBaseCombinedInfo.Pointers.push_back(LB.
emitRawPointer(CGF));
8090 StructBaseCombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8092 StructBaseCombinedInfo.NonContigInfo.Dims.push_back(
8093 IsNonContiguous ? DimSize : 1);
8097 bool HasMapper = Mapper &&
Next == CE;
8098 if (!IsMappingWholeStruct)
8099 CombinedInfo.Mappers.push_back(HasMapper ? Mapper :
nullptr);
8101 StructBaseCombinedInfo.Mappers.push_back(HasMapper ? Mapper
8108 OpenMPOffloadMappingFlags Flags =
8109 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
8110 !IsExpressionFirstInfo || RequiresReference ||
8111 FirstPointerInComplexData || IsMemberReference,
8112 AreBothBasePtrAndPteeMapped ||
8113 (IsCaptureFirstInfo && !RequiresReference),
8116 if (!IsExpressionFirstInfo || IsMemberReference) {
8119 if (IsPointer || (IsMemberReference &&
Next != CE))
8120 Flags &= ~(OpenMPOffloadMappingFlags::OMP_MAP_TO |
8121 OpenMPOffloadMappingFlags::OMP_MAP_FROM |
8122 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
8123 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
8124 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
8126 if (ShouldBeMemberOf) {
8129 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
8132 ShouldBeMemberOf =
false;
8136 if (!IsMappingWholeStruct)
8137 CombinedInfo.Types.push_back(Flags);
8139 StructBaseCombinedInfo.Types.push_back(Flags);
8145 if (EncounteredME) {
8150 if (!PartialStruct.Base.isValid()) {
8151 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8152 if (IsFinalArraySection && OASE) {
8156 PartialStruct.HighestElem = {FieldIndex, HB};
8158 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8160 PartialStruct.Base = BP;
8161 PartialStruct.LB = BP;
8162 }
else if (FieldIndex < PartialStruct.LowestElem.first) {
8163 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8164 }
else if (FieldIndex > PartialStruct.HighestElem.first) {
8165 if (IsFinalArraySection && OASE) {
8169 PartialStruct.HighestElem = {FieldIndex, HB};
8171 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8177 if (IsFinalArraySection || IsNonContiguous)
8178 PartialStruct.IsArraySection =
true;
8181 if (IsFinalArraySection)
8186 BP = IsMemberReference ? LowestElem : LB;
8187 if (!IsPartialMapped)
8188 IsExpressionFirstInfo =
false;
8189 IsCaptureFirstInfo =
false;
8190 FirstPointerInComplexData =
false;
8191 IsPrevMemberReference = IsMemberReference;
8192 }
else if (FirstPointerInComplexData) {
8193 QualType Ty = Components.rbegin()
8194 ->getAssociatedDeclaration()
8196 .getNonReferenceType();
8198 FirstPointerInComplexData =
false;
8204 PartialStruct.HasCompleteRecord =
true;
8206 if (!IsNonContiguous)
8209 const ASTContext &Context = CGF.
getContext();
8213 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 0)};
8214 MapValuesArrayTy CurCounts = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8215 MapValuesArrayTy CurStrides;
8216 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8222 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8224 const Expr *AssocExpr = Component.getAssociatedExpression();
8225 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8235 assert((VAT || CAT || &Component == &*Components.begin()) &&
8236 "Should be either ConstantArray or VariableArray if not the "
8240 if (CurStrides.empty()) {
8241 const Type *ElementType =
nullptr;
8243 ElementType = CAT->getElementType().getTypePtr();
8245 ElementType = VAT->getElementType().getTypePtr();
8247 assert(&Component == &*Components.begin() &&
8248 "Only expect pointer (non CAT or VAT) when this is the "
8256 if (&Component != &*Components.begin())
8260 CurStrides.push_back(
8261 llvm::ConstantInt::get(CGF.
Int64Ty, ElementTypeSize));
8266 if (DimSizes.size() < Components.size() - 1) {
8269 llvm::ConstantInt::get(CGF.
Int64Ty, CAT->getZExtSize()));
8271 DimSizes.push_back(CGF.
Builder.CreateIntCast(
8278 auto *DI = DimSizes.begin() + 1;
8280 llvm::Value *DimProd =
8281 llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, ElementTypeSize);
8290 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8292 const Expr *AssocExpr = Component.getAssociatedExpression();
8294 if (
const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) {
8295 llvm::Value *Offset = CGF.
Builder.CreateIntCast(
8298 CurOffsets.push_back(Offset);
8299 CurCounts.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 1));
8300 CurStrides.push_back(CurStrides.back());
8304 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8310 const Expr *OffsetExpr = OASE->getLowerBound();
8311 llvm::Value *Offset =
nullptr;
8314 Offset = llvm::ConstantInt::get(CGF.
Int64Ty, 0);
8320 CurOffsets.push_back(Offset);
8323 const Expr *CountExpr = OASE->getLength();
8324 llvm::Value *Count =
nullptr;
8330 if (!OASE->getColonLocFirst().isValid() &&
8331 !OASE->getColonLocSecond().isValid()) {
8332 Count = llvm::ConstantInt::get(CGF.
Int64Ty, 1);
8338 const Expr *StrideExpr = OASE->getStride();
8339 llvm::Value *Stride =
8345 Count = CGF.
Builder.CreateUDiv(
8346 CGF.
Builder.CreateNUWSub(*DI, Offset), Stride);
8348 Count = CGF.
Builder.CreateNUWSub(*DI, Offset);
8354 CurCounts.push_back(Count);
8363 const Expr *StrideExpr = OASE->getStride();
8364 llvm::Value *Stride =
8369 DimProd = CGF.
Builder.CreateNUWMul(DimProd, *(DI - 1));
8371 CurStrides.push_back(CGF.
Builder.CreateNUWMul(DimProd, Stride));
8373 CurStrides.push_back(DimProd);
8374 if (DI != DimSizes.end())
8378 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets);
8379 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts);
8380 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides);
8386 OpenMPOffloadMappingFlags
8387 getMapModifiersForPrivateClauses(
const CapturedStmt::Capture &Cap)
const {
8395 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8396 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
8397 return OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE |
8398 OpenMPOffloadMappingFlags::OMP_MAP_TO;
8401 if (I != LambdasMap.end())
8403 return getMapTypeBits(
8404 I->getSecond()->getMapType(), I->getSecond()->getMapTypeModifiers(),
8405 {}, I->getSecond()->isImplicit(),
8409 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8410 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
8413 void getPlainLayout(
const CXXRecordDecl *RD,
8414 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
8415 bool AsBase)
const {
8418 llvm::StructType *St =
8421 unsigned NumElements = St->getNumElements();
8423 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
8424 RecordLayout(NumElements);
8427 for (
const auto &I : RD->
bases()) {
8431 QualType BaseTy = I.getType();
8442 RecordLayout[FieldIndex] =
Base;
8445 for (
const auto &I : RD->
vbases()) {
8446 QualType BaseTy = I.getType();
8453 if (RecordLayout[FieldIndex])
8455 RecordLayout[FieldIndex] =
Base;
8458 assert(!RD->
isUnion() &&
"Unexpected union.");
8459 for (
const auto *Field : RD->
fields()) {
8462 if (!
Field->isBitField() &&
8465 RecordLayout[FieldIndex] =
Field;
8468 for (
const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
8469 &
Data : RecordLayout) {
8472 if (
const auto *Base = dyn_cast<const CXXRecordDecl *>(
Data))
8473 getPlainLayout(Base, Layout,
true);
8480 static Address getAttachPtrAddr(
const Expr *PointerExpr,
8481 CodeGenFunction &CGF) {
8482 assert(PointerExpr &&
"Cannot get addr from null attach-ptr expr");
8485 if (
auto *DRE = dyn_cast<DeclRefExpr>(PointerExpr)) {
8488 }
else if (
auto *OASE = dyn_cast<ArraySectionExpr>(PointerExpr)) {
8491 }
else if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(PointerExpr)) {
8493 }
else if (
auto *ME = dyn_cast<MemberExpr>(PointerExpr)) {
8495 }
else if (
auto *UO = dyn_cast<UnaryOperator>(PointerExpr)) {
8496 assert(UO->getOpcode() == UO_Deref &&
8497 "Unexpected unary-operator on attach-ptr-expr");
8500 assert(AttachPtrAddr.
isValid() &&
8501 "Failed to get address for attach pointer expression");
8502 return AttachPtrAddr;
8509 static std::pair<Address, Address>
8510 getAttachPtrAddrAndPteeBaseAddr(
const Expr *AttachPtrExpr,
8511 CodeGenFunction &CGF) {
8516 Address AttachPtrAddr = getAttachPtrAddr(AttachPtrExpr, CGF);
8517 assert(AttachPtrAddr.
isValid() &&
"Invalid attach pointer addr");
8519 QualType AttachPtrType =
8524 AttachPtrAddr, AttachPtrType->
castAs<PointerType>());
8525 assert(AttachPteeBaseAddr.
isValid() &&
"Invalid attach pointee base addr");
8527 return {AttachPtrAddr, AttachPteeBaseAddr};
8533 shouldEmitAttachEntry(
const Expr *PointerExpr,
const ValueDecl *MapBaseDecl,
8534 CodeGenFunction &CGF,
8535 llvm::PointerUnion<
const OMPExecutableDirective *,
8536 const OMPDeclareMapperDecl *>
8546 ->getDirectiveKind());
8555 void collectAttachPtrExprInfo(
8557 llvm::PointerUnion<
const OMPExecutableDirective *,
8558 const OMPDeclareMapperDecl *>
8563 ? OMPD_declare_mapper
8566 const auto &[AttachPtrExpr, Depth] =
8570 AttachPtrComputationOrderMap.try_emplace(
8571 AttachPtrExpr, AttachPtrComputationOrderMap.size());
8572 AttachPtrComponentDepthMap.try_emplace(AttachPtrExpr, Depth);
8573 AttachPtrExprMap.try_emplace(Components, AttachPtrExpr);
8581 void generateAllInfoForClauses(
8582 ArrayRef<const OMPClause *> Clauses, MapCombinedInfoTy &CombinedInfo,
8583 llvm::OpenMPIRBuilder &OMPBuilder,
8584 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
8585 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
8590 llvm::MapVector<CanonicalDeclPtr<const Decl>,
8591 SmallVector<SmallVector<MapInfo, 8>, 4>>
8597 [&Info, &SkipVarSet](
8598 const ValueDecl *D, MapKind
Kind,
8601 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8602 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
8603 bool ReturnDevicePointer,
bool IsImplicit,
const ValueDecl *Mapper,
8604 const Expr *VarRef =
nullptr,
bool ForDeviceAddr =
false) {
8605 if (SkipVarSet.contains(D))
8607 auto It = Info.try_emplace(D, Total).first;
8608 It->second[
Kind].emplace_back(
8609 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer,
8610 IsImplicit, Mapper, VarRef, ForDeviceAddr);
8613 for (
const auto *
Cl : Clauses) {
8614 const auto *
C = dyn_cast<OMPMapClause>(
Cl);
8618 if (llvm::is_contained(
C->getMapTypeModifiers(),
8619 OMPC_MAP_MODIFIER_present))
8621 else if (
C->getMapType() == OMPC_MAP_alloc)
8623 const auto *EI =
C->getVarRefs().begin();
8624 for (
const auto L :
C->component_lists()) {
8625 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
8626 InfoGen(std::get<0>(L), Kind, std::get<1>(L),
C->getMapType(),
8627 C->getMapTypeModifiers(), {},
8628 false,
C->isImplicit(), std::get<2>(L),
8633 for (
const auto *
Cl : Clauses) {
8634 const auto *
C = dyn_cast<OMPToClause>(
Cl);
8638 if (llvm::is_contained(
C->getMotionModifiers(),
8639 OMPC_MOTION_MODIFIER_present))
8641 if (llvm::is_contained(
C->getMotionModifiers(),
8642 OMPC_MOTION_MODIFIER_iterator)) {
8643 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
8644 C->getIteratorModifier()->IgnoreParenImpCasts())) {
8645 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
8650 const auto *EI =
C->getVarRefs().begin();
8651 for (
const auto L :
C->component_lists()) {
8652 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_to, {},
8653 C->getMotionModifiers(),
false,
8654 C->isImplicit(), std::get<2>(L), *EI);
8658 for (
const auto *
Cl : Clauses) {
8659 const auto *
C = dyn_cast<OMPFromClause>(
Cl);
8663 if (llvm::is_contained(
C->getMotionModifiers(),
8664 OMPC_MOTION_MODIFIER_present))
8666 if (llvm::is_contained(
C->getMotionModifiers(),
8667 OMPC_MOTION_MODIFIER_iterator)) {
8668 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
8669 C->getIteratorModifier()->IgnoreParenImpCasts())) {
8670 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
8675 const auto *EI =
C->getVarRefs().begin();
8676 for (
const auto L :
C->component_lists()) {
8677 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_from, {},
8678 C->getMotionModifiers(),
8679 false,
C->isImplicit(), std::get<2>(L),
8692 llvm::MapVector<CanonicalDeclPtr<const Decl>,
8693 SmallVector<DeferredDevicePtrEntryTy, 4>>
8695 MapCombinedInfoTy UseDeviceDataCombinedInfo;
8697 auto &&UseDeviceDataCombinedInfoGen =
8698 [&UseDeviceDataCombinedInfo](
const ValueDecl *VD, llvm::Value *Ptr,
8699 CodeGenFunction &CGF,
bool IsDevAddr) {
8700 UseDeviceDataCombinedInfo.Exprs.push_back(VD);
8701 UseDeviceDataCombinedInfo.BasePointers.emplace_back(Ptr);
8702 UseDeviceDataCombinedInfo.DevicePtrDecls.emplace_back(VD);
8703 UseDeviceDataCombinedInfo.DevicePointers.emplace_back(
8704 IsDevAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer);
8705 UseDeviceDataCombinedInfo.Pointers.push_back(Ptr);
8706 UseDeviceDataCombinedInfo.Sizes.push_back(
8707 llvm::Constant::getNullValue(CGF.Int64Ty));
8708 UseDeviceDataCombinedInfo.Types.push_back(
8709 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM);
8710 UseDeviceDataCombinedInfo.Mappers.push_back(
nullptr);
8714 [&DeferredInfo, &UseDeviceDataCombinedInfoGen,
8715 &InfoGen](CodeGenFunction &CGF,
const Expr *IE,
const ValueDecl *VD,
8718 bool IsImplicit,
bool IsDevAddr) {
8731 false, IsImplicit,
nullptr,
nullptr,
8733 DeferredInfo[
nullptr].emplace_back(IE, VD, IsDevAddr);
8737 if (IE->isGLValue())
8738 Ptr = CGF.EmitLValue(IE).getPointer(CGF);
8740 Ptr = CGF.EmitScalarExpr(IE);
8742 Ptr = CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc());
8744 UseDeviceDataCombinedInfoGen(VD, Ptr, CGF, IsDevAddr);
8748 auto &&IsMapInfoExist = [&Info](CodeGenFunction &CGF,
const ValueDecl *VD,
8749 const Expr *IE,
bool IsDevAddr) ->
bool {
8757 if (It != Info.end()) {
8759 for (
auto &
Data : It->second) {
8760 auto *CI = llvm::find_if(
Data, [VD](
const MapInfo &MI) {
8761 return MI.Components.back().getAssociatedDeclaration() == VD;
8769 if (CI !=
Data.end()) {
8771 CI->ForDeviceAddr = IsDevAddr;
8772 CI->ReturnDevicePointer =
true;
8776 auto PrevCI = std::next(CI->Components.rbegin());
8777 const auto *VarD = dyn_cast<VarDecl>(VD);
8780 !VD->getType().getNonReferenceType()->isPointerType() ||
8781 PrevCI == CI->Components.rend() ||
8783 VarD->hasLocalStorage()) {
8784 CI->ForDeviceAddr = IsDevAddr;
8785 CI->ReturnDevicePointer =
true;
8803 for (
const auto *
Cl : Clauses) {
8804 const auto *
C = dyn_cast<OMPUseDevicePtrClause>(
Cl);
8807 for (
const auto L :
C->component_lists()) {
8810 assert(!Components.empty() &&
8811 "Not expecting empty list of components!");
8812 const ValueDecl *VD = Components.back().getAssociatedDeclaration();
8814 const Expr *IE = Components.back().getAssociatedExpression();
8815 if (IsMapInfoExist(CGF, VD, IE,
false))
8817 MapInfoGen(CGF, IE, VD, Components,
C->isImplicit(),
8822 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
8823 for (
const auto *
Cl : Clauses) {
8824 const auto *
C = dyn_cast<OMPUseDeviceAddrClause>(
Cl);
8827 for (
const auto L :
C->component_lists()) {
8830 assert(!std::get<1>(L).empty() &&
8831 "Not expecting empty list of components!");
8832 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration();
8833 if (!Processed.insert(VD).second)
8836 const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
8837 if (IsMapInfoExist(CGF, VD, IE,
true))
8839 MapInfoGen(CGF, IE, VD, Components,
C->isImplicit(),
8844 for (
const auto &
Data : Info) {
8845 StructRangeInfoTy PartialStruct;
8847 MapCombinedInfoTy CurInfo;
8849 MapCombinedInfoTy StructBaseCurInfo;
8851 const ValueDecl *VD = cast_or_null<ValueDecl>(D);
8852 bool HasMapBasePtr =
false;
8853 bool HasMapArraySec =
false;
8855 for (
const auto &M :
Data.second) {
8856 HasMapBasePtr = any_of(M, [](
const MapInfo &L) {
8857 return isa_and_present<DeclRefExpr>(L.VarRef);
8859 HasMapArraySec = any_of(M, [](
const MapInfo &L) {
8860 return isa_and_present<ArraySectionExpr, ArraySubscriptExpr>(
8863 if (HasMapBasePtr && HasMapArraySec)
8867 for (
const auto &M :
Data.second) {
8868 for (
const MapInfo &L : M) {
8869 assert(!L.Components.empty() &&
8870 "Not expecting declaration with no component lists.");
8873 unsigned CurrentBasePointersIdx = CurInfo.BasePointers.size();
8874 unsigned StructBasePointersIdx =
8875 StructBaseCurInfo.BasePointers.size();
8876 CurInfo.NonContigInfo.IsNonContiguous =
8877 L.Components.back().isNonContiguous();
8878 generateInfoForComponentList(
8879 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
8880 CurInfo, StructBaseCurInfo, PartialStruct,
8881 false, L.IsImplicit,
8882 true, L.Mapper, L.ForDeviceAddr, VD,
8884 HasMapBasePtr && HasMapArraySec);
8888 if (L.ReturnDevicePointer) {
8892 assert((CurrentBasePointersIdx < CurInfo.BasePointers.size() ||
8893 StructBasePointersIdx <
8894 StructBaseCurInfo.BasePointers.size()) &&
8895 "Unexpected number of mapped base pointers.");
8898 const ValueDecl *RelevantVD =
8899 L.Components.back().getAssociatedDeclaration();
8900 assert(RelevantVD &&
8901 "No relevant declaration related with device pointer??");
8908 if (StructBasePointersIdx < StructBaseCurInfo.BasePointers.size()) {
8909 StructBaseCurInfo.DevicePtrDecls[StructBasePointersIdx] =
8911 StructBaseCurInfo.DevicePointers[StructBasePointersIdx] =
8912 L.ForDeviceAddr ? DeviceInfoTy::Address
8913 : DeviceInfoTy::Pointer;
8914 StructBaseCurInfo.Types[StructBasePointersIdx] |=
8915 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
8917 CurInfo.DevicePtrDecls[CurrentBasePointersIdx] = RelevantVD;
8918 CurInfo.DevicePointers[CurrentBasePointersIdx] =
8919 L.ForDeviceAddr ? DeviceInfoTy::Address
8920 : DeviceInfoTy::Pointer;
8921 CurInfo.Types[CurrentBasePointersIdx] |=
8922 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
8930 auto CI = DeferredInfo.find(
Data.first);
8931 if (CI != DeferredInfo.end()) {
8932 for (
const DeferredDevicePtrEntryTy &L : CI->second) {
8933 llvm::Value *BasePtr;
8935 if (L.ForDeviceAddr) {
8936 if (L.IE->isGLValue())
8944 CurInfo.Types.push_back(
8945 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM |
8946 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
8950 L.IE->getExprLoc());
8954 CurInfo.Types.push_back(
8955 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
8956 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM |
8957 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
8959 CurInfo.Exprs.push_back(L.VD);
8960 CurInfo.BasePointers.emplace_back(BasePtr);
8961 CurInfo.DevicePtrDecls.emplace_back(L.VD);
8962 CurInfo.DevicePointers.emplace_back(
8963 L.ForDeviceAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer);
8964 CurInfo.Pointers.push_back(Ptr);
8965 CurInfo.Sizes.push_back(
8966 llvm::Constant::getNullValue(this->CGF.
Int64Ty));
8967 CurInfo.Mappers.push_back(
nullptr);
8973 MapCombinedInfoTy UnionCurInfo;
8974 UnionCurInfo.append(StructBaseCurInfo);
8975 UnionCurInfo.append(CurInfo);
8979 if (PartialStruct.Base.isValid()) {
8980 UnionCurInfo.NonContigInfo.Dims.push_back(0);
8982 emitCombinedEntry(CombinedInfo, UnionCurInfo.Types, PartialStruct,
8983 !VD, OMPBuilder, VD);
8987 CombinedInfo.append(UnionCurInfo);
8990 CombinedInfo.append(UseDeviceDataCombinedInfo);
8994 MappableExprsHandler(
const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
8995 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {
8997 for (
const auto *
C : Dir.getClausesOfKind<OMPFirstprivateClause>())
8998 for (
const auto *D :
C->varlist())
8999 FirstPrivateDecls.try_emplace(
9002 for (
const auto *
C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) {
9003 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
9004 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
9005 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits))
9006 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()),
9008 else if (const auto *VD = dyn_cast<VarDecl>(
9009 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts())
9011 FirstPrivateDecls.try_emplace(VD, true);
9015 for (
const auto *
C : Dir.getClausesOfKind<OMPDefaultmapClause>())
9016 if (
C->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_firstprivate)
9017 DefaultmapFirstprivateKinds.insert(
C->getDefaultmapKind());
9019 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9020 for (
auto L :
C->component_lists())
9021 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L));
9023 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9024 for (
auto L :
C->component_lists())
9025 HasDevAddrsMap[std::get<0>(L)].push_back(std::get<1>(L));
9027 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>()) {
9028 if (C->getMapType() != OMPC_MAP_to)
9030 for (auto L : C->component_lists()) {
9031 const ValueDecl *VD = std::get<0>(L);
9032 const auto *RD = VD ? VD->getType()
9034 .getNonReferenceType()
9035 ->getAsCXXRecordDecl()
9037 if (RD && RD->isLambda())
9038 LambdasMap.try_emplace(std::get<0>(L), C);
9044 MappableExprsHandler(
const OMPDeclareMapperDecl &Dir,
CodeGenFunction &CGF)
9045 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {}
9050 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo,
9051 MapFlagsArrayTy &CurTypes,
9052 const StructRangeInfoTy &PartialStruct,
bool IsMapThis,
9053 llvm::OpenMPIRBuilder &OMPBuilder,
9054 const ValueDecl *VD =
nullptr,
9055 unsigned OffsetForMemberOfFlag = 0,
9056 bool NotTargetParams =
true)
const {
9057 if (CurTypes.size() == 1 &&
9058 ((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
9059 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) &&
9060 !PartialStruct.IsArraySection)
9062 Address LBAddr = PartialStruct.LowestElem.second;
9063 Address HBAddr = PartialStruct.HighestElem.second;
9064 if (PartialStruct.HasCompleteRecord) {
9065 LBAddr = PartialStruct.LB;
9066 HBAddr = PartialStruct.LB;
9068 CombinedInfo.Exprs.push_back(VD);
9070 CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9071 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9072 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9075 const CXXMethodDecl *MD =
9077 const CXXRecordDecl *RD = MD ? MD->
getParent() :
nullptr;
9078 bool HasBaseClass = RD && IsMapThis ? RD->
getNumBases() > 0 :
false;
9088 CombinedInfo.Pointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9093 CombinedInfo.Sizes.push_back(Size);
9095 CombinedInfo.Pointers.push_back(LB);
9098 llvm::Value *HAddr = CGF.
Builder.CreateConstGEP1_32(
9102 llvm::Value *Diff = CGF.
Builder.CreatePtrDiff(CGF.
Int8Ty, CHAddr, CLAddr);
9105 CombinedInfo.Sizes.push_back(Size);
9107 CombinedInfo.Mappers.push_back(
nullptr);
9109 CombinedInfo.Types.push_back(
9110 NotTargetParams ? OpenMPOffloadMappingFlags::OMP_MAP_NONE
9111 : !PartialStruct.PreliminaryMapData.BasePointers.empty()
9112 ? OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ
9113 : OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9116 if (CurTypes.end() !=
9117 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9118 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9119 Type & OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
9121 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
9123 (*CurTypes.begin()) &= ~OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
9130 if (CurTypes.end() !=
9131 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9132 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9133 Type & OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD);
9135 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9136 for (
auto &M : CurTypes)
9137 M |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9143 OpenMPOffloadMappingFlags MemberOfFlag = OMPBuilder.getMemberOfFlag(
9144 OffsetForMemberOfFlag + CombinedInfo.BasePointers.size() - 1);
9145 for (
auto &M : CurTypes)
9146 OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
9154 void generateAllInfo(
9155 MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9156 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
9157 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
9159 "Expect a executable directive");
9161 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, OMPBuilder,
9168 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo,
9169 llvm::OpenMPIRBuilder &OMPBuilder)
const {
9171 "Expect a declare mapper directive");
9173 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo,
9178 void generateInfoForLambdaCaptures(
9179 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
9180 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers)
const {
9188 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
9189 FieldDecl *ThisCapture =
nullptr;
9195 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF),
9196 VDLVal.getPointer(CGF));
9197 CombinedInfo.Exprs.push_back(VD);
9198 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF));
9199 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9200 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9201 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF));
9202 CombinedInfo.Sizes.push_back(
9205 CombinedInfo.Types.push_back(
9206 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9207 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9208 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9209 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9210 CombinedInfo.Mappers.push_back(
nullptr);
9212 for (
const LambdaCapture &LC : RD->
captures()) {
9213 if (!LC.capturesVariable())
9218 auto It = Captures.find(VD);
9219 assert(It != Captures.end() &&
"Found lambda capture without field.");
9223 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9224 VDLVal.getPointer(CGF));
9225 CombinedInfo.Exprs.push_back(VD);
9226 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9227 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9228 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9229 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF));
9230 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9236 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9237 VDLVal.getPointer(CGF));
9238 CombinedInfo.Exprs.push_back(VD);
9239 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9240 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9241 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9242 CombinedInfo.Pointers.push_back(VarRVal.
getScalarVal());
9243 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 0));
9245 CombinedInfo.Types.push_back(
9246 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9247 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9248 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9249 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9250 CombinedInfo.Mappers.push_back(
nullptr);
9255 void adjustMemberOfForLambdaCaptures(
9256 llvm::OpenMPIRBuilder &OMPBuilder,
9257 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
9258 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
9259 MapFlagsArrayTy &Types)
const {
9260 for (
unsigned I = 0, E = Types.size(); I < E; ++I) {
9262 if (Types[I] != (OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9263 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9264 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9265 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))
9267 llvm::Value *BasePtr = LambdaPointers.lookup(BasePointers[I]);
9268 assert(BasePtr &&
"Unable to find base lambda address.");
9270 for (
unsigned J = I; J > 0; --J) {
9271 unsigned Idx = J - 1;
9272 if (Pointers[Idx] != BasePtr)
9277 assert(TgtIdx != -1 &&
"Unable to find parent lambda.");
9281 OpenMPOffloadMappingFlags MemberOfFlag =
9282 OMPBuilder.getMemberOfFlag(TgtIdx);
9283 OMPBuilder.setCorrectMemberOfFlag(Types[I], MemberOfFlag);
9290 void generateInfoForCaptureFromClauseInfo(
9291 const CapturedStmt::Capture *Cap, llvm::Value *Arg,
9292 MapCombinedInfoTy &CurCaptureVarInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9293 unsigned OffsetForMemberOfFlag)
const {
9295 "Not expecting to generate map info for a variable array type!");
9304 if (LambdasMap.count(VD))
9310 if (VD && (DevPointersMap.count(VD) || HasDevAddrsMap.count(VD))) {
9311 CurCaptureVarInfo.Exprs.push_back(VD);
9312 CurCaptureVarInfo.BasePointers.emplace_back(Arg);
9313 CurCaptureVarInfo.DevicePtrDecls.emplace_back(VD);
9314 CurCaptureVarInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
9315 CurCaptureVarInfo.Pointers.push_back(Arg);
9316 CurCaptureVarInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9319 CurCaptureVarInfo.Types.push_back(
9320 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9321 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9322 CurCaptureVarInfo.Mappers.push_back(
nullptr);
9326 MapDataArrayTy DeclComponentLists;
9330 auto It = DevPointersMap.find(VD);
9331 if (It != DevPointersMap.end())
9332 for (
const auto &MCL : It->second)
9333 DeclComponentLists.emplace_back(MCL, OMPC_MAP_to,
Unknown,
9336 auto I = HasDevAddrsMap.find(VD);
9337 if (I != HasDevAddrsMap.end())
9338 for (
const auto &MCL : I->second)
9339 DeclComponentLists.emplace_back(MCL, OMPC_MAP_tofrom,
Unknown,
9343 "Expect a executable directive");
9345 bool HasMapBasePtr =
false;
9346 bool HasMapArraySec =
false;
9347 for (
const auto *
C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
9348 const auto *EI =
C->getVarRefs().begin();
9349 for (
const auto L :
C->decl_component_lists(VD)) {
9350 const ValueDecl *VDecl, *Mapper;
9352 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
9354 std::tie(VDecl, Components, Mapper) = L;
9355 assert(VDecl == VD &&
"We got information for the wrong declaration??");
9356 assert(!Components.empty() &&
9357 "Not expecting declaration with no component lists.");
9359 HasMapBasePtr =
true;
9362 HasMapArraySec =
true;
9363 DeclComponentLists.emplace_back(Components,
C->getMapType(),
9364 C->getMapTypeModifiers(),
9365 C->isImplicit(), Mapper, E);
9369 llvm::stable_sort(DeclComponentLists, [](
const MapData &LHS,
9370 const MapData &RHS) {
9371 ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS);
9374 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9375 bool HasAllocs = MapType == OMPC_MAP_alloc;
9376 MapModifiers = std::get<2>(RHS);
9377 MapType = std::get<1>(LHS);
9379 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9380 bool HasAllocsR = MapType == OMPC_MAP_alloc;
9381 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
9384 auto GenerateInfoForComponentLists =
9385 [&](ArrayRef<MapData> DeclComponentLists,
9386 bool IsEligibleForTargetParamFlag) {
9387 MapCombinedInfoTy CurInfoForComponentLists;
9388 StructRangeInfoTy PartialStruct;
9390 if (DeclComponentLists.empty())
9393 generateInfoForCaptureFromComponentLists(
9394 VD, DeclComponentLists, CurInfoForComponentLists, PartialStruct,
9395 IsEligibleForTargetParamFlag,
9396 HasMapBasePtr && HasMapArraySec);
9401 if (PartialStruct.Base.isValid()) {
9402 CurCaptureVarInfo.append(PartialStruct.PreliminaryMapData);
9404 CurCaptureVarInfo, CurInfoForComponentLists.Types,
9405 PartialStruct, Cap->
capturesThis(), OMPBuilder,
nullptr,
9406 OffsetForMemberOfFlag,
9407 !IsEligibleForTargetParamFlag);
9411 if (CurInfoForComponentLists.BasePointers.empty())
9414 CurCaptureVarInfo.append(CurInfoForComponentLists);
9417 GenerateInfoForComponentLists(DeclComponentLists,
9424 void generateInfoForCaptureFromComponentLists(
9425 const ValueDecl *VD, ArrayRef<MapData> DeclComponentLists,
9426 MapCombinedInfoTy &CurComponentListInfo, StructRangeInfoTy &PartialStruct,
9427 bool IsListEligibleForTargetParamFlag,
9428 bool AreBothBasePtrAndPteeMapped =
false)
const {
9430 llvm::SmallDenseMap<
9437 for (
const MapData &L : DeclComponentLists) {
9440 ArrayRef<OpenMPMapModifierKind> MapModifiers;
9442 const ValueDecl *Mapper;
9444 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
9447 for (
const MapData &L1 : ArrayRef(DeclComponentLists).slice(Count)) {
9449 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper,
9451 auto CI = Components.rbegin();
9452 auto CE = Components.rend();
9453 auto SI = Components1.rbegin();
9454 auto SE = Components1.rend();
9455 for (; CI != CE && SI != SE; ++CI, ++SI) {
9456 if (CI->getAssociatedExpression()->getStmtClass() !=
9457 SI->getAssociatedExpression()->getStmtClass())
9460 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
9465 if (CI == CE || SI == SE) {
9467 if (CI == CE && SI == SE)
9469 const auto It = (SI == SE) ? CI : SI;
9476 (std::prev(It)->getAssociatedDeclaration() &&
9478 ->getAssociatedDeclaration()
9480 ->isPointerType()) ||
9481 (It->getAssociatedDeclaration() &&
9482 It->getAssociatedDeclaration()->getType()->isPointerType() &&
9483 std::next(It) != CE && std::next(It) != SE))
9485 const MapData &BaseData = CI == CE ? L : L1;
9487 SI == SE ? Components : Components1;
9488 OverlappedData[&BaseData].push_back(SubData);
9493 llvm::SmallVector<const FieldDecl *, 4> Layout;
9494 if (!OverlappedData.empty()) {
9497 while (BaseType != OrigType) {
9503 getPlainLayout(CRD, Layout,
false);
9509 for (
auto &Pair : OverlappedData) {
9516 auto CI = First.rbegin();
9517 auto CE = First.rend();
9518 auto SI = Second.rbegin();
9519 auto SE = Second.rend();
9520 for (; CI != CE && SI != SE; ++CI, ++SI) {
9521 if (CI->getAssociatedExpression()->getStmtClass() !=
9522 SI->getAssociatedExpression()->getStmtClass())
9525 if (CI->getAssociatedDeclaration() !=
9526 SI->getAssociatedDeclaration())
9531 if (CI == CE && SI == SE)
9535 if (CI == CE || SI == SE)
9540 if (FD1->getParent() == FD2->getParent())
9541 return FD1->getFieldIndex() < FD2->getFieldIndex();
9543 llvm::find_if(Layout, [FD1, FD2](
const FieldDecl *FD) {
9544 return FD == FD1 || FD == FD2;
9552 bool AddTargetParamFlag = IsListEligibleForTargetParamFlag;
9553 MapCombinedInfoTy StructBaseCombinedInfo;
9554 for (
const auto &Pair : OverlappedData) {
9555 const MapData &L = *Pair.getFirst();
9558 ArrayRef<OpenMPMapModifierKind> MapModifiers;
9560 const ValueDecl *Mapper;
9562 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
9564 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
9565 OverlappedComponents = Pair.getSecond();
9566 generateInfoForComponentList(
9567 MapType, MapModifiers, {}, Components, CurComponentListInfo,
9568 StructBaseCombinedInfo, PartialStruct, AddTargetParamFlag, IsImplicit,
9570 false, VD, VarRef, OverlappedComponents);
9571 AddTargetParamFlag =
false;
9574 for (
const MapData &L : DeclComponentLists) {
9577 ArrayRef<OpenMPMapModifierKind> MapModifiers;
9579 const ValueDecl *Mapper;
9581 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
9583 auto It = OverlappedData.find(&L);
9584 if (It == OverlappedData.end())
9585 generateInfoForComponentList(
9586 MapType, MapModifiers, {}, Components, CurComponentListInfo,
9587 StructBaseCombinedInfo, PartialStruct, AddTargetParamFlag,
9588 IsImplicit,
false, Mapper,
9590 {}, AreBothBasePtrAndPteeMapped);
9591 AddTargetParamFlag =
false;
9597 bool isEffectivelyFirstprivate(
const VarDecl *VD, QualType
Type)
const {
9599 auto I = FirstPrivateDecls.find(VD);
9600 if (I != FirstPrivateDecls.end() && !I->getSecond())
9604 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_scalar)) {
9605 if (
Type->isScalarType())
9610 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_pointer)) {
9611 if (
Type->isAnyPointerType())
9616 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_aggregate)) {
9617 if (
Type->isAggregateType())
9622 return DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_all);
9627 void generateDefaultMapInfo(
const CapturedStmt::Capture &CI,
9628 const FieldDecl &RI, llvm::Value *CV,
9629 MapCombinedInfoTy &CombinedInfo)
const {
9630 bool IsImplicit =
true;
9633 CombinedInfo.Exprs.push_back(
nullptr);
9634 CombinedInfo.BasePointers.push_back(CV);
9635 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9636 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9637 CombinedInfo.Pointers.push_back(CV);
9639 CombinedInfo.Sizes.push_back(
9643 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TO |
9644 OpenMPOffloadMappingFlags::OMP_MAP_FROM);
9648 CombinedInfo.BasePointers.push_back(CV);
9649 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9650 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9651 CombinedInfo.Pointers.push_back(CV);
9652 bool IsFirstprivate =
9658 CombinedInfo.Types.push_back(
9659 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
9660 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9662 }
else if (IsFirstprivate) {
9665 CombinedInfo.Types.push_back(
9666 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
9668 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
9672 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_NONE);
9673 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
9675 auto I = FirstPrivateDecls.find(VD);
9676 if (I != FirstPrivateDecls.end())
9677 IsImplicit = I->getSecond();
9683 bool IsFirstprivate = isEffectivelyFirstprivate(VD, ElementType);
9685 CombinedInfo.BasePointers.push_back(CV);
9686 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9687 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9692 CombinedInfo.Pointers.push_back(CV);
9694 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
9695 CombinedInfo.Types.push_back(
9696 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
9698 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9703 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
9704 CombinedInfo.Pointers.push_back(CV);
9706 auto I = FirstPrivateDecls.find(VD);
9707 if (I != FirstPrivateDecls.end())
9708 IsImplicit = I->getSecond();
9711 CombinedInfo.Types.back() |=
9712 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
9716 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
9719 CombinedInfo.Mappers.push_back(
nullptr);
9731 dyn_cast<MemberExpr>(OASE->getBase()->IgnoreParenImpCasts()))
9732 return ME->getMemberDecl();
9738static llvm::Constant *
9740 MappableExprsHandler::MappingExprInfo &MapExprs) {
9742 uint32_t SrcLocStrSize;
9743 if (!MapExprs.getMapDecl() && !MapExprs.getMapExpr())
9744 return OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
9747 if (!MapExprs.getMapDecl() && MapExprs.getMapExpr()) {
9751 Loc = MapExprs.getMapExpr()->getExprLoc();
9753 Loc = MapExprs.getMapDecl()->getLocation();
9756 std::string ExprName;
9757 if (MapExprs.getMapExpr()) {
9759 llvm::raw_string_ostream OS(ExprName);
9760 MapExprs.getMapExpr()->printPretty(OS,
nullptr, P);
9762 ExprName = MapExprs.getMapDecl()->getNameAsString();
9771 return OMPBuilder.getOrCreateSrcLocStr(
FileName, ExprName, PLoc.
getLine(),
9778 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
9780 bool IsNonContiguous =
false,
bool ForEndCall =
false) {
9783 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
9786 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
9787 CGF.
Builder.GetInsertPoint());
9789 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
9790 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
9795 auto CustomMapperCB = [&](
unsigned int I) {
9796 llvm::Function *MFunc =
nullptr;
9797 if (CombinedInfo.Mappers[I]) {
9798 Info.HasMapper =
true;
9804 cantFail(OMPBuilder.emitOffloadingArraysAndArgs(
9805 AllocaIP, CodeGenIP, Info, Info.RTArgs, CombinedInfo, CustomMapperCB,
9806 IsNonContiguous, ForEndCall, DeviceAddrCB));
9810static const OMPExecutableDirective *
9812 const auto *CS = D.getInnermostCapturedStmt();
9815 const Stmt *ChildStmt =
9818 if (
const auto *NestedDir =
9819 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
9821 switch (D.getDirectiveKind()) {
9827 if (DKind == OMPD_teams) {
9828 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
9833 if (
const auto *NND =
9834 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
9835 DKind = NND->getDirectiveKind();
9841 case OMPD_target_teams:
9845 case OMPD_target_parallel:
9846 case OMPD_target_simd:
9847 case OMPD_target_parallel_for:
9848 case OMPD_target_parallel_for_simd:
9850 case OMPD_target_teams_distribute:
9851 case OMPD_target_teams_distribute_simd:
9852 case OMPD_target_teams_distribute_parallel_for:
9853 case OMPD_target_teams_distribute_parallel_for_simd:
9856 case OMPD_parallel_for:
9857 case OMPD_parallel_master:
9858 case OMPD_parallel_sections:
9860 case OMPD_parallel_for_simd:
9862 case OMPD_cancellation_point:
9864 case OMPD_threadprivate:
9875 case OMPD_taskyield:
9878 case OMPD_taskgroup:
9884 case OMPD_target_data:
9885 case OMPD_target_exit_data:
9886 case OMPD_target_enter_data:
9887 case OMPD_distribute:
9888 case OMPD_distribute_simd:
9889 case OMPD_distribute_parallel_for:
9890 case OMPD_distribute_parallel_for_simd:
9891 case OMPD_teams_distribute:
9892 case OMPD_teams_distribute_simd:
9893 case OMPD_teams_distribute_parallel_for:
9894 case OMPD_teams_distribute_parallel_for_simd:
9895 case OMPD_target_update:
9896 case OMPD_declare_simd:
9897 case OMPD_declare_variant:
9898 case OMPD_begin_declare_variant:
9899 case OMPD_end_declare_variant:
9900 case OMPD_declare_target:
9901 case OMPD_end_declare_target:
9902 case OMPD_declare_reduction:
9903 case OMPD_declare_mapper:
9905 case OMPD_taskloop_simd:
9906 case OMPD_master_taskloop:
9907 case OMPD_master_taskloop_simd:
9908 case OMPD_parallel_master_taskloop:
9909 case OMPD_parallel_master_taskloop_simd:
9911 case OMPD_metadirective:
9914 llvm_unreachable(
"Unexpected directive.");
9959 auto *MapperVarDecl =
9961 CharUnits ElementSize =
C.getTypeSizeInChars(Ty);
9962 llvm::Type *ElemTy =
CGM.getTypes().ConvertTypeForMem(Ty);
9965 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
9966 auto PrivatizeAndGenMapInfoCB =
9967 [&](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP, llvm::Value *PtrPHI,
9968 llvm::Value *BeginArg) -> llvm::OpenMPIRBuilder::MapInfosTy & {
9969 MapperCGF.
Builder.restoreIP(CodeGenIP);
9979 Scope.addPrivate(MapperVarDecl, PtrCurrent);
9980 (void)
Scope.Privatize();
9983 MappableExprsHandler MEHandler(*D, MapperCGF);
9984 MEHandler.generateAllInfoForMapper(CombinedInfo,
OMPBuilder);
9986 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
9989 if (
CGM.getCodeGenOpts().getDebugInfo() !=
9990 llvm::codegenoptions::NoDebugInfo) {
9991 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
9992 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
9996 return CombinedInfo;
9999 auto CustomMapperCB = [&](
unsigned I) {
10000 llvm::Function *MapperFunc =
nullptr;
10001 if (CombinedInfo.Mappers[I]) {
10005 assert(MapperFunc &&
"Expect a valid mapper function is available.");
10011 llvm::raw_svector_ostream Out(TyStr);
10012 CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out);
10013 std::string Name =
getName({
"omp_mapper", TyStr, D->
getName()});
10015 llvm::Function *NewFn = cantFail(
OMPBuilder.emitUserDefinedMapper(
10016 PrivatizeAndGenMapInfoCB, ElemTy, Name, CustomMapperCB));
10017 UDMMap.try_emplace(D, NewFn);
10024 auto I =
UDMMap.find(D);
10028 return UDMMap.lookup(D);
10041 Kind != OMPD_target_teams_loop)
10044 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10047 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD))
10048 return NumIterations;
10049 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10058 if (OffloadingMandatory) {
10059 CGF.
Builder.CreateUnreachable();
10061 if (RequiresOuterTask) {
10062 CapturedVars.clear();
10071 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10074 llvm::Value *DeviceID;
10075 if (
Device.getPointer()) {
10077 Device.getInt() == OMPC_DEVICE_device_num) &&
10078 "Expected device_num modifier.");
10083 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
10088static std::pair<llvm::Value *, OMPDynGroupprivateFallbackType>
10090 llvm::Value *DynGP = CGF.
Builder.getInt32(0);
10091 auto DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10095 llvm::Value *DynGPVal =
10099 auto FallbackModifier = DynGPClause->getDynGroupprivateFallbackModifier();
10100 switch (FallbackModifier) {
10101 case OMPC_DYN_GROUPPRIVATE_FALLBACK_abort:
10102 DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10104 case OMPC_DYN_GROUPPRIVATE_FALLBACK_null:
10105 DynGPFallback = OMPDynGroupprivateFallbackType::Null;
10107 case OMPC_DYN_GROUPPRIVATE_FALLBACK_default_mem:
10110 DynGPFallback = OMPDynGroupprivateFallbackType::DefaultMem;
10113 llvm_unreachable(
"Unknown fallback modifier for OpenMP dyn_groupprivate");
10115 }
else if (
auto *OMPXDynCGClause =
10118 llvm::Value *DynCGMemVal = CGF.
EmitScalarExpr(OMPXDynCGClause->getSize(),
10123 return {DynGP, DynGPFallback};
10129 llvm::OpenMPIRBuilder &OMPBuilder,
10131 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10133 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
10135 auto *CV = CapturedVars.begin();
10138 CI != CE; ++CI, ++RI, ++CV) {
10139 MappableExprsHandler::MapCombinedInfoTy CurInfo;
10144 CurInfo.Exprs.push_back(
nullptr);
10145 CurInfo.BasePointers.push_back(*CV);
10146 CurInfo.DevicePtrDecls.push_back(
nullptr);
10147 CurInfo.DevicePointers.push_back(
10148 MappableExprsHandler::DeviceInfoTy::None);
10149 CurInfo.Pointers.push_back(*CV);
10150 CurInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10153 CurInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
10154 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
10155 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
10156 CurInfo.Mappers.push_back(
nullptr);
10160 MEHandler.generateInfoForCaptureFromClauseInfo(
10161 CI, *CV, CurInfo, OMPBuilder,
10162 CombinedInfo.BasePointers.size());
10167 MappedVarSet.insert(
nullptr);
10169 if (CurInfo.BasePointers.empty())
10170 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
10175 MEHandler.generateInfoForLambdaCaptures(CI->
getCapturedVar(), *CV,
10176 CurInfo, LambdaPointers);
10179 assert(!CurInfo.BasePointers.empty() &&
10180 "Non-existing map pointer for capture!");
10181 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
10182 CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
10183 CurInfo.BasePointers.size() == CurInfo.Types.size() &&
10184 CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
10185 "Inconsistent map information sizes!");
10188 CombinedInfo.append(CurInfo);
10191 MEHandler.adjustMemberOfForLambdaCaptures(
10192 OMPBuilder, LambdaPointers, CombinedInfo.BasePointers,
10193 CombinedInfo.Pointers, CombinedInfo.Types);
10197 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10198 llvm::OpenMPIRBuilder &OMPBuilder,
10205 MEHandler.generateAllInfo(CombinedInfo, OMPBuilder, SkippedVarSet);
10207 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10211 llvm::codegenoptions::NoDebugInfo) {
10212 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10213 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10221 llvm::OpenMPIRBuilder &OMPBuilder,
10222 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10224 MappableExprsHandler MEHandler(D, CGF);
10225 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet;
10228 MappedVarSet, CombinedInfo);
10229 genMapInfo(MEHandler, CGF, CombinedInfo, OMPBuilder, MappedVarSet);
10232template <
typename ClauseTy>
10237 const auto *
C = D.getSingleClause<ClauseTy>();
10238 assert(!
C->varlist_empty() &&
10239 "ompx_bare requires explicit num_teams and thread_limit");
10241 for (
auto *E :
C->varlist()) {
10253 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10255 llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray,
10260 llvm::OpenMPIRBuilder &OMPBuilder = OMPRuntime->
getOMPBuilder();
10263 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10265 genMapInfo(D, CGF, CS, CapturedVars, OMPBuilder, CombinedInfo);
10279 MapTypesArray = Info.RTArgs.MapTypesArray;
10280 MapNamesArray = Info.RTArgs.MapNamesArray;
10282 auto &&ThenGen = [&OMPRuntime, OutlinedFn, &D, &CapturedVars,
10283 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
10284 OutlinedFnID, &InputInfo, &MapTypesArray, &MapNamesArray,
10286 bool IsReverseOffloading =
Device.getInt() == OMPC_DEVICE_ancestor;
10288 if (IsReverseOffloading) {
10294 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10299 unsigned NumTargetItems = InputInfo.NumberOfTargetItems;
10301 llvm::Value *BasePointersArray =
10302 InputInfo.BasePointersArray.emitRawPointer(CGF);
10303 llvm::Value *PointersArray = InputInfo.PointersArray.emitRawPointer(CGF);
10304 llvm::Value *SizesArray = InputInfo.SizesArray.emitRawPointer(CGF);
10305 llvm::Value *MappersArray = InputInfo.MappersArray.emitRawPointer(CGF);
10307 auto &&EmitTargetCallFallbackCB =
10308 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
10309 OffloadingMandatory, &CGF](llvm::OpenMPIRBuilder::InsertPointTy IP)
10310 -> llvm::OpenMPIRBuilder::InsertPointTy {
10313 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10326 NumThreads.push_back(
10332 llvm::Value *NumIterations =
10335 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
10338 llvm::OpenMPIRBuilder::TargetDataRTArgs RTArgs(
10339 BasePointersArray, PointersArray, SizesArray, MapTypesArray,
10340 nullptr , MappersArray, MapNamesArray);
10342 llvm::OpenMPIRBuilder::TargetKernelArgs Args(
10343 NumTargetItems, RTArgs, NumIterations, NumTeams, NumThreads,
10344 DynCGroupMem, HasNoWait, DynCGroupMemFallback);
10346 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
10348 CGF.
Builder, OutlinedFnID, EmitTargetCallFallbackCB, Args, DeviceID,
10350 CGF.
Builder.restoreIP(AfterIP);
10353 if (RequiresOuterTask)
10368 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
10371 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10374 if (RequiresOuterTask) {
10384 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
10385 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10392 const bool OffloadingMandatory = !
CGM.getLangOpts().OpenMPIsTargetDevice &&
10393 CGM.getLangOpts().OpenMPOffloadMandatory;
10395 assert((OffloadingMandatory || OutlinedFn) &&
"Invalid outlined function!");
10397 const bool RequiresOuterTask =
10401 (
CGM.getLangOpts().OpenMP >= 51 &&
10405 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
10413 llvm::Value *MapTypesArray =
nullptr;
10414 llvm::Value *MapNamesArray =
nullptr;
10416 auto &&TargetThenGen = [
this, OutlinedFn, &D, &CapturedVars,
10417 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
10418 OutlinedFnID, &InputInfo, &MapTypesArray,
10422 RequiresOuterTask, CS, OffloadingMandatory,
10423 Device, OutlinedFnID, InputInfo, MapTypesArray,
10424 MapNamesArray, SizeEmitter, CGF,
CGM);
10427 auto &&TargetElseGen =
10428 [
this, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
10431 CS, OffloadingMandatory, CGF);
10438 if (OutlinedFnID) {
10440 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
10452 StringRef ParentName) {
10457 bool RequiresDeviceCodegen =
10462 if (RequiresDeviceCodegen) {
10470 if (!
OMPBuilder.OffloadInfoManager.hasTargetRegionEntryInfo(EntryInfo))
10473 switch (E.getDirectiveKind()) {
10478 case OMPD_target_parallel:
10482 case OMPD_target_teams:
10486 case OMPD_target_teams_distribute:
10490 case OMPD_target_teams_distribute_simd:
10494 case OMPD_target_parallel_for:
10498 case OMPD_target_parallel_for_simd:
10502 case OMPD_target_simd:
10506 case OMPD_target_teams_distribute_parallel_for:
10511 case OMPD_target_teams_distribute_parallel_for_simd:
10517 case OMPD_target_teams_loop:
10521 case OMPD_target_parallel_loop:
10525 case OMPD_parallel:
10527 case OMPD_parallel_for:
10528 case OMPD_parallel_master:
10529 case OMPD_parallel_sections:
10530 case OMPD_for_simd:
10531 case OMPD_parallel_for_simd:
10533 case OMPD_cancellation_point:
10535 case OMPD_threadprivate:
10536 case OMPD_allocate:
10541 case OMPD_sections:
10545 case OMPD_critical:
10546 case OMPD_taskyield:
10548 case OMPD_taskwait:
10549 case OMPD_taskgroup:
10555 case OMPD_target_data:
10556 case OMPD_target_exit_data:
10557 case OMPD_target_enter_data:
10558 case OMPD_distribute:
10559 case OMPD_distribute_simd:
10560 case OMPD_distribute_parallel_for:
10561 case OMPD_distribute_parallel_for_simd:
10562 case OMPD_teams_distribute:
10563 case OMPD_teams_distribute_simd:
10564 case OMPD_teams_distribute_parallel_for:
10565 case OMPD_teams_distribute_parallel_for_simd:
10566 case OMPD_target_update:
10567 case OMPD_declare_simd:
10568 case OMPD_declare_variant:
10569 case OMPD_begin_declare_variant:
10570 case OMPD_end_declare_variant:
10571 case OMPD_declare_target:
10572 case OMPD_end_declare_target:
10573 case OMPD_declare_reduction:
10574 case OMPD_declare_mapper:
10575 case OMPD_taskloop:
10576 case OMPD_taskloop_simd:
10577 case OMPD_master_taskloop:
10578 case OMPD_master_taskloop_simd:
10579 case OMPD_parallel_master_taskloop:
10580 case OMPD_parallel_master_taskloop_simd:
10581 case OMPD_requires:
10582 case OMPD_metadirective:
10585 llvm_unreachable(
"Unknown target directive for OpenMP device codegen.");
10590 if (
const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
10591 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
10599 if (
const auto *L = dyn_cast<LambdaExpr>(S))
10608 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
10609 OMPDeclareTargetDeclAttr::getDeviceType(VD);
10613 if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
10616 if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host)
10624 if (!
CGM.getLangOpts().OpenMPIsTargetDevice) {
10625 if (
const auto *FD = dyn_cast<FunctionDecl>(GD.
getDecl()))
10627 CGM.getLangOpts().OpenMPIsTargetDevice))
10634 if (
const auto *FD = dyn_cast<FunctionDecl>(VD)) {
10635 StringRef Name =
CGM.getMangledName(GD);
10638 CGM.getLangOpts().OpenMPIsTargetDevice))
10643 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
10649 CGM.getLangOpts().OpenMPIsTargetDevice))
10652 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
10661 StringRef ParentName =
10666 StringRef ParentName =
10673 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
10674 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
10676 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
10677 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
10678 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
10687 llvm::Constant *
Addr) {
10688 if (
CGM.getLangOpts().OMPTargetTriples.empty() &&
10689 !
CGM.getLangOpts().OpenMPIsTargetDevice)
10692 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
10693 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
10697 if (Res && *Res != OMPDeclareTargetDeclAttr::MT_Link &&
10702 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
10705 StringRef VarName =
CGM.getMangledName(VD);
10711 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
10712 auto LinkageForVariable = [&VD,
this]() {
10713 return CGM.getLLVMLinkageVarDefinition(VD);
10716 std::vector<llvm::GlobalVariable *> GeneratedRefs;
10723 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
10724 CGM.getLangOpts().OMPTargetTriples, AddrOfGlobal, LinkageForVariable,
10725 CGM.getTypes().ConvertTypeForMem(
10726 CGM.getContext().getPointerType(VD->
getType())),
10729 for (
auto *ref : GeneratedRefs)
10730 CGM.addCompilerUsedGlobal(ref);
10743 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
10744 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
10747 if ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
10748 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
10750 CGM.EmitGlobal(VD);
10752 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
10753 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
10754 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
10756 "Expected link clause or to clause with unified memory.");
10757 (void)
CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
10765 " Expected target-based directive.");
10770 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
10772 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
10773 }
else if (
const auto *AC =
10774 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
10775 switch (AC->getAtomicDefaultMemOrderKind()) {
10776 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
10779 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
10782 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
10798 if (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())
10800 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
10801 switch(A->getAllocatorType()) {
10802 case OMPAllocateDeclAttr::OMPNullMemAlloc:
10803 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
10805 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
10806 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
10807 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
10808 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
10809 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
10810 case OMPAllocateDeclAttr::OMPConstMemAlloc:
10811 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
10814 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
10815 llvm_unreachable(
"Expected predefined allocator for the variables with the "
10816 "static storage.");
10828 if (CGM.getLangOpts().OpenMPIsTargetDevice) {
10829 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
10830 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
10835 if (CGM.getLangOpts().OpenMPIsTargetDevice)
10836 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
10846 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
10848 if (
auto *F = dyn_cast_or_null<llvm::Function>(
10849 CGM.GetGlobalValue(
CGM.getMangledName(GD))))
10850 return !F->isDeclaration();
10862 llvm::Function *OutlinedFn,
10871 llvm::Value *Args[] = {
10873 CGF.
Builder.getInt32(CapturedVars.size()),
10876 RealArgs.append(std::begin(Args), std::end(Args));
10877 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
10879 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
10880 CGM.getModule(), OMPRTL___kmpc_fork_teams);
10885 const Expr *NumTeams,
10886 const Expr *ThreadLimit,
10893 llvm::Value *NumTeamsVal =
10899 llvm::Value *ThreadLimitVal =
10906 llvm::Value *PushNumTeamsArgs[] = {RTLoc,
getThreadID(CGF, Loc), NumTeamsVal,
10909 CGM.getModule(), OMPRTL___kmpc_push_num_teams),
10914 const Expr *ThreadLimit,
10917 llvm::Value *ThreadLimitVal =
10924 llvm::Value *ThreadLimitArgs[] = {RTLoc,
getThreadID(CGF, Loc),
10927 CGM.getModule(), OMPRTL___kmpc_set_thread_limit),
10942 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
10944 llvm::Value *IfCondVal =
nullptr;
10949 llvm::Value *DeviceID =
nullptr;
10954 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
10958 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10959 auto GenMapInfoCB =
10960 [&](InsertPointTy CodeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & {
10961 CGF.
Builder.restoreIP(CodeGenIP);
10963 MappableExprsHandler MEHandler(D, CGF);
10964 MEHandler.generateAllInfo(CombinedInfo,
OMPBuilder);
10966 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10969 if (
CGM.getCodeGenOpts().getDebugInfo() !=
10970 llvm::codegenoptions::NoDebugInfo) {
10971 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10972 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10976 return CombinedInfo;
10978 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
10979 auto BodyCB = [&](InsertPointTy CodeGenIP, BodyGenTy BodyGenType) {
10980 CGF.
Builder.restoreIP(CodeGenIP);
10981 switch (BodyGenType) {
10982 case BodyGenTy::Priv:
10986 case BodyGenTy::DupNoPriv:
10988 CodeGen.setAction(NoPrivAction);
10992 case BodyGenTy::NoPriv:
10994 CodeGen.setAction(NoPrivAction);
10999 return InsertPointTy(CGF.
Builder.GetInsertBlock(),
11000 CGF.
Builder.GetInsertPoint());
11003 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
11004 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
11009 auto CustomMapperCB = [&](
unsigned int I) {
11010 llvm::Function *MFunc =
nullptr;
11011 if (CombinedInfo.Mappers[I]) {
11012 Info.HasMapper =
true;
11024 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
11025 CGF.
Builder.GetInsertPoint());
11026 llvm::OpenMPIRBuilder::LocationDescription OmpLoc(CodeGenIP);
11027 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
11029 OmpLoc, AllocaIP, CodeGenIP, DeviceID, IfCondVal, Info, GenMapInfoCB,
11031 nullptr, BodyCB, DeviceAddrCB, RTLoc));
11032 CGF.
Builder.restoreIP(AfterIP);
11044 "Expecting either target enter, exit data, or update directives.");
11047 llvm::Value *MapTypesArray =
nullptr;
11048 llvm::Value *MapNamesArray =
nullptr;
11050 auto &&ThenGen = [
this, &D,
Device, &InputInfo, &MapTypesArray,
11053 llvm::Value *DeviceID =
nullptr;
11058 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11062 llvm::Constant *PointerNum =
11069 {RTLoc, DeviceID, PointerNum,
11078 RuntimeFunction RTLFn;
11079 switch (D.getDirectiveKind()) {
11080 case OMPD_target_enter_data:
11081 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper
11082 : OMPRTL___tgt_target_data_begin_mapper;
11084 case OMPD_target_exit_data:
11085 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper
11086 : OMPRTL___tgt_target_data_end_mapper;
11088 case OMPD_target_update:
11089 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper
11090 : OMPRTL___tgt_target_data_update_mapper;
11092 case OMPD_parallel:
11094 case OMPD_parallel_for:
11095 case OMPD_parallel_master:
11096 case OMPD_parallel_sections:
11097 case OMPD_for_simd:
11098 case OMPD_parallel_for_simd:
11100 case OMPD_cancellation_point:
11102 case OMPD_threadprivate:
11103 case OMPD_allocate:
11108 case OMPD_sections:
11112 case OMPD_critical:
11113 case OMPD_taskyield:
11115 case OMPD_taskwait:
11116 case OMPD_taskgroup:
11122 case OMPD_target_data:
11123 case OMPD_distribute:
11124 case OMPD_distribute_simd:
11125 case OMPD_distribute_parallel_for:
11126 case OMPD_distribute_parallel_for_simd:
11127 case OMPD_teams_distribute:
11128 case OMPD_teams_distribute_simd:
11129 case OMPD_teams_distribute_parallel_for:
11130 case OMPD_teams_distribute_parallel_for_simd:
11131 case OMPD_declare_simd:
11132 case OMPD_declare_variant:
11133 case OMPD_begin_declare_variant:
11134 case OMPD_end_declare_variant:
11135 case OMPD_declare_target:
11136 case OMPD_end_declare_target:
11137 case OMPD_declare_reduction:
11138 case OMPD_declare_mapper:
11139 case OMPD_taskloop:
11140 case OMPD_taskloop_simd:
11141 case OMPD_master_taskloop:
11142 case OMPD_master_taskloop_simd:
11143 case OMPD_parallel_master_taskloop:
11144 case OMPD_parallel_master_taskloop_simd:
11146 case OMPD_target_simd:
11147 case OMPD_target_teams_distribute:
11148 case OMPD_target_teams_distribute_simd:
11149 case OMPD_target_teams_distribute_parallel_for:
11150 case OMPD_target_teams_distribute_parallel_for_simd:
11151 case OMPD_target_teams:
11152 case OMPD_target_parallel:
11153 case OMPD_target_parallel_for:
11154 case OMPD_target_parallel_for_simd:
11155 case OMPD_requires:
11156 case OMPD_metadirective:
11159 llvm_unreachable(
"Unexpected standalone target data directive.");
11163 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11164 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11165 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11166 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11169 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), RTLFn),
11173 auto &&TargetThenGen = [
this, &ThenGen, &D, &InputInfo, &MapTypesArray,
11177 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11179 MappableExprsHandler MEHandler(D, CGF);
11191 CGM.getPointerAlign());
11196 MapTypesArray = Info.RTArgs.MapTypesArray;
11197 MapNamesArray = Info.RTArgs.MapNamesArray;
11198 if (RequiresOuterTask)
11224struct ParamAttrTy {
11225 ParamKindTy Kind =
Vector;
11226 llvm::APSInt StrideOrArg;
11227 llvm::APSInt Alignment;
11228 bool HasVarStride =
false;
11261 unsigned Offset = 0;
11262 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
11263 if (ParamAttrs[Offset].Kind ==
Vector)
11264 CDT =
C.getPointerType(
C.getCanonicalTagType(MD->
getParent()));
11268 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
11269 if (ParamAttrs[I + Offset].Kind ==
Vector) {
11281 return C.getTypeSize(CDT);
11289 llvm::raw_svector_ostream Out(Buffer);
11290 for (
const auto &ParamAttr : ParamAttrs) {
11291 switch (ParamAttr.Kind) {
11311 if (ParamAttr.HasVarStride)
11312 Out <<
"s" << ParamAttr.StrideOrArg;
11313 else if (ParamAttr.Kind == Linear || ParamAttr.Kind == LinearRef ||
11314 ParamAttr.Kind == LinearUVal || ParamAttr.Kind == LinearVal) {
11317 if (ParamAttr.StrideOrArg < 0)
11318 Out <<
'n' << -ParamAttr.StrideOrArg;
11319 else if (ParamAttr.StrideOrArg != 1)
11320 Out << ParamAttr.StrideOrArg;
11323 if (!!ParamAttr.Alignment)
11324 Out <<
'a' << ParamAttr.Alignment;
11327 return std::string(Out.str());
11332 const llvm::APSInt &VLENVal,
11334 OMPDeclareSimdDeclAttr::BranchStateTy State) {
11337 unsigned VecRegSize;
11339 ISADataTy ISAData[] = {
11355 case OMPDeclareSimdDeclAttr::BS_Undefined:
11356 Masked.push_back(
'N');
11357 Masked.push_back(
'M');
11359 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
11360 Masked.push_back(
'N');
11362 case OMPDeclareSimdDeclAttr::BS_Inbranch:
11363 Masked.push_back(
'M');
11366 for (
char Mask : Masked) {
11367 for (
const ISADataTy &
Data : ISAData) {
11369 llvm::raw_svector_ostream Out(Buffer);
11370 Out <<
"_ZGV" <<
Data.ISA << Mask;
11373 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
11374 Out << llvm::APSInt::getUnsigned(
Data.VecRegSize / NumElts);
11379 Out <<
'_' << Fn->getName();
11380 Fn->addFnAttr(Out.str());
11398 if (Kind == ParamKindTy::Uniform)
11401 if (Kind == ParamKindTy::LinearUVal || Kind == ParamKindTy::LinearRef)
11404 if ((Kind == ParamKindTy::Linear || Kind == ParamKindTy::LinearVal) &&
11414 unsigned Size =
C.getTypeSize(QT);
11417 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
11441 return C.getTypeSize(PTy);
11444 return C.getTypeSize(QT);
11446 return C.getTypeSize(
C.getUIntPtrType());
11452static std::tuple<unsigned, unsigned, bool>
11458 bool OutputBecomesInput =
false;
11462 Sizes.push_back(
getAArch64LS(RetType, ParamKindTy::Vector,
C));
11464 OutputBecomesInput =
true;
11466 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
11471 assert(!Sizes.empty() &&
"Unable to determine NDS and WDS.");
11474 assert(llvm::all_of(Sizes,
11475 [](
unsigned Size) {
11476 return Size == 8 || Size == 16 || Size == 32 ||
11477 Size == 64 || Size == 128;
11481 return std::make_tuple(*llvm::min_element(Sizes), *llvm::max_element(Sizes),
11482 OutputBecomesInput);
11488template <
typename T>
11490 char ISA, StringRef ParSeq,
11491 StringRef MangledName,
bool OutputBecomesInput,
11492 llvm::Function *Fn) {
11494 llvm::raw_svector_ostream Out(Buffer);
11495 Out << Prefix << ISA << LMask << VLEN;
11496 if (OutputBecomesInput)
11498 Out << ParSeq <<
"_" << MangledName;
11499 Fn->addFnAttr(Out.str());
11505 StringRef Prefix,
char ISA,
11506 StringRef ParSeq, StringRef MangledName,
11507 bool OutputBecomesInput,
11508 llvm::Function *Fn) {
11512 OutputBecomesInput, Fn);
11514 OutputBecomesInput, Fn);
11518 OutputBecomesInput, Fn);
11520 OutputBecomesInput, Fn);
11524 OutputBecomesInput, Fn);
11526 OutputBecomesInput, Fn);
11531 OutputBecomesInput, Fn);
11534 llvm_unreachable(
"Scalar type is too wide.");
11542 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
11543 char ISA,
unsigned VecRegSize, llvm::Function *Fn,
SourceLocation SLoc) {
11547 const unsigned NDS = std::get<0>(
Data);
11548 const unsigned WDS = std::get<1>(
Data);
11549 const bool OutputBecomesInput = std::get<2>(
Data);
11553 if (UserVLEN == 1) {
11556 "The clause simdlen(1) has no effect when targeting aarch64.");
11563 if (ISA ==
'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
11566 "power of 2 when targeting Advanced SIMD.");
11573 if (ISA ==
's' && UserVLEN != 0) {
11574 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
11577 "lanes in the architectural constraints "
11578 "for SVE (min is 128-bit, max is "
11579 "2048-bit, by steps of 128-bit)");
11587 StringRef Prefix =
"_ZGV";
11593 OutputBecomesInput, Fn);
11595 assert(ISA ==
'n' &&
"Expected ISA either 's' or 'n'.");
11599 case OMPDeclareSimdDeclAttr::BS_Undefined:
11601 OutputBecomesInput, Fn);
11603 OutputBecomesInput, Fn);
11605 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
11607 OutputBecomesInput, Fn);
11609 case OMPDeclareSimdDeclAttr::BS_Inbranch:
11611 OutputBecomesInput, Fn);
11621 OutputBecomesInput, Fn);
11623 assert(ISA ==
'n' &&
"Expected ISA either 's' or 'n'.");
11628 case OMPDeclareSimdDeclAttr::BS_Undefined:
11630 OutputBecomesInput, Fn);
11632 OutputBecomesInput, Fn);
11634 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
11636 OutputBecomesInput, Fn);
11638 case OMPDeclareSimdDeclAttr::BS_Inbranch:
11640 OutputBecomesInput, Fn);
11648 llvm::Function *Fn) {
11653 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
11655 ParamPositions.try_emplace(FD, 0);
11656 unsigned ParamPos = ParamPositions.size();
11658 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
11664 for (
const Expr *E :
Attr->uniforms()) {
11668 Pos = ParamPositions[FD];
11671 ->getCanonicalDecl();
11672 auto It = ParamPositions.find(PVD);
11673 assert(It != ParamPositions.end() &&
"Function parameter not found");
11676 ParamAttrs[Pos].Kind = Uniform;
11679 auto *NI =
Attr->alignments_begin();
11680 for (
const Expr *E :
Attr->aligneds()) {
11685 Pos = ParamPositions[FD];
11689 ->getCanonicalDecl();
11690 auto It = ParamPositions.find(PVD);
11691 assert(It != ParamPositions.end() &&
"Function parameter not found");
11693 ParmTy = PVD->getType();
11695 ParamAttrs[Pos].Alignment =
11697 ? (*NI)->EvaluateKnownConstInt(
C)
11698 : llvm::APSInt::getUnsigned(
11699 C.toCharUnitsFromBits(
C.getOpenMPDefaultSimdAlign(ParmTy))
11704 auto *SI =
Attr->steps_begin();
11705 auto *MI =
Attr->modifiers_begin();
11706 for (
const Expr *E :
Attr->linears()) {
11709 bool IsReferenceType =
false;
11712 unsigned PtrRescalingFactor = 1;
11714 Pos = ParamPositions[FD];
11716 PtrRescalingFactor =
CGM.getContext()
11717 .getTypeSizeInChars(P->getPointeeType())
11721 ->getCanonicalDecl();
11722 auto It = ParamPositions.find(PVD);
11723 assert(It != ParamPositions.end() &&
"Function parameter not found");
11725 if (
auto *P = dyn_cast<PointerType>(PVD->getType()))
11726 PtrRescalingFactor =
CGM.getContext()
11727 .getTypeSizeInChars(P->getPointeeType())
11729 else if (PVD->getType()->isReferenceType()) {
11730 IsReferenceType =
true;
11731 PtrRescalingFactor =
11733 .getTypeSizeInChars(PVD->getType().getNonReferenceType())
11737 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
11738 if (*MI == OMPC_LINEAR_ref)
11739 ParamAttr.Kind = LinearRef;
11740 else if (*MI == OMPC_LINEAR_uval)
11741 ParamAttr.Kind = LinearUVal;
11742 else if (IsReferenceType)
11743 ParamAttr.Kind = LinearVal;
11745 ParamAttr.Kind = Linear;
11747 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1);
11751 if (
const auto *DRE =
11753 if (
const auto *StridePVD =
11754 dyn_cast<ParmVarDecl>(DRE->getDecl())) {
11755 ParamAttr.HasVarStride =
true;
11756 auto It = ParamPositions.find(StridePVD->getCanonicalDecl());
11757 assert(It != ParamPositions.end() &&
11758 "Function parameter not found");
11759 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(It->second);
11763 ParamAttr.StrideOrArg =
Result.Val.getInt();
11769 if (!ParamAttr.HasVarStride &&
11770 (ParamAttr.Kind == Linear || ParamAttr.Kind == LinearRef))
11771 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor;
11775 llvm::APSInt VLENVal;
11777 const Expr *VLENExpr =
Attr->getSimdlen();
11782 OMPDeclareSimdDeclAttr::BranchStateTy State =
Attr->getBranchState();
11783 if (
CGM.getTriple().isX86()) {
11785 }
else if (
CGM.getTriple().getArch() == llvm::Triple::aarch64) {
11786 unsigned VLEN = VLENVal.getExtValue();
11787 StringRef MangledName = Fn->getName();
11788 if (
CGM.getTarget().hasFeature(
"sve"))
11790 MangledName,
's', 128, Fn, ExprLoc);
11791 else if (
CGM.getTarget().hasFeature(
"neon"))
11793 MangledName,
'n', 128, Fn, ExprLoc);
11802class DoacrossCleanupTy final :
public EHScopeStack::Cleanup {
11804 static const int DoacrossFinArgs = 2;
11807 llvm::FunctionCallee RTLFn;
11808 llvm::Value *Args[DoacrossFinArgs];
11811 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
11814 assert(CallArgs.size() == DoacrossFinArgs);
11815 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
11832 QualType Int64Ty =
C.getIntTypeForBitwidth(64,
true);
11840 RD =
C.buildImplicitRecord(
"kmp_dim");
11848 RD =
KmpDimTy->castAsRecordDecl();
11850 llvm::APInt Size(32, NumIterations.size());
11856 enum { LowerFD = 0, UpperFD, StrideFD };
11858 for (
unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
11863 DimsLVal, *std::next(RD->
field_begin(), UpperFD));
11865 CGF.
EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(),
11866 Int64Ty, NumIterations[I]->getExprLoc());
11870 DimsLVal, *std::next(RD->
field_begin(), StrideFD));
11877 llvm::Value *Args[] = {
11880 llvm::ConstantInt::getSigned(
CGM.Int32Ty, NumIterations.size()),
11885 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
11886 CGM.getModule(), OMPRTL___kmpc_doacross_init);
11888 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
11890 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
11891 CGM.getModule(), OMPRTL___kmpc_doacross_fini);
11896template <
typename T>
11898 const T *
C, llvm::Value *ULoc,
11899 llvm::Value *ThreadID) {
11902 llvm::APInt Size(32,
C->getNumLoops());
11906 for (
unsigned I = 0, E =
C->getNumLoops(); I < E; ++I) {
11907 const Expr *CounterVal =
C->getLoopData(I);
11908 assert(CounterVal);
11915 llvm::Value *Args[] = {
11918 llvm::FunctionCallee RTLFn;
11920 OMPDoacrossKind<T> ODK;
11921 if (ODK.isSource(
C)) {
11923 OMPRTL___kmpc_doacross_post);
11925 assert(ODK.isSink(
C) &&
"Expect sink modifier.");
11927 OMPRTL___kmpc_doacross_wait);
11947 llvm::FunctionCallee Callee,
11949 assert(Loc.
isValid() &&
"Outlined function call location must be valid.");
11952 if (
auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
11953 if (Fn->doesNotThrow()) {
11964 emitCall(CGF, Loc, OutlinedFn, Args);
11968 if (
const auto *FD = dyn_cast<FunctionDecl>(D))
11969 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
11975 const VarDecl *TargetParam)
const {
11982 const Expr *Allocator) {
11983 llvm::Value *AllocVal;
11993 AllocVal = llvm::Constant::getNullValue(
12003 if (!AllocateAlignment)
12006 return llvm::ConstantInt::get(
CGM.
SizeTy, AllocateAlignment->getQuantity());
12019 auto I = UntiedData.find(VD);
12020 if (I != UntiedData.end()) {
12021 UntiedAddr = I->second.first;
12022 UntiedRealAddr = I->second.second;
12026 if (CVD->
hasAttr<OMPAllocateDeclAttr>()) {
12035 Size = CGF.
Builder.CreateNUWAdd(
12037 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
12038 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
12044 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
12045 const Expr *Allocator = AA->getAllocator();
12049 Args.push_back(ThreadID);
12051 Args.push_back(Alignment);
12052 Args.push_back(Size);
12053 Args.push_back(AllocVal);
12054 llvm::omp::RuntimeFunction FnID =
12055 Alignment ? OMPRTL___kmpc_aligned_alloc : OMPRTL___kmpc_alloc;
12057 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args,
12059 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12060 CGM.getModule(), OMPRTL___kmpc_free);
12068 class OMPAllocateCleanupTy final :
public EHScopeStack::Cleanup {
12069 llvm::FunctionCallee RTLFn;
12072 const Expr *AllocExpr;
12075 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
12077 const Expr *AllocExpr)
12078 : RTLFn(RTLFn), LocEncoding(LocEncoding),
Addr(
Addr),
12079 AllocExpr(AllocExpr) {}
12083 llvm::Value *Args[3];
12089 Args[2] = AllocVal;
12097 CGF.
EHStack.pushCleanup<OMPAllocateCleanupTy>(
12099 VDAddr, Allocator);
12100 if (UntiedRealAddr.
isValid())
12103 Region->emitUntiedSwitch(CGF);
12120 assert(CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12124 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back();
12126 for (
const Stmt *Ref :
C->private_refs()) {
12127 const auto *SimpleRefExpr =
cast<Expr>(Ref)->IgnoreParenImpCasts();
12129 if (
const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
12130 VD = DRE->getDecl();
12133 assert((ME->isImplicitCXXThis() ||
12135 "Expected member of current class.");
12136 VD = ME->getMemberDecl();
12146 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back();
12152 std::pair<Address, Address>> &LocalVars)
12153 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) {
12157 CGF.
CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size());
12158 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars);
12164 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back();
12168 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12170 return llvm::any_of(
12171 CGM.getOpenMPRuntime().NontemporalDeclsStack,
12175void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
12179 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
12185 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front());
12193 for (
const Expr *Ref :
C->varlist()) {
12194 if (!Ref->getType()->isScalarType())
12196 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12199 NeedToCheckForLPCs.insert(DRE->getDecl());
12202 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
12203 for (
const Expr *Ref :
C->varlist()) {
12204 if (!Ref->getType()->isScalarType())
12206 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12209 NeedToCheckForLPCs.insert(DRE->getDecl());
12212 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12213 for (
const Expr *Ref :
C->varlist()) {
12214 if (!Ref->getType()->isScalarType())
12216 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12219 NeedToCheckForLPCs.insert(DRE->getDecl());
12222 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
12223 for (
const Expr *Ref :
C->varlist()) {
12224 if (!Ref->getType()->isScalarType())
12226 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12229 NeedToCheckForLPCs.insert(DRE->getDecl());
12232 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
12233 for (
const Expr *Ref :
C->varlist()) {
12234 if (!Ref->getType()->isScalarType())
12236 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12239 NeedToCheckForLPCs.insert(DRE->getDecl());
12242 for (
const Decl *VD : NeedToCheckForLPCs) {
12244 llvm::reverse(
CGM.getOpenMPRuntime().LastprivateConditionalStack)) {
12245 if (
Data.DeclToUniqueName.count(VD) > 0) {
12246 if (!
Data.Disabled)
12247 NeedToAddForLPCsAsDisabled.insert(VD);
12254CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12257 Action((CGM.getLangOpts().OpenMP >= 50 &&
12260 return C->getKind() ==
12261 OMPC_LASTPRIVATE_conditional;
12263 ? ActionToDo::PushAsLastprivateConditional
12264 : ActionToDo::DoNotPush) {
12265 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12266 if (
CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
12268 assert(Action == ActionToDo::PushAsLastprivateConditional &&
12269 "Expected a push action.");
12271 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
12273 if (
C->getKind() != OMPC_LASTPRIVATE_conditional)
12276 for (
const Expr *Ref :
C->varlist()) {
12277 Data.DeclToUniqueName.insert(std::make_pair(
12282 Data.IVLVal = IVLVal;
12286CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12288 :
CGM(CGF.
CGM), Action(ActionToDo::DoNotPush) {
12292 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
12293 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
12294 if (!NeedToAddForLPCsAsDisabled.empty()) {
12295 Action = ActionToDo::DisableLastprivateConditional;
12296 LastprivateConditionalData &
Data =
12298 for (
const Decl *VD : NeedToAddForLPCsAsDisabled)
12299 Data.DeclToUniqueName.try_emplace(VD);
12301 Data.Disabled =
true;
12305CGOpenMPRuntime::LastprivateConditionalRAII
12308 return LastprivateConditionalRAII(CGF, S);
12312 if (CGM.getLangOpts().OpenMP < 50)
12314 if (Action == ActionToDo::DisableLastprivateConditional) {
12315 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12316 "Expected list of disabled private vars.");
12317 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12319 if (Action == ActionToDo::PushAsLastprivateConditional) {
12321 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12322 "Expected list of lastprivate conditional vars.");
12323 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12335 auto VI = I->getSecond().find(VD);
12336 if (VI == I->getSecond().end()) {
12337 RecordDecl *RD =
C.buildImplicitRecord(
"lasprivate.conditional");
12342 NewType =
C.getCanonicalTagType(RD);
12345 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
12347 NewType = std::get<0>(VI->getSecond());
12348 VDField = std::get<1>(VI->getSecond());
12349 FiredField = std::get<2>(VI->getSecond());
12350 BaseLVal = std::get<3>(VI->getSecond());
12362class LastprivateConditionalRefChecker final
12365 const Expr *FoundE =
nullptr;
12366 const Decl *FoundD =
nullptr;
12367 StringRef UniqueDeclName;
12369 llvm::Function *FoundFn =
nullptr;
12375 llvm::reverse(LPM)) {
12376 auto It = D.DeclToUniqueName.find(E->
getDecl());
12377 if (It == D.DeclToUniqueName.end())
12383 UniqueDeclName = It->second;
12388 return FoundE == E;
12394 llvm::reverse(LPM)) {
12396 if (It == D.DeclToUniqueName.end())
12402 UniqueDeclName = It->second;
12407 return FoundE == E;
12409 bool VisitStmt(
const Stmt *S) {
12410 for (
const Stmt *Child : S->
children()) {
12413 if (
const auto *E = dyn_cast<Expr>(Child))
12421 explicit LastprivateConditionalRefChecker(
12422 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM)
12424 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
12425 getFoundData()
const {
12426 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
12433 StringRef UniqueDeclName,
12439 llvm::Constant *LastIV =
OMPBuilder.getOrCreateInternalVariable(
12440 LLIVTy,
getName({UniqueDeclName,
"iv"}));
12448 llvm::GlobalVariable *
Last =
OMPBuilder.getOrCreateInternalVariable(
12464 auto &&
CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
12470 llvm::Value *CmpRes;
12472 CmpRes = CGF.
Builder.CreateICmpSLE(LastIVVal, IVVal);
12475 "Loop iteration variable must be integer.");
12476 CmpRes = CGF.
Builder.CreateICmpULE(LastIVVal, IVVal);
12480 CGF.
Builder.CreateCondBr(CmpRes, ThenBB, ExitBB);
12501 "Aggregates are not supported in lastprivate conditional.");
12510 if (
CGM.getLangOpts().OpenMPSimd) {
12524 if (!Checker.Visit(LHS))
12526 const Expr *FoundE;
12527 const Decl *FoundD;
12528 StringRef UniqueDeclName;
12530 llvm::Function *FoundFn;
12531 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
12532 Checker.getFoundData();
12533 if (FoundFn != CGF.
CurFn) {
12538 "Lastprivate conditional is not found in outer region.");
12539 QualType StructTy = std::get<0>(It->getSecond());
12540 const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
12551 FiredLVal, llvm::AtomicOrdering::Unordered,
12569 auto It = llvm::find_if(
12571 if (It == Range.end() || It->Fn != CGF.
CurFn)
12575 "Lastprivates must be registered already.");
12578 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back());
12579 for (
const auto &Pair : It->DeclToUniqueName) {
12580 const auto *VD =
cast<VarDecl>(Pair.first->getCanonicalDecl());
12583 auto I = LPCI->getSecond().find(Pair.first);
12584 assert(I != LPCI->getSecond().end() &&
12585 "Lastprivate must be rehistered already.");
12587 LValue BaseLVal = std::get<3>(I->getSecond());
12591 llvm::Value *Cmp = CGF.
Builder.CreateIsNotNull(Res);
12595 CGF.
Builder.CreateCondBr(Cmp, ThenBB, DoneBB);
12620 "Unknown lastprivate conditional variable.");
12621 StringRef UniqueName = It->second;
12622 llvm::GlobalVariable *GV =
CGM.getModule().getNamedGlobal(UniqueName);
12636 llvm_unreachable(
"Not supported in SIMD-only mode");
12643 llvm_unreachable(
"Not supported in SIMD-only mode");
12650 bool Tied,
unsigned &NumberOfParts) {
12651 llvm_unreachable(
"Not supported in SIMD-only mode");
12659 llvm_unreachable(
"Not supported in SIMD-only mode");
12665 const Expr *Hint) {
12666 llvm_unreachable(
"Not supported in SIMD-only mode");
12672 llvm_unreachable(
"Not supported in SIMD-only mode");
12678 const Expr *Filter) {
12679 llvm_unreachable(
"Not supported in SIMD-only mode");
12684 llvm_unreachable(
"Not supported in SIMD-only mode");
12690 llvm_unreachable(
"Not supported in SIMD-only mode");
12698 llvm_unreachable(
"Not supported in SIMD-only mode");
12705 llvm_unreachable(
"Not supported in SIMD-only mode");
12712 bool ForceSimpleCall) {
12713 llvm_unreachable(
"Not supported in SIMD-only mode");
12720 llvm_unreachable(
"Not supported in SIMD-only mode");
12725 llvm_unreachable(
"Not supported in SIMD-only mode");
12731 llvm_unreachable(
"Not supported in SIMD-only mode");
12737 llvm_unreachable(
"Not supported in SIMD-only mode");
12744 llvm_unreachable(
"Not supported in SIMD-only mode");
12750 llvm_unreachable(
"Not supported in SIMD-only mode");
12755 unsigned IVSize,
bool IVSigned,
12758 llvm_unreachable(
"Not supported in SIMD-only mode");
12766 llvm_unreachable(
"Not supported in SIMD-only mode");
12770 ProcBindKind ProcBind,
12772 llvm_unreachable(
"Not supported in SIMD-only mode");
12779 llvm_unreachable(
"Not supported in SIMD-only mode");
12785 llvm_unreachable(
"Not supported in SIMD-only mode");
12790 llvm_unreachable(
"Not supported in SIMD-only mode");
12796 llvm::AtomicOrdering AO) {
12797 llvm_unreachable(
"Not supported in SIMD-only mode");
12802 llvm::Function *TaskFunction,
12804 const Expr *IfCond,
12806 llvm_unreachable(
"Not supported in SIMD-only mode");
12813 llvm_unreachable(
"Not supported in SIMD-only mode");
12820 assert(Options.
SimpleReduction &&
"Only simple reduction is expected.");
12822 ReductionOps, Options);
12828 llvm_unreachable(
"Not supported in SIMD-only mode");
12833 bool IsWorksharingReduction) {
12834 llvm_unreachable(
"Not supported in SIMD-only mode");
12841 llvm_unreachable(
"Not supported in SIMD-only mode");
12846 llvm::Value *ReductionsPtr,
12848 llvm_unreachable(
"Not supported in SIMD-only mode");
12854 llvm_unreachable(
"Not supported in SIMD-only mode");
12860 llvm_unreachable(
"Not supported in SIMD-only mode");
12866 llvm_unreachable(
"Not supported in SIMD-only mode");
12871 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
12873 llvm_unreachable(
"Not supported in SIMD-only mode");
12878 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
12879 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
12883 llvm_unreachable(
"Not supported in SIMD-only mode");
12887 llvm_unreachable(
"Not supported in SIMD-only mode");
12891 llvm_unreachable(
"Not supported in SIMD-only mode");
12901 llvm::Function *OutlinedFn,
12903 llvm_unreachable(
"Not supported in SIMD-only mode");
12907 const Expr *NumTeams,
12908 const Expr *ThreadLimit,
12910 llvm_unreachable(
"Not supported in SIMD-only mode");
12917 llvm_unreachable(
"Not supported in SIMD-only mode");
12923 llvm_unreachable(
"Not supported in SIMD-only mode");
12929 llvm_unreachable(
"Not supported in SIMD-only mode");
12934 llvm_unreachable(
"Not supported in SIMD-only mode");
12939 llvm_unreachable(
"Not supported in SIMD-only mode");
12944 const VarDecl *NativeParam)
const {
12945 llvm_unreachable(
"Not supported in SIMD-only mode");
12951 const VarDecl *TargetParam)
const {
12952 llvm_unreachable(
"Not supported in SIMD-only mode");
static llvm::Value * emitCopyprivateCopyFunction(CodeGenModule &CGM, llvm::Type *ArgsElemType, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps, SourceLocation Loc)
static StringRef getIdentStringFromSourceLocation(CodeGenFunction &CGF, SourceLocation Loc, SmallString< 128 > &Buffer)
static void emitOffloadingArraysAndArgs(CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, CGOpenMPRuntime::TargetDataInfo &Info, llvm::OpenMPIRBuilder &OMPBuilder, bool IsNonContiguous=false, bool ForEndCall=false)
Emit the arrays used to pass the captures and map information to the offloading runtime library.
static RecordDecl * createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, ArrayRef< PrivateDataTy > Privates)
static void emitInitWithReductionInitializer(CodeGenFunction &CGF, const OMPDeclareReductionDecl *DRD, const Expr *InitOp, Address Private, Address Original, QualType Ty)
static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, Address OriginalBaseAddress, llvm::Value *Addr)
static void emitPrivatesInit(CodeGenFunction &CGF, const OMPExecutableDirective &D, Address KmpTaskSharedsPtr, LValue TDBase, const RecordDecl *KmpTaskTWithPrivatesQTyRD, QualType SharedsTy, QualType SharedsPtrTy, const OMPTaskDataTy &Data, ArrayRef< PrivateDataTy > Privates, bool ForDup)
Emit initialization for private variables in task-based directives.
static void emitClauseForBareTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &Values)
static llvm::Value * emitDestructorsFunction(CodeGenModule &CGM, SourceLocation Loc, QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy, QualType KmpTaskTWithPrivatesQTy)
static unsigned evaluateCDTSize(const FunctionDecl *FD, ArrayRef< ParamAttrTy > ParamAttrs)
static void EmitOMPAggregateReduction(CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, const VarDecl *RHSVar, const llvm::function_ref< void(CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *)> &RedOpGen, const Expr *XExpr=nullptr, const Expr *EExpr=nullptr, const Expr *UpExpr=nullptr)
Emit reduction operation for each element of array (required for array sections) LHS op = RHS.
static void emitTargetCallFallback(CGOpenMPRuntime *OMPRuntime, llvm::Function *OutlinedFn, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, bool RequiresOuterTask, const CapturedStmt &CS, bool OffloadingMandatory, CodeGenFunction &CGF)
static llvm::Value * emitReduceInitFunction(CodeGenModule &CGM, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Emits reduction initializer function:
static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion)
static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy, llvm::PointerUnion< unsigned *, LValue * > Pos, const OMPTaskDataTy::DependData &Data, Address DependenciesArray)
static llvm::Value * emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, const OMPTaskDataTy &Data, QualType PrivatesQTy, ArrayRef< PrivateDataTy > Privates)
Emit a privates mapping function for correct handling of private and firstprivate variables.
static llvm::Value * emitReduceCombFunction(CodeGenModule &CGM, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N, const Expr *ReductionOp, const Expr *LHS, const Expr *RHS, const Expr *PrivateRef)
Emits reduction combiner function:
static RecordDecl * createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef< PrivateDataTy > Privates)
static llvm::Value * getAllocatorVal(CodeGenFunction &CGF, const Expr *Allocator)
Return allocator value from expression, or return a null allocator (default when no allocator specifi...
static llvm::Function * emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, OpenMPDirectiveKind Kind, QualType KmpInt32Ty, QualType KmpTaskTWithPrivatesPtrQTy, QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, QualType SharedsPtrTy, llvm::Function *TaskFunction, llvm::Value *TaskPrivatesMap)
Emit a proxy function which accepts kmp_task_t as the second argument.
static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, char ISA, StringRef ParSeq, StringRef MangledName, bool OutputBecomesInput, llvm::Function *Fn)
static bool isAllocatableDecl(const VarDecl *VD)
static llvm::Value * getAlignmentValue(CodeGenModule &CGM, const VarDecl *VD)
Return the alignment from an allocate directive if present.
static void emitTargetCallKernelLaunch(CGOpenMPRuntime *OMPRuntime, llvm::Function *OutlinedFn, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, bool RequiresOuterTask, const CapturedStmt &CS, bool OffloadingMandatory, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::Value *OutlinedFnID, CodeGenFunction::OMPTargetDataInfo &InputInfo, llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter, CodeGenFunction &CGF, CodeGenModule &CGM)
static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind convertCaptureClause(const VarDecl *VD)
static std::tuple< unsigned, unsigned, bool > getNDSWDS(const FunctionDecl *FD, ArrayRef< ParamAttrTy > ParamAttrs)
static const OMPExecutableDirective * getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D)
Check for inner distribute directive.
static std::pair< llvm::Value *, llvm::Value * > getPointerAndSize(CodeGenFunction &CGF, const Expr *E)
static const VarDecl * getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE)
static bool isTrivial(ASTContext &Ctx, const Expr *E)
Checks if the expression is constant or does not have non-trivial function calls.
static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, bool Chunked, bool Ordered)
Map the OpenMP loop schedule to the runtime enumeration.
static void getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, const Expr **E, int32_t &UpperBound, bool UpperBoundOnly, llvm::Value **CondVal)
Check for a num threads constant value (stored in DefaultVal), or expression (stored in E).
static llvm::Value * emitDeviceID(llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, CodeGenFunction &CGF)
static const OMPDeclareReductionDecl * getReductionInit(const Expr *ReductionOp)
Check if the combiner is a call to UDR combiner and if it is so return the UDR decl used for reductio...
static bool checkInitIsRequired(CodeGenFunction &CGF, ArrayRef< PrivateDataTy > Privates)
Check if duplication function is required for taskloops.
static bool checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD, ArrayRef< PrivateDataTy > Privates)
Checks if destructor function is required to be generated.
static llvm::TargetRegionEntryInfo getEntryInfoFromPresumedLoc(CodeGenModule &CGM, llvm::OpenMPIRBuilder &OMPBuilder, SourceLocation BeginLoc, llvm::StringRef ParentName="")
static void genMapInfo(MappableExprsHandler &MEHandler, CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder, const llvm::DenseSet< CanonicalDeclPtr< const Decl > > &SkippedVarSet=llvm::DenseSet< CanonicalDeclPtr< const Decl > >())
static void emitForStaticInitCall(CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, const CGOpenMPRuntime::StaticRTInput &Values)
static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, LValue BaseLV)
static void getKmpAffinityType(ASTContext &C, QualType &KmpTaskAffinityInfoTy)
Builds kmp_depend_info, if it is not built yet, and builds flags type.
static llvm::Constant * emitMappingInformation(CodeGenFunction &CGF, llvm::OpenMPIRBuilder &OMPBuilder, MappableExprsHandler::MappingExprInfo &MapExprs)
Emit a string constant containing the names of the values mapped to the offloading runtime library.
static void getDependTypes(ASTContext &C, QualType &KmpDependInfoTy, QualType &FlagsTy)
Builds kmp_depend_info, if it is not built yet, and builds flags type.
static llvm::Value * emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, const OMPExecutableDirective &D, QualType KmpTaskTWithPrivatesPtrQTy, const RecordDecl *KmpTaskTWithPrivatesQTyRD, const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, QualType SharedsPtrTy, const OMPTaskDataTy &Data, ArrayRef< PrivateDataTy > Privates, bool WithLastIter)
Emit task_dup function (for initialization of private/firstprivate/lastprivate vars and last_iter fla...
static std::pair< llvm::Value *, OMPDynGroupprivateFallbackType > emitDynCGroupMem(const OMPExecutableDirective &D, CodeGenFunction &CGF)
static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind convertDeviceClause(const VarDecl *VD)
static llvm::Value * emitReduceFiniFunction(CodeGenModule &CGM, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Emits reduction finalizer function:
static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, QualType Type, bool EmitDeclareReductionInit, const Expr *Init, const OMPDeclareReductionDecl *DRD, Address SrcAddr=Address::invalid())
Emit initialization of arrays of complex types.
static bool getAArch64PBV(QualType QT, ASTContext &C)
Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI.
static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C)
Computes the lane size (LS) of a return type or of an input parameter, as defined by LS(P) in 3....
static void EmitDoacrossOrdered(CodeGenFunction &CGF, CodeGenModule &CGM, const T *C, llvm::Value *ULoc, llvm::Value *ThreadID)
static RTLDependenceKindTy translateDependencyKind(OpenMPDependClauseKind K)
Translates internal dependency kind into the runtime kind.
static void emitTargetCallElse(CGOpenMPRuntime *OMPRuntime, llvm::Function *OutlinedFn, const OMPExecutableDirective &D, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars, bool RequiresOuterTask, const CapturedStmt &CS, bool OffloadingMandatory, CodeGenFunction &CGF)
static llvm::Function * emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, const Expr *CombinerInitializer, const VarDecl *In, const VarDecl *Out, bool IsCombiner)
static void emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, const llvm::APSInt &VLENVal, ArrayRef< ParamAttrTy > ParamAttrs, OMPDeclareSimdDeclAttr::BranchStateTy State)
static void emitReductionCombiner(CodeGenFunction &CGF, const Expr *ReductionOp)
Emit reduction combiner.
static std::string mangleVectorParameters(ArrayRef< ParamAttrTy > ParamAttrs)
Mangle the parameter part of the vector function name according to their OpenMP classification.
static std::string generateUniqueName(CodeGenModule &CGM, llvm::StringRef Prefix, const Expr *Ref)
static llvm::Function * emitParallelOrTeamsOutlinedFunction(CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen)
static void emitAArch64DeclareSimdFunction(CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, ArrayRef< ParamAttrTy > ParamAttrs, OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc)
Emit vector function attributes for AArch64, as defined in the AAVFABI.
static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, unsigned Index, const VarDecl *Var)
Given an array of pointers to variables, project the address of a given variable.
static 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).
@ 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,...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
const LangOptions & getLangOpts() const
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
const VariableArrayType * getAsVariableArrayType(QualType T) const
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
unsigned getTypeAlign(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in bits.
CharUnits getSize() const
getSize - Get the record size in characters.
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getNonVirtualSize() const
getNonVirtualSize - Get the non-virtual size (in chars) of an object, which is the size of the object...
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Attr - This represents one attribute.
Represents a C++ constructor within a class.
Represents a C++ destructor within a class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
QualType getFunctionObjectParameterType() const
bool isLambda() const
Determine whether this class describes a lambda function object.
void getCaptureFields(llvm::DenseMap< const ValueDecl *, FieldDecl * > &Captures, FieldDecl *&ThisCapture) const
For a closure type, retrieve the mapping from captured variables and this to the non-static data memb...
unsigned getNumBases() const
Retrieves the number of base classes of this class.
base_class_range vbases()
capture_const_range captures() const
CXXDestructorDecl * getDestructor() const
Returns the destructor decl for this class.
CanProxy< U > castAs() const
A wrapper class around a pointer that always points to its canonical declaration.
Describes the capture of either a variable, or 'this', or variable-length array type.
bool capturesVariableByCopy() const
Determine whether this capture handles a variable by copy.
VarDecl * getCapturedVar() const
Retrieve the declaration of the variable being captured.
bool capturesVariableArrayType() const
Determine whether this capture handles a variable-length array type.
bool capturesThis() const
Determine whether this capture handles the C++ 'this' pointer.
bool capturesVariable() const
Determine whether this capture handles a variable (by reference).
This captures a statement into a function.
const Capture * const_capture_iterator
capture_iterator capture_end() const
Retrieve an iterator pointing past the end of the sequence of captures.
const RecordDecl * getCapturedRecordDecl() const
Retrieve the record declaration for captured variables.
Stmt * getCapturedStmt()
Retrieve the statement being captured.
bool capturesVariable(const VarDecl *Var) const
True if this variable has been captured.
capture_iterator capture_begin()
Retrieve an iterator pointing to the first capture.
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
CharUnits getAlignment() const
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Address withPointer(llvm::Value *NewPointer, KnownNonNull_t IsKnownNonNull) const
Return address with different pointer, but same element type and alignment.
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
llvm::PointerType * getType() const
Return the type of the pointer value.
static ApplyDebugLocation CreateArtificial(CodeGenFunction &CGF)
Apply TemporaryLocation if it is valid.
static ApplyDebugLocation CreateDefaultArtificial(CodeGenFunction &CGF, SourceLocation TemporaryLocation)
Apply TemporaryLocation if it is valid.
static ApplyDebugLocation CreateEmpty(CodeGenFunction &CGF)
Set the IRBuilder to not attach debug locations.
llvm::StoreInst * CreateStore(llvm::Value *Val, Address Addr, bool IsVolatile=false)
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, const llvm::Twine &Name="")
Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
Address CreateConstArrayGEP(Address Addr, uint64_t Index, const llvm::Twine &Name="")
Given addr = [n x T]* ... produce name = getelementptr inbounds addr, i64 0, i64 index where i64 is a...
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::CallInst * CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, bool IsVolatile=false)
Address CreateConstGEP(Address Addr, uint64_t Index, const llvm::Twine &Name="")
Given addr = T* ... produce name = getelementptr inbounds addr, i64 index where i64 is actually the t...
Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
CGFunctionInfo - Class to encapsulate the information about a function definition.
DisableAutoDeclareTargetRAII(CodeGenModule &CGM)
~DisableAutoDeclareTargetRAII()
~LastprivateConditionalRAII()
static LastprivateConditionalRAII disable(CodeGenFunction &CGF, const OMPExecutableDirective &S)
NontemporalDeclsRAII(CodeGenModule &CGM, const OMPLoopDirective &S)
Struct that keeps all the relevant information that should be kept throughout a 'target data' region.
llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap
Map between the a declaration of a capture and the corresponding new llvm address where the runtime r...
~UntiedTaskLocalDeclsRAII()
UntiedTaskLocalDeclsRAII(CodeGenFunction &CGF, const llvm::MapVector< CanonicalDeclPtr< const VarDecl >, std::pair< Address, Address > > &LocalVars)
virtual Address emitThreadIDAddress(CodeGenFunction &CGF, SourceLocation Loc)
Emits address of the word in a memory where current thread id is stored.
llvm::StringSet ThreadPrivateWithDefinition
Set of threadprivate variables with the generated initializer.
CGOpenMPRuntime(CodeGenModule &CGM)
virtual void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the task directive.
void createOffloadEntriesAndInfoMetadata()
Creates all the offload entries in the current compilation unit along with the associated metadata.
const Expr * getNumTeamsExprForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, int32_t &MinTeamsVal, int32_t &MaxTeamsVal)
Emit the number of teams for a target directive.
virtual Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc)
Returns address of the threadprivate variable for the current thread.
void emitDeferredTargetDecls() const
Emit deferred declare target variables marked for deferred emission.
virtual llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST)
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
bool markAsGlobalTarget(GlobalDecl GD)
Marks the declaration as already emitted for the device code and returns true, if it was marked alrea...
virtual void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr)
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
llvm::SmallDenseSet< CanonicalDeclPtr< const Decl > > NontemporalDeclsSet
virtual void emitTargetDataStandAloneCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device)
Emit the data mapping/movement code associated with the directive D that should be of the form 'targe...
virtual void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, SourceLocation SeverityLoc=SourceLocation(), const Expr *Message=nullptr, SourceLocation MessageLoc=SourceLocation())
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_tid, kmp_int32 num_threads) ...
QualType SavedKmpTaskloopTQTy
Saved kmp_task_t for taskloop-based directive.
virtual void emitSingleRegion(CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps)
Emits a single region.
virtual bool emitTargetGlobal(GlobalDecl GD)
Emit the global GD if it is meaningful for the target.
void setLocThreadIdInsertPt(CodeGenFunction &CGF, bool AtCurrentPoint=false)
std::string getOutlinedHelperName(StringRef Name) const
Get the function name of an outlined region.
bool HasEmittedDeclareTargetRegion
Flag for keeping track of weather a device routine has been emitted.
llvm::Constant * getOrCreateThreadPrivateCache(const VarDecl *VD)
If the specified mangled name is not in the module, create and return threadprivate cache object.
virtual Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal)
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
virtual void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc)
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
void emitCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee Callee, ArrayRef< llvm::Value * > Args={}) const
Emits Callee function call with arguments Args with location Loc.
virtual void getDefaultScheduleAndChunk(CodeGenFunction &CGF, const OMPLoopDirective &S, OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const
Choose default schedule type and chunk value for the schedule clause.
virtual std::pair< llvm::Function *, llvm::Function * > getUserDefinedReduction(const OMPDeclareReductionDecl *D)
Get combiner/initializer for the specified user-defined reduction, if any.
virtual bool isGPU() const
Returns true if the current target is a GPU.
static const Stmt * getSingleCompoundChild(ASTContext &Ctx, const Stmt *Body)
Checks if the Body is the CompoundStmt and returns its child statement iff there is only one that is ...
virtual void emitDeclareTargetFunction(const FunctionDecl *FD, llvm::GlobalValue *GV)
Emit code for handling declare target functions in the runtime.
bool HasRequiresUnifiedSharedMemory
Flag for keeping track of weather a requires unified_shared_memory directive is present.
llvm::Value * emitUpdateLocation(CodeGenFunction &CGF, SourceLocation Loc, unsigned Flags=0, bool EmitLoc=false)
Emits object of ident_t type with info for source location.
bool isLocalVarInUntiedTask(CodeGenFunction &CGF, const VarDecl *VD) const
Returns true if the variable is a local variable in untied task.
virtual void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars)
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
virtual void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancellation point' construct.
virtual llvm::Function * emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, CodeGenFunction *CGF=nullptr)
Emit a code for initialization of threadprivate variable.
FunctionUDMMapTy FunctionUDMMap
virtual ConstantAddress getAddrOfDeclareTargetVar(const VarDecl *VD)
Returns the address of the variable marked as declare target with link clause OR as declare target wi...
llvm::Function * getOrCreateUserDefinedMapperFunc(const OMPDeclareMapperDecl *D)
Get the function for the specified user-defined mapper.
OpenMPLocThreadIDMapTy OpenMPLocThreadIDMap
virtual void functionFinished(CodeGenFunction &CGF)
Cleans up references to the objects in finished function.
virtual llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP teams directive D.
QualType KmpTaskTQTy
Type typedef struct kmp_task { void * shareds; /**< pointer to block of pointers to shared vars / k...
llvm::OpenMPIRBuilder OMPBuilder
An OpenMP-IR-Builder instance.
virtual void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef< Expr * > NumIterations)
Emit initialization for doacross loop nesting support.
virtual void adjustTargetSpecificDataForLambdas(CodeGenFunction &CGF, const OMPExecutableDirective &D) const
Adjust some parameters for the target-based directives, like addresses of the variables captured by r...
FunctionUDRMapTy FunctionUDRMap
virtual void emitTargetDataCalls(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device, const RegionCodeGenTy &CodeGen, CGOpenMPRuntime::TargetDataInfo &Info)
Emit the target data mapping code associated with D.
virtual unsigned getDefaultLocationReserved2Flags() const
Returns additional flags that can be stored in reserved_2 field of the default location.
virtual Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const
Gets the address of the native argument basing on the address of the target-specific parameter.
void emitUsesAllocatorsFini(CodeGenFunction &CGF, const Expr *Allocator)
Destroys user defined allocators specified in the uses_allocators clause.
QualType KmpTaskAffinityInfoTy
Type typedef struct kmp_task_affinity_info { kmp_intptr_t base_addr; size_t len; struct { bool flag1 ...
void emitPrivateReduction(CodeGenFunction &CGF, SourceLocation Loc, const Expr *Privates, const Expr *LHSExprs, const Expr *RHSExprs, const Expr *ReductionOps)
Emits code for private variable reduction.
llvm::Value * emitNumTeamsForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D)
virtual void emitTargetOutlinedFunctionHelper(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Helper to emit outlined function for 'target' directive.
void scanForTargetRegionsFunctions(const Stmt *S, StringRef ParentName)
Start scanning from statement S and emit all target regions found along the way.
SmallVector< llvm::Value *, 4 > emitDepobjElementsSizes(CodeGenFunction &CGF, QualType &KmpDependInfoTy, const OMPTaskDataTy::DependData &Data)
virtual llvm::Value * emitMessageClause(CodeGenFunction &CGF, const Expr *Message, SourceLocation Loc)
virtual void emitTaskgroupRegion(CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, SourceLocation Loc)
Emit a taskgroup region.
llvm::DenseMap< llvm::Function *, llvm::DenseMap< CanonicalDeclPtr< const Decl >, std::tuple< QualType, const FieldDecl *, const FieldDecl *, LValue > > > LastprivateConditionalToTypes
Maps local variables marked as lastprivate conditional to their internal types.
virtual bool emitTargetGlobalVariable(GlobalDecl GD)
Emit the global variable if it is a valid device global variable.
virtual void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc)
Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32global_tid, kmp_int32 num_teams,...
bool hasRequiresUnifiedSharedMemory() const
Return whether the unified_shared_memory has been specified.
virtual Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, QualType VarType, StringRef Name)
Creates artificial threadprivate variable with name Name and type VarType.
void emitUserDefinedMapper(const OMPDeclareMapperDecl *D, CodeGenFunction *CGF=nullptr)
Emit the function for the user defined mapper construct.
bool HasEmittedTargetRegion
Flag for keeping track of weather a target region has been emitted.
void emitDepobjElements(CodeGenFunction &CGF, QualType &KmpDependInfoTy, LValue PosLVal, const OMPTaskDataTy::DependData &Data, Address DependenciesArray)
std::string getReductionFuncName(StringRef Name) const
Get the function name of a reduction function.
virtual void processRequiresDirective(const OMPRequiresDecl *D)
Perform check on requires decl to ensure that target architecture supports unified addressing.
llvm::DenseSet< CanonicalDeclPtr< const Decl > > AlreadyEmittedTargetDecls
List of the emitted declarations.
virtual llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data)
Emit a code for initialization of task reduction clause.
llvm::Value * getThreadID(CodeGenFunction &CGF, SourceLocation Loc)
Gets thread id value for the current thread.
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.
llvm::MapVector< CanonicalDeclPtr< const VarDecl >, std::pair< Address, Address > > UntiedLocalVarsAddressesMap
virtual void emitErrorCall(CodeGenFunction &CGF, SourceLocation Loc, Expr *ME, bool IsFatal)
Emit __kmpc_error call for error directive extern void __kmpc_error(ident_t *loc, int severity,...
void clearLocThreadIdInsertPt(CodeGenFunction &CGF)
virtual void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc)
Emits code for a taskyield directive.
std::string getName(ArrayRef< StringRef > Parts) const
Get the platform-specific name separator.
QualType KmpRoutineEntryPtrQTy
void computeMinAndMaxThreadsAndTeams(const OMPExecutableDirective &D, CodeGenFunction &CGF, llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs)
Helper to determine the min/max number of threads/teams for D.
virtual void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO)
Emit flush of the variables specified in 'omp flush' directive.
virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPTaskDataTy &Data)
Emit code for 'taskwait' directive.
virtual void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc)
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32global_tid, int proc_bind) to generate...
void emitLastprivateConditionalUpdate(CodeGenFunction &CGF, LValue IVLVal, StringRef UniqueDeclName, LValue LVal, SourceLocation Loc)
Emit update for lastprivate conditional data.
virtual void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the taskloop directive.
virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false)
Emit an implicit/explicit barrier for OpenMP threads.
static unsigned getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind)
Returns default flags for the barriers depending on the directive, for which this barier is going to ...
virtual bool emitTargetFunctions(GlobalDecl GD)
Emit the target regions enclosed in GD function definition or the function itself in case it is a val...
TaskResultTy emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const OMPTaskDataTy &Data)
Emit task region for the task directive.
llvm::Value * emitTargetNumIterationsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Return the trip count of loops associated with constructs / 'target teams distribute' and 'teams dist...
llvm::StringMap< llvm::AssertingVH< llvm::GlobalVariable >, llvm::BumpPtrAllocator > InternalVars
An ordered map of auto-generated variables to their unique names.
virtual void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values)
llvm::SmallVector< UntiedLocalVarsAddressesMap, 4 > UntiedLocalVarsStack
virtual void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind)
Call the appropriate runtime routine to notify that we finished all the work with current loop.
virtual void emitThreadLimitClause(CodeGenFunction &CGF, const Expr *ThreadLimit, SourceLocation Loc)
Emits call to void __kmpc_set_thread_limit(ident_t *loc, kmp_int32global_tid, kmp_int32 thread_limit)...
void emitIfClause(CodeGenFunction &CGF, const Expr *Cond, const RegionCodeGenTy &ThenGen, const RegionCodeGenTy &ElseGen)
Emits code for OpenMP 'if' clause using specified CodeGen function.
Address emitDepobjDependClause(CodeGenFunction &CGF, const OMPTaskDataTy::DependData &Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs) for depob...
bool isNontemporalDecl(const ValueDecl *VD) const
Checks if the VD variable is marked as nontemporal declaration in current context.
virtual llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP parallel directive D.
const Expr * getNumThreadsExprForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D, int32_t &UpperBound, bool UpperBoundOnly, llvm::Value **CondExpr=nullptr, const Expr **ThreadLimitExpr=nullptr)
Check for a number of threads upper bound constant value (stored in UpperBound), or expression (retur...
virtual llvm::Value * emitSeverityClause(OpenMPSeverityClauseKind Severity, SourceLocation Loc)
llvm::SmallVector< LastprivateConditionalData, 4 > LastprivateConditionalStack
Stack for list of addresses of declarations in current context marked as lastprivate conditional.
virtual void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values)
Call the appropriate runtime routine to initialize it before start of loop.
virtual void emitDeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn)
Marks function Fn with properly mangled versions of vector functions.
llvm::AtomicOrdering getDefaultMemoryOrdering() const
Gets default memory ordering as specified in requires directive.
virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static non-chunked.
llvm::Value * getCriticalRegionLock(StringRef CriticalName)
Returns corresponding lock object for the specified critical region name.
virtual void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, const Expr *IfCond, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancel' construct.
QualType SavedKmpTaskTQTy
Saved kmp_task_t for task directive.
virtual void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc)
Emits a master region.
virtual llvm::Function * emitTaskOutlinedFunction(const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, const VarDecl *PartIDVar, const VarDecl *TaskTVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool Tied, unsigned &NumberOfParts)
Emits outlined function for the OpenMP task directive D.
llvm::DenseMap< llvm::Function *, unsigned > FunctionToUntiedTaskStackMap
Maps function to the position of the untied task locals stack.
void emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Emits the code to destroy the dependency object provided in depobj directive.
virtual void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Required to resolve existing problems in the runtime.
llvm::ArrayType * KmpCriticalNameTy
Type kmp_critical_name, originally defined as typedef kmp_int32 kmp_critical_name[8];.
virtual void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C)
Emit code for doacross ordered directive with 'depend' clause.
llvm::DenseMap< const OMPDeclareMapperDecl *, llvm::Function * > UDMMap
Map from the user-defined mapper declaration to its corresponding functions.
virtual void checkAndEmitLastprivateConditional(CodeGenFunction &CGF, const Expr *LHS)
Checks if the provided LVal is lastprivate conditional and emits the code to update the value of the ...
std::pair< llvm::Value *, LValue > getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Returns the number of the elements and the address of the depobj dependency array.
llvm::SmallDenseSet< const VarDecl * > DeferredGlobalVariables
List of variables that can become declare target implicitly and, thus, must be emitted.
void emitUsesAllocatorsInit(CodeGenFunction &CGF, const Expr *Allocator, const Expr *AllocatorTraits)
Initializes user defined allocators specified in the uses_allocators clauses.
llvm::Type * KmpRoutineEntryPtrTy
Type typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *);.
llvm::Type * getIdentTyPointerTy()
Returns pointer to ident_t type.
void emitSingleReductionCombiner(CodeGenFunction &CGF, const Expr *ReductionOp, const Expr *PrivateRef, const DeclRefExpr *LHS, const DeclRefExpr *RHS)
Emits single reduction combiner.
llvm::OpenMPIRBuilder & getOMPBuilder()
virtual void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Emit outilined function for 'target' directive.
virtual void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr)
Emits a critical region.
virtual void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned)
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
virtual void emitOutlinedFunctionCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, ArrayRef< llvm::Value * > Args={}) const
Emits call of the outlined function with the provided arguments, translating these arguments to corre...
llvm::Value * emitNumThreadsForTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &D)
Emit an expression that denotes the number of threads a target region shall use.
void emitThreadPrivateVarInit(CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc)
Emits initialization code for the threadprivate variables.
virtual void emitUserDefinedReduction(CodeGenFunction *CGF, const OMPDeclareReductionDecl *D)
Emit code for the specified user defined reduction construct.
virtual void checkAndEmitSharedLastprivateConditional(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::DenseSet< CanonicalDeclPtr< const VarDecl > > &IgnoredDecls)
Checks if the lastprivate conditional was updated in inner region and writes the value.
QualType KmpDimTy
struct kmp_dim { // loop bounds info casted to kmp_int64 kmp_int64 lo; // lower kmp_int64 up; // uppe...
virtual void emitInlinedDirective(CodeGenFunction &CGF, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool HasCancel=false)
Emit code for the directive that does not require outlining.
virtual void registerTargetGlobalVariable(const VarDecl *VD, llvm::Constant *Addr)
Checks if the provided global decl GD is a declare target variable and registers it when emitting cod...
virtual void emitFunctionProlog(CodeGenFunction &CGF, const Decl *D)
Emits OpenMP-specific function prolog.
void emitKmpRoutineEntryT(QualType KmpInt32Ty)
Build type kmp_routine_entry_t (if not built yet).
virtual bool isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static chunked.
virtual void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Emit the target offloading code associated with D.
virtual bool hasAllocateAttributeForGlobalVar(const VarDecl *VD, LangAS &AS)
Checks if the variable has associated OMPAllocateDeclAttr attribute with the predefined allocator and...
llvm::AtomicOrdering RequiresAtomicOrdering
Atomic ordering from the omp requires directive.
virtual void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps, ReductionOptionsTy Options)
Emit a code for reduction clause.
std::pair< llvm::Value *, Address > emitDependClause(CodeGenFunction &CGF, ArrayRef< OMPTaskDataTy::DependData > Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs).
llvm::StringMap< llvm::WeakTrackingVH > EmittedNonTargetVariables
List of the global variables with their addresses that should not be emitted for the target.
virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const
Check if the specified ScheduleKind is dynamic.
Address emitLastprivateConditionalInit(CodeGenFunction &CGF, const VarDecl *VD)
Create specialized alloca to handle lastprivate conditionals.
virtual void emitOrderedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &OrderedOpGen, SourceLocation Loc, bool IsThreads)
Emit an ordered region.
virtual Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD)
Gets the OpenMP-specific address of the local variable.
virtual void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, bool IsWorksharingReduction)
Emits the following code for reduction clause with task modifier:
virtual void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr)
Emits a masked region.
QualType KmpDependInfoTy
Type typedef struct kmp_depend_info { kmp_intptr_t base_addr; size_t len; struct { bool in:1; bool ou...
llvm::Function * emitReductionFunction(StringRef ReducerName, SourceLocation Loc, llvm::Type *ArgsElemType, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps)
Emits reduction function.
virtual void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues)
Call the appropriate runtime routine to initialize it before start of loop.
Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal) override
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
void emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr) override
Emits a critical region.
void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) override
void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) override
Call the appropriate runtime routine to initialize it before start of loop.
bool emitTargetGlobalVariable(GlobalDecl GD) override
Emit the global variable if it is a valid device global variable.
llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST) override
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
llvm::Function * emitThreadPrivateVarDefinition(const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, CodeGenFunction *CGF=nullptr) override
Emit a code for initialization of threadprivate variable.
void emitTargetDataStandAloneCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device) override
Emit the data mapping/movement code associated with the directive D that should be of the form 'targe...
llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) override
Emits outlined function for the specified OpenMP teams directive D.
void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr) override
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps, ReductionOptionsTy Options) override
Emit a code for reduction clause.
void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO) override
Emit flush of the variables specified in 'omp flush' directive.
void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C) override
Emit code for doacross ordered directive with 'depend' clause.
void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc) override
Emits a masked region.
Address getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, QualType VarType, StringRef Name) override
Creates artificial threadprivate variable with name Name and type VarType.
Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc) override
Returns address of the threadprivate variable for the current thread.
void emitSingleRegion(CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps) override
Emits a single region.
void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N) override
Required to resolve existing problems in the runtime.
llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) override
Emits outlined function for the specified OpenMP parallel directive D.
void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind CancelRegion) override
Emit code for 'cancellation point' construct.
void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false) override
Emit an implicit/explicit barrier for OpenMP threads.
Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const override
Gets the address of the native argument basing on the address of the target-specific parameter.
void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars) override
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned) override
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
bool emitTargetGlobal(GlobalDecl GD) override
Emit the global GD if it is meaningful for the target.
void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, bool IsWorksharingReduction) override
Emits the following code for reduction clause with task modifier:
void emitOrderedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &OrderedOpGen, SourceLocation Loc, bool IsThreads) override
Emit an ordered region.
void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind) override
Call the appropriate runtime routine to notify that we finished all the work with current loop.
llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data) override
Emit a code for initialization of task reduction clause.
void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc) override
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32global_tid, int proc_bind) to generate...
void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) override
Emit outilined function for 'target' directive.
void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc) override
Emits a master region.
void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc) override
Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32global_tid, kmp_int32 num_teams,...
void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc) override
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
const VarDecl * translateParameter(const FieldDecl *FD, const VarDecl *NativeParam) const override
Translates the native parameter of outlined function if this is required for target.
void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, SourceLocation SeverityLoc=SourceLocation(), const Expr *Message=nullptr, SourceLocation MessageLoc=SourceLocation()) override
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_tid, kmp_int32 num_threads) ...
void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr) override
Emits a masked region.
void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data) override
Emit task region for the task directive.
void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter) override
Emit the target offloading code associated with D.
bool emitTargetFunctions(GlobalDecl GD) override
Emit the target regions enclosed in GD function definition or the function itself in case it is a val...
void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef< Expr * > NumIterations) override
Emit initialization for doacross loop nesting support.
void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, const Expr *IfCond, OpenMPDirectiveKind CancelRegion) override
Emit code for 'cancel' construct.
void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPTaskDataTy &Data) override
Emit code for 'taskwait' directive.
void emitTaskgroupRegion(CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, SourceLocation Loc) override
Emit a taskgroup region.
void emitTargetDataCalls(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device, const RegionCodeGenTy &CodeGen, CGOpenMPRuntime::TargetDataInfo &Info) override
Emit the target data mapping code associated with D.
void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues) override
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
llvm::Function * emitTaskOutlinedFunction(const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, const VarDecl *PartIDVar, const VarDecl *TaskTVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool Tied, unsigned &NumberOfParts) override
Emits outlined function for the OpenMP task directive D.
void emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data) override
Emit task region for the taskloop directive.
unsigned getNonVirtualBaseLLVMFieldNo(const CXXRecordDecl *RD) const
llvm::StructType * getLLVMType() const
Return the "complete object" LLVM type associated with this record.
llvm::StructType * getBaseSubobjectLLVMType() const
Return the "base subobject" LLVM type associated with this record.
unsigned getLLVMFieldNo(const FieldDecl *FD) const
Return llvm::StructType element number that corresponds to the field FD.
unsigned getVirtualBaseIndex(const CXXRecordDecl *base) const
Return the LLVM field index corresponding to the given virtual base.
API for captured statement code generation.
virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S)
Emit the captured statement body.
virtual const FieldDecl * lookup(const VarDecl *VD) const
Lookup the captured field decl for a variable.
RAII for correct setting/restoring of CapturedStmtInfo.
The scope used to remap some variables as private in the OpenMP loop body (or other captured region e...
bool Privatize()
Privatizes local variables previously registered as private.
bool addPrivate(const VarDecl *LocalVD, Address Addr)
Registers LocalVD variable as a private with Addr as the address of the corresponding private variabl...
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
LValue EmitLoadOfReferenceLValue(LValue RefLVal)
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr, const VarDecl *ConditionalDecl=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
void emitDestroy(Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray)
emitDestroy - Immediately perform the destruction of the given object.
JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target)
The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...
static void EmitOMPTargetParallelDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelDirective &S)
void EmitNullInitialization(Address DestPtr, QualType Ty)
EmitNullInitialization - Generate code to set a value of the given type to null, If the type contains...
Address LoadCXXThisAddress()
CGCapturedStmtInfo * CapturedStmtInfo
ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc)
EmitLoadOfComplex - Load a complex number from the specified l-value.
static void EmitOMPTargetDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetDirective &S)
Emit device code for the target directive.
static void EmitOMPTargetTeamsDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDirective &S)
Emit device code for the target teams directive.
static void EmitOMPTargetTeamsDistributeDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeDirective &S)
Emit device code for the target teams distribute directive.
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
const LangOptions & getLangOpts() const
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
EmitAutoVarAlloca - Emit the alloca and debug information for a local variable.
void pushDestroy(QualType::DestructionKind dtorKind, Address addr, QualType type)
pushDestroy - Push the standard destructor for the given type as at least a normal cleanup.
Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr)
Load a pointer with type PtrTy stored at address Ptr.
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
Destroyer * getDestroyer(QualType::DestructionKind destructionKind)
llvm::AssertingVH< llvm::Instruction > AllocaInsertPt
AllocaInsertPoint - This is an instruction in the entry block before which we prefer to insert alloca...
void EmitAggregateAssign(LValue Dest, LValue Src, QualType EltTy)
Emit an aggregate assignment.
JumpDest ReturnBlock
ReturnBlock - Unified return block.
void EmitAggregateCopy(LValue Dest, LValue Src, QualType EltTy, AggValueSlot::Overlap_t MayOverlap, bool isVolatile=false)
EmitAggregateCopy - Emit an aggregate copy.
LValue EmitLValueForField(LValue Base, const FieldDecl *Field, bool IsInBounds=true)
RawAddress CreateDefaultAlignTempAlloca(llvm::Type *Ty, const Twine &Name="tmp")
CreateDefaultAlignedTempAlloca - This creates an alloca with the default ABI alignment of the given L...
void GenerateOpenMPCapturedVars(const CapturedStmt &S, SmallVectorImpl< llvm::Value * > &CapturedVars)
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
LValue EmitArraySectionExpr(const ArraySectionExpr *E, bool IsLowerBound=true)
LValue EmitOMPSharedLValue(const Expr *E)
Emits the lvalue for the expression with possibly captured variable.
void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())
Emit code for the start of a function.
void EmitOMPCopy(QualType OriginalType, Address DestAddr, Address SrcAddr, const VarDecl *DestVD, const VarDecl *SrcVD, const Expr *Copy)
Emit proper copying of data from one variable to another.
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
JumpDest getOMPCancelDestination(OpenMPDirectiveKind Kind)
llvm::Value * emitArrayLength(const ArrayType *arrayType, QualType &baseType, Address &addr)
emitArrayLength - Compute the length of an array, even if it's a VLA, and drill down to the base elem...
void EmitOMPAggregateAssign(Address DestAddr, Address SrcAddr, QualType OriginalType, const llvm::function_ref< void(Address, Address)> CopyGen)
Perform element by element copying of arrays with type OriginalType from SrcAddr to DestAddr using co...
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
CGDebugInfo * getDebugInfo()
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
LValue MakeRawAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment, AlignmentSource Source=AlignmentSource::Type)
Same as MakeAddrLValue above except that the pointer is known to be unsigned.
LValue EmitLValueForFieldInitialization(LValue Base, const FieldDecl *Field)
EmitLValueForFieldInitialization - Like EmitLValueForField, except that if the Field is a reference,...
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
VlaSizePair getVLASize(const VariableArrayType *vla)
Returns an LLVM value that corresponds to the size, in non-variably-sized elements,...
llvm::CallInst * EmitNounwindRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
ASTContext & getContext() const
llvm::Value * EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, AlignmentSource Source=AlignmentSource::Type, bool isNontemporal=false)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
void EmitAutoVarCleanups(const AutoVarEmission &emission)
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
LValue EmitLoadOfPointerLValue(Address Ptr, const PointerType *PtrTy)
void EmitAnyExprToMem(const Expr *E, Address Location, Qualifiers Quals, bool IsInitializer)
EmitAnyExprToMem - Emits the code necessary to evaluate an arbitrary expression into the given memory...
bool needsEHCleanup(QualType::DestructionKind kind)
Determines whether an EH cleanup is required to destroy a type with the given destruction kind.
llvm::DenseMap< const ValueDecl *, FieldDecl * > LambdaCaptureFields
llvm::CallInst * EmitRuntimeCall(llvm::FunctionCallee callee, const Twine &name="")
llvm::Type * ConvertTypeForMem(QualType T)
static void EmitOMPTargetTeamsDistributeParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForDirective &S)
static void EmitOMPTargetParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForSimdDirective &S)
Emit device code for the target parallel for simd directive.
CodeGenTypes & getTypes() const
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
void EmitOMPTargetTaskBasedDirective(const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen, OMPTargetDataInfo &InputInfo)
Address EmitPointerWithAlignment(const Expr *Addr, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitPointerWithAlignment - Given an expression with a pointer type, emit the value and compute our be...
static void EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForSimdDirective &S)
Emit device code for the target teams distribute parallel for simd directive.
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
llvm::Function * GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S, const OMPExecutableDirective &D)
RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
llvm::Value * EmitCheckedInBoundsGEP(llvm::Type *ElemTy, llvm::Value *Ptr, ArrayRef< llvm::Value * > IdxList, bool SignedIndices, bool IsSubtraction, SourceLocation Loc, const Twine &Name="")
Same as IRBuilder::CreateInBoundsGEP, but additionally emits a check to detect undefined behavior whe...
static void EmitOMPTargetParallelGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelGenericLoopDirective &S)
Emit device code for the target parallel loop directive.
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
static bool IsWrappedCXXThis(const Expr *E)
Check if E is a C++ "this" pointer wrapped in value-preserving casts.
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S)
Emit device code for the target simd directive.
static void EmitOMPTargetParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForDirective &S)
Emit device code for the target parallel for directive.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)
ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant,...
static void EmitOMPTargetTeamsGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsGenericLoopDirective &S)
Emit device code for the target teams loop directive.
LValue EmitMemberExpr(const MemberExpr *E)
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
static void EmitOMPTargetTeamsDistributeSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeSimdDirective &S)
Emit device code for the target teams distribute simd directive.
llvm::Value * EmitScalarConversion(llvm::Value *Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified type to the specified destination type, both of which are LLVM s...
void EmitVariablyModifiedType(QualType Ty)
EmitVLASize - Capture all the sizes for the VLA expressions in the given variably-modified type and s...
bool isTrivialInitializer(const Expr *Init)
Determine whether the given initializer is trivial in the sense that it requires no code to be genera...
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
void EmitExprAsInit(const Expr *init, const ValueDecl *D, LValue lvalue, bool capturedByInit)
EmitExprAsInit - Emits the code necessary to initialize a location in memory with the given initializ...
LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T)
This class organizes the cross-function state that is used while generating LLVM code.
void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)
Set the attributes on the LLVM function for the given decl and function info.
llvm::Module & getModule() const
const IntrusiveRefCntPtr< llvm::vfs::FileSystem > & getFileSystem() const
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
CharUnits getNaturalTypeAlignment(QualType T, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, bool forPointeeType=false)
CodeGenTypes & getTypes()
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
TBAAAccessInfo getTBAAInfoForSubobject(LValue Base, QualType AccessType)
getTBAAInfoForSubobject - Get TBAA information for an access with a given base lvalue.
ASTContext & getContext() const
const CodeGenOptions & getCodeGenOpts() const
StringRef getMangledName(GlobalDecl GD)
std::optional< CharUnits > getOMPAllocateAlignment(const VarDecl *VD)
Return the alignment specified in an allocate directive, if present.
llvm::Constant * EmitNullConstant(QualType T)
Return the result of value-initializing the given type, i.e.
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
const CGRecordLayout & getCGRecordLayout(const RecordDecl *)
getCGRecordLayout - Return record layout info for the given record decl.
A specialization of Address that requires the address to be an LLVM Constant.
static ConstantAddress invalid()
bool requiresLandingPad() const
void pushTerminate()
Push a terminate handler on the stack.
void popTerminate()
Pops a terminate handler off the stack.
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
CharUnits getAlignment() const
llvm::Value * getPointer(CodeGenFunction &CGF) const
const Qualifiers & getQuals() const
Address getAddress() const
LValueBaseInfo getBaseInfo() const
TBAAAccessInfo getTBAAInfo() const
A basic class for pre|post-action for advanced codegen sequence for OpenMP region.
virtual void Enter(CodeGenFunction &CGF)
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
static RValue getComplex(llvm::Value *V1, llvm::Value *V2)
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
An abstract representation of an aligned address.
llvm::Type * getElementType() const
Return the type of the values stored in this address.
llvm::Value * getPointer() const
static RawAddress invalid()
Class intended to support codegen of all kind of the reduction clauses.
LValue getSharedLValue(unsigned N) const
Returns LValue for the reduction item.
const Expr * getRefExpr(unsigned N) const
Returns the base declaration of the reduction item.
LValue getOrigLValue(unsigned N) const
Returns LValue for the original reduction item.
bool needCleanups(unsigned N)
Returns true if the private copy requires cleanups.
void emitAggregateType(CodeGenFunction &CGF, unsigned N)
Emits the code for the variable-modified type, if required.
const VarDecl * getBaseDecl(unsigned N) const
Returns the base declaration of the reduction item.
QualType getPrivateType(unsigned N) const
Return the type of the private item.
bool usesReductionInitializer(unsigned N) const
Returns true if the initialization of the reduction item uses initializer from declare reduction cons...
void emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N)
Emits lvalue for the shared and original reduction item.
void emitInitialization(CodeGenFunction &CGF, unsigned N, Address PrivateAddr, Address SharedAddr, llvm::function_ref< bool(CodeGenFunction &)> DefaultInit)
Performs initialization of the private copy for the reduction item.
std::pair< llvm::Value *, llvm::Value * > getSizes(unsigned N) const
Returns the size of the reduction item (in chars and total number of elements in the item),...
ReductionCodeGen(ArrayRef< const Expr * > Shareds, ArrayRef< const Expr * > Origs, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > ReductionOps)
void emitCleanups(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Emits cleanup code for the reduction item.
Address adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Adjusts PrivatedAddr for using instead of the original variable address in normal operations.
Class provides a way to call simple version of codegen for OpenMP region, or an advanced with possibl...
void operator()(CodeGenFunction &CGF) const
void setAction(PrePostActionTy &Action) const
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
void addDecl(Decl *D)
Add the declaration D into this context.
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
SourceLocation getLocation() const
DeclContext * getDeclContext()
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
This represents one expression.
bool isIntegerConstantExpr(const ASTContext &Ctx) const
Expr * IgnoreParenNoopCasts(const ASTContext &Ctx) LLVM_READONLY
Skip past any parentheses and casts which do not change the value (including ptr->int casts of the sa...
@ SE_AllowSideEffects
Allow any unmodeled side effect.
@ SE_AllowUndefinedBehavior
Allow UB that we can give a value, but not arbitrary unmodeled side effects.
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsBooleanCondition - Return true if this is a constant which we can fold and convert to a boo...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
static bool isSameComparisonOperand(const Expr *E1, const Expr *E2)
Checks that the two Expr's will refer to the same value as a comparison operand.
bool hasNonTrivialCall(const ASTContext &Ctx) const
Determine whether this expression involves a call to any function that is not trivial.
Represents a member of a struct/union/class.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
FunctionDecl * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
FunctionDecl * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
GlobalDecl - represents a global declaration.
const Decl * getDecl() const
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, 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'.
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.
Expr * getAssociatedExpression() const
ValueDecl * getAssociatedDeclaration() const
ArrayRef< MappableComponent > MappableExprComponentListRef
static std::pair< const Expr *, std::optional< size_t > > findAttachPtrExpr(MappableExprComponentListRef Components, OpenMPDirectiveKind CurDirKind)
Find the attach pointer expression from a list of mappable expression components.
static QualType getComponentExprElementType(const Expr *Exp)
Get the type of an element of a ComponentList Expr Exp.
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.
Expr * getMapperVarRef()
Get the variable declared in the mapper.
This represents 'pragma omp declare reduction ...' directive.
Expr * getInitializer()
Get initializer expression (if specified) of the declare reduction construct.
Expr * getInitPriv()
Get Priv variable of the initializer.
Expr * getCombinerOut()
Get Out variable of the combiner.
Expr * getCombinerIn()
Get In variable of the combiner.
Expr * getCombiner()
Get combiner expression of the declare reduction construct.
Expr * getInitOrig()
Get Orig variable of the initializer.
OMPDeclareReductionInitKind getInitializerKind() const
Get initializer kind.
This represents implicit clause 'depend' for the 'pragma omp task' directive.
This represents 'detach' clause in the 'pragma omp task' directive.
This represents 'device' clause in the 'pragma omp ...' directive.
This represents the 'doacross' clause for the 'pragma omp ordered' directive.
This represents 'dyn_groupprivate' clause in 'pragma omp target ...' and 'pragma omp teams ....
This represents 'if' clause in the 'pragma omp ...' directive.
Expr * getCondition() const
Returns condition.
This represents clause 'in_reduction' in the 'pragma omp task' directives.
OMPIteratorHelperData & getHelper(unsigned I)
Fetches helper data for the specified iteration space.
unsigned numOfIterators() const
Returns number of iterator definitions.
This represents clause 'lastprivate' 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 'pragma omp requires...' directive.
clauselist_range clauselists()
This represents 'thread_limit' clause in the 'pragma omp ...' directive.
This represents 'threadset' clause in the 'pragma omp task ...' 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
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
static SourceLocation getFromRawEncoding(UIntTy Encoding)
Turn a raw encoding of a SourceLocation object into a real SourceLocation.
bool isValid() const
Return true if this is a valid SourceLocation object.
UIntTy getRawEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it.
This class handles loading and caching of source files into memory.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
Stmt - This represents one statement.
StmtClass getStmtClass() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
SourceLocation getBeginLoc() const LLVM_READONLY
void startDefinition()
Starts the definition of this tag declaration.
The base class of the type hierarchy.
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isPointerType() const
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isLValueReferenceType() const
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
RecordDecl * castAsRecordDecl() const
QualType getCanonicalTypeInternal() const
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
bool isFloatingType() const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
bool isAnyPointerType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
VarDecl * getDefinition(ASTContext &)
Get the real (not just tentative) definition for this declaration.
const Expr * getInit() const
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
@ DeclarationOnly
This declaration is only a declaration.
DefinitionKind hasDefinition(ASTContext &) const
Check whether this variable is defined in this translation unit.
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Represents a C array with a specified size that is not an integer-constant-expression.
Expr * getSizeExpr() const
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
bool isEmptyRecordForLayout(const ASTContext &Context, QualType T)
isEmptyRecordForLayout - Return true iff a structure contains only empty base classes (per isEmptyRec...
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
bool isEmptyFieldForLayout(const ASTContext &Context, const FieldDecl *FD)
isEmptyFieldForLayout - Return true iff the field is "empty", that is, either a zero-width bit-field ...
ComparisonResult
Indicates the result of a tentative comparison.
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool needsTaskBasedThreadLimit(OpenMPDirectiveKind DKind)
Checks if the specified target directive, combined or not, needs task based thread_limit.
@ Ctor_Complete
Complete object ctor.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
@ Conditional
A conditional (?:) operator.
@ ICIS_NoInit
No in-class initializer.
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE()
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
@ Vector
'vector' clause, allowed on 'loop', Combined, and 'routine' directives.
@ Reduction
'reduction' clause, allowed on Parallel, Serial, Loop, and the combined constructs.
@ Present
'present' clause, allowed on Compute and Combined constructs, plus 'data' and 'declare'.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_last
@ OMPC_SCHEDULE_MODIFIER_unknown
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
static bool classof(const Stmt *T)
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
@ OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
const FunctionProtoType * T
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
@ Dtor_Complete
Complete object dtor.
@ Union
The "union" keyword.
bool isOpenMPTargetMapEnteringDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a map-entering target directive.
@ Type
The name was classified as a type.
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
LangAS
Defines the address space values used by the address space qualifier of QualType.
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
for(const auto &A :T->param_types())
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPNumThreadsClauseModifier
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
U cast(CodeGen::Address addr)
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
@ OMPC_MAP_MODIFIER_unknown
@ Other
Other implicit parameter.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
OpenMPThreadsetKind
OpenMP modifiers for 'threadset' clause.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Diagnostic wrappers for TextAPI types for error reporting.
Maps the expression for the lastprivate variable to the global copy used to store new value because o...
llvm::SmallVector< bool, 8 > IsPrivateVarReduction
A jump destination is an abstract label, branching to which may require a jump out through normal cle...
llvm::BasicBlock * getBlock() const
unsigned NumberOfTargetItems
Address BasePointersArray
llvm::PointerType * VoidPtrTy
llvm::IntegerType * Int64Ty
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::CallingConv::ID getRuntimeCC() const
llvm::IntegerType * SizeTy
llvm::PointerType * VoidPtrPtrTy
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntPtrTy
llvm::IntegerType * IntTy
int
CharUnits getPointerAlign() const
OpenMPDependClauseKind DepKind
const Expr * IteratorExpr
SmallVector< const Expr *, 4 > DepExprs
EvalResult is a struct with detailed info about an evaluated expression.
Extra information about a function prototype.
Expr * CounterUpdate
Updater for the internal counter: ++CounterVD;.
Data for list of allocators.
Expr * AllocatorTraits
Allocator traits.
Expr * Allocator
Allocator.
Scheduling data for loop-based OpenMP directives.
OpenMPScheduleClauseModifier M2
OpenMPScheduleClauseModifier M1
OpenMPScheduleClauseKind Schedule
Describes how types, statements, expressions, and declarations should be printed.