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::getSigned(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) {}
7190 llvm::PointerUnion<
const OMPExecutableDirective *,
7191 const OMPDeclareMapperDecl *>
7195 CodeGenFunction &CGF;
7200 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
bool> FirstPrivateDecls;
7203 llvm::SmallSet<OpenMPDefaultmapClauseKind, 4> DefaultmapFirstprivateKinds;
7209 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7216 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7220 llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap;
7235 llvm::DenseMap<const Expr *, std::optional<size_t>>
7236 AttachPtrComponentDepthMap = {{
nullptr, std::nullopt}};
7240 llvm::DenseMap<const Expr *, size_t> AttachPtrComputationOrderMap = {
7245 AttachPtrExprComparator AttachPtrComparator;
7247 llvm::Value *getExprTypeSize(
const Expr *E)
const {
7251 if (
const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) {
7253 CGF.
getTypeSize(OAE->getBase()->getType()->getPointeeType());
7254 for (
const Expr *SE : OAE->getDimensions()) {
7265 if (
const auto *RefTy = ExprTy->
getAs<ReferenceType>())
7271 if (
const auto *OAE = dyn_cast<ArraySectionExpr>(E)) {
7273 OAE->getBase()->IgnoreParenImpCasts())
7279 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7280 !OAE->getLowerBound())
7283 llvm::Value *ElemSize;
7284 if (
const auto *PTy = BaseTy->
getAs<PointerType>()) {
7285 ElemSize = CGF.
getTypeSize(PTy->getPointeeType().getCanonicalType());
7288 assert(ATy &&
"Expecting array type if not a pointer type.");
7289 ElemSize = CGF.
getTypeSize(ATy->getElementType().getCanonicalType());
7294 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
7297 if (
const Expr *LenExpr = OAE->getLength()) {
7301 LenExpr->getExprLoc());
7302 return CGF.
Builder.CreateNUWMul(LengthVal, ElemSize);
7304 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7305 OAE->getLowerBound() &&
"expected array_section[lb:].");
7311 OAE->getLowerBound()->getExprLoc());
7312 LBVal = CGF.
Builder.CreateNUWMul(LBVal, ElemSize);
7313 llvm::Value *Cmp = CGF.
Builder.CreateICmpUGT(LengthVal, LBVal);
7314 llvm::Value *TrueVal = CGF.
Builder.CreateNUWSub(LengthVal, LBVal);
7315 LengthVal = CGF.
Builder.CreateSelect(
7316 Cmp, TrueVal, llvm::ConstantInt::get(CGF.
SizeTy, 0));
7326 OpenMPOffloadMappingFlags getMapTypeBits(
7328 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
bool IsImplicit,
7329 bool AddPtrFlag,
bool AddIsTargetParamFlag,
bool IsNonContiguous)
const {
7330 OpenMPOffloadMappingFlags Bits =
7331 IsImplicit ? OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT
7332 : OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7334 case OMPC_MAP_alloc:
7335 case OMPC_MAP_release:
7342 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO;
7345 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7347 case OMPC_MAP_tofrom:
7348 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO |
7349 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7351 case OMPC_MAP_delete:
7352 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
7355 llvm_unreachable(
"Unexpected map type!");
7358 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
7359 if (AddIsTargetParamFlag)
7360 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7361 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_always))
7362 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7363 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_close))
7364 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
7365 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_present) ||
7366 llvm::is_contained(MotionModifiers, OMPC_MOTION_MODIFIER_present))
7367 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
7368 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold))
7369 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
7370 if (IsNonContiguous)
7371 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG;
7377 bool isFinalArraySectionExpression(
const Expr *E)
const {
7378 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
7385 if (OASE->getColonLocFirst().isInvalid())
7388 const Expr *Length = OASE->getLength();
7395 OASE->getBase()->IgnoreParenImpCasts())
7397 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
7398 return ATy->getSExtSize() != 1;
7410 llvm::APSInt ConstLength =
Result.Val.getInt();
7411 return ConstLength.getSExtValue() != 1;
7418 void emitAttachEntry(CodeGenFunction &CGF, MapCombinedInfoTy &CombinedInfo,
7419 const AttachInfoTy &AttachInfo)
const {
7420 assert(AttachInfo.isValid() &&
7421 "Expected valid attach pointer/pointee information!");
7425 llvm::Value *PointerSize = CGF.
Builder.CreateIntCast(
7426 llvm::ConstantInt::get(
7432 CombinedInfo.Exprs.emplace_back(AttachInfo.AttachPtrDecl,
7433 AttachInfo.AttachMapExpr);
7434 CombinedInfo.BasePointers.push_back(
7435 AttachInfo.AttachPtrAddr.emitRawPointer(CGF));
7436 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7437 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7438 CombinedInfo.Pointers.push_back(
7439 AttachInfo.AttachPteeAddr.emitRawPointer(CGF));
7440 CombinedInfo.Sizes.push_back(PointerSize);
7441 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
7442 CombinedInfo.Mappers.push_back(
nullptr);
7443 CombinedInfo.NonContigInfo.Dims.push_back(1);
7450 class CopyOverlappedEntryGaps {
7451 CodeGenFunction &CGF;
7452 MapCombinedInfoTy &CombinedInfo;
7453 OpenMPOffloadMappingFlags Flags = OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7454 const ValueDecl *MapDecl =
nullptr;
7455 const Expr *MapExpr =
nullptr;
7457 bool IsNonContiguous =
false;
7461 const RecordDecl *LastParent =
nullptr;
7463 unsigned LastIndex = -1u;
7467 CopyOverlappedEntryGaps(CodeGenFunction &CGF,
7468 MapCombinedInfoTy &CombinedInfo,
7469 OpenMPOffloadMappingFlags Flags,
7470 const ValueDecl *MapDecl,
const Expr *MapExpr,
7471 Address BP, Address LB,
bool IsNonContiguous,
7473 : CGF(CGF), CombinedInfo(CombinedInfo), Flags(Flags), MapDecl(MapDecl),
7474 MapExpr(MapExpr), BP(BP), IsNonContiguous(IsNonContiguous),
7475 DimSize(DimSize), LB(LB) {}
7478 const OMPClauseMappableExprCommon::MappableComponent &MC,
7479 const FieldDecl *FD,
7480 llvm::function_ref<LValue(CodeGenFunction &,
const MemberExpr *)>
7481 EmitMemberExprBase) {
7491 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
7503 copyUntilField(FD, ComponentLB);
7506 if (((int64_t)FieldOffset - (int64_t)Cursor) > 0)
7507 copyUntilField(FD, ComponentLB);
7509 Cursor = FieldOffset + FieldSize;
7514 void copyUntilField(
const FieldDecl *FD, Address ComponentLB) {
7518 CGF.
Builder.CreatePtrDiff(CGF.
Int8Ty, ComponentLBPtr, LBPtr);
7519 copySizedChunk(LBPtr, Size);
7522 void copyUntilEnd(Address HB) {
7524 const ASTRecordLayout &RL =
7533 copySizedChunk(LBPtr, Size);
7536 void copySizedChunk(llvm::Value *Base, llvm::Value *Size) {
7537 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7539 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7540 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7541 CombinedInfo.Pointers.push_back(Base);
7542 CombinedInfo.Sizes.push_back(
7544 CombinedInfo.Types.push_back(Flags);
7545 CombinedInfo.Mappers.push_back(
nullptr);
7546 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1);
7555 void generateInfoForComponentList(
7557 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7559 MapCombinedInfoTy &CombinedInfo,
7560 MapCombinedInfoTy &StructBaseCombinedInfo,
7561 StructRangeInfoTy &PartialStruct, AttachInfoTy &AttachInfo,
7562 bool IsFirstComponentList,
bool IsImplicit,
7563 bool GenerateAllInfoForClauses,
const ValueDecl *Mapper =
nullptr,
7564 bool ForDeviceAddr =
false,
const ValueDecl *BaseDecl =
nullptr,
7565 const Expr *MapExpr =
nullptr,
7566 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7567 OverlappedElements = {})
const {
7785 bool IsCaptureFirstInfo = IsFirstComponentList;
7789 bool RequiresReference =
false;
7792 auto CI = Components.rbegin();
7793 auto CE = Components.rend();
7798 bool IsExpressionFirstInfo =
true;
7799 bool FirstPointerInComplexData =
false;
7802 const Expr *AssocExpr = I->getAssociatedExpression();
7803 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7804 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
7805 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
7808 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
7809 auto [AttachPtrAddr, AttachPteeBaseAddr] =
7810 getAttachPtrAddrAndPteeBaseAddr(AttachPtrExpr, CGF);
7812 bool HasAttachPtr = AttachPtrExpr !=
nullptr;
7813 bool FirstComponentIsForAttachPtr = AssocExpr == AttachPtrExpr;
7814 bool SeenAttachPtr = FirstComponentIsForAttachPtr;
7816 if (FirstComponentIsForAttachPtr) {
7824 }
else if ((AE &&
isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7838 if (
const auto *VD =
7839 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7840 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
7841 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7842 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7843 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
7844 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
7846 RequiresReference =
true;
7856 I->getAssociatedDeclaration()->
getType().getNonReferenceType();
7861 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
7863 !VD || VD->hasLocalStorage() || HasAttachPtr)
7866 FirstPointerInComplexData =
true;
7885 bool ShouldBeMemberOf =
false;
7894 const MemberExpr *EncounteredME =
nullptr;
7906 bool IsNonContiguous =
7907 CombinedInfo.NonContigInfo.IsNonContiguous ||
7908 any_of(Components, [&](
const auto &Component) {
7910 dyn_cast<ArraySectionExpr>(Component.getAssociatedExpression());
7914 const Expr *StrideExpr = OASE->getStride();
7918 const auto Constant =
7923 return !Constant->isOne();
7926 bool IsPrevMemberReference =
false;
7928 bool IsPartialMapped =
7929 !PartialStruct.PreliminaryMapData.BasePointers.empty();
7936 bool IsMappingWholeStruct =
true;
7937 if (!GenerateAllInfoForClauses) {
7938 IsMappingWholeStruct =
false;
7940 for (
auto TempI = I; TempI != CE; ++TempI) {
7941 const MemberExpr *PossibleME =
7942 dyn_cast<MemberExpr>(TempI->getAssociatedExpression());
7944 IsMappingWholeStruct =
false;
7950 bool SeenFirstNonBinOpExprAfterAttachPtr =
false;
7951 for (; I != CE; ++I) {
7954 if (HasAttachPtr && !SeenAttachPtr) {
7955 SeenAttachPtr = I->getAssociatedExpression() == AttachPtrExpr;
7962 if (HasAttachPtr && !SeenFirstNonBinOpExprAfterAttachPtr) {
7963 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
7968 SeenFirstNonBinOpExprAfterAttachPtr =
true;
7969 BP = AttachPteeBaseAddr;
7973 if (!EncounteredME) {
7974 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
7977 if (EncounteredME) {
7978 ShouldBeMemberOf =
true;
7981 if (FirstPointerInComplexData) {
7982 QualType Ty = std::prev(I)
7983 ->getAssociatedDeclaration()
7985 .getNonReferenceType();
7987 FirstPointerInComplexData =
false;
7992 auto Next = std::next(I);
8002 bool IsFinalArraySection =
8004 isFinalArraySectionExpression(I->getAssociatedExpression());
8008 const ValueDecl *MapDecl = (I->getAssociatedDeclaration())
8009 ? I->getAssociatedDeclaration()
8011 MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression()
8018 dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
8020 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
8021 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
8022 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
8028 I->getAssociatedExpression()->getType()->isAnyPointerType();
8029 bool IsMemberReference =
isa<MemberExpr>(I->getAssociatedExpression()) &&
8032 bool IsNonDerefPointer = IsPointer &&
8033 !(UO && UO->getOpcode() != UO_Deref) && !BO &&
8039 if (
Next == CE || IsMemberReference || IsNonDerefPointer ||
8040 IsFinalArraySection) {
8043 assert((
Next == CE ||
8050 "Unexpected expression");
8054 auto &&EmitMemberExprBase = [](CodeGenFunction &CGF,
8055 const MemberExpr *E) {
8056 const Expr *BaseExpr = E->getBase();
8061 LValueBaseInfo BaseInfo;
8062 TBAAAccessInfo TBAAInfo;
8076 OAShE->getBase()->getType()->getPointeeType()),
8078 OAShE->getBase()->getType()));
8079 }
else if (IsMemberReference) {
8081 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
8096 FinalLowestElem = LowestElem;
8101 bool IsMemberPointerOrAddr =
8103 (((IsPointer || ForDeviceAddr) &&
8104 I->getAssociatedExpression() == EncounteredME) ||
8105 (IsPrevMemberReference && !IsPointer) ||
8106 (IsMemberReference &&
Next != CE &&
8107 !
Next->getAssociatedExpression()->getType()->isPointerType()));
8108 if (!OverlappedElements.empty() &&
Next == CE) {
8110 assert(!PartialStruct.Base.isValid() &&
"The base element is set.");
8111 assert(!IsPointer &&
8112 "Unexpected base element with the pointer type.");
8115 PartialStruct.LowestElem = {0, LowestElem};
8117 I->getAssociatedExpression()->getType());
8122 PartialStruct.HighestElem = {
8123 std::numeric_limits<
decltype(
8124 PartialStruct.HighestElem.first)>
::max(),
8126 PartialStruct.Base = BP;
8127 PartialStruct.LB = LB;
8129 PartialStruct.PreliminaryMapData.BasePointers.empty() &&
8130 "Overlapped elements must be used only once for the variable.");
8131 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo);
8133 OpenMPOffloadMappingFlags Flags =
8134 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8135 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
8137 false, IsNonContiguous);
8138 CopyOverlappedEntryGaps CopyGaps(CGF, CombinedInfo, Flags, MapDecl,
8139 MapExpr, BP, LB, IsNonContiguous,
8143 Component : OverlappedElements) {
8144 for (
const OMPClauseMappableExprCommon::MappableComponent &MC :
8147 if (
const auto *FD = dyn_cast<FieldDecl>(VD)) {
8148 CopyGaps.processField(MC, FD, EmitMemberExprBase);
8153 CopyGaps.copyUntilEnd(HB);
8156 llvm::Value *
Size = getExprTypeSize(I->getAssociatedExpression());
8163 if ((!IsMemberPointerOrAddr && !IsPartialMapped) ||
8165 if (!IsMappingWholeStruct) {
8166 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8168 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8169 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8171 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8173 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
8176 StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8177 StructBaseCombinedInfo.BasePointers.push_back(
8179 StructBaseCombinedInfo.DevicePtrDecls.push_back(
nullptr);
8180 StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8181 StructBaseCombinedInfo.Pointers.push_back(LB.
emitRawPointer(CGF));
8182 StructBaseCombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8184 StructBaseCombinedInfo.NonContigInfo.Dims.push_back(
8185 IsNonContiguous ? DimSize : 1);
8189 bool HasMapper = Mapper &&
Next == CE;
8190 if (!IsMappingWholeStruct)
8191 CombinedInfo.Mappers.push_back(HasMapper ? Mapper :
nullptr);
8193 StructBaseCombinedInfo.Mappers.push_back(HasMapper ? Mapper
8200 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
8201 MapType, MapModifiers, MotionModifiers, IsImplicit,
8202 !IsExpressionFirstInfo || RequiresReference ||
8203 FirstPointerInComplexData || IsMemberReference,
8204 IsCaptureFirstInfo && !RequiresReference, IsNonContiguous);
8206 if (!IsExpressionFirstInfo || IsMemberReference) {
8209 if (IsPointer || (IsMemberReference &&
Next != CE))
8210 Flags &= ~(OpenMPOffloadMappingFlags::OMP_MAP_TO |
8211 OpenMPOffloadMappingFlags::OMP_MAP_FROM |
8212 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
8213 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
8214 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
8216 if (ShouldBeMemberOf) {
8219 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
8222 ShouldBeMemberOf =
false;
8226 if (!IsMappingWholeStruct)
8227 CombinedInfo.Types.push_back(Flags);
8229 StructBaseCombinedInfo.Types.push_back(Flags);
8235 if (EncounteredME) {
8240 if (!PartialStruct.Base.isValid()) {
8241 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8242 if (IsFinalArraySection && OASE) {
8246 PartialStruct.HighestElem = {FieldIndex, HB};
8248 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8250 PartialStruct.Base = BP;
8251 PartialStruct.LB = BP;
8252 }
else if (FieldIndex < PartialStruct.LowestElem.first) {
8253 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8254 }
else if (FieldIndex > PartialStruct.HighestElem.first) {
8255 if (IsFinalArraySection && OASE) {
8259 PartialStruct.HighestElem = {FieldIndex, HB};
8261 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8267 if (IsFinalArraySection || IsNonContiguous)
8268 PartialStruct.IsArraySection =
true;
8271 if (IsFinalArraySection)
8276 BP = IsMemberReference ? LowestElem : LB;
8277 if (!IsPartialMapped)
8278 IsExpressionFirstInfo =
false;
8279 IsCaptureFirstInfo =
false;
8280 FirstPointerInComplexData =
false;
8281 IsPrevMemberReference = IsMemberReference;
8282 }
else if (FirstPointerInComplexData) {
8283 QualType Ty = Components.rbegin()
8284 ->getAssociatedDeclaration()
8286 .getNonReferenceType();
8288 FirstPointerInComplexData =
false;
8294 PartialStruct.HasCompleteRecord =
true;
8297 if (shouldEmitAttachEntry(AttachPtrExpr, BaseDecl, CGF, CurDir)) {
8298 AttachInfo.AttachPtrAddr = AttachPtrAddr;
8299 AttachInfo.AttachPteeAddr = FinalLowestElem;
8300 AttachInfo.AttachPtrDecl = BaseDecl;
8301 AttachInfo.AttachMapExpr = MapExpr;
8304 if (!IsNonContiguous)
8307 const ASTContext &Context = CGF.
getContext();
8311 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 0)};
8312 MapValuesArrayTy CurCounts = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8313 MapValuesArrayTy CurStrides;
8314 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8320 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8322 const Expr *AssocExpr = Component.getAssociatedExpression();
8323 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8333 assert((VAT || CAT || &Component == &*Components.begin()) &&
8334 "Should be either ConstantArray or VariableArray if not the "
8338 if (CurStrides.empty()) {
8339 const Type *ElementType =
nullptr;
8341 ElementType = CAT->getElementType().getTypePtr();
8343 ElementType = VAT->getElementType().getTypePtr();
8345 assert(&Component == &*Components.begin() &&
8346 "Only expect pointer (non CAT or VAT) when this is the "
8354 if (&Component != &*Components.begin())
8358 CurStrides.push_back(
8359 llvm::ConstantInt::get(CGF.
Int64Ty, ElementTypeSize));
8364 if (DimSizes.size() < Components.size() - 1) {
8367 llvm::ConstantInt::get(CGF.
Int64Ty, CAT->getZExtSize()));
8369 DimSizes.push_back(CGF.
Builder.CreateIntCast(
8376 auto *DI = DimSizes.begin() + 1;
8378 llvm::Value *DimProd =
8379 llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, ElementTypeSize);
8388 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8390 const Expr *AssocExpr = Component.getAssociatedExpression();
8392 if (
const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) {
8393 llvm::Value *Offset = CGF.
Builder.CreateIntCast(
8396 CurOffsets.push_back(Offset);
8397 CurCounts.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 1));
8398 CurStrides.push_back(CurStrides.back());
8402 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8408 const Expr *OffsetExpr = OASE->getLowerBound();
8409 llvm::Value *Offset =
nullptr;
8412 Offset = llvm::ConstantInt::get(CGF.
Int64Ty, 0);
8418 CurOffsets.push_back(Offset);
8421 const Expr *CountExpr = OASE->getLength();
8422 llvm::Value *Count =
nullptr;
8428 if (!OASE->getColonLocFirst().isValid() &&
8429 !OASE->getColonLocSecond().isValid()) {
8430 Count = llvm::ConstantInt::get(CGF.
Int64Ty, 1);
8436 const Expr *StrideExpr = OASE->getStride();
8437 llvm::Value *Stride =
8443 Count = CGF.
Builder.CreateUDiv(
8444 CGF.
Builder.CreateNUWSub(*DI, Offset), Stride);
8446 Count = CGF.
Builder.CreateNUWSub(*DI, Offset);
8452 CurCounts.push_back(Count);
8461 const Expr *StrideExpr = OASE->getStride();
8462 llvm::Value *Stride =
8467 DimProd = CGF.
Builder.CreateNUWMul(DimProd, *(DI - 1));
8469 CurStrides.push_back(CGF.
Builder.CreateNUWMul(DimProd, Stride));
8471 CurStrides.push_back(DimProd);
8472 if (DI != DimSizes.end())
8476 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets);
8477 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts);
8478 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides);
8484 OpenMPOffloadMappingFlags
8485 getMapModifiersForPrivateClauses(
const CapturedStmt::Capture &Cap)
const {
8493 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8494 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
8495 return OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE |
8496 OpenMPOffloadMappingFlags::OMP_MAP_TO;
8499 if (I != LambdasMap.end())
8501 return getMapTypeBits(
8502 I->getSecond()->getMapType(), I->getSecond()->getMapTypeModifiers(),
8503 {}, I->getSecond()->isImplicit(),
8507 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8508 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
8511 void getPlainLayout(
const CXXRecordDecl *RD,
8512 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
8513 bool AsBase)
const {
8516 llvm::StructType *St =
8519 unsigned NumElements = St->getNumElements();
8521 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
8522 RecordLayout(NumElements);
8525 for (
const auto &I : RD->
bases()) {
8529 QualType BaseTy = I.getType();
8540 RecordLayout[FieldIndex] =
Base;
8543 for (
const auto &I : RD->
vbases()) {
8544 QualType BaseTy = I.getType();
8551 if (RecordLayout[FieldIndex])
8553 RecordLayout[FieldIndex] =
Base;
8556 assert(!RD->
isUnion() &&
"Unexpected union.");
8557 for (
const auto *Field : RD->
fields()) {
8560 if (!
Field->isBitField() &&
8563 RecordLayout[FieldIndex] =
Field;
8566 for (
const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
8567 &
Data : RecordLayout) {
8570 if (
const auto *Base = dyn_cast<const CXXRecordDecl *>(
Data))
8571 getPlainLayout(Base, Layout,
true);
8578 static Address getAttachPtrAddr(
const Expr *PointerExpr,
8579 CodeGenFunction &CGF) {
8580 assert(PointerExpr &&
"Cannot get addr from null attach-ptr expr");
8583 if (
auto *DRE = dyn_cast<DeclRefExpr>(PointerExpr)) {
8586 }
else if (
auto *OASE = dyn_cast<ArraySectionExpr>(PointerExpr)) {
8589 }
else if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(PointerExpr)) {
8591 }
else if (
auto *ME = dyn_cast<MemberExpr>(PointerExpr)) {
8593 }
else if (
auto *UO = dyn_cast<UnaryOperator>(PointerExpr)) {
8594 assert(UO->getOpcode() == UO_Deref &&
8595 "Unexpected unary-operator on attach-ptr-expr");
8598 assert(AttachPtrAddr.
isValid() &&
8599 "Failed to get address for attach pointer expression");
8600 return AttachPtrAddr;
8607 static std::pair<Address, Address>
8608 getAttachPtrAddrAndPteeBaseAddr(
const Expr *AttachPtrExpr,
8609 CodeGenFunction &CGF) {
8614 Address AttachPtrAddr = getAttachPtrAddr(AttachPtrExpr, CGF);
8615 assert(AttachPtrAddr.
isValid() &&
"Invalid attach pointer addr");
8617 QualType AttachPtrType =
8622 AttachPtrAddr, AttachPtrType->
castAs<PointerType>());
8623 assert(AttachPteeBaseAddr.
isValid() &&
"Invalid attach pointee base addr");
8625 return {AttachPtrAddr, AttachPteeBaseAddr};
8631 shouldEmitAttachEntry(
const Expr *PointerExpr,
const ValueDecl *MapBaseDecl,
8632 CodeGenFunction &CGF,
8633 llvm::PointerUnion<
const OMPExecutableDirective *,
8634 const OMPDeclareMapperDecl *>
8644 ->getDirectiveKind());
8653 void collectAttachPtrExprInfo(
8655 llvm::PointerUnion<
const OMPExecutableDirective *,
8656 const OMPDeclareMapperDecl *>
8661 ? OMPD_declare_mapper
8664 const auto &[AttachPtrExpr, Depth] =
8668 AttachPtrComputationOrderMap.try_emplace(
8669 AttachPtrExpr, AttachPtrComputationOrderMap.size());
8670 AttachPtrComponentDepthMap.try_emplace(AttachPtrExpr, Depth);
8671 AttachPtrExprMap.try_emplace(Components, AttachPtrExpr);
8679 void generateAllInfoForClauses(
8680 ArrayRef<const OMPClause *> Clauses, MapCombinedInfoTy &CombinedInfo,
8681 llvm::OpenMPIRBuilder &OMPBuilder,
8682 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
8683 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
8688 llvm::MapVector<CanonicalDeclPtr<const Decl>,
8689 SmallVector<SmallVector<MapInfo, 8>, 4>>
8695 [&Info, &SkipVarSet](
8696 const ValueDecl *D, MapKind
Kind,
8699 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8700 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
8701 bool ReturnDevicePointer,
bool IsImplicit,
const ValueDecl *Mapper,
8702 const Expr *VarRef =
nullptr,
bool ForDeviceAddr =
false) {
8703 if (SkipVarSet.contains(D))
8705 auto It = Info.try_emplace(D, Total).first;
8706 It->second[
Kind].emplace_back(
8707 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer,
8708 IsImplicit, Mapper, VarRef, ForDeviceAddr);
8711 for (
const auto *
Cl : Clauses) {
8712 const auto *
C = dyn_cast<OMPMapClause>(
Cl);
8716 if (llvm::is_contained(
C->getMapTypeModifiers(),
8717 OMPC_MAP_MODIFIER_present))
8719 else if (
C->getMapType() == OMPC_MAP_alloc)
8721 const auto *EI =
C->getVarRefs().begin();
8722 for (
const auto L :
C->component_lists()) {
8723 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
8724 InfoGen(std::get<0>(L), Kind, std::get<1>(L),
C->getMapType(),
8725 C->getMapTypeModifiers(), {},
8726 false,
C->isImplicit(), std::get<2>(L),
8731 for (
const auto *
Cl : Clauses) {
8732 const auto *
C = dyn_cast<OMPToClause>(
Cl);
8736 if (llvm::is_contained(
C->getMotionModifiers(),
8737 OMPC_MOTION_MODIFIER_present))
8739 if (llvm::is_contained(
C->getMotionModifiers(),
8740 OMPC_MOTION_MODIFIER_iterator)) {
8741 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
8742 C->getIteratorModifier()->IgnoreParenImpCasts())) {
8743 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
8748 const auto *EI =
C->getVarRefs().begin();
8749 for (
const auto L :
C->component_lists()) {
8750 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_to, {},
8751 C->getMotionModifiers(),
false,
8752 C->isImplicit(), std::get<2>(L), *EI);
8756 for (
const auto *
Cl : Clauses) {
8757 const auto *
C = dyn_cast<OMPFromClause>(
Cl);
8761 if (llvm::is_contained(
C->getMotionModifiers(),
8762 OMPC_MOTION_MODIFIER_present))
8764 if (llvm::is_contained(
C->getMotionModifiers(),
8765 OMPC_MOTION_MODIFIER_iterator)) {
8766 if (
auto *IteratorExpr = dyn_cast<OMPIteratorExpr>(
8767 C->getIteratorModifier()->IgnoreParenImpCasts())) {
8768 const auto *VD =
cast<VarDecl>(IteratorExpr->getIteratorDecl(0));
8773 const auto *EI =
C->getVarRefs().begin();
8774 for (
const auto L :
C->component_lists()) {
8775 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_from, {},
8776 C->getMotionModifiers(),
8777 false,
C->isImplicit(), std::get<2>(L),
8790 MapCombinedInfoTy UseDeviceDataCombinedInfo;
8792 auto &&UseDeviceDataCombinedInfoGen =
8793 [&UseDeviceDataCombinedInfo](
const ValueDecl *VD, llvm::Value *Ptr,
8794 CodeGenFunction &CGF,
bool IsDevAddr) {
8795 UseDeviceDataCombinedInfo.Exprs.push_back(VD);
8796 UseDeviceDataCombinedInfo.BasePointers.emplace_back(Ptr);
8797 UseDeviceDataCombinedInfo.DevicePtrDecls.emplace_back(VD);
8798 UseDeviceDataCombinedInfo.DevicePointers.emplace_back(
8799 IsDevAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer);
8805 UseDeviceDataCombinedInfo.Pointers.push_back(Ptr);
8806 UseDeviceDataCombinedInfo.Sizes.push_back(
8807 llvm::Constant::getNullValue(CGF.Int64Ty));
8808 UseDeviceDataCombinedInfo.Types.push_back(
8809 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM);
8810 UseDeviceDataCombinedInfo.Mappers.push_back(
nullptr);
8814 [&UseDeviceDataCombinedInfoGen](
8815 CodeGenFunction &CGF,
const Expr *IE,
const ValueDecl *VD,
8818 bool IsDevAddr,
bool IEIsAttachPtrForDevAddr =
false) {
8822 if (IsDevAddr && !IEIsAttachPtrForDevAddr) {
8823 if (IE->isGLValue())
8830 bool TreatDevAddrAsDevPtr = IEIsAttachPtrForDevAddr;
8837 UseDeviceDataCombinedInfoGen(VD, Ptr, CGF, IsDevAddr &&
8838 !TreatDevAddrAsDevPtr);
8841 auto &&IsMapInfoExist = [&Info,
this](CodeGenFunction &CGF,
8842 const ValueDecl *VD,
const Expr *IE,
8843 const Expr *DesiredAttachPtrExpr,
8844 bool IsDevAddr) ->
bool {
8852 if (It != Info.end()) {
8854 for (
auto &
Data : It->second) {
8855 MapInfo *CI =
nullptr;
8859 auto *It = llvm::find_if(
Data, [&](
const MapInfo &MI) {
8860 if (MI.Components.back().getAssociatedDeclaration() != VD)
8863 const Expr *MapAttachPtr = getAttachPtrExpr(MI.Components);
8864 bool Match = AttachPtrComparator.areEqual(MapAttachPtr,
8865 DesiredAttachPtrExpr);
8869 if (It !=
Data.end())
8874 CI->ForDeviceAddr =
true;
8875 CI->ReturnDevicePointer =
true;
8879 auto PrevCI = std::next(CI->Components.rbegin());
8880 const auto *VarD = dyn_cast<VarDecl>(VD);
8881 const Expr *AttachPtrExpr = getAttachPtrExpr(CI->Components);
8882 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
8884 !VD->getType().getNonReferenceType()->isPointerType() ||
8885 PrevCI == CI->Components.rend() ||
8887 VarD->hasLocalStorage() ||
8888 (isa_and_nonnull<DeclRefExpr>(AttachPtrExpr) &&
8890 CI->ForDeviceAddr = IsDevAddr;
8891 CI->ReturnDevicePointer =
true;
8909 for (
const auto *
Cl : Clauses) {
8910 const auto *
C = dyn_cast<OMPUseDevicePtrClause>(
Cl);
8913 for (
const auto L :
C->component_lists()) {
8916 assert(!Components.empty() &&
8917 "Not expecting empty list of components!");
8918 const ValueDecl *VD = Components.back().getAssociatedDeclaration();
8920 const Expr *IE = Components.back().getAssociatedExpression();
8928 const Expr *UDPOperandExpr =
8929 Components.front().getAssociatedExpression();
8930 if (IsMapInfoExist(CGF, VD, IE,
8934 MapInfoGen(CGF, IE, VD, Components,
false);
8938 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
8939 for (
const auto *
Cl : Clauses) {
8940 const auto *
C = dyn_cast<OMPUseDeviceAddrClause>(
Cl);
8943 for (
const auto L :
C->component_lists()) {
8946 assert(!std::get<1>(L).empty() &&
8947 "Not expecting empty list of components!");
8948 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration();
8949 if (!Processed.insert(VD).second)
8970 const Expr *UDAAttachPtrExpr = getAttachPtrExpr(Components);
8971 const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
8972 assert((!UDAAttachPtrExpr || UDAAttachPtrExpr == IE) &&
8973 "use_device_addr operand has an attach-ptr, but does not match "
8974 "last component's expr.");
8975 if (IsMapInfoExist(CGF, VD, IE,
8979 MapInfoGen(CGF, IE, VD, Components,
8981 UDAAttachPtrExpr !=
nullptr);
8985 for (
const auto &
Data : Info) {
8986 MapCombinedInfoTy CurInfo;
8988 const ValueDecl *VD = cast_or_null<ValueDecl>(D);
8995 SmallVector<std::pair<const Expr *, MapInfo>, 16> AttachPtrMapInfoPairs;
8998 for (
const auto &M :
Data.second) {
8999 for (
const MapInfo &L : M) {
9000 assert(!L.Components.empty() &&
9001 "Not expecting declaration with no component lists.");
9003 const Expr *AttachPtrExpr = getAttachPtrExpr(L.Components);
9004 AttachPtrMapInfoPairs.emplace_back(AttachPtrExpr, L);
9009 llvm::stable_sort(AttachPtrMapInfoPairs,
9010 [
this](
const auto &LHS,
const auto &RHS) {
9011 return AttachPtrComparator(LHS.first, RHS.first);
9016 auto *It = AttachPtrMapInfoPairs.begin();
9017 while (It != AttachPtrMapInfoPairs.end()) {
9018 const Expr *AttachPtrExpr = It->first;
9020 SmallVector<MapInfo, 8> GroupLists;
9021 while (It != AttachPtrMapInfoPairs.end() &&
9022 (It->first == AttachPtrExpr ||
9023 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
9024 GroupLists.push_back(It->second);
9027 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
9029 StructRangeInfoTy PartialStruct;
9030 AttachInfoTy AttachInfo;
9031 MapCombinedInfoTy GroupCurInfo;
9033 MapCombinedInfoTy GroupStructBaseCurInfo;
9034 for (
const MapInfo &L : GroupLists) {
9036 unsigned CurrentBasePointersIdx = GroupCurInfo.BasePointers.size();
9037 unsigned StructBasePointersIdx =
9038 GroupStructBaseCurInfo.BasePointers.size();
9040 GroupCurInfo.NonContigInfo.IsNonContiguous =
9041 L.Components.back().isNonContiguous();
9042 generateInfoForComponentList(
9043 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
9044 GroupCurInfo, GroupStructBaseCurInfo, PartialStruct, AttachInfo,
9045 false, L.IsImplicit,
9046 true, L.Mapper, L.ForDeviceAddr, VD,
9051 if (L.ReturnDevicePointer) {
9055 assert((CurrentBasePointersIdx < GroupCurInfo.BasePointers.size() ||
9056 StructBasePointersIdx <
9057 GroupStructBaseCurInfo.BasePointers.size()) &&
9058 "Unexpected number of mapped base pointers.");
9061 const ValueDecl *RelevantVD =
9062 L.Components.back().getAssociatedDeclaration();
9063 assert(RelevantVD &&
9064 "No relevant declaration related with device pointer??");
9071 if (StructBasePointersIdx <
9072 GroupStructBaseCurInfo.BasePointers.size()) {
9073 GroupStructBaseCurInfo.DevicePtrDecls[StructBasePointersIdx] =
9075 GroupStructBaseCurInfo.DevicePointers[StructBasePointersIdx] =
9076 L.ForDeviceAddr ? DeviceInfoTy::Address
9077 : DeviceInfoTy::Pointer;
9078 GroupStructBaseCurInfo.Types[StructBasePointersIdx] |=
9079 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
9081 GroupCurInfo.DevicePtrDecls[CurrentBasePointersIdx] = RelevantVD;
9082 GroupCurInfo.DevicePointers[CurrentBasePointersIdx] =
9083 L.ForDeviceAddr ? DeviceInfoTy::Address
9084 : DeviceInfoTy::Pointer;
9085 GroupCurInfo.Types[CurrentBasePointersIdx] |=
9086 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
9093 MapCombinedInfoTy GroupUnionCurInfo;
9094 GroupUnionCurInfo.append(GroupStructBaseCurInfo);
9095 GroupUnionCurInfo.append(GroupCurInfo);
9099 if (PartialStruct.Base.isValid()) {
9100 GroupUnionCurInfo.NonContigInfo.Dims.push_back(0);
9102 CurInfo, GroupUnionCurInfo.Types, PartialStruct, AttachInfo,
9103 !VD, OMPBuilder, VD,
9104 CombinedInfo.BasePointers.size(),
9110 CurInfo.append(GroupUnionCurInfo);
9111 if (AttachInfo.isValid())
9112 emitAttachEntry(CGF, CurInfo, AttachInfo);
9116 CombinedInfo.append(CurInfo);
9119 CombinedInfo.append(UseDeviceDataCombinedInfo);
9123 MappableExprsHandler(
const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
9124 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {
9126 for (
const auto *
C : Dir.getClausesOfKind<OMPFirstprivateClause>())
9127 for (
const auto *D :
C->varlist())
9128 FirstPrivateDecls.try_emplace(
9131 for (
const auto *
C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) {
9132 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
9133 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
9134 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits))
9135 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()),
9137 else if (const auto *VD = dyn_cast<VarDecl>(
9138 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts())
9140 FirstPrivateDecls.try_emplace(VD, true);
9144 for (
const auto *
C : Dir.getClausesOfKind<OMPDefaultmapClause>())
9145 if (
C->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_firstprivate)
9146 DefaultmapFirstprivateKinds.insert(
C->getDefaultmapKind());
9148 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9149 for (
auto L :
C->component_lists())
9150 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L));
9152 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9153 for (
auto L :
C->component_lists())
9154 HasDevAddrsMap[std::get<0>(L)].push_back(std::get<1>(L));
9156 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>()) {
9157 if (C->getMapType() != OMPC_MAP_to)
9159 for (auto L : C->component_lists()) {
9160 const ValueDecl *VD = std::get<0>(L);
9161 const auto *RD = VD ? VD->getType()
9163 .getNonReferenceType()
9164 ->getAsCXXRecordDecl()
9166 if (RD && RD->isLambda())
9167 LambdasMap.try_emplace(std::get<0>(L), C);
9171 auto CollectAttachPtrExprsForClauseComponents = [
this](
const auto *
C) {
9172 for (
auto L :
C->component_lists()) {
9175 if (!Components.empty())
9176 collectAttachPtrExprInfo(Components, CurDir);
9182 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>())
9183 CollectAttachPtrExprsForClauseComponents(
C);
9184 for (
const auto *
C : Dir.getClausesOfKind<OMPToClause>())
9185 CollectAttachPtrExprsForClauseComponents(
C);
9186 for (
const auto *
C : Dir.getClausesOfKind<OMPFromClause>())
9187 CollectAttachPtrExprsForClauseComponents(
C);
9188 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDevicePtrClause>())
9189 CollectAttachPtrExprsForClauseComponents(
C);
9190 for (
const auto *
C : Dir.getClausesOfKind<OMPUseDeviceAddrClause>())
9191 CollectAttachPtrExprsForClauseComponents(
C);
9192 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
9193 CollectAttachPtrExprsForClauseComponents(
C);
9194 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
9195 CollectAttachPtrExprsForClauseComponents(
C);
9199 MappableExprsHandler(
const OMPDeclareMapperDecl &Dir,
CodeGenFunction &CGF)
9200 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {}
9210 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo,
9211 MapFlagsArrayTy &CurTypes,
9212 const StructRangeInfoTy &PartialStruct,
9213 AttachInfoTy &AttachInfo,
bool IsMapThis,
9214 llvm::OpenMPIRBuilder &OMPBuilder,
const ValueDecl *VD,
9215 unsigned OffsetForMemberOfFlag,
9216 bool NotTargetParams)
const {
9217 if (CurTypes.size() == 1 &&
9218 ((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
9219 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) &&
9220 !PartialStruct.IsArraySection)
9222 Address LBAddr = PartialStruct.LowestElem.second;
9223 Address HBAddr = PartialStruct.HighestElem.second;
9224 if (PartialStruct.HasCompleteRecord) {
9225 LBAddr = PartialStruct.LB;
9226 HBAddr = PartialStruct.LB;
9228 CombinedInfo.Exprs.push_back(VD);
9230 CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9231 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9232 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9235 const CXXMethodDecl *MD =
9237 const CXXRecordDecl *RD = MD ? MD->
getParent() :
nullptr;
9238 bool HasBaseClass = RD && IsMapThis ? RD->
getNumBases() > 0 :
false;
9248 CombinedInfo.Pointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9253 CombinedInfo.Sizes.push_back(Size);
9255 CombinedInfo.Pointers.push_back(LB);
9258 llvm::Value *HAddr = CGF.
Builder.CreateConstGEP1_32(
9262 llvm::Value *Diff = CGF.
Builder.CreatePtrDiff(CGF.
Int8Ty, CHAddr, CLAddr);
9265 CombinedInfo.Sizes.push_back(Size);
9267 CombinedInfo.Mappers.push_back(
nullptr);
9269 CombinedInfo.Types.push_back(
9270 NotTargetParams ? OpenMPOffloadMappingFlags::OMP_MAP_NONE
9271 : !PartialStruct.PreliminaryMapData.BasePointers.empty()
9272 ? OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ
9273 : OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9276 if (CurTypes.end() !=
9277 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9278 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9279 Type & OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
9281 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
9283 (*CurTypes.begin()) &= ~OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
9290 if (CurTypes.end() !=
9291 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9292 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9293 Type & OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD);
9295 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9296 for (
auto &M : CurTypes)
9297 M |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9304 OpenMPOffloadMappingFlags MemberOfFlag = OMPBuilder.getMemberOfFlag(
9305 OffsetForMemberOfFlag + CombinedInfo.BasePointers.size() - 1);
9306 for (
auto &M : CurTypes)
9307 OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
9324 if (AttachInfo.isValid())
9325 AttachInfo.AttachPteeAddr = LBAddr;
9333 void generateAllInfo(
9334 MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9335 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
9336 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
9338 "Expect a executable directive");
9340 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, OMPBuilder,
9347 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo,
9348 llvm::OpenMPIRBuilder &OMPBuilder)
const {
9350 "Expect a declare mapper directive");
9352 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo,
9357 void generateInfoForLambdaCaptures(
9358 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
9359 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers)
const {
9367 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
9368 FieldDecl *ThisCapture =
nullptr;
9374 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF),
9375 VDLVal.getPointer(CGF));
9376 CombinedInfo.Exprs.push_back(VD);
9377 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF));
9378 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9379 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9380 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF));
9381 CombinedInfo.Sizes.push_back(
9384 CombinedInfo.Types.push_back(
9385 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9386 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9387 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9388 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9389 CombinedInfo.Mappers.push_back(
nullptr);
9391 for (
const LambdaCapture &LC : RD->
captures()) {
9392 if (!LC.capturesVariable())
9397 auto It = Captures.find(VD);
9398 assert(It != Captures.end() &&
"Found lambda capture without field.");
9402 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9403 VDLVal.getPointer(CGF));
9404 CombinedInfo.Exprs.push_back(VD);
9405 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9406 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9407 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9408 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF));
9409 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9415 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9416 VDLVal.getPointer(CGF));
9417 CombinedInfo.Exprs.push_back(VD);
9418 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9419 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9420 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9421 CombinedInfo.Pointers.push_back(VarRVal.
getScalarVal());
9422 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 0));
9424 CombinedInfo.Types.push_back(
9425 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9426 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9427 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9428 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9429 CombinedInfo.Mappers.push_back(
nullptr);
9434 void adjustMemberOfForLambdaCaptures(
9435 llvm::OpenMPIRBuilder &OMPBuilder,
9436 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
9437 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
9438 MapFlagsArrayTy &Types)
const {
9439 for (
unsigned I = 0, E = Types.size(); I < E; ++I) {
9441 if (Types[I] != (OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9442 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9443 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9444 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))
9446 llvm::Value *BasePtr = LambdaPointers.lookup(BasePointers[I]);
9447 assert(BasePtr &&
"Unable to find base lambda address.");
9449 for (
unsigned J = I; J > 0; --J) {
9450 unsigned Idx = J - 1;
9451 if (Pointers[Idx] != BasePtr)
9456 assert(TgtIdx != -1 &&
"Unable to find parent lambda.");
9460 OpenMPOffloadMappingFlags MemberOfFlag =
9461 OMPBuilder.getMemberOfFlag(TgtIdx);
9462 OMPBuilder.setCorrectMemberOfFlag(Types[I], MemberOfFlag);
9468 void populateComponentListsForNonLambdaCaptureFromClauses(
9469 const ValueDecl *VD, MapDataArrayTy &DeclComponentLists,
9471 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9472 &StorageForImplicitlyAddedComponentLists)
const {
9473 if (VD && LambdasMap.count(VD))
9479 auto It = DevPointersMap.find(VD);
9480 if (It != DevPointersMap.end())
9481 for (
const auto &MCL : It->second)
9482 DeclComponentLists.emplace_back(MCL, OMPC_MAP_to,
Unknown,
9485 auto I = HasDevAddrsMap.find(VD);
9486 if (I != HasDevAddrsMap.end())
9487 for (
const auto &MCL : I->second)
9488 DeclComponentLists.emplace_back(MCL, OMPC_MAP_tofrom,
Unknown,
9492 "Expect a executable directive");
9494 for (
const auto *
C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
9495 const auto *EI =
C->getVarRefs().begin();
9496 for (
const auto L :
C->decl_component_lists(VD)) {
9497 const ValueDecl *VDecl, *Mapper;
9499 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
9501 std::tie(VDecl, Components, Mapper) = L;
9502 assert(VDecl == VD &&
"We got information for the wrong declaration??");
9503 assert(!Components.empty() &&
9504 "Not expecting declaration with no component lists.");
9505 DeclComponentLists.emplace_back(Components,
C->getMapType(),
9506 C->getMapTypeModifiers(),
9507 C->isImplicit(), Mapper, E);
9516 addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9517 VD, DeclComponentLists, StorageForImplicitlyAddedComponentLists);
9519 llvm::stable_sort(DeclComponentLists, [](
const MapData &LHS,
9520 const MapData &RHS) {
9521 ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS);
9524 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9525 bool HasAllocs = MapType == OMPC_MAP_alloc;
9526 MapModifiers = std::get<2>(RHS);
9527 MapType = std::get<1>(LHS);
9529 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9530 bool HasAllocsR = MapType == OMPC_MAP_alloc;
9531 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
9567 void addImplicitMapForAttachPtrBaseIfMemberOfCapturedVD(
9568 const ValueDecl *CapturedVD, MapDataArrayTy &DeclComponentLists,
9570 SmallVector<OMPClauseMappableExprCommon::MappableComponent, 8>>
9571 &ComponentVectorStorage)
const {
9572 bool IsThisCapture = CapturedVD ==
nullptr;
9574 for (
const auto &ComponentsAndAttachPtr : AttachPtrExprMap) {
9576 ComponentsWithAttachPtr = ComponentsAndAttachPtr.first;
9577 const Expr *AttachPtrExpr = ComponentsAndAttachPtr.second;
9581 const auto *ME = dyn_cast<MemberExpr>(AttachPtrExpr);
9585 const Expr *
Base = ME->getBase()->IgnoreParenImpCasts();
9606 bool FoundExistingMap =
false;
9607 for (
const MapData &ExistingL : DeclComponentLists) {
9609 ExistingComponents = std::get<0>(ExistingL);
9611 if (ExistingComponents.empty())
9615 const auto &FirstComponent = ExistingComponents.front();
9616 const Expr *FirstExpr = FirstComponent.getAssociatedExpression();
9622 if (AttachPtrComparator.areEqual(FirstExpr, AttachPtrExpr)) {
9623 FoundExistingMap =
true;
9628 if (IsThisCapture) {
9629 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(FirstExpr)) {
9631 FoundExistingMap =
true;
9640 if (
const auto *DRE = dyn_cast<DeclRefExpr>(FirstExpr)) {
9641 if (DRE->getDecl() == CapturedVD) {
9642 FoundExistingMap =
true;
9648 if (FoundExistingMap)
9654 ComponentVectorStorage.emplace_back();
9655 auto &AttachPtrComponents = ComponentVectorStorage.back();
9658 bool SeenAttachPtrComponent =
false;
9664 for (
size_t i = 0; i < ComponentsWithAttachPtr.size(); ++i) {
9665 const auto &Component = ComponentsWithAttachPtr[i];
9666 const Expr *ComponentExpr = Component.getAssociatedExpression();
9668 if (!SeenAttachPtrComponent && ComponentExpr != AttachPtrExpr)
9670 SeenAttachPtrComponent =
true;
9672 AttachPtrComponents.emplace_back(Component.getAssociatedExpression(),
9673 Component.getAssociatedDeclaration(),
9674 Component.isNonContiguous());
9676 assert(!AttachPtrComponents.empty() &&
9677 "Could not populate component-lists for mapping attach-ptr");
9679 DeclComponentLists.emplace_back(
9680 AttachPtrComponents, OMPC_MAP_tofrom,
Unknown,
9681 true,
nullptr, AttachPtrExpr);
9688 void generateInfoForCaptureFromClauseInfo(
9689 const MapDataArrayTy &DeclComponentListsFromClauses,
9690 const CapturedStmt::Capture *Cap, llvm::Value *Arg,
9691 MapCombinedInfoTy &CurCaptureVarInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9692 unsigned OffsetForMemberOfFlag)
const {
9694 "Not expecting to generate map info for a variable array type!");
9703 if (LambdasMap.count(VD))
9709 if (VD && (DevPointersMap.count(VD) || HasDevAddrsMap.count(VD))) {
9710 CurCaptureVarInfo.Exprs.push_back(VD);
9711 CurCaptureVarInfo.BasePointers.emplace_back(Arg);
9712 CurCaptureVarInfo.DevicePtrDecls.emplace_back(VD);
9713 CurCaptureVarInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
9714 CurCaptureVarInfo.Pointers.push_back(Arg);
9715 CurCaptureVarInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9718 CurCaptureVarInfo.Types.push_back(
9719 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9720 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9721 CurCaptureVarInfo.Mappers.push_back(
nullptr);
9725 auto GenerateInfoForComponentLists =
9726 [&](ArrayRef<MapData> DeclComponentListsFromClauses,
9727 bool IsEligibleForTargetParamFlag) {
9728 MapCombinedInfoTy CurInfoForComponentLists;
9729 StructRangeInfoTy PartialStruct;
9730 AttachInfoTy AttachInfo;
9732 if (DeclComponentListsFromClauses.empty())
9735 generateInfoForCaptureFromComponentLists(
9736 VD, DeclComponentListsFromClauses, CurInfoForComponentLists,
9737 PartialStruct, AttachInfo, IsEligibleForTargetParamFlag);
9742 if (PartialStruct.Base.isValid()) {
9743 CurCaptureVarInfo.append(PartialStruct.PreliminaryMapData);
9745 CurCaptureVarInfo, CurInfoForComponentLists.Types,
9746 PartialStruct, AttachInfo, Cap->
capturesThis(), OMPBuilder,
9747 nullptr, OffsetForMemberOfFlag,
9748 !IsEligibleForTargetParamFlag);
9753 CurCaptureVarInfo.append(CurInfoForComponentLists);
9754 if (AttachInfo.isValid())
9755 emitAttachEntry(CGF, CurCaptureVarInfo, AttachInfo);
9779 SmallVector<std::pair<const Expr *, MapData>, 16> AttachPtrMapDataPairs;
9781 for (
const MapData &L : DeclComponentListsFromClauses) {
9784 const Expr *AttachPtrExpr = getAttachPtrExpr(Components);
9785 AttachPtrMapDataPairs.emplace_back(AttachPtrExpr, L);
9789 llvm::stable_sort(AttachPtrMapDataPairs,
9790 [
this](
const auto &LHS,
const auto &RHS) {
9791 return AttachPtrComparator(LHS.first, RHS.first);
9794 bool NoDefaultMappingDoneForVD = CurCaptureVarInfo.BasePointers.empty();
9795 bool IsFirstGroup =
true;
9799 auto *It = AttachPtrMapDataPairs.begin();
9800 while (It != AttachPtrMapDataPairs.end()) {
9801 const Expr *AttachPtrExpr = It->first;
9803 MapDataArrayTy GroupLists;
9804 while (It != AttachPtrMapDataPairs.end() &&
9805 (It->first == AttachPtrExpr ||
9806 AttachPtrComparator.areEqual(It->first, AttachPtrExpr))) {
9807 GroupLists.push_back(It->second);
9810 assert(!GroupLists.empty() &&
"GroupLists should not be empty");
9815 bool IsEligibleForTargetParamFlag =
9816 IsFirstGroup && NoDefaultMappingDoneForVD;
9818 GenerateInfoForComponentLists(GroupLists, IsEligibleForTargetParamFlag);
9819 IsFirstGroup =
false;
9826 void generateInfoForCaptureFromComponentLists(
9827 const ValueDecl *VD, ArrayRef<MapData> DeclComponentLists,
9828 MapCombinedInfoTy &CurComponentListInfo, StructRangeInfoTy &PartialStruct,
9829 AttachInfoTy &AttachInfo,
bool IsListEligibleForTargetParamFlag)
const {
9831 llvm::SmallDenseMap<
9838 for (
const MapData &L : DeclComponentLists) {
9841 ArrayRef<OpenMPMapModifierKind> MapModifiers;
9843 const ValueDecl *Mapper;
9845 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
9848 for (
const MapData &L1 : ArrayRef(DeclComponentLists).slice(Count)) {
9850 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper,
9852 auto CI = Components.rbegin();
9853 auto CE = Components.rend();
9854 auto SI = Components1.rbegin();
9855 auto SE = Components1.rend();
9856 for (; CI != CE && SI != SE; ++CI, ++SI) {
9857 if (CI->getAssociatedExpression()->getStmtClass() !=
9858 SI->getAssociatedExpression()->getStmtClass())
9861 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
9866 if (CI == CE || SI == SE) {
9868 if (CI == CE && SI == SE)
9870 const auto It = (SI == SE) ? CI : SI;
9877 (std::prev(It)->getAssociatedDeclaration() &&
9879 ->getAssociatedDeclaration()
9881 ->isPointerType()) ||
9882 (It->getAssociatedDeclaration() &&
9883 It->getAssociatedDeclaration()->getType()->isPointerType() &&
9884 std::next(It) != CE && std::next(It) != SE))
9886 const MapData &BaseData = CI == CE ? L : L1;
9888 SI == SE ? Components : Components1;
9889 OverlappedData[&BaseData].push_back(SubData);
9894 llvm::SmallVector<const FieldDecl *, 4> Layout;
9895 if (!OverlappedData.empty()) {
9898 while (BaseType != OrigType) {
9904 getPlainLayout(CRD, Layout,
false);
9910 for (
auto &Pair : OverlappedData) {
9917 auto CI = First.rbegin();
9918 auto CE = First.rend();
9919 auto SI = Second.rbegin();
9920 auto SE = Second.rend();
9921 for (; CI != CE && SI != SE; ++CI, ++SI) {
9922 if (CI->getAssociatedExpression()->getStmtClass() !=
9923 SI->getAssociatedExpression()->getStmtClass())
9926 if (CI->getAssociatedDeclaration() !=
9927 SI->getAssociatedDeclaration())
9932 if (CI == CE && SI == SE)
9936 if (CI == CE || SI == SE)
9941 if (FD1->getParent() == FD2->getParent())
9942 return FD1->getFieldIndex() < FD2->getFieldIndex();
9944 llvm::find_if(Layout, [FD1, FD2](
const FieldDecl *FD) {
9945 return FD == FD1 || FD == FD2;
9953 bool AddTargetParamFlag = IsListEligibleForTargetParamFlag;
9954 MapCombinedInfoTy StructBaseCombinedInfo;
9955 for (
const auto &Pair : OverlappedData) {
9956 const MapData &L = *Pair.getFirst();
9959 ArrayRef<OpenMPMapModifierKind> MapModifiers;
9961 const ValueDecl *Mapper;
9963 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
9965 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
9966 OverlappedComponents = Pair.getSecond();
9967 generateInfoForComponentList(
9968 MapType, MapModifiers, {}, Components, CurComponentListInfo,
9969 StructBaseCombinedInfo, PartialStruct, AttachInfo, AddTargetParamFlag,
9970 IsImplicit,
false, Mapper,
9971 false, VD, VarRef, OverlappedComponents);
9972 AddTargetParamFlag =
false;
9975 for (
const MapData &L : DeclComponentLists) {
9978 ArrayRef<OpenMPMapModifierKind> MapModifiers;
9980 const ValueDecl *Mapper;
9982 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
9984 auto It = OverlappedData.find(&L);
9985 if (It == OverlappedData.end())
9986 generateInfoForComponentList(
9987 MapType, MapModifiers, {}, Components, CurComponentListInfo,
9988 StructBaseCombinedInfo, PartialStruct, AttachInfo,
9989 AddTargetParamFlag, IsImplicit,
false,
9990 Mapper,
false, VD, VarRef,
9992 AddTargetParamFlag =
false;
9998 bool isEffectivelyFirstprivate(
const VarDecl *VD, QualType
Type)
const {
10000 auto I = FirstPrivateDecls.find(VD);
10001 if (I != FirstPrivateDecls.end() && !I->getSecond())
10005 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_scalar)) {
10006 if (
Type->isScalarType())
10011 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_pointer)) {
10012 if (
Type->isAnyPointerType())
10017 if (DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_aggregate)) {
10018 if (
Type->isAggregateType())
10023 return DefaultmapFirstprivateKinds.count(OMPC_DEFAULTMAP_all);
10028 void generateDefaultMapInfo(
const CapturedStmt::Capture &CI,
10029 const FieldDecl &RI, llvm::Value *CV,
10030 MapCombinedInfoTy &CombinedInfo)
const {
10031 bool IsImplicit =
true;
10034 CombinedInfo.Exprs.push_back(
nullptr);
10035 CombinedInfo.BasePointers.push_back(CV);
10036 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10037 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10038 CombinedInfo.Pointers.push_back(CV);
10040 CombinedInfo.Sizes.push_back(
10044 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TO |
10045 OpenMPOffloadMappingFlags::OMP_MAP_FROM);
10049 CombinedInfo.BasePointers.push_back(CV);
10050 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10051 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10052 CombinedInfo.Pointers.push_back(CV);
10053 bool IsFirstprivate =
10059 CombinedInfo.Types.push_back(
10060 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10061 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10063 }
else if (IsFirstprivate) {
10066 CombinedInfo.Types.push_back(
10067 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10069 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10073 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_NONE);
10074 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10076 auto I = FirstPrivateDecls.find(VD);
10077 if (I != FirstPrivateDecls.end())
10078 IsImplicit = I->getSecond();
10084 bool IsFirstprivate = isEffectivelyFirstprivate(VD, ElementType);
10086 CombinedInfo.BasePointers.push_back(CV);
10087 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
10088 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
10093 CombinedInfo.Pointers.push_back(CV);
10095 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
10096 CombinedInfo.Types.push_back(
10097 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
10099 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10104 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
10105 CombinedInfo.Pointers.push_back(CV);
10107 auto I = FirstPrivateDecls.find(VD);
10108 if (I != FirstPrivateDecls.end())
10109 IsImplicit = I->getSecond();
10112 CombinedInfo.Types.back() |=
10113 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
10117 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
10120 CombinedInfo.Mappers.push_back(
nullptr);
10132 dyn_cast<MemberExpr>(OASE->getBase()->IgnoreParenImpCasts()))
10133 return ME->getMemberDecl();
10139static llvm::Constant *
10141 MappableExprsHandler::MappingExprInfo &MapExprs) {
10143 uint32_t SrcLocStrSize;
10144 if (!MapExprs.getMapDecl() && !MapExprs.getMapExpr())
10145 return OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
10148 if (!MapExprs.getMapDecl() && MapExprs.getMapExpr()) {
10152 Loc = MapExprs.getMapExpr()->getExprLoc();
10154 Loc = MapExprs.getMapDecl()->getLocation();
10157 std::string ExprName;
10158 if (MapExprs.getMapExpr()) {
10160 llvm::raw_string_ostream OS(ExprName);
10161 MapExprs.getMapExpr()->printPretty(OS,
nullptr, P);
10163 ExprName = MapExprs.getMapDecl()->getNameAsString();
10172 return OMPBuilder.getOrCreateSrcLocStr(
FileName, ExprName, PLoc.
getLine(),
10179 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10181 bool IsNonContiguous =
false,
bool ForEndCall =
false) {
10184 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
10187 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
10188 CGF.
Builder.GetInsertPoint());
10190 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
10191 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
10196 auto CustomMapperCB = [&](
unsigned int I) {
10197 llvm::Function *MFunc =
nullptr;
10198 if (CombinedInfo.Mappers[I]) {
10199 Info.HasMapper =
true;
10205 cantFail(OMPBuilder.emitOffloadingArraysAndArgs(
10206 AllocaIP, CodeGenIP, Info, Info.RTArgs, CombinedInfo, CustomMapperCB,
10207 IsNonContiguous, ForEndCall, DeviceAddrCB));
10211static const OMPExecutableDirective *
10213 const auto *CS = D.getInnermostCapturedStmt();
10216 const Stmt *ChildStmt =
10219 if (
const auto *NestedDir =
10220 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10222 switch (D.getDirectiveKind()) {
10228 if (DKind == OMPD_teams) {
10229 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
10234 if (
const auto *NND =
10235 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
10236 DKind = NND->getDirectiveKind();
10242 case OMPD_target_teams:
10246 case OMPD_target_parallel:
10247 case OMPD_target_simd:
10248 case OMPD_target_parallel_for:
10249 case OMPD_target_parallel_for_simd:
10251 case OMPD_target_teams_distribute:
10252 case OMPD_target_teams_distribute_simd:
10253 case OMPD_target_teams_distribute_parallel_for:
10254 case OMPD_target_teams_distribute_parallel_for_simd:
10255 case OMPD_parallel:
10257 case OMPD_parallel_for:
10258 case OMPD_parallel_master:
10259 case OMPD_parallel_sections:
10260 case OMPD_for_simd:
10261 case OMPD_parallel_for_simd:
10263 case OMPD_cancellation_point:
10265 case OMPD_threadprivate:
10266 case OMPD_allocate:
10271 case OMPD_sections:
10275 case OMPD_critical:
10276 case OMPD_taskyield:
10278 case OMPD_taskwait:
10279 case OMPD_taskgroup:
10285 case OMPD_target_data:
10286 case OMPD_target_exit_data:
10287 case OMPD_target_enter_data:
10288 case OMPD_distribute:
10289 case OMPD_distribute_simd:
10290 case OMPD_distribute_parallel_for:
10291 case OMPD_distribute_parallel_for_simd:
10292 case OMPD_teams_distribute:
10293 case OMPD_teams_distribute_simd:
10294 case OMPD_teams_distribute_parallel_for:
10295 case OMPD_teams_distribute_parallel_for_simd:
10296 case OMPD_target_update:
10297 case OMPD_declare_simd:
10298 case OMPD_declare_variant:
10299 case OMPD_begin_declare_variant:
10300 case OMPD_end_declare_variant:
10301 case OMPD_declare_target:
10302 case OMPD_end_declare_target:
10303 case OMPD_declare_reduction:
10304 case OMPD_declare_mapper:
10305 case OMPD_taskloop:
10306 case OMPD_taskloop_simd:
10307 case OMPD_master_taskloop:
10308 case OMPD_master_taskloop_simd:
10309 case OMPD_parallel_master_taskloop:
10310 case OMPD_parallel_master_taskloop_simd:
10311 case OMPD_requires:
10312 case OMPD_metadirective:
10315 llvm_unreachable(
"Unexpected directive.");
10356 if (
UDMMap.count(D) > 0)
10360 auto *MapperVarDecl =
10362 CharUnits ElementSize =
C.getTypeSizeInChars(Ty);
10363 llvm::Type *ElemTy =
CGM.getTypes().ConvertTypeForMem(Ty);
10366 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10367 auto PrivatizeAndGenMapInfoCB =
10368 [&](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP, llvm::Value *PtrPHI,
10369 llvm::Value *BeginArg) -> llvm::OpenMPIRBuilder::MapInfosTy & {
10370 MapperCGF.
Builder.restoreIP(CodeGenIP);
10380 Scope.addPrivate(MapperVarDecl, PtrCurrent);
10381 (void)
Scope.Privatize();
10384 MappableExprsHandler MEHandler(*D, MapperCGF);
10385 MEHandler.generateAllInfoForMapper(CombinedInfo,
OMPBuilder);
10387 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10390 if (
CGM.getCodeGenOpts().getDebugInfo() !=
10391 llvm::codegenoptions::NoDebugInfo) {
10392 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10393 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10397 return CombinedInfo;
10400 auto CustomMapperCB = [&](
unsigned I) {
10401 llvm::Function *MapperFunc =
nullptr;
10402 if (CombinedInfo.Mappers[I]) {
10406 assert(MapperFunc &&
"Expect a valid mapper function is available.");
10412 llvm::raw_svector_ostream Out(TyStr);
10413 CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out);
10414 std::string Name =
getName({
"omp_mapper", TyStr, D->
getName()});
10416 llvm::Function *NewFn = cantFail(
OMPBuilder.emitUserDefinedMapper(
10417 PrivatizeAndGenMapInfoCB, ElemTy, Name, CustomMapperCB));
10418 UDMMap.try_emplace(D, NewFn);
10425 auto I =
UDMMap.find(D);
10429 return UDMMap.lookup(D);
10442 Kind != OMPD_target_teams_loop)
10445 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10448 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD))
10449 return NumIterations;
10450 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
10459 if (OffloadingMandatory) {
10460 CGF.
Builder.CreateUnreachable();
10462 if (RequiresOuterTask) {
10463 CapturedVars.clear();
10472 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10475 llvm::Value *DeviceID;
10476 if (
Device.getPointer()) {
10478 Device.getInt() == OMPC_DEVICE_device_num) &&
10479 "Expected device_num modifier.");
10484 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
10489static std::pair<llvm::Value *, OMPDynGroupprivateFallbackType>
10491 llvm::Value *DynGP = CGF.
Builder.getInt32(0);
10492 auto DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10496 llvm::Value *DynGPVal =
10500 auto FallbackModifier = DynGPClause->getDynGroupprivateFallbackModifier();
10501 switch (FallbackModifier) {
10502 case OMPC_DYN_GROUPPRIVATE_FALLBACK_abort:
10503 DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10505 case OMPC_DYN_GROUPPRIVATE_FALLBACK_null:
10506 DynGPFallback = OMPDynGroupprivateFallbackType::Null;
10508 case OMPC_DYN_GROUPPRIVATE_FALLBACK_default_mem:
10511 DynGPFallback = OMPDynGroupprivateFallbackType::DefaultMem;
10514 llvm_unreachable(
"Unknown fallback modifier for OpenMP dyn_groupprivate");
10516 }
else if (
auto *OMPXDynCGClause =
10519 llvm::Value *DynCGMemVal = CGF.
EmitScalarExpr(OMPXDynCGClause->getSize(),
10524 return {DynGP, DynGPFallback};
10530 llvm::OpenMPIRBuilder &OMPBuilder,
10532 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10534 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
10536 auto *CV = CapturedVars.begin();
10539 CI != CE; ++CI, ++RI, ++CV) {
10540 MappableExprsHandler::MapCombinedInfoTy CurInfo;
10545 CurInfo.Exprs.push_back(
nullptr);
10546 CurInfo.BasePointers.push_back(*CV);
10547 CurInfo.DevicePtrDecls.push_back(
nullptr);
10548 CurInfo.DevicePointers.push_back(
10549 MappableExprsHandler::DeviceInfoTy::None);
10550 CurInfo.Pointers.push_back(*CV);
10551 CurInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10554 CurInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
10555 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
10556 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
10557 CurInfo.Mappers.push_back(
nullptr);
10562 bool HasEntryWithCVAsAttachPtr =
false;
10564 HasEntryWithCVAsAttachPtr =
10565 MEHandler.hasAttachEntryForCapturedVar(CapturedVD);
10568 MappableExprsHandler::MapDataArrayTy DeclComponentLists;
10571 StorageForImplicitlyAddedComponentLists;
10572 MEHandler.populateComponentListsForNonLambdaCaptureFromClauses(
10573 CapturedVD, DeclComponentLists,
10574 StorageForImplicitlyAddedComponentLists);
10585 bool HasEntryWithoutAttachPtr =
10586 llvm::any_of(DeclComponentLists, [&](
const auto &MapData) {
10588 Components = std::get<0>(MapData);
10589 return !MEHandler.getAttachPtrExpr(Components);
10594 if (DeclComponentLists.empty() ||
10595 (!HasEntryWithCVAsAttachPtr && !HasEntryWithoutAttachPtr))
10596 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
10600 MEHandler.generateInfoForCaptureFromClauseInfo(
10601 DeclComponentLists, CI, *CV, CurInfo, OMPBuilder,
10602 CombinedInfo.BasePointers.size());
10607 MappedVarSet.insert(
nullptr);
10612 MEHandler.generateInfoForLambdaCaptures(CI->
getCapturedVar(), *CV,
10613 CurInfo, LambdaPointers);
10616 assert(!CurInfo.BasePointers.empty() &&
10617 "Non-existing map pointer for capture!");
10618 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
10619 CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
10620 CurInfo.BasePointers.size() == CurInfo.Types.size() &&
10621 CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
10622 "Inconsistent map information sizes!");
10625 CombinedInfo.append(CurInfo);
10628 MEHandler.adjustMemberOfForLambdaCaptures(
10629 OMPBuilder, LambdaPointers, CombinedInfo.BasePointers,
10630 CombinedInfo.Pointers, CombinedInfo.Types);
10634 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10635 llvm::OpenMPIRBuilder &OMPBuilder,
10642 MEHandler.generateAllInfo(CombinedInfo, OMPBuilder, SkippedVarSet);
10644 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10648 llvm::codegenoptions::NoDebugInfo) {
10649 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10650 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10658 llvm::OpenMPIRBuilder &OMPBuilder,
10659 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10661 MappableExprsHandler MEHandler(D, CGF);
10662 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet;
10665 MappedVarSet, CombinedInfo);
10666 genMapInfo(MEHandler, CGF, CombinedInfo, OMPBuilder, MappedVarSet);
10669template <
typename ClauseTy>
10674 const auto *
C = D.getSingleClause<ClauseTy>();
10675 assert(!
C->varlist_empty() &&
10676 "ompx_bare requires explicit num_teams and thread_limit");
10678 for (
auto *E :
C->varlist()) {
10690 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10692 llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray,
10697 llvm::OpenMPIRBuilder &OMPBuilder = OMPRuntime->
getOMPBuilder();
10700 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10702 genMapInfo(D, CGF, CS, CapturedVars, OMPBuilder, CombinedInfo);
10716 MapTypesArray = Info.RTArgs.MapTypesArray;
10717 MapNamesArray = Info.RTArgs.MapNamesArray;
10719 auto &&ThenGen = [&OMPRuntime, OutlinedFn, &D, &CapturedVars,
10720 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
10721 OutlinedFnID, &InputInfo, &MapTypesArray, &MapNamesArray,
10723 bool IsReverseOffloading =
Device.getInt() == OMPC_DEVICE_ancestor;
10725 if (IsReverseOffloading) {
10731 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10736 unsigned NumTargetItems = InputInfo.NumberOfTargetItems;
10738 llvm::Value *BasePointersArray =
10739 InputInfo.BasePointersArray.emitRawPointer(CGF);
10740 llvm::Value *PointersArray = InputInfo.PointersArray.emitRawPointer(CGF);
10741 llvm::Value *SizesArray = InputInfo.SizesArray.emitRawPointer(CGF);
10742 llvm::Value *MappersArray = InputInfo.MappersArray.emitRawPointer(CGF);
10744 auto &&EmitTargetCallFallbackCB =
10745 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
10746 OffloadingMandatory, &CGF](llvm::OpenMPIRBuilder::InsertPointTy IP)
10747 -> llvm::OpenMPIRBuilder::InsertPointTy {
10750 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10763 NumThreads.push_back(
10769 llvm::Value *NumIterations =
10772 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
10775 llvm::OpenMPIRBuilder::TargetDataRTArgs RTArgs(
10776 BasePointersArray, PointersArray, SizesArray, MapTypesArray,
10777 nullptr , MappersArray, MapNamesArray);
10779 llvm::OpenMPIRBuilder::TargetKernelArgs Args(
10780 NumTargetItems, RTArgs, NumIterations, NumTeams, NumThreads,
10781 DynCGroupMem, HasNoWait, DynCGroupMemFallback);
10783 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
10785 CGF.
Builder, OutlinedFnID, EmitTargetCallFallbackCB, Args, DeviceID,
10787 CGF.
Builder.restoreIP(AfterIP);
10790 if (RequiresOuterTask)
10805 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
10808 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10811 if (RequiresOuterTask) {
10821 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
10822 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10829 const bool OffloadingMandatory = !
CGM.getLangOpts().OpenMPIsTargetDevice &&
10830 CGM.getLangOpts().OpenMPOffloadMandatory;
10832 assert((OffloadingMandatory || OutlinedFn) &&
"Invalid outlined function!");
10834 const bool RequiresOuterTask =
10838 (
CGM.getLangOpts().OpenMP >= 51 &&
10842 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
10850 llvm::Value *MapTypesArray =
nullptr;
10851 llvm::Value *MapNamesArray =
nullptr;
10853 auto &&TargetThenGen = [
this, OutlinedFn, &D, &CapturedVars,
10854 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
10855 OutlinedFnID, &InputInfo, &MapTypesArray,
10859 RequiresOuterTask, CS, OffloadingMandatory,
10860 Device, OutlinedFnID, InputInfo, MapTypesArray,
10861 MapNamesArray, SizeEmitter, CGF,
CGM);
10864 auto &&TargetElseGen =
10865 [
this, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
10868 CS, OffloadingMandatory, CGF);
10875 if (OutlinedFnID) {
10877 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
10889 StringRef ParentName) {
10894 bool RequiresDeviceCodegen =
10899 if (RequiresDeviceCodegen) {
10907 if (!
OMPBuilder.OffloadInfoManager.hasTargetRegionEntryInfo(EntryInfo))
10910 switch (E.getDirectiveKind()) {
10915 case OMPD_target_parallel:
10919 case OMPD_target_teams:
10923 case OMPD_target_teams_distribute:
10927 case OMPD_target_teams_distribute_simd:
10931 case OMPD_target_parallel_for:
10935 case OMPD_target_parallel_for_simd:
10939 case OMPD_target_simd:
10943 case OMPD_target_teams_distribute_parallel_for:
10948 case OMPD_target_teams_distribute_parallel_for_simd:
10954 case OMPD_target_teams_loop:
10958 case OMPD_target_parallel_loop:
10962 case OMPD_parallel:
10964 case OMPD_parallel_for:
10965 case OMPD_parallel_master:
10966 case OMPD_parallel_sections:
10967 case OMPD_for_simd:
10968 case OMPD_parallel_for_simd:
10970 case OMPD_cancellation_point:
10972 case OMPD_threadprivate:
10973 case OMPD_allocate:
10978 case OMPD_sections:
10982 case OMPD_critical:
10983 case OMPD_taskyield:
10985 case OMPD_taskwait:
10986 case OMPD_taskgroup:
10992 case OMPD_target_data:
10993 case OMPD_target_exit_data:
10994 case OMPD_target_enter_data:
10995 case OMPD_distribute:
10996 case OMPD_distribute_simd:
10997 case OMPD_distribute_parallel_for:
10998 case OMPD_distribute_parallel_for_simd:
10999 case OMPD_teams_distribute:
11000 case OMPD_teams_distribute_simd:
11001 case OMPD_teams_distribute_parallel_for:
11002 case OMPD_teams_distribute_parallel_for_simd:
11003 case OMPD_target_update:
11004 case OMPD_declare_simd:
11005 case OMPD_declare_variant:
11006 case OMPD_begin_declare_variant:
11007 case OMPD_end_declare_variant:
11008 case OMPD_declare_target:
11009 case OMPD_end_declare_target:
11010 case OMPD_declare_reduction:
11011 case OMPD_declare_mapper:
11012 case OMPD_taskloop:
11013 case OMPD_taskloop_simd:
11014 case OMPD_master_taskloop:
11015 case OMPD_master_taskloop_simd:
11016 case OMPD_parallel_master_taskloop:
11017 case OMPD_parallel_master_taskloop_simd:
11018 case OMPD_requires:
11019 case OMPD_metadirective:
11022 llvm_unreachable(
"Unknown target directive for OpenMP device codegen.");
11027 if (
const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
11028 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
11036 if (
const auto *L = dyn_cast<LambdaExpr>(S))
11045 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
11046 OMPDeclareTargetDeclAttr::getDeviceType(VD);
11050 if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
11053 if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host)
11061 if (!
CGM.getLangOpts().OpenMPIsTargetDevice) {
11062 if (
const auto *FD = dyn_cast<FunctionDecl>(GD.
getDecl()))
11064 CGM.getLangOpts().OpenMPIsTargetDevice))
11071 if (
const auto *FD = dyn_cast<FunctionDecl>(VD)) {
11072 StringRef Name =
CGM.getMangledName(GD);
11075 CGM.getLangOpts().OpenMPIsTargetDevice))
11080 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
11086 CGM.getLangOpts().OpenMPIsTargetDevice))
11089 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
11098 StringRef ParentName =
11103 StringRef ParentName =
11110 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11111 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
11113 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
11114 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11115 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11124 llvm::Constant *
Addr) {
11125 if (
CGM.getLangOpts().OMPTargetTriples.empty() &&
11126 !
CGM.getLangOpts().OpenMPIsTargetDevice)
11129 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11130 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11134 if (Res && *Res != OMPDeclareTargetDeclAttr::MT_Link &&
11139 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
11142 StringRef VarName =
CGM.getMangledName(VD);
11148 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
11149 auto LinkageForVariable = [&VD,
this]() {
11150 return CGM.getLLVMLinkageVarDefinition(VD);
11153 std::vector<llvm::GlobalVariable *> GeneratedRefs;
11160 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
11161 CGM.getLangOpts().OMPTargetTriples, AddrOfGlobal, LinkageForVariable,
11162 CGM.getTypes().ConvertTypeForMem(
11163 CGM.getContext().getPointerType(VD->
getType())),
11166 for (
auto *ref : GeneratedRefs)
11167 CGM.addCompilerUsedGlobal(ref);
11180 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
11181 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
11184 if ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11185 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11187 CGM.EmitGlobal(VD);
11189 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
11190 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
11191 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
11193 "Expected link clause or to clause with unified memory.");
11194 (void)
CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
11202 " Expected target-based directive.");
11207 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
11209 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
11210 }
else if (
const auto *AC =
11211 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
11212 switch (AC->getAtomicDefaultMemOrderKind()) {
11213 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
11216 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
11219 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
11235 if (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())
11237 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
11238 switch(A->getAllocatorType()) {
11239 case OMPAllocateDeclAttr::OMPNullMemAlloc:
11240 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
11242 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
11243 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
11244 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
11245 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
11246 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
11247 case OMPAllocateDeclAttr::OMPConstMemAlloc:
11248 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
11251 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
11252 llvm_unreachable(
"Expected predefined allocator for the variables with the "
11253 "static storage.");
11265 if (CGM.getLangOpts().OpenMPIsTargetDevice) {
11266 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
11267 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
11272 if (CGM.getLangOpts().OpenMPIsTargetDevice)
11273 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
11283 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
11285 if (
auto *F = dyn_cast_or_null<llvm::Function>(
11286 CGM.GetGlobalValue(
CGM.getMangledName(GD))))
11287 return !F->isDeclaration();
11299 llvm::Function *OutlinedFn,
11308 llvm::Value *Args[] = {
11310 CGF.
Builder.getInt32(CapturedVars.size()),
11313 RealArgs.append(std::begin(Args), std::end(Args));
11314 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
11316 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
11317 CGM.getModule(), OMPRTL___kmpc_fork_teams);
11322 const Expr *NumTeams,
11323 const Expr *ThreadLimit,
11330 llvm::Value *NumTeamsVal =
11336 llvm::Value *ThreadLimitVal =
11343 llvm::Value *PushNumTeamsArgs[] = {RTLoc,
getThreadID(CGF, Loc), NumTeamsVal,
11346 CGM.getModule(), OMPRTL___kmpc_push_num_teams),
11351 const Expr *ThreadLimit,
11354 llvm::Value *ThreadLimitVal =
11361 llvm::Value *ThreadLimitArgs[] = {RTLoc,
getThreadID(CGF, Loc),
11364 CGM.getModule(), OMPRTL___kmpc_set_thread_limit),
11379 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
11381 llvm::Value *IfCondVal =
nullptr;
11386 llvm::Value *DeviceID =
nullptr;
11391 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11395 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11396 auto GenMapInfoCB =
11397 [&](InsertPointTy CodeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & {
11398 CGF.
Builder.restoreIP(CodeGenIP);
11400 MappableExprsHandler MEHandler(D, CGF);
11401 MEHandler.generateAllInfo(CombinedInfo,
OMPBuilder);
11403 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
11406 if (
CGM.getCodeGenOpts().getDebugInfo() !=
11407 llvm::codegenoptions::NoDebugInfo) {
11408 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
11409 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
11413 return CombinedInfo;
11415 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
11416 auto BodyCB = [&](InsertPointTy CodeGenIP, BodyGenTy BodyGenType) {
11417 CGF.
Builder.restoreIP(CodeGenIP);
11418 switch (BodyGenType) {
11419 case BodyGenTy::Priv:
11423 case BodyGenTy::DupNoPriv:
11425 CodeGen.setAction(NoPrivAction);
11429 case BodyGenTy::NoPriv:
11431 CodeGen.setAction(NoPrivAction);
11436 return InsertPointTy(CGF.
Builder.GetInsertBlock(),
11437 CGF.
Builder.GetInsertPoint());
11440 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
11441 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
11446 auto CustomMapperCB = [&](
unsigned int I) {
11447 llvm::Function *MFunc =
nullptr;
11448 if (CombinedInfo.Mappers[I]) {
11449 Info.HasMapper =
true;
11461 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
11462 CGF.
Builder.GetInsertPoint());
11463 llvm::OpenMPIRBuilder::LocationDescription OmpLoc(CodeGenIP);
11464 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
11466 OmpLoc, AllocaIP, CodeGenIP, DeviceID, IfCondVal, Info, GenMapInfoCB,
11468 nullptr, BodyCB, DeviceAddrCB, RTLoc));
11469 CGF.
Builder.restoreIP(AfterIP);
11481 "Expecting either target enter, exit data, or update directives.");
11484 llvm::Value *MapTypesArray =
nullptr;
11485 llvm::Value *MapNamesArray =
nullptr;
11487 auto &&ThenGen = [
this, &D,
Device, &InputInfo, &MapTypesArray,
11490 llvm::Value *DeviceID =
nullptr;
11495 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
11499 llvm::Constant *PointerNum =
11506 {RTLoc, DeviceID, PointerNum,
11515 RuntimeFunction RTLFn;
11516 switch (D.getDirectiveKind()) {
11517 case OMPD_target_enter_data:
11518 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper
11519 : OMPRTL___tgt_target_data_begin_mapper;
11521 case OMPD_target_exit_data:
11522 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper
11523 : OMPRTL___tgt_target_data_end_mapper;
11525 case OMPD_target_update:
11526 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper
11527 : OMPRTL___tgt_target_data_update_mapper;
11529 case OMPD_parallel:
11531 case OMPD_parallel_for:
11532 case OMPD_parallel_master:
11533 case OMPD_parallel_sections:
11534 case OMPD_for_simd:
11535 case OMPD_parallel_for_simd:
11537 case OMPD_cancellation_point:
11539 case OMPD_threadprivate:
11540 case OMPD_allocate:
11545 case OMPD_sections:
11549 case OMPD_critical:
11550 case OMPD_taskyield:
11552 case OMPD_taskwait:
11553 case OMPD_taskgroup:
11559 case OMPD_target_data:
11560 case OMPD_distribute:
11561 case OMPD_distribute_simd:
11562 case OMPD_distribute_parallel_for:
11563 case OMPD_distribute_parallel_for_simd:
11564 case OMPD_teams_distribute:
11565 case OMPD_teams_distribute_simd:
11566 case OMPD_teams_distribute_parallel_for:
11567 case OMPD_teams_distribute_parallel_for_simd:
11568 case OMPD_declare_simd:
11569 case OMPD_declare_variant:
11570 case OMPD_begin_declare_variant:
11571 case OMPD_end_declare_variant:
11572 case OMPD_declare_target:
11573 case OMPD_end_declare_target:
11574 case OMPD_declare_reduction:
11575 case OMPD_declare_mapper:
11576 case OMPD_taskloop:
11577 case OMPD_taskloop_simd:
11578 case OMPD_master_taskloop:
11579 case OMPD_master_taskloop_simd:
11580 case OMPD_parallel_master_taskloop:
11581 case OMPD_parallel_master_taskloop_simd:
11583 case OMPD_target_simd:
11584 case OMPD_target_teams_distribute:
11585 case OMPD_target_teams_distribute_simd:
11586 case OMPD_target_teams_distribute_parallel_for:
11587 case OMPD_target_teams_distribute_parallel_for_simd:
11588 case OMPD_target_teams:
11589 case OMPD_target_parallel:
11590 case OMPD_target_parallel_for:
11591 case OMPD_target_parallel_for_simd:
11592 case OMPD_requires:
11593 case OMPD_metadirective:
11596 llvm_unreachable(
"Unexpected standalone target data directive.");
11600 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11601 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11602 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11603 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11606 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), RTLFn),
11610 auto &&TargetThenGen = [
this, &ThenGen, &D, &InputInfo, &MapTypesArray,
11614 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11616 MappableExprsHandler MEHandler(D, CGF);
11628 CGM.getPointerAlign());
11633 MapTypesArray = Info.RTArgs.MapTypesArray;
11634 MapNamesArray = Info.RTArgs.MapNamesArray;
11635 if (RequiresOuterTask)
11661struct ParamAttrTy {
11662 ParamKindTy Kind =
Vector;
11663 llvm::APSInt StrideOrArg;
11664 llvm::APSInt Alignment;
11665 bool HasVarStride =
false;
11698 unsigned Offset = 0;
11699 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
11700 if (ParamAttrs[Offset].Kind ==
Vector)
11701 CDT =
C.getPointerType(
C.getCanonicalTagType(MD->
getParent()));
11705 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
11706 if (ParamAttrs[I + Offset].Kind ==
Vector) {
11718 return C.getTypeSize(CDT);
11726 llvm::raw_svector_ostream Out(Buffer);
11727 for (
const auto &ParamAttr : ParamAttrs) {
11728 switch (ParamAttr.Kind) {
11748 if (ParamAttr.HasVarStride)
11749 Out <<
"s" << ParamAttr.StrideOrArg;
11750 else if (ParamAttr.Kind == Linear || ParamAttr.Kind == LinearRef ||
11751 ParamAttr.Kind == LinearUVal || ParamAttr.Kind == LinearVal) {
11754 if (ParamAttr.StrideOrArg < 0)
11755 Out <<
'n' << -ParamAttr.StrideOrArg;
11756 else if (ParamAttr.StrideOrArg != 1)
11757 Out << ParamAttr.StrideOrArg;
11760 if (!!ParamAttr.Alignment)
11761 Out <<
'a' << ParamAttr.Alignment;
11764 return std::string(Out.str());
11769 const llvm::APSInt &VLENVal,
11771 OMPDeclareSimdDeclAttr::BranchStateTy State) {
11774 unsigned VecRegSize;
11776 ISADataTy ISAData[] = {
11792 case OMPDeclareSimdDeclAttr::BS_Undefined:
11793 Masked.push_back(
'N');
11794 Masked.push_back(
'M');
11796 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
11797 Masked.push_back(
'N');
11799 case OMPDeclareSimdDeclAttr::BS_Inbranch:
11800 Masked.push_back(
'M');
11803 for (
char Mask : Masked) {
11804 for (
const ISADataTy &
Data : ISAData) {
11806 llvm::raw_svector_ostream Out(Buffer);
11807 Out <<
"_ZGV" <<
Data.ISA << Mask;
11810 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
11811 Out << llvm::APSInt::getUnsigned(
Data.VecRegSize / NumElts);
11816 Out <<
'_' << Fn->getName();
11817 Fn->addFnAttr(Out.str());
11835 if (Kind == ParamKindTy::Uniform)
11838 if (Kind == ParamKindTy::LinearUVal || Kind == ParamKindTy::LinearRef)
11841 if ((Kind == ParamKindTy::Linear || Kind == ParamKindTy::LinearVal) &&
11851 unsigned Size =
C.getTypeSize(QT);
11854 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
11878 return C.getTypeSize(PTy);
11881 return C.getTypeSize(QT);
11883 return C.getTypeSize(
C.getUIntPtrType());
11889static std::tuple<unsigned, unsigned, bool>
11895 bool OutputBecomesInput =
false;
11899 Sizes.push_back(
getAArch64LS(RetType, ParamKindTy::Vector,
C));
11901 OutputBecomesInput =
true;
11903 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
11908 assert(!Sizes.empty() &&
"Unable to determine NDS and WDS.");
11911 assert(llvm::all_of(Sizes,
11912 [](
unsigned Size) {
11913 return Size == 8 || Size == 16 || Size == 32 ||
11914 Size == 64 || Size == 128;
11918 return std::make_tuple(*llvm::min_element(Sizes), *llvm::max_element(Sizes),
11919 OutputBecomesInput);
11925template <
typename T>
11927 char ISA, StringRef ParSeq,
11928 StringRef MangledName,
bool OutputBecomesInput,
11929 llvm::Function *Fn) {
11931 llvm::raw_svector_ostream Out(Buffer);
11932 Out << Prefix << ISA << LMask << VLEN;
11933 if (OutputBecomesInput)
11935 Out << ParSeq <<
"_" << MangledName;
11936 Fn->addFnAttr(Out.str());
11942 StringRef Prefix,
char ISA,
11943 StringRef ParSeq, StringRef MangledName,
11944 bool OutputBecomesInput,
11945 llvm::Function *Fn) {
11949 OutputBecomesInput, Fn);
11951 OutputBecomesInput, Fn);
11955 OutputBecomesInput, Fn);
11957 OutputBecomesInput, Fn);
11961 OutputBecomesInput, Fn);
11963 OutputBecomesInput, Fn);
11968 OutputBecomesInput, Fn);
11971 llvm_unreachable(
"Scalar type is too wide.");
11979 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
11980 char ISA,
unsigned VecRegSize, llvm::Function *Fn,
SourceLocation SLoc) {
11984 const unsigned NDS = std::get<0>(
Data);
11985 const unsigned WDS = std::get<1>(
Data);
11986 const bool OutputBecomesInput = std::get<2>(
Data);
11990 if (UserVLEN == 1) {
11993 "The clause simdlen(1) has no effect when targeting aarch64.");
12000 if (ISA ==
'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
12003 "power of 2 when targeting Advanced SIMD.");
12010 if (ISA ==
's' && UserVLEN != 0) {
12011 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
12014 "lanes in the architectural constraints "
12015 "for SVE (min is 128-bit, max is "
12016 "2048-bit, by steps of 128-bit)");
12024 StringRef Prefix =
"_ZGV";
12030 OutputBecomesInput, Fn);
12032 assert(ISA ==
'n' &&
"Expected ISA either 's' or 'n'.");
12036 case OMPDeclareSimdDeclAttr::BS_Undefined:
12038 OutputBecomesInput, Fn);
12040 OutputBecomesInput, Fn);
12042 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
12044 OutputBecomesInput, Fn);
12046 case OMPDeclareSimdDeclAttr::BS_Inbranch:
12048 OutputBecomesInput, Fn);
12058 OutputBecomesInput, Fn);
12060 assert(ISA ==
'n' &&
"Expected ISA either 's' or 'n'.");
12065 case OMPDeclareSimdDeclAttr::BS_Undefined:
12067 OutputBecomesInput, Fn);
12069 OutputBecomesInput, Fn);
12071 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
12073 OutputBecomesInput, Fn);
12075 case OMPDeclareSimdDeclAttr::BS_Inbranch:
12077 OutputBecomesInput, Fn);
12085 llvm::Function *Fn) {
12090 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
12092 ParamPositions.try_emplace(FD, 0);
12093 unsigned ParamPos = ParamPositions.size();
12095 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
12101 for (
const Expr *E :
Attr->uniforms()) {
12105 Pos = ParamPositions[FD];
12108 ->getCanonicalDecl();
12109 auto It = ParamPositions.find(PVD);
12110 assert(It != ParamPositions.end() &&
"Function parameter not found");
12113 ParamAttrs[Pos].Kind = Uniform;
12116 auto *NI =
Attr->alignments_begin();
12117 for (
const Expr *E :
Attr->aligneds()) {
12122 Pos = ParamPositions[FD];
12126 ->getCanonicalDecl();
12127 auto It = ParamPositions.find(PVD);
12128 assert(It != ParamPositions.end() &&
"Function parameter not found");
12130 ParmTy = PVD->getType();
12132 ParamAttrs[Pos].Alignment =
12134 ? (*NI)->EvaluateKnownConstInt(
C)
12135 : llvm::APSInt::getUnsigned(
12136 C.toCharUnitsFromBits(
C.getOpenMPDefaultSimdAlign(ParmTy))
12141 auto *SI =
Attr->steps_begin();
12142 auto *MI =
Attr->modifiers_begin();
12143 for (
const Expr *E :
Attr->linears()) {
12146 bool IsReferenceType =
false;
12149 unsigned PtrRescalingFactor = 1;
12151 Pos = ParamPositions[FD];
12153 PtrRescalingFactor =
CGM.getContext()
12154 .getTypeSizeInChars(P->getPointeeType())
12158 ->getCanonicalDecl();
12159 auto It = ParamPositions.find(PVD);
12160 assert(It != ParamPositions.end() &&
"Function parameter not found");
12162 if (
auto *P = dyn_cast<PointerType>(PVD->getType()))
12163 PtrRescalingFactor =
CGM.getContext()
12164 .getTypeSizeInChars(P->getPointeeType())
12166 else if (PVD->getType()->isReferenceType()) {
12167 IsReferenceType =
true;
12168 PtrRescalingFactor =
12170 .getTypeSizeInChars(PVD->getType().getNonReferenceType())
12174 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
12175 if (*MI == OMPC_LINEAR_ref)
12176 ParamAttr.Kind = LinearRef;
12177 else if (*MI == OMPC_LINEAR_uval)
12178 ParamAttr.Kind = LinearUVal;
12179 else if (IsReferenceType)
12180 ParamAttr.Kind = LinearVal;
12182 ParamAttr.Kind = Linear;
12184 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1);
12188 if (
const auto *DRE =
12190 if (
const auto *StridePVD =
12191 dyn_cast<ParmVarDecl>(DRE->getDecl())) {
12192 ParamAttr.HasVarStride =
true;
12193 auto It = ParamPositions.find(StridePVD->getCanonicalDecl());
12194 assert(It != ParamPositions.end() &&
12195 "Function parameter not found");
12196 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(It->second);
12200 ParamAttr.StrideOrArg =
Result.Val.getInt();
12206 if (!ParamAttr.HasVarStride &&
12207 (ParamAttr.Kind == Linear || ParamAttr.Kind == LinearRef))
12208 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor;
12212 llvm::APSInt VLENVal;
12214 const Expr *VLENExpr =
Attr->getSimdlen();
12219 OMPDeclareSimdDeclAttr::BranchStateTy State =
Attr->getBranchState();
12220 if (
CGM.getTriple().isX86()) {
12222 }
else if (
CGM.getTriple().getArch() == llvm::Triple::aarch64) {
12223 unsigned VLEN = VLENVal.getExtValue();
12224 StringRef MangledName = Fn->getName();
12225 if (
CGM.getTarget().hasFeature(
"sve"))
12227 MangledName,
's', 128, Fn, ExprLoc);
12228 else if (
CGM.getTarget().hasFeature(
"neon"))
12230 MangledName,
'n', 128, Fn, ExprLoc);
12239class DoacrossCleanupTy final :
public EHScopeStack::Cleanup {
12241 static const int DoacrossFinArgs = 2;
12244 llvm::FunctionCallee RTLFn;
12245 llvm::Value *Args[DoacrossFinArgs];
12248 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
12251 assert(CallArgs.size() == DoacrossFinArgs);
12252 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
12269 QualType Int64Ty =
C.getIntTypeForBitwidth(64,
true);
12277 RD =
C.buildImplicitRecord(
"kmp_dim");
12285 RD =
KmpDimTy->castAsRecordDecl();
12287 llvm::APInt Size(32, NumIterations.size());
12293 enum { LowerFD = 0, UpperFD, StrideFD };
12295 for (
unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
12300 DimsLVal, *std::next(RD->
field_begin(), UpperFD));
12302 CGF.
EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(),
12303 Int64Ty, NumIterations[I]->getExprLoc());
12307 DimsLVal, *std::next(RD->
field_begin(), StrideFD));
12314 llvm::Value *Args[] = {
12317 llvm::ConstantInt::getSigned(
CGM.Int32Ty, NumIterations.size()),
12322 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12323 CGM.getModule(), OMPRTL___kmpc_doacross_init);
12325 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
12327 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12328 CGM.getModule(), OMPRTL___kmpc_doacross_fini);
12333template <
typename T>
12335 const T *
C, llvm::Value *ULoc,
12336 llvm::Value *ThreadID) {
12339 llvm::APInt Size(32,
C->getNumLoops());
12343 for (
unsigned I = 0, E =
C->getNumLoops(); I < E; ++I) {
12344 const Expr *CounterVal =
C->getLoopData(I);
12345 assert(CounterVal);
12352 llvm::Value *Args[] = {
12355 llvm::FunctionCallee RTLFn;
12357 OMPDoacrossKind<T> ODK;
12358 if (ODK.isSource(
C)) {
12360 OMPRTL___kmpc_doacross_post);
12362 assert(ODK.isSink(
C) &&
"Expect sink modifier.");
12364 OMPRTL___kmpc_doacross_wait);
12384 llvm::FunctionCallee Callee,
12386 assert(Loc.
isValid() &&
"Outlined function call location must be valid.");
12389 if (
auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
12390 if (Fn->doesNotThrow()) {
12401 emitCall(CGF, Loc, OutlinedFn, Args);
12405 if (
const auto *FD = dyn_cast<FunctionDecl>(D))
12406 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
12412 const VarDecl *TargetParam)
const {
12419 const Expr *Allocator) {
12420 llvm::Value *AllocVal;
12430 AllocVal = llvm::Constant::getNullValue(
12440 if (!AllocateAlignment)
12443 return llvm::ConstantInt::get(
CGM.
SizeTy, AllocateAlignment->getQuantity());
12456 auto I = UntiedData.find(VD);
12457 if (I != UntiedData.end()) {
12458 UntiedAddr = I->second.first;
12459 UntiedRealAddr = I->second.second;
12463 if (CVD->
hasAttr<OMPAllocateDeclAttr>()) {
12472 Size = CGF.
Builder.CreateNUWAdd(
12474 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
12475 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
12481 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
12482 const Expr *Allocator = AA->getAllocator();
12486 Args.push_back(ThreadID);
12488 Args.push_back(Alignment);
12489 Args.push_back(Size);
12490 Args.push_back(AllocVal);
12491 llvm::omp::RuntimeFunction FnID =
12492 Alignment ? OMPRTL___kmpc_aligned_alloc : OMPRTL___kmpc_alloc;
12494 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args,
12496 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
12497 CGM.getModule(), OMPRTL___kmpc_free);
12505 class OMPAllocateCleanupTy final :
public EHScopeStack::Cleanup {
12506 llvm::FunctionCallee RTLFn;
12509 const Expr *AllocExpr;
12512 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
12514 const Expr *AllocExpr)
12515 : RTLFn(RTLFn), LocEncoding(LocEncoding),
Addr(
Addr),
12516 AllocExpr(AllocExpr) {}
12520 llvm::Value *Args[3];
12526 Args[2] = AllocVal;
12534 CGF.
EHStack.pushCleanup<OMPAllocateCleanupTy>(
12536 VDAddr, Allocator);
12537 if (UntiedRealAddr.
isValid())
12540 Region->emitUntiedSwitch(CGF);
12557 assert(CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12561 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back();
12563 for (
const Stmt *Ref :
C->private_refs()) {
12564 const auto *SimpleRefExpr =
cast<Expr>(Ref)->IgnoreParenImpCasts();
12566 if (
const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
12567 VD = DRE->getDecl();
12570 assert((ME->isImplicitCXXThis() ||
12572 "Expected member of current class.");
12573 VD = ME->getMemberDecl();
12583 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back();
12589 std::pair<Address, Address>> &LocalVars)
12590 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) {
12594 CGF.
CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size());
12595 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars);
12601 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back();
12605 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12607 return llvm::any_of(
12608 CGM.getOpenMPRuntime().NontemporalDeclsStack,
12612void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
12616 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
12622 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front());
12630 for (
const Expr *Ref :
C->varlist()) {
12631 if (!Ref->getType()->isScalarType())
12633 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12636 NeedToCheckForLPCs.insert(DRE->getDecl());
12639 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
12640 for (
const Expr *Ref :
C->varlist()) {
12641 if (!Ref->getType()->isScalarType())
12643 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12646 NeedToCheckForLPCs.insert(DRE->getDecl());
12649 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12650 for (
const Expr *Ref :
C->varlist()) {
12651 if (!Ref->getType()->isScalarType())
12653 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12656 NeedToCheckForLPCs.insert(DRE->getDecl());
12659 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
12660 for (
const Expr *Ref :
C->varlist()) {
12661 if (!Ref->getType()->isScalarType())
12663 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12666 NeedToCheckForLPCs.insert(DRE->getDecl());
12669 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
12670 for (
const Expr *Ref :
C->varlist()) {
12671 if (!Ref->getType()->isScalarType())
12673 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12676 NeedToCheckForLPCs.insert(DRE->getDecl());
12679 for (
const Decl *VD : NeedToCheckForLPCs) {
12681 llvm::reverse(
CGM.getOpenMPRuntime().LastprivateConditionalStack)) {
12682 if (
Data.DeclToUniqueName.count(VD) > 0) {
12683 if (!
Data.Disabled)
12684 NeedToAddForLPCsAsDisabled.insert(VD);
12691CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12694 Action((CGM.getLangOpts().OpenMP >= 50 &&
12697 return C->getKind() ==
12698 OMPC_LASTPRIVATE_conditional;
12700 ? ActionToDo::PushAsLastprivateConditional
12701 : ActionToDo::DoNotPush) {
12702 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12703 if (
CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
12705 assert(Action == ActionToDo::PushAsLastprivateConditional &&
12706 "Expected a push action.");
12708 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
12710 if (
C->getKind() != OMPC_LASTPRIVATE_conditional)
12713 for (
const Expr *Ref :
C->varlist()) {
12714 Data.DeclToUniqueName.insert(std::make_pair(
12719 Data.IVLVal = IVLVal;
12723CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12725 :
CGM(CGF.
CGM), Action(ActionToDo::DoNotPush) {
12729 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
12730 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
12731 if (!NeedToAddForLPCsAsDisabled.empty()) {
12732 Action = ActionToDo::DisableLastprivateConditional;
12733 LastprivateConditionalData &
Data =
12735 for (
const Decl *VD : NeedToAddForLPCsAsDisabled)
12736 Data.DeclToUniqueName.try_emplace(VD);
12738 Data.Disabled =
true;
12742CGOpenMPRuntime::LastprivateConditionalRAII
12745 return LastprivateConditionalRAII(CGF, S);
12749 if (CGM.getLangOpts().OpenMP < 50)
12751 if (Action == ActionToDo::DisableLastprivateConditional) {
12752 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12753 "Expected list of disabled private vars.");
12754 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12756 if (Action == ActionToDo::PushAsLastprivateConditional) {
12758 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12759 "Expected list of lastprivate conditional vars.");
12760 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12772 auto VI = I->getSecond().find(VD);
12773 if (VI == I->getSecond().end()) {
12774 RecordDecl *RD =
C.buildImplicitRecord(
"lasprivate.conditional");
12779 NewType =
C.getCanonicalTagType(RD);
12782 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
12784 NewType = std::get<0>(VI->getSecond());
12785 VDField = std::get<1>(VI->getSecond());
12786 FiredField = std::get<2>(VI->getSecond());
12787 BaseLVal = std::get<3>(VI->getSecond());
12799class LastprivateConditionalRefChecker final
12802 const Expr *FoundE =
nullptr;
12803 const Decl *FoundD =
nullptr;
12804 StringRef UniqueDeclName;
12806 llvm::Function *FoundFn =
nullptr;
12812 llvm::reverse(LPM)) {
12813 auto It = D.DeclToUniqueName.find(E->
getDecl());
12814 if (It == D.DeclToUniqueName.end())
12820 UniqueDeclName = It->second;
12825 return FoundE == E;
12831 llvm::reverse(LPM)) {
12833 if (It == D.DeclToUniqueName.end())
12839 UniqueDeclName = It->second;
12844 return FoundE == E;
12846 bool VisitStmt(
const Stmt *S) {
12847 for (
const Stmt *Child : S->
children()) {
12850 if (
const auto *E = dyn_cast<Expr>(Child))
12858 explicit LastprivateConditionalRefChecker(
12859 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM)
12861 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
12862 getFoundData()
const {
12863 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
12870 StringRef UniqueDeclName,
12876 llvm::Constant *LastIV =
OMPBuilder.getOrCreateInternalVariable(
12877 LLIVTy,
getName({UniqueDeclName,
"iv"}));
12885 llvm::GlobalVariable *
Last =
OMPBuilder.getOrCreateInternalVariable(
12901 auto &&
CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
12907 llvm::Value *CmpRes;
12909 CmpRes = CGF.
Builder.CreateICmpSLE(LastIVVal, IVVal);
12912 "Loop iteration variable must be integer.");
12913 CmpRes = CGF.
Builder.CreateICmpULE(LastIVVal, IVVal);
12917 CGF.
Builder.CreateCondBr(CmpRes, ThenBB, ExitBB);
12938 "Aggregates are not supported in lastprivate conditional.");
12947 if (
CGM.getLangOpts().OpenMPSimd) {
12961 if (!Checker.Visit(LHS))
12963 const Expr *FoundE;
12964 const Decl *FoundD;
12965 StringRef UniqueDeclName;
12967 llvm::Function *FoundFn;
12968 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
12969 Checker.getFoundData();
12970 if (FoundFn != CGF.
CurFn) {
12975 "Lastprivate conditional is not found in outer region.");
12976 QualType StructTy = std::get<0>(It->getSecond());
12977 const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
12988 FiredLVal, llvm::AtomicOrdering::Unordered,
13006 auto It = llvm::find_if(
13008 if (It == Range.end() || It->Fn != CGF.
CurFn)
13012 "Lastprivates must be registered already.");
13015 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back());
13016 for (
const auto &Pair : It->DeclToUniqueName) {
13017 const auto *VD =
cast<VarDecl>(Pair.first->getCanonicalDecl());
13020 auto I = LPCI->getSecond().find(Pair.first);
13021 assert(I != LPCI->getSecond().end() &&
13022 "Lastprivate must be rehistered already.");
13024 LValue BaseLVal = std::get<3>(I->getSecond());
13028 llvm::Value *Cmp = CGF.
Builder.CreateIsNotNull(Res);
13032 CGF.
Builder.CreateCondBr(Cmp, ThenBB, DoneBB);
13057 "Unknown lastprivate conditional variable.");
13058 StringRef UniqueName = It->second;
13059 llvm::GlobalVariable *GV =
CGM.getModule().getNamedGlobal(UniqueName);
13073 llvm_unreachable(
"Not supported in SIMD-only mode");
13080 llvm_unreachable(
"Not supported in SIMD-only mode");
13087 bool Tied,
unsigned &NumberOfParts) {
13088 llvm_unreachable(
"Not supported in SIMD-only mode");
13096 llvm_unreachable(
"Not supported in SIMD-only mode");
13102 const Expr *Hint) {
13103 llvm_unreachable(
"Not supported in SIMD-only mode");
13109 llvm_unreachable(
"Not supported in SIMD-only mode");
13115 const Expr *Filter) {
13116 llvm_unreachable(
"Not supported in SIMD-only mode");
13121 llvm_unreachable(
"Not supported in SIMD-only mode");
13127 llvm_unreachable(
"Not supported in SIMD-only mode");
13135 llvm_unreachable(
"Not supported in SIMD-only mode");
13142 llvm_unreachable(
"Not supported in SIMD-only mode");
13149 bool ForceSimpleCall) {
13150 llvm_unreachable(
"Not supported in SIMD-only mode");
13157 llvm_unreachable(
"Not supported in SIMD-only mode");
13162 llvm_unreachable(
"Not supported in SIMD-only mode");
13168 llvm_unreachable(
"Not supported in SIMD-only mode");
13174 llvm_unreachable(
"Not supported in SIMD-only mode");
13181 llvm_unreachable(
"Not supported in SIMD-only mode");
13187 llvm_unreachable(
"Not supported in SIMD-only mode");
13192 unsigned IVSize,
bool IVSigned,
13195 llvm_unreachable(
"Not supported in SIMD-only mode");
13203 llvm_unreachable(
"Not supported in SIMD-only mode");
13207 ProcBindKind ProcBind,
13209 llvm_unreachable(
"Not supported in SIMD-only mode");
13216 llvm_unreachable(
"Not supported in SIMD-only mode");
13222 llvm_unreachable(
"Not supported in SIMD-only mode");
13227 llvm_unreachable(
"Not supported in SIMD-only mode");
13233 llvm::AtomicOrdering AO) {
13234 llvm_unreachable(
"Not supported in SIMD-only mode");
13239 llvm::Function *TaskFunction,
13241 const Expr *IfCond,
13243 llvm_unreachable(
"Not supported in SIMD-only mode");
13250 llvm_unreachable(
"Not supported in SIMD-only mode");
13257 assert(Options.
SimpleReduction &&
"Only simple reduction is expected.");
13259 ReductionOps, Options);
13265 llvm_unreachable(
"Not supported in SIMD-only mode");
13270 bool IsWorksharingReduction) {
13271 llvm_unreachable(
"Not supported in SIMD-only mode");
13278 llvm_unreachable(
"Not supported in SIMD-only mode");
13283 llvm::Value *ReductionsPtr,
13285 llvm_unreachable(
"Not supported in SIMD-only mode");
13291 llvm_unreachable(
"Not supported in SIMD-only mode");
13297 llvm_unreachable(
"Not supported in SIMD-only mode");
13303 llvm_unreachable(
"Not supported in SIMD-only mode");
13308 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
13310 llvm_unreachable(
"Not supported in SIMD-only mode");
13315 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
13316 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
13320 llvm_unreachable(
"Not supported in SIMD-only mode");
13324 llvm_unreachable(
"Not supported in SIMD-only mode");
13328 llvm_unreachable(
"Not supported in SIMD-only mode");
13338 llvm::Function *OutlinedFn,
13340 llvm_unreachable(
"Not supported in SIMD-only mode");
13344 const Expr *NumTeams,
13345 const Expr *ThreadLimit,
13347 llvm_unreachable(
"Not supported in SIMD-only mode");
13354 llvm_unreachable(
"Not supported in SIMD-only mode");
13360 llvm_unreachable(
"Not supported in SIMD-only mode");
13366 llvm_unreachable(
"Not supported in SIMD-only mode");
13371 llvm_unreachable(
"Not supported in SIMD-only mode");
13376 llvm_unreachable(
"Not supported in SIMD-only mode");
13381 const VarDecl *NativeParam)
const {
13382 llvm_unreachable(
"Not supported in SIMD-only mode");
13388 const VarDecl *TargetParam)
const {
13389 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.
@ Match
This is not an overload because the signature exactly matches an existing declaration.
@ 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.