30#include "llvm/ADT/ArrayRef.h"
31#include "llvm/ADT/SmallVector.h"
32#include "llvm/ADT/StringExtras.h"
33#include "llvm/Bitcode/BitcodeReader.h"
34#include "llvm/IR/Constants.h"
35#include "llvm/IR/DerivedTypes.h"
36#include "llvm/IR/GlobalValue.h"
37#include "llvm/IR/InstrTypes.h"
38#include "llvm/IR/Value.h"
39#include "llvm/Support/AtomicOrdering.h"
40#include "llvm/Support/raw_ostream.h"
48using namespace llvm::omp;
55 enum CGOpenMPRegionKind {
58 ParallelOutlinedRegion,
68 CGOpenMPRegionInfo(
const CapturedStmt &CS,
69 const CGOpenMPRegionKind RegionKind,
72 : CGCapturedStmtInfo(CS,
CR_OpenMP), RegionKind(RegionKind),
73 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
75 CGOpenMPRegionInfo(
const CGOpenMPRegionKind RegionKind,
78 : CGCapturedStmtInfo(
CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
79 Kind(Kind), HasCancel(HasCancel) {}
83 virtual const VarDecl *getThreadIDVariable()
const = 0;
86 void EmitBody(CodeGenFunction &CGF,
const Stmt *S)
override;
90 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
92 virtual void emitUntiedSwitch(CodeGenFunction & ) {}
94 CGOpenMPRegionKind getRegionKind()
const {
return RegionKind; }
98 bool hasCancel()
const {
return HasCancel; }
100 static bool classof(
const CGCapturedStmtInfo *Info) {
104 ~CGOpenMPRegionInfo()
override =
default;
107 CGOpenMPRegionKind RegionKind;
108 RegionCodeGenTy CodeGen;
114class CGOpenMPOutlinedRegionInfo final :
public CGOpenMPRegionInfo {
116 CGOpenMPOutlinedRegionInfo(
const CapturedStmt &CS,
const VarDecl *ThreadIDVar,
117 const RegionCodeGenTy &CodeGen,
119 StringRef HelperName)
120 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen,
Kind,
122 ThreadIDVar(ThreadIDVar), HelperName(HelperName) {
123 assert(ThreadIDVar !=
nullptr &&
"No ThreadID in OpenMP region.");
128 const VarDecl *getThreadIDVariable()
const override {
return ThreadIDVar; }
131 StringRef getHelperName()
const override {
return HelperName; }
133 static bool classof(
const CGCapturedStmtInfo *Info) {
134 return CGOpenMPRegionInfo::classof(Info) &&
136 ParallelOutlinedRegion;
142 const VarDecl *ThreadIDVar;
143 StringRef HelperName;
147class CGOpenMPTaskOutlinedRegionInfo final :
public CGOpenMPRegionInfo {
149 class UntiedTaskActionTy final :
public PrePostActionTy {
151 const VarDecl *PartIDVar;
152 const RegionCodeGenTy UntiedCodeGen;
153 llvm::SwitchInst *UntiedSwitch =
nullptr;
156 UntiedTaskActionTy(
bool Tied,
const VarDecl *PartIDVar,
157 const RegionCodeGenTy &UntiedCodeGen)
158 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
159 void Enter(CodeGenFunction &CGF)
override {
164 PartIDVar->
getType()->castAs<PointerType>());
168 UntiedSwitch = CGF.
Builder.CreateSwitch(Res, DoneBB);
172 UntiedSwitch->addCase(CGF.
Builder.getInt32(0),
174 emitUntiedSwitch(CGF);
177 void emitUntiedSwitch(CodeGenFunction &CGF)
const {
181 PartIDVar->
getType()->castAs<PointerType>());
185 CodeGenFunction::JumpDest CurPoint =
189 UntiedSwitch->addCase(CGF.
Builder.getInt32(UntiedSwitch->getNumCases()),
195 unsigned getNumberOfParts()
const {
return UntiedSwitch->getNumCases(); }
197 CGOpenMPTaskOutlinedRegionInfo(
const CapturedStmt &CS,
198 const VarDecl *ThreadIDVar,
199 const RegionCodeGenTy &CodeGen,
201 const UntiedTaskActionTy &Action)
202 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen,
Kind, HasCancel),
203 ThreadIDVar(ThreadIDVar), Action(Action) {
204 assert(ThreadIDVar !=
nullptr &&
"No ThreadID in OpenMP region.");
209 const VarDecl *getThreadIDVariable()
const override {
return ThreadIDVar; }
212 LValue getThreadIDVariableLValue(CodeGenFunction &CGF)
override;
215 StringRef getHelperName()
const override {
return ".omp_outlined."; }
217 void emitUntiedSwitch(CodeGenFunction &CGF)
override {
218 Action.emitUntiedSwitch(CGF);
221 static bool classof(
const CGCapturedStmtInfo *Info) {
222 return CGOpenMPRegionInfo::classof(Info) &&
230 const VarDecl *ThreadIDVar;
232 const UntiedTaskActionTy &Action;
237class CGOpenMPInlinedRegionInfo :
public CGOpenMPRegionInfo {
239 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
240 const RegionCodeGenTy &CodeGen,
242 : CGOpenMPRegionInfo(InlinedRegion, CodeGen,
Kind, HasCancel),
244 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
247 llvm::Value *getContextValue()
const override {
249 return OuterRegionInfo->getContextValue();
250 llvm_unreachable(
"No context value for inlined OpenMP region");
253 void setContextValue(llvm::Value *
V)
override {
254 if (OuterRegionInfo) {
255 OuterRegionInfo->setContextValue(
V);
258 llvm_unreachable(
"No context value for inlined OpenMP region");
262 const FieldDecl *lookup(
const VarDecl *VD)
const override {
264 return OuterRegionInfo->lookup(VD);
270 FieldDecl *getThisFieldDecl()
const override {
272 return OuterRegionInfo->getThisFieldDecl();
278 const VarDecl *getThreadIDVariable()
const override {
280 return OuterRegionInfo->getThreadIDVariable();
285 LValue getThreadIDVariableLValue(CodeGenFunction &CGF)
override {
287 return OuterRegionInfo->getThreadIDVariableLValue(CGF);
288 llvm_unreachable(
"No LValue for inlined OpenMP construct");
292 StringRef getHelperName()
const override {
293 if (
auto *OuterRegionInfo = getOldCSI())
294 return OuterRegionInfo->getHelperName();
295 llvm_unreachable(
"No helper name for inlined OpenMP construct");
298 void emitUntiedSwitch(CodeGenFunction &CGF)
override {
300 OuterRegionInfo->emitUntiedSwitch(CGF);
303 CodeGenFunction::CGCapturedStmtInfo *getOldCSI()
const {
return OldCSI; }
305 static bool classof(
const CGCapturedStmtInfo *Info) {
306 return CGOpenMPRegionInfo::classof(Info) &&
310 ~CGOpenMPInlinedRegionInfo()
override =
default;
314 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
315 CGOpenMPRegionInfo *OuterRegionInfo;
323class CGOpenMPTargetRegionInfo final :
public CGOpenMPRegionInfo {
325 CGOpenMPTargetRegionInfo(
const CapturedStmt &CS,
326 const RegionCodeGenTy &CodeGen, StringRef HelperName)
327 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
329 HelperName(HelperName) {}
333 const VarDecl *getThreadIDVariable()
const override {
return nullptr; }
336 StringRef getHelperName()
const override {
return HelperName; }
338 static bool classof(
const CGCapturedStmtInfo *Info) {
339 return CGOpenMPRegionInfo::classof(Info) &&
344 StringRef HelperName;
348 llvm_unreachable(
"No codegen for expressions");
352class CGOpenMPInnerExprInfo final :
public CGOpenMPInlinedRegionInfo {
354 CGOpenMPInnerExprInfo(CodeGenFunction &CGF,
const CapturedStmt &CS)
355 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
363 if (!C.capturesVariable() && !C.capturesVariableByCopy())
366 const VarDecl *VD = C.getCapturedVar();
367 if (VD->isLocalVarDeclOrParm())
370 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
372 VD->getType().getNonReferenceType(), VK_LValue,
374 PrivScope.addPrivate(VD, CGF.EmitLValue(&DRE).getAddress());
376 (
void)PrivScope.Privatize();
380 const FieldDecl *lookup(
const VarDecl *VD)
const override {
381 if (
const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
387 void EmitBody(CodeGenFunction &CGF,
const Stmt *S)
override {
388 llvm_unreachable(
"No body for expressions");
393 const VarDecl *getThreadIDVariable()
const override {
394 llvm_unreachable(
"No thread id for expressions");
398 StringRef getHelperName()
const override {
399 llvm_unreachable(
"No helper name for expressions");
402 static bool classof(
const CGCapturedStmtInfo *Info) {
return false; }
406 CodeGenFunction::OMPPrivateScope PrivScope;
410class InlinedOpenMPRegionRAII {
411 CodeGenFunction &CGF;
412 llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
413 FieldDecl *LambdaThisCaptureField =
nullptr;
414 const CodeGen::CGBlockInfo *BlockInfo =
nullptr;
415 bool NoInheritance =
false;
422 InlinedOpenMPRegionRAII(CodeGenFunction &CGF,
const RegionCodeGenTy &CodeGen,
424 bool NoInheritance =
true)
425 : CGF(CGF), NoInheritance(NoInheritance) {
427 CGF.CapturedStmtInfo =
new CGOpenMPInlinedRegionInfo(
428 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
430 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
431 LambdaThisCaptureField = CGF.LambdaThisCaptureField;
432 CGF.LambdaThisCaptureField =
nullptr;
433 BlockInfo = CGF.BlockInfo;
434 CGF.BlockInfo =
nullptr;
438 ~InlinedOpenMPRegionRAII() {
442 delete CGF.CapturedStmtInfo;
443 CGF.CapturedStmtInfo = OldCSI;
445 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
446 CGF.LambdaThisCaptureField = LambdaThisCaptureField;
447 CGF.BlockInfo = BlockInfo;
455enum OpenMPLocationFlags :
unsigned {
457 OMP_IDENT_IMD = 0x01,
459 OMP_IDENT_KMPC = 0x02,
461 OMP_ATOMIC_REDUCE = 0x10,
463 OMP_IDENT_BARRIER_EXPL = 0x20,
465 OMP_IDENT_BARRIER_IMPL = 0x40,
467 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
469 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
471 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140,
473 OMP_IDENT_WORK_LOOP = 0x200,
475 OMP_IDENT_WORK_SECTIONS = 0x400,
477 OMP_IDENT_WORK_DISTRIBUTE = 0x800,
507enum IdentFieldIndex {
509 IdentField_Reserved_1,
513 IdentField_Reserved_2,
515 IdentField_Reserved_3,
524enum OpenMPSchedType {
527 OMP_sch_static_chunked = 33,
529 OMP_sch_dynamic_chunked = 35,
530 OMP_sch_guided_chunked = 36,
531 OMP_sch_runtime = 37,
534 OMP_sch_static_balanced_chunked = 45,
537 OMP_ord_static_chunked = 65,
539 OMP_ord_dynamic_chunked = 67,
540 OMP_ord_guided_chunked = 68,
541 OMP_ord_runtime = 69,
543 OMP_sch_default = OMP_sch_static,
545 OMP_dist_sch_static_chunked = 91,
546 OMP_dist_sch_static = 92,
549 OMP_sch_modifier_monotonic = (1 << 29),
551 OMP_sch_modifier_nonmonotonic = (1 << 30),
556class CleanupTy final :
public EHScopeStack::Cleanup {
557 PrePostActionTy *Action;
560 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
561 void Emit(CodeGenFunction &CGF, Flags )
override {
574 Callback(CodeGen, CGF, *PrePostAction);
577 Callback(CodeGen, CGF, Action);
585 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
586 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
587 if (
const auto *DRE =
588 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
589 if (
const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
600 std::pair<llvm::Function *, llvm::Function *>
Reduction =
620 auto *GV =
new llvm::GlobalVariable(
622 llvm::GlobalValue::PrivateLinkage,
Init, Name);
663 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, DestAddr);
667 llvm::Value *SrcBegin =
nullptr;
669 SrcBegin = SrcAddr.emitRawPointer(CGF);
672 llvm::Value *DestEnd =
677 llvm::Value *IsEmpty =
678 CGF.
Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arrayinit.isempty");
679 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
682 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
687 llvm::PHINode *SrcElementPHI =
nullptr;
690 SrcElementPHI = CGF.
Builder.CreatePHI(SrcBegin->getType(), 2,
691 "omp.arraycpy.srcElementPast");
692 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
694 Address(SrcElementPHI, SrcAddr.getElementType(),
695 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
697 llvm::PHINode *DestElementPHI = CGF.
Builder.CreatePHI(
698 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
699 DestElementPHI->addIncoming(DestBegin, EntryBB);
707 if (EmitDeclareReductionInit) {
709 SrcElementCurrent, ElementTy);
717 llvm::Value *SrcElementNext = CGF.
Builder.CreateConstGEP1_32(
718 SrcAddr.getElementType(), SrcElementPHI, 1,
719 "omp.arraycpy.dest.element");
720 SrcElementPHI->addIncoming(SrcElementNext, CGF.
Builder.GetInsertBlock());
724 llvm::Value *DestElementNext = CGF.
Builder.CreateConstGEP1_32(
726 "omp.arraycpy.dest.element");
729 CGF.
Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
730 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
731 DestElementPHI->addIncoming(DestElementNext, CGF.
Builder.GetInsertBlock());
743 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(E))
748void ReductionCodeGen::emitAggregateInitialization(
750 const OMPDeclareReductionDecl *DRD) {
754 const auto *PrivateVD =
756 bool EmitDeclareReductionInit =
759 EmitDeclareReductionInit,
760 EmitDeclareReductionInit ? ClausesData[N].ReductionOp
761 : PrivateVD->getInit(),
769 ClausesData.reserve(Shareds.size());
770 SharedAddresses.reserve(Shareds.size());
771 Sizes.reserve(Shareds.size());
772 BaseDecls.reserve(Shareds.size());
773 const auto *IOrig = Origs.begin();
774 const auto *IPriv = Privates.begin();
775 const auto *IRed = ReductionOps.begin();
776 for (
const Expr *Ref : Shareds) {
777 ClausesData.emplace_back(Ref, *IOrig, *IPriv, *IRed);
778 std::advance(IOrig, 1);
779 std::advance(IPriv, 1);
780 std::advance(IRed, 1);
785 assert(SharedAddresses.size() == N && OrigAddresses.size() == N &&
786 "Number of generated lvalues must be exactly N.");
787 LValue First = emitSharedLValue(CGF, ClausesData[N].Shared);
788 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Shared);
789 SharedAddresses.emplace_back(
First, Second);
790 if (ClausesData[N].Shared == ClausesData[N].Ref) {
791 OrigAddresses.emplace_back(
First, Second);
793 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref);
794 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref);
795 OrigAddresses.emplace_back(
First, Second);
804 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()),
809 llvm::Value *SizeInChars;
810 auto *ElemType = OrigAddresses[N].first.getAddress().getElementType();
811 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType);
812 if (AsArraySection) {
813 Size = CGF.
Builder.CreatePtrDiff(ElemType,
814 OrigAddresses[N].second.getPointer(CGF),
815 OrigAddresses[N].first.getPointer(CGF));
816 Size = CGF.
Builder.CreateNUWAdd(
817 Size, llvm::ConstantInt::get(Size->getType(), 1));
818 SizeInChars = CGF.
Builder.CreateNUWMul(Size, ElemSizeOf);
821 CGF.
getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType());
822 Size = CGF.
Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
824 Sizes.emplace_back(SizeInChars, Size);
837 assert(!Size && !Sizes[N].second &&
838 "Size should be nullptr for non-variably modified reduction "
853 assert(SharedAddresses.size() > N &&
"No variable was generated");
854 const auto *PrivateVD =
860 (void)DefaultInit(CGF);
861 emitAggregateInitialization(CGF, N, PrivateAddr, SharedAddr, DRD);
862 }
else if (DRD && (DRD->
getInitializer() || !PrivateVD->hasInit())) {
863 (void)DefaultInit(CGF);
864 QualType SharedType = SharedAddresses[N].first.getType();
866 PrivateAddr, SharedAddr, SharedType);
867 }
else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&
870 PrivateVD->
getType().getQualifiers(),
888 CGF.
pushDestroy(DTorKind, PrivateAddr, PrivateType);
907 BaseLV.getType(), BaseLV.getBaseInfo(),
941 const VarDecl *OrigVD =
nullptr;
942 if (
const auto *OASE = dyn_cast<ArraySectionExpr>(Ref)) {
943 const Expr *
Base = OASE->getBase()->IgnoreParenImpCasts();
944 while (
const auto *TempOASE = dyn_cast<ArraySectionExpr>(
Base))
945 Base = TempOASE->getBase()->IgnoreParenImpCasts();
946 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
947 Base = TempASE->getBase()->IgnoreParenImpCasts();
950 }
else if (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
951 const Expr *
Base = ASE->getBase()->IgnoreParenImpCasts();
952 while (
const auto *TempASE = dyn_cast<ArraySubscriptExpr>(
Base))
953 Base = TempASE->getBase()->IgnoreParenImpCasts();
964 BaseDecls.emplace_back(OrigVD);
967 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
969 Address SharedAddr = SharedAddresses[N].first.getAddress();
970 llvm::Value *Adjustment = CGF.
Builder.CreatePtrDiff(
973 llvm::Value *PrivatePointer =
979 SharedAddresses[N].first.getType(),
982 BaseDecls.emplace_back(
996 getThreadIDVariable()->
getType()->castAs<PointerType>());
1014LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1017 getThreadIDVariable()->
getType(),
1035 llvm::OpenMPIRBuilderConfig Config(
1036 CGM.getLangOpts().OpenMPIsTargetDevice,
isGPU(),
1037 CGM.getLangOpts().OpenMPOffloadMandatory,
1040 Config.setDefaultTargetAS(
1046 CGM.getLangOpts().OpenMPIsTargetDevice
1047 ?
CGM.getLangOpts().OMPHostIRFile
1052 if (
CGM.getLangOpts().OpenMPForceUSM) {
1054 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
1062 if (!
Data.getValue().pointsToAliveValue())
1064 auto *GV = dyn_cast<llvm::GlobalVariable>(
Data.getValue());
1067 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1069 GV->eraseFromParent();
1074 return OMPBuilder.createPlatformSpecificName(Parts);
1077static llvm::Function *
1079 const Expr *CombinerInitializer,
const VarDecl *In,
1080 const VarDecl *Out,
bool IsCombiner) {
1083 QualType PtrTy =
C.getPointerType(Ty).withRestrict();
1089 Args.push_back(&OmpOutParm);
1090 Args.push_back(&OmpInParm);
1095 {IsCombiner ?
"omp_combiner" :
"omp_initializer",
""});
1096 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1100 Fn->removeFnAttr(llvm::Attribute::NoInline);
1101 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1102 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1108 Out->getLocation());
1118 (void)
Scope.Privatize();
1119 if (!IsCombiner && Out->hasInit() &&
1122 Out->getType().getQualifiers(),
1125 if (CombinerInitializer)
1127 Scope.ForceCleanup();
1156std::pair<llvm::Function *, llvm::Function *>
1168struct PushAndPopStackRAII {
1169 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder,
CodeGenFunction &CGF,
1170 bool HasCancel, llvm::omp::Directive Kind)
1171 : OMPBuilder(OMPBuilder) {
1187 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) {
1188 assert(IP.getBlock()->end() == IP.getPoint() &&
1189 "Clang CG should cause non-terminated block!");
1190 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1195 return llvm::Error::success();
1200 llvm::OpenMPIRBuilder::FinalizationInfo FI({FiniCB, Kind, HasCancel});
1201 OMPBuilder->pushFinalizationCB(std::move(FI));
1203 ~PushAndPopStackRAII() {
1205 OMPBuilder->popFinalizationCB();
1207 llvm::OpenMPIRBuilder *OMPBuilder;
1216 "thread id variable must be of type kmp_int32 *");
1218 bool HasCancel =
false;
1219 if (
const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
1220 HasCancel = OPD->hasCancel();
1221 else if (
const auto *OPD = dyn_cast<OMPTargetParallelDirective>(&D))
1222 HasCancel = OPD->hasCancel();
1223 else if (
const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
1224 HasCancel = OPSD->hasCancel();
1225 else if (
const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
1226 HasCancel = OPFD->hasCancel();
1227 else if (
const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
1228 HasCancel = OPFD->hasCancel();
1229 else if (
const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
1230 HasCancel = OPFD->hasCancel();
1231 else if (
const auto *OPFD =
1232 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
1233 HasCancel = OPFD->hasCancel();
1234 else if (
const auto *OPFD =
1235 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
1236 HasCancel = OPFD->hasCancel();
1241 PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel, InnermostKind);
1242 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar,
CodeGen, InnermostKind,
1243 HasCancel, OutlinedHelperName);
1249 std::string Suffix =
getName({
"omp_outlined"});
1250 return (Name + Suffix).str();
1258 std::string Suffix =
getName({
"omp",
"reduction",
"reduction_func"});
1259 return (Name + Suffix).str();
1266 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
1276 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
1286 bool Tied,
unsigned &NumberOfParts) {
1289 llvm::Value *ThreadID =
getThreadID(CGF, D.getBeginLoc());
1291 llvm::Value *TaskArgs[] = {
1293 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1296 CGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(
1297 CGM.getModule(), OMPRTL___kmpc_omp_task),
1300 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1304 "thread id variable must be of type kmp_int32 for tasks");
1309 bool HasCancel =
false;
1310 if (
const auto *TD = dyn_cast<OMPTaskDirective>(&D))
1311 HasCancel = TD->hasCancel();
1312 else if (
const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D))
1313 HasCancel = TD->hasCancel();
1314 else if (
const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D))
1315 HasCancel = TD->hasCancel();
1316 else if (
const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D))
1317 HasCancel = TD->hasCancel();
1320 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar,
CodeGen,
1321 InnermostKind, HasCancel, Action);
1323 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
1325 NumberOfParts = Action.getNumberOfParts();
1330 bool AtCurrentPoint) {
1332 assert(!Elem.ServiceInsertPt &&
"Insert point is set already.");
1334 llvm::Value *Undef = llvm::UndefValue::get(CGF.
Int32Ty);
1335 if (AtCurrentPoint) {
1336 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt",
1337 CGF.
Builder.GetInsertBlock());
1339 Elem.ServiceInsertPt =
new llvm::BitCastInst(Undef, CGF.
Int32Ty,
"svcpt");
1340 Elem.ServiceInsertPt->insertAfter(CGF.
AllocaInsertPt->getIterator());
1346 if (Elem.ServiceInsertPt) {
1347 llvm::Instruction *Ptr = Elem.ServiceInsertPt;
1348 Elem.ServiceInsertPt =
nullptr;
1349 Ptr->eraseFromParent();
1356 llvm::raw_svector_ostream OS(Buffer);
1365 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1366 OS << FD->getQualifiedNameAsString();
1373 unsigned Flags,
bool EmitLoc) {
1374 uint32_t SrcLocStrSize;
1375 llvm::Constant *SrcLocStr;
1376 if ((!EmitLoc &&
CGM.getCodeGenOpts().getDebugInfo() ==
1377 llvm::codegenoptions::NoDebugInfo) ||
1379 SrcLocStr =
OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
1381 std::string FunctionName;
1383 if (
const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.
CurFuncDecl))
1384 FunctionName = FD->getQualifiedNameAsString();
1397 SrcLocStr, SrcLocStrSize, llvm::omp::IdentFlag(Flags), Reserved2Flags);
1402 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1405 if (
CGM.getLangOpts().OpenMPIRBuilder) {
1408 uint32_t SrcLocStrSize;
1409 auto *SrcLocStr =
OMPBuilder.getOrCreateSrcLocStr(
1412 OMPBuilder.getOrCreateIdent(SrcLocStr, SrcLocStrSize));
1415 llvm::Value *ThreadID =
nullptr;
1420 ThreadID = I->second.ThreadID;
1421 if (ThreadID !=
nullptr)
1425 if (
auto *OMPRegionInfo =
1427 if (OMPRegionInfo->getThreadIDVariable()) {
1429 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
1433 CGF.
Builder.GetInsertBlock() == TopBlock ||
1438 CGF.
Builder.GetInsertBlock()) {
1442 if (CGF.
Builder.GetInsertBlock() == TopBlock)
1454 if (!Elem.ServiceInsertPt)
1456 CGBuilderTy::InsertPointGuard IPG(CGF.
Builder);
1457 CGF.
Builder.SetInsertPoint(Elem.ServiceInsertPt);
1461 OMPRTL___kmpc_global_thread_num),
1464 Elem.ThreadID =
Call;
1469 assert(CGF.
CurFn &&
"No function in current CodeGenFunction.");
1475 for (
const auto *D : I->second)
1480 for (
const auto *D : I->second)
1492static llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseKind
1494 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
1495 OMPDeclareTargetDeclAttr::getDeviceType(VD);
1497 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1499 switch ((
int)*DevTy) {
1500 case OMPDeclareTargetDeclAttr::DT_Host:
1501 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseHost;
1503 case OMPDeclareTargetDeclAttr::DT_NoHost:
1504 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNoHost;
1506 case OMPDeclareTargetDeclAttr::DT_Any:
1507 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseAny;
1510 return llvm::OffloadEntriesInfoManager::OMPTargetDeviceClauseNone;
1515static llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind
1517 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapType =
1518 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
1520 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1521 switch ((
int)*MapType) {
1522 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_To:
1523 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
1525 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Enter:
1526 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
1528 case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Link:
1529 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink;
1532 return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryNone;
1541 auto FileInfoCallBack = [&]() {
1546 PLoc =
SM.getPresumedLoc(BeginLoc,
false);
1551 return OMPBuilder.getTargetEntryUniqueInfo(FileInfoCallBack,
1556 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
1558 auto LinkageForVariable = [&VD,
this]() {
1559 return CGM.getLLVMLinkageVarDefinition(VD);
1562 std::vector<llvm::GlobalVariable *> GeneratedRefs;
1564 llvm::Type *LlvmPtrTy =
CGM.getTypes().ConvertTypeForMem(
1565 CGM.getContext().getPointerType(VD->
getType()));
1566 llvm::Constant *addr =
OMPBuilder.getAddrOfDeclareTargetVar(
1572 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
1573 CGM.getLangOpts().OMPTargetTriples, LlvmPtrTy, AddrOfGlobal,
1574 LinkageForVariable);
1583 assert(!
CGM.getLangOpts().OpenMPUseTLS ||
1584 !
CGM.getContext().getTargetInfo().isTLSSupported());
1586 std::string Suffix =
getName({
"cache",
""});
1587 return OMPBuilder.getOrCreateInternalVariable(
1588 CGM.Int8PtrPtrTy, Twine(
CGM.getMangledName(VD)).concat(Suffix).str());
1595 if (
CGM.getLangOpts().OpenMPUseTLS &&
1596 CGM.getContext().getTargetInfo().isTLSSupported())
1600 llvm::Value *Args[] = {
1603 CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy)),
1608 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1620 CGM.getModule(), OMPRTL___kmpc_global_thread_num),
1624 llvm::Value *Args[] = {
1627 Ctor, CopyCtor, Dtor};
1630 CGM.getModule(), OMPRTL___kmpc_threadprivate_register),
1637 if (
CGM.getLangOpts().OpenMPUseTLS &&
1638 CGM.getContext().getTargetInfo().isTLSSupported())
1645 llvm::Value *Ctor =
nullptr, *CopyCtor =
nullptr, *Dtor =
nullptr;
1647 if (
CGM.getLangOpts().CPlusPlus && PerformInit) {
1653 nullptr,
CGM.getContext().VoidPtrTy,
1655 Args.push_back(&Dst);
1657 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1658 CGM.getContext().VoidPtrTy, Args);
1659 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1660 std::string Name =
getName({
"__kmpc_global_ctor_",
""});
1661 llvm::Function *Fn =
1662 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1685 nullptr,
CGM.getContext().VoidPtrTy,
1687 Args.push_back(&Dst);
1689 const auto &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(
1690 CGM.getContext().VoidTy, Args);
1691 llvm::FunctionType *FTy =
CGM.getTypes().GetFunctionType(FI);
1692 std::string Name =
getName({
"__kmpc_global_dtor_",
""});
1693 llvm::Function *Fn =
1694 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc);
1717 CopyCtor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1718 if (Ctor ==
nullptr) {
1719 Ctor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1721 if (Dtor ==
nullptr) {
1722 Dtor = llvm::Constant::getNullValue(
CGM.DefaultPtrTy);
1725 auto *InitFunctionTy =
1726 llvm::FunctionType::get(
CGM.VoidTy,
false);
1727 std::string Name =
getName({
"__omp_threadprivate_init_",
""});
1728 llvm::Function *InitFunction =
CGM.CreateGlobalInitOrCleanUpFunction(
1729 InitFunctionTy, Name,
CGM.getTypes().arrangeNullaryFunction());
1733 CGM.getTypes().arrangeNullaryFunction(), ArgList,
1737 return InitFunction;
1745 llvm::GlobalValue *GV) {
1746 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
1747 OMPDeclareTargetDeclAttr::getActiveAttr(FD);
1750 if (!ActiveAttr || !(*ActiveAttr)->getIndirect())
1757 OMPBuilder.OffloadInfoManager.getTargetRegionEntryFnName(Name, EntryInfo);
1763 llvm::GlobalValue *
Addr = GV;
1764 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
1765 llvm::PointerType *FnPtrTy = llvm::PointerType::get(
1766 CGM.getLLVMContext(),
1767 CGM.getModule().getDataLayout().getProgramAddressSpace());
1768 Addr =
new llvm::GlobalVariable(
1769 CGM.getModule(), FnPtrTy,
1770 true, llvm::GlobalValue::ExternalLinkage, GV, Name,
1771 nullptr, llvm::GlobalValue::NotThreadLocal,
1772 CGM.getModule().getDataLayout().getDefaultGlobalsAddressSpace());
1773 Addr->setVisibility(llvm::GlobalValue::ProtectedVisibility);
1776 OMPBuilder.OffloadInfoManager.registerDeviceGlobalVarEntryInfo(
1777 Name,
Addr,
CGM.GetTargetTypeStoreSize(
CGM.VoidPtrTy).getQuantity(),
1778 llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryIndirect,
1779 llvm::GlobalValue::WeakODRLinkage);
1785 std::string Suffix =
getName({
"artificial",
""});
1787 llvm::GlobalVariable *GAddr =
OMPBuilder.getOrCreateInternalVariable(
1788 VarLVType, Twine(Name).concat(Suffix).str());
1789 if (
CGM.getLangOpts().OpenMP &&
CGM.getLangOpts().OpenMPUseTLS &&
1790 CGM.getTarget().isTLSSupported()) {
1791 GAddr->setThreadLocal(
true);
1792 return Address(GAddr, GAddr->getValueType(),
1793 CGM.getContext().getTypeAlignInChars(VarType));
1795 std::string CacheSuffix =
getName({
"cache",
""});
1796 llvm::Value *Args[] = {
1804 Twine(Name).concat(Suffix).concat(CacheSuffix).str())};
1809 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
1812 VarLVType,
CGM.getContext().getTypeAlignInChars(VarType));
1862 auto &M =
CGM.getModule();
1863 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc,
1866 llvm::Value *Args[] = {
1868 CGF.
Builder.getInt32(CapturedVars.size()),
1871 RealArgs.append(std::begin(Args), std::end(Args));
1872 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
1874 llvm::FunctionCallee RTLFn =
1875 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call);
1878 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc, Loc,
1884 llvm::Value *Args[] = {RTLoc, ThreadID};
1886 M, OMPRTL___kmpc_serialized_parallel),
1893 ".bound.zero.addr");
1898 OutlinedFnArgs.push_back(ZeroAddrBound.
getPointer());
1899 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
1907 OutlinedFn->removeFnAttr(llvm::Attribute::AlwaysInline);
1908 OutlinedFn->addFnAttr(llvm::Attribute::NoInline);
1914 M, OMPRTL___kmpc_end_serialized_parallel),
1933 if (
auto *OMPRegionInfo =
1935 if (OMPRegionInfo->getThreadIDVariable())
1936 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
1945 return ThreadIDTemp;
1949 std::string Prefix = Twine(
"gomp_critical_user_", CriticalName).str();
1950 std::string Name =
getName({Prefix,
"var"});
1957 llvm::FunctionCallee EnterCallee;
1959 llvm::FunctionCallee ExitCallee;
1962 llvm::BasicBlock *ContBlock =
nullptr;
1965 CommonActionTy(llvm::FunctionCallee EnterCallee,
1967 llvm::FunctionCallee ExitCallee,
1969 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
1974 llvm::Value *CallBool = CGF.
Builder.CreateIsNotNull(EnterRes);
1978 CGF.
Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
1982 void Done(CodeGenFunction &CGF) {
1987 void Exit(CodeGenFunction &CGF)
override {
1994 StringRef CriticalName,
2003 llvm::FunctionCallee RuntimeFcn =
OMPBuilder.getOrCreateRuntimeFunction(
2005 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical);
2007 unsigned LockVarArgIdx = 2;
2009 RuntimeFcn.getFunctionType()
2010 ->getParamType(LockVarArgIdx)
2011 ->getPointerAddressSpace())
2013 LockVar, RuntimeFcn.getFunctionType()->getParamType(LockVarArgIdx));
2019 EnterArgs.push_back(CGF.
Builder.CreateIntCast(
2022 CommonActionTy Action(RuntimeFcn, EnterArgs,
2024 CGM.getModule(), OMPRTL___kmpc_end_critical),
2041 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2042 CGM.getModule(), OMPRTL___kmpc_master),
2045 CGM.getModule(), OMPRTL___kmpc_end_master),
2063 llvm::Value *FilterVal = Filter
2065 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
2070 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2071 CGM.getModule(), OMPRTL___kmpc_masked),
2074 CGM.getModule(), OMPRTL___kmpc_end_masked),
2090 llvm::Value *Args[] = {
2092 llvm::ConstantInt::get(
CGM.IntTy, 0,
true)};
2094 CGM.getModule(), OMPRTL___kmpc_omp_taskyield),
2098 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
2099 Region->emitUntiedSwitch(CGF);
2112 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2113 CGM.getModule(), OMPRTL___kmpc_taskgroup),
2116 CGM.getModule(), OMPRTL___kmpc_end_taskgroup),
2125 unsigned Index,
const VarDecl *Var) {
2146 Args.push_back(&LHSArg);
2147 Args.push_back(&RHSArg);
2153 llvm::GlobalValue::InternalLinkage, Name,
2156 Fn->setDoesNotRecurse();
2173 for (
unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
2174 const auto *DestVar =
2178 const auto *SrcVar =
2184 CGF.
EmitOMPCopy(
Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
2199 assert(CopyprivateVars.size() == SrcExprs.size() &&
2200 CopyprivateVars.size() == DstExprs.size() &&
2201 CopyprivateVars.size() == AssignmentOps.size());
2213 if (!CopyprivateVars.empty()) {
2216 C.getIntTypeForBitwidth(32, 1);
2217 DidIt = CGF.
CreateMemTemp(KmpInt32Ty,
".omp.copyprivate.did_it");
2222 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2223 CGM.getModule(), OMPRTL___kmpc_single),
2226 CGM.getModule(), OMPRTL___kmpc_end_single),
2239 llvm::APInt ArraySize(32, CopyprivateVars.size());
2240 QualType CopyprivateArrayTy =
C.getConstantArrayType(
2245 CGF.
CreateMemTemp(CopyprivateArrayTy,
".omp.copyprivate.cpr_list");
2246 for (
unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
2258 SrcExprs, DstExprs, AssignmentOps, Loc);
2259 llvm::Value *BufSize = CGF.
getTypeSize(CopyprivateArrayTy);
2263 llvm::Value *Args[] = {
2267 CL.emitRawPointer(CGF),
2272 CGM.getModule(), OMPRTL___kmpc_copyprivate),
2288 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
2289 CGM.getModule(), OMPRTL___kmpc_ordered),
2292 CGM.getModule(), OMPRTL___kmpc_end_ordered),
2303 if (Kind == OMPD_for)
2304 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
2305 else if (Kind == OMPD_sections)
2306 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
2307 else if (Kind == OMPD_single)
2308 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
2309 else if (Kind == OMPD_barrier)
2310 Flags = OMP_IDENT_BARRIER_EXPL;
2312 Flags = OMP_IDENT_BARRIER_IMPL;
2324 ScheduleKind = OMPC_SCHEDULE_static;
2326 llvm::APInt ChunkSize(32, 1);
2336 bool ForceSimpleCall) {
2338 auto *OMPRegionInfo =
2341 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2344 CGF.
Builder.restoreIP(AfterIP);
2357 if (OMPRegionInfo) {
2358 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
2361 OMPRTL___kmpc_cancel_barrier),
2370 CGF.
Builder.CreateCondBr(Cmp, ExitBB, ContBB);
2382 CGM.getModule(), OMPRTL___kmpc_barrier),
2387 Expr *ME,
bool IsFatal) {
2389 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2392 llvm::Value *Args[] = {
2394 llvm::ConstantInt::get(
CGM.Int32Ty, IsFatal ? 2 : 1),
2395 CGF.
Builder.CreatePointerCast(MVL,
CGM.Int8PtrTy)};
2397 CGM.getModule(), OMPRTL___kmpc_error),
2403 bool Chunked,
bool Ordered) {
2404 switch (ScheduleKind) {
2405 case OMPC_SCHEDULE_static:
2406 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
2407 : (Ordered ? OMP_ord_static : OMP_sch_static);
2408 case OMPC_SCHEDULE_dynamic:
2409 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
2410 case OMPC_SCHEDULE_guided:
2411 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
2412 case OMPC_SCHEDULE_runtime:
2413 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
2414 case OMPC_SCHEDULE_auto:
2415 return Ordered ? OMP_ord_auto : OMP_sch_auto;
2417 assert(!Chunked &&
"chunk was specified but schedule kind not known");
2418 return Ordered ? OMP_ord_static : OMP_sch_static;
2420 llvm_unreachable(
"Unexpected runtime schedule");
2424static OpenMPSchedType
2427 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
2431 bool Chunked)
const {
2432 OpenMPSchedType Schedule =
2434 return Schedule == OMP_sch_static;
2440 return Schedule == OMP_dist_sch_static;
2444 bool Chunked)
const {
2445 OpenMPSchedType Schedule =
2447 return Schedule == OMP_sch_static_chunked;
2453 return Schedule == OMP_dist_sch_static_chunked;
2457 OpenMPSchedType Schedule =
2459 assert(Schedule != OMP_sch_static_chunked &&
"cannot be chunked here");
2460 return Schedule != OMP_sch_static;
2468 case OMPC_SCHEDULE_MODIFIER_monotonic:
2469 Modifier = OMP_sch_modifier_monotonic;
2471 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2472 Modifier = OMP_sch_modifier_nonmonotonic;
2474 case OMPC_SCHEDULE_MODIFIER_simd:
2475 if (Schedule == OMP_sch_static_chunked)
2476 Schedule = OMP_sch_static_balanced_chunked;
2483 case OMPC_SCHEDULE_MODIFIER_monotonic:
2484 Modifier = OMP_sch_modifier_monotonic;
2486 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
2487 Modifier = OMP_sch_modifier_nonmonotonic;
2489 case OMPC_SCHEDULE_MODIFIER_simd:
2490 if (Schedule == OMP_sch_static_chunked)
2491 Schedule = OMP_sch_static_balanced_chunked;
2503 if (CGM.
getLangOpts().OpenMP >= 50 && Modifier == 0) {
2504 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
2505 Schedule == OMP_sch_static_balanced_chunked ||
2506 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
2507 Schedule == OMP_dist_sch_static_chunked ||
2508 Schedule == OMP_dist_sch_static))
2509 Modifier = OMP_sch_modifier_nonmonotonic;
2511 return Schedule | Modifier;
2521 ScheduleKind.
Schedule, DispatchValues.
Chunk !=
nullptr, Ordered);
2523 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
2524 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
2525 Schedule != OMP_sch_static_balanced_chunked));
2532 llvm::Value *Chunk = DispatchValues.
Chunk ? DispatchValues.
Chunk
2533 : CGF.
Builder.getIntN(IVSize, 1);
2534 llvm::Value *Args[] = {
2538 CGM, Schedule, ScheduleKind.
M1, ScheduleKind.
M2)),
2541 CGF.
Builder.getIntN(IVSize, 1),
2558 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
2559 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
2566 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
2567 Schedule == OMP_sch_static_balanced_chunked ||
2568 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
2569 Schedule == OMP_dist_sch_static ||
2570 Schedule == OMP_dist_sch_static_chunked);
2577 llvm::Value *Chunk = Values.
Chunk;
2578 if (Chunk ==
nullptr) {
2579 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
2580 Schedule == OMP_dist_sch_static) &&
2581 "expected static non-chunked schedule");
2585 assert((Schedule == OMP_sch_static_chunked ||
2586 Schedule == OMP_sch_static_balanced_chunked ||
2587 Schedule == OMP_ord_static_chunked ||
2588 Schedule == OMP_dist_sch_static_chunked) &&
2589 "expected static chunked schedule");
2591 llvm::Value *Args[] = {
2614 "Expected loop-based or sections-based directive.");
2617 ? OMP_IDENT_WORK_LOOP
2618 : OMP_IDENT_WORK_SECTIONS);
2620 llvm::FunctionCallee StaticInitFunction =
2625 ScheduleNum, ScheduleKind.
M1, ScheduleKind.
M2, Values);
2632 OpenMPSchedType ScheduleNum =
2634 llvm::Value *UpdatedLocation =
2637 llvm::FunctionCallee StaticInitFunction;
2638 bool isGPUDistribute =
2639 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU();
2640 StaticInitFunction =
OMPBuilder.createForStaticInitFunction(
2651 assert((DKind == OMPD_distribute || DKind == OMPD_for ||
2652 DKind == OMPD_sections) &&
2653 "Expected distribute, for, or sections directive kind");
2657 llvm::Value *Args[] = {
2660 (DKind == OMPD_target_teams_loop)
2661 ? OMP_IDENT_WORK_DISTRIBUTE
2663 ? OMP_IDENT_WORK_LOOP
2664 : OMP_IDENT_WORK_SECTIONS),
2668 CGM.getLangOpts().OpenMPIsTargetDevice &&
CGM.getTriple().isGPU())
2671 CGM.getModule(), OMPRTL___kmpc_distribute_static_fini),
2675 CGM.getModule(), OMPRTL___kmpc_for_static_fini),
2700 llvm::Value *Args[] = {
2708 OMPBuilder.createDispatchNextFunction(IVSize, IVSigned), Args);
2715 const Expr *Message,
2718 return llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
2727 return llvm::ConstantInt::get(
CGM.Int32Ty,
2728 Severity == OMPC_SEVERITY_warning ? 1 : 2);
2744 RuntimeFunction FnID = OMPRTL___kmpc_push_num_threads;
2745 if (Modifier == OMPC_NUMTHREADS_strict) {
2746 FnID = OMPRTL___kmpc_push_num_threads_strict;
2751 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args);
2755 ProcBindKind ProcBind,
2759 assert(ProcBind != OMP_PROC_BIND_unknown &&
"Unsupported proc_bind value.");
2761 llvm::Value *Args[] = {
2763 llvm::ConstantInt::get(
CGM.IntTy,
unsigned(ProcBind),
true)};
2765 CGM.getModule(), OMPRTL___kmpc_push_proc_bind),
2778 CGM.getModule(), OMPRTL___kmpc_flush),
2785enum KmpTaskTFields {
2812 if (
CGM.getLangOpts().OpenMPSimd ||
OMPBuilder.OffloadInfoManager.empty())
2815 llvm::OpenMPIRBuilder::EmitMetadataErrorReportFunctionTy &&ErrorReportFn =
2816 [
this](llvm::OpenMPIRBuilder::EmitMetadataErrorKind Kind,
2817 const llvm::TargetRegionEntryInfo &EntryInfo) ->
void {
2819 if (Kind != llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR) {
2820 for (
auto I =
CGM.getContext().getSourceManager().fileinfo_begin(),
2821 E =
CGM.getContext().getSourceManager().fileinfo_end();
2823 if (I->getFirst().getUniqueID().getDevice() == EntryInfo.DeviceID &&
2824 I->getFirst().getUniqueID().getFile() == EntryInfo.FileID) {
2825 Loc =
CGM.getContext().getSourceManager().translateFileLineCol(
2826 I->getFirst(), EntryInfo.Line, 1);
2832 case llvm::OpenMPIRBuilder::EMIT_MD_TARGET_REGION_ERROR: {
2833 unsigned DiagID =
CGM.getDiags().getCustomDiagID(
2835 "%0 is incorrect: either the "
2836 "address or the ID is invalid.");
2837 CGM.getDiags().Report(Loc, DiagID) << EntryInfo.ParentName;
2839 case llvm::OpenMPIRBuilder::EMIT_MD_DECLARE_TARGET_ERROR: {
2840 unsigned DiagID =
CGM.getDiags().getCustomDiagID(
2842 "variable %0 is incorrect: the "
2843 "address is invalid.");
2844 CGM.getDiags().Report(Loc, DiagID) << EntryInfo.ParentName;
2846 case llvm::OpenMPIRBuilder::EMIT_MD_GLOBAL_VAR_LINK_ERROR: {
2847 unsigned DiagID =
CGM.getDiags().getCustomDiagID(
2849 "Offloading entry for declare target variable is incorrect: the "
2850 "address is invalid.");
2851 CGM.getDiags().Report(DiagID);
2856 OMPBuilder.createOffloadEntriesAndInfoMetadata(ErrorReportFn);
2863 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty,
C.VoidPtrTy};
2866 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
2872struct PrivateHelpersTy {
2873 PrivateHelpersTy(
const Expr *OriginalRef,
const VarDecl *Original,
2875 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy),
2876 PrivateElemInit(PrivateElemInit) {}
2877 PrivateHelpersTy(
const VarDecl *Original) : Original(Original) {}
2878 const Expr *OriginalRef =
nullptr;
2879 const VarDecl *Original =
nullptr;
2880 const VarDecl *PrivateCopy =
nullptr;
2881 const VarDecl *PrivateElemInit =
nullptr;
2882 bool isLocalPrivate()
const {
2883 return !OriginalRef && !PrivateCopy && !PrivateElemInit;
2886typedef std::pair<CharUnits , PrivateHelpersTy> PrivateDataTy;
2891 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
2893 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
2895 return !(AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
2896 !AA->getAllocator());
2901 if (!Privates.empty()) {
2906 RecordDecl *RD =
C.buildImplicitRecord(
".kmp_privates.t");
2908 for (
const auto &Pair : Privates) {
2909 const VarDecl *VD = Pair.second.Original;
2913 if (Pair.second.isLocalPrivate()) {
2936 QualType KmpRoutineEntryPointerQTy) {
2956 CanQualType KmpCmplrdataTy =
C.getCanonicalTagType(UD);
2957 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t");
2987 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_task_t_with_privates");
3007static llvm::Function *
3010 QualType KmpTaskTWithPrivatesPtrQTy,
3012 QualType SharedsPtrTy, llvm::Function *TaskFunction,
3013 llvm::Value *TaskPrivatesMap) {
3021 Args.push_back(&GtidArg);
3022 Args.push_back(&TaskTypeArg);
3023 const auto &TaskEntryFnInfo =
3025 llvm::FunctionType *TaskEntryTy =
3028 auto *TaskEntry = llvm::Function::Create(
3029 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3031 TaskEntry->setDoesNotRecurse();
3046 const auto *KmpTaskTWithPrivatesQTyRD =
3051 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
3053 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF);
3055 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
3061 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
3062 llvm::Value *PrivatesParam;
3063 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
3066 PrivatesLVal.getPointer(CGF), CGF.
VoidPtrTy);
3068 PrivatesParam = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
3071 llvm::Value *CommonArgs[] = {
3072 GtidParam, PartidParam, PrivatesParam, TaskPrivatesMap,
3078 std::end(CommonArgs));
3080 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
3083 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
3086 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
3089 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
3092 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
3095 CallArgs.push_back(LBParam);
3096 CallArgs.push_back(UBParam);
3097 CallArgs.push_back(StParam);
3098 CallArgs.push_back(LIParam);
3099 CallArgs.push_back(RParam);
3101 CallArgs.push_back(SharedsParam);
3114 QualType KmpTaskTWithPrivatesPtrQTy,
3115 QualType KmpTaskTWithPrivatesQTy) {
3123 Args.push_back(&GtidArg);
3124 Args.push_back(&TaskTypeArg);
3125 const auto &DestructorFnInfo =
3127 llvm::FunctionType *DestructorFnTy =
3131 auto *DestructorFn =
3132 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
3136 DestructorFn->setDoesNotRecurse();
3144 const auto *KmpTaskTWithPrivatesQTyRD =
3146 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
3148 for (
const auto *Field : FI->getType()->castAsRecordDecl()->fields()) {
3150 Field->getType().isDestructedType()) {
3152 CGF.
pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
3156 return DestructorFn;
3176 C,
nullptr, Loc,
nullptr,
3177 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
3179 Args.push_back(&TaskPrivatesArg);
3180 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
unsigned> PrivateVarsPos;
3181 unsigned Counter = 1;
3182 for (
const Expr *E :
Data.PrivateVars) {
3184 C,
nullptr, Loc,
nullptr,
3185 C.getPointerType(
C.getPointerType(E->
getType()))
3190 PrivateVarsPos[VD] = Counter;
3193 for (
const Expr *E :
Data.FirstprivateVars) {
3195 C,
nullptr, Loc,
nullptr,
3196 C.getPointerType(
C.getPointerType(E->
getType()))
3201 PrivateVarsPos[VD] = Counter;
3204 for (
const Expr *E :
Data.LastprivateVars) {
3206 C,
nullptr, Loc,
nullptr,
3207 C.getPointerType(
C.getPointerType(E->
getType()))
3212 PrivateVarsPos[VD] = Counter;
3218 Ty =
C.getPointerType(Ty);
3220 Ty =
C.getPointerType(Ty);
3222 C,
nullptr, Loc,
nullptr,
3223 C.getPointerType(
C.getPointerType(Ty)).withConst().withRestrict(),
3225 PrivateVarsPos[VD] = Counter;
3228 const auto &TaskPrivatesMapFnInfo =
3230 llvm::FunctionType *TaskPrivatesMapTy =
3234 auto *TaskPrivatesMap = llvm::Function::Create(
3235 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
3238 TaskPrivatesMapFnInfo);
3240 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
3241 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
3242 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
3246 TaskPrivatesMapFnInfo, Args, Loc, Loc);
3254 for (
const FieldDecl *Field : PrivatesQTyRD->fields()) {
3256 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
3260 RefLVal.getAddress(), RefLVal.getType()->castAs<
PointerType>());
3265 return TaskPrivatesMap;
3271 Address KmpTaskSharedsPtr, LValue TDBase,
3277 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3291 if ((!IsTargetTask && !
Data.FirstprivateVars.empty() && ForDup) ||
3292 (IsTargetTask && KmpTaskSharedsPtr.
isValid())) {
3299 FI = FI->getType()->castAsRecordDecl()->field_begin();
3300 for (
const PrivateDataTy &Pair : Privates) {
3302 if (Pair.second.isLocalPrivate()) {
3306 const VarDecl *VD = Pair.second.PrivateCopy;
3311 if (
const VarDecl *Elem = Pair.second.PrivateElemInit) {
3312 const VarDecl *OriginalVD = Pair.second.Original;
3315 LValue SharedRefLValue;
3318 if (IsTargetTask && !SharedField) {
3322 ->getNumParams() == 0 &&
3325 ->getDeclContext()) &&
3326 "Expected artificial target data variable.");
3329 }
else if (ForDup) {
3332 SharedRefLValue.getAddress().withAlignment(
3333 C.getDeclAlign(OriginalVD)),
3335 SharedRefLValue.getTBAAInfo());
3337 Pair.second.Original->getCanonicalDecl()) > 0 ||
3339 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3342 InlinedOpenMPRegionRAII Region(
3345 SharedRefLValue = CGF.
EmitLValue(Pair.second.OriginalRef);
3356 PrivateLValue.getAddress(), SharedRefLValue.getAddress(),
Type,
3357 [&CGF, Elem,
Init, &CapturesInfo](
Address DestElement,
3360 CodeGenFunction::OMPPrivateScope InitScope(CGF);
3361 InitScope.addPrivate(Elem, SrcElement);
3362 (void)InitScope.Privatize();
3364 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
3365 CGF, &CapturesInfo);
3366 CGF.EmitAnyExprToMem(Init, DestElement,
3367 Init->getType().getQualifiers(),
3373 InitScope.addPrivate(Elem, SharedRefLValue.getAddress());
3374 (void)InitScope.Privatize();
3390 bool InitRequired =
false;
3391 for (
const PrivateDataTy &Pair : Privates) {
3392 if (Pair.second.isLocalPrivate())
3394 const VarDecl *VD = Pair.second.PrivateCopy;
3396 InitRequired = InitRequired || (isa_and_nonnull<CXXConstructExpr>(
Init) &&
3401 return InitRequired;
3418 QualType KmpTaskTWithPrivatesPtrQTy,
3426 KmpTaskTWithPrivatesPtrQTy,
3429 KmpTaskTWithPrivatesPtrQTy,
3433 Args.push_back(&DstArg);
3434 Args.push_back(&SrcArg);
3435 Args.push_back(&LastprivArg);
3436 const auto &TaskDupFnInfo =
3440 auto *TaskDup = llvm::Function::Create(
3441 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.
getModule());
3443 TaskDup->setDoesNotRecurse();
3453 auto LIFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTLastIter);
3455 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3463 assert(!Privates.empty());
3465 if (!
Data.FirstprivateVars.empty()) {
3470 TDBase, *KmpTaskTWithPrivatesQTyRD->
field_begin());
3478 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
3479 SharedsTy, SharedsPtrTy,
Data, Privates,
true);
3489 for (
const PrivateDataTy &P : Privates) {
3490 if (P.second.isLocalPrivate())
3492 QualType Ty = P.second.Original->getType().getNonReferenceType();
3501class OMPIteratorGeneratorScope final
3503 CodeGenFunction &CGF;
3504 const OMPIteratorExpr *E =
nullptr;
3505 SmallVector<CodeGenFunction::JumpDest, 4> ContDests;
3506 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests;
3507 OMPIteratorGeneratorScope() =
delete;
3508 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) =
delete;
3511 OMPIteratorGeneratorScope(CodeGenFunction &CGF,
const OMPIteratorExpr *E)
3512 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) {
3515 SmallVector<llvm::Value *, 4> Uppers;
3517 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper));
3518 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I));
3519 addPrivate(VD, CGF.CreateMemTemp(VD->getType(), VD->getName()));
3520 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3522 HelperData.CounterVD,
3523 CGF.CreateMemTemp(HelperData.CounterVD->getType(),
"counter.addr"));
3528 const OMPIteratorHelperData &HelperData = E->getHelper(I);
3530 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD),
3531 HelperData.CounterVD->getType());
3533 CGF.EmitStoreOfScalar(
3534 llvm::ConstantInt::get(CLVal.getAddress().getElementType(), 0),
3536 CodeGenFunction::JumpDest &ContDest =
3537 ContDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.cont"));
3538 CodeGenFunction::JumpDest &ExitDest =
3539 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope(
"iter.exit"));
3541 llvm::Value *N = Uppers[I];
3544 CGF.EmitBlock(ContDest.getBlock());
3546 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation());
3548 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType()
3549 ? CGF.Builder.CreateICmpSLT(CVal, N)
3550 : CGF.Builder.CreateICmpULT(CVal, N);
3551 llvm::BasicBlock *BodyBB = CGF.createBasicBlock(
"iter.body");
3552 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock());
3554 CGF.EmitBlock(BodyBB);
3556 CGF.EmitIgnoredExpr(HelperData.Update);
3559 ~OMPIteratorGeneratorScope() {
3564 const OMPIteratorHelperData &HelperData = E->
getHelper(I - 1);
3569 CGF.
EmitBlock(ExitDests[I - 1].getBlock(), I == 1);
3575static std::pair<llvm::Value *, llvm::Value *>
3577 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E);
3580 const Expr *
Base = OASE->getBase();
3585 llvm::Value *SizeVal;
3588 SizeVal = CGF.
getTypeSize(OASE->getBase()->getType()->getPointeeType());
3589 for (
const Expr *SE : OASE->getDimensions()) {
3593 SizeVal = CGF.
Builder.CreateNUWMul(SizeVal, Sz);
3595 }
else if (
const auto *ASE =
3598 Address UpAddrAddress = UpAddrLVal.getAddress();
3599 llvm::Value *UpAddr = CGF.
Builder.CreateConstGEP1_32(
3603 llvm::Value *UpIntPtr = CGF.
Builder.CreatePtrToInt(UpAddr, CGF.
SizeTy);
3604 SizeVal = CGF.
Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
3608 return std::make_pair(
Addr, SizeVal);
3613 QualType FlagsTy =
C.getIntTypeForBitwidth(32,
false);
3614 if (KmpTaskAffinityInfoTy.
isNull()) {
3616 C.buildImplicitRecord(
"kmp_task_affinity_info_t");
3622 KmpTaskAffinityInfoTy =
C.getCanonicalTagType(KmpAffinityInfoRD);
3629 llvm::Function *TaskFunction,
QualType SharedsTy,
3634 const auto *I =
Data.PrivateCopies.begin();
3635 for (
const Expr *E :
Data.PrivateVars) {
3637 Privates.emplace_back(
3643 I =
Data.FirstprivateCopies.begin();
3644 const auto *IElemInitRef =
Data.FirstprivateInits.begin();
3645 for (
const Expr *E :
Data.FirstprivateVars) {
3647 Privates.emplace_back(
3655 I =
Data.LastprivateCopies.begin();
3656 for (
const Expr *E :
Data.LastprivateVars) {
3658 Privates.emplace_back(
3666 Privates.emplace_back(
CGM.getPointerAlign(), PrivateHelpersTy(VD));
3668 Privates.emplace_back(
C.getDeclAlign(VD), PrivateHelpersTy(VD));
3670 llvm::stable_sort(Privates,
3671 [](
const PrivateDataTy &L,
const PrivateDataTy &R) {
3672 return L.first > R.first;
3674 QualType KmpInt32Ty =
C.getIntTypeForBitwidth(32, 1);
3685 assert((D.getDirectiveKind() == OMPD_task ||
3688 "Expected taskloop, task or target directive");
3695 const auto *KmpTaskTQTyRD =
KmpTaskTQTy->castAsRecordDecl();
3697 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
3700 C.getCanonicalTagType(KmpTaskTWithPrivatesQTyRD);
3701 QualType KmpTaskTWithPrivatesPtrQTy =
3702 C.getPointerType(KmpTaskTWithPrivatesQTy);
3703 llvm::Type *KmpTaskTWithPrivatesPtrTy = CGF.
Builder.getPtrTy(0);
3704 llvm::Value *KmpTaskTWithPrivatesTySize =
3706 QualType SharedsPtrTy =
C.getPointerType(SharedsTy);
3709 llvm::Value *TaskPrivatesMap =
nullptr;
3710 llvm::Type *TaskPrivatesMapTy =
3711 std::next(TaskFunction->arg_begin(), 3)->getType();
3712 if (!Privates.empty()) {
3713 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->
field_begin());
3717 TaskPrivatesMap, TaskPrivatesMapTy);
3719 TaskPrivatesMap = llvm::ConstantPointerNull::get(
3725 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
3726 KmpTaskTWithPrivatesQTy,
KmpTaskTQTy, SharedsPtrTy, TaskFunction,
3738 DestructorsFlag = 0x8,
3739 PriorityFlag = 0x20,
3740 DetachableFlag = 0x40,
3741 FreeAgentFlag = 0x80,
3743 unsigned Flags =
Data.Tied ? TiedFlag : 0;
3744 bool NeedsCleanup =
false;
3745 if (!Privates.empty()) {
3749 Flags = Flags | DestructorsFlag;
3753 if (Kind == OMPC_THREADSET_omp_pool)
3754 Flags = Flags | FreeAgentFlag;
3756 if (
Data.Priority.getInt())
3757 Flags = Flags | PriorityFlag;
3759 Flags = Flags | DetachableFlag;
3760 llvm::Value *TaskFlags =
3761 Data.Final.getPointer()
3762 ? CGF.
Builder.CreateSelect(
Data.Final.getPointer(),
3763 CGF.
Builder.getInt32(FinalFlag),
3765 : CGF.
Builder.getInt32(
Data.Final.getInt() ? FinalFlag : 0);
3766 TaskFlags = CGF.
Builder.CreateOr(TaskFlags, CGF.
Builder.getInt32(Flags));
3767 llvm::Value *SharedsSize =
CGM.getSize(
C.getTypeSizeInChars(SharedsTy));
3769 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
3772 llvm::Value *NewTask;
3779 llvm::Value *DeviceID;
3784 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
3785 AllocArgs.push_back(DeviceID);
3788 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc),
3793 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc),
3806 llvm::Value *Tid =
getThreadID(CGF, DC->getBeginLoc());
3807 Tid = CGF.
Builder.CreateIntCast(Tid, CGF.
IntTy,
false);
3810 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event),
3811 {Loc, Tid, NewTask});
3822 llvm::Value *NumOfElements =
nullptr;
3823 unsigned NumAffinities = 0;
3825 if (
const Expr *Modifier =
C->getModifier()) {
3827 for (
unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) {
3831 NumOfElements ? CGF.
Builder.CreateNUWMul(NumOfElements, Sz) : Sz;
3834 NumAffinities +=
C->varlist_size();
3839 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags };
3841 QualType KmpTaskAffinityInfoArrayTy;
3842 if (NumOfElements) {
3843 NumOfElements = CGF.
Builder.CreateNUWAdd(
3844 llvm::ConstantInt::get(CGF.
SizeTy, NumAffinities), NumOfElements);
3847 C.getIntTypeForBitwidth(
C.getTypeSize(
C.getSizeType()), 0),
3851 KmpTaskAffinityInfoArrayTy =
C.getVariableArrayType(
3859 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
3862 KmpTaskAffinityInfoArrayTy =
C.getConstantArrayType(
3864 llvm::APInt(
C.getTypeSize(
C.getSizeType()), NumAffinities),
nullptr,
3867 CGF.
CreateMemTemp(KmpTaskAffinityInfoArrayTy,
".affs.arr.addr");
3869 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumAffinities,
3876 bool HasIterator =
false;
3878 if (
C->getModifier()) {
3882 for (
const Expr *E :
C->varlist()) {
3891 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
3896 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
3910 const Expr *Modifier =
C->getModifier();
3913 OMPIteratorGeneratorScope IteratorScope(
3915 for (
const Expr *E :
C->varlist()) {
3925 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr));
3930 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len));
3932 Idx = CGF.
Builder.CreateNUWAdd(
3933 Idx, llvm::ConstantInt::get(Idx->getType(), 1));
3948 CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity),
3949 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr});
3951 llvm::Value *NewTaskNewTaskTTy =
3953 NewTask, KmpTaskTWithPrivatesPtrTy);
3955 KmpTaskTWithPrivatesQTy);
3966 *std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds)),
3968 CGF.
Int8Ty,
CGM.getNaturalTypeAlignment(SharedsTy));
3975 if (!Privates.empty()) {
3977 SharedsTy, SharedsPtrTy,
Data, Privates,
3982 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
3983 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy,
Data, Privates,
3984 !
Data.LastprivateVars.empty());
3988 enum { Priority = 0, Destructors = 1 };
3990 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
3991 const auto *KmpCmplrdataUD = (*FI)->getType()->castAsRecordDecl();
3992 assert(KmpCmplrdataUD->isUnion());
3995 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
3996 KmpTaskTWithPrivatesQTy);
3999 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
4005 if (
Data.Priority.getInt()) {
4007 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
4009 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
4012 Result.NewTask = NewTask;
4013 Result.TaskEntry = TaskEntry;
4014 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
4016 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
4022 RTLDependenceKindTy DepKind;
4024 case OMPC_DEPEND_in:
4025 DepKind = RTLDependenceKindTy::DepIn;
4028 case OMPC_DEPEND_out:
4029 case OMPC_DEPEND_inout:
4030 DepKind = RTLDependenceKindTy::DepInOut;
4032 case OMPC_DEPEND_mutexinoutset:
4033 DepKind = RTLDependenceKindTy::DepMutexInOutSet;
4035 case OMPC_DEPEND_inoutset:
4036 DepKind = RTLDependenceKindTy::DepInOutSet;
4038 case OMPC_DEPEND_outallmemory:
4039 DepKind = RTLDependenceKindTy::DepOmpAllMem;
4041 case OMPC_DEPEND_source:
4042 case OMPC_DEPEND_sink:
4043 case OMPC_DEPEND_depobj:
4044 case OMPC_DEPEND_inoutallmemory:
4046 llvm_unreachable(
"Unknown task dependence type");
4054 FlagsTy =
C.getIntTypeForBitwidth(
C.getTypeSize(
C.BoolTy),
false);
4055 if (KmpDependInfoTy.
isNull()) {
4056 RecordDecl *KmpDependInfoRD =
C.buildImplicitRecord(
"kmp_depend_info");
4062 KmpDependInfoTy =
C.getCanonicalTagType(KmpDependInfoRD);
4066std::pair<llvm::Value *, LValue>
4079 CGF,
Base.getAddress(),
4080 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4086 *std::next(KmpDependInfoRD->field_begin(),
4087 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4089 return std::make_pair(NumDeps,
Base);
4093 llvm::PointerUnion<unsigned *, LValue *> Pos,
4103 OMPIteratorGeneratorScope IteratorScope(
4104 CGF, cast_or_null<OMPIteratorExpr>(
4105 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4107 for (
const Expr *E :
Data.DepExprs) {
4117 Size = llvm::ConstantInt::get(CGF.
SizeTy, 0);
4120 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4124 assert(E &&
"Expected a non-null expression");
4133 *std::next(KmpDependInfoRD->field_begin(),
4134 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4138 Base, *std::next(KmpDependInfoRD->field_begin(),
4139 static_cast<unsigned int>(RTLDependInfoFields::Len)));
4145 *std::next(KmpDependInfoRD->field_begin(),
4146 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4148 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4150 if (
unsigned *P = dyn_cast<unsigned *>(Pos)) {
4155 Idx = CGF.
Builder.CreateNUWAdd(Idx,
4156 llvm::ConstantInt::get(Idx->getType(), 1));
4165 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4166 "Expected depobj dependency kind.");
4171 OMPIteratorGeneratorScope IteratorScope(
4172 CGF, cast_or_null<OMPIteratorExpr>(
4173 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4175 for (
const Expr *E :
Data.DepExprs) {
4176 llvm::Value *NumDeps;
4179 std::tie(NumDeps,
Base) =
4183 C.getUIntPtrType());
4187 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(PrevVal, NumDeps);
4189 SizeLVals.push_back(NumLVal);
4192 for (
unsigned I = 0, E = SizeLVals.size(); I < E; ++I) {
4195 Sizes.push_back(Size);
4205 assert(
Data.DepKind == OMPC_DEPEND_depobj &&
4206 "Expected depobj dependency kind.");
4209 OMPIteratorGeneratorScope IteratorScope(
4210 CGF, cast_or_null<OMPIteratorExpr>(
4211 Data.IteratorExpr ?
Data.IteratorExpr->IgnoreParenImpCasts()
4213 for (
const Expr *E :
Data.DepExprs) {
4214 llvm::Value *NumDeps;
4217 std::tie(NumDeps,
Base) =
4221 llvm::Value *Size = CGF.
Builder.CreateNUWMul(
4230 llvm::Value *Add = CGF.
Builder.CreateNUWAdd(Pos, NumDeps);
4246 llvm::Value *NumOfElements =
nullptr;
4247 unsigned NumDependencies = std::accumulate(
4248 Dependencies.begin(), Dependencies.end(), 0,
4250 return D.DepKind == OMPC_DEPEND_depobj
4252 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size()));
4256 bool HasDepobjDeps =
false;
4257 bool HasRegularWithIterators =
false;
4258 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4259 llvm::Value *NumOfRegularWithIterators =
4260 llvm::ConstantInt::get(CGF.
IntPtrTy, 0);
4264 if (D.
DepKind == OMPC_DEPEND_depobj) {
4267 for (llvm::Value *Size : Sizes) {
4268 NumOfDepobjElements =
4269 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, Size);
4271 HasDepobjDeps =
true;
4276 if (
const auto *IE = cast_or_null<OMPIteratorExpr>(D.
IteratorExpr)) {
4277 llvm::Value *ClauseIteratorSpace =
4278 llvm::ConstantInt::get(CGF.
IntPtrTy, 1);
4282 ClauseIteratorSpace = CGF.
Builder.CreateNUWMul(Sz, ClauseIteratorSpace);
4284 llvm::Value *NumClauseDeps = CGF.
Builder.CreateNUWMul(
4285 ClauseIteratorSpace,
4287 NumOfRegularWithIterators =
4288 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumClauseDeps);
4289 HasRegularWithIterators =
true;
4295 if (HasDepobjDeps || HasRegularWithIterators) {
4296 NumOfElements = llvm::ConstantInt::get(
CGM.IntPtrTy, NumDependencies,
4298 if (HasDepobjDeps) {
4300 CGF.
Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements);
4302 if (HasRegularWithIterators) {
4304 CGF.
Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements);
4307 Loc,
C.getIntTypeForBitwidth(64, 0),
4311 KmpDependInfoArrayTy =
4320 NumOfElements = CGF.
Builder.CreateIntCast(NumOfElements, CGF.
Int32Ty,
4323 KmpDependInfoArrayTy =
C.getConstantArrayType(
4329 NumOfElements = llvm::ConstantInt::get(
CGM.Int32Ty, NumDependencies,
4334 if (Dep.DepKind == OMPC_DEPEND_depobj || Dep.IteratorExpr)
4340 CGF.
CreateMemTemp(
C.getSizeType(),
"dep.counter.addr"),
C.getSizeType());
4343 if (Dep.DepKind == OMPC_DEPEND_depobj || !Dep.IteratorExpr)
4348 if (HasDepobjDeps) {
4350 if (Dep.DepKind != OMPC_DEPEND_depobj)
4357 return std::make_pair(NumOfElements, DependenciesArray);
4368 unsigned NumDependencies = Dependencies.
DepExprs.size();
4378 llvm::Value *NumDepsVal;
4380 if (
const auto *IE =
4381 cast_or_null<OMPIteratorExpr>(Dependencies.
IteratorExpr)) {
4382 NumDepsVal = llvm::ConstantInt::get(CGF.
SizeTy, 1);
4386 NumDepsVal = CGF.
Builder.CreateNUWMul(NumDepsVal, Sz);
4388 Size = CGF.
Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.
SizeTy, 1),
4392 llvm::Value *RecSize =
CGM.getSize(SizeInBytes);
4393 Size = CGF.
Builder.CreateNUWMul(Size, RecSize);
4397 QualType KmpDependInfoArrayTy =
C.getConstantArrayType(
4400 CharUnits Sz =
C.getTypeSizeInChars(KmpDependInfoArrayTy);
4402 NumDepsVal = llvm::ConstantInt::get(CGF.
IntPtrTy, NumDependencies);
4407 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4408 llvm::Value *Args[] = {ThreadID, Size, Allocator};
4412 CGM.getModule(), OMPRTL___kmpc_alloc),
4413 Args,
".dep.arr.addr");
4417 DependenciesArray =
Address(
Addr, KmpDependInfoLlvmTy, Align);
4423 *std::next(KmpDependInfoRD->field_begin(),
4424 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr)));
4426 llvm::PointerUnion<unsigned *, LValue *> Pos;
4443 return DependenciesArray;
4458 Addr.getElementType(),
Addr.emitRawPointer(CGF),
4459 llvm::ConstantInt::get(CGF.
IntPtrTy, -1,
true));
4464 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4465 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator};
4469 CGM.getModule(), OMPRTL___kmpc_free),
4481 llvm::Value *NumDeps;
4492 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4494 llvm::PHINode *ElementPHI =
4499 Base.getTBAAInfo());
4503 Base, *std::next(KmpDependInfoRD->field_begin(),
4504 static_cast<unsigned int>(RTLDependInfoFields::Flags)));
4506 llvm::ConstantInt::get(LLVMFlagsTy,
static_cast<unsigned int>(DepKind)),
4510 llvm::Value *ElementNext =
4513 ElementPHI->addIncoming(ElementNext, CGF.
Builder.GetInsertBlock());
4514 llvm::Value *IsEmpty =
4515 CGF.
Builder.CreateICmpEQ(ElementNext, End,
"omp.isempty");
4516 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4523 llvm::Function *TaskFunction,
4532 llvm::Value *NewTask =
Result.NewTask;
4533 llvm::Function *TaskEntry =
Result.TaskEntry;
4534 llvm::Value *NewTaskNewTaskTTy =
Result.NewTaskNewTaskTTy;
4539 llvm::Value *NumOfElements;
4540 std::tie(NumOfElements, DependenciesArray) =
4551 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
4552 llvm::Value *DepTaskArgs[7];
4553 if (!
Data.Dependences.empty()) {
4554 DepTaskArgs[0] = UpLoc;
4555 DepTaskArgs[1] = ThreadID;
4556 DepTaskArgs[2] = NewTask;
4557 DepTaskArgs[3] = NumOfElements;
4559 DepTaskArgs[5] = CGF.
Builder.getInt32(0);
4560 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4562 auto &&ThenCodeGen = [
this, &
Data, TDBase, KmpTaskTQTyRD, &TaskArgs,
4565 auto PartIdFI = std::next(KmpTaskTQTyRD->
field_begin(), KmpTaskTPartId);
4569 if (!
Data.Dependences.empty()) {
4572 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps),
4576 CGM.getModule(), OMPRTL___kmpc_omp_task),
4582 Region->emitUntiedSwitch(CGF);
4585 llvm::Value *DepWaitTaskArgs[7];
4586 if (!
Data.Dependences.empty()) {
4587 DepWaitTaskArgs[0] = UpLoc;
4588 DepWaitTaskArgs[1] = ThreadID;
4589 DepWaitTaskArgs[2] = NumOfElements;
4591 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
4592 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
4593 DepWaitTaskArgs[6] =
4594 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
4596 auto &M =
CGM.getModule();
4597 auto &&ElseCodeGen = [
this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy,
4598 TaskEntry, &
Data, &DepWaitTaskArgs,
4605 if (!
Data.Dependences.empty())
4607 M, OMPRTL___kmpc_omp_taskwait_deps_51),
4610 auto &&
CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
4613 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
4614 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
4623 CommonActionTy Action(
OMPBuilder.getOrCreateRuntimeFunction(
4624 M, OMPRTL___kmpc_omp_task_begin_if0),
4627 M, OMPRTL___kmpc_omp_task_complete_if0),
4643 llvm::Function *TaskFunction,
4663 IfVal = llvm::ConstantInt::getSigned(CGF.
IntTy, 1);
4668 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
4675 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
4682 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
4690 *std::next(
Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
4691 if (
Data.Reductions) {
4697 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
4706 llvm::ConstantInt::getSigned(
4708 llvm::ConstantInt::getSigned(
4710 ?
Data.Schedule.getInt() ? NumTasks : Grainsize
4712 Data.Schedule.getPointer()
4715 : llvm::ConstantInt::get(CGF.
Int64Ty, 0)};
4716 if (
Data.HasModifier)
4717 TaskArgs.push_back(llvm::ConstantInt::get(CGF.
Int32Ty, 1));
4719 TaskArgs.push_back(
Result.TaskDupFn
4722 : llvm::ConstantPointerNull::get(CGF.
VoidPtrTy));
4724 CGM.getModule(),
Data.HasModifier
4725 ? OMPRTL___kmpc_taskloop_5
4726 : OMPRTL___kmpc_taskloop),
4743 const Expr *,
const Expr *)> &RedOpGen,
4744 const Expr *XExpr =
nullptr,
const Expr *EExpr =
nullptr,
4745 const Expr *UpExpr =
nullptr) {
4753 llvm::Value *NumElements = CGF.
emitArrayLength(ArrayTy, ElementTy, LHSAddr);
4758 llvm::Value *LHSEnd =
4763 llvm::Value *IsEmpty =
4764 CGF.
Builder.CreateICmpEQ(LHSBegin, LHSEnd,
"omp.arraycpy.isempty");
4765 CGF.
Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
4768 llvm::BasicBlock *EntryBB = CGF.
Builder.GetInsertBlock();
4773 llvm::PHINode *RHSElementPHI = CGF.
Builder.CreatePHI(
4774 RHSBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
4775 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
4780 llvm::PHINode *LHSElementPHI = CGF.
Builder.CreatePHI(
4781 LHSBegin->getType(), 2,
"omp.arraycpy.destElementPast");
4782 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
4789 Scope.addPrivate(LHSVar, LHSElementCurrent);
4790 Scope.addPrivate(RHSVar, RHSElementCurrent);
4792 RedOpGen(CGF, XExpr, EExpr, UpExpr);
4793 Scope.ForceCleanup();
4796 llvm::Value *LHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4798 "omp.arraycpy.dest.element");
4799 llvm::Value *RHSElementNext = CGF.
Builder.CreateConstGEP1_32(
4801 "omp.arraycpy.src.element");
4804 CGF.
Builder.CreateICmpEQ(LHSElementNext, LHSEnd,
"omp.arraycpy.done");
4805 CGF.
Builder.CreateCondBr(Done, DoneBB, BodyBB);
4806 LHSElementPHI->addIncoming(LHSElementNext, CGF.
Builder.GetInsertBlock());
4807 RHSElementPHI->addIncoming(RHSElementNext, CGF.
Builder.GetInsertBlock());
4817 const Expr *ReductionOp) {
4818 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp))
4819 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
4820 if (
const auto *DRE =
4821 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
4822 if (
const auto *DRD =
4823 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
4824 std::pair<llvm::Function *, llvm::Function *>
Reduction =
4835 StringRef ReducerName,
SourceLocation Loc, llvm::Type *ArgsElemType,
4846 Args.push_back(&LHSArg);
4847 Args.push_back(&RHSArg);
4849 CGM.getTypes().arrangeBuiltinFunctionDeclaration(
C.VoidTy, Args);
4851 auto *Fn = llvm::Function::Create(
CGM.getTypes().GetFunctionType(CGFI),
4852 llvm::GlobalValue::InternalLinkage, Name,
4855 Fn->setDoesNotRecurse();
4874 const auto *IPriv = Privates.begin();
4876 for (
unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
4877 const auto *RHSVar =
4880 const auto *LHSVar =
4883 QualType PrivTy = (*IPriv)->getType();
4898 IPriv = Privates.begin();
4899 const auto *ILHS = LHSExprs.begin();
4900 const auto *IRHS = RHSExprs.begin();
4901 for (
const Expr *E : ReductionOps) {
4902 if ((*IPriv)->getType()->isArrayType()) {
4907 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
4909 emitReductionCombiner(CGF, E);
4919 Scope.ForceCleanup();
4925 const Expr *ReductionOp,
4926 const Expr *PrivateRef,
4934 CGF, PrivateRef->
getType(), LHSVar, RHSVar,
4936 emitReductionCombiner(CGF, ReductionOp);
4945 llvm::StringRef Prefix,
const Expr *Ref);
4949 const Expr *LHSExprs,
const Expr *RHSExprs,
const Expr *ReductionOps) {
4976 std::string ReductionVarNameStr;
4978 ReductionVarNameStr =
4981 ReductionVarNameStr =
"unnamed_priv_var";
4984 std::string SharedName =
4985 CGM.getOpenMPRuntime().getName({
"internal_pivate_", ReductionVarNameStr});
4986 llvm::GlobalVariable *SharedVar =
OMPBuilder.getOrCreateInternalVariable(
4987 LLVMType,
".omp.reduction." + SharedName);
4989 SharedVar->setAlignment(
4997 llvm::Value *BarrierArgs[] = {BarrierLoc, ThreadId};
5002 llvm::Value *IsWorker = CGF.
Builder.CreateICmpEQ(
5003 ThreadId, llvm::ConstantInt::get(ThreadId->getType(), 0));
5004 CGF.
Builder.CreateCondBr(IsWorker, InitBB, InitEndBB);
5008 auto EmitSharedInit = [&]() {
5011 std::pair<llvm::Function *, llvm::Function *> FnPair =
5013 llvm::Function *InitializerFn = FnPair.second;
5014 if (InitializerFn) {
5015 if (
const auto *CE =
5016 dyn_cast<CallExpr>(UDRInitExpr->IgnoreParenImpCasts())) {
5023 LocalScope.addPrivate(OutVD, SharedResult);
5025 (void)LocalScope.Privatize();
5026 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(
5027 CE->getCallee()->IgnoreParenImpCasts())) {
5053 if (
const auto *DRE = dyn_cast<DeclRefExpr>(Privates)) {
5054 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
5065 CGF.
Builder.CreateBr(InitEndBB);
5069 CGM.getModule(), OMPRTL___kmpc_barrier),
5072 const Expr *ReductionOp = ReductionOps;
5077 auto EmitCriticalReduction = [&](
auto ReductionGen) {
5078 std::string CriticalName =
getName({
"reduction_critical"});
5086 std::pair<llvm::Function *, llvm::Function *> FnPair =
5089 if (
const auto *CE = dyn_cast<CallExpr>(ReductionOp)) {
5101 (void)LocalScope.Privatize();
5106 EmitCriticalReduction(ReductionGen);
5111 if (
const auto *Cleanup = dyn_cast<ExprWithCleanups>(ReductionClauseExpr))
5114 const Expr *AssignRHS =
nullptr;
5115 if (
const auto *BinOp = dyn_cast<BinaryOperator>(ReductionClauseExpr)) {
5116 if (BinOp->getOpcode() == BO_Assign)
5117 AssignRHS = BinOp->getRHS();
5118 }
else if (
const auto *OpCall =
5119 dyn_cast<CXXOperatorCallExpr>(ReductionClauseExpr)) {
5120 if (OpCall->getOperator() == OO_Equal)
5121 AssignRHS = OpCall->getArg(1);
5125 "Private Variable Reduction : Invalid ReductionOp expression");
5130 const auto *OmpOutDRE =
5132 const auto *OmpInDRE =
5135 OmpOutDRE && OmpInDRE &&
5136 "Private Variable Reduction : LHSExpr/RHSExpr must be DeclRefExprs");
5140 LocalScope.addPrivate(OmpOutVD, SharedLV.
getAddress());
5141 LocalScope.addPrivate(OmpInVD, LHSLV.
getAddress());
5142 (void)LocalScope.Privatize();
5146 EmitCriticalReduction(ReductionGen);
5150 CGM.getModule(), OMPRTL___kmpc_barrier),
5156 llvm::Value *FinalResultVal =
nullptr;
5160 FinalResultAddr = SharedResult;
5174 CGM.getModule(), OMPRTL___kmpc_barrier),
5185 EmitCriticalReduction(OriginalListCombiner);
5237 if (SimpleReduction) {
5239 const auto *IPriv = OrgPrivates.begin();
5240 const auto *ILHS = OrgLHSExprs.begin();
5241 const auto *IRHS = OrgRHSExprs.begin();
5242 for (
const Expr *E : OrgReductionOps) {
5255 FilteredRHSExprs, FilteredReductionOps;
5256 for (
unsigned I : llvm::seq<unsigned>(
5257 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5259 FilteredPrivates.emplace_back(OrgPrivates[I]);
5260 FilteredLHSExprs.emplace_back(OrgLHSExprs[I]);
5261 FilteredRHSExprs.emplace_back(OrgRHSExprs[I]);
5262 FilteredReductionOps.emplace_back(OrgReductionOps[I]);
5274 auto Size = RHSExprs.size();
5275 for (
const Expr *E : Privates) {
5280 llvm::APInt ArraySize(32, Size);
5281 QualType ReductionArrayTy =
C.getConstantArrayType(
5285 CGF.
CreateMemTemp(ReductionArrayTy,
".omp.reduction.red_list");
5286 const auto *IPriv = Privates.begin();
5288 for (
unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
5294 if ((*IPriv)->getType()->isVariablyModifiedType()) {
5298 llvm::Value *Size = CGF.
Builder.CreateIntCast(
5311 Privates, LHSExprs, RHSExprs, ReductionOps);
5314 std::string Name =
getName({
"reduction"});
5321 llvm::Value *ReductionArrayTySize = CGF.
getTypeSize(ReductionArrayTy);
5324 llvm::Value *Args[] = {
5327 CGF.
Builder.getInt32(RHSExprs.size()),
5328 ReductionArrayTySize,
5336 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce),
5340 llvm::BasicBlock *DefaultBB = CGF.
createBasicBlock(
".omp.reduction.default");
5341 llvm::SwitchInst *SwInst =
5342 CGF.
Builder.CreateSwitch(Res, DefaultBB, 2);
5351 SwInst->addCase(CGF.
Builder.getInt32(1), Case1BB);
5355 llvm::Value *EndArgs[] = {
5360 auto &&
CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps](
5363 const auto *IPriv = Privates.begin();
5364 const auto *ILHS = LHSExprs.begin();
5365 const auto *IRHS = RHSExprs.begin();
5366 for (
const Expr *E : ReductionOps) {
5375 CommonActionTy Action(
5378 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait
5379 : OMPRTL___kmpc_end_reduce),
5392 SwInst->addCase(CGF.
Builder.getInt32(2), Case2BB);
5395 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps](
5397 const auto *ILHS = LHSExprs.begin();
5398 const auto *IRHS = RHSExprs.begin();
5399 const auto *IPriv = Privates.begin();
5400 for (
const Expr *E : ReductionOps) {
5401 const Expr *XExpr =
nullptr;
5402 const Expr *EExpr =
nullptr;
5403 const Expr *UpExpr =
nullptr;
5405 if (
const auto *BO = dyn_cast<BinaryOperator>(E)) {
5406 if (BO->getOpcode() == BO_Assign) {
5407 XExpr = BO->getLHS();
5408 UpExpr = BO->getRHS();
5412 const Expr *RHSExpr = UpExpr;
5415 if (
const auto *ACO = dyn_cast<AbstractConditionalOperator>(
5419 RHSExpr = ACO->getCond();
5421 if (
const auto *BORHS =
5423 EExpr = BORHS->getRHS();
5424 BO = BORHS->getOpcode();
5429 auto &&AtomicRedGen = [BO, VD,
5431 const Expr *EExpr,
const Expr *UpExpr) {
5432 LValue X = CGF.EmitLValue(XExpr);
5435 E = CGF.EmitAnyExpr(EExpr);
5436 CGF.EmitOMPAtomicSimpleUpdateExpr(
5438 llvm::AtomicOrdering::Monotonic, Loc,
5439 [&CGF, UpExpr, VD, Loc](
RValue XRValue) {
5441 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5442 CGF.emitOMPSimpleStore(
5443 CGF.MakeAddrLValue(LHSTemp, VD->
getType()), XRValue,
5444 VD->getType().getNonReferenceType(), Loc);
5447 return CGF.EmitAnyExpr(UpExpr);
5450 if ((*IPriv)->getType()->isArrayType()) {
5452 const auto *RHSVar =
5455 AtomicRedGen, XExpr, EExpr, UpExpr);
5458 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
5465 std::string Name = RT.
getName({
"atomic_reduction"});
5474 if ((*IPriv)->getType()->isArrayType()) {
5475 const auto *LHSVar =
5477 const auto *RHSVar =
5482 CritRedGen(CGF,
nullptr,
nullptr,
nullptr);
5493 llvm::Value *EndArgs[] = {
5498 CommonActionTy Action(
nullptr, {},
5500 CGM.getModule(), OMPRTL___kmpc_end_reduce),
5510 assert(OrgLHSExprs.size() == OrgPrivates.size() &&
5511 "PrivateVarReduction: Privates size mismatch");
5512 assert(OrgLHSExprs.size() == OrgReductionOps.size() &&
5513 "PrivateVarReduction: ReductionOps size mismatch");
5514 for (
unsigned I : llvm::seq<unsigned>(
5515 std::min(OrgReductionOps.size(), OrgLHSExprs.size()))) {
5518 OrgRHSExprs[I], OrgReductionOps[I]);
5527 llvm::raw_svector_ostream Out(Buffer);
5535 Out << Prefix << Name <<
"_"
5537 return std::string(Out.str());
5559 Args.emplace_back(&Param);
5560 Args.emplace_back(&ParamOrig);
5561 const auto &FnInfo =
5565 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5568 Fn->setDoesNotRecurse();
5575 llvm::Value *Size =
nullptr;
5618 const Expr *ReductionOp,
5620 const Expr *PrivateRef) {
5629 Args.emplace_back(&ParamInOut);
5630 Args.emplace_back(&ParamIn);
5631 const auto &FnInfo =
5635 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5638 Fn->setDoesNotRecurse();
5641 llvm::Value *Size =
nullptr;
5662 C.getPointerType(LHSVD->getType())->castAs<
PointerType>()));
5669 C.getPointerType(RHSVD->getType())->castAs<
PointerType>()));
5698 Args.emplace_back(&Param);
5699 const auto &FnInfo =
5703 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
5706 Fn->setDoesNotRecurse();
5711 llvm::Value *Size =
nullptr;
5746 RecordDecl *RD =
C.buildImplicitRecord(
"kmp_taskred_input_t");
5755 C, RD,
C.getIntTypeForBitwidth(32,
false));
5758 unsigned Size =
Data.ReductionVars.size();
5759 llvm::APInt ArraySize(64, Size);
5761 C.getConstantArrayType(RDType, ArraySize,
nullptr,
5766 Data.ReductionCopies,
Data.ReductionOps);
5767 for (
unsigned Cnt = 0; Cnt < Size; ++Cnt) {
5769 llvm::Value *Idxs[] = {llvm::ConstantInt::get(
CGM.SizeTy, 0),
5770 llvm::ConstantInt::get(
CGM.SizeTy, Cnt)};
5786 llvm::Value *SizeValInChars;
5787 llvm::Value *SizeVal;
5788 std::tie(SizeValInChars, SizeVal) = RCG.
getSizes(Cnt);
5794 bool DelayedCreation = !!SizeVal;
5795 SizeValInChars = CGF.
Builder.CreateIntCast(SizeValInChars,
CGM.SizeTy,
5806 llvm::Value *FiniAddr =
5807 Fini ? Fini : llvm::ConstantPointerNull::get(
CGM.VoidPtrTy);
5812 CGM, Loc, RCG, Cnt,
Data.ReductionOps[Cnt], LHSExprs[Cnt],
5813 RHSExprs[Cnt],
Data.ReductionCopies[Cnt]);
5817 if (DelayedCreation) {
5819 llvm::ConstantInt::get(
CGM.Int32Ty, 1,
true),
5824 if (
Data.IsReductionWithTaskMod) {
5830 llvm::Value *Args[] = {
5832 llvm::ConstantInt::get(
CGM.IntTy,
Data.IsWorksharingReduction ? 1 : 0,
5834 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
5839 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init),
5843 llvm::Value *Args[] = {
5846 llvm::ConstantInt::get(
CGM.IntTy, Size,
true),
5850 CGM.getModule(), OMPRTL___kmpc_taskred_init),
5856 bool IsWorksharingReduction) {
5862 llvm::Value *Args[] = {IdentTLoc, GTid,
5863 llvm::ConstantInt::get(
CGM.IntTy,
5864 IsWorksharingReduction ? 1 : 0,
5868 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini),
5880 llvm::Value *SizeVal = CGF.
Builder.CreateIntCast(Sizes.second,
CGM.SizeTy,
5883 CGF,
CGM.getContext().getSizeType(),
5891 llvm::Value *ReductionsPtr,
5904 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data),
5920 auto &M =
CGM.getModule();
5922 llvm::Value *NumOfElements;
5923 std::tie(NumOfElements, DependenciesArray) =
5925 if (!
Data.Dependences.empty()) {
5926 llvm::Value *DepWaitTaskArgs[7];
5927 DepWaitTaskArgs[0] = UpLoc;
5928 DepWaitTaskArgs[1] = ThreadID;
5929 DepWaitTaskArgs[2] = NumOfElements;
5931 DepWaitTaskArgs[4] = CGF.
Builder.getInt32(0);
5932 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
5933 DepWaitTaskArgs[6] =
5934 llvm::ConstantInt::get(CGF.
Int32Ty,
Data.HasNowaitClause);
5943 M, OMPRTL___kmpc_omp_taskwait_deps_51),
5950 llvm::Value *Args[] = {UpLoc, ThreadID};
5953 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_taskwait),
5958 if (
auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.
CapturedStmtInfo))
5959 Region->emitUntiedSwitch(CGF);
5968 InlinedOpenMPRegionRAII Region(CGF,
CodeGen, InnerKind, HasCancel,
5969 InnerKind != OMPD_critical &&
5970 InnerKind != OMPD_master &&
5971 InnerKind != OMPD_masked);
5986 RTCancelKind CancelKind = CancelNoreq;
5987 if (CancelRegion == OMPD_parallel)
5988 CancelKind = CancelParallel;
5989 else if (CancelRegion == OMPD_for)
5990 CancelKind = CancelLoop;
5991 else if (CancelRegion == OMPD_sections)
5992 CancelKind = CancelSections;
5994 assert(CancelRegion == OMPD_taskgroup);
5995 CancelKind = CancelTaskgroup;
6007 if (
auto *OMPRegionInfo =
6011 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
6012 llvm::Value *Args[] = {
6018 CGM.getModule(), OMPRTL___kmpc_cancellationpoint),
6027 CGF.
Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6029 if (CancelRegion == OMPD_parallel)
6047 auto &M =
CGM.getModule();
6048 if (
auto *OMPRegionInfo =
6050 auto &&ThenGen = [
this, &M, Loc, CancelRegion,
6053 llvm::Value *Args[] = {
6057 llvm::Value *
Result = CGF.EmitRuntimeCall(
6058 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args);
6063 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".cancel.exit");
6064 llvm::BasicBlock *ContBB = CGF.createBasicBlock(
".cancel.continue");
6065 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(
Result);
6066 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6067 CGF.EmitBlock(ExitBB);
6068 if (CancelRegion == OMPD_parallel)
6072 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6073 CGF.EmitBranchThroughCleanup(CancelDest);
6074 CGF.EmitBlock(ContBB,
true);
6092 OMPUsesAllocatorsActionTy(
6093 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators)
6094 : Allocators(Allocators) {}
6098 for (
const auto &AllocatorData : Allocators) {
6100 CGF, AllocatorData.first, AllocatorData.second);
6103 void Exit(CodeGenFunction &CGF)
override {
6106 for (
const auto &AllocatorData : Allocators) {
6108 AllocatorData.first);
6116 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6118 assert(!ParentName.empty() &&
"Invalid target entry parent name!");
6122 for (
unsigned I = 0, E =
C->getNumberOfAllocators(); I < E; ++I) {
6129 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators);
6130 CodeGen.setAction(UsesAllocatorAction);
6136 const Expr *Allocator,
6137 const Expr *AllocatorTraits) {
6139 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6141 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6142 llvm::Value *NumTraits = llvm::ConstantInt::get(
6146 .getLimitedValue());
6153 llvm::Value *Traits =
Addr.emitRawPointer(CGF);
6155 llvm::Value *AllocatorVal =
6157 CGM.getModule(), OMPRTL___kmpc_init_allocator),
6158 {ThreadId, MemSpaceHandle, NumTraits, Traits});
6170 const Expr *Allocator) {
6172 ThreadId = CGF.
Builder.CreateIntCast(ThreadId, CGF.
IntTy,
true);
6174 llvm::Value *AllocatorVal =
6181 OMPRTL___kmpc_destroy_allocator),
6182 {ThreadId, AllocatorVal});
6187 llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs) {
6188 assert(Attrs.MaxTeams.size() == 1 && Attrs.MaxThreads.size() == 1 &&
6189 "invalid default attrs structure");
6190 int32_t &MaxTeamsVal = Attrs.MaxTeams.front();
6191 int32_t &MaxThreadsVal = Attrs.MaxThreads.front();
6198 for (
auto *A :
C->getAttrs()) {
6199 int32_t AttrMinThreadsVal = 1, AttrMaxThreadsVal = -1;
6200 int32_t AttrMinBlocksVal = 1, AttrMaxBlocksVal = -1;
6201 if (
auto *
Attr = dyn_cast<CUDALaunchBoundsAttr>(A))
6202 CGM.handleCUDALaunchBoundsAttr(
nullptr,
Attr, &AttrMaxThreadsVal,
6203 &AttrMinBlocksVal, &AttrMaxBlocksVal);
6204 else if (
auto *
Attr = dyn_cast<AMDGPUFlatWorkGroupSizeAttr>(A))
6205 CGM.handleAMDGPUFlatWorkGroupSizeAttr(
6206 nullptr,
Attr,
nullptr, &AttrMinThreadsVal,
6207 &AttrMaxThreadsVal);
6211 Attrs.MinThreads = std::max(Attrs.MinThreads, AttrMinThreadsVal);
6212 if (AttrMaxThreadsVal > 0)
6213 MaxThreadsVal = MaxThreadsVal > 0
6214 ? std::min(MaxThreadsVal, AttrMaxThreadsVal)
6215 : AttrMaxThreadsVal;
6216 Attrs.MinTeams = std::max(Attrs.MinTeams, AttrMinBlocksVal);
6217 if (AttrMaxBlocksVal > 0)
6218 MaxTeamsVal = MaxTeamsVal > 0 ? std::min(MaxTeamsVal, AttrMaxBlocksVal)
6226 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6229 llvm::TargetRegionEntryInfo EntryInfo =
6233 llvm::OpenMPIRBuilder::FunctionGenCallback &&GenerateOutlinedFunction =
6234 [&CGF, &D, &
CodeGen](StringRef EntryFnName) {
6235 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
6237 CGOpenMPTargetRegionInfo CGInfo(CS,
CodeGen, EntryFnName);
6242 cantFail(
OMPBuilder.emitTargetRegionFunction(
6243 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
6249 CGM.getTargetCodeGenInfo().setTargetAttributes(
nullptr, OutlinedFn,
CGM);
6252 for (
auto *A :
C->getAttrs()) {
6253 if (
auto *
Attr = dyn_cast<AMDGPUWavesPerEUAttr>(A))
6254 CGM.handleAMDGPUWavesPerEUAttr(OutlinedFn,
Attr);
6272 while (
const auto *
C = dyn_cast_or_null<CompoundStmt>(Child)) {
6274 for (
const Stmt *S :
C->body()) {
6275 if (
const auto *E = dyn_cast<Expr>(S)) {
6284 if (
const auto *DS = dyn_cast<DeclStmt>(S)) {
6285 if (llvm::all_of(DS->decls(), [](
const Decl *D) {
6286 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6287 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6288 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6289 isa<UsingDirectiveDecl>(D) ||
6290 isa<OMPDeclareReductionDecl>(D) ||
6291 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6293 const auto *VD = dyn_cast<VarDecl>(D);
6296 return VD->hasGlobalStorage() || !VD->isUsed();
6306 Child = Child->IgnoreContainers();
6313 int32_t &MaxTeamsVal) {
6317 "Expected target-based executable directive.");
6318 switch (DirectiveKind) {
6320 const auto *CS = D.getInnermostCapturedStmt();
6323 const Stmt *ChildStmt =
6325 if (
const auto *NestedDir =
6326 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6335 MinTeamsVal = MaxTeamsVal = Constant->getExtValue();
6338 MinTeamsVal = MaxTeamsVal = 0;
6341 MinTeamsVal = MaxTeamsVal = 1;
6345 MinTeamsVal = MaxTeamsVal = -1;
6348 case OMPD_target_teams_loop:
6349 case OMPD_target_teams:
6350 case OMPD_target_teams_distribute:
6351 case OMPD_target_teams_distribute_simd:
6352 case OMPD_target_teams_distribute_parallel_for:
6353 case OMPD_target_teams_distribute_parallel_for_simd: {
6355 const Expr *NumTeams =
6359 MinTeamsVal = MaxTeamsVal = Constant->getExtValue();
6362 MinTeamsVal = MaxTeamsVal = 0;
6365 case OMPD_target_parallel:
6366 case OMPD_target_parallel_for:
6367 case OMPD_target_parallel_for_simd:
6368 case OMPD_target_parallel_loop:
6369 case OMPD_target_simd:
6370 MinTeamsVal = MaxTeamsVal = 1;
6374 case OMPD_parallel_for:
6375 case OMPD_parallel_loop:
6376 case OMPD_parallel_master:
6377 case OMPD_parallel_sections:
6379 case OMPD_parallel_for_simd:
6381 case OMPD_cancellation_point:
6383 case OMPD_threadprivate:
6394 case OMPD_taskyield:
6397 case OMPD_taskgroup:
6403 case OMPD_target_data:
6404 case OMPD_target_exit_data:
6405 case OMPD_target_enter_data:
6406 case OMPD_distribute:
6407 case OMPD_distribute_simd:
6408 case OMPD_distribute_parallel_for:
6409 case OMPD_distribute_parallel_for_simd:
6410 case OMPD_teams_distribute:
6411 case OMPD_teams_distribute_simd:
6412 case OMPD_teams_distribute_parallel_for:
6413 case OMPD_teams_distribute_parallel_for_simd:
6414 case OMPD_target_update:
6415 case OMPD_declare_simd:
6416 case OMPD_declare_variant:
6417 case OMPD_begin_declare_variant:
6418 case OMPD_end_declare_variant:
6419 case OMPD_declare_target:
6420 case OMPD_end_declare_target:
6421 case OMPD_declare_reduction:
6422 case OMPD_declare_mapper:
6424 case OMPD_taskloop_simd:
6425 case OMPD_master_taskloop:
6426 case OMPD_master_taskloop_simd:
6427 case OMPD_parallel_master_taskloop:
6428 case OMPD_parallel_master_taskloop_simd:
6430 case OMPD_metadirective:
6436 llvm_unreachable(
"Unexpected directive kind.");
6442 "Clauses associated with the teams directive expected to be emitted "
6443 "only for the host!");
6445 int32_t MinNT = -1, MaxNT = -1;
6446 const Expr *NumTeams =
6448 if (NumTeams !=
nullptr) {
6451 switch (DirectiveKind) {
6453 const auto *CS = D.getInnermostCapturedStmt();
6454 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6458 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6461 case OMPD_target_teams:
6462 case OMPD_target_teams_distribute:
6463 case OMPD_target_teams_distribute_simd:
6464 case OMPD_target_teams_distribute_parallel_for:
6465 case OMPD_target_teams_distribute_parallel_for_simd: {
6469 return Bld.CreateIntCast(NumTeamsVal, CGF.
Int32Ty,
6477 assert(MinNT == MaxNT &&
"Num threads ranges require handling here.");
6478 return llvm::ConstantInt::get(CGF.
Int32Ty, MinNT);
6486 const Expr **E, int32_t &UpperBound,
6487 bool UpperBoundOnly, llvm::Value **CondVal) {
6490 const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6497 if (CondVal && Dir->hasClausesOfKind<
OMPIfClause>()) {
6498 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6501 for (
const auto *
C : Dir->getClausesOfKind<
OMPIfClause>()) {
6502 if (
C->getNameModifier() == OMPD_unknown ||
6503 C->getNameModifier() == OMPD_parallel) {
6518 if (
const auto *PreInit =
6520 for (
const auto *I : PreInit->decls()) {
6521 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6537 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6539 const auto *NumThreadsClause =
6541 const Expr *NTExpr = NumThreadsClause->getNumThreads();
6542 if (NTExpr->isIntegerConstantExpr(CGF.
getContext()))
6543 if (
auto Constant = NTExpr->getIntegerConstantExpr(CGF.
getContext()))
6546 ? Constant->getZExtValue()
6547 : std::min(UpperBound,
6548 static_cast<int32_t
>(Constant->getZExtValue()));
6551 if (UpperBound == -1)
6556 if (
const auto *PreInit =
6557 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6558 for (
const auto *I : PreInit->decls()) {
6559 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6578 bool UpperBoundOnly, llvm::Value **CondVal,
const Expr **ThreadLimitExpr) {
6579 assert((!CGF.
getLangOpts().OpenMPIsTargetDevice || UpperBoundOnly) &&
6580 "Clauses associated with the teams directive expected to be emitted "
6581 "only for the host!");
6584 "Expected target-based executable directive.");
6586 const Expr *NT =
nullptr;
6587 const Expr **NTPtr = UpperBoundOnly ?
nullptr : &NT;
6589 auto CheckForConstExpr = [&](
const Expr *E,
const Expr **EPtr) {
6592 UpperBound = UpperBound ? Constant->getZExtValue()
6593 : std::min(UpperBound,
6594 int32_t(Constant->getZExtValue()));
6598 if (UpperBound == -1)
6604 auto ReturnSequential = [&]() {
6609 switch (DirectiveKind) {
6612 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6618 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6620 ThreadLimitClause = TLC;
6621 if (ThreadLimitExpr) {
6622 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6626 ThreadLimitClause->getThreadLimit().front()->getSourceRange());
6627 if (
const auto *PreInit =
6628 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6629 for (
const auto *I : PreInit->decls()) {
6630 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6642 if (ThreadLimitClause)
6643 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6645 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6648 CS = Dir->getInnermostCapturedStmt();
6651 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6654 CS = Dir->getInnermostCapturedStmt();
6655 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6657 return ReturnSequential();
6661 case OMPD_target_teams: {
6665 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6669 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6672 if (
const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6673 if (Dir->getDirectiveKind() == OMPD_distribute) {
6674 CS = Dir->getInnermostCapturedStmt();
6675 getNumThreads(CGF, CS, NTPtr, UpperBound, UpperBoundOnly, CondVal);
6680 case OMPD_target_teams_distribute:
6684 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6687 getNumThreads(CGF, D.getInnermostCapturedStmt(), NTPtr, UpperBound,
6688 UpperBoundOnly, CondVal);
6690 case OMPD_target_teams_loop:
6691 case OMPD_target_parallel_loop:
6692 case OMPD_target_parallel:
6693 case OMPD_target_parallel_for:
6694 case OMPD_target_parallel_for_simd:
6695 case OMPD_target_teams_distribute_parallel_for:
6696 case OMPD_target_teams_distribute_parallel_for_simd: {
6697 if (CondVal && D.hasClausesOfKind<
OMPIfClause>()) {
6699 for (
const auto *
C : D.getClausesOfKind<
OMPIfClause>()) {
6700 if (
C->getNameModifier() == OMPD_unknown ||
6701 C->getNameModifier() == OMPD_parallel) {
6711 return ReturnSequential();
6721 CheckForConstExpr(ThreadLimitClause->getThreadLimit().front(),
6727 CheckForConstExpr(NumThreadsClause->getNumThreads(),
nullptr);
6728 return NumThreadsClause->getNumThreads();
6732 case OMPD_target_teams_distribute_simd:
6733 case OMPD_target_simd:
6734 return ReturnSequential();
6738 llvm_unreachable(
"Unsupported directive kind.");
6743 llvm::Value *NumThreadsVal =
nullptr;
6744 llvm::Value *CondVal =
nullptr;
6745 llvm::Value *ThreadLimitVal =
nullptr;
6746 const Expr *ThreadLimitExpr =
nullptr;
6747 int32_t UpperBound = -1;
6750 CGF, D, UpperBound,
false, &CondVal,
6754 if (ThreadLimitExpr) {
6757 ThreadLimitVal = CGF.
Builder.CreateIntCast(ThreadLimitVal, CGF.
Int32Ty,
6762 if (UpperBound == 1) {
6763 NumThreadsVal = CGF.
Builder.getInt32(UpperBound);
6766 NumThreadsVal = CGF.
Builder.CreateIntCast(NumThreadsVal, CGF.
Int32Ty,
6768 }
else if (ThreadLimitVal) {
6771 NumThreadsVal = ThreadLimitVal;
6772 ThreadLimitVal =
nullptr;
6775 assert(!ThreadLimitVal &&
"Default not applicable with thread limit value");
6776 NumThreadsVal = CGF.
Builder.getInt32(0);
6783 NumThreadsVal = CGF.
Builder.CreateSelect(CondVal, NumThreadsVal,
6789 if (ThreadLimitVal) {
6790 NumThreadsVal = CGF.
Builder.CreateSelect(
6791 CGF.
Builder.CreateICmpULT(ThreadLimitVal, NumThreadsVal),
6792 ThreadLimitVal, NumThreadsVal);
6795 return NumThreadsVal;
6805class MappableExprsHandler {
6811 struct AttachPtrExprComparator {
6812 const MappableExprsHandler &Handler;
6814 mutable llvm::DenseMap<std::pair<const Expr *, const Expr *>,
bool>
6815 CachedEqualityComparisons;
6817 AttachPtrExprComparator(
const MappableExprsHandler &H) : Handler(H) {}
6818 AttachPtrExprComparator() =
delete;
6821 bool operator()(
const Expr *LHS,
const Expr *RHS)
const {
6826 const auto ItLHS = Handler.AttachPtrComponentDepthMap.find(LHS);
6827 const auto ItRHS = Handler.AttachPtrComponentDepthMap.find(RHS);
6829 std::optional<size_t> DepthLHS =
6830 (ItLHS != Handler.AttachPtrComponentDepthMap.end()) ? ItLHS->second
6832 std::optional<size_t> DepthRHS =
6833 (ItRHS != Handler.AttachPtrComponentDepthMap.end()) ? ItRHS->second
6837 if (!DepthLHS.has_value() && !DepthRHS.has_value()) {
6839 if (areEqual(LHS, RHS))
6842 return wasComputedBefore(LHS, RHS);
6844 if (!DepthLHS.has_value())
6846 if (!DepthRHS.has_value())
6850 if (DepthLHS.value() != DepthRHS.value())
6851 return DepthLHS.value() < DepthRHS.value();
6854 if (areEqual(LHS, RHS))
6857 return wasComputedBefore(LHS, RHS);
6863 bool areEqual(
const Expr *LHS,
const Expr *RHS)
const {
6865 const auto CachedResultIt = CachedEqualityComparisons.find({LHS, RHS});
6866 if (CachedResultIt != CachedEqualityComparisons.end())
6867 return CachedResultIt->second;
6881 bool wasComputedBefore(
const Expr *LHS,
const Expr *RHS)
const {
6882 const size_t &OrderLHS = Handler.AttachPtrComputationOrderMap.at(LHS);
6883 const size_t &OrderRHS = Handler.AttachPtrComputationOrderMap.at(RHS);
6885 return OrderLHS < OrderRHS;
6894 bool areSemanticallyEqual(
const Expr *LHS,
const Expr *RHS)
const {
6916 if (
const auto *LD = dyn_cast<DeclRefExpr>(LHS)) {
6917 const auto *RD = dyn_cast<DeclRefExpr>(RHS);
6920 return LD->getDecl()->getCanonicalDecl() ==
6921 RD->getDecl()->getCanonicalDecl();
6925 if (
const auto *LA = dyn_cast<ArraySubscriptExpr>(LHS)) {
6926 const auto *RA = dyn_cast<ArraySubscriptExpr>(RHS);
6929 return areSemanticallyEqual(LA->getBase(), RA->getBase()) &&
6930 areSemanticallyEqual(LA->getIdx(), RA->getIdx());
6934 if (
const auto *LM = dyn_cast<MemberExpr>(LHS)) {
6935 const auto *RM = dyn_cast<MemberExpr>(RHS);
6938 if (LM->getMemberDecl()->getCanonicalDecl() !=
6939 RM->getMemberDecl()->getCanonicalDecl())
6941 return areSemanticallyEqual(LM->getBase(), RM->getBase());
6945 if (
const auto *LU = dyn_cast<UnaryOperator>(LHS)) {
6946 const auto *RU = dyn_cast<UnaryOperator>(RHS);
6949 if (LU->getOpcode() != RU->getOpcode())
6951 return areSemanticallyEqual(LU->getSubExpr(), RU->getSubExpr());
6955 if (
const auto *LB = dyn_cast<BinaryOperator>(LHS)) {
6956 const auto *RB = dyn_cast<BinaryOperator>(RHS);
6959 if (LB->getOpcode() != RB->getOpcode())
6961 return areSemanticallyEqual(LB->getLHS(), RB->getLHS()) &&
6962 areSemanticallyEqual(LB->getRHS(), RB->getRHS());
6968 if (
const auto *LAS = dyn_cast<ArraySectionExpr>(LHS)) {
6969 const auto *RAS = dyn_cast<ArraySectionExpr>(RHS);
6972 return areSemanticallyEqual(LAS->getBase(), RAS->getBase()) &&
6973 areSemanticallyEqual(LAS->getLowerBound(),
6974 RAS->getLowerBound()) &&
6975 areSemanticallyEqual(LAS->getLength(), RAS->getLength());
6979 if (
const auto *LC = dyn_cast<CastExpr>(LHS)) {
6980 const auto *RC = dyn_cast<CastExpr>(RHS);
6983 if (LC->getCastKind() != RC->getCastKind())
6985 return areSemanticallyEqual(LC->getSubExpr(), RC->getSubExpr());
6993 if (
const auto *LI = dyn_cast<IntegerLiteral>(LHS)) {
6994 const auto *RI = dyn_cast<IntegerLiteral>(RHS);
6997 return LI->getValue() == RI->getValue();
7001 if (
const auto *LC = dyn_cast<CharacterLiteral>(LHS)) {
7002 const auto *RC = dyn_cast<CharacterLiteral>(RHS);
7005 return LC->getValue() == RC->getValue();
7009 if (
const auto *LF = dyn_cast<FloatingLiteral>(LHS)) {
7010 const auto *RF = dyn_cast<FloatingLiteral>(RHS);
7014 return LF->getValue().bitwiseIsEqual(RF->getValue());
7018 if (
const auto *LS = dyn_cast<StringLiteral>(LHS)) {
7019 const auto *RS = dyn_cast<StringLiteral>(RHS);
7022 return LS->getString() == RS->getString();
7030 if (
const auto *LB = dyn_cast<CXXBoolLiteralExpr>(LHS)) {
7031 const auto *RB = dyn_cast<CXXBoolLiteralExpr>(RHS);
7034 return LB->getValue() == RB->getValue();
7043 static unsigned getFlagMemberOffset() {
7044 unsigned Offset = 0;
7045 for (uint64_t Remain =
7046 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
7047 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
7048 !(Remain & 1); Remain = Remain >> 1)
7055 class MappingExprInfo {
7057 const ValueDecl *MapDecl =
nullptr;
7060 const Expr *MapExpr =
nullptr;
7063 MappingExprInfo(
const ValueDecl *MapDecl,
const Expr *MapExpr =
nullptr)
7064 : MapDecl(MapDecl), MapExpr(MapExpr) {}
7066 const ValueDecl *getMapDecl()
const {
return MapDecl; }
7067 const Expr *getMapExpr()
const {
return MapExpr; }
7070 using DeviceInfoTy = llvm::OpenMPIRBuilder::DeviceInfoTy;
7071 using MapBaseValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7072 using MapValuesArrayTy = llvm::OpenMPIRBuilder::MapValuesArrayTy;
7073 using MapFlagsArrayTy = llvm::OpenMPIRBuilder::MapFlagsArrayTy;
7074 using MapDimArrayTy = llvm::OpenMPIRBuilder::MapDimArrayTy;
7075 using MapNonContiguousArrayTy =
7076 llvm::OpenMPIRBuilder::MapNonContiguousArrayTy;
7077 using MapExprsArrayTy = SmallVector<MappingExprInfo, 4>;
7078 using MapValueDeclsArrayTy = SmallVector<const ValueDecl *, 4>;
7082 bool ,
const ValueDecl *,
const Expr *>;
7083 using MapDataArrayTy = SmallVector<MapData, 4>;
7088 struct MapCombinedInfoTy : llvm::OpenMPIRBuilder::MapInfosTy {
7089 MapExprsArrayTy Exprs;
7090 MapValueDeclsArrayTy Mappers;
7091 MapValueDeclsArrayTy DevicePtrDecls;
7094 void append(MapCombinedInfoTy &CurInfo) {
7095 Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end());
7096 DevicePtrDecls.append(CurInfo.DevicePtrDecls.begin(),
7097 CurInfo.DevicePtrDecls.end());
7098 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end());
7099 llvm::OpenMPIRBuilder::MapInfosTy::append(CurInfo);
7107 struct StructRangeInfoTy {
7108 MapCombinedInfoTy PreliminaryMapData;
7109 std::pair<
unsigned , Address > LowestElem = {
7111 std::pair<
unsigned , Address > HighestElem = {
7115 bool IsArraySection =
false;
7116 bool HasCompleteRecord =
false;
7121 struct AttachInfoTy {
7124 const ValueDecl *AttachPtrDecl =
nullptr;
7125 const Expr *AttachMapExpr =
nullptr;
7127 bool isValid()
const {
7134 bool hasAttachEntryForCapturedVar(
const ValueDecl *VD)
const {
7135 for (
const auto &AttachEntry : AttachPtrExprMap) {
7136 if (AttachEntry.second) {
7139 if (
const auto *DRE = dyn_cast<DeclRefExpr>(AttachEntry.second))
7140 if (DRE->getDecl() == VD)
7148 const Expr *getAttachPtrExpr(
7151 const auto It = AttachPtrExprMap.find(Components);
7152 if (It != AttachPtrExprMap.end())
7163 ArrayRef<OpenMPMapModifierKind> MapModifiers;
7164 ArrayRef<OpenMPMotionModifierKind> MotionModifiers;
7165 bool ReturnDevicePointer =
false;
7166 bool IsImplicit =
false;
7167 const ValueDecl *Mapper =
nullptr;
7168 const Expr *VarRef =
nullptr;
7169 bool ForDeviceAddr =
false;
7171 MapInfo() =
default;
7175 ArrayRef<OpenMPMapModifierKind> MapModifiers,
7176 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7177 bool ReturnDevicePointer,
bool IsImplicit,
7178 const ValueDecl *Mapper =
nullptr,
const Expr *VarRef =
nullptr,
7179 bool ForDeviceAddr =
false)
7180 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
7181 MotionModifiers(MotionModifiers),
7182 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit),
7183 Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr) {}
7189 struct DeferredDevicePtrEntryTy {
7190 const Expr *IE =
nullptr;
7191 const ValueDecl *VD =
nullptr;
7192 bool ForDeviceAddr =
false;
7194 DeferredDevicePtrEntryTy(
const Expr *IE,
const ValueDecl *VD,
7196 : IE(IE), VD(VD), ForDeviceAddr(ForDeviceAddr) {}
7201 llvm::PointerUnion<
const OMPExecutableDirective *,
7202 const OMPDeclareMapperDecl *>
7206 CodeGenFunction &CGF;
7211 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>,
bool> FirstPrivateDecls;
7217 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7224 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7228 llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap;
7243 llvm::DenseMap<const Expr *, std::optional<size_t>>
7244 AttachPtrComponentDepthMap = {{
nullptr, std::nullopt}};
7248 llvm::DenseMap<const Expr *, size_t> AttachPtrComputationOrderMap = {
7253 AttachPtrExprComparator AttachPtrComparator;
7255 llvm::Value *getExprTypeSize(
const Expr *E)
const {
7259 if (
const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) {
7261 CGF.
getTypeSize(OAE->getBase()->getType()->getPointeeType());
7262 for (
const Expr *SE : OAE->getDimensions()) {
7273 if (
const auto *RefTy = ExprTy->
getAs<ReferenceType>())
7279 if (
const auto *OAE = dyn_cast<ArraySectionExpr>(E)) {
7281 OAE->getBase()->IgnoreParenImpCasts())
7287 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7288 !OAE->getLowerBound())
7291 llvm::Value *ElemSize;
7292 if (
const auto *PTy = BaseTy->
getAs<PointerType>()) {
7293 ElemSize = CGF.
getTypeSize(PTy->getPointeeType().getCanonicalType());
7296 assert(ATy &&
"Expecting array type if not a pointer type.");
7297 ElemSize = CGF.
getTypeSize(ATy->getElementType().getCanonicalType());
7302 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid())
7305 if (
const Expr *LenExpr = OAE->getLength()) {
7309 LenExpr->getExprLoc());
7310 return CGF.
Builder.CreateNUWMul(LengthVal, ElemSize);
7312 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() &&
7313 OAE->getLowerBound() &&
"expected array_section[lb:].");
7319 OAE->getLowerBound()->getExprLoc());
7320 LBVal = CGF.
Builder.CreateNUWMul(LBVal, ElemSize);
7321 llvm::Value *Cmp = CGF.
Builder.CreateICmpUGT(LengthVal, LBVal);
7322 llvm::Value *TrueVal = CGF.
Builder.CreateNUWSub(LengthVal, LBVal);
7323 LengthVal = CGF.
Builder.CreateSelect(
7324 Cmp, TrueVal, llvm::ConstantInt::get(CGF.
SizeTy, 0));
7334 OpenMPOffloadMappingFlags getMapTypeBits(
7336 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
bool IsImplicit,
7337 bool AddPtrFlag,
bool AddIsTargetParamFlag,
bool IsNonContiguous)
const {
7338 OpenMPOffloadMappingFlags Bits =
7339 IsImplicit ? OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT
7340 : OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7342 case OMPC_MAP_alloc:
7343 case OMPC_MAP_release:
7350 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO;
7353 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7355 case OMPC_MAP_tofrom:
7356 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TO |
7357 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
7359 case OMPC_MAP_delete:
7360 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
7363 llvm_unreachable(
"Unexpected map type!");
7366 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
7367 if (AddIsTargetParamFlag)
7368 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
7369 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_always))
7370 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
7371 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_close))
7372 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
7373 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_present) ||
7374 llvm::is_contained(MotionModifiers, OMPC_MOTION_MODIFIER_present))
7375 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
7376 if (llvm::is_contained(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold))
7377 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
7378 if (IsNonContiguous)
7379 Bits |= OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG;
7385 bool isFinalArraySectionExpression(
const Expr *E)
const {
7386 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
7393 if (OASE->getColonLocFirst().isInvalid())
7396 const Expr *Length = OASE->getLength();
7403 OASE->getBase()->IgnoreParenImpCasts())
7405 if (
const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.
getTypePtr()))
7406 return ATy->getSExtSize() != 1;
7418 llvm::APSInt ConstLength =
Result.Val.getInt();
7419 return ConstLength.getSExtValue() != 1;
7426 class CopyOverlappedEntryGaps {
7427 CodeGenFunction &CGF;
7428 MapCombinedInfoTy &CombinedInfo;
7429 OpenMPOffloadMappingFlags Flags = OpenMPOffloadMappingFlags::OMP_MAP_NONE;
7430 const ValueDecl *MapDecl =
nullptr;
7431 const Expr *MapExpr =
nullptr;
7433 bool IsNonContiguous =
false;
7437 const RecordDecl *LastParent =
nullptr;
7439 unsigned LastIndex = -1u;
7443 CopyOverlappedEntryGaps(CodeGenFunction &CGF,
7444 MapCombinedInfoTy &CombinedInfo,
7445 OpenMPOffloadMappingFlags Flags,
7446 const ValueDecl *MapDecl,
const Expr *MapExpr,
7447 Address BP, Address LB,
bool IsNonContiguous,
7449 : CGF(CGF), CombinedInfo(CombinedInfo), Flags(Flags), MapDecl(MapDecl),
7450 MapExpr(MapExpr), BP(BP), IsNonContiguous(IsNonContiguous),
7451 DimSize(DimSize), LB(LB) {}
7454 const OMPClauseMappableExprCommon::MappableComponent &MC,
7455 const FieldDecl *FD,
7456 llvm::function_ref<LValue(CodeGenFunction &,
const MemberExpr *)>
7457 EmitMemberExprBase) {
7467 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
7479 copyUntilField(FD, ComponentLB);
7482 if (((int64_t)FieldOffset - (int64_t)Cursor) > 0)
7483 copyUntilField(FD, ComponentLB);
7485 Cursor = FieldOffset + FieldSize;
7490 void copyUntilField(
const FieldDecl *FD, Address ComponentLB) {
7494 CGF.
Builder.CreatePtrDiff(CGF.
Int8Ty, ComponentLBPtr, LBPtr);
7495 copySizedChunk(LBPtr, Size);
7498 void copyUntilEnd(Address HB) {
7500 const ASTRecordLayout &RL =
7509 copySizedChunk(LBPtr, Size);
7512 void copySizedChunk(llvm::Value *Base, llvm::Value *Size) {
7513 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
7515 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
7516 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
7517 CombinedInfo.Pointers.push_back(Base);
7518 CombinedInfo.Sizes.push_back(
7520 CombinedInfo.Types.push_back(Flags);
7521 CombinedInfo.Mappers.push_back(
nullptr);
7522 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize : 1);
7531 void generateInfoForComponentList(
7533 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
7535 MapCombinedInfoTy &CombinedInfo,
7536 MapCombinedInfoTy &StructBaseCombinedInfo,
7537 StructRangeInfoTy &PartialStruct,
bool IsFirstComponentList,
7538 bool IsImplicit,
bool GenerateAllInfoForClauses,
7539 const ValueDecl *Mapper =
nullptr,
bool ForDeviceAddr =
false,
7540 const ValueDecl *BaseDecl =
nullptr,
const Expr *MapExpr =
nullptr,
7541 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7542 OverlappedElements = {},
7543 bool AreBothBasePtrAndPteeMapped =
false)
const {
7725 bool IsCaptureFirstInfo = IsFirstComponentList;
7729 bool RequiresReference =
false;
7732 auto CI = Components.rbegin();
7733 auto CE = Components.rend();
7738 bool IsExpressionFirstInfo =
true;
7739 bool FirstPointerInComplexData =
false;
7741 const Expr *AssocExpr = I->getAssociatedExpression();
7742 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7743 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
7744 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr);
7746 if (AreBothBasePtrAndPteeMapped && std::next(I) == CE)
7752 }
else if ((AE &&
isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7766 if (
const auto *VD =
7767 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7768 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
7769 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7770 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7771 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
7772 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
7774 RequiresReference =
true;
7784 I->getAssociatedDeclaration()->
getType().getNonReferenceType();
7789 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration());
7790 if (!AreBothBasePtrAndPteeMapped &&
7792 !VD || VD->hasLocalStorage()))
7795 FirstPointerInComplexData =
true;
7814 bool ShouldBeMemberOf =
false;
7823 const MemberExpr *EncounteredME =
nullptr;
7835 bool IsNonContiguous =
7836 CombinedInfo.NonContigInfo.IsNonContiguous ||
7837 any_of(Components, [&](
const auto &Component) {
7839 dyn_cast<ArraySectionExpr>(Component.getAssociatedExpression());
7843 const Expr *StrideExpr = OASE->getStride();
7847 const auto Constant =
7852 return !Constant->isOne();
7855 bool IsPrevMemberReference =
false;
7857 bool IsPartialMapped =
7858 !PartialStruct.PreliminaryMapData.BasePointers.empty();
7865 bool IsMappingWholeStruct =
true;
7866 if (!GenerateAllInfoForClauses) {
7867 IsMappingWholeStruct =
false;
7869 for (
auto TempI = I; TempI != CE; ++TempI) {
7870 const MemberExpr *PossibleME =
7871 dyn_cast<MemberExpr>(TempI->getAssociatedExpression());
7873 IsMappingWholeStruct =
false;
7879 for (; I != CE; ++I) {
7881 if (!EncounteredME) {
7882 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
7885 if (EncounteredME) {
7886 ShouldBeMemberOf =
true;
7889 if (FirstPointerInComplexData) {
7890 QualType Ty = std::prev(I)
7891 ->getAssociatedDeclaration()
7893 .getNonReferenceType();
7895 FirstPointerInComplexData =
false;
7900 auto Next = std::next(I);
7910 bool IsFinalArraySection =
7912 isFinalArraySectionExpression(I->getAssociatedExpression());
7916 const ValueDecl *MapDecl = (I->getAssociatedDeclaration())
7917 ? I->getAssociatedDeclaration()
7919 MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression()
7926 dyn_cast<ArraySectionExpr>(I->getAssociatedExpression());
7928 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression());
7929 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression());
7930 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression());
7936 I->getAssociatedExpression()->getType()->isAnyPointerType();
7937 bool IsMemberReference =
isa<MemberExpr>(I->getAssociatedExpression()) &&
7940 bool IsNonDerefPointer = IsPointer &&
7941 !(UO && UO->getOpcode() != UO_Deref) && !BO &&
7947 if (
Next == CE || IsMemberReference || IsNonDerefPointer ||
7948 IsFinalArraySection) {
7951 assert((
Next == CE ||
7958 "Unexpected expression");
7962 auto &&EmitMemberExprBase = [](CodeGenFunction &CGF,
7963 const MemberExpr *E) {
7964 const Expr *BaseExpr = E->getBase();
7969 LValueBaseInfo BaseInfo;
7970 TBAAAccessInfo TBAAInfo;
7984 OAShE->getBase()->getType()->getPointeeType()),
7986 OAShE->getBase()->getType()));
7987 }
else if (IsMemberReference) {
7989 LValue BaseLVal = EmitMemberExprBase(CGF, ME);
8004 bool IsMemberPointerOrAddr =
8006 (((IsPointer || ForDeviceAddr) &&
8007 I->getAssociatedExpression() == EncounteredME) ||
8008 (IsPrevMemberReference && !IsPointer) ||
8009 (IsMemberReference &&
Next != CE &&
8010 !
Next->getAssociatedExpression()->getType()->isPointerType()));
8011 if (!OverlappedElements.empty() &&
Next == CE) {
8013 assert(!PartialStruct.Base.isValid() &&
"The base element is set.");
8014 assert(!IsPointer &&
8015 "Unexpected base element with the pointer type.");
8018 PartialStruct.LowestElem = {0, LowestElem};
8020 I->getAssociatedExpression()->getType());
8025 PartialStruct.HighestElem = {
8026 std::numeric_limits<
decltype(
8027 PartialStruct.HighestElem.first)>
::max(),
8029 PartialStruct.Base = BP;
8030 PartialStruct.LB = LB;
8032 PartialStruct.PreliminaryMapData.BasePointers.empty() &&
8033 "Overlapped elements must be used only once for the variable.");
8034 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo);
8036 OpenMPOffloadMappingFlags Flags =
8037 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
8038 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
8040 false, IsNonContiguous);
8041 CopyOverlappedEntryGaps CopyGaps(CGF, CombinedInfo, Flags, MapDecl,
8042 MapExpr, BP, LB, IsNonContiguous,
8046 Component : OverlappedElements) {
8047 for (
const OMPClauseMappableExprCommon::MappableComponent &MC :
8050 if (
const auto *FD = dyn_cast<FieldDecl>(VD)) {
8051 CopyGaps.processField(MC, FD, EmitMemberExprBase);
8056 CopyGaps.copyUntilEnd(HB);
8059 llvm::Value *
Size = getExprTypeSize(I->getAssociatedExpression());
8066 if ((!IsMemberPointerOrAddr && !IsPartialMapped) ||
8068 if (!IsMappingWholeStruct) {
8069 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8071 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
8072 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8074 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8076 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize
8079 StructBaseCombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
8080 StructBaseCombinedInfo.BasePointers.push_back(
8082 StructBaseCombinedInfo.DevicePtrDecls.push_back(
nullptr);
8083 StructBaseCombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
8084 StructBaseCombinedInfo.Pointers.push_back(LB.
emitRawPointer(CGF));
8085 StructBaseCombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
8087 StructBaseCombinedInfo.NonContigInfo.Dims.push_back(
8088 IsNonContiguous ? DimSize : 1);
8092 bool HasMapper = Mapper &&
Next == CE;
8093 if (!IsMappingWholeStruct)
8094 CombinedInfo.Mappers.push_back(HasMapper ? Mapper :
nullptr);
8096 StructBaseCombinedInfo.Mappers.push_back(HasMapper ? Mapper
8103 OpenMPOffloadMappingFlags Flags =
8104 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit,
8105 !IsExpressionFirstInfo || RequiresReference ||
8106 FirstPointerInComplexData || IsMemberReference,
8107 AreBothBasePtrAndPteeMapped ||
8108 (IsCaptureFirstInfo && !RequiresReference),
8111 if (!IsExpressionFirstInfo || IsMemberReference) {
8114 if (IsPointer || (IsMemberReference &&
Next != CE))
8115 Flags &= ~(OpenMPOffloadMappingFlags::OMP_MAP_TO |
8116 OpenMPOffloadMappingFlags::OMP_MAP_FROM |
8117 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
8118 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
8119 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
8121 if (ShouldBeMemberOf) {
8124 Flags |= OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
8127 ShouldBeMemberOf =
false;
8131 if (!IsMappingWholeStruct)
8132 CombinedInfo.Types.push_back(Flags);
8134 StructBaseCombinedInfo.Types.push_back(Flags);
8140 if (EncounteredME) {
8145 if (!PartialStruct.Base.isValid()) {
8146 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8147 if (IsFinalArraySection && OASE) {
8151 PartialStruct.HighestElem = {FieldIndex, HB};
8153 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8155 PartialStruct.Base = BP;
8156 PartialStruct.LB = BP;
8157 }
else if (FieldIndex < PartialStruct.LowestElem.first) {
8158 PartialStruct.LowestElem = {FieldIndex, LowestElem};
8159 }
else if (FieldIndex > PartialStruct.HighestElem.first) {
8160 if (IsFinalArraySection && OASE) {
8164 PartialStruct.HighestElem = {FieldIndex, HB};
8166 PartialStruct.HighestElem = {FieldIndex, LowestElem};
8172 if (IsFinalArraySection || IsNonContiguous)
8173 PartialStruct.IsArraySection =
true;
8176 if (IsFinalArraySection)
8181 BP = IsMemberReference ? LowestElem : LB;
8182 if (!IsPartialMapped)
8183 IsExpressionFirstInfo =
false;
8184 IsCaptureFirstInfo =
false;
8185 FirstPointerInComplexData =
false;
8186 IsPrevMemberReference = IsMemberReference;
8187 }
else if (FirstPointerInComplexData) {
8188 QualType Ty = Components.rbegin()
8189 ->getAssociatedDeclaration()
8191 .getNonReferenceType();
8193 FirstPointerInComplexData =
false;
8199 PartialStruct.HasCompleteRecord =
true;
8201 if (!IsNonContiguous)
8204 const ASTContext &Context = CGF.
getContext();
8208 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 0)};
8209 MapValuesArrayTy CurCounts = {llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8210 MapValuesArrayTy CurStrides;
8211 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, 1)};
8217 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8219 const Expr *AssocExpr = Component.getAssociatedExpression();
8220 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8230 assert((VAT || CAT || &Component == &*Components.begin()) &&
8231 "Should be either ConstantArray or VariableArray if not the "
8235 if (CurStrides.empty()) {
8236 const Type *ElementType =
nullptr;
8238 ElementType = CAT->getElementType().getTypePtr();
8240 ElementType = VAT->getElementType().getTypePtr();
8242 assert(&Component == &*Components.begin() &&
8243 "Only expect pointer (non CAT or VAT) when this is the "
8251 if (&Component != &*Components.begin())
8255 CurStrides.push_back(
8256 llvm::ConstantInt::get(CGF.
Int64Ty, ElementTypeSize));
8261 if (DimSizes.size() < Components.size() - 1) {
8264 llvm::ConstantInt::get(CGF.
Int64Ty, CAT->getZExtSize()));
8266 DimSizes.push_back(CGF.
Builder.CreateIntCast(
8273 auto *DI = DimSizes.begin() + 1;
8275 llvm::Value *DimProd =
8276 llvm::ConstantInt::get(CGF.
CGM.
Int64Ty, ElementTypeSize);
8285 for (
const OMPClauseMappableExprCommon::MappableComponent &Component :
8287 const Expr *AssocExpr = Component.getAssociatedExpression();
8289 if (
const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) {
8290 llvm::Value *Offset = CGF.
Builder.CreateIntCast(
8293 CurOffsets.push_back(Offset);
8294 CurCounts.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 1));
8295 CurStrides.push_back(CurStrides.back());
8299 const auto *OASE = dyn_cast<ArraySectionExpr>(AssocExpr);
8305 const Expr *OffsetExpr = OASE->getLowerBound();
8306 llvm::Value *Offset =
nullptr;
8309 Offset = llvm::ConstantInt::get(CGF.
Int64Ty, 0);
8315 CurOffsets.push_back(Offset);
8318 const Expr *CountExpr = OASE->getLength();
8319 llvm::Value *Count =
nullptr;
8325 if (!OASE->getColonLocFirst().isValid() &&
8326 !OASE->getColonLocSecond().isValid()) {
8327 Count = llvm::ConstantInt::get(CGF.
Int64Ty, 1);
8333 const Expr *StrideExpr = OASE->getStride();
8334 llvm::Value *Stride =
8340 Count = CGF.
Builder.CreateUDiv(
8341 CGF.
Builder.CreateNUWSub(*DI, Offset), Stride);
8343 Count = CGF.
Builder.CreateNUWSub(*DI, Offset);
8349 CurCounts.push_back(Count);
8358 const Expr *StrideExpr = OASE->getStride();
8359 llvm::Value *Stride =
8364 DimProd = CGF.
Builder.CreateNUWMul(DimProd, *(DI - 1));
8366 CurStrides.push_back(CGF.
Builder.CreateNUWMul(DimProd, Stride));
8368 CurStrides.push_back(DimProd);
8369 if (DI != DimSizes.end())
8373 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets);
8374 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts);
8375 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides);
8381 OpenMPOffloadMappingFlags
8382 getMapModifiersForPrivateClauses(
const CapturedStmt::Capture &Cap)
const {
8390 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8391 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ;
8392 return OpenMPOffloadMappingFlags::OMP_MAP_PRIVATE |
8393 OpenMPOffloadMappingFlags::OMP_MAP_TO;
8396 if (I != LambdasMap.end())
8398 return getMapTypeBits(
8399 I->getSecond()->getMapType(), I->getSecond()->getMapTypeModifiers(),
8400 {}, I->getSecond()->isImplicit(),
8404 return OpenMPOffloadMappingFlags::OMP_MAP_TO |
8405 OpenMPOffloadMappingFlags::OMP_MAP_FROM;
8408 void getPlainLayout(
const CXXRecordDecl *RD,
8409 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
8410 bool AsBase)
const {
8413 llvm::StructType *St =
8416 unsigned NumElements = St->getNumElements();
8418 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
8419 RecordLayout(NumElements);
8422 for (
const auto &I : RD->
bases()) {
8426 QualType BaseTy = I.getType();
8437 RecordLayout[FieldIndex] =
Base;
8440 for (
const auto &I : RD->
vbases()) {
8441 QualType BaseTy = I.getType();
8448 if (RecordLayout[FieldIndex])
8450 RecordLayout[FieldIndex] =
Base;
8453 assert(!RD->
isUnion() &&
"Unexpected union.");
8454 for (
const auto *Field : RD->
fields()) {
8457 if (!
Field->isBitField() &&
8460 RecordLayout[FieldIndex] =
Field;
8463 for (
const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
8464 &
Data : RecordLayout) {
8467 if (
const auto *Base = dyn_cast<const CXXRecordDecl *>(
Data))
8468 getPlainLayout(Base, Layout,
true);
8475 static Address getAttachPtrAddr(
const Expr *PointerExpr,
8476 CodeGenFunction &CGF) {
8477 assert(PointerExpr &&
"Cannot get addr from null attach-ptr expr");
8480 if (
auto *DRE = dyn_cast<DeclRefExpr>(PointerExpr)) {
8483 }
else if (
auto *OASE = dyn_cast<ArraySectionExpr>(PointerExpr)) {
8486 }
else if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(PointerExpr)) {
8488 }
else if (
auto *ME = dyn_cast<MemberExpr>(PointerExpr)) {
8490 }
else if (
auto *UO = dyn_cast<UnaryOperator>(PointerExpr)) {
8491 assert(UO->getOpcode() == UO_Deref &&
8492 "Unexpected unary-operator on attach-ptr-expr");
8495 assert(AttachPtrAddr.
isValid() &&
8496 "Failed to get address for attach pointer expression");
8497 return AttachPtrAddr;
8504 static std::pair<Address, Address>
8505 getAttachPtrAddrAndPteeBaseAddr(
const Expr *AttachPtrExpr,
8506 CodeGenFunction &CGF) {
8511 Address AttachPtrAddr = getAttachPtrAddr(AttachPtrExpr, CGF);
8512 assert(AttachPtrAddr.
isValid() &&
"Invalid attach pointer addr");
8514 QualType AttachPtrType =
8519 AttachPtrAddr, AttachPtrType->
castAs<PointerType>());
8520 assert(AttachPteeBaseAddr.
isValid() &&
"Invalid attach pointee base addr");
8522 return {AttachPtrAddr, AttachPteeBaseAddr};
8528 shouldEmitAttachEntry(
const Expr *PointerExpr,
const ValueDecl *MapBaseDecl,
8529 CodeGenFunction &CGF,
8530 llvm::PointerUnion<
const OMPExecutableDirective *,
8531 const OMPDeclareMapperDecl *>
8541 ->getDirectiveKind());
8550 void collectAttachPtrExprInfo(
8552 llvm::PointerUnion<
const OMPExecutableDirective *,
8553 const OMPDeclareMapperDecl *>
8558 ? OMPD_declare_mapper
8561 const auto &[AttachPtrExpr, Depth] =
8565 AttachPtrComputationOrderMap.try_emplace(
8566 AttachPtrExpr, AttachPtrComputationOrderMap.size());
8567 AttachPtrComponentDepthMap.try_emplace(AttachPtrExpr, Depth);
8568 AttachPtrExprMap.try_emplace(Components, AttachPtrExpr);
8576 void generateAllInfoForClauses(
8577 ArrayRef<const OMPClause *> Clauses, MapCombinedInfoTy &CombinedInfo,
8578 llvm::OpenMPIRBuilder &OMPBuilder,
8579 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
8580 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
8585 llvm::MapVector<CanonicalDeclPtr<const Decl>,
8586 SmallVector<SmallVector<MapInfo, 8>, 4>>
8592 [&Info, &SkipVarSet](
8593 const ValueDecl *D, MapKind
Kind,
8596 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8597 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
8598 bool ReturnDevicePointer,
bool IsImplicit,
const ValueDecl *Mapper,
8599 const Expr *VarRef =
nullptr,
bool ForDeviceAddr =
false) {
8600 if (SkipVarSet.contains(D))
8602 auto It = Info.try_emplace(D, Total).first;
8603 It->second[
Kind].emplace_back(
8604 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer,
8605 IsImplicit, Mapper, VarRef, ForDeviceAddr);
8608 for (
const auto *
Cl : Clauses) {
8609 const auto *
C = dyn_cast<OMPMapClause>(
Cl);
8613 if (llvm::is_contained(
C->getMapTypeModifiers(),
8614 OMPC_MAP_MODIFIER_present))
8616 else if (
C->getMapType() == OMPC_MAP_alloc)
8618 const auto *EI =
C->getVarRefs().begin();
8619 for (
const auto L :
C->component_lists()) {
8620 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
8621 InfoGen(std::get<0>(L), Kind, std::get<1>(L),
C->getMapType(),
8622 C->getMapTypeModifiers(), {},
8623 false,
C->isImplicit(), std::get<2>(L),
8628 for (
const auto *
Cl : Clauses) {
8629 const auto *
C = dyn_cast<OMPToClause>(
Cl);
8633 if (llvm::is_contained(
C->getMotionModifiers(),
8634 OMPC_MOTION_MODIFIER_present))
8636 const auto *EI =
C->getVarRefs().begin();
8637 for (
const auto L :
C->component_lists()) {
8638 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_to, {},
8639 C->getMotionModifiers(),
false,
8640 C->isImplicit(), std::get<2>(L), *EI);
8644 for (
const auto *
Cl : Clauses) {
8645 const auto *
C = dyn_cast<OMPFromClause>(
Cl);
8649 if (llvm::is_contained(
C->getMotionModifiers(),
8650 OMPC_MOTION_MODIFIER_present))
8652 const auto *EI =
C->getVarRefs().begin();
8653 for (
const auto L :
C->component_lists()) {
8654 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_from, {},
8655 C->getMotionModifiers(),
8656 false,
C->isImplicit(), std::get<2>(L),
8669 llvm::MapVector<CanonicalDeclPtr<const Decl>,
8670 SmallVector<DeferredDevicePtrEntryTy, 4>>
8672 MapCombinedInfoTy UseDeviceDataCombinedInfo;
8674 auto &&UseDeviceDataCombinedInfoGen =
8675 [&UseDeviceDataCombinedInfo](
const ValueDecl *VD, llvm::Value *Ptr,
8676 CodeGenFunction &CGF,
bool IsDevAddr) {
8677 UseDeviceDataCombinedInfo.Exprs.push_back(VD);
8678 UseDeviceDataCombinedInfo.BasePointers.emplace_back(Ptr);
8679 UseDeviceDataCombinedInfo.DevicePtrDecls.emplace_back(VD);
8680 UseDeviceDataCombinedInfo.DevicePointers.emplace_back(
8681 IsDevAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer);
8682 UseDeviceDataCombinedInfo.Pointers.push_back(Ptr);
8683 UseDeviceDataCombinedInfo.Sizes.push_back(
8684 llvm::Constant::getNullValue(CGF.Int64Ty));
8685 UseDeviceDataCombinedInfo.Types.push_back(
8686 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM);
8687 UseDeviceDataCombinedInfo.Mappers.push_back(
nullptr);
8691 [&DeferredInfo, &UseDeviceDataCombinedInfoGen,
8692 &InfoGen](CodeGenFunction &CGF,
const Expr *IE,
const ValueDecl *VD,
8695 bool IsImplicit,
bool IsDevAddr) {
8708 false, IsImplicit,
nullptr,
nullptr,
8710 DeferredInfo[
nullptr].emplace_back(IE, VD, IsDevAddr);
8714 if (IE->isGLValue())
8715 Ptr = CGF.EmitLValue(IE).getPointer(CGF);
8717 Ptr = CGF.EmitScalarExpr(IE);
8719 Ptr = CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc());
8721 UseDeviceDataCombinedInfoGen(VD, Ptr, CGF, IsDevAddr);
8725 auto &&IsMapInfoExist = [&Info](CodeGenFunction &CGF,
const ValueDecl *VD,
8726 const Expr *IE,
bool IsDevAddr) ->
bool {
8734 if (It != Info.end()) {
8736 for (
auto &
Data : It->second) {
8737 auto *CI = llvm::find_if(
Data, [VD](
const MapInfo &MI) {
8738 return MI.Components.back().getAssociatedDeclaration() == VD;
8746 if (CI !=
Data.end()) {
8748 CI->ForDeviceAddr = IsDevAddr;
8749 CI->ReturnDevicePointer =
true;
8753 auto PrevCI = std::next(CI->Components.rbegin());
8754 const auto *VarD = dyn_cast<VarDecl>(VD);
8757 !VD->getType().getNonReferenceType()->isPointerType() ||
8758 PrevCI == CI->Components.rend() ||
8760 VarD->hasLocalStorage()) {
8761 CI->ForDeviceAddr = IsDevAddr;
8762 CI->ReturnDevicePointer =
true;
8780 for (
const auto *
Cl : Clauses) {
8781 const auto *
C = dyn_cast<OMPUseDevicePtrClause>(
Cl);
8784 for (
const auto L :
C->component_lists()) {
8787 assert(!Components.empty() &&
8788 "Not expecting empty list of components!");
8789 const ValueDecl *VD = Components.back().getAssociatedDeclaration();
8791 const Expr *IE = Components.back().getAssociatedExpression();
8792 if (IsMapInfoExist(CGF, VD, IE,
false))
8794 MapInfoGen(CGF, IE, VD, Components,
C->isImplicit(),
8799 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
8800 for (
const auto *
Cl : Clauses) {
8801 const auto *
C = dyn_cast<OMPUseDeviceAddrClause>(
Cl);
8804 for (
const auto L :
C->component_lists()) {
8807 assert(!std::get<1>(L).empty() &&
8808 "Not expecting empty list of components!");
8809 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration();
8810 if (!Processed.insert(VD).second)
8813 const Expr *IE = std::get<1>(L).back().getAssociatedExpression();
8814 if (IsMapInfoExist(CGF, VD, IE,
true))
8816 MapInfoGen(CGF, IE, VD, Components,
C->isImplicit(),
8821 for (
const auto &
Data : Info) {
8822 StructRangeInfoTy PartialStruct;
8824 MapCombinedInfoTy CurInfo;
8826 MapCombinedInfoTy StructBaseCurInfo;
8828 const ValueDecl *VD = cast_or_null<ValueDecl>(D);
8829 bool HasMapBasePtr =
false;
8830 bool HasMapArraySec =
false;
8832 for (
const auto &M :
Data.second) {
8833 HasMapBasePtr = any_of(M, [](
const MapInfo &L) {
8834 return isa_and_present<DeclRefExpr>(L.VarRef);
8836 HasMapArraySec = any_of(M, [](
const MapInfo &L) {
8837 return isa_and_present<ArraySectionExpr, ArraySubscriptExpr>(
8840 if (HasMapBasePtr && HasMapArraySec)
8844 for (
const auto &M :
Data.second) {
8845 for (
const MapInfo &L : M) {
8846 assert(!L.Components.empty() &&
8847 "Not expecting declaration with no component lists.");
8850 unsigned CurrentBasePointersIdx = CurInfo.BasePointers.size();
8851 unsigned StructBasePointersIdx =
8852 StructBaseCurInfo.BasePointers.size();
8853 CurInfo.NonContigInfo.IsNonContiguous =
8854 L.Components.back().isNonContiguous();
8855 generateInfoForComponentList(
8856 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components,
8857 CurInfo, StructBaseCurInfo, PartialStruct,
8858 false, L.IsImplicit,
8859 true, L.Mapper, L.ForDeviceAddr, VD,
8861 HasMapBasePtr && HasMapArraySec);
8865 if (L.ReturnDevicePointer) {
8869 assert((CurrentBasePointersIdx < CurInfo.BasePointers.size() ||
8870 StructBasePointersIdx <
8871 StructBaseCurInfo.BasePointers.size()) &&
8872 "Unexpected number of mapped base pointers.");
8875 const ValueDecl *RelevantVD =
8876 L.Components.back().getAssociatedDeclaration();
8877 assert(RelevantVD &&
8878 "No relevant declaration related with device pointer??");
8885 if (StructBasePointersIdx < StructBaseCurInfo.BasePointers.size()) {
8886 StructBaseCurInfo.DevicePtrDecls[StructBasePointersIdx] =
8888 StructBaseCurInfo.DevicePointers[StructBasePointersIdx] =
8889 L.ForDeviceAddr ? DeviceInfoTy::Address
8890 : DeviceInfoTy::Pointer;
8891 StructBaseCurInfo.Types[StructBasePointersIdx] |=
8892 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
8894 CurInfo.DevicePtrDecls[CurrentBasePointersIdx] = RelevantVD;
8895 CurInfo.DevicePointers[CurrentBasePointersIdx] =
8896 L.ForDeviceAddr ? DeviceInfoTy::Address
8897 : DeviceInfoTy::Pointer;
8898 CurInfo.Types[CurrentBasePointersIdx] |=
8899 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM;
8907 auto CI = DeferredInfo.find(
Data.first);
8908 if (CI != DeferredInfo.end()) {
8909 for (
const DeferredDevicePtrEntryTy &L : CI->second) {
8910 llvm::Value *BasePtr;
8912 if (L.ForDeviceAddr) {
8913 if (L.IE->isGLValue())
8921 CurInfo.Types.push_back(
8922 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM |
8923 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
8927 L.IE->getExprLoc());
8931 CurInfo.Types.push_back(
8932 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
8933 OpenMPOffloadMappingFlags::OMP_MAP_RETURN_PARAM |
8934 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
8936 CurInfo.Exprs.push_back(L.VD);
8937 CurInfo.BasePointers.emplace_back(BasePtr);
8938 CurInfo.DevicePtrDecls.emplace_back(L.VD);
8939 CurInfo.DevicePointers.emplace_back(
8940 L.ForDeviceAddr ? DeviceInfoTy::Address : DeviceInfoTy::Pointer);
8941 CurInfo.Pointers.push_back(Ptr);
8942 CurInfo.Sizes.push_back(
8943 llvm::Constant::getNullValue(this->CGF.
Int64Ty));
8944 CurInfo.Mappers.push_back(
nullptr);
8950 MapCombinedInfoTy UnionCurInfo;
8951 UnionCurInfo.append(StructBaseCurInfo);
8952 UnionCurInfo.append(CurInfo);
8956 if (PartialStruct.Base.isValid()) {
8957 UnionCurInfo.NonContigInfo.Dims.push_back(0);
8959 emitCombinedEntry(CombinedInfo, UnionCurInfo.Types, PartialStruct,
8960 !VD, OMPBuilder, VD);
8964 CombinedInfo.append(UnionCurInfo);
8967 CombinedInfo.append(UseDeviceDataCombinedInfo);
8971 MappableExprsHandler(
const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
8972 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {
8974 for (
const auto *
C : Dir.getClausesOfKind<OMPFirstprivateClause>())
8975 for (
const auto *D :
C->varlist())
8976 FirstPrivateDecls.try_emplace(
8979 for (
const auto *
C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) {
8980 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) {
8981 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I);
8982 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits))
8983 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()),
8985 else if (const auto *VD = dyn_cast<VarDecl>(
8986 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts())
8988 FirstPrivateDecls.try_emplace(VD, true);
8992 for (
const auto *
C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
8993 for (
auto L :
C->component_lists())
8994 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L));
8996 for (
const auto *
C : Dir.getClausesOfKind<OMPHasDeviceAddrClause>())
8997 for (
auto L :
C->component_lists())
8998 HasDevAddrsMap[std::get<0>(L)].push_back(std::get<1>(L));
9000 for (
const auto *
C : Dir.getClausesOfKind<OMPMapClause>()) {
9001 if (C->getMapType() != OMPC_MAP_to)
9003 for (auto L : C->component_lists()) {
9004 const ValueDecl *VD = std::get<0>(L);
9005 const auto *RD = VD ? VD->getType()
9007 .getNonReferenceType()
9008 ->getAsCXXRecordDecl()
9010 if (RD && RD->isLambda())
9011 LambdasMap.try_emplace(std::get<0>(L), C);
9017 MappableExprsHandler(
const OMPDeclareMapperDecl &Dir,
CodeGenFunction &CGF)
9018 : CurDir(&Dir), CGF(CGF), AttachPtrComparator(*this) {}
9023 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo,
9024 MapFlagsArrayTy &CurTypes,
9025 const StructRangeInfoTy &PartialStruct,
bool IsMapThis,
9026 llvm::OpenMPIRBuilder &OMPBuilder,
9027 const ValueDecl *VD =
nullptr,
9028 unsigned OffsetForMemberOfFlag = 0,
9029 bool NotTargetParams =
true)
const {
9030 if (CurTypes.size() == 1 &&
9031 ((CurTypes.back() & OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) !=
9032 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF) &&
9033 !PartialStruct.IsArraySection)
9035 Address LBAddr = PartialStruct.LowestElem.second;
9036 Address HBAddr = PartialStruct.HighestElem.second;
9037 if (PartialStruct.HasCompleteRecord) {
9038 LBAddr = PartialStruct.LB;
9039 HBAddr = PartialStruct.LB;
9041 CombinedInfo.Exprs.push_back(VD);
9043 CombinedInfo.BasePointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9044 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9045 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9048 const CXXMethodDecl *MD =
9050 const CXXRecordDecl *RD = MD ? MD->
getParent() :
nullptr;
9051 bool HasBaseClass = RD && IsMapThis ? RD->
getNumBases() > 0 :
false;
9061 CombinedInfo.Pointers.push_back(PartialStruct.Base.emitRawPointer(CGF));
9066 CombinedInfo.Sizes.push_back(Size);
9068 CombinedInfo.Pointers.push_back(LB);
9071 llvm::Value *HAddr = CGF.
Builder.CreateConstGEP1_32(
9075 llvm::Value *Diff = CGF.
Builder.CreatePtrDiff(CGF.
Int8Ty, CHAddr, CLAddr);
9078 CombinedInfo.Sizes.push_back(Size);
9080 CombinedInfo.Mappers.push_back(
nullptr);
9082 CombinedInfo.Types.push_back(
9083 NotTargetParams ? OpenMPOffloadMappingFlags::OMP_MAP_NONE
9084 : !PartialStruct.PreliminaryMapData.BasePointers.empty()
9085 ? OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ
9086 : OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9089 if (CurTypes.end() !=
9090 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9091 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9092 Type & OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
9094 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
9096 (*CurTypes.begin()) &= ~OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
9103 if (CurTypes.end() !=
9104 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags
Type) {
9105 return static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
9106 Type & OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD);
9108 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9109 for (
auto &M : CurTypes)
9110 M |= OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
9116 OpenMPOffloadMappingFlags MemberOfFlag = OMPBuilder.getMemberOfFlag(
9117 OffsetForMemberOfFlag + CombinedInfo.BasePointers.size() - 1);
9118 for (
auto &M : CurTypes)
9119 OMPBuilder.setCorrectMemberOfFlag(M, MemberOfFlag);
9127 void generateAllInfo(
9128 MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9129 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
9130 llvm::DenseSet<CanonicalDeclPtr<const Decl>>())
const {
9132 "Expect a executable directive");
9134 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, OMPBuilder,
9141 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo,
9142 llvm::OpenMPIRBuilder &OMPBuilder)
const {
9144 "Expect a declare mapper directive");
9146 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo,
9151 void generateInfoForLambdaCaptures(
9152 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo,
9153 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers)
const {
9161 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
9162 FieldDecl *ThisCapture =
nullptr;
9168 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF),
9169 VDLVal.getPointer(CGF));
9170 CombinedInfo.Exprs.push_back(VD);
9171 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF));
9172 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9173 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9174 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF));
9175 CombinedInfo.Sizes.push_back(
9178 CombinedInfo.Types.push_back(
9179 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9180 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9181 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9182 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9183 CombinedInfo.Mappers.push_back(
nullptr);
9185 for (
const LambdaCapture &LC : RD->
captures()) {
9186 if (!LC.capturesVariable())
9191 auto It = Captures.find(VD);
9192 assert(It != Captures.end() &&
"Found lambda capture without field.");
9196 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9197 VDLVal.getPointer(CGF));
9198 CombinedInfo.Exprs.push_back(VD);
9199 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9200 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9201 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9202 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF));
9203 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9209 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
9210 VDLVal.getPointer(CGF));
9211 CombinedInfo.Exprs.push_back(VD);
9212 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF));
9213 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9214 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9215 CombinedInfo.Pointers.push_back(VarRVal.
getScalarVal());
9216 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.
Int64Ty, 0));
9218 CombinedInfo.Types.push_back(
9219 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9220 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9221 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9222 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
9223 CombinedInfo.Mappers.push_back(
nullptr);
9228 void adjustMemberOfForLambdaCaptures(
9229 llvm::OpenMPIRBuilder &OMPBuilder,
9230 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
9231 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
9232 MapFlagsArrayTy &Types)
const {
9233 for (
unsigned I = 0, E = Types.size(); I < E; ++I) {
9235 if (Types[I] != (OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ |
9236 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9237 OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF |
9238 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))
9240 llvm::Value *BasePtr = LambdaPointers.lookup(BasePointers[I]);
9241 assert(BasePtr &&
"Unable to find base lambda address.");
9243 for (
unsigned J = I; J > 0; --J) {
9244 unsigned Idx = J - 1;
9245 if (Pointers[Idx] != BasePtr)
9250 assert(TgtIdx != -1 &&
"Unable to find parent lambda.");
9254 OpenMPOffloadMappingFlags MemberOfFlag =
9255 OMPBuilder.getMemberOfFlag(TgtIdx);
9256 OMPBuilder.setCorrectMemberOfFlag(Types[I], MemberOfFlag);
9263 void generateInfoForCaptureFromClauseInfo(
9264 const CapturedStmt::Capture *Cap, llvm::Value *Arg,
9265 MapCombinedInfoTy &CurCaptureVarInfo, llvm::OpenMPIRBuilder &OMPBuilder,
9266 unsigned OffsetForMemberOfFlag)
const {
9268 "Not expecting to generate map info for a variable array type!");
9277 if (LambdasMap.count(VD))
9283 if (VD && (DevPointersMap.count(VD) || HasDevAddrsMap.count(VD))) {
9284 CurCaptureVarInfo.Exprs.push_back(VD);
9285 CurCaptureVarInfo.BasePointers.emplace_back(Arg);
9286 CurCaptureVarInfo.DevicePtrDecls.emplace_back(VD);
9287 CurCaptureVarInfo.DevicePointers.emplace_back(DeviceInfoTy::Pointer);
9288 CurCaptureVarInfo.Pointers.push_back(Arg);
9289 CurCaptureVarInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9292 CurCaptureVarInfo.Types.push_back(
9293 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
9294 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
9295 CurCaptureVarInfo.Mappers.push_back(
nullptr);
9299 MapDataArrayTy DeclComponentLists;
9303 auto It = DevPointersMap.find(VD);
9304 if (It != DevPointersMap.end())
9305 for (
const auto &MCL : It->second)
9306 DeclComponentLists.emplace_back(MCL, OMPC_MAP_to,
Unknown,
9309 auto I = HasDevAddrsMap.find(VD);
9310 if (I != HasDevAddrsMap.end())
9311 for (
const auto &MCL : I->second)
9312 DeclComponentLists.emplace_back(MCL, OMPC_MAP_tofrom,
Unknown,
9316 "Expect a executable directive");
9318 bool HasMapBasePtr =
false;
9319 bool HasMapArraySec =
false;
9320 for (
const auto *
C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
9321 const auto *EI =
C->getVarRefs().begin();
9322 for (
const auto L :
C->decl_component_lists(VD)) {
9323 const ValueDecl *VDecl, *Mapper;
9325 const Expr *E = (
C->getMapLoc().isValid()) ? *EI :
nullptr;
9327 std::tie(VDecl, Components, Mapper) = L;
9328 assert(VDecl == VD &&
"We got information for the wrong declaration??");
9329 assert(!Components.empty() &&
9330 "Not expecting declaration with no component lists.");
9332 HasMapBasePtr =
true;
9335 HasMapArraySec =
true;
9336 DeclComponentLists.emplace_back(Components,
C->getMapType(),
9337 C->getMapTypeModifiers(),
9338 C->isImplicit(), Mapper, E);
9342 llvm::stable_sort(DeclComponentLists, [](
const MapData &LHS,
9343 const MapData &RHS) {
9344 ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS);
9347 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9348 bool HasAllocs = MapType == OMPC_MAP_alloc;
9349 MapModifiers = std::get<2>(RHS);
9350 MapType = std::get<1>(LHS);
9352 llvm::is_contained(MapModifiers, clang::OMPC_MAP_MODIFIER_present);
9353 bool HasAllocsR = MapType == OMPC_MAP_alloc;
9354 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR);
9357 auto GenerateInfoForComponentLists =
9358 [&](ArrayRef<MapData> DeclComponentLists,
9359 bool IsEligibleForTargetParamFlag) {
9360 MapCombinedInfoTy CurInfoForComponentLists;
9361 StructRangeInfoTy PartialStruct;
9363 if (DeclComponentLists.empty())
9366 generateInfoForCaptureFromComponentLists(
9367 VD, DeclComponentLists, CurInfoForComponentLists, PartialStruct,
9368 IsEligibleForTargetParamFlag,
9369 HasMapBasePtr && HasMapArraySec);
9374 if (PartialStruct.Base.isValid()) {
9375 CurCaptureVarInfo.append(PartialStruct.PreliminaryMapData);
9377 CurCaptureVarInfo, CurInfoForComponentLists.Types,
9378 PartialStruct, Cap->
capturesThis(), OMPBuilder,
nullptr,
9379 OffsetForMemberOfFlag,
9380 !IsEligibleForTargetParamFlag);
9384 if (CurInfoForComponentLists.BasePointers.empty())
9387 CurCaptureVarInfo.append(CurInfoForComponentLists);
9390 GenerateInfoForComponentLists(DeclComponentLists,
9397 void generateInfoForCaptureFromComponentLists(
9398 const ValueDecl *VD, ArrayRef<MapData> DeclComponentLists,
9399 MapCombinedInfoTy &CurComponentListInfo, StructRangeInfoTy &PartialStruct,
9400 bool IsListEligibleForTargetParamFlag,
9401 bool AreBothBasePtrAndPteeMapped =
false)
const {
9403 llvm::SmallDenseMap<
9410 for (
const MapData &L : DeclComponentLists) {
9413 ArrayRef<OpenMPMapModifierKind> MapModifiers;
9415 const ValueDecl *Mapper;
9417 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
9420 for (
const MapData &L1 : ArrayRef(DeclComponentLists).slice(Count)) {
9422 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper,
9424 auto CI = Components.rbegin();
9425 auto CE = Components.rend();
9426 auto SI = Components1.rbegin();
9427 auto SE = Components1.rend();
9428 for (; CI != CE && SI != SE; ++CI, ++SI) {
9429 if (CI->getAssociatedExpression()->getStmtClass() !=
9430 SI->getAssociatedExpression()->getStmtClass())
9433 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
9438 if (CI == CE || SI == SE) {
9440 if (CI == CE && SI == SE)
9442 const auto It = (SI == SE) ? CI : SI;
9449 (std::prev(It)->getAssociatedDeclaration() &&
9451 ->getAssociatedDeclaration()
9453 ->isPointerType()) ||
9454 (It->getAssociatedDeclaration() &&
9455 It->getAssociatedDeclaration()->getType()->isPointerType() &&
9456 std::next(It) != CE && std::next(It) != SE))
9458 const MapData &BaseData = CI == CE ? L : L1;
9460 SI == SE ? Components : Components1;
9461 OverlappedData[&BaseData].push_back(SubData);
9466 llvm::SmallVector<const FieldDecl *, 4> Layout;
9467 if (!OverlappedData.empty()) {
9470 while (BaseType != OrigType) {
9476 getPlainLayout(CRD, Layout,
false);
9482 for (
auto &Pair : OverlappedData) {
9489 auto CI = First.rbegin();
9490 auto CE = First.rend();
9491 auto SI = Second.rbegin();
9492 auto SE = Second.rend();
9493 for (; CI != CE && SI != SE; ++CI, ++SI) {
9494 if (CI->getAssociatedExpression()->getStmtClass() !=
9495 SI->getAssociatedExpression()->getStmtClass())
9498 if (CI->getAssociatedDeclaration() !=
9499 SI->getAssociatedDeclaration())
9504 if (CI == CE && SI == SE)
9508 if (CI == CE || SI == SE)
9513 if (FD1->getParent() == FD2->getParent())
9514 return FD1->getFieldIndex() < FD2->getFieldIndex();
9516 llvm::find_if(Layout, [FD1, FD2](
const FieldDecl *FD) {
9517 return FD == FD1 || FD == FD2;
9525 bool AddTargetParamFlag = IsListEligibleForTargetParamFlag;
9526 MapCombinedInfoTy StructBaseCombinedInfo;
9527 for (
const auto &Pair : OverlappedData) {
9528 const MapData &L = *Pair.getFirst();
9531 ArrayRef<OpenMPMapModifierKind> MapModifiers;
9533 const ValueDecl *Mapper;
9535 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
9537 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
9538 OverlappedComponents = Pair.getSecond();
9539 generateInfoForComponentList(
9540 MapType, MapModifiers, {}, Components, CurComponentListInfo,
9541 StructBaseCombinedInfo, PartialStruct, AddTargetParamFlag, IsImplicit,
9543 false, VD, VarRef, OverlappedComponents);
9544 AddTargetParamFlag =
false;
9547 for (
const MapData &L : DeclComponentLists) {
9550 ArrayRef<OpenMPMapModifierKind> MapModifiers;
9552 const ValueDecl *Mapper;
9554 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) =
9556 auto It = OverlappedData.find(&L);
9557 if (It == OverlappedData.end())
9558 generateInfoForComponentList(
9559 MapType, MapModifiers, {}, Components, CurComponentListInfo,
9560 StructBaseCombinedInfo, PartialStruct, AddTargetParamFlag,
9561 IsImplicit,
false, Mapper,
9563 {}, AreBothBasePtrAndPteeMapped);
9564 AddTargetParamFlag =
false;
9570 void generateDefaultMapInfo(
const CapturedStmt::Capture &CI,
9571 const FieldDecl &RI, llvm::Value *CV,
9572 MapCombinedInfoTy &CombinedInfo)
const {
9573 bool IsImplicit =
true;
9576 CombinedInfo.Exprs.push_back(
nullptr);
9577 CombinedInfo.BasePointers.push_back(CV);
9578 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9579 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9580 CombinedInfo.Pointers.push_back(CV);
9582 CombinedInfo.Sizes.push_back(
9586 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_TO |
9587 OpenMPOffloadMappingFlags::OMP_MAP_FROM);
9591 CombinedInfo.BasePointers.push_back(CV);
9592 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9593 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9594 CombinedInfo.Pointers.push_back(CV);
9598 CombinedInfo.Types.push_back(
9599 OpenMPOffloadMappingFlags::OMP_MAP_LITERAL);
9600 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9605 CombinedInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_NONE);
9606 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.
Int64Ty));
9608 auto I = FirstPrivateDecls.find(VD);
9609 if (I != FirstPrivateDecls.end())
9610 IsImplicit = I->getSecond();
9615 CombinedInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
9620 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI));
9622 auto I = FirstPrivateDecls.find(VD);
9624 CombinedInfo.BasePointers.push_back(CV);
9625 CombinedInfo.DevicePtrDecls.push_back(
nullptr);
9626 CombinedInfo.DevicePointers.push_back(DeviceInfoTy::None);
9633 CombinedInfo.Pointers.push_back(CV);
9635 if (I != FirstPrivateDecls.end())
9636 IsImplicit = I->getSecond();
9639 CombinedInfo.Types.back() |=
9640 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM;
9644 CombinedInfo.Types.back() |= OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;
9647 CombinedInfo.Mappers.push_back(
nullptr);
9659 dyn_cast<MemberExpr>(OASE->getBase()->IgnoreParenImpCasts()))
9660 return ME->getMemberDecl();
9666static llvm::Constant *
9668 MappableExprsHandler::MappingExprInfo &MapExprs) {
9670 uint32_t SrcLocStrSize;
9671 if (!MapExprs.getMapDecl() && !MapExprs.getMapExpr())
9672 return OMPBuilder.getOrCreateDefaultSrcLocStr(SrcLocStrSize);
9675 if (!MapExprs.getMapDecl() && MapExprs.getMapExpr()) {
9679 Loc = MapExprs.getMapExpr()->getExprLoc();
9681 Loc = MapExprs.getMapDecl()->getLocation();
9684 std::string ExprName;
9685 if (MapExprs.getMapExpr()) {
9687 llvm::raw_string_ostream OS(ExprName);
9688 MapExprs.getMapExpr()->printPretty(OS,
nullptr, P);
9690 ExprName = MapExprs.getMapDecl()->getNameAsString();
9699 return OMPBuilder.getOrCreateSrcLocStr(
FileName, ExprName, PLoc.
getLine(),
9706 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
9708 bool IsNonContiguous =
false,
bool ForEndCall =
false) {
9711 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
9714 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
9715 CGF.
Builder.GetInsertPoint());
9717 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
9718 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
9723 auto CustomMapperCB = [&](
unsigned int I) {
9724 llvm::Function *MFunc =
nullptr;
9725 if (CombinedInfo.Mappers[I]) {
9726 Info.HasMapper =
true;
9732 cantFail(OMPBuilder.emitOffloadingArraysAndArgs(
9733 AllocaIP, CodeGenIP, Info, Info.RTArgs, CombinedInfo, CustomMapperCB,
9734 IsNonContiguous, ForEndCall, DeviceAddrCB));
9738static const OMPExecutableDirective *
9740 const auto *CS = D.getInnermostCapturedStmt();
9743 const Stmt *ChildStmt =
9746 if (
const auto *NestedDir =
9747 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
9749 switch (D.getDirectiveKind()) {
9755 if (DKind == OMPD_teams) {
9756 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
9761 if (
const auto *NND =
9762 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
9763 DKind = NND->getDirectiveKind();
9769 case OMPD_target_teams:
9773 case OMPD_target_parallel:
9774 case OMPD_target_simd:
9775 case OMPD_target_parallel_for:
9776 case OMPD_target_parallel_for_simd:
9778 case OMPD_target_teams_distribute:
9779 case OMPD_target_teams_distribute_simd:
9780 case OMPD_target_teams_distribute_parallel_for:
9781 case OMPD_target_teams_distribute_parallel_for_simd:
9784 case OMPD_parallel_for:
9785 case OMPD_parallel_master:
9786 case OMPD_parallel_sections:
9788 case OMPD_parallel_for_simd:
9790 case OMPD_cancellation_point:
9792 case OMPD_threadprivate:
9803 case OMPD_taskyield:
9806 case OMPD_taskgroup:
9812 case OMPD_target_data:
9813 case OMPD_target_exit_data:
9814 case OMPD_target_enter_data:
9815 case OMPD_distribute:
9816 case OMPD_distribute_simd:
9817 case OMPD_distribute_parallel_for:
9818 case OMPD_distribute_parallel_for_simd:
9819 case OMPD_teams_distribute:
9820 case OMPD_teams_distribute_simd:
9821 case OMPD_teams_distribute_parallel_for:
9822 case OMPD_teams_distribute_parallel_for_simd:
9823 case OMPD_target_update:
9824 case OMPD_declare_simd:
9825 case OMPD_declare_variant:
9826 case OMPD_begin_declare_variant:
9827 case OMPD_end_declare_variant:
9828 case OMPD_declare_target:
9829 case OMPD_end_declare_target:
9830 case OMPD_declare_reduction:
9831 case OMPD_declare_mapper:
9833 case OMPD_taskloop_simd:
9834 case OMPD_master_taskloop:
9835 case OMPD_master_taskloop_simd:
9836 case OMPD_parallel_master_taskloop:
9837 case OMPD_parallel_master_taskloop_simd:
9839 case OMPD_metadirective:
9842 llvm_unreachable(
"Unexpected directive.");
9887 auto *MapperVarDecl =
9889 CharUnits ElementSize =
C.getTypeSizeInChars(Ty);
9890 llvm::Type *ElemTy =
CGM.getTypes().ConvertTypeForMem(Ty);
9893 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
9894 auto PrivatizeAndGenMapInfoCB =
9895 [&](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP, llvm::Value *PtrPHI,
9896 llvm::Value *BeginArg) -> llvm::OpenMPIRBuilder::MapInfosTy & {
9897 MapperCGF.
Builder.restoreIP(CodeGenIP);
9907 Scope.addPrivate(MapperVarDecl, PtrCurrent);
9908 (void)
Scope.Privatize();
9911 MappableExprsHandler MEHandler(*D, MapperCGF);
9912 MEHandler.generateAllInfoForMapper(CombinedInfo,
OMPBuilder);
9914 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
9917 if (
CGM.getCodeGenOpts().getDebugInfo() !=
9918 llvm::codegenoptions::NoDebugInfo) {
9919 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
9920 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
9924 return CombinedInfo;
9927 auto CustomMapperCB = [&](
unsigned I) {
9928 llvm::Function *MapperFunc =
nullptr;
9929 if (CombinedInfo.Mappers[I]) {
9933 assert(MapperFunc &&
"Expect a valid mapper function is available.");
9939 llvm::raw_svector_ostream Out(TyStr);
9940 CGM.getCXXABI().getMangleContext().mangleCanonicalTypeName(Ty, Out);
9943 llvm::Function *NewFn = cantFail(
OMPBuilder.emitUserDefinedMapper(
9944 PrivatizeAndGenMapInfoCB, ElemTy, Name, CustomMapperCB));
9945 UDMMap.try_emplace(D, NewFn);
9969 Kind != OMPD_target_teams_loop)
9972 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
9975 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD))
9976 return NumIterations;
9977 return llvm::ConstantInt::get(CGF.
Int64Ty, 0);
9986 if (OffloadingMandatory) {
9987 CGF.
Builder.CreateUnreachable();
9989 if (RequiresOuterTask) {
9990 CapturedVars.clear();
9999 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10002 llvm::Value *DeviceID;
10003 if (
Device.getPointer()) {
10005 Device.getInt() == OMPC_DEVICE_device_num) &&
10006 "Expected device_num modifier.");
10011 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
10016static std::pair<llvm::Value *, OMPDynGroupprivateFallbackType>
10018 llvm::Value *DynGP = CGF.
Builder.getInt32(0);
10019 auto DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10023 llvm::Value *DynGPVal =
10027 auto FallbackModifier = DynGPClause->getDynGroupprivateFallbackModifier();
10028 switch (FallbackModifier) {
10029 case OMPC_DYN_GROUPPRIVATE_FALLBACK_abort:
10030 DynGPFallback = OMPDynGroupprivateFallbackType::Abort;
10032 case OMPC_DYN_GROUPPRIVATE_FALLBACK_null:
10033 DynGPFallback = OMPDynGroupprivateFallbackType::Null;
10035 case OMPC_DYN_GROUPPRIVATE_FALLBACK_default_mem:
10038 DynGPFallback = OMPDynGroupprivateFallbackType::DefaultMem;
10041 llvm_unreachable(
"Unknown fallback modifier for OpenMP dyn_groupprivate");
10043 }
else if (
auto *OMPXDynCGClause =
10046 llvm::Value *DynCGMemVal = CGF.
EmitScalarExpr(OMPXDynCGClause->getSize(),
10051 return {DynGP, DynGPFallback};
10057 llvm::OpenMPIRBuilder &OMPBuilder,
10059 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10061 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
10063 auto *CV = CapturedVars.begin();
10066 CI != CE; ++CI, ++RI, ++CV) {
10067 MappableExprsHandler::MapCombinedInfoTy CurInfo;
10072 CurInfo.Exprs.push_back(
nullptr);
10073 CurInfo.BasePointers.push_back(*CV);
10074 CurInfo.DevicePtrDecls.push_back(
nullptr);
10075 CurInfo.DevicePointers.push_back(
10076 MappableExprsHandler::DeviceInfoTy::None);
10077 CurInfo.Pointers.push_back(*CV);
10078 CurInfo.Sizes.push_back(CGF.
Builder.CreateIntCast(
10081 CurInfo.Types.push_back(OpenMPOffloadMappingFlags::OMP_MAP_LITERAL |
10082 OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM |
10083 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT);
10084 CurInfo.Mappers.push_back(
nullptr);
10088 MEHandler.generateInfoForCaptureFromClauseInfo(
10089 CI, *CV, CurInfo, OMPBuilder,
10090 CombinedInfo.BasePointers.size());
10095 MappedVarSet.insert(
nullptr);
10097 if (CurInfo.BasePointers.empty())
10098 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo);
10103 MEHandler.generateInfoForLambdaCaptures(CI->
getCapturedVar(), *CV,
10104 CurInfo, LambdaPointers);
10107 assert(!CurInfo.BasePointers.empty() &&
10108 "Non-existing map pointer for capture!");
10109 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() &&
10110 CurInfo.BasePointers.size() == CurInfo.Sizes.size() &&
10111 CurInfo.BasePointers.size() == CurInfo.Types.size() &&
10112 CurInfo.BasePointers.size() == CurInfo.Mappers.size() &&
10113 "Inconsistent map information sizes!");
10116 CombinedInfo.append(CurInfo);
10119 MEHandler.adjustMemberOfForLambdaCaptures(
10120 OMPBuilder, LambdaPointers, CombinedInfo.BasePointers,
10121 CombinedInfo.Pointers, CombinedInfo.Types);
10125 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo,
10126 llvm::OpenMPIRBuilder &OMPBuilder,
10133 MEHandler.generateAllInfo(CombinedInfo, OMPBuilder, SkippedVarSet);
10135 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10139 llvm::codegenoptions::NoDebugInfo) {
10140 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10141 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10149 llvm::OpenMPIRBuilder &OMPBuilder,
10150 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo) {
10152 MappableExprsHandler MEHandler(D, CGF);
10153 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet;
10156 MappedVarSet, CombinedInfo);
10157 genMapInfo(MEHandler, CGF, CombinedInfo, OMPBuilder, MappedVarSet);
10160template <
typename ClauseTy>
10165 const auto *
C = D.getSingleClause<ClauseTy>();
10166 assert(!
C->varlist_empty() &&
10167 "ompx_bare requires explicit num_teams and thread_limit");
10169 for (
auto *E :
C->varlist()) {
10181 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10183 llvm::Value *&MapTypesArray, llvm::Value *&MapNamesArray,
10188 llvm::OpenMPIRBuilder &OMPBuilder = OMPRuntime->
getOMPBuilder();
10191 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10193 genMapInfo(D, CGF, CS, CapturedVars, OMPBuilder, CombinedInfo);
10207 MapTypesArray = Info.RTArgs.MapTypesArray;
10208 MapNamesArray = Info.RTArgs.MapNamesArray;
10210 auto &&ThenGen = [&OMPRuntime, OutlinedFn, &D, &CapturedVars,
10211 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
10212 OutlinedFnID, &InputInfo, &MapTypesArray, &MapNamesArray,
10214 bool IsReverseOffloading =
Device.getInt() == OMPC_DEVICE_ancestor;
10216 if (IsReverseOffloading) {
10222 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10227 unsigned NumTargetItems = InputInfo.NumberOfTargetItems;
10229 llvm::Value *BasePointersArray =
10230 InputInfo.BasePointersArray.emitRawPointer(CGF);
10231 llvm::Value *PointersArray = InputInfo.PointersArray.emitRawPointer(CGF);
10232 llvm::Value *SizesArray = InputInfo.SizesArray.emitRawPointer(CGF);
10233 llvm::Value *MappersArray = InputInfo.MappersArray.emitRawPointer(CGF);
10235 auto &&EmitTargetCallFallbackCB =
10236 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
10237 OffloadingMandatory, &CGF](llvm::OpenMPIRBuilder::InsertPointTy IP)
10238 -> llvm::OpenMPIRBuilder::InsertPointTy {
10241 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10254 NumThreads.push_back(
10260 llvm::Value *NumIterations =
10263 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
10266 llvm::OpenMPIRBuilder::TargetDataRTArgs RTArgs(
10267 BasePointersArray, PointersArray, SizesArray, MapTypesArray,
10268 nullptr , MappersArray, MapNamesArray);
10270 llvm::OpenMPIRBuilder::TargetKernelArgs Args(
10271 NumTargetItems, RTArgs, NumIterations, NumTeams, NumThreads,
10272 DynCGroupMem, HasNoWait, DynCGroupMemFallback);
10274 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
10276 CGF.
Builder, OutlinedFnID, EmitTargetCallFallbackCB, Args, DeviceID,
10278 CGF.
Builder.restoreIP(AfterIP);
10281 if (RequiresOuterTask)
10296 [&OMPRuntime, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
10299 RequiresOuterTask, CS, OffloadingMandatory, CGF);
10302 if (RequiresOuterTask) {
10312 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
10313 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
10320 const bool OffloadingMandatory = !
CGM.getLangOpts().OpenMPIsTargetDevice &&
10321 CGM.getLangOpts().OpenMPOffloadMandatory;
10323 assert((OffloadingMandatory || OutlinedFn) &&
"Invalid outlined function!");
10325 const bool RequiresOuterTask =
10329 (
CGM.getLangOpts().OpenMP >= 51 &&
10333 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
10341 llvm::Value *MapTypesArray =
nullptr;
10342 llvm::Value *MapNamesArray =
nullptr;
10344 auto &&TargetThenGen = [
this, OutlinedFn, &D, &CapturedVars,
10345 RequiresOuterTask, &CS, OffloadingMandatory,
Device,
10346 OutlinedFnID, &InputInfo, &MapTypesArray,
10350 RequiresOuterTask, CS, OffloadingMandatory,
10351 Device, OutlinedFnID, InputInfo, MapTypesArray,
10352 MapNamesArray, SizeEmitter, CGF,
CGM);
10355 auto &&TargetElseGen =
10356 [
this, OutlinedFn, &D, &CapturedVars, RequiresOuterTask, &CS,
10359 CS, OffloadingMandatory, CGF);
10366 if (OutlinedFnID) {
10368 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
10380 StringRef ParentName) {
10385 bool RequiresDeviceCodegen =
10390 if (RequiresDeviceCodegen) {
10398 if (!
OMPBuilder.OffloadInfoManager.hasTargetRegionEntryInfo(EntryInfo))
10401 switch (E.getDirectiveKind()) {
10406 case OMPD_target_parallel:
10410 case OMPD_target_teams:
10414 case OMPD_target_teams_distribute:
10418 case OMPD_target_teams_distribute_simd:
10422 case OMPD_target_parallel_for:
10426 case OMPD_target_parallel_for_simd:
10430 case OMPD_target_simd:
10434 case OMPD_target_teams_distribute_parallel_for:
10439 case OMPD_target_teams_distribute_parallel_for_simd:
10445 case OMPD_target_teams_loop:
10449 case OMPD_target_parallel_loop:
10453 case OMPD_parallel:
10455 case OMPD_parallel_for:
10456 case OMPD_parallel_master:
10457 case OMPD_parallel_sections:
10458 case OMPD_for_simd:
10459 case OMPD_parallel_for_simd:
10461 case OMPD_cancellation_point:
10463 case OMPD_threadprivate:
10464 case OMPD_allocate:
10469 case OMPD_sections:
10473 case OMPD_critical:
10474 case OMPD_taskyield:
10476 case OMPD_taskwait:
10477 case OMPD_taskgroup:
10483 case OMPD_target_data:
10484 case OMPD_target_exit_data:
10485 case OMPD_target_enter_data:
10486 case OMPD_distribute:
10487 case OMPD_distribute_simd:
10488 case OMPD_distribute_parallel_for:
10489 case OMPD_distribute_parallel_for_simd:
10490 case OMPD_teams_distribute:
10491 case OMPD_teams_distribute_simd:
10492 case OMPD_teams_distribute_parallel_for:
10493 case OMPD_teams_distribute_parallel_for_simd:
10494 case OMPD_target_update:
10495 case OMPD_declare_simd:
10496 case OMPD_declare_variant:
10497 case OMPD_begin_declare_variant:
10498 case OMPD_end_declare_variant:
10499 case OMPD_declare_target:
10500 case OMPD_end_declare_target:
10501 case OMPD_declare_reduction:
10502 case OMPD_declare_mapper:
10503 case OMPD_taskloop:
10504 case OMPD_taskloop_simd:
10505 case OMPD_master_taskloop:
10506 case OMPD_master_taskloop_simd:
10507 case OMPD_parallel_master_taskloop:
10508 case OMPD_parallel_master_taskloop_simd:
10509 case OMPD_requires:
10510 case OMPD_metadirective:
10513 llvm_unreachable(
"Unknown target directive for OpenMP device codegen.");
10518 if (
const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
10519 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
10527 if (
const auto *L = dyn_cast<LambdaExpr>(S))
10536 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
10537 OMPDeclareTargetDeclAttr::getDeviceType(VD);
10541 if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
10544 if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host)
10552 if (!
CGM.getLangOpts().OpenMPIsTargetDevice) {
10553 if (
const auto *FD = dyn_cast<FunctionDecl>(GD.
getDecl()))
10555 CGM.getLangOpts().OpenMPIsTargetDevice))
10562 if (
const auto *FD = dyn_cast<FunctionDecl>(VD)) {
10563 StringRef Name =
CGM.getMangledName(GD);
10566 CGM.getLangOpts().OpenMPIsTargetDevice))
10571 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
10577 CGM.getLangOpts().OpenMPIsTargetDevice))
10580 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
10589 StringRef ParentName =
10594 StringRef ParentName =
10601 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
10602 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
10604 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
10605 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
10606 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
10615 llvm::Constant *
Addr) {
10616 if (
CGM.getLangOpts().OMPTargetTriples.empty() &&
10617 !
CGM.getLangOpts().OpenMPIsTargetDevice)
10620 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
10621 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
10625 if (Res && *Res != OMPDeclareTargetDeclAttr::MT_Link &&
10630 if (
CGM.getLangOpts().OpenMPIsTargetDevice) {
10633 StringRef VarName =
CGM.getMangledName(VD);
10639 auto AddrOfGlobal = [&VD,
this]() {
return CGM.GetAddrOfGlobal(VD); };
10640 auto LinkageForVariable = [&VD,
this]() {
10641 return CGM.getLLVMLinkageVarDefinition(VD);
10644 std::vector<llvm::GlobalVariable *> GeneratedRefs;
10651 CGM.getMangledName(VD), GeneratedRefs,
CGM.getLangOpts().OpenMPSimd,
10652 CGM.getLangOpts().OMPTargetTriples, AddrOfGlobal, LinkageForVariable,
10653 CGM.getTypes().ConvertTypeForMem(
10654 CGM.getContext().getPointerType(VD->
getType())),
10657 for (
auto *ref : GeneratedRefs)
10658 CGM.addCompilerUsedGlobal(ref);
10671 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
10672 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
10675 if ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
10676 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
10678 CGM.EmitGlobal(VD);
10680 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
10681 ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
10682 *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
10684 "Expected link clause or to clause with unified memory.");
10685 (void)
CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
10693 " Expected target-based directive.");
10698 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
10700 OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(
true);
10701 }
else if (
const auto *AC =
10702 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
10703 switch (AC->getAtomicDefaultMemOrderKind()) {
10704 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
10707 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
10710 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
10726 if (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())
10728 const auto *A = VD->
getAttr<OMPAllocateDeclAttr>();
10729 switch(A->getAllocatorType()) {
10730 case OMPAllocateDeclAttr::OMPNullMemAlloc:
10731 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
10733 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
10734 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
10735 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
10736 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
10737 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
10738 case OMPAllocateDeclAttr::OMPConstMemAlloc:
10739 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
10742 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
10743 llvm_unreachable(
"Expected predefined allocator for the variables with the "
10744 "static storage.");
10756 if (CGM.getLangOpts().OpenMPIsTargetDevice) {
10757 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
10758 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
10763 if (CGM.getLangOpts().OpenMPIsTargetDevice)
10764 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
10774 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
10776 if (
auto *F = dyn_cast_or_null<llvm::Function>(
10777 CGM.GetGlobalValue(
CGM.getMangledName(GD))))
10778 return !F->isDeclaration();
10790 llvm::Function *OutlinedFn,
10799 llvm::Value *Args[] = {
10801 CGF.
Builder.getInt32(CapturedVars.size()),
10804 RealArgs.append(std::begin(Args), std::end(Args));
10805 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
10807 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
10808 CGM.getModule(), OMPRTL___kmpc_fork_teams);
10813 const Expr *NumTeams,
10814 const Expr *ThreadLimit,
10821 llvm::Value *NumTeamsVal =
10827 llvm::Value *ThreadLimitVal =
10834 llvm::Value *PushNumTeamsArgs[] = {RTLoc,
getThreadID(CGF, Loc), NumTeamsVal,
10837 CGM.getModule(), OMPRTL___kmpc_push_num_teams),
10842 const Expr *ThreadLimit,
10845 llvm::Value *ThreadLimitVal =
10852 llvm::Value *ThreadLimitArgs[] = {RTLoc,
getThreadID(CGF, Loc),
10855 CGM.getModule(), OMPRTL___kmpc_set_thread_limit),
10870 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
10872 llvm::Value *IfCondVal =
nullptr;
10877 llvm::Value *DeviceID =
nullptr;
10882 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
10886 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
10887 auto GenMapInfoCB =
10888 [&](InsertPointTy CodeGenIP) -> llvm::OpenMPIRBuilder::MapInfosTy & {
10889 CGF.
Builder.restoreIP(CodeGenIP);
10891 MappableExprsHandler MEHandler(D, CGF);
10892 MEHandler.generateAllInfo(CombinedInfo,
OMPBuilder);
10894 auto FillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) {
10897 if (
CGM.getCodeGenOpts().getDebugInfo() !=
10898 llvm::codegenoptions::NoDebugInfo) {
10899 CombinedInfo.Names.resize(CombinedInfo.Exprs.size());
10900 llvm::transform(CombinedInfo.Exprs, CombinedInfo.Names.begin(),
10904 return CombinedInfo;
10906 using BodyGenTy = llvm::OpenMPIRBuilder::BodyGenTy;
10907 auto BodyCB = [&](InsertPointTy CodeGenIP, BodyGenTy BodyGenType) {
10908 CGF.
Builder.restoreIP(CodeGenIP);
10909 switch (BodyGenType) {
10910 case BodyGenTy::Priv:
10914 case BodyGenTy::DupNoPriv:
10916 CodeGen.setAction(NoPrivAction);
10920 case BodyGenTy::NoPriv:
10922 CodeGen.setAction(NoPrivAction);
10927 return InsertPointTy(CGF.
Builder.GetInsertBlock(),
10928 CGF.
Builder.GetInsertPoint());
10931 auto DeviceAddrCB = [&](
unsigned int I, llvm::Value *NewDecl) {
10932 if (
const ValueDecl *DevVD = CombinedInfo.DevicePtrDecls[I]) {
10937 auto CustomMapperCB = [&](
unsigned int I) {
10938 llvm::Function *MFunc =
nullptr;
10939 if (CombinedInfo.Mappers[I]) {
10940 Info.HasMapper =
true;
10952 InsertPointTy CodeGenIP(CGF.
Builder.GetInsertBlock(),
10953 CGF.
Builder.GetInsertPoint());
10954 llvm::OpenMPIRBuilder::LocationDescription OmpLoc(CodeGenIP);
10955 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
10957 OmpLoc, AllocaIP, CodeGenIP, DeviceID, IfCondVal, Info, GenMapInfoCB,
10959 nullptr, BodyCB, DeviceAddrCB, RTLoc));
10960 CGF.
Builder.restoreIP(AfterIP);
10972 "Expecting either target enter, exit data, or update directives.");
10975 llvm::Value *MapTypesArray =
nullptr;
10976 llvm::Value *MapNamesArray =
nullptr;
10978 auto &&ThenGen = [
this, &D,
Device, &InputInfo, &MapTypesArray,
10981 llvm::Value *DeviceID =
nullptr;
10986 DeviceID = CGF.
Builder.getInt64(OMP_DEVICEID_UNDEF);
10990 llvm::Constant *PointerNum =
10997 {RTLoc, DeviceID, PointerNum,
11006 RuntimeFunction RTLFn;
11007 switch (D.getDirectiveKind()) {
11008 case OMPD_target_enter_data:
11009 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper
11010 : OMPRTL___tgt_target_data_begin_mapper;
11012 case OMPD_target_exit_data:
11013 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper
11014 : OMPRTL___tgt_target_data_end_mapper;
11016 case OMPD_target_update:
11017 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper
11018 : OMPRTL___tgt_target_data_update_mapper;
11020 case OMPD_parallel:
11022 case OMPD_parallel_for:
11023 case OMPD_parallel_master:
11024 case OMPD_parallel_sections:
11025 case OMPD_for_simd:
11026 case OMPD_parallel_for_simd:
11028 case OMPD_cancellation_point:
11030 case OMPD_threadprivate:
11031 case OMPD_allocate:
11036 case OMPD_sections:
11040 case OMPD_critical:
11041 case OMPD_taskyield:
11043 case OMPD_taskwait:
11044 case OMPD_taskgroup:
11050 case OMPD_target_data:
11051 case OMPD_distribute:
11052 case OMPD_distribute_simd:
11053 case OMPD_distribute_parallel_for:
11054 case OMPD_distribute_parallel_for_simd:
11055 case OMPD_teams_distribute:
11056 case OMPD_teams_distribute_simd:
11057 case OMPD_teams_distribute_parallel_for:
11058 case OMPD_teams_distribute_parallel_for_simd:
11059 case OMPD_declare_simd:
11060 case OMPD_declare_variant:
11061 case OMPD_begin_declare_variant:
11062 case OMPD_end_declare_variant:
11063 case OMPD_declare_target:
11064 case OMPD_end_declare_target:
11065 case OMPD_declare_reduction:
11066 case OMPD_declare_mapper:
11067 case OMPD_taskloop:
11068 case OMPD_taskloop_simd:
11069 case OMPD_master_taskloop:
11070 case OMPD_master_taskloop_simd:
11071 case OMPD_parallel_master_taskloop:
11072 case OMPD_parallel_master_taskloop_simd:
11074 case OMPD_target_simd:
11075 case OMPD_target_teams_distribute:
11076 case OMPD_target_teams_distribute_simd:
11077 case OMPD_target_teams_distribute_parallel_for:
11078 case OMPD_target_teams_distribute_parallel_for_simd:
11079 case OMPD_target_teams:
11080 case OMPD_target_parallel:
11081 case OMPD_target_parallel_for:
11082 case OMPD_target_parallel_for_simd:
11083 case OMPD_requires:
11084 case OMPD_metadirective:
11087 llvm_unreachable(
"Unexpected standalone target data directive.");
11091 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11092 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11093 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
Int32Ty));
11094 OffloadingArgs.push_back(llvm::Constant::getNullValue(CGF.
VoidPtrTy));
11097 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), RTLFn),
11101 auto &&TargetThenGen = [
this, &ThenGen, &D, &InputInfo, &MapTypesArray,
11105 MappableExprsHandler::MapCombinedInfoTy CombinedInfo;
11107 MappableExprsHandler MEHandler(D, CGF);
11119 CGM.getPointerAlign());
11124 MapTypesArray = Info.RTArgs.MapTypesArray;
11125 MapNamesArray = Info.RTArgs.MapNamesArray;
11126 if (RequiresOuterTask)
11152struct ParamAttrTy {
11153 ParamKindTy Kind =
Vector;
11154 llvm::APSInt StrideOrArg;
11155 llvm::APSInt Alignment;
11156 bool HasVarStride =
false;
11189 unsigned Offset = 0;
11190 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
11191 if (ParamAttrs[Offset].Kind ==
Vector)
11192 CDT =
C.getPointerType(
C.getCanonicalTagType(MD->
getParent()));
11196 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
11197 if (ParamAttrs[I + Offset].Kind ==
Vector) {
11209 return C.getTypeSize(CDT);
11217 llvm::raw_svector_ostream Out(Buffer);
11218 for (
const auto &ParamAttr : ParamAttrs) {
11219 switch (ParamAttr.Kind) {
11239 if (ParamAttr.HasVarStride)
11240 Out <<
"s" << ParamAttr.StrideOrArg;
11241 else if (ParamAttr.Kind == Linear || ParamAttr.Kind == LinearRef ||
11242 ParamAttr.Kind == LinearUVal || ParamAttr.Kind == LinearVal) {
11245 if (ParamAttr.StrideOrArg < 0)
11246 Out <<
'n' << -ParamAttr.StrideOrArg;
11247 else if (ParamAttr.StrideOrArg != 1)
11248 Out << ParamAttr.StrideOrArg;
11251 if (!!ParamAttr.Alignment)
11252 Out <<
'a' << ParamAttr.Alignment;
11255 return std::string(Out.str());
11260 const llvm::APSInt &VLENVal,
11262 OMPDeclareSimdDeclAttr::BranchStateTy State) {
11265 unsigned VecRegSize;
11267 ISADataTy ISAData[] = {
11283 case OMPDeclareSimdDeclAttr::BS_Undefined:
11284 Masked.push_back(
'N');
11285 Masked.push_back(
'M');
11287 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
11288 Masked.push_back(
'N');
11290 case OMPDeclareSimdDeclAttr::BS_Inbranch:
11291 Masked.push_back(
'M');
11294 for (
char Mask : Masked) {
11295 for (
const ISADataTy &
Data : ISAData) {
11297 llvm::raw_svector_ostream Out(Buffer);
11298 Out <<
"_ZGV" <<
Data.ISA << Mask;
11301 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
11302 Out << llvm::APSInt::getUnsigned(
Data.VecRegSize / NumElts);
11307 Out <<
'_' << Fn->getName();
11308 Fn->addFnAttr(Out.str());
11326 if (Kind == ParamKindTy::Uniform)
11329 if (Kind == ParamKindTy::LinearUVal || Kind == ParamKindTy::LinearRef)
11332 if ((Kind == ParamKindTy::Linear || Kind == ParamKindTy::LinearVal) &&
11342 unsigned Size =
C.getTypeSize(QT);
11345 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
11369 return C.getTypeSize(PTy);
11372 return C.getTypeSize(QT);
11374 return C.getTypeSize(
C.getUIntPtrType());
11380static std::tuple<unsigned, unsigned, bool>
11386 bool OutputBecomesInput =
false;
11390 Sizes.push_back(
getAArch64LS(RetType, ParamKindTy::Vector,
C));
11392 OutputBecomesInput =
true;
11394 for (
unsigned I = 0, E = FD->
getNumParams(); I < E; ++I) {
11399 assert(!Sizes.empty() &&
"Unable to determine NDS and WDS.");
11402 assert(llvm::all_of(Sizes,
11403 [](
unsigned Size) {
11404 return Size == 8 || Size == 16 || Size == 32 ||
11405 Size == 64 || Size == 128;
11409 return std::make_tuple(*llvm::min_element(Sizes), *llvm::max_element(Sizes),
11410 OutputBecomesInput);
11416template <
typename T>
11418 char ISA, StringRef ParSeq,
11419 StringRef MangledName,
bool OutputBecomesInput,
11420 llvm::Function *Fn) {
11422 llvm::raw_svector_ostream Out(Buffer);
11423 Out << Prefix << ISA << LMask << VLEN;
11424 if (OutputBecomesInput)
11426 Out << ParSeq <<
"_" << MangledName;
11427 Fn->addFnAttr(Out.str());
11433 StringRef Prefix,
char ISA,
11434 StringRef ParSeq, StringRef MangledName,
11435 bool OutputBecomesInput,
11436 llvm::Function *Fn) {
11440 OutputBecomesInput, Fn);
11442 OutputBecomesInput, Fn);
11446 OutputBecomesInput, Fn);
11448 OutputBecomesInput, Fn);
11452 OutputBecomesInput, Fn);
11454 OutputBecomesInput, Fn);
11459 OutputBecomesInput, Fn);
11462 llvm_unreachable(
"Scalar type is too wide.");
11470 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
11471 char ISA,
unsigned VecRegSize, llvm::Function *Fn,
SourceLocation SLoc) {
11475 const unsigned NDS = std::get<0>(
Data);
11476 const unsigned WDS = std::get<1>(
Data);
11477 const bool OutputBecomesInput = std::get<2>(
Data);
11481 if (UserVLEN == 1) {
11484 "The clause simdlen(1) has no effect when targeting aarch64.");
11491 if (ISA ==
'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
11494 "power of 2 when targeting Advanced SIMD.");
11501 if (ISA ==
's' && UserVLEN != 0) {
11502 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
11505 "lanes in the architectural constraints "
11506 "for SVE (min is 128-bit, max is "
11507 "2048-bit, by steps of 128-bit)");
11515 StringRef Prefix =
"_ZGV";
11521 OutputBecomesInput, Fn);
11523 assert(ISA ==
'n' &&
"Expected ISA either 's' or 'n'.");
11527 case OMPDeclareSimdDeclAttr::BS_Undefined:
11529 OutputBecomesInput, Fn);
11531 OutputBecomesInput, Fn);
11533 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
11535 OutputBecomesInput, Fn);
11537 case OMPDeclareSimdDeclAttr::BS_Inbranch:
11539 OutputBecomesInput, Fn);
11549 OutputBecomesInput, Fn);
11551 assert(ISA ==
'n' &&
"Expected ISA either 's' or 'n'.");
11556 case OMPDeclareSimdDeclAttr::BS_Undefined:
11558 OutputBecomesInput, Fn);
11560 OutputBecomesInput, Fn);
11562 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
11564 OutputBecomesInput, Fn);
11566 case OMPDeclareSimdDeclAttr::BS_Inbranch:
11568 OutputBecomesInput, Fn);
11576 llvm::Function *Fn) {
11581 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
11583 ParamPositions.try_emplace(FD, 0);
11584 unsigned ParamPos = ParamPositions.size();
11586 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
11592 for (
const Expr *E :
Attr->uniforms()) {
11596 Pos = ParamPositions[FD];
11599 ->getCanonicalDecl();
11600 auto It = ParamPositions.find(PVD);
11601 assert(It != ParamPositions.end() &&
"Function parameter not found");
11604 ParamAttrs[Pos].Kind = Uniform;
11607 auto *NI =
Attr->alignments_begin();
11608 for (
const Expr *E :
Attr->aligneds()) {
11613 Pos = ParamPositions[FD];
11617 ->getCanonicalDecl();
11618 auto It = ParamPositions.find(PVD);
11619 assert(It != ParamPositions.end() &&
"Function parameter not found");
11621 ParmTy = PVD->getType();
11623 ParamAttrs[Pos].Alignment =
11625 ? (*NI)->EvaluateKnownConstInt(
C)
11626 : llvm::APSInt::getUnsigned(
11627 C.toCharUnitsFromBits(
C.getOpenMPDefaultSimdAlign(ParmTy))
11632 auto *SI =
Attr->steps_begin();
11633 auto *MI =
Attr->modifiers_begin();
11634 for (
const Expr *E :
Attr->linears()) {
11637 bool IsReferenceType =
false;
11640 unsigned PtrRescalingFactor = 1;
11642 Pos = ParamPositions[FD];
11644 PtrRescalingFactor =
CGM.getContext()
11645 .getTypeSizeInChars(P->getPointeeType())
11649 ->getCanonicalDecl();
11650 auto It = ParamPositions.find(PVD);
11651 assert(It != ParamPositions.end() &&
"Function parameter not found");
11653 if (
auto *P = dyn_cast<PointerType>(PVD->getType()))
11654 PtrRescalingFactor =
CGM.getContext()
11655 .getTypeSizeInChars(P->getPointeeType())
11657 else if (PVD->getType()->isReferenceType()) {
11658 IsReferenceType =
true;
11659 PtrRescalingFactor =
11661 .getTypeSizeInChars(PVD->getType().getNonReferenceType())
11665 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
11666 if (*MI == OMPC_LINEAR_ref)
11667 ParamAttr.Kind = LinearRef;
11668 else if (*MI == OMPC_LINEAR_uval)
11669 ParamAttr.Kind = LinearUVal;
11670 else if (IsReferenceType)
11671 ParamAttr.Kind = LinearVal;
11673 ParamAttr.Kind = Linear;
11675 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1);
11679 if (
const auto *DRE =
11681 if (
const auto *StridePVD =
11682 dyn_cast<ParmVarDecl>(DRE->getDecl())) {
11683 ParamAttr.HasVarStride =
true;
11684 auto It = ParamPositions.find(StridePVD->getCanonicalDecl());
11685 assert(It != ParamPositions.end() &&
11686 "Function parameter not found");
11687 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(It->second);
11691 ParamAttr.StrideOrArg =
Result.Val.getInt();
11697 if (!ParamAttr.HasVarStride &&
11698 (ParamAttr.Kind == Linear || ParamAttr.Kind == LinearRef))
11699 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor;
11703 llvm::APSInt VLENVal;
11705 const Expr *VLENExpr =
Attr->getSimdlen();
11710 OMPDeclareSimdDeclAttr::BranchStateTy State =
Attr->getBranchState();
11711 if (
CGM.getTriple().isX86()) {
11713 }
else if (
CGM.getTriple().getArch() == llvm::Triple::aarch64) {
11714 unsigned VLEN = VLENVal.getExtValue();
11715 StringRef MangledName = Fn->getName();
11716 if (
CGM.getTarget().hasFeature(
"sve"))
11718 MangledName,
's', 128, Fn, ExprLoc);
11719 else if (
CGM.getTarget().hasFeature(
"neon"))
11721 MangledName,
'n', 128, Fn, ExprLoc);
11730class DoacrossCleanupTy final :
public EHScopeStack::Cleanup {
11732 static const int DoacrossFinArgs = 2;
11735 llvm::FunctionCallee RTLFn;
11736 llvm::Value *Args[DoacrossFinArgs];
11739 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
11742 assert(CallArgs.size() == DoacrossFinArgs);
11743 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
11760 QualType Int64Ty =
C.getIntTypeForBitwidth(64,
true);
11768 RD =
C.buildImplicitRecord(
"kmp_dim");
11776 RD =
KmpDimTy->castAsRecordDecl();
11778 llvm::APInt Size(32, NumIterations.size());
11784 enum { LowerFD = 0, UpperFD, StrideFD };
11786 for (
unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
11791 DimsLVal, *std::next(RD->
field_begin(), UpperFD));
11793 CGF.
EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(),
11794 Int64Ty, NumIterations[I]->getExprLoc());
11798 DimsLVal, *std::next(RD->
field_begin(), StrideFD));
11805 llvm::Value *Args[] = {
11808 llvm::ConstantInt::getSigned(
CGM.Int32Ty, NumIterations.size()),
11813 llvm::FunctionCallee RTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
11814 CGM.getModule(), OMPRTL___kmpc_doacross_init);
11816 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
11818 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
11819 CGM.getModule(), OMPRTL___kmpc_doacross_fini);
11824template <
typename T>
11826 const T *
C, llvm::Value *ULoc,
11827 llvm::Value *ThreadID) {
11830 llvm::APInt Size(32,
C->getNumLoops());
11834 for (
unsigned I = 0, E =
C->getNumLoops(); I < E; ++I) {
11835 const Expr *CounterVal =
C->getLoopData(I);
11836 assert(CounterVal);
11843 llvm::Value *Args[] = {
11846 llvm::FunctionCallee RTLFn;
11848 OMPDoacrossKind<T> ODK;
11849 if (ODK.isSource(
C)) {
11851 OMPRTL___kmpc_doacross_post);
11853 assert(ODK.isSink(
C) &&
"Expect sink modifier.");
11855 OMPRTL___kmpc_doacross_wait);
11875 llvm::FunctionCallee Callee,
11877 assert(Loc.
isValid() &&
"Outlined function call location must be valid.");
11880 if (
auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
11881 if (Fn->doesNotThrow()) {
11892 emitCall(CGF, Loc, OutlinedFn, Args);
11896 if (
const auto *FD = dyn_cast<FunctionDecl>(D))
11897 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
11903 const VarDecl *TargetParam)
const {
11910 const Expr *Allocator) {
11911 llvm::Value *AllocVal;
11921 AllocVal = llvm::Constant::getNullValue(
11931 if (!AllocateAlignment)
11934 return llvm::ConstantInt::get(
CGM.
SizeTy, AllocateAlignment->getQuantity());
11947 auto I = UntiedData.find(VD);
11948 if (I != UntiedData.end()) {
11949 UntiedAddr = I->second.first;
11950 UntiedRealAddr = I->second.second;
11954 if (CVD->
hasAttr<OMPAllocateDeclAttr>()) {
11963 Size = CGF.
Builder.CreateNUWAdd(
11965 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
11966 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
11972 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
11973 const Expr *Allocator = AA->getAllocator();
11977 Args.push_back(ThreadID);
11979 Args.push_back(Alignment);
11980 Args.push_back(Size);
11981 Args.push_back(AllocVal);
11982 llvm::omp::RuntimeFunction FnID =
11983 Alignment ? OMPRTL___kmpc_aligned_alloc : OMPRTL___kmpc_alloc;
11985 OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), FnID), Args,
11987 llvm::FunctionCallee FiniRTLFn =
OMPBuilder.getOrCreateRuntimeFunction(
11988 CGM.getModule(), OMPRTL___kmpc_free);
11996 class OMPAllocateCleanupTy final :
public EHScopeStack::Cleanup {
11997 llvm::FunctionCallee RTLFn;
12000 const Expr *AllocExpr;
12003 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
12005 const Expr *AllocExpr)
12006 : RTLFn(RTLFn), LocEncoding(LocEncoding),
Addr(
Addr),
12007 AllocExpr(AllocExpr) {}
12011 llvm::Value *Args[3];
12017 Args[2] = AllocVal;
12025 CGF.
EHStack.pushCleanup<OMPAllocateCleanupTy>(
12027 VDAddr, Allocator);
12028 if (UntiedRealAddr.
isValid())
12031 Region->emitUntiedSwitch(CGF);
12048 assert(CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12052 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back();
12054 for (
const Stmt *Ref :
C->private_refs()) {
12055 const auto *SimpleRefExpr =
cast<Expr>(Ref)->IgnoreParenImpCasts();
12057 if (
const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
12058 VD = DRE->getDecl();
12061 assert((ME->isImplicitCXXThis() ||
12063 "Expected member of current class.");
12064 VD = ME->getMemberDecl();
12074 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back();
12080 std::pair<Address, Address>> &LocalVars)
12081 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) {
12085 CGF.
CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size());
12086 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars);
12092 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back();
12096 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12098 return llvm::any_of(
12099 CGM.getOpenMPRuntime().NontemporalDeclsStack,
12103void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
12107 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
12113 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front());
12121 for (
const Expr *Ref :
C->varlist()) {
12122 if (!Ref->getType()->isScalarType())
12124 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12127 NeedToCheckForLPCs.insert(DRE->getDecl());
12130 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
12131 for (
const Expr *Ref :
C->varlist()) {
12132 if (!Ref->getType()->isScalarType())
12134 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12137 NeedToCheckForLPCs.insert(DRE->getDecl());
12140 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
12141 for (
const Expr *Ref :
C->varlist()) {
12142 if (!Ref->getType()->isScalarType())
12144 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12147 NeedToCheckForLPCs.insert(DRE->getDecl());
12150 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
12151 for (
const Expr *Ref :
C->varlist()) {
12152 if (!Ref->getType()->isScalarType())
12154 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12157 NeedToCheckForLPCs.insert(DRE->getDecl());
12160 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
12161 for (
const Expr *Ref :
C->varlist()) {
12162 if (!Ref->getType()->isScalarType())
12164 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
12167 NeedToCheckForLPCs.insert(DRE->getDecl());
12170 for (
const Decl *VD : NeedToCheckForLPCs) {
12172 llvm::reverse(
CGM.getOpenMPRuntime().LastprivateConditionalStack)) {
12173 if (
Data.DeclToUniqueName.count(VD) > 0) {
12174 if (!
Data.Disabled)
12175 NeedToAddForLPCsAsDisabled.insert(VD);
12182CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12185 Action((CGM.getLangOpts().OpenMP >= 50 &&
12188 return C->getKind() ==
12189 OMPC_LASTPRIVATE_conditional;
12191 ? ActionToDo::PushAsLastprivateConditional
12192 : ActionToDo::DoNotPush) {
12193 assert(
CGM.getLangOpts().OpenMP &&
"Not in OpenMP mode.");
12194 if (
CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
12196 assert(Action == ActionToDo::PushAsLastprivateConditional &&
12197 "Expected a push action.");
12199 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
12201 if (
C->getKind() != OMPC_LASTPRIVATE_conditional)
12204 for (
const Expr *Ref :
C->varlist()) {
12205 Data.DeclToUniqueName.insert(std::make_pair(
12210 Data.IVLVal = IVLVal;
12214CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
12216 :
CGM(CGF.
CGM), Action(ActionToDo::DoNotPush) {
12220 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
12221 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
12222 if (!NeedToAddForLPCsAsDisabled.empty()) {
12223 Action = ActionToDo::DisableLastprivateConditional;
12224 LastprivateConditionalData &
Data =
12226 for (
const Decl *VD : NeedToAddForLPCsAsDisabled)
12227 Data.DeclToUniqueName.try_emplace(VD);
12229 Data.Disabled =
true;
12233CGOpenMPRuntime::LastprivateConditionalRAII
12236 return LastprivateConditionalRAII(CGF, S);
12240 if (CGM.getLangOpts().OpenMP < 50)
12242 if (Action == ActionToDo::DisableLastprivateConditional) {
12243 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12244 "Expected list of disabled private vars.");
12245 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12247 if (Action == ActionToDo::PushAsLastprivateConditional) {
12249 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
12250 "Expected list of lastprivate conditional vars.");
12251 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
12263 auto VI = I->getSecond().find(VD);
12264 if (VI == I->getSecond().end()) {
12265 RecordDecl *RD =
C.buildImplicitRecord(
"lasprivate.conditional");
12270 NewType =
C.getCanonicalTagType(RD);
12273 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
12275 NewType = std::get<0>(VI->getSecond());
12276 VDField = std::get<1>(VI->getSecond());
12277 FiredField = std::get<2>(VI->getSecond());
12278 BaseLVal = std::get<3>(VI->getSecond());
12290class LastprivateConditionalRefChecker final
12293 const Expr *FoundE =
nullptr;
12294 const Decl *FoundD =
nullptr;
12295 StringRef UniqueDeclName;
12297 llvm::Function *FoundFn =
nullptr;
12303 llvm::reverse(LPM)) {
12304 auto It = D.DeclToUniqueName.find(E->
getDecl());
12305 if (It == D.DeclToUniqueName.end())
12311 UniqueDeclName = It->second;
12316 return FoundE == E;
12322 llvm::reverse(LPM)) {
12324 if (It == D.DeclToUniqueName.end())
12330 UniqueDeclName = It->second;
12335 return FoundE == E;
12337 bool VisitStmt(
const Stmt *S) {
12338 for (
const Stmt *Child : S->
children()) {
12341 if (
const auto *E = dyn_cast<Expr>(Child))
12349 explicit LastprivateConditionalRefChecker(
12350 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM)
12352 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
12353 getFoundData()
const {
12354 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
12361 StringRef UniqueDeclName,
12367 llvm::Constant *LastIV =
OMPBuilder.getOrCreateInternalVariable(
12368 LLIVTy,
getName({UniqueDeclName,
"iv"}));
12376 llvm::GlobalVariable *
Last =
OMPBuilder.getOrCreateInternalVariable(
12392 auto &&
CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
12398 llvm::Value *CmpRes;
12400 CmpRes = CGF.
Builder.CreateICmpSLE(LastIVVal, IVVal);
12403 "Loop iteration variable must be integer.");
12404 CmpRes = CGF.
Builder.CreateICmpULE(LastIVVal, IVVal);
12408 CGF.
Builder.CreateCondBr(CmpRes, ThenBB, ExitBB);
12429 "Aggregates are not supported in lastprivate conditional.");
12438 if (
CGM.getLangOpts().OpenMPSimd) {
12452 if (!Checker.Visit(LHS))
12454 const Expr *FoundE;
12455 const Decl *FoundD;
12456 StringRef UniqueDeclName;
12458 llvm::Function *FoundFn;
12459 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
12460 Checker.getFoundData();
12461 if (FoundFn != CGF.
CurFn) {
12466 "Lastprivate conditional is not found in outer region.");
12467 QualType StructTy = std::get<0>(It->getSecond());
12468 const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
12479 FiredLVal, llvm::AtomicOrdering::Unordered,
12497 auto It = llvm::find_if(
12499 if (It == Range.end() || It->Fn != CGF.
CurFn)
12503 "Lastprivates must be registered already.");
12506 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back());
12507 for (
const auto &Pair : It->DeclToUniqueName) {
12508 const auto *VD =
cast<VarDecl>(Pair.first->getCanonicalDecl());
12511 auto I = LPCI->getSecond().find(Pair.first);
12512 assert(I != LPCI->getSecond().end() &&
12513 "Lastprivate must be rehistered already.");
12515 LValue BaseLVal = std::get<3>(I->getSecond());
12519 llvm::Value *Cmp = CGF.
Builder.CreateIsNotNull(Res);
12523 CGF.
Builder.CreateCondBr(Cmp, ThenBB, DoneBB);
12548 "Unknown lastprivate conditional variable.");
12549 StringRef UniqueName = It->second;
12550 llvm::GlobalVariable *GV =
CGM.getModule().getNamedGlobal(UniqueName);
12564 llvm_unreachable(
"Not supported in SIMD-only mode");
12571 llvm_unreachable(
"Not supported in SIMD-only mode");
12578 bool Tied,
unsigned &NumberOfParts) {
12579 llvm_unreachable(
"Not supported in SIMD-only mode");
12587 llvm_unreachable(
"Not supported in SIMD-only mode");
12593 const Expr *Hint) {
12594 llvm_unreachable(
"Not supported in SIMD-only mode");
12600 llvm_unreachable(
"Not supported in SIMD-only mode");
12606 const Expr *Filter) {
12607 llvm_unreachable(
"Not supported in SIMD-only mode");
12612 llvm_unreachable(
"Not supported in SIMD-only mode");
12618 llvm_unreachable(
"Not supported in SIMD-only mode");
12626 llvm_unreachable(
"Not supported in SIMD-only mode");
12633 llvm_unreachable(
"Not supported in SIMD-only mode");
12640 bool ForceSimpleCall) {
12641 llvm_unreachable(
"Not supported in SIMD-only mode");
12648 llvm_unreachable(
"Not supported in SIMD-only mode");
12653 llvm_unreachable(
"Not supported in SIMD-only mode");
12659 llvm_unreachable(
"Not supported in SIMD-only mode");
12665 llvm_unreachable(
"Not supported in SIMD-only mode");
12672 llvm_unreachable(
"Not supported in SIMD-only mode");
12678 llvm_unreachable(
"Not supported in SIMD-only mode");
12683 unsigned IVSize,
bool IVSigned,
12686 llvm_unreachable(
"Not supported in SIMD-only mode");
12694 llvm_unreachable(
"Not supported in SIMD-only mode");
12698 ProcBindKind ProcBind,
12700 llvm_unreachable(
"Not supported in SIMD-only mode");
12707 llvm_unreachable(
"Not supported in SIMD-only mode");
12713 llvm_unreachable(
"Not supported in SIMD-only mode");
12718 llvm_unreachable(
"Not supported in SIMD-only mode");
12724 llvm::AtomicOrdering AO) {
12725 llvm_unreachable(
"Not supported in SIMD-only mode");
12730 llvm::Function *TaskFunction,
12732 const Expr *IfCond,
12734 llvm_unreachable(
"Not supported in SIMD-only mode");
12741 llvm_unreachable(
"Not supported in SIMD-only mode");
12748 assert(Options.
SimpleReduction &&
"Only simple reduction is expected.");
12750 ReductionOps, Options);
12756 llvm_unreachable(
"Not supported in SIMD-only mode");
12761 bool IsWorksharingReduction) {
12762 llvm_unreachable(
"Not supported in SIMD-only mode");
12769 llvm_unreachable(
"Not supported in SIMD-only mode");
12774 llvm::Value *ReductionsPtr,
12776 llvm_unreachable(
"Not supported in SIMD-only mode");
12782 llvm_unreachable(
"Not supported in SIMD-only mode");
12788 llvm_unreachable(
"Not supported in SIMD-only mode");
12794 llvm_unreachable(
"Not supported in SIMD-only mode");
12799 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
12801 llvm_unreachable(
"Not supported in SIMD-only mode");
12806 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID,
const Expr *IfCond,
12807 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device,
12811 llvm_unreachable(
"Not supported in SIMD-only mode");
12815 llvm_unreachable(
"Not supported in SIMD-only mode");
12819 llvm_unreachable(
"Not supported in SIMD-only mode");
12829 llvm::Function *OutlinedFn,
12831 llvm_unreachable(
"Not supported in SIMD-only mode");
12835 const Expr *NumTeams,
12836 const Expr *ThreadLimit,
12838 llvm_unreachable(
"Not supported in SIMD-only mode");
12845 llvm_unreachable(
"Not supported in SIMD-only mode");
12851 llvm_unreachable(
"Not supported in SIMD-only mode");
12857 llvm_unreachable(
"Not supported in SIMD-only mode");
12862 llvm_unreachable(
"Not supported in SIMD-only mode");
12867 llvm_unreachable(
"Not supported in SIMD-only mode");
12872 const VarDecl *NativeParam)
const {
12873 llvm_unreachable(
"Not supported in SIMD-only mode");
12879 const VarDecl *TargetParam)
const {
12880 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...
Address EmitLoadOfReference(LValue RefLVal, LValueBaseInfo *PointeeBaseInfo=nullptr, TBAAAccessInfo *PointeeTBAAInfo=nullptr)
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
llvm::Value * EmitCheckedInBoundsGEP(llvm::Type *ElemTy, llvm::Value *Ptr, ArrayRef< llvm::Value * > IdxList, bool SignedIndices, bool IsSubtraction, SourceLocation Loc, const Twine &Name="")
Same as IRBuilder::CreateInBoundsGEP, but additionally emits a check to detect undefined behavior whe...
static void EmitOMPTargetParallelGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelGenericLoopDirective &S)
Emit device code for the target parallel loop directive.
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
static bool IsWrappedCXXThis(const Expr *E)
Check if E is a C++ "this" pointer wrapped in value-preserving casts.
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S)
Emit device code for the target simd directive.
static void EmitOMPTargetParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForDirective &S)
Emit device code for the target parallel for directive.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)
ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant,...
static void EmitOMPTargetTeamsGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsGenericLoopDirective &S)
Emit device code for the target teams loop directive.
LValue EmitMemberExpr(const MemberExpr *E)
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
Address ReturnValue
ReturnValue - The temporary alloca to hold the return value.
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
static void EmitOMPTargetTeamsDistributeSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeSimdDirective &S)
Emit device code for the target teams distribute simd directive.
llvm::Value * EmitScalarConversion(llvm::Value *Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified type to the specified destination type, both of which are LLVM s...
void EmitVariablyModifiedType(QualType Ty)
EmitVLASize - Capture all the sizes for the VLA expressions in the given variably-modified type and s...
bool isTrivialInitializer(const Expr *Init)
Determine whether the given initializer is trivial in the sense that it requires no code to be genera...
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
void EmitExprAsInit(const Expr *init, const ValueDecl *D, LValue lvalue, bool capturedByInit)
EmitExprAsInit - Emits the code necessary to initialize a location in memory with the given initializ...
LValue MakeNaturalAlignRawAddrLValue(llvm::Value *V, QualType T)
This class organizes the cross-function state that is used while generating LLVM code.
void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)
Set the attributes on the LLVM function for the given decl and function info.
llvm::Module & getModule() const
const IntrusiveRefCntPtr< llvm::vfs::FileSystem > & getFileSystem() const
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
CharUnits getNaturalTypeAlignment(QualType T, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, bool forPointeeType=false)
CodeGenTypes & getTypes()
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
TBAAAccessInfo getTBAAInfoForSubobject(LValue Base, QualType AccessType)
getTBAAInfoForSubobject - Get TBAA information for an access with a given base lvalue.
ASTContext & getContext() const
const CodeGenOptions & getCodeGenOpts() const
StringRef getMangledName(GlobalDecl GD)
std::optional< CharUnits > getOMPAllocateAlignment(const VarDecl *VD)
Return the alignment specified in an allocate directive, if present.
llvm::Constant * EmitNullConstant(QualType T)
Return the result of value-initializing the given type, i.e.
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
const CGRecordLayout & getCGRecordLayout(const RecordDecl *)
getCGRecordLayout - Return record layout info for the given record decl.
A specialization of Address that requires the address to be an LLVM Constant.
static ConstantAddress invalid()
bool requiresLandingPad() const
void pushTerminate()
Push a terminate handler on the stack.
void popTerminate()
Pops a terminate handler off the stack.
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
CharUnits getAlignment() const
llvm::Value * getPointer(CodeGenFunction &CGF) const
const Qualifiers & getQuals() const
Address getAddress() const
LValueBaseInfo getBaseInfo() const
TBAAAccessInfo getTBAAInfo() const
A basic class for pre|post-action for advanced codegen sequence for OpenMP region.
virtual void Enter(CodeGenFunction &CGF)
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
static RValue getComplex(llvm::Value *V1, llvm::Value *V2)
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
An abstract representation of an aligned address.
llvm::Type * getElementType() const
Return the type of the values stored in this address.
llvm::Value * getPointer() const
static RawAddress invalid()
Class intended to support codegen of all kind of the reduction clauses.
LValue getSharedLValue(unsigned N) const
Returns LValue for the reduction item.
const Expr * getRefExpr(unsigned N) const
Returns the base declaration of the reduction item.
LValue getOrigLValue(unsigned N) const
Returns LValue for the original reduction item.
bool needCleanups(unsigned N)
Returns true if the private copy requires cleanups.
void emitAggregateType(CodeGenFunction &CGF, unsigned N)
Emits the code for the variable-modified type, if required.
const VarDecl * getBaseDecl(unsigned N) const
Returns the base declaration of the reduction item.
QualType getPrivateType(unsigned N) const
Return the type of the private item.
bool usesReductionInitializer(unsigned N) const
Returns true if the initialization of the reduction item uses initializer from declare reduction cons...
void emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N)
Emits lvalue for the shared and original reduction item.
void emitInitialization(CodeGenFunction &CGF, unsigned N, Address PrivateAddr, Address SharedAddr, llvm::function_ref< bool(CodeGenFunction &)> DefaultInit)
Performs initialization of the private copy for the reduction item.
std::pair< llvm::Value *, llvm::Value * > getSizes(unsigned N) const
Returns the size of the reduction item (in chars and total number of elements in the item),...
ReductionCodeGen(ArrayRef< const Expr * > Shareds, ArrayRef< const Expr * > Origs, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > ReductionOps)
void emitCleanups(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Emits cleanup code for the reduction item.
Address adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Adjusts PrivatedAddr for using instead of the original variable address in normal operations.
Class provides a way to call simple version of codegen for OpenMP region, or an advanced with possibl...
void operator()(CodeGenFunction &CGF) const
void setAction(PrePostActionTy &Action) const
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
void addDecl(Decl *D)
Add the declaration D into this context.
A reference to a declared variable, function, enum, etc.
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
SourceLocation getLocation() const
DeclContext * getDeclContext()
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
This represents one expression.
bool isIntegerConstantExpr(const ASTContext &Ctx) const
Expr * IgnoreParenNoopCasts(const ASTContext &Ctx) LLVM_READONLY
Skip past any parentheses and casts which do not change the value (including ptr->int casts of the sa...
@ SE_AllowSideEffects
Allow any unmodeled side effect.
@ SE_AllowUndefinedBehavior
Allow UB that we can give a value, but not arbitrary unmodeled side effects.
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsBooleanCondition - Return true if this is a constant which we can fold and convert to a boo...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
static bool isSameComparisonOperand(const Expr *E1, const Expr *E2)
Checks that the two Expr's will refer to the same value as a comparison operand.
bool hasNonTrivialCall(const ASTContext &Ctx) const
Determine whether this expression involves a call to any function that is not trivial.
Represents a member of a struct/union/class.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
FunctionDecl * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
FunctionDecl * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
GlobalDecl - represents a global declaration.
const Decl * getDecl() const
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
bool isExternallyVisible() const
This represents clause 'affinity' in the 'pragma omp task'-based directives.
Expr * getAssociatedExpression() const
ValueDecl * getAssociatedDeclaration() const
ArrayRef< MappableComponent > MappableExprComponentListRef
static std::pair< const Expr *, std::optional< size_t > > findAttachPtrExpr(MappableExprComponentListRef Components, OpenMPDirectiveKind CurDirKind)
Find the attach pointer expression from a list of mappable expression components.
static QualType getComponentExprElementType(const Expr *Exp)
Get the type of an element of a ComponentList Expr Exp.
const Stmt * getPreInitStmt() const
Get pre-initialization statement for the clause.
This is a basic class for representing single OpenMP clause.
This represents 'pragma omp declare mapper ...' directive.
Expr * getMapperVarRef()
Get the variable declared in the mapper.
This represents 'pragma omp declare reduction ...' directive.
Expr * getInitializer()
Get initializer expression (if specified) of the declare reduction construct.
Expr * getInitPriv()
Get Priv variable of the initializer.
Expr * getCombinerOut()
Get Out variable of the combiner.
Expr * getCombinerIn()
Get In variable of the combiner.
Expr * getCombiner()
Get combiner expression of the declare reduction construct.
Expr * getInitOrig()
Get Orig variable of the initializer.
OMPDeclareReductionInitKind getInitializerKind() const
Get initializer kind.
This represents implicit clause 'depend' for the 'pragma omp task' directive.
This represents 'detach' clause in the 'pragma omp task' directive.
This represents 'device' clause in the 'pragma omp ...' directive.
This represents the 'doacross' clause for the 'pragma omp ordered' directive.
This represents 'dyn_groupprivate' clause in 'pragma omp target ...' and 'pragma omp teams ....
This represents 'if' clause in the 'pragma omp ...' directive.
Expr * getCondition() const
Returns condition.
This represents clause 'in_reduction' in the 'pragma omp task' directives.
OMPIteratorHelperData & getHelper(unsigned I)
Fetches helper data for the specified iteration space.
unsigned numOfIterators() const
Returns number of iterator definitions.
This represents clause 'lastprivate' in the 'pragma omp ...' directives.
This represents clause 'nontemporal' in the 'pragma omp ...' directives.
This represents 'nowait' clause in the 'pragma omp ...' directive.
This represents 'num_teams' clause in the 'pragma omp ...' directive.
This represents 'num_threads' clause in the 'pragma omp ...' directive.
This represents 'ordered' clause in the 'pragma omp ...' directive.
This represents clause 'private' in the 'pragma omp ...' directives.
This represents 'pragma omp requires...' directive.
clauselist_range clauselists()
This represents 'thread_limit' clause in the 'pragma omp ...' directive.
This represents 'threadset' clause in the 'pragma omp task ...' directive.
This represents clause 'uses_allocators' in the 'pragma omp target'-based directives.
This represents 'ompx_attribute' clause in a directive that might generate an outlined function.
This represents 'ompx_bare' clause in the 'pragma omp target teams ...' directive.
This represents 'ompx_dyn_cgroup_mem' clause in the 'pragma omp target ...' directive.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Represents a parameter to a function.
PointerType - C99 6.7.5.1 - Pointer Declarators.
Represents an unpacked "presumed" location which can be presented to the user.
unsigned getColumn() const
Return the presumed column number of this location.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
A (possibly-)qualified type.
void addRestrict()
Add the restrict qualifier to this QualType.
QualType withRestrict() const
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
QualType getCanonicalType() const
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
Represents a struct/union/class.
field_iterator field_end() const
field_range fields() const
virtual void completeDefinition()
Note that the definition of this type is now complete.
field_iterator field_begin() const
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
static SourceLocation getFromRawEncoding(UIntTy Encoding)
Turn a raw encoding of a SourceLocation object into a real SourceLocation.
bool isValid() const
Return true if this is a valid SourceLocation object.
UIntTy getRawEncoding() const
When a SourceLocation itself cannot be used, this returns an (opaque) 32-bit integer encoding for it.
This class handles loading and caching of source files into memory.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
Stmt - This represents one statement.
StmtClass getStmtClass() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
SourceLocation getBeginLoc() const LLVM_READONLY
void startDefinition()
Starts the definition of this tag declaration.
The base class of the type hierarchy.
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isPointerType() const
CanQualType getCanonicalTypeUnqualified() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isLValueReferenceType() const
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
RecordDecl * castAsRecordDecl() const
QualType getCanonicalTypeInternal() const
const Type * getBaseElementTypeUnsafe() const
Get the base element type of this type, potentially discarding type qualifiers.
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
bool isFloatingType() const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
bool isAnyPointerType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isRecordType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
VarDecl * getDefinition(ASTContext &)
Get the real (not just tentative) definition for this declaration.
const Expr * getInit() const
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
@ DeclarationOnly
This declaration is only a declaration.
DefinitionKind hasDefinition(ASTContext &) const
Check whether this variable is defined in this translation unit.
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Represents a C array with a specified size that is not an integer-constant-expression.
Expr * getSizeExpr() const
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
bool isEmptyRecordForLayout(const ASTContext &Context, QualType T)
isEmptyRecordForLayout - Return true iff a structure contains only empty base classes (per isEmptyRec...
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
bool isEmptyFieldForLayout(const ASTContext &Context, const FieldDecl *FD)
isEmptyFieldForLayout - Return true iff the field is "empty", that is, either a zero-width bit-field ...
ComparisonResult
Indicates the result of a tentative comparison.
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool needsTaskBasedThreadLimit(OpenMPDirectiveKind DKind)
Checks if the specified target directive, combined or not, needs task based thread_limit.
@ Ctor_Complete
Complete object ctor.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
@ Conditional
A conditional (?:) operator.
@ ICIS_NoInit
No in-class initializer.
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE()
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
@ Vector
'vector' clause, allowed on 'loop', Combined, and 'routine' directives.
@ Reduction
'reduction' clause, allowed on Parallel, Serial, Loop, and the combined constructs.
@ Present
'present' clause, allowed on Compute and Combined constructs, plus 'data' and 'declare'.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_last
@ OMPC_SCHEDULE_MODIFIER_unknown
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
static bool classof(const Stmt *T)
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
@ OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
const FunctionProtoType * T
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
@ Dtor_Complete
Complete object dtor.
@ Union
The "union" keyword.
bool isOpenMPTargetMapEnteringDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a map-entering target directive.
@ Type
The name was classified as a type.
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
LangAS
Defines the address space values used by the address space qualifier of QualType.
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
for(const auto &A :T->param_types())
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPNumThreadsClauseModifier
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
U cast(CodeGen::Address addr)
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
@ OMPC_MAP_MODIFIER_unknown
@ Other
Other implicit parameter.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
OpenMPThreadsetKind
OpenMP modifiers for 'threadset' clause.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Diagnostic wrappers for TextAPI types for error reporting.
Maps the expression for the lastprivate variable to the global copy used to store new value because o...
llvm::SmallVector< bool, 8 > IsPrivateVarReduction
A jump destination is an abstract label, branching to which may require a jump out through normal cle...
llvm::BasicBlock * getBlock() const
unsigned NumberOfTargetItems
Address BasePointersArray
llvm::PointerType * VoidPtrTy
llvm::IntegerType * Int64Ty
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::CallingConv::ID getRuntimeCC() const
llvm::IntegerType * SizeTy
llvm::PointerType * VoidPtrPtrTy
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntPtrTy
llvm::IntegerType * IntTy
int
CharUnits getPointerAlign() const
OpenMPDependClauseKind DepKind
const Expr * IteratorExpr
SmallVector< const Expr *, 4 > DepExprs
EvalResult is a struct with detailed info about an evaluated expression.
Extra information about a function prototype.
Expr * CounterUpdate
Updater for the internal counter: ++CounterVD;.
Data for list of allocators.
Expr * AllocatorTraits
Allocator traits.
Expr * Allocator
Allocator.
Scheduling data for loop-based OpenMP directives.
OpenMPScheduleClauseModifier M2
OpenMPScheduleClauseModifier M1
OpenMPScheduleClauseKind Schedule
Describes how types, statements, expressions, and declarations should be printed.