31#include "llvm/ADT/SmallSet.h"
32#include "llvm/BinaryFormat/Dwarf.h"
33#include "llvm/Frontend/OpenMP/OMPConstants.h"
34#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
35#include "llvm/IR/Constants.h"
36#include "llvm/IR/DebugInfoMetadata.h"
37#include "llvm/IR/Instructions.h"
38#include "llvm/IR/IntrinsicInst.h"
39#include "llvm/IR/Metadata.h"
40#include "llvm/Support/AtomicOrdering.h"
41#include "llvm/Support/Debug.h"
45using namespace llvm::omp;
47#define TTL_CODEGEN_TYPE "target-teams-loop-codegen"
63 S.hasClausesOfKind<OMPReductionClause>() &&
65 !S.getSingleClause<OMPScheduleClause>() &&
66 !S.getSingleClause<OMPOrderedClause>();
73 void emitPreInitStmt(CodeGenFunction &CGF,
const OMPExecutableDirective &S) {
74 for (
const auto *
C : S.clauses()) {
75 if (
const auto *CPI = OMPClauseWithPreInit::get(
C)) {
76 if (
const auto *PreInit =
77 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
78 for (
const auto *I : PreInit->decls()) {
79 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
82 CodeGenFunction::AutoVarEmission Emission =
91 CodeGenFunction::OMPPrivateScope InlinedShareds;
93 static bool isCapturedVar(CodeGenFunction &CGF,
const VarDecl *VD) {
102 CodeGenFunction &CGF,
const OMPExecutableDirective &S,
103 const std::optional<OpenMPDirectiveKind> CapturedRegion = std::nullopt,
104 const bool EmitPreInitStmt =
true)
106 InlinedShareds(CGF) {
108 emitPreInitStmt(CGF, S);
111 assert(S.hasAssociatedStmt() &&
112 "Expected associated statement for inlined directive.");
113 const CapturedStmt *CS = S.getCapturedStmt(*CapturedRegion);
115 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
116 auto *VD =
C.getCapturedVar();
118 "Canonical decl must be captured.");
122 InlinedShareds.isGlobalVarCaptured(VD)),
127 (void)InlinedShareds.Privatize();
133class OMPParallelScope final :
public OMPLexicalScope {
134 bool EmitPreInitStmt(
const OMPExecutableDirective &S) {
142 OMPParallelScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
143 : OMPLexicalScope(CGF, S, std::nullopt,
144 EmitPreInitStmt(S)) {}
149class OMPTeamsScope final :
public OMPLexicalScope {
150 bool EmitPreInitStmt(
const OMPExecutableDirective &S) {
157 OMPTeamsScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
158 : OMPLexicalScope(CGF, S, std::nullopt,
159 EmitPreInitStmt(S)) {}
165 void emitPreInitStmt(CodeGenFunction &CGF,
const OMPLoopBasedDirective &S) {
166 const Stmt *PreInits;
167 CodeGenFunction::OMPMapVars PreCondVars;
168 if (
auto *LD = dyn_cast<OMPLoopDirective>(&S)) {
170 (void)OMPLoopBasedDirective::doForAllLoops(
171 LD->getInnermostCapturedStmt()->getCapturedStmt(),
172 true, LD->getLoopsNumber(),
173 [&CGF](
unsigned Cnt,
const Stmt *CurStmt) {
174 if (const auto *CXXFor = dyn_cast<CXXForRangeStmt>(CurStmt)) {
175 if (const Stmt *Init = CXXFor->getInit())
177 CGF.EmitStmt(CXXFor->getRangeStmt());
178 CGF.EmitStmt(CXXFor->getBeginStmt());
179 CGF.EmitStmt(CXXFor->getEndStmt());
183 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
184 for (
const auto *E : LD->counters()) {
191 for (
const auto *
C : LD->getClausesOfKind<OMPPrivateClause>()) {
192 for (
const Expr *IRef :
C->varlist()) {
195 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
196 QualType OrigVDTy = OrigVD->getType().getNonReferenceType();
206 (void)PreCondVars.
apply(CGF);
207 PreInits = LD->getPreInits();
208 }
else if (
const auto *
Tile = dyn_cast<OMPTileDirective>(&S)) {
209 PreInits =
Tile->getPreInits();
210 }
else if (
const auto *Stripe = dyn_cast<OMPStripeDirective>(&S)) {
211 PreInits = Stripe->getPreInits();
212 }
else if (
const auto *Unroll = dyn_cast<OMPUnrollDirective>(&S)) {
213 PreInits = Unroll->getPreInits();
214 }
else if (
const auto *Reverse = dyn_cast<OMPReverseDirective>(&S)) {
215 PreInits = Reverse->getPreInits();
216 }
else if (
const auto *Split = dyn_cast<OMPSplitDirective>(&S)) {
217 PreInits =
Split->getPreInits();
218 }
else if (
const auto *Interchange =
219 dyn_cast<OMPInterchangeDirective>(&S)) {
220 PreInits = Interchange->getPreInits();
222 llvm_unreachable(
"Unknown loop-based directive kind.");
224 doEmitPreinits(PreInits);
231 const Stmt *PreInits;
232 if (
const auto *Fuse = dyn_cast<OMPFuseDirective>(&S)) {
233 PreInits = Fuse->getPreInits();
236 "Unknown canonical loop sequence transform directive kind.");
238 doEmitPreinits(PreInits);
241 void doEmitPreinits(
const Stmt *PreInits) {
247 if (
auto *PreInitCompound = dyn_cast<CompoundStmt>(PreInits))
248 llvm::append_range(PreInitStmts, PreInitCompound->body());
250 PreInitStmts.push_back(PreInits);
252 for (
const Stmt *S : PreInitStmts) {
255 if (
auto *PreInitDecl = dyn_cast<DeclStmt>(S)) {
256 for (
Decl *I : PreInitDecl->decls())
268 emitPreInitStmt(CGF, S);
273 emitPreInitStmt(CGF, S);
278 CodeGenFunction::OMPPrivateScope InlinedShareds;
280 static bool isCapturedVar(CodeGenFunction &CGF,
const VarDecl *VD) {
288 OMPSimdLexicalScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
290 InlinedShareds(CGF) {
291 for (
const auto *
C : S.clauses()) {
292 if (const auto *CPI = OMPClauseWithPreInit::get(C)) {
293 if (const auto *PreInit =
294 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
295 for (const auto *I : PreInit->decls()) {
296 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
297 CGF.EmitVarDecl(cast<VarDecl>(*I));
299 CodeGenFunction::AutoVarEmission Emission =
300 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
301 CGF.EmitAutoVarCleanups(Emission);
305 }
else if (
const auto *UDP = dyn_cast<OMPUseDevicePtrClause>(
C)) {
306 for (
const Expr *E : UDP->varlist()) {
308 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
311 }
else if (
const auto *UDP = dyn_cast<OMPUseDeviceAddrClause>(
C)) {
312 for (
const Expr *E : UDP->varlist()) {
314 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
321 if (
const auto *TG = dyn_cast<OMPTaskgroupDirective>(&S)) {
322 if (
const Expr *E = TG->getReductionRef())
327 llvm::DenseSet<CanonicalDeclPtr<const Decl>> CopyArrayTemps;
328 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
329 if (C->getModifier() != OMPC_REDUCTION_inscan)
331 for (const Expr *E : C->copy_array_temps())
332 CopyArrayTemps.insert(cast<DeclRefExpr>(E)->getDecl());
334 const auto *CS = cast_or_null<CapturedStmt>(S.getAssociatedStmt());
337 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
338 auto *VD =
C.getCapturedVar();
339 if (CopyArrayTemps.contains(VD))
342 "Canonical decl must be captured.");
343 DeclRefExpr DRE(CGF.
getContext(),
const_cast<VarDecl *
>(VD),
344 isCapturedVar(CGF, VD) ||
346 InlinedShareds.isGlobalVarCaptured(VD)),
354 (void)InlinedShareds.Privatize();
365 if (Kind != OMPD_loop)
370 BindKind =
C->getBindKind();
373 case OMPC_BIND_parallel:
375 case OMPC_BIND_teams:
376 return OMPD_distribute;
377 case OMPC_BIND_thread:
389 if (
const auto *OrigDRE = dyn_cast<DeclRefExpr>(E)) {
390 if (
const auto *OrigVD = dyn_cast<VarDecl>(OrigDRE->getDecl())) {
391 OrigVD = OrigVD->getCanonicalDecl();
397 OrigDRE->getType(),
VK_LValue, OrigDRE->getExprLoc());
406 llvm::Value *Size =
nullptr;
407 auto SizeInChars =
C.getTypeSizeInChars(Ty);
408 if (SizeInChars.isZero()) {
416 SizeInChars =
C.getTypeSizeInChars(Ty);
417 if (SizeInChars.isZero())
418 return llvm::ConstantInt::get(
SizeTy, 0);
419 return Builder.CreateNUWMul(Size,
CGM.getSize(SizeInChars));
421 return CGM.getSize(SizeInChars);
431 I != E; ++I, ++CurField, ++CurCap) {
432 if (CurField->hasCapturedVLAType()) {
435 CapturedVars.push_back(Val);
436 }
else if (CurCap->capturesThis()) {
437 CapturedVars.push_back(CXXThisValue);
438 }
else if (CurCap->capturesVariableByCopy()) {
443 if (!CurField->getType()->isAnyPointerType()) {
447 Twine(CurCap->getCapturedVar()->getName(),
".casted"));
463 CapturedVars.push_back(CV);
465 assert(CurCap->capturesVariable() &&
"Expected capture by reference.");
486 if (
T->isLValueReferenceType())
487 return C.getLValueReferenceType(
490 if (
T->isPointerType())
492 if (
const ArrayType *A =
T->getAsArrayTypeUnsafe()) {
493 if (
const auto *VLA = dyn_cast<VariableArrayType>(A))
495 if (!A->isVariablyModifiedType())
496 return C.getCanonicalType(
T);
498 return C.getCanonicalParamType(
T);
503struct FunctionOptions {
505 const CapturedStmt *S =
nullptr;
508 const bool UIntPtrCastRequired =
true;
511 const bool RegisterCastedArgsOnly =
false;
513 const StringRef FunctionName;
516 const bool IsDeviceKernel =
false;
517 explicit FunctionOptions(
const CapturedStmt *S,
bool UIntPtrCastRequired,
518 bool RegisterCastedArgsOnly, StringRef FunctionName,
519 SourceLocation Loc,
bool IsDeviceKernel)
520 : S(S), UIntPtrCastRequired(UIntPtrCastRequired),
521 RegisterCastedArgsOnly(UIntPtrCastRequired && RegisterCastedArgsOnly),
522 FunctionName(FunctionName), Loc(Loc), IsDeviceKernel(IsDeviceKernel) {}
528 llvm::MapVector<
const Decl *, std::pair<const VarDecl *, Address>>
530 llvm::DenseMap<
const Decl *, std::pair<const Expr *, llvm::Value *>>
532 llvm::Value *&CXXThisValue,
const FunctionOptions &FO) {
535 assert(CD->
hasBody() &&
"missing CapturedDecl body");
537 CXXThisValue =
nullptr;
549 if (!FO.UIntPtrCastRequired) {
569 if (FO.UIntPtrCastRequired &&
570 ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) ||
571 I->capturesVariableArrayType()))
574 if (I->capturesVariable() || I->capturesVariableByCopy()) {
575 CapVar = I->getCapturedVar();
577 }
else if (I->capturesThis()) {
580 assert(I->capturesVariableArrayType());
583 if (ArgType->isVariablyModifiedType())
590 }
else if (DebugFunctionDecl && (CapVar || I->capturesThis())) {
592 Ctx, DebugFunctionDecl,
593 CapVar ? CapVar->
getBeginLoc() : FD->getBeginLoc(),
594 CapVar ? CapVar->
getLocation() : FD->getLocation(), II, ArgType,
600 Args.emplace_back(Arg);
602 TargetArgs.emplace_back(
603 FO.UIntPtrCastRequired
624 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
630 if (CGM.
getTriple().isSPIRV() && !FO.IsDeviceKernel)
631 F->setCallingConv(llvm::CallingConv::SPIR_FUNC);
634 F->setDoesNotThrow();
638 F->removeFnAttr(llvm::Attribute::NoInline);
639 F->addFnAttr(llvm::Attribute::AlwaysInline);
642 F->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
646 FO.UIntPtrCastRequired ? FO.Loc : FO.S->
getBeginLoc(),
647 FO.UIntPtrCastRequired ? FO.Loc
654 if (!FO.UIntPtrCastRequired && Args[Cnt] != TargetArgs[Cnt]) {
662 if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
663 const VarDecl *CurVD = I->getCapturedVar();
664 if (!FO.RegisterCastedArgsOnly)
665 LocalAddrs.insert({Args[Cnt], {CurVD, LocalAddr}});
673 if (FD->hasCapturedVLAType()) {
674 if (FO.UIntPtrCastRequired) {
677 Args[Cnt]->getName(), ArgLVal),
682 VLASizes.try_emplace(Args[Cnt], VAT->
getSizeExpr(), ExprArg);
683 }
else if (I->capturesVariable()) {
684 const VarDecl *Var = I->getCapturedVar();
686 Address ArgAddr = ArgLVal.getAddress();
687 if (ArgLVal.getType()->isLValueReferenceType()) {
690 assert(ArgLVal.getType()->isPointerType());
692 ArgAddr, ArgLVal.getType()->castAs<
PointerType>());
694 if (!FO.RegisterCastedArgsOnly) {
698 }
else if (I->capturesVariableByCopy()) {
699 assert(!FD->getType()->isAnyPointerType() &&
700 "Not expecting a captured pointer.");
701 const VarDecl *Var = I->getCapturedVar();
702 LocalAddrs.insert({Args[Cnt],
703 {Var, FO.UIntPtrCastRequired
705 CGF, I->getLocation(), FD->getType(),
706 Args[Cnt]->getName(), ArgLVal)
707 : ArgLVal.getAddress()}});
710 assert(I->capturesThis());
712 LocalAddrs.insert({Args[Cnt], {
nullptr, ArgLVal.getAddress()}});
723 llvm::MapVector<
const Decl *, std::pair<const VarDecl *, Address>>
725 llvm::DenseMap<
const Decl *, std::pair<const Expr *, llvm::Value *>>
727 llvm::Value *&CXXThisValue, llvm::Value *&ContextV,
const CapturedStmt &CS,
732 CXXThisValue =
nullptr;
742 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
746 F->setDoesNotThrow();
753 llvm::Type *PtrTy = CGF.
Builder.getPtrTy();
754 llvm::Align PtrAlign = CGM.
getDataLayout().getPointerABIAlignment(0);
757 for (
auto [FD,
C, FieldIdx] :
760 llvm::Value *SlotPtr =
761 CGF.
Builder.CreateConstInBoundsGEP1_32(PtrTy, ContextV, FieldIdx);
767 if (
C.capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
768 const VarDecl *CurVD =
C.getCapturedVar();
769 Slot->setName(CurVD->
getName());
770 Address SlotAddr(Slot, PtrTy, SlotAlign);
771 LocalAddrs.insert({FD, {CurVD, SlotAddr}});
772 }
else if (FD->hasCapturedVLAType()) {
779 VLASizes.try_emplace(FD, VAT->
getSizeExpr(), ExprArg);
780 }
else if (
C.capturesVariable()) {
781 const VarDecl *Var =
C.getCapturedVar();
785 Slot->setName(Var->
getName() +
".addr");
786 Address SlotAddr(Slot, PtrTy, SlotAlign);
787 LocalAddrs.insert({FD, {Var, SlotAddr}});
790 PtrTy, Slot, PtrAlign, Var->
getName());
791 LocalAddrs.insert({FD,
795 }
else if (
C.capturesVariableByCopy()) {
796 assert(!FD->getType()->isAnyPointerType() &&
797 "Not expecting a captured pointer.");
798 const VarDecl *Var =
C.getCapturedVar();
813 LocalAddrs.insert({FD, {Var, CopyAddr}});
815 assert(
C.capturesThis() &&
"Default case expected to be CXX 'this'");
818 Address SlotAddr(Slot, PtrTy, SlotAlign);
819 LocalAddrs.insert({FD, {
nullptr, SlotAddr}});
831 "CapturedStmtInfo should be set when generating the captured function");
834 bool NeedWrapperFunction =
837 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs,
839 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes,
842 llvm::raw_svector_ostream Out(Buffer);
845 bool IsDeviceKernel =
CGM.getOpenMPRuntime().isGPU() &&
847 D.getCapturedStmt(OMPD_target) == &S;
848 CodeGenFunction WrapperCGF(
CGM,
true);
849 llvm::Function *WrapperF =
nullptr;
850 if (NeedWrapperFunction) {
853 FunctionOptions WrapperFO(&S,
true,
860 WrapperCGF.CXXThisValue, WrapperFO);
863 FunctionOptions FO(&S, !NeedWrapperFunction,
false,
864 Out.str(), Loc, !NeedWrapperFunction && IsDeviceKernel);
866 *
this, WrapperArgs, WrapperLocalAddrs, WrapperVLASizes, CXXThisValue, FO);
868 for (
const auto &LocalAddrPair : WrapperLocalAddrs) {
869 if (LocalAddrPair.second.first) {
870 LocalScope.addPrivate(LocalAddrPair.second.first,
871 LocalAddrPair.second.second);
874 (void)LocalScope.Privatize();
875 for (
const auto &VLASizePair : WrapperVLASizes)
876 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
879 LocalScope.ForceCleanup();
881 if (!NeedWrapperFunction)
885 WrapperF->removeFromParent();
886 F->getParent()->getFunctionList().insertAfter(F->getIterator(), WrapperF);
889 auto *PI = F->arg_begin();
890 for (
const auto *Arg : Args) {
892 auto I = LocalAddrs.find(Arg);
893 if (I != LocalAddrs.end()) {
896 I->second.first ? I->second.first->getType() : Arg->getType(),
902 auto EI = VLASizes.find(Arg);
903 if (EI != VLASizes.end()) {
915 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
925 "CapturedStmtInfo should be set when generating the captured function");
929 bool NeedWrapperFunction =
932 CodeGenFunction WrapperCGF(
CGM,
true);
933 llvm::Function *WrapperF =
nullptr;
934 llvm::Value *WrapperContextV =
nullptr;
935 if (NeedWrapperFunction) {
938 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>>
940 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>>
943 WrapperCGF, WrapperArgs, WrapperLocalAddrs, WrapperVLASizes,
944 WrapperCGF.CXXThisValue, WrapperContextV, S, Loc, FunctionName);
948 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs;
949 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes;
952 if (NeedWrapperFunction) {
954 llvm::raw_svector_ostream Out(Buffer);
955 Out << FunctionName <<
"_debug__";
957 FunctionOptions FO(&S,
false,
958 false, Out.str(), Loc,
963 llvm::Value *ContextV =
nullptr;
965 CXXThisValue, ContextV, S, Loc,
974 llvm::Align PtrAlign =
CGM.getDataLayout().getPointerABIAlignment(0);
975 llvm::Value *SlotPtr =
Builder.CreateConstInBoundsGEP1_32(
976 Builder.getPtrTy(), ContextV, FieldIdx,
977 Twine(Param->getName()) +
".addr");
978 llvm::Value *ParamAddr =
980 llvm::Value *ParamVal =
Builder.CreateAlignedLoad(
981 Builder.getPtrTy(), ParamAddr, PtrAlign, Param->getName());
984 Builder.CreateStore(ParamVal, ParamLocalAddr);
985 LocalAddrs.insert({Param, {Param, ParamLocalAddr}});
991 for (
const auto &LocalAddrPair : LocalAddrs) {
992 if (LocalAddrPair.second.first)
993 LocalScope.addPrivate(LocalAddrPair.second.first,
994 LocalAddrPair.second.second);
996 (void)LocalScope.Privatize();
997 for (
const auto &VLASizePair : VLASizes)
998 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
1001 (void)LocalScope.ForceCleanup();
1004 if (!NeedWrapperFunction)
1008 WrapperF->removeFromParent();
1009 F->getParent()->getFunctionList().insertAfter(F->getIterator(), WrapperF);
1011 llvm::Align PtrAlign =
CGM.getDataLayout().getPointerABIAlignment(0);
1014 "Expected context param at position 0 for target regions");
1015 assert(RD->
getNumFields() + 1 == F->getNumOperands() &&
1016 "Argument count mismatch");
1018 for (
auto [FD, InnerParam, SlotIdx] : llvm::zip(
1020 llvm::Value *SlotPtr = WrapperCGF.
Builder.CreateConstInBoundsGEP1_32(
1021 WrapperCGF.
Builder.getPtrTy(), WrapperContextV, SlotIdx);
1023 WrapperCGF.
Builder.getPtrTy(), SlotPtr, PtrAlign);
1025 InnerParam.getType(), Slot, PtrAlign, InnerParam.getName());
1026 CallArgs.push_back(Val);
1031 auto InnerParam = F->arg_begin() + SlotIdx;
1032 llvm::Value *SlotPtr = WrapperCGF.
Builder.CreateConstInBoundsGEP1_32(
1033 WrapperCGF.
Builder.getPtrTy(), WrapperContextV, SlotIdx);
1035 WrapperCGF.
Builder.getPtrTy(), SlotPtr, PtrAlign);
1037 InnerParam->getType(), Slot, PtrAlign, InnerParam->getName());
1038 CallArgs.push_back(Val);
1040 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
1056 llvm::Value *NumElements =
emitArrayLength(ArrayTy, ElementTy, DestAddr);
1063 DestBegin, NumElements);
1068 llvm::Value *IsEmpty =
1069 Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arraycpy.isempty");
1070 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
1073 llvm::BasicBlock *EntryBB =
Builder.GetInsertBlock();
1078 llvm::PHINode *SrcElementPHI =
1079 Builder.CreatePHI(SrcBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
1080 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
1085 llvm::PHINode *DestElementPHI =
Builder.CreatePHI(
1086 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
1087 DestElementPHI->addIncoming(DestBegin, EntryBB);
1093 CopyGen(DestElementCurrent, SrcElementCurrent);
1096 llvm::Value *DestElementNext =
1098 1,
"omp.arraycpy.dest.element");
1099 llvm::Value *SrcElementNext =
1101 1,
"omp.arraycpy.src.element");
1104 Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
1105 Builder.CreateCondBr(Done, DoneBB, BodyBB);
1106 DestElementPHI->addIncoming(DestElementNext,
Builder.GetInsertBlock());
1107 SrcElementPHI->addIncoming(SrcElementNext,
Builder.GetInsertBlock());
1117 const auto *BO = dyn_cast<BinaryOperator>(
Copy);
1118 if (BO && BO->getOpcode() == BO_Assign) {
1127 DestAddr, SrcAddr, OriginalType,
1155 bool DeviceConstTarget =
getLangOpts().OpenMPIsTargetDevice &&
1157 bool FirstprivateIsLastprivate =
false;
1158 llvm::DenseMap<const VarDecl *, OpenMPLastprivateModifier> Lastprivates;
1159 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1160 for (
const auto *D :
C->varlist())
1161 Lastprivates.try_emplace(
1165 llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
1170 bool MustEmitFirstprivateCopy =
1171 CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown;
1172 for (
const auto *
C : D.getClausesOfKind<OMPFirstprivateClause>()) {
1173 const auto *IRef =
C->varlist_begin();
1174 const auto *InitsRef =
C->inits().begin();
1175 for (
const Expr *IInit :
C->private_copies()) {
1177 bool ThisFirstprivateIsLastprivate =
1178 Lastprivates.count(OrigVD->getCanonicalDecl()) > 0;
1181 if (!MustEmitFirstprivateCopy && !ThisFirstprivateIsLastprivate && FD &&
1183 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
1184 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
1191 if (DeviceConstTarget && OrigVD->getType().isConstant(
getContext()) &&
1193 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
1194 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
1199 FirstprivateIsLastprivate =
1200 FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate;
1201 if (EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()).second) {
1202 const auto *VDInit =
1221 assert(!CE &&
"Expected non-constant firstprivate.");
1228 if (
Type->isArrayType()) {
1244 RunCleanupsScope InitScope(*this);
1246 setAddrOfLocalVar(VDInit, SrcElement);
1247 EmitAnyExprToMem(Init, DestElement,
1248 Init->getType().getQualifiers(),
1250 LocalDeclMap.erase(VDInit);
1261 setAddrOfLocalVar(VDInit, OriginalAddr);
1263 LocalDeclMap.erase(VDInit);
1265 if (ThisFirstprivateIsLastprivate &&
1266 Lastprivates[OrigVD->getCanonicalDecl()] ==
1267 OMPC_LASTPRIVATE_conditional) {
1272 (*IRef)->getExprLoc());
1273 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1277 LocalDeclMap.erase(VD);
1278 setAddrOfLocalVar(VD, VDAddr);
1280 IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1282 assert(IsRegistered &&
1283 "firstprivate var already registered as private");
1291 return FirstprivateIsLastprivate && !EmittedAsFirstprivate.empty();
1299 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
1300 for (
const auto *
C : D.getClausesOfKind<OMPPrivateClause>()) {
1301 auto IRef =
C->varlist_begin();
1302 for (
const Expr *IInit :
C->private_copies()) {
1304 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
1310 assert(IsRegistered &&
"private var already registered as private");
1326 llvm::DenseSet<const VarDecl *> CopiedVars;
1327 llvm::BasicBlock *CopyBegin =
nullptr, *CopyEnd =
nullptr;
1329 auto IRef =
C->varlist_begin();
1330 auto ISrcRef =
C->source_exprs().begin();
1331 auto IDestRef =
C->destination_exprs().begin();
1332 for (
const Expr *AssignOp :
C->assignment_ops()) {
1341 getContext().getTargetInfo().isTLSSupported()) {
1343 "Copyin threadprivates should have been captured!");
1347 LocalDeclMap.erase(VD);
1351 :
CGM.GetAddrOfGlobal(VD),
1352 CGM.getTypes().ConvertTypeForMem(VD->
getType()),
1357 if (CopiedVars.size() == 1) {
1363 auto *MasterAddrInt =
Builder.CreatePtrToInt(
1365 auto *PrivateAddrInt =
Builder.CreatePtrToInt(
1368 Builder.CreateICmpNE(MasterAddrInt, PrivateAddrInt), CopyBegin,
1374 const auto *DestVD =
1395 bool HasAtLeastOneLastprivate =
false;
1397 llvm::DenseSet<const VarDecl *> SIMDLCVs;
1400 for (
const Expr *
C : LoopDirective->counters()) {
1405 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1406 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1407 HasAtLeastOneLastprivate =
true;
1410 const auto *IRef =
C->varlist_begin();
1411 const auto *IDestRef =
C->destination_exprs().begin();
1412 for (
const Expr *IInit :
C->private_copies()) {
1418 if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) {
1419 const auto *DestVD =
1424 (*IRef)->getType(),
VK_LValue, (*IRef)->getExprLoc());
1429 if (IInit && !SIMDLCVs.count(OrigVD->getCanonicalDecl())) {
1432 if (
C->getKind() == OMPC_LASTPRIVATE_conditional) {
1433 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1435 setAddrOfLocalVar(VD, VDAddr);
1441 bool IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1442 assert(IsRegistered &&
1443 "lastprivate var already registered as private");
1451 return HasAtLeastOneLastprivate;
1456 llvm::Value *IsLastIterCond) {
1465 llvm::BasicBlock *ThenBB =
nullptr;
1466 llvm::BasicBlock *DoneBB =
nullptr;
1467 if (IsLastIterCond) {
1471 llvm::any_of(D.getClausesOfKind<OMPLastprivateClause>(),
1472 [](
const OMPLastprivateClause *
C) {
1473 return C->getKind() == OMPC_LASTPRIVATE_conditional;
1475 CGM.getOpenMPRuntime().emitBarrierCall(*
this, D.getBeginLoc(),
1482 Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB);
1485 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1486 llvm::DenseMap<const VarDecl *, const Expr *> LoopCountersAndUpdates;
1487 if (
const auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) {
1488 auto IC = LoopDirective->counters().begin();
1489 for (
const Expr *F : LoopDirective->finals()) {
1493 AlreadyEmittedVars.insert(D);
1495 LoopCountersAndUpdates[D] = F;
1499 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1500 auto IRef =
C->varlist_begin();
1501 auto ISrcRef =
C->source_exprs().begin();
1502 auto IDestRef =
C->destination_exprs().begin();
1503 for (
const Expr *AssignOp :
C->assignment_ops()) {
1504 const auto *PrivateVD =
1507 const auto *CanonicalVD = PrivateVD->getCanonicalDecl();
1508 if (AlreadyEmittedVars.insert(CanonicalVD).second) {
1512 if (
const Expr *FinalExpr = LoopCountersAndUpdates.lookup(CanonicalVD))
1516 const auto *DestVD =
1520 if (
const auto *RefTy = PrivateVD->getType()->getAs<
ReferenceType>())
1522 Builder.CreateLoad(PrivateAddr),
1523 CGM.getTypes().ConvertTypeForMem(RefTy->getPointeeType()),
1524 CGM.getNaturalTypeAlignment(RefTy->getPointeeType()));
1526 if (
C->getKind() == OMPC_LASTPRIVATE_conditional)
1527 CGM.getOpenMPRuntime().emitLastprivateConditionalFinalUpdate(
1529 (*IRef)->getExprLoc());
1532 EmitOMPCopy(
Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp);
1538 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
1558 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1559 if (ForInscan != (
C->getModifier() == OMPC_REDUCTION_inscan))
1561 Shareds.append(
C->varlist_begin(),
C->varlist_end());
1562 Privates.append(
C->privates().begin(),
C->privates().end());
1563 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1564 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1565 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1566 if (
C->getModifier() == OMPC_REDUCTION_task) {
1567 Data.ReductionVars.append(
C->privates().begin(),
C->privates().end());
1568 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
1569 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
1570 Data.ReductionOps.append(
C->reduction_ops().begin(),
1571 C->reduction_ops().end());
1572 TaskLHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1573 TaskRHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1578 auto *ILHS = LHSs.begin();
1579 auto *IRHS = RHSs.begin();
1581 for (
const Expr *IRef : Shareds) {
1589 [&Emission](CodeGenFunction &CGF) {
1590 CGF.EmitAutoVarInit(Emission);
1598 assert(IsRegistered &&
"private var already registered as private");
1606 if (isaOMPArraySectionExpr &&
Type->isVariablyModifiedType()) {
1611 }
else if ((isaOMPArraySectionExpr &&
Type->isScalarType()) ||
1629 PrivateScope.
addPrivate(LHSVD, OriginalAddr);
1640 if (!
Data.ReductionVars.empty()) {
1642 Data.IsReductionWithTaskMod =
true;
1644 llvm::Value *ReductionDesc =
CGM.getOpenMPRuntime().emitTaskReductionInit(
1645 *
this, D.getBeginLoc(), TaskLHSs, TaskRHSs,
Data);
1646 const Expr *TaskRedRef =
nullptr;
1657 case OMPD_parallel_for:
1660 case OMPD_parallel_master:
1664 case OMPD_parallel_sections:
1668 case OMPD_target_parallel:
1672 case OMPD_target_parallel_for:
1676 case OMPD_distribute_parallel_for:
1680 case OMPD_teams_distribute_parallel_for:
1682 .getTaskReductionRefExpr();
1684 case OMPD_target_teams_distribute_parallel_for:
1686 .getTaskReductionRefExpr();
1694 case OMPD_parallel_for_simd:
1696 case OMPD_taskyield:
1700 case OMPD_taskgroup:
1704 case OMPD_ordered_standalone:
1705 case OMPD_ordered_blockassoc:
1709 case OMPD_cancellation_point:
1711 case OMPD_target_data:
1712 case OMPD_target_enter_data:
1713 case OMPD_target_exit_data:
1715 case OMPD_taskloop_simd:
1716 case OMPD_master_taskloop:
1717 case OMPD_master_taskloop_simd:
1718 case OMPD_parallel_master_taskloop:
1719 case OMPD_parallel_master_taskloop_simd:
1720 case OMPD_distribute:
1721 case OMPD_target_update:
1722 case OMPD_distribute_parallel_for_simd:
1723 case OMPD_distribute_simd:
1724 case OMPD_target_parallel_for_simd:
1725 case OMPD_target_simd:
1726 case OMPD_teams_distribute:
1727 case OMPD_teams_distribute_simd:
1728 case OMPD_teams_distribute_parallel_for_simd:
1729 case OMPD_target_teams:
1730 case OMPD_target_teams_distribute:
1731 case OMPD_target_teams_distribute_parallel_for_simd:
1732 case OMPD_target_teams_distribute_simd:
1733 case OMPD_declare_target:
1734 case OMPD_end_declare_target:
1735 case OMPD_threadprivate:
1737 case OMPD_declare_reduction:
1738 case OMPD_declare_mapper:
1739 case OMPD_declare_simd:
1741 case OMPD_declare_variant:
1742 case OMPD_begin_declare_variant:
1743 case OMPD_end_declare_variant:
1746 llvm_unreachable(
"Unexpected directive with task reductions.");
1752 false, TaskRedRef->
getType());
1765 bool HasAtLeastOneReduction =
false;
1766 bool IsReductionWithTaskMod =
false;
1767 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1769 if (
C->getModifier() == OMPC_REDUCTION_inscan)
1771 HasAtLeastOneReduction =
true;
1772 Privates.append(
C->privates().begin(),
C->privates().end());
1773 LHSExprs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1774 RHSExprs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1775 IsPrivateVarReduction.append(
C->private_var_reduction_flags().begin(),
1776 C->private_var_reduction_flags().end());
1777 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1778 IsReductionWithTaskMod =
1779 IsReductionWithTaskMod ||
C->getModifier() == OMPC_REDUCTION_task;
1781 if (HasAtLeastOneReduction) {
1783 if (IsReductionWithTaskMod) {
1784 CGM.getOpenMPRuntime().emitTaskReductionFini(
1787 bool TeamsLoopCanBeParallel =
false;
1788 if (
auto *TTLD = dyn_cast<OMPTargetTeamsGenericLoopDirective>(&D))
1789 TeamsLoopCanBeParallel = TTLD->canBeParallelFor();
1790 bool WithNowait = D.getSingleClause<OMPNowaitClause>() ||
1792 TeamsLoopCanBeParallel || ReductionKind == OMPD_simd;
1793 bool SimpleReduction = ReductionKind == OMPD_simd;
1796 CGM.getOpenMPRuntime().emitReduction(
1797 *
this, D.getEndLoc(),
Privates, LHSExprs, RHSExprs, ReductionOps,
1798 {WithNowait, SimpleReduction, IsPrivateVarReduction, ReductionKind});
1807 llvm::BasicBlock *DoneBB =
nullptr;
1808 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1809 if (
const Expr *PostUpdate =
C->getPostUpdateExpr()) {
1811 if (llvm::Value *Cond = CondGen(CGF)) {
1816 CGF.
Builder.CreateCondBr(Cond, ThenBB, DoneBB);
1832 const OMPExecutableDirective &,
1833 llvm::SmallVectorImpl<llvm::Value *> &)>
1834 CodeGenBoundParametersTy;
1842 llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> PrivateDecls;
1843 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
1844 for (
const Expr *Ref :
C->varlist()) {
1845 if (!Ref->getType()->isScalarType())
1847 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1854 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
1855 for (
const Expr *Ref :
C->varlist()) {
1856 if (!Ref->getType()->isScalarType())
1858 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1865 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
1866 for (
const Expr *Ref :
C->varlist()) {
1867 if (!Ref->getType()->isScalarType())
1869 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1880 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
1881 for (
const Expr *Ref :
C->varlist()) {
1882 if (!Ref->getType()->isScalarType())
1884 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1891 CGF, S, PrivateDecls);
1897 const CodeGenBoundParametersTy &CodeGenBoundParameters) {
1898 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
1899 llvm::Value *NumThreads =
nullptr;
1908 llvm::Function *OutlinedFn =
1915 NumThreads = CGF.
EmitScalarExpr(NumThreadsClause->getNumThreads().front(),
1917 Modifier = NumThreadsClause->getPrescriptivenessModifier();
1918 if (
const auto *MessageClause = S.getSingleClause<OMPMessageClause>()) {
1919 Message = MessageClause->getMessageString();
1920 MessageLoc = MessageClause->getBeginLoc();
1922 if (
const auto *SeverityClause = S.getSingleClause<OMPSeverityClause>()) {
1923 Severity = SeverityClause->getSeverityKind();
1924 SeverityLoc = SeverityClause->getBeginLoc();
1927 CGF, NumThreads, NumThreadsClause->getBeginLoc(), Modifier, Severity,
1928 SeverityLoc, Message, MessageLoc);
1930 if (
const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>()) {
1933 CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getBeginLoc());
1935 const Expr *IfCond =
nullptr;
1936 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
1937 if (
C->getNameModifier() == OMPD_unknown ||
1938 C->getNameModifier() == OMPD_parallel) {
1939 IfCond =
C->getCondition();
1944 OMPParallelScope
Scope(CGF, S);
1950 CodeGenBoundParameters(CGF, S, CapturedVars);
1953 CapturedVars, IfCond, NumThreads,
1954 Modifier, Severity, Message);
1959 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
1961 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
1963 return !((AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc ||
1964 AA->getAllocatorType() == OMPAllocateDeclAttr::OMPNullMemAlloc) &&
1965 !AA->getAllocator());
1980 CGF, S.getBeginLoc(), OMPD_unknown,
false,
1986 CodeGenFunction &CGF,
const VarDecl *VD) {
1988 auto &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2000 Size = CGF.
Builder.CreateNUWAdd(
2002 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
2003 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
2009 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
2010 assert(AA->getAllocator() &&
2011 "Expected allocator expression for non-default allocator.");
2015 if (Allocator->getType()->isIntegerTy())
2016 Allocator = CGF.
Builder.CreateIntToPtr(Allocator,
CGM.VoidPtrTy);
2017 else if (Allocator->getType()->isPointerTy())
2021 llvm::Value *
Addr = OMPBuilder.createOMPAlloc(
2024 llvm::CallInst *FreeCI =
2025 OMPBuilder.createOMPFree(CGF.
Builder,
Addr, Allocator);
2039 if (
CGM.getLangOpts().OpenMPUseTLS &&
2040 CGM.getContext().getTargetInfo().isTLSSupported())
2043 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2048 llvm::ConstantInt *Size =
CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy));
2050 llvm::Twine CacheName = Twine(
CGM.getMangledName(VD)).concat(Suffix);
2052 llvm::CallInst *ThreadPrivateCacheCall =
2053 OMPBuilder.createCachedThreadPrivate(CGF.
Builder,
Data, Size, CacheName);
2061 llvm::raw_svector_ostream OS(Buffer);
2062 StringRef Sep = FirstSeparator;
2063 for (StringRef Part : Parts) {
2067 return OS.str().str();
2075 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
2076 "." + RegionName +
".after");
2092 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
2093 "." + RegionName +
".after");
2105 if (
CGM.getLangOpts().OpenMPIRBuilder) {
2106 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2108 llvm::Value *IfCond =
nullptr;
2113 llvm::Value *NumThreads =
nullptr;
2115 NumThreads =
EmitScalarExpr(NumThreadsClause->getNumThreads().front(),
2118 ProcBindKind ProcBind = OMP_PROC_BIND_default;
2119 if (
const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>())
2120 ProcBind = ProcBindClause->getProcBindKind();
2122 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2126 auto FiniCB = [
this](InsertPointTy IP) {
2128 return llvm::Error::success();
2135 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
2136 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
2147 auto BodyGenCB = [&,
this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
2150 *
this, ParallelRegionBodyStmt, AllocIP, CodeGenIP,
"parallel");
2151 return llvm::Error::success();
2156 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
2158 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2159 cantFail(OMPBuilder.createParallel(
2160 Builder, AllocaIP, {}, BodyGenCB, PrivCB, FiniCB,
2161 IfCond, NumThreads, ProcBind, S.hasCancel()));
2175 CGF.
EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt());
2184 [](CodeGenFunction &) {
return nullptr; });
2196class OMPTransformDirectiveScopeRAII {
2197 OMPLoopScope *
Scope =
nullptr;
2201 OMPTransformDirectiveScopeRAII(
const OMPTransformDirectiveScopeRAII &) =
2203 OMPTransformDirectiveScopeRAII &
2204 operator=(
const OMPTransformDirectiveScopeRAII &) =
delete;
2208 if (
const auto *Dir = dyn_cast<OMPLoopBasedDirective>(S)) {
2209 Scope =
new OMPLoopScope(CGF, *Dir);
2212 }
else if (
const auto *Dir =
2213 dyn_cast<OMPCanonicalLoopSequenceTransformationDirective>(
2218 Scope =
new OMPLoopScope(CGF, *Dir);
2223 ~OMPTransformDirectiveScopeRAII() {
2234 int MaxLevel,
int Level = 0) {
2235 assert(Level < MaxLevel &&
"Too deep lookup during loop body codegen.");
2237 if (
const auto *CS = dyn_cast<CompoundStmt>(SimplifiedS)) {
2240 "LLVM IR generation of compound statement ('{}')");
2244 for (
const Stmt *CurStmt : CS->body())
2245 emitBody(CGF, CurStmt, NextLoop, MaxLevel, Level);
2252 if (SimplifiedS == OMPLoopBasedDirective::ignoreIntraTileHint(NextLoop)) {
2253 if (
auto *Dir = dyn_cast<OMPLoopTransformationDirective>(SimplifiedS))
2254 SimplifiedS = Dir->getTransformedStmt();
2255 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(SimplifiedS))
2256 SimplifiedS = CanonLoop->getLoopStmt();
2257 if (
const auto *For = dyn_cast<ForStmt>(SimplifiedS)) {
2261 "Expected canonical for loop or range-based for loop.");
2263 CGF.
EmitStmt(CXXFor->getLoopVarStmt());
2264 S = CXXFor->getBody();
2266 if (Level + 1 < MaxLevel) {
2267 NextLoop = OMPLoopDirective::tryToFindNextInnerLoop(
2269 emitBody(CGF, S, NextLoop, MaxLevel, Level + 1);
2287 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2288 for (
const Expr *UE :
C->updates())
2295 BreakContinueStack.push_back(BreakContinue(D,
LoopExit, Continue));
2309 bool IsInscanRegion = InscanScope.
Privatize();
2310 if (IsInscanRegion) {
2320 if (EKind != OMPD_simd && !
getLangOpts().OpenMPSimd)
2329 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
2332 OMPLoopBasedDirective::tryToFindNextInnerLoop(
2334 D.getLoopsNumber());
2342 BreakContinueStack.pop_back();
2353 std::unique_ptr<CodeGenFunction::CGCapturedStmtInfo> CSI =
2354 std::make_unique<CodeGenFunction::CGCapturedStmtInfo>(*S);
2358 return {F, CapStruct.getPointer(
ParentCGF)};
2362static llvm::CallInst *
2367 EffectiveArgs.reserve(Args.size() + 1);
2368 llvm::append_range(EffectiveArgs, Args);
2369 EffectiveArgs.push_back(Cap.second);
2374llvm::CanonicalLoopInfo *
2376 assert(Depth == 1 &&
"Nested loops with OpenMPIRBuilder not yet implemented");
2402 const Stmt *SyntacticalLoop = S->getLoopStmt();
2413 const Stmt *BodyStmt;
2414 if (
const auto *For = dyn_cast<ForStmt>(SyntacticalLoop)) {
2415 if (
const Stmt *InitStmt = For->getInit())
2417 BodyStmt = For->getBody();
2418 }
else if (
const auto *RangeFor =
2419 dyn_cast<CXXForRangeStmt>(SyntacticalLoop)) {
2420 if (
const DeclStmt *RangeStmt = RangeFor->getRangeStmt())
2422 if (
const DeclStmt *BeginStmt = RangeFor->getBeginStmt())
2424 if (
const DeclStmt *EndStmt = RangeFor->getEndStmt())
2426 if (
const DeclStmt *LoopVarStmt = RangeFor->getLoopVarStmt())
2428 BodyStmt = RangeFor->getBody();
2430 llvm_unreachable(
"Expected for-stmt or range-based for-stmt");
2433 const CapturedStmt *DistanceFunc = S->getDistanceFunc();
2446 llvm::Value *DistVal =
Builder.CreateLoad(CountAddr,
".count");
2449 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2450 auto BodyGen = [&,
this](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP,
2451 llvm::Value *IndVar) {
2456 const DeclRefExpr *LoopVarRef = S->getLoopVarRef();
2464 return llvm::Error::success();
2467 llvm::CanonicalLoopInfo *
CL =
2468 cantFail(OMPBuilder.createCanonicalLoop(
Builder, BodyGen, DistVal));
2480 const Expr *IncExpr,
2481 const llvm::function_ref<
void(CodeGenFunction &)> BodyGen,
2482 const llvm::function_ref<
void(CodeGenFunction &)> PostIncGen) {
2492 const CapturedStmt *ICS = OMPED.getInnermostCapturedStmt();
2506 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
2507 if (RequiresCleanup)
2514 if (ExitBlock !=
LoopExit.getBlock()) {
2524 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
2532 BreakContinueStack.pop_back();
2543 bool HasLinears =
false;
2544 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2548 if (
const auto *Ref =
2567 if (
const auto *CS = cast_or_null<BinaryOperator>(
C->getCalcStep()))
2579 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2582 llvm::BasicBlock *DoneBB =
nullptr;
2584 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2585 auto IC =
C->varlist_begin();
2586 for (
const Expr *F :
C->finals()) {
2588 if (llvm::Value *Cond = CondGen(*
this)) {
2593 Builder.CreateCondBr(Cond, ThenBB, DoneBB);
2600 (*IC)->getType(),
VK_LValue, (*IC)->getExprLoc());
2608 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
2620 llvm::APInt ClauseAlignment(64, 0);
2621 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
2624 ClauseAlignment = AlignmentCI->getValue();
2626 for (
const Expr *E : Clause->varlist()) {
2627 llvm::APInt Alignment(ClauseAlignment);
2628 if (Alignment == 0) {
2635 E->getType()->getPointeeType()))
2638 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2639 "alignment is not power of 2");
2640 if (Alignment != 0) {
2661 LocalDeclMap.erase(PrivateVD);
2667 E->getType(),
VK_LValue, E->getExprLoc());
2675 for (
const auto *
C : S.getClausesOfKind<OMPOrderedClause>()) {
2676 if (!
C->getNumForLoops())
2678 for (
unsigned I = S.getLoopsNumber(), E =
C->getLoopNumIterations().size();
2684 if (DRE->refersToEnclosingVariableOrCapture()) {
2693 const Expr *Cond, llvm::BasicBlock *TrueBlock,
2694 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
2712 assert(!E->getType().getNonReferenceType()->isRecordType() &&
2713 "dependent counter must not be an iterator.");
2717 (void)PreCondVars.
setVarAddr(CGF, VD, CounterAddr);
2719 (void)PreCondVars.
apply(CGF);
2734 llvm::DenseSet<const VarDecl *> SIMDLCVs;
2738 for (
const Expr *
C : LoopDirective->counters()) {
2743 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2744 auto CurPrivate =
C->privates().begin();
2745 for (
const Expr *E :
C->varlist()) {
2747 const auto *PrivateVD =
2754 assert(IsRegistered &&
"linear var already registered as private");
2842 if (
const auto *CS = dyn_cast<CapturedStmt>(S))
2860 if (HasOrderedDirective)
2868 const Stmt *AssociatedStmt = D.getAssociatedStmt();
2872 if (
C->getKind() == OMPC_ORDER_concurrent)
2875 if ((EKind == OMPD_simd ||
2877 llvm::any_of(D.getClausesOfKind<OMPReductionClause>(),
2878 [](
const OMPReductionClause *
C) {
2879 return C->getModifier() == OMPC_REDUCTION_inscan;
2887 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2890 llvm::BasicBlock *DoneBB =
nullptr;
2896 const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
2898 OrigVD->hasGlobalStorage() || CED) {
2900 if (llvm::Value *Cond = CondGen(*
this)) {
2905 Builder.CreateCondBr(Cond, ThenBB, DoneBB);
2948 auto &&ThenGen = [&S, &SimdInitGen, &BodyCodeGen](
CodeGenFunction &CGF,
2962 const Expr *IfCond =
nullptr;
2965 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
2967 (
C->getNameModifier() == OMPD_unknown ||
2968 C->getNameModifier() == OMPD_simd)) {
2969 IfCond =
C->getCondition();
2985 OMPLoopScope PreInitScope(CGF, S);
3007 llvm::BasicBlock *ContBlock =
nullptr;
3059 emitOMPLoopBodyWithStopPoint(CGF, S,
3060 CodeGenFunction::JumpDest());
3066 if (HasLastprivateClause)
3095 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(S.getRawStmt())) {
3096 if (
const Stmt *SyntacticalLoop = CanonLoop->getLoopStmt()) {
3097 for (
const Stmt *SubStmt : SyntacticalLoop->
children()) {
3100 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(SubStmt)) {
3115static llvm::MapVector<llvm::Value *, llvm::Value *>
3117 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars;
3119 llvm::APInt ClauseAlignment(64, 0);
3120 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
3123 ClauseAlignment = AlignmentCI->getValue();
3125 for (
const Expr *E : Clause->varlist()) {
3126 llvm::APInt Alignment(ClauseAlignment);
3127 if (Alignment == 0) {
3134 E->getType()->getPointeeType()))
3137 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
3138 "alignment is not power of 2");
3140 AlignedVars[PtrValue] = CGF.
Builder.getInt64(Alignment.getSExtValue());
3150 bool UseOMPIRBuilder =
3152 if (UseOMPIRBuilder) {
3156 if (UseOMPIRBuilder) {
3157 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars =
3160 const Stmt *Inner = S.getRawStmt();
3161 llvm::CanonicalLoopInfo *CLI =
3162 CGF.EmitOMPCollapsedCanonicalLoopNest(Inner, 1);
3164 llvm::OpenMPIRBuilder &OMPBuilder =
3167 llvm::ConstantInt *Simdlen =
nullptr;
3174 llvm::ConstantInt *Safelen =
nullptr;
3181 llvm::omp::OrderKind Order = llvm::omp::OrderKind::OMP_ORDER_unknown;
3183 if (
C->getKind() == OpenMPOrderClauseKind::OMPC_ORDER_concurrent) {
3184 Order = llvm::omp::OrderKind::OMP_ORDER_concurrent;
3189 OMPBuilder.applySimd(CLI, AlignedVars,
3190 nullptr, Order, Simdlen, Safelen);
3197 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
3212 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
3225 OMPTransformDirectiveScopeRAII TileScope(*
this, &S);
3231 OMPTransformDirectiveScopeRAII StripeScope(*
this, &S);
3237 OMPTransformDirectiveScopeRAII ReverseScope(*
this, &S);
3243 OMPTransformDirectiveScopeRAII SplitScope(*
this, &S);
3250 OMPTransformDirectiveScopeRAII InterchangeScope(*
this, &S);
3256 OMPTransformDirectiveScopeRAII FuseScope(*
this, &S);
3261 bool UseOMPIRBuilder =
CGM.getLangOpts().OpenMPIRBuilder;
3263 if (UseOMPIRBuilder) {
3265 const Stmt *Inner = S.getRawStmt();
3273 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
3276 llvm::CanonicalLoopInfo *UnrolledCLI =
nullptr;
3280 OMPBuilder.unrollLoopFull(DL, CLI);
3282 uint64_t Factor = 0;
3283 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3284 Factor = FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
3285 assert(Factor >= 1 &&
"Only positive factors are valid");
3287 OMPBuilder.unrollLoopPartial(DL, CLI, Factor,
3288 NeedsUnrolledCLI ? &UnrolledCLI :
nullptr);
3290 OMPBuilder.unrollLoopHeuristic(DL, CLI);
3293 assert((!NeedsUnrolledCLI || UnrolledCLI) &&
3294 "NeedsUnrolledCLI implies UnrolledCLI to be set");
3311 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3313 FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
3314 assert(Factor >= 1 &&
"Only positive factors are valid");
3322void CodeGenFunction::EmitOMPOuterLoop(
3325 const CodeGenFunction::OMPLoopArguments &LoopArgs,
3344 llvm::Value *BoolCondVal =
nullptr;
3345 if (!DynamicOrOrdered) {
3356 RT.
emitForNext(*
this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL,
3357 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST);
3362 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
3367 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
3368 if (ExitBlock !=
LoopExit.getBlock()) {
3376 if (DynamicOrOrdered)
3381 BreakContinueStack.push_back(BreakContinue(S, LoopExit, Continue));
3386 [&S, IsMonotonic, EKind](CodeGenFunction &CGF, PrePostActionTy &) {
3391 if (
const auto *
C = S.getSingleClause<OMPOrderClause>())
3392 if (
C->getKind() == OMPC_ORDER_concurrent)
3398 [&S, &LoopArgs, LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered,
3399 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
3400 SourceLocation Loc = S.getBeginLoc();
3406 CGF.EmitOMPInnerLoop(
3408 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
3409 CodeGenLoop(CGF, S, LoopExit);
3411 [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) {
3412 CodeGenOrdered(CGF, Loc, IVSize, IVSigned);
3417 BreakContinueStack.pop_back();
3418 if (!DynamicOrOrdered) {
3431 auto &&CodeGen = [DynamicOrOrdered, &S, &LoopArgs](CodeGenFunction &CGF) {
3432 if (!DynamicOrOrdered)
3433 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
3436 OMPCancelStack.emitExit(*
this, EKind, CodeGen);
3439void CodeGenFunction::EmitOMPForOuterLoop(
3440 const OpenMPScheduleTy &ScheduleKind,
bool IsMonotonic,
3442 const OMPLoopArguments &LoopArgs,
3444 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3450 LoopArgs.Chunk !=
nullptr)) &&
3451 "static non-chunked schedule does not need outer loop");
3509 if (DynamicOrOrdered) {
3510 const std::pair<llvm::Value *, llvm::Value *> DispatchBounds =
3511 CGDispatchBounds(*
this, S, LoopArgs.LB, LoopArgs.UB);
3512 llvm::Value *LBVal = DispatchBounds.first;
3513 llvm::Value *UBVal = DispatchBounds.second;
3514 CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal,
3517 IVSigned, Ordered, DipatchRTInputValues);
3519 CGOpenMPRuntime::StaticRTInput StaticInit(
3520 IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
3521 LoopArgs.ST, LoopArgs.Chunk);
3527 auto &&CodeGenOrdered = [Ordered](CodeGenFunction &CGF, SourceLocation Loc,
3528 const unsigned IVSize,
3529 const bool IVSigned) {
3536 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST,
3537 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB);
3538 OuterLoopArgs.IncExpr = S.
getInc();
3539 OuterLoopArgs.Init = S.
getInit();
3540 OuterLoopArgs.Cond = S.
getCond();
3543 OuterLoopArgs.DKind = LoopArgs.DKind;
3544 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
3546 if (DynamicOrOrdered) {
3552 const unsigned IVSize,
const bool IVSigned) {}
3554void CodeGenFunction::EmitOMPDistributeOuterLoop(
3559 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3571 CGOpenMPRuntime::StaticRTInput StaticInit(
3572 IVSize, IVSigned,
false, LoopArgs.IL, LoopArgs.LB,
3573 LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
3587 OMPLoopArguments OuterLoopArgs;
3588 OuterLoopArgs.LB = LoopArgs.LB;
3589 OuterLoopArgs.UB = LoopArgs.UB;
3590 OuterLoopArgs.ST = LoopArgs.ST;
3591 OuterLoopArgs.IL = LoopArgs.IL;
3592 OuterLoopArgs.Chunk = LoopArgs.Chunk;
3596 OuterLoopArgs.IncExpr = IncExpr;
3609 OuterLoopArgs.DKind = OMPD_distribute;
3611 EmitOMPOuterLoop(
false,
false, S,
3612 LoopScope, OuterLoopArgs, CodeGenLoopContent,
3616static std::pair<LValue, LValue>
3659static std::pair<llvm::Value *, llvm::Value *>
3670 llvm::Value *LBVal =
3672 llvm::Value *UBVal =
3674 return {LBVal, UBVal};
3683 llvm::Value *LBCast = CGF.
Builder.CreateIntCast(
3685 CapturedVars.push_back(LBCast);
3689 llvm::Value *UBCast = CGF.
Builder.CreateIntCast(
3691 CapturedVars.push_back(UBCast);
3702 bool HasCancel =
false;
3704 if (
const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
3705 HasCancel = D->hasCancel();
3706 else if (
const auto *D = dyn_cast<OMPDistributeParallelForDirective>(&S))
3707 HasCancel = D->hasCancel();
3708 else if (
const auto *D =
3709 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S))
3710 HasCancel = D->hasCancel();
3720 CGInlinedWorksharingLoop,
3730 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3731 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3740 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3741 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3749 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
3750 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
3760 llvm::Constant *
Addr;
3762 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
3764 assert(Fn &&
Addr &&
"Target device function emission failed.");
3776struct ScheduleKindModifiersTy {
3783 : Kind(Kind), M1(M1), M2(M2) {}
3807 bool HasLastprivateClause;
3810 OMPLoopScope PreInitScope(*
this, S);
3815 llvm::BasicBlock *ContBlock =
nullptr;
3829 bool Ordered =
false;
3830 if (
const auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) {
3831 if (OrderedClause->getNumForLoops())
3841 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*
this, S);
3842 LValue LB = Bounds.first;
3843 LValue UB = Bounds.second;
3857 CGM.getOpenMPRuntime().emitBarrierCall(
3858 *
this, S.getBeginLoc(), OMPD_unknown,
false,
3870 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
3873 const Expr *ChunkExpr =
nullptr;
3875 if (
const auto *
C = S.getSingleClause<OMPScheduleClause>()) {
3876 ScheduleKind.
Schedule =
C->getScheduleKind();
3877 ScheduleKind.
M1 =
C->getFirstScheduleModifier();
3878 ScheduleKind.
M2 =
C->getSecondScheduleModifier();
3879 ChunkExpr =
C->getChunkSize();
3882 CGM.getOpenMPRuntime().getDefaultScheduleAndChunk(
3883 *
this, S, ScheduleKind.
Schedule, ChunkExpr);
3885 bool HasChunkSizeOne =
false;
3886 llvm::Value *Chunk =
nullptr;
3894 llvm::APSInt EvaluatedChunk =
Result.Val.getInt();
3895 HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
3904 bool StaticChunkedOne =
3906 Chunk !=
nullptr) &&
3918 "fused distribute schedule requires a static chunk-one schedule");
3921 (ScheduleKind.
Schedule == OMPC_SCHEDULE_static &&
3922 !(ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
3923 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)) ||
3924 ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
3925 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
3927 Chunk !=
nullptr) ||
3928 StaticChunkedOne) &&
3938 if (
C->getKind() == OMPC_ORDER_concurrent)
3942 [IVSize, IVSigned, Ordered, IL, LB, UB, ST, StaticChunkedOne, Chunk,
3951 IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(),
3952 UB.getAddress(), ST.getAddress(),
3953 StaticChunkedOne ? Chunk :
nullptr);
3955 CGF, S.getBeginLoc(), EKind, ScheduleKind, StaticInit);
3957 if (!StaticChunkedOne)
3976 StaticChunkedOne ? S.getCombinedParForInDistCond()
3978 StaticChunkedOne ? S.getDistInc() : S.getInc(),
3979 [&S,
LoopExit](CodeGenFunction &CGF) {
3980 emitOMPLoopBodyWithStopPoint(CGF, S, LoopExit);
3982 [](CodeGenFunction &) {});
3986 auto &&
CodeGen = [&S](CodeGenFunction &CGF) {
3990 OMPCancelStack.emitExit(*
this, EKind,
CodeGen);
3997 LoopArguments.DKind = OMPD_for;
3998 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
3999 LoopArguments, CGDispatchBounds);
4003 return CGF.
Builder.CreateIsNotNull(
4009 ? OMPD_parallel_for_simd
4013 *
this, S, [IL, &S](CodeGenFunction &CGF) {
4014 return CGF.
Builder.CreateIsNotNull(
4018 if (HasLastprivateClause)
4024 return CGF.
Builder.CreateIsNotNull(
4035 return HasLastprivateClause;
4041static std::pair<LValue, LValue>
4055static std::pair<llvm::Value *, llvm::Value *>
4059 const Expr *IVExpr = LS.getIterationVariable();
4061 llvm::Value *LBVal = CGF.
Builder.getIntN(IVSize, 0);
4063 return {LBVal, UBVal};
4075 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
4076 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4077 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4082 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4083 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4084 "Only inscan reductions are expected.");
4085 Shareds.append(
C->varlist_begin(),
C->varlist_end());
4086 Privates.append(
C->privates().begin(),
C->privates().end());
4087 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
4088 CopyArrayTemps.append(
C->copy_array_temps().begin(),
4089 C->copy_array_temps().end());
4097 auto *ITA = CopyArrayTemps.begin();
4102 if (PrivateVD->getType()->isVariablyModifiedType()) {
4127 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
4128 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4129 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4136 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4137 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4138 "Only inscan reductions are expected.");
4139 Shareds.append(
C->varlist_begin(),
C->varlist_end());
4140 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
4141 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
4142 Privates.append(
C->privates().begin(),
C->privates().end());
4143 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
4144 CopyArrayElems.append(
C->copy_array_elems().begin(),
4145 C->copy_array_elems().end());
4149 llvm::Value *OMPLast = CGF.
Builder.CreateNSWSub(
4150 OMPScanNumIterations,
4151 llvm::ConstantInt::get(CGF.
SizeTy, 1,
false));
4152 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
4154 const Expr *OrigExpr = Shareds[I];
4155 const Expr *CopyArrayElem = CopyArrayElems[I];
4162 LValue SrcLVal = CGF.
EmitLValue(CopyArrayElem);
4164 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
4194 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4195 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4201 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4202 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4203 "Only inscan reductions are expected.");
4204 Privates.append(
C->privates().begin(),
C->privates().end());
4205 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
4206 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
4207 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
4208 CopyArrayElems.append(
C->copy_array_elems().begin(),
4209 C->copy_array_elems().end());
4224 auto &&
CodeGen = [&S, OMPScanNumIterations, &LHSs, &RHSs, &CopyArrayElems,
4231 llvm::BasicBlock *InputBB = CGF.Builder.GetInsertBlock();
4232 llvm::BasicBlock *LoopBB = CGF.createBasicBlock(
"omp.outer.log.scan.body");
4233 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
"omp.outer.log.scan.exit");
4235 CGF.CGM.getIntrinsic(llvm::Intrinsic::log2, CGF.DoubleTy);
4237 CGF.Builder.CreateUIToFP(OMPScanNumIterations, CGF.DoubleTy);
4238 llvm::Value *LogVal = CGF.EmitNounwindRuntimeCall(F, Arg);
4239 F = CGF.CGM.getIntrinsic(llvm::Intrinsic::ceil, CGF.DoubleTy);
4240 LogVal = CGF.EmitNounwindRuntimeCall(F, LogVal);
4241 LogVal = CGF.Builder.CreateFPToUI(LogVal, CGF.IntTy);
4242 llvm::Value *NMin1 = CGF.Builder.CreateNUWSub(
4243 OMPScanNumIterations, llvm::ConstantInt::get(CGF.SizeTy, 1));
4245 CGF.EmitBlock(LoopBB);
4246 auto *Counter = CGF.Builder.CreatePHI(CGF.IntTy, 2);
4248 auto *Pow2K = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
4249 Counter->addIncoming(llvm::ConstantInt::get(CGF.IntTy, 0), InputBB);
4250 Pow2K->addIncoming(llvm::ConstantInt::get(CGF.SizeTy, 1), InputBB);
4253 llvm::BasicBlock *InnerLoopBB =
4254 CGF.createBasicBlock(
"omp.inner.log.scan.body");
4255 llvm::BasicBlock *InnerExitBB =
4256 CGF.createBasicBlock(
"omp.inner.log.scan.exit");
4257 llvm::Value *CmpI = CGF.Builder.CreateICmpUGE(NMin1, Pow2K);
4258 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4259 CGF.EmitBlock(InnerLoopBB);
4260 auto *IVal = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
4261 IVal->addIncoming(NMin1, LoopBB);
4264 auto *ILHS = LHSs.begin();
4265 auto *IRHS = RHSs.begin();
4266 for (
const Expr *CopyArrayElem : CopyArrayElems) {
4276 LHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4281 llvm::Value *OffsetIVal = CGF.Builder.CreateNUWSub(IVal, Pow2K);
4287 RHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4294 CGF.CGM.getOpenMPRuntime().emitReduction(
4295 CGF, S.getEndLoc(),
Privates, LHSs, RHSs, ReductionOps,
4299 llvm::Value *NextIVal =
4300 CGF.Builder.CreateNUWSub(IVal, llvm::ConstantInt::get(CGF.SizeTy, 1));
4301 IVal->addIncoming(NextIVal, CGF.Builder.GetInsertBlock());
4302 CmpI = CGF.Builder.CreateICmpUGE(NextIVal, Pow2K);
4303 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4304 CGF.EmitBlock(InnerExitBB);
4306 CGF.Builder.CreateNUWAdd(Counter, llvm::ConstantInt::get(CGF.IntTy, 1));
4307 Counter->addIncoming(
Next, CGF.Builder.GetInsertBlock());
4309 llvm::Value *NextPow2K =
4310 CGF.Builder.CreateShl(Pow2K, 1,
"",
true);
4311 Pow2K->addIncoming(NextPow2K, CGF.Builder.GetInsertBlock());
4312 llvm::Value *
Cmp = CGF.Builder.CreateICmpNE(
Next, LogVal);
4313 CGF.Builder.CreateCondBr(
Cmp, LoopBB, ExitBB);
4315 CGF.EmitBlock(ExitBB);
4321 CGF, S.getBeginLoc(), OMPD_unknown,
false,
4324 RegionCodeGenTy RCG(CodeGen);
4335 bool HasLastprivates;
4337 if (llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4338 [](
const OMPReductionClause *
C) {
4339 return C->getModifier() == OMPC_REDUCTION_inscan;
4343 OMPLoopScope LoopScope(CGF, S);
4346 const auto &&FirstGen = [&S, HasCancel, EKind](
CodeGenFunction &CGF) {
4355 const auto &&SecondGen = [&S, HasCancel, EKind,
4373 return HasLastprivates;
4386 if (
auto *SC = dyn_cast<OMPScheduleClause>(
C)) {
4391 switch (SC->getScheduleKind()) {
4392 case OMPC_SCHEDULE_auto:
4393 case OMPC_SCHEDULE_dynamic:
4394 case OMPC_SCHEDULE_runtime:
4395 case OMPC_SCHEDULE_guided:
4396 case OMPC_SCHEDULE_static:
4409static llvm::omp::ScheduleKind
4411 switch (ScheduleClauseKind) {
4413 return llvm::omp::OMP_SCHEDULE_Default;
4414 case OMPC_SCHEDULE_auto:
4415 return llvm::omp::OMP_SCHEDULE_Auto;
4416 case OMPC_SCHEDULE_dynamic:
4417 return llvm::omp::OMP_SCHEDULE_Dynamic;
4418 case OMPC_SCHEDULE_guided:
4419 return llvm::omp::OMP_SCHEDULE_Guided;
4420 case OMPC_SCHEDULE_runtime:
4421 return llvm::omp::OMP_SCHEDULE_Runtime;
4422 case OMPC_SCHEDULE_static:
4423 return llvm::omp::OMP_SCHEDULE_Static;
4425 llvm_unreachable(
"Unhandled schedule kind");
4432 bool HasLastprivates =
false;
4435 auto &&
CodeGen = [&S, &
CGM, HasCancel, &HasLastprivates,
4438 if (UseOMPIRBuilder) {
4439 bool NeedsBarrier = !S.getSingleClause<OMPNowaitClause>();
4441 llvm::omp::ScheduleKind SchedKind = llvm::omp::OMP_SCHEDULE_Default;
4442 llvm::Value *ChunkSize =
nullptr;
4443 if (
auto *SchedClause = S.getSingleClause<OMPScheduleClause>()) {
4446 if (
const Expr *ChunkSizeExpr = SchedClause->getChunkSize())
4451 const Stmt *Inner = S.getRawStmt();
4452 llvm::CanonicalLoopInfo *CLI =
4455 llvm::OpenMPIRBuilder &OMPBuilder =
4457 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4459 cantFail(OMPBuilder.applyWorkshareLoop(
4460 CGF.
Builder.getCurrentDebugLocation(), CLI, AllocaIP, NeedsBarrier,
4461 SchedKind, ChunkSize,
false,
4472 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
4477 if (!UseOMPIRBuilder) {
4479 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4491 bool HasLastprivates =
false;
4492 auto &&
CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
4499 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4500 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
4504 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4505 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_for);
4512 llvm::Value *
Init =
nullptr) {
4519void CodeGenFunction::EmitSections(
const OMPExecutableDirective &S) {
4520 const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4521 const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt);
4522 bool HasLastprivates =
false;
4524 auto &&CodeGen = [&S, CapturedStmt, CS, EKind,
4525 &HasLastprivates](CodeGenFunction &CGF, PrePostActionTy &) {
4526 const ASTContext &
C = CGF.getContext();
4527 QualType KmpInt32Ty =
4528 C.getIntTypeForBitwidth(32, 1);
4531 CGF.Builder.getInt32(0));
4532 llvm::ConstantInt *GlobalUBVal = CS !=
nullptr
4533 ? CGF.Builder.getInt32(CS->size() - 1)
4534 : CGF.Builder.getInt32(0);
4538 CGF.Builder.getInt32(1));
4540 CGF.Builder.getInt32(0));
4543 OpaqueValueExpr IVRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4544 CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
4545 OpaqueValueExpr UBRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4546 CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
4550 S.getBeginLoc(), FPOptionsOverride());
4554 S.getBeginLoc(),
true, FPOptionsOverride());
4555 auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
4567 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".omp.sections.exit");
4568 llvm::SwitchInst *SwitchStmt =
4569 CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.
getBeginLoc()),
4570 ExitBB, CS ==
nullptr ? 1 : CS->size());
4572 unsigned CaseNumber = 0;
4573 for (
const Stmt *SubStmt : CS->
children()) {
4574 auto CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4575 CGF.EmitBlock(CaseBB);
4576 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
4577 CGF.EmitStmt(SubStmt);
4578 CGF.EmitBranch(ExitBB);
4582 llvm::BasicBlock *CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4583 CGF.EmitBlock(CaseBB);
4584 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
4585 CGF.EmitStmt(CapturedStmt);
4586 CGF.EmitBranch(ExitBB);
4588 CGF.EmitBlock(ExitBB,
true);
4591 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
4592 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
4596 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
4600 CGF.EmitOMPPrivateClause(S, LoopScope);
4601 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(CGF, S, IV);
4602 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
4603 CGF.EmitOMPReductionClauseInit(S, LoopScope);
4604 (void)LoopScope.Privatize();
4606 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
4609 OpenMPScheduleTy ScheduleKind;
4610 ScheduleKind.
Schedule = OMPC_SCHEDULE_static;
4611 CGOpenMPRuntime::StaticRTInput StaticInit(
4612 32,
true,
false, IL.getAddress(),
4613 LB.getAddress(), UB.getAddress(), ST.getAddress());
4614 CGF.CGM.getOpenMPRuntime().emitForStaticInit(CGF, S.
getBeginLoc(), EKind,
4615 ScheduleKind, StaticInit);
4617 llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.
getBeginLoc());
4618 llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
4619 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
4620 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
4622 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.
getBeginLoc()), IV);
4624 CGF.EmitOMPInnerLoop(S,
false, Cond, Inc, BodyGen,
4625 [](CodeGenFunction &) {});
4627 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
4628 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.
getEndLoc(),
4631 CGF.OMPCancelStack.emitExit(CGF, EKind, CodeGen);
4632 CGF.EmitOMPReductionClauseFinal(S, OMPD_parallel);
4635 return CGF.
Builder.CreateIsNotNull(
4640 if (HasLastprivates)
4647 bool HasCancel =
false;
4648 if (
auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
4649 HasCancel = OSD->hasCancel();
4650 else if (
auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
4651 HasCancel = OPSD->hasCancel();
4653 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_sections, CodeGen,
4658 if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) {
4676 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4681 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4682 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_scope,
CodeGen);
4685 if (!S.getSingleClause<OMPNowaitClause>()) {
4686 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_scope);
4693 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4694 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4695 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4696 using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
4698 auto FiniCB = [](InsertPointTy IP) {
4701 return llvm::Error::success();
4704 const CapturedStmt *ICS = S.getInnermostCapturedStmt();
4705 const Stmt *
CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4710 auto SectionCB = [
this, SubStmt](
4711 InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4714 CodeGenIP,
"section");
4715 return llvm::Error::success();
4717 SectionCBVector.push_back(SectionCB);
4721 [
this,
CapturedStmt](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4725 return llvm::Error::success();
4727 SectionCBVector.push_back(SectionCB);
4734 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
4735 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
4745 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4747 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4748 cantFail(OMPBuilder.createSections(
4750 S.getSingleClause<OMPNowaitClause>()));
4757 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4761 if (!S.getSingleClause<OMPNowaitClause>()) {
4762 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(),
4770 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4771 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4772 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4774 const Stmt *SectionRegionBodyStmt = S.getAssociatedStmt();
4775 auto FiniCB = [
this](InsertPointTy IP) {
4777 return llvm::Error::success();
4780 auto BodyGenCB = [SectionRegionBodyStmt,
4781 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4784 *
this, SectionRegionBodyStmt, AllocIP, CodeGenIP,
"section");
4785 return llvm::Error::success();
4790 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4791 cantFail(OMPBuilder.createSection(
Builder, BodyGenCB, FiniCB));
4811 CopyprivateVars.append(
C->varlist_begin(),
C->varlist_end());
4812 DestExprs.append(
C->destination_exprs().begin(),
4813 C->destination_exprs().end());
4814 SrcExprs.append(
C->source_exprs().begin(),
C->source_exprs().end());
4815 AssignmentOps.append(
C->assignment_ops().begin(),
4816 C->assignment_ops().end());
4825 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4830 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4831 CGM.getOpenMPRuntime().emitSingleRegion(*
this,
CodeGen, S.getBeginLoc(),
4832 CopyprivateVars, DestExprs,
4833 SrcExprs, AssignmentOps);
4837 if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) {
4838 CGM.getOpenMPRuntime().emitBarrierCall(
4839 *
this, S.getBeginLoc(),
4840 S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);
4855 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4856 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4857 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4859 const Stmt *MasterRegionBodyStmt = S.getAssociatedStmt();
4861 auto FiniCB = [
this](InsertPointTy IP) {
4863 return llvm::Error::success();
4866 auto BodyGenCB = [MasterRegionBodyStmt,
4867 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4870 *
this, MasterRegionBodyStmt, AllocIP, CodeGenIP,
"master");
4871 return llvm::Error::success();
4876 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4877 cantFail(OMPBuilder.createMaster(
Builder, BodyGenCB, FiniCB));
4892 Expr *Filter =
nullptr;
4894 Filter = FilterClause->getThreadID();
4900 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4901 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4902 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4904 const Stmt *MaskedRegionBodyStmt = S.getAssociatedStmt();
4905 const Expr *Filter =
nullptr;
4907 Filter = FilterClause->getThreadID();
4908 llvm::Value *FilterVal = Filter
4910 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
4912 auto FiniCB = [
this](InsertPointTy IP) {
4914 return llvm::Error::success();
4917 auto BodyGenCB = [MaskedRegionBodyStmt,
4918 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4921 *
this, MaskedRegionBodyStmt, AllocIP, CodeGenIP,
"masked");
4922 return llvm::Error::success();
4927 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
4928 OMPBuilder.createMasked(
Builder, BodyGenCB, FiniCB, FilterVal));
4939 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4940 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4941 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4943 const Stmt *CriticalRegionBodyStmt = S.getAssociatedStmt();
4944 const Expr *Hint =
nullptr;
4945 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4946 Hint = HintClause->getHint();
4951 llvm::Value *HintInst =
nullptr;
4956 auto FiniCB = [
this](InsertPointTy IP) {
4958 return llvm::Error::success();
4961 auto BodyGenCB = [CriticalRegionBodyStmt,
4962 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4965 *
this, CriticalRegionBodyStmt, AllocIP, CodeGenIP,
"critical");
4966 return llvm::Error::success();
4971 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4972 cantFail(OMPBuilder.createCritical(
Builder, BodyGenCB, FiniCB,
4982 CGF.
EmitStmt(S.getAssociatedStmt());
4984 const Expr *Hint =
nullptr;
4985 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4986 Hint = HintClause->getHint();
4989 CGM.getOpenMPRuntime().emitCriticalRegion(*
this,
4991 CodeGen, S.getBeginLoc(), Hint);
5004 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
5008 OMPLoopScope LoopScope(CGF, S);
5011 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
5012 [](
const OMPReductionClause *
C) {
5013 return C->getModifier() == OMPC_REDUCTION_inscan;
5038 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
5042 OMPLoopScope LoopScope(CGF, S);
5045 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
5046 [](
const OMPReductionClause *
C) {
5047 return C->getModifier() == OMPC_REDUCTION_inscan;
5083 [](CodeGenFunction &) {
return nullptr; });
5110 [](CodeGenFunction &) {
return nullptr; });
5123 CGF.EmitSections(S);
5137class CheckVarsEscapingUntiedTaskDeclContext final
5142 explicit CheckVarsEscapingUntiedTaskDeclContext() =
default;
5143 ~CheckVarsEscapingUntiedTaskDeclContext() =
default;
5144 void VisitDeclStmt(
const DeclStmt *S) {
5149 if (
const auto *VD = dyn_cast_or_null<VarDecl>(D))
5151 PrivateDecls.push_back(VD);
5155 void VisitCapturedStmt(
const CapturedStmt *) {}
5157 void VisitBlockExpr(
const BlockExpr *) {}
5158 void VisitStmt(
const Stmt *S) {
5161 for (
const Stmt *Child : S->
children())
5167 ArrayRef<const VarDecl *> getPrivateDecls()
const {
return PrivateDecls; }
5175 bool OmpAllMemory =
false;
5178 return C->getDependencyKind() == OMPC_DEPEND_outallmemory ||
5179 C->getDependencyKind() == OMPC_DEPEND_inoutallmemory;
5181 OmpAllMemory =
true;
5186 Data.Dependences.emplace_back(OMPC_DEPEND_outallmemory,
5195 if (Kind == OMPC_DEPEND_outallmemory || Kind == OMPC_DEPEND_inoutallmemory)
5197 if (OmpAllMemory && (Kind == OMPC_DEPEND_out || Kind == OMPC_DEPEND_inout))
5200 Data.Dependences.emplace_back(
C->getDependencyKind(),
C->getModifier());
5201 DD.
DepExprs.append(
C->varlist_begin(),
C->varlist_end());
5210 const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion);
5212 auto PartId = std::next(I);
5213 auto TaskT = std::next(I, 4);
5218 const Expr *Cond = Clause->getCondition();
5221 Data.Final.setInt(CondConstant);
5226 Data.Final.setInt(
false);
5230 const Expr *Prio = Clause->getPriority();
5231 Data.Priority.setInt(
true);
5239 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
5241 for (
const auto *
C : S.getClausesOfKind<OMPPrivateClause>()) {
5242 auto IRef =
C->varlist_begin();
5243 for (
const Expr *IInit :
C->private_copies()) {
5245 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
5246 Data.PrivateVars.push_back(*IRef);
5247 Data.PrivateCopies.push_back(IInit);
5252 EmittedAsPrivate.clear();
5254 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5255 auto IRef =
C->varlist_begin();
5256 auto IElemInitRef =
C->inits().begin();
5257 for (
const Expr *IInit :
C->private_copies()) {
5259 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
5260 Data.FirstprivateVars.push_back(*IRef);
5261 Data.FirstprivateCopies.push_back(IInit);
5262 Data.FirstprivateInits.push_back(*IElemInitRef);
5269 llvm::MapVector<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
5270 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
5271 auto IRef =
C->varlist_begin();
5272 auto ID =
C->destination_exprs().begin();
5273 for (
const Expr *IInit :
C->private_copies()) {
5275 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
5276 Data.LastprivateVars.push_back(*IRef);
5277 Data.LastprivateCopies.push_back(IInit);
5279 LastprivateDstsOrigs.insert(
5288 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
5289 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5290 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5291 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5292 Data.ReductionOps.append(
C->reduction_ops().begin(),
5293 C->reduction_ops().end());
5294 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5295 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5297 Data.Reductions =
CGM.getOpenMPRuntime().emitTaskReductionInit(
5298 *
this, S.getBeginLoc(), LHSs, RHSs,
Data);
5303 CheckVarsEscapingUntiedTaskDeclContext Checker;
5304 Checker.Visit(S.getInnermostCapturedStmt()->getCapturedStmt());
5305 Data.PrivateLocals.append(Checker.getPrivateDecls().begin(),
5306 Checker.getPrivateDecls().end());
5308 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
5309 CapturedRegion](CodeGenFunction &CGF,
5311 llvm::MapVector<CanonicalDeclPtr<const VarDecl>,
5312 std::pair<Address, Address>>
5317 if (
auto *DI = CGF.getDebugInfo()) {
5318 llvm::SmallDenseMap<const VarDecl *, FieldDecl *> CaptureFields =
5319 CGF.CapturedStmtInfo->getCaptureFields();
5320 llvm::Value *ContextValue = CGF.CapturedStmtInfo->getContextValue();
5321 if (CaptureFields.size() && ContextValue) {
5322 unsigned CharWidth = CGF.getContext().getCharWidth();
5336 for (
auto It = CaptureFields.begin(); It != CaptureFields.end(); ++It) {
5337 const VarDecl *SharedVar = It->first;
5340 CGF.getContext().getASTRecordLayout(CaptureRecord);
5343 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5344 (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue,
5345 CGF.Builder,
false);
5348 auto UpdateExpr = [](llvm::LLVMContext &Ctx,
auto *
Declare,
5353 Ops.push_back(llvm::dwarf::DW_OP_plus_uconst);
5354 Ops.push_back(Offset);
5356 Ops.push_back(llvm::dwarf::DW_OP_deref);
5357 Declare->setExpression(llvm::DIExpression::get(Ctx, Ops));
5359 llvm::Instruction &
Last = CGF.Builder.GetInsertBlock()->back();
5360 if (
auto DDI = dyn_cast<llvm::DbgVariableIntrinsic>(&
Last))
5361 UpdateExpr(DDI->getContext(), DDI, Offset);
5364 assert(!
Last.isTerminator() &&
"unexpected terminator");
5366 CGF.Builder.GetInsertBlock()->getTrailingDbgRecords()) {
5367 for (llvm::DbgVariableRecord &DVR : llvm::reverse(
5368 llvm::filterDbgVars(Marker->getDbgRecordRange()))) {
5369 UpdateExpr(
Last.getContext(), &DVR, Offset);
5377 if (!
Data.PrivateVars.empty() || !
Data.FirstprivateVars.empty() ||
5378 !
Data.LastprivateVars.empty() || !
Data.PrivateLocals.empty()) {
5379 enum { PrivatesParam = 2, CopyFnParam = 3 };
5380 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5382 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5388 CallArgs.push_back(PrivatesPtr);
5389 ParamTypes.push_back(PrivatesPtr->getType());
5390 for (
const Expr *E :
Data.PrivateVars) {
5392 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5393 CGF.getContext().getPointerType(E->
getType()),
".priv.ptr.addr");
5394 PrivatePtrs.emplace_back(VD, PrivatePtr);
5396 ParamTypes.push_back(PrivatePtr.
getType());
5398 for (
const Expr *E :
Data.FirstprivateVars) {
5400 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5401 CGF.getContext().getPointerType(E->
getType()),
5402 ".firstpriv.ptr.addr");
5403 PrivatePtrs.emplace_back(VD, PrivatePtr);
5404 FirstprivatePtrs.emplace_back(VD, PrivatePtr);
5406 ParamTypes.push_back(PrivatePtr.
getType());
5408 for (
const Expr *E :
Data.LastprivateVars) {
5410 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5411 CGF.getContext().getPointerType(E->
getType()),
5412 ".lastpriv.ptr.addr");
5413 PrivatePtrs.emplace_back(VD, PrivatePtr);
5415 ParamTypes.push_back(PrivatePtr.
getType());
5420 Ty = CGF.getContext().getPointerType(Ty);
5422 Ty = CGF.getContext().getPointerType(Ty);
5423 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5424 CGF.getContext().getPointerType(Ty),
".local.ptr.addr");
5425 auto Result = UntiedLocalVars.insert(
5428 if (
Result.second ==
false)
5429 *
Result.first = std::make_pair(
5432 ParamTypes.push_back(PrivatePtr.
getType());
5434 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5436 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5437 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5438 for (
const auto &Pair : LastprivateDstsOrigs) {
5442 CGF.CapturedStmtInfo->lookup(OrigVD) !=
nullptr,
5444 Pair.second->getExprLoc());
5445 Scope.addPrivate(Pair.first, CGF.EmitLValue(&DRE).getAddress());
5447 for (
const auto &Pair : PrivatePtrs) {
5449 CGF.Builder.CreateLoad(Pair.second),
5450 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5451 CGF.getContext().getDeclAlign(Pair.first));
5452 Scope.addPrivate(Pair.first, Replacement);
5453 if (
auto *DI = CGF.getDebugInfo())
5454 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5455 (void)DI->EmitDeclareOfAutoVariable(
5456 Pair.first, Pair.second.getBasePointer(), CGF.Builder,
5461 for (
auto &Pair : UntiedLocalVars) {
5462 QualType VDType = Pair.first->getType().getNonReferenceType();
5463 if (Pair.first->getType()->isLValueReferenceType())
5464 VDType = CGF.getContext().getPointerType(VDType);
5466 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5469 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(VDType)),
5470 CGF.getPointerAlign());
5471 Pair.second.first = Replacement;
5472 Ptr = CGF.Builder.CreateLoad(Replacement);
5473 Replacement =
Address(Ptr, CGF.ConvertTypeForMem(VDType),
5474 CGF.getContext().getDeclAlign(Pair.first));
5475 Pair.second.second = Replacement;
5477 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5478 Address Replacement(Ptr, CGF.ConvertTypeForMem(VDType),
5479 CGF.getContext().getDeclAlign(Pair.first));
5480 Pair.second.first = Replacement;
5484 if (
Data.Reductions) {
5486 for (
const auto &Pair : FirstprivatePtrs) {
5488 CGF.Builder.CreateLoad(Pair.second),
5489 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5490 CGF.getContext().getDeclAlign(Pair.first));
5491 FirstprivateScope.
addPrivate(Pair.first, Replacement);
5494 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5496 Data.ReductionCopies,
Data.ReductionOps);
5497 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
5499 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5505 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5507 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5510 CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF),
5511 CGF.getContext().VoidPtrTy,
5512 CGF.getContext().getPointerType(
5513 Data.ReductionCopies[Cnt]->getType()),
5514 Data.ReductionCopies[Cnt]->getExprLoc()),
5515 CGF.ConvertTypeForMem(
Data.ReductionCopies[Cnt]->getType()),
5516 Replacement.getAlignment());
5522 (void)
Scope.Privatize();
5527 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5528 auto IPriv =
C->privates().begin();
5529 auto IRed =
C->reduction_ops().begin();
5530 auto ITD =
C->taskgroup_descriptors().begin();
5531 for (
const Expr *Ref :
C->varlist()) {
5532 InRedVars.emplace_back(Ref);
5533 InRedPrivs.emplace_back(*IPriv);
5534 InRedOps.emplace_back(*IRed);
5535 TaskgroupDescriptors.emplace_back(*ITD);
5536 std::advance(IPriv, 1);
5537 std::advance(IRed, 1);
5538 std::advance(ITD, 1);
5544 if (!InRedVars.empty()) {
5546 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5554 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5556 llvm::Value *ReductionsPtr;
5557 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5558 ReductionsPtr = CGF.EmitLoadOfScalar(CGF.EmitLValue(TRExpr),
5559 TRExpr->getExprLoc());
5561 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5563 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5566 CGF.EmitScalarConversion(
5567 Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy,
5568 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
5569 InRedPrivs[Cnt]->getExprLoc()),
5570 CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()),
5571 Replacement.getAlignment());
5584 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5585 S, *I, *PartId, *TaskT, EKind,
CodeGen,
Data.Tied,
Data.NumberOfParts);
5586 OMPLexicalScope
Scope(*
this, S, std::nullopt,
5589 TaskGen(*
this, OutlinedFn,
Data);
5606 QualType ElemType =
C.getBaseElementType(Ty);
5616 Data.FirstprivateVars.emplace_back(OrigRef);
5617 Data.FirstprivateCopies.emplace_back(PrivateRef);
5618 Data.FirstprivateInits.emplace_back(InitRef);
5631 auto PartId = std::next(I);
5632 auto TaskT = std::next(I, 4);
5635 Data.Final.setInt(
false);
5637 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5638 auto IRef =
C->varlist_begin();
5639 auto IElemInitRef =
C->inits().begin();
5640 for (
auto *IInit :
C->private_copies()) {
5641 Data.FirstprivateVars.push_back(*IRef);
5642 Data.FirstprivateCopies.push_back(IInit);
5643 Data.FirstprivateInits.push_back(*IElemInitRef);
5650 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5651 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5652 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5653 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5654 Data.ReductionOps.append(
C->reduction_ops().begin(),
5655 C->reduction_ops().end());
5656 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5657 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5672 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5674 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5686 if (!isa_and_nonnull<llvm::ConstantPointerNull>(
5689 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5696 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, BPVD, PVD, SVD, MVD, EKind,
5700 if (!
Data.FirstprivateVars.empty()) {
5701 enum { PrivatesParam = 2, CopyFnParam = 3 };
5702 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5704 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5710 CallArgs.push_back(PrivatesPtr);
5711 ParamTypes.push_back(PrivatesPtr->getType());
5712 for (
const Expr *E :
Data.FirstprivateVars) {
5714 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5715 CGF.getContext().getPointerType(E->
getType()),
5716 ".firstpriv.ptr.addr");
5717 PrivatePtrs.emplace_back(VD, PrivatePtr);
5719 ParamTypes.push_back(PrivatePtr.
getType());
5721 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5723 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5724 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5725 for (
const auto &Pair : PrivatePtrs) {
5727 CGF.Builder.CreateLoad(Pair.second),
5728 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5729 CGF.getContext().getDeclAlign(Pair.first));
5730 Scope.addPrivate(Pair.first, Replacement);
5733 CGF.processInReduction(S,
Data, CGF, CS,
Scope);
5736 CGF.GetAddrOfLocalVar(BPVD), 0);
5738 CGF.GetAddrOfLocalVar(PVD), 0);
5739 InputInfo.
SizesArray = CGF.Builder.CreateConstArrayGEP(
5740 CGF.GetAddrOfLocalVar(SVD), 0);
5743 InputInfo.
MappersArray = CGF.Builder.CreateConstArrayGEP(
5744 CGF.GetAddrOfLocalVar(MVD), 0);
5748 OMPLexicalScope LexScope(CGF, S, OMPD_task,
false);
5750 if (CGF.CGM.getLangOpts().OpenMP >= 51 &&
5755 CGF.CGM.getOpenMPRuntime().emitThreadLimitClause(
5756 CGF, TL->getThreadLimit().front(), S.getBeginLoc());
5760 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5761 S, *I, *PartId, *TaskT, EKind,
CodeGen,
true,
5762 Data.NumberOfParts);
5763 llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<OMPNowaitClause>() ? 1 : 0);
5767 CGM.getOpenMPRuntime().emitTaskCall(*
this, S.getBeginLoc(), S, OutlinedFn,
5768 SharedsTy, CapturedStruct, &IfCond,
Data);
5773 CodeGenFunction &CGF,
5777 if (
Data.Reductions) {
5779 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5781 Data.ReductionCopies,
Data.ReductionOps);
5784 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5798 Data.ReductionCopies[Cnt]->getType()),
5799 Data.ReductionCopies[Cnt]->getExprLoc()),
5801 Replacement.getAlignment());
5806 (void)
Scope.Privatize();
5811 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5812 auto IPriv =
C->privates().begin();
5813 auto IRed =
C->reduction_ops().begin();
5814 auto ITD =
C->taskgroup_descriptors().begin();
5815 for (
const Expr *Ref :
C->varlist()) {
5816 InRedVars.emplace_back(Ref);
5817 InRedPrivs.emplace_back(*IPriv);
5818 InRedOps.emplace_back(*IRed);
5819 TaskgroupDescriptors.emplace_back(*ITD);
5820 std::advance(IPriv, 1);
5821 std::advance(IRed, 1);
5822 std::advance(ITD, 1);
5826 if (!InRedVars.empty()) {
5828 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5836 llvm::Value *ReductionsPtr;
5837 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5841 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
5849 InRedPrivs[Cnt]->getExprLoc()),
5851 Replacement.getAlignment());
5865 const Expr *IfCond =
nullptr;
5866 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
5867 if (
C->getNameModifier() == OMPD_unknown ||
5868 C->getNameModifier() == OMPD_task) {
5869 IfCond =
C->getCondition();
5876 Data.Tied = !S.getSingleClause<OMPUntiedClause>();
5880 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
5881 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
5884 SharedsTy, CapturedStruct, IfCond,
5894 CGM.getOpenMPRuntime().emitTaskyieldCall(*
this, S.getBeginLoc());
5898 const OMPMessageClause *MC = S.getSingleClause<OMPMessageClause>();
5899 Expr *ME = MC ? MC->getMessageString() :
nullptr;
5900 const OMPSeverityClause *SC = S.getSingleClause<OMPSeverityClause>();
5901 bool IsFatal =
false;
5902 if (!SC || SC->getSeverityKind() == OMPC_SEVERITY_fatal)
5904 CGM.getOpenMPRuntime().emitErrorCall(*
this, S.getBeginLoc(), ME, IsFatal);
5908 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_barrier);
5915 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
5916 CGM.getOpenMPRuntime().emitTaskwaitCall(*
this, S.getBeginLoc(),
Data);
5920 return T.clauses().empty();
5925 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
5927 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
5928 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5932 auto BodyGenCB = [&,
this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
5935 EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5936 return llvm::Error::success();
5941 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5942 cantFail(OMPBuilder.createTaskgroup(
Builder, AllocaIP,
5953 for (
const auto *
C : S.getClausesOfKind<OMPTaskReductionClause>()) {
5954 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5955 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5956 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5957 Data.ReductionOps.append(
C->reduction_ops().begin(),
5958 C->reduction_ops().end());
5959 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5960 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5962 llvm::Value *ReductionDesc =
5970 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5972 CGM.getOpenMPRuntime().emitTaskgroupRegion(*
this,
CodeGen, S.getBeginLoc());
5977 ? llvm::AtomicOrdering::NotAtomic
5978 : llvm::AtomicOrdering::AcquireRelease;
5979 CGM.getOpenMPRuntime().emitFlush(
5982 if (
const auto *FlushClause = S.getSingleClause<
OMPFlushClause>())
5984 FlushClause->varlist_end());
5987 S.getBeginLoc(), AO);
5997 for (
auto &Dep :
Data.Dependences) {
5998 Address DepAddr =
CGM.getOpenMPRuntime().emitDepobjDependClause(
5999 *
this, Dep, DC->getBeginLoc());
6005 CGM.getOpenMPRuntime().emitDestroyClause(*
this, DOLVal, DC->getBeginLoc());
6008 if (
const auto *UC = S.getSingleClause<OMPUpdateDependObjectsClause>()) {
6009 CGM.getOpenMPRuntime().emitUpdateDependObjectsClause(
6010 *
this, DOLVal, UC->getDependencyKind(), UC->getBeginLoc());
6028 for (
const auto *
C : ParentDir.getClausesOfKind<OMPReductionClause>()) {
6029 if (
C->getModifier() != OMPC_REDUCTION_inscan)
6031 Shareds.append(
C->varlist_begin(),
C->varlist_end());
6032 Privates.append(
C->privates().begin(),
C->privates().end());
6033 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
6034 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
6035 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
6036 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
6037 CopyArrayTemps.append(
C->copy_array_temps().begin(),
6038 C->copy_array_temps().end());
6039 CopyArrayElems.append(
C->copy_array_elems().begin(),
6040 C->copy_array_elems().end());
6042 if (ParentDir.getDirectiveKind() == OMPD_simd ||
6084 : BreakContinueStack.back().ContinueBlock.getBlock());
6095 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6097 const Expr *TempExpr = CopyArrayTemps[I];
6109 CGM.getOpenMPRuntime().emitReduction(
6110 *
this, ParentDir.getEndLoc(),
Privates, LHSs, RHSs, ReductionOps,
6113 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6121 const Expr *TempExpr = CopyArrayTemps[I];
6133 ? BreakContinueStack.back().ContinueBlock.getBlock()
6139 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6145 .getIterationVariable()
6146 ->IgnoreParenImpCasts();
6149 IdxVal = Builder.CreateIntCast(IdxVal,
SizeTy,
false);
6150 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6152 const Expr *OrigExpr = Shareds[I];
6153 const Expr *CopyArrayElem = CopyArrayElems[I];
6154 OpaqueValueMapping IdxMapping(
6167 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6170 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6176 .getIterationVariable()
6177 ->IgnoreParenImpCasts();
6181 llvm::BasicBlock *ExclusiveExitBB =
nullptr;
6185 llvm::Value *
Cmp =
Builder.CreateIsNull(IdxVal);
6186 Builder.CreateCondBr(
Cmp, ExclusiveExitBB, ContBB);
6189 IdxVal =
Builder.CreateNUWSub(IdxVal, llvm::ConstantInt::get(
SizeTy, 1));
6191 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6192 const Expr *PrivateExpr =
Privates[I];
6193 const Expr *OrigExpr = Shareds[I];
6194 const Expr *CopyArrayElem = CopyArrayElems[I];
6203 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
6235 bool HasLastprivateClause =
false;
6238 OMPLoopScope PreInitScope(*
this, S);
6243 llvm::BasicBlock *ContBlock =
nullptr;
6281 CGM.getOpenMPRuntime().emitBarrierCall(
6282 *
this, S.getBeginLoc(), OMPD_unknown,
false,
6294 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
6297 llvm::Value *Chunk =
nullptr;
6300 ScheduleKind =
C->getDistScheduleKind();
6301 if (
const Expr *Ch =
C->getChunkSize()) {
6309 CGM.getOpenMPRuntime().getDefaultDistScheduleAndChunk(
6310 *
this, S, ScheduleKind, Chunk);
6331 bool StaticChunked =
6335 Chunk !=
nullptr) ||
6340 StaticChunked ? Chunk :
nullptr);
6394 [&S, &LoopScope, Cond, IncExpr,
LoopExit, &CodeGenLoop,
6397 S, LoopScope.requiresCleanups(), Cond, IncExpr,
6398 [&S,
LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
6399 CodeGenLoop(CGF, S, LoopExit);
6401 [&S, StaticChunked](CodeGenFunction &CGF) {
6402 if (StaticChunked) {
6403 CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound());
6404 CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound());
6405 CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound());
6406 CGF.EmitIgnoredExpr(S.getCombinedInit());
6416 const OMPLoopArguments LoopArguments = {
6419 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments,
6425 return CGF.
Builder.CreateIsNotNull(
6435 *
this, S, [IL, &S](CodeGenFunction &CGF) {
6436 return CGF.
Builder.CreateIsNotNull(
6441 if (HasLastprivateClause) {
6464 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
6473static llvm::Function *
6480 Fn->setDoesNotRecurse();
6484template <
typename T>
6486 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP,
6487 llvm::OpenMPIRBuilder &OMPBuilder) {
6489 unsigned NumLoops =
C->getNumLoops();
6493 for (
unsigned I = 0; I < NumLoops; I++) {
6494 const Expr *CounterVal =
C->getLoopData(I);
6499 StoreValues.emplace_back(StoreValue);
6501 OMPDoacrossKind<T> ODK;
6502 bool IsDependSource = ODK.isSource(
C);
6504 OMPBuilder.createOrderedDepend(CGF.
Builder, AllocaIP, NumLoops,
6505 StoreValues,
".cnt.addr", IsDependSource));
6512 "Standalone ordered directive should have either depend or doacross "
6515 assert(!S.hasAssociatedStmt() &&
"No associated statement must be in "
6516 "ordered depend|doacross construct.");
6518 if (
CGM.getLangOpts().OpenMPIRBuilder) {
6519 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
6520 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6533 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6536 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6542 if (
CGM.getLangOpts().OpenMPIRBuilder) {
6543 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
6544 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6550 auto FiniCB = [
this](InsertPointTy IP) {
6552 return llvm::Error::success();
6555 auto BodyGenCB = [&S,
C,
this](InsertPointTy AllocIP,
6556 InsertPointTy CodeGenIP,
6562 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
6563 Builder,
false,
".ordered.after");
6567 assert(S.getBeginLoc().isValid() &&
6568 "Outlined function call location must be valid.");
6571 OutlinedFn, CapturedVars);
6576 return llvm::Error::success();
6579 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6580 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
6581 OMPBuilder.createOrderedThreadsSimd(
Builder, BodyGenCB, FiniCB, !
C));
6587 auto &&
CodeGen = [&S,
C,
this](CodeGenFunction &CGF,
6592 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
6594 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
6595 OutlinedFn, CapturedVars);
6601 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6602 CGM.getOpenMPRuntime().emitOrderedRegion(*
this,
CodeGen, S.getBeginLoc(), !
C);
6609 "DestType must have scalar evaluation kind.");
6610 assert(!Val.
isAggregate() &&
"Must be a scalar or complex.");
6621 "DestType must have complex evaluation kind.");
6630 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
6632 assert(Val.
isComplex() &&
"Must be a scalar or complex.");
6637 Val.
getComplexVal().first, SrcElementType, DestElementType, Loc);
6639 Val.
getComplexVal().second, SrcElementType, DestElementType, Loc);
6645 LValue LVal,
RValue RVal) {
6646 if (LVal.isGlobalReg())
6653 llvm::AtomicOrdering AO, LValue LVal,
6655 if (LVal.isGlobalReg())
6658 LVal, Loc, llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO),
6667 *
this, RVal, RValTy, LVal.
getType(), Loc)),
6676 llvm_unreachable(
"Must be a scalar or complex.");
6684 assert(
V->isLValue() &&
"V of 'omp atomic read' is not lvalue");
6685 assert(
X->isLValue() &&
"X of 'omp atomic read' is not lvalue");
6694 case llvm::AtomicOrdering::Acquire:
6695 case llvm::AtomicOrdering::AcquireRelease:
6696 case llvm::AtomicOrdering::SequentiallyConsistent:
6698 llvm::AtomicOrdering::Acquire);
6700 case llvm::AtomicOrdering::Monotonic:
6701 case llvm::AtomicOrdering::Release:
6703 case llvm::AtomicOrdering::NotAtomic:
6704 case llvm::AtomicOrdering::Unordered:
6705 llvm_unreachable(
"Unexpected ordering.");
6712 llvm::AtomicOrdering AO,
const Expr *
X,
6715 assert(
X->isLValue() &&
"X of 'omp atomic write' is not lvalue");
6723 case llvm::AtomicOrdering::Release:
6724 case llvm::AtomicOrdering::AcquireRelease:
6725 case llvm::AtomicOrdering::SequentiallyConsistent:
6727 llvm::AtomicOrdering::Release);
6729 case llvm::AtomicOrdering::Acquire:
6730 case llvm::AtomicOrdering::Monotonic:
6732 case llvm::AtomicOrdering::NotAtomic:
6733 case llvm::AtomicOrdering::Unordered:
6734 llvm_unreachable(
"Unexpected ordering.");
6741 llvm::AtomicOrdering AO,
6742 bool IsXLHSInRHSPart) {
6747 if (BO == BO_Comma || !
Update.isScalar() || !
X.isSimple() ||
6749 (
Update.getScalarVal()->getType() !=
X.getAddress().getElementType())) ||
6750 !Context.getTargetInfo().hasBuiltinAtomic(
6751 Context.getTypeSize(
X.getType()), Context.toBits(
X.getAlignment())))
6752 return std::make_pair(
false,
RValue::get(
nullptr));
6755 if (
T->isIntegerTy())
6758 if (
T->isFloatingPointTy() && (BO == BO_Add || BO == BO_Sub))
6764 if (!CheckAtomicSupport(
Update.getScalarVal()->getType(), BO) ||
6765 !CheckAtomicSupport(
X.getAddress().getElementType(), BO))
6766 return std::make_pair(
false,
RValue::get(
nullptr));
6768 bool IsInteger =
X.getAddress().getElementType()->isIntegerTy();
6769 llvm::AtomicRMWInst::BinOp RMWOp;
6772 RMWOp = IsInteger ? llvm::AtomicRMWInst::Add : llvm::AtomicRMWInst::FAdd;
6775 if (!IsXLHSInRHSPart)
6776 return std::make_pair(
false,
RValue::get(
nullptr));
6777 RMWOp = IsInteger ? llvm::AtomicRMWInst::Sub : llvm::AtomicRMWInst::FSub;
6780 RMWOp = llvm::AtomicRMWInst::And;
6783 RMWOp = llvm::AtomicRMWInst::Or;
6786 RMWOp = llvm::AtomicRMWInst::Xor;
6790 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6791 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Min
6792 : llvm::AtomicRMWInst::Max)
6793 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMin
6794 : llvm::AtomicRMWInst::UMax);
6796 RMWOp = IsXLHSInRHSPart ? llvm::AtomicRMWInst::FMin
6797 : llvm::AtomicRMWInst::FMax;
6801 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6802 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Max
6803 : llvm::AtomicRMWInst::Min)
6804 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMax
6805 : llvm::AtomicRMWInst::UMin);
6807 RMWOp = IsXLHSInRHSPart ? llvm::AtomicRMWInst::FMax
6808 : llvm::AtomicRMWInst::FMin;
6811 RMWOp = llvm::AtomicRMWInst::Xchg;
6820 return std::make_pair(
false,
RValue::get(
nullptr));
6839 llvm_unreachable(
"Unsupported atomic update operation");
6841 llvm::Value *UpdateVal =
Update.getScalarVal();
6842 if (
auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
6844 UpdateVal = CGF.
Builder.CreateIntCast(
6845 IC,
X.getAddress().getElementType(),
6846 X.getType()->hasSignedIntegerRepresentation());
6848 UpdateVal = CGF.
Builder.CreateCast(llvm::Instruction::CastOps::UIToFP, IC,
6849 X.getAddress().getElementType());
6851 llvm::AtomicRMWInst *Res =
6868 if (
X.isGlobalReg()) {
6881 llvm::AtomicOrdering AO,
const Expr *
X,
6885 "Update expr in 'atomic update' must be a binary operator.");
6893 assert(
X->isLValue() &&
"X of 'omp atomic update' is not lvalue");
6900 auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](
RValue XRValue) {
6906 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
6913 case llvm::AtomicOrdering::Release:
6914 case llvm::AtomicOrdering::AcquireRelease:
6915 case llvm::AtomicOrdering::SequentiallyConsistent:
6917 llvm::AtomicOrdering::Release);
6919 case llvm::AtomicOrdering::Acquire:
6920 case llvm::AtomicOrdering::Monotonic:
6922 case llvm::AtomicOrdering::NotAtomic:
6923 case llvm::AtomicOrdering::Unordered:
6924 llvm_unreachable(
"Unexpected ordering.");
6942 llvm_unreachable(
"Must be a scalar or complex.");
6946 llvm::AtomicOrdering AO,
6947 bool IsPostfixUpdate,
const Expr *
V,
6949 const Expr *UE,
bool IsXLHSInRHSPart,
6951 assert(
X->isLValue() &&
"X of 'omp atomic capture' is not lvalue");
6952 assert(
V->isLValue() &&
"V of 'omp atomic capture' is not lvalue");
6961 "Update expr in 'atomic capture' must be a binary operator.");
6972 NewVValType = XRValExpr->
getType();
6974 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
6975 IsPostfixUpdate](
RValue XRValue) {
6979 NewVVal = IsPostfixUpdate ? XRValue : Res;
6983 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
6987 if (IsPostfixUpdate) {
6989 NewVVal = Res.second;
7000 NewVValType =
X->getType().getNonReferenceType();
7002 X->getType().getNonReferenceType(), Loc);
7003 auto &&Gen = [&NewVVal, ExprRValue](
RValue XRValue) {
7009 XLValue, ExprRValue, BO_Assign,
false, AO,
7014 NewVVal = IsPostfixUpdate ? Res.second : ExprRValue;
7030 case llvm::AtomicOrdering::Release:
7032 llvm::AtomicOrdering::Release);
7034 case llvm::AtomicOrdering::Acquire:
7036 llvm::AtomicOrdering::Acquire);
7038 case llvm::AtomicOrdering::AcquireRelease:
7039 case llvm::AtomicOrdering::SequentiallyConsistent:
7041 CGF, {}, Loc, llvm::AtomicOrdering::AcquireRelease);
7043 case llvm::AtomicOrdering::Monotonic:
7045 case llvm::AtomicOrdering::NotAtomic:
7046 case llvm::AtomicOrdering::Unordered:
7047 llvm_unreachable(
"Unexpected ordering.");
7053 CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO,
7055 const Expr *CE,
bool IsXBinopExpr,
bool IsPostfixUpdate,
bool IsFailOnly,
7057 llvm::OpenMPIRBuilder &OMPBuilder =
7060 OMPAtomicCompareOp Op;
7064 Op = OMPAtomicCompareOp::EQ;
7067 Op = OMPAtomicCompareOp::MIN;
7070 Op = OMPAtomicCompareOp::MAX;
7073 llvm_unreachable(
"unsupported atomic compare binary operator");
7077 Address XAddr = XLVal.getAddress();
7079 auto EmitRValueWithCastIfNeeded = [&CGF, Loc](
const Expr *
X,
const Expr *E) {
7084 if (NewE->
getType() ==
X->getType())
7089 llvm::Value *EVal = EmitRValueWithCastIfNeeded(
X, E);
7090 llvm::Value *DVal = D ? EmitRValueWithCastIfNeeded(
X, D) :
nullptr;
7091 if (
auto *CI = dyn_cast<llvm::ConstantInt>(EVal))
7092 EVal = CGF.
Builder.CreateIntCast(
7093 CI, XLVal.getAddress().getElementType(),
7096 if (
auto *CI = dyn_cast<llvm::ConstantInt>(DVal))
7097 DVal = CGF.
Builder.CreateIntCast(
7098 CI, XLVal.getAddress().getElementType(),
7101 llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{
7103 X->getType()->hasSignedIntegerRepresentation(),
7104 X->getType().isVolatileQualified()};
7105 llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal;
7109 VOpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
7110 V->getType()->hasSignedIntegerRepresentation(),
7111 V->getType().isVolatileQualified()};
7116 ROpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
7117 R->getType()->hasSignedIntegerRepresentation(),
7118 R->getType().isVolatileQualified()};
7121 if (FailAO == llvm::AtomicOrdering::NotAtomic) {
7124 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
7125 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
7126 IsPostfixUpdate, IsFailOnly));
7128 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
7129 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
7130 IsPostfixUpdate, IsFailOnly, FailAO));
7134 llvm::AtomicOrdering AO,
7135 llvm::AtomicOrdering FailAO,
bool IsPostfixUpdate,
7138 const Expr *CE,
bool IsXLHSInRHSPart,
7153 IsXLHSInRHSPart, Loc);
7155 case OMPC_compare: {
7157 IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly, Loc);
7161 llvm_unreachable(
"Clause is not allowed in 'omp atomic'.");
7166 llvm::AtomicOrdering AO =
CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
7168 llvm::AtomicOrdering FailAO = llvm::AtomicOrdering::NotAtomic;
7169 bool MemOrderingSpecified =
false;
7170 if (S.getSingleClause<OMPSeqCstClause>()) {
7171 AO = llvm::AtomicOrdering::SequentiallyConsistent;
7172 MemOrderingSpecified =
true;
7173 }
else if (S.getSingleClause<OMPAcqRelClause>()) {
7174 AO = llvm::AtomicOrdering::AcquireRelease;
7175 MemOrderingSpecified =
true;
7176 }
else if (S.getSingleClause<OMPAcquireClause>()) {
7177 AO = llvm::AtomicOrdering::Acquire;
7178 MemOrderingSpecified =
true;
7179 }
else if (S.getSingleClause<OMPReleaseClause>()) {
7180 AO = llvm::AtomicOrdering::Release;
7181 MemOrderingSpecified =
true;
7182 }
else if (S.getSingleClause<OMPRelaxedClause>()) {
7183 AO = llvm::AtomicOrdering::Monotonic;
7184 MemOrderingSpecified =
true;
7186 llvm::SmallSet<OpenMPClauseKind, 2> KindsEncountered;
7195 if (K == OMPC_seq_cst || K == OMPC_acq_rel || K == OMPC_acquire ||
7196 K == OMPC_release || K == OMPC_relaxed || K == OMPC_hint)
7199 KindsEncountered.insert(K);
7204 if (KindsEncountered.contains(OMPC_compare) &&
7205 KindsEncountered.contains(OMPC_capture))
7206 Kind = OMPC_compare;
7207 if (!MemOrderingSpecified) {
7208 llvm::AtomicOrdering DefaultOrder =
7209 CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
7210 if (DefaultOrder == llvm::AtomicOrdering::Monotonic ||
7211 DefaultOrder == llvm::AtomicOrdering::SequentiallyConsistent ||
7212 (DefaultOrder == llvm::AtomicOrdering::AcquireRelease &&
7213 Kind == OMPC_capture)) {
7215 }
else if (DefaultOrder == llvm::AtomicOrdering::AcquireRelease) {
7216 if (Kind == OMPC_unknown || Kind == OMPC_update || Kind == OMPC_write) {
7217 AO = llvm::AtomicOrdering::Release;
7218 }
else if (Kind == OMPC_read) {
7219 assert(Kind == OMPC_read &&
"Unexpected atomic kind.");
7220 AO = llvm::AtomicOrdering::Acquire;
7225 if (KindsEncountered.contains(OMPC_compare) &&
7226 KindsEncountered.contains(OMPC_fail)) {
7227 Kind = OMPC_compare;
7228 const auto *FailClause = S.getSingleClause<OMPFailClause>();
7231 if (FailParameter == llvm::omp::OMPC_relaxed)
7232 FailAO = llvm::AtomicOrdering::Monotonic;
7233 else if (FailParameter == llvm::omp::OMPC_acquire)
7234 FailAO = llvm::AtomicOrdering::Acquire;
7235 else if (FailParameter == llvm::omp::OMPC_seq_cst)
7236 FailAO = llvm::AtomicOrdering::SequentiallyConsistent;
7256 OMPLexicalScope
Scope(CGF, S, OMPD_target);
7259 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
7265 llvm::Function *Fn =
nullptr;
7266 llvm::Constant *FnID =
nullptr;
7268 const Expr *IfCond =
nullptr;
7270 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7271 if (
C->getNameModifier() == OMPD_unknown ||
7272 C->getNameModifier() == OMPD_target) {
7273 IfCond =
C->getCondition();
7279 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device(
7282 Device.setPointerAndInt(
C->getDevice(),
C->getModifier());
7287 bool IsOffloadEntry =
true;
7291 IsOffloadEntry =
false;
7294 IsOffloadEntry =
false;
7296 if (
CGM.
getLangOpts().OpenMPOffloadMandatory && !IsOffloadEntry) {
7300 assert(CGF.
CurFuncDecl &&
"No parent declaration for target region!");
7301 StringRef ParentName;
7304 if (
const auto *D = dyn_cast<CXXConstructorDecl>(CGF.
CurFuncDecl))
7306 else if (
const auto *D = dyn_cast<CXXDestructorDecl>(CGF.
CurFuncDecl))
7315 OMPLexicalScope
Scope(CGF, S, OMPD_task);
7316 auto &&SizeEmitter =
7319 if (IsOffloadEntry) {
7320 OMPLoopScope PreInitScope(CGF, D);
7323 NumIterations = CGF.
Builder.CreateIntCast(NumIterations, CGF.
Int64Ty,
7325 return NumIterations;
7343 CGF.
EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
7348 StringRef ParentName,
7354 llvm::Constant *
Addr;
7356 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7358 assert(Fn &&
Addr &&
"Target device function emission failed.");
7372 const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams);
7373 llvm::Function *OutlinedFn =
7378 OMPTeamsScope
Scope(CGF, S);
7383 const Expr *NumTeams = NT ? NT->getNumTeams().front() :
nullptr;
7384 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() :
nullptr;
7391 const Expr *IfCond =
nullptr;
7392 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7393 if (
C->getNameModifier() == OMPD_unknown ||
7394 C->getNameModifier() == OMPD_teams) {
7395 IfCond =
C->getCondition();
7404 const llvm::APInt One(32, 1);
7411 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() :
nullptr;
7437 CGF.
EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt());
7442 [](CodeGenFunction &) {
return nullptr; });
7447 auto *CS = S.getCapturedStmt(OMPD_teams);
7474 llvm::Constant *
Addr;
7476 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7478 assert(Fn &&
Addr &&
"Target device function emission failed.");
7520 llvm::Constant *
Addr;
7522 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7524 assert(Fn &&
Addr &&
"Target device function emission failed.");
7566 llvm::Constant *
Addr;
7568 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7570 assert(Fn &&
Addr &&
"Target device function emission failed.");
7584 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7589 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7601 [](CodeGenFunction &) {
return nullptr; });
7606 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7611 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7623 [](CodeGenFunction &) {
return nullptr; });
7628 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7634 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7646 [](CodeGenFunction &) {
return nullptr; });
7651 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7657 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7664 CGF, OMPD_distribute, CodeGenDistribute,
false);
7670 [](CodeGenFunction &) {
return nullptr; });
7674 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7675 llvm::Value *
Device =
nullptr;
7676 llvm::Value *NumDependences =
nullptr;
7677 llvm::Value *DependenceList =
nullptr;
7685 if (!
Data.Dependences.empty()) {
7687 std::tie(NumDependences, DependenciesArray) =
7688 CGM.getOpenMPRuntime().emitDependClause(*
this,
Data.Dependences,
7692 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
7697 "OMPNowaitClause clause is used separately in OMPInteropDirective.");
7700 if (!ItOMPInitClause.empty()) {
7703 llvm::Value *InteropvarPtr =
7705 llvm::omp::OMPInteropType InteropType =
7706 llvm::omp::OMPInteropType::Unknown;
7707 if (
C->getIsTarget()) {
7708 InteropType = llvm::omp::OMPInteropType::Target;
7710 assert(
C->getIsTargetSync() &&
7711 "Expected interop-type target/targetsync");
7712 InteropType = llvm::omp::OMPInteropType::TargetSync;
7714 OMPBuilder.createOMPInteropInit(
Builder, InteropvarPtr, InteropType,
7715 Device, NumDependences, DependenceList,
7716 Data.HasNowaitClause);
7720 if (!ItOMPDestroyClause.empty()) {
7723 llvm::Value *InteropvarPtr =
7725 OMPBuilder.createOMPInteropDestroy(
Builder, InteropvarPtr,
Device,
7726 NumDependences, DependenceList,
7727 Data.HasNowaitClause);
7730 auto ItOMPUseClause = S.getClausesOfKind<
OMPUseClause>();
7731 if (!ItOMPUseClause.empty()) {
7734 llvm::Value *InteropvarPtr =
7736 OMPBuilder.createOMPInteropUse(
Builder, InteropvarPtr,
Device,
7737 NumDependences, DependenceList,
7738 Data.HasNowaitClause);
7760 CGF, OMPD_distribute, CodeGenDistribute,
false);
7779 llvm::Constant *
Addr;
7781 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7783 assert(Fn &&
Addr &&
"Target device function emission failed.");
7812 CGF, OMPD_distribute, CodeGenDistribute,
false);
7831 llvm::Constant *
Addr;
7833 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7835 assert(Fn &&
Addr &&
"Target device function emission failed.");
7848 CGM.getOpenMPRuntime().emitCancellationPointCall(*
this, S.getBeginLoc(),
7853 const Expr *IfCond =
nullptr;
7854 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7855 if (
C->getNameModifier() == OMPD_unknown ||
7856 C->getNameModifier() == OMPD_cancel) {
7857 IfCond =
C->getCondition();
7861 if (
CGM.getLangOpts().OpenMPIRBuilder) {
7862 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7868 llvm::Value *IfCondition =
nullptr;
7872 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
7874 return Builder.restoreIP(AfterIP);
7878 CGM.getOpenMPRuntime().emitCancelCall(*
this, S.getBeginLoc(), IfCond,
7884 if (Kind == OMPD_parallel || Kind == OMPD_task ||
7885 Kind == OMPD_target_parallel || Kind == OMPD_taskloop ||
7886 Kind == OMPD_master_taskloop || Kind == OMPD_parallel_master_taskloop)
7888 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
7889 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
7890 Kind == OMPD_distribute_parallel_for ||
7891 Kind == OMPD_target_parallel_for ||
7892 Kind == OMPD_teams_distribute_parallel_for ||
7893 Kind == OMPD_target_teams_distribute_parallel_for);
7894 return OMPCancelStack.getExitBlock();
7899 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7900 CaptureDeviceAddrMap) {
7901 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7902 for (
const Expr *OrigVarIt :
C.varlist()) {
7904 if (!Processed.insert(OrigVD).second)
7911 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7916 "Base should be the current struct!");
7917 MatchingVD = ME->getMemberDecl();
7922 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7923 if (InitAddrIt == CaptureDeviceAddrMap.end())
7931 Address(InitAddrIt->second, Ty,
7933 assert(IsRegistered &&
"firstprivate var already registered as private");
7941 while (
const auto *OASE = dyn_cast<ArraySectionExpr>(
Base))
7942 Base = OASE->getBase()->IgnoreParenImpCasts();
7943 while (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(
Base))
7944 Base = ASE->getBase()->IgnoreParenImpCasts();
7950 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7951 CaptureDeviceAddrMap) {
7952 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7953 for (
const Expr *Ref :
C.varlist()) {
7955 if (!Processed.insert(OrigVD).second)
7961 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7966 "Base should be the current struct!");
7967 MatchingVD = ME->getMemberDecl();
7972 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7973 if (InitAddrIt == CaptureDeviceAddrMap.end())
7979 Address(InitAddrIt->second, Ty,
7992 (void)PrivateScope.
addPrivate(OrigVD, PrivAddr);
8000 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
8001 CGM.getOpenMPRuntime().registerVTable(S);
8009 bool PrivatizeDevicePointers =
false;
8011 bool &PrivatizeDevicePointers;
8014 explicit DevicePointerPrivActionTy(
bool &PrivatizeDevicePointers)
8015 : PrivatizeDevicePointers(PrivatizeDevicePointers) {}
8016 void Enter(CodeGenFunction &CGF)
override {
8017 PrivatizeDevicePointers =
true;
8020 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
8023 auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
8024 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
8028 auto &&PrivCodeGen = [&](CodeGenFunction &CGF,
PrePostActionTy &Action) {
8030 PrivatizeDevicePointers =
false;
8036 if (PrivatizeDevicePointers) {
8050 std::optional<OpenMPDirectiveKind> CaptureRegion;
8051 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
8054 for (
const Expr *E :
C->varlist()) {
8056 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
8060 for (
const Expr *E :
C->varlist()) {
8062 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
8066 CaptureRegion = OMPD_unknown;
8069 OMPLexicalScope
Scope(CGF, S, CaptureRegion);
8081 OMPLexicalScope
Scope(CGF, S);
8090 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
8096 const Expr *IfCond =
nullptr;
8098 IfCond =
C->getCondition();
8109 CGM.getOpenMPRuntime().emitTargetDataCalls(*
this, S, IfCond,
Device, RCG,
8117 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8121 const Expr *IfCond =
nullptr;
8123 IfCond =
C->getCondition();
8130 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8131 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8138 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8142 const Expr *IfCond =
nullptr;
8144 IfCond =
C->getCondition();
8151 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8152 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8159 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
8187 llvm::Constant *
Addr;
8189 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8191 assert(Fn &&
Addr &&
"Target device function emission failed.");
8211 CGF, OMPD_target_parallel_for, S.
hasCancel());
8227 llvm::Constant *
Addr;
8229 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8231 assert(Fn &&
Addr &&
"Target device function emission failed.");
8266 llvm::Constant *
Addr;
8268 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8270 assert(Fn &&
Addr &&
"Target device function emission failed.");
8292 const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop);
8295 OMPLexicalScope
Scope(*
this, S, OMPD_taskloop,
false);
8300 const Expr *IfCond =
nullptr;
8301 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
8302 if (
C->getNameModifier() == OMPD_unknown ||
8303 C->getNameModifier() == OMPD_taskloop) {
8304 IfCond =
C->getCondition();
8317 Data.Schedule.setInt(
false);
8320 (Clause->getModifier() == OMPC_GRAINSIZE_strict) ?
true :
false;
8323 Data.Schedule.setInt(
true);
8326 (Clause->getModifier() == OMPC_NUMTASKS_strict) ?
true :
false;
8340 llvm::BasicBlock *ContBlock =
nullptr;
8341 OMPLoopScope PreInitScope(CGF, S);
8342 if (CGF.ConstantFoldsToSimpleInteger(S.
getPreCond(), CondConstant)) {
8346 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock(
"taskloop.if.then");
8347 ContBlock = CGF.createBasicBlock(
"taskloop.if.end");
8349 CGF.getProfileCount(&S));
8350 CGF.EmitBlock(ThenBlock);
8351 CGF.incrementProfileCounter(&S);
8354 (void)CGF.EmitOMPLinearClauseInit(S);
8358 enum { LowerBound = 5, UpperBound, Stride, LastIter };
8360 auto *LBP = std::next(I, LowerBound);
8361 auto *UBP = std::next(I, UpperBound);
8362 auto *STP = std::next(I, Stride);
8363 auto *LIP = std::next(I, LastIter);
8371 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
8372 CGF.EmitOMPLinearClause(S, LoopScope);
8373 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
8378 CGF.EmitVarDecl(*IVDecl);
8379 CGF.EmitIgnoredExpr(S.
getInit());
8391 OMPLexicalScope
Scope(CGF, S, OMPD_taskloop,
false);
8401 [&S](CodeGenFunction &CGF) {
8402 emitOMPLoopBodyWithStopPoint(CGF, S,
8403 CodeGenFunction::JumpDest());
8405 [](CodeGenFunction &) {});
8410 CGF.EmitBranch(ContBlock);
8411 CGF.EmitBlock(ContBlock,
true);
8414 if (HasLastprivateClause) {
8415 CGF.EmitOMPLastprivateClauseFinal(
8417 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
8418 CGF.GetAddrOfLocalVar(*LIP),
false,
8419 (*LIP)->getType(), S.getBeginLoc())));
8422 CGF.EmitOMPLinearClauseFinal(S, [LIP, &S](CodeGenFunction &CGF) {
8423 return CGF.
Builder.CreateIsNotNull(
8425 (*LIP)->
getType(), S.getBeginLoc()));
8428 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
8429 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
8431 auto &&
CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
8433 OMPLoopScope PreInitScope(CGF, S);
8434 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S,
8435 OutlinedFn, SharedsTy,
8436 CapturedStruct, IfCond,
Data);
8438 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
8444 CGM.getOpenMPRuntime().emitTaskgroupRegion(
8446 [&S, &BodyGen, &TaskGen, &
Data](CodeGenFunction &CGF,
8466 OMPLexicalScope
Scope(*
this, S);
8478 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8479 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8490 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8491 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8502 OMPLexicalScope
Scope(*
this, S);
8503 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8514 OMPLexicalScope
Scope(*
this, S);
8515 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8521 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8526 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8527 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8539 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8544 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8545 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8557 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8562 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8563 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8575 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8580 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8581 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8595 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8599 const Expr *IfCond =
nullptr;
8601 IfCond =
C->getCondition();
8608 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8609 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8619 BindKind =
C->getBindKind();
8622 case OMPC_BIND_parallel:
8624 case OMPC_BIND_teams:
8626 case OMPC_BIND_thread:
8637 const auto *ForS = dyn_cast<ForStmt>(CS);
8648 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
8649 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_loop,
CodeGen);
8675 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
8680 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
8692 [](CodeGenFunction &) {
return nullptr; });
8697 std::string StatusMsg,
8701 StatusMsg +=
": DEVICE";
8703 StatusMsg +=
": HOST";
8710 llvm::dbgs() << StatusMsg <<
": " <<
FileName <<
": " << LineNo <<
"\n";
8733 CGF, OMPD_distribute, CodeGenDistribute,
false);
8762 CGF, OMPD_distribute, CodeGenDistribute,
false);
8795 llvm::Constant *
Addr;
8797 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8799 assert(Fn &&
Addr &&
8800 "Target device function emission failed for 'target teams loop'.");
8811 CGF, OMPD_target_parallel_loop,
false);
8827 llvm::Constant *
Addr;
8829 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8831 assert(Fn &&
Addr &&
"Target device function emission failed.");
8846 if (
const auto *SD = dyn_cast<OMPScanDirective>(&D)) {
8850 if (!D.hasAssociatedStmt() || !D.getAssociatedStmt())
8856 for (
const auto *
C : D.getClausesOfKind<OMPFirstprivateClause>()) {
8857 for (
const Expr *Ref :
C->varlist()) {
8861 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
8864 if (!CGF.LocalDeclMap.count(VD)) {
8876 if (
const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
8877 for (
const Expr *E : LD->counters()) {
8885 if (!CGF.LocalDeclMap.count(VD))
8889 for (
const auto *
C : D.getClausesOfKind<OMPOrderedClause>()) {
8890 if (!
C->getNumForLoops())
8892 for (
unsigned I = LD->getLoopsNumber(),
8893 E =
C->getLoopNumIterations().size();
8895 if (
const auto *VD = dyn_cast<OMPCapturedExprDecl>(
8898 if (!CGF.LocalDeclMap.count(VD))
8905 CGF.
EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
8908 if (D.getDirectiveKind() == OMPD_atomic ||
8909 D.getDirectiveKind() == OMPD_critical ||
8910 D.getDirectiveKind() == OMPD_section ||
8911 D.getDirectiveKind() == OMPD_master ||
8912 D.getDirectiveKind() == OMPD_masked ||
8913 D.getDirectiveKind() == OMPD_unroll ||
8914 D.getDirectiveKind() == OMPD_assume) {
8919 OMPSimdLexicalScope
Scope(*
this, D);
8920 CGM.getOpenMPRuntime().emitInlinedDirective(
8923 : D.getDirectiveKind(),
8931 for (
const auto *
C : S.getClausesOfKind<OMPHoldsClause>()) {
8932 const Expr *E =
C->getExpr();
8933 assert(E &&
"holds clause requires an expression");
Defines the clang::ASTContext interface.
static bool isAllocatableDecl(const VarDecl *VD)
static const VarDecl * getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE)
static void emitTargetRegion(CodeGenFunction &CGF, const OMPTargetDirective &S, PrePostActionTy &Action)
static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S, PrePostActionTy &Action)
static const VarDecl * getBaseDecl(const Expr *Ref)
static void emitTargetTeamsGenericLoopRegionAsParallel(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsGenericLoopDirective &S)
static void emitOMPAtomicReadExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, const Expr *X, const Expr *V, SourceLocation Loc)
static void emitOMPAtomicCaptureExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, bool IsPostfixUpdate, const Expr *V, const Expr *X, const Expr *E, const Expr *UE, bool IsXLHSInRHSPart, SourceLocation Loc)
static void emitScanBasedDirective(CodeGenFunction &CGF, const OMPLoopDirective &S, llvm::function_ref< llvm::Value *(CodeGenFunction &)> NumIteratorsGen, llvm::function_ref< void(CodeGenFunction &)> FirstGen, llvm::function_ref< void(CodeGenFunction &)> SecondGen)
Emits the code for the directive with inscan reductions.
static void emitSimpleAtomicStore(CodeGenFunction &CGF, llvm::AtomicOrdering AO, LValue LVal, RValue RVal)
static bool isSupportedByOpenMPIRBuilder(const OMPTaskgroupDirective &T)
static Address castValueFromUintptr(CodeGenFunction &CGF, SourceLocation Loc, QualType DstType, StringRef Name, LValue AddrLV)
static bool canEmitGPUFusedDistSchedule(const CodeGenModule &CGM, const OMPLoopDirective &S, OpenMPDirectiveKind DKind)
Whether a combined distribute parallel for may use the fused distr_static_chunk + static_chunkone sch...
static void emitDistributeParallelForDistributeInnerBoundParams(CodeGenFunction &CGF, const OMPExecutableDirective &S, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars)
static void emitScanBasedDirectiveFinals(CodeGenFunction &CGF, const OMPLoopDirective &S, llvm::function_ref< llvm::Value *(CodeGenFunction &)> NumIteratorsGen)
Copies final inscan reductions values to the original variables.
static void checkForLastprivateConditionalUpdate(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static std::pair< LValue, LValue > emitForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S)
The following two functions generate expressions for the loop lower and upper bounds in case of stati...
static void emitTargetParallelForRegion(CodeGenFunction &CGF, const OMPTargetParallelForDirective &S, PrePostActionTy &Action)
static llvm::Function * emitOutlinedFunctionPrologueAggregate(CodeGenFunction &CGF, FunctionArgList &Args, llvm::MapVector< const Decl *, std::pair< const VarDecl *, Address > > &LocalAddrs, llvm::DenseMap< const Decl *, std::pair< const Expr *, llvm::Value * > > &VLASizes, llvm::Value *&CXXThisValue, llvm::Value *&ContextV, const CapturedStmt &CS, SourceLocation Loc, StringRef FunctionName)
static LValue EmitOMPHelperVar(CodeGenFunction &CGF, const DeclRefExpr *Helper)
Emit a helper variable and return corresponding lvalue.
static void emitOMPAtomicUpdateExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, const Expr *X, const Expr *E, const Expr *UE, bool IsXLHSInRHSPart, SourceLocation Loc)
static llvm::Value * convertToScalarValue(CodeGenFunction &CGF, RValue Val, QualType SrcType, QualType DestType, SourceLocation Loc)
static llvm::Function * emitOutlinedOrderedFunction(CodeGenModule &CGM, const CapturedStmt *S, const OMPExecutableDirective &D)
static void emitPreCond(CodeGenFunction &CGF, const OMPLoopDirective &S, const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount)
static std::pair< bool, RValue > emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X, RValue Update, BinaryOperatorKind BO, llvm::AtomicOrdering AO, bool IsXLHSInRHSPart)
static std::pair< LValue, LValue > emitDistributeParallelForInnerBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitTargetTeamsGenericLoopRegionAsDistribute(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsGenericLoopDirective &S)
static void emitTargetParallelRegion(CodeGenFunction &CGF, const OMPTargetParallelDirective &S, PrePostActionTy &Action)
static std::pair< llvm::Value *, llvm::Value * > emitDispatchForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S, Address LB, Address UB)
When dealing with dispatch schedules (e.g.
static void emitMaster(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitRestoreIP(CodeGenFunction &CGF, const T *C, llvm::OpenMPIRBuilder::InsertPointTy AllocaIP, llvm::OpenMPIRBuilder &OMPBuilder)
static void emitCommonOMPTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, const RegionCodeGenTy &CodeGen)
static void emitSimdlenSafelenClause(CodeGenFunction &CGF, const OMPExecutableDirective &D)
static void emitAlignedClause(CodeGenFunction &CGF, const OMPExecutableDirective &D)
static bool isSimdSupportedByOpenMPIRBuilder(const OMPLoopDirective &S)
static void emitCommonOMPParallelDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, const CodeGenBoundParametersTy &CodeGenBoundParameters)
static void applyConservativeSimdOrderedDirective(const Stmt &AssociatedStmt, LoopInfoStack &LoopStack)
static bool emitWorksharingDirective(CodeGenFunction &CGF, const OMPLoopDirective &S, bool HasCancel)
static void emitPostUpdateForReductionClause(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
static void emitEmptyOrdered(CodeGenFunction &, SourceLocation Loc, const unsigned IVSize, const bool IVSigned)
static void emitTargetTeamsLoopCodegenStatus(CodeGenFunction &CGF, std::string StatusMsg, const OMPExecutableDirective &D)
static bool isForSupportedByOpenMPIRBuilder(const OMPLoopDirective &S, bool HasCancel)
static RValue emitSimpleAtomicLoad(CodeGenFunction &CGF, llvm::AtomicOrdering AO, LValue LVal, SourceLocation Loc)
static std::pair< llvm::Value *, llvm::Value * > emitDistributeParallelForDispatchBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S, Address LB, Address UB)
if the 'for' loop has a dispatch schedule (e.g.
static bool hasOrderedBlockAssocDirective(const Stmt *S)
static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO, bool IsPostfixUpdate, const Expr *X, const Expr *V, const Expr *R, const Expr *E, const Expr *UE, const Expr *D, const Expr *CE, bool IsXLHSInRHSPart, bool IsFailOnly, SourceLocation Loc)
static CodeGenFunction::ComplexPairTy convertToComplexValue(CodeGenFunction &CGF, RValue Val, QualType SrcType, QualType DestType, SourceLocation Loc)
static ImplicitParamDecl * createImplicitFirstprivateForType(ASTContext &C, OMPTaskDataTy &Data, QualType Ty, CapturedDecl *CD, SourceLocation Loc)
static EmittedClosureTy emitCapturedStmtFunc(CodeGenFunction &ParentCGF, const CapturedStmt *S)
Emit a captured statement and return the function as well as its captured closure context.
static void emitOMPLoopBodyWithStopPoint(CodeGenFunction &CGF, const OMPLoopDirective &S, CodeGenFunction::JumpDest LoopExit)
static void emitOMPDistributeDirective(const OMPLoopDirective &S, CodeGenFunction &CGF, CodeGenModule &CGM)
static void emitOMPCopyinClause(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitTargetTeamsDistributeParallelForRegion(CodeGenFunction &CGF, const OMPTargetTeamsDistributeParallelForDirective &S, PrePostActionTy &Action)
static llvm::CallInst * emitCapturedStmtCall(CodeGenFunction &ParentCGF, EmittedClosureTy Cap, llvm::ArrayRef< llvm::Value * > Args)
Emit a call to a previously captured closure.
static void emitMasked(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitBody(CodeGenFunction &CGF, const Stmt *S, const Stmt *NextLoop, int MaxLevel, int Level=0)
static void emitOMPForDirective(const OMPLoopDirective &S, CodeGenFunction &CGF, CodeGenModule &CGM, bool HasCancel)
static void emitEmptyBoundParameters(CodeGenFunction &, const OMPExecutableDirective &, llvm::SmallVectorImpl< llvm::Value * > &)
static void emitTargetParallelForSimdRegion(CodeGenFunction &CGF, const OMPTargetParallelForSimdDirective &S, PrePostActionTy &Action)
static void emitOMPSimdDirective(const OMPLoopDirective &S, CodeGenFunction &CGF, CodeGenModule &CGM)
static void emitOMPAtomicCompareExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO, const Expr *X, const Expr *V, const Expr *R, const Expr *E, const Expr *D, const Expr *CE, bool IsXBinopExpr, bool IsPostfixUpdate, bool IsFailOnly, SourceLocation Loc)
std::pair< llvm::Function *, llvm::Value * > EmittedClosureTy
static OpenMPDirectiveKind getEffectiveDirectiveKind(const OMPExecutableDirective &S)
static void emitTargetTeamsRegion(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsDirective &S)
static void buildDependences(const OMPExecutableDirective &S, OMPTaskDataTy &Data)
static RValue convertToType(CodeGenFunction &CGF, RValue Value, QualType SourceType, QualType ResType, SourceLocation Loc)
static void emitScanBasedDirectiveDecls(CodeGenFunction &CGF, const OMPLoopDirective &S, llvm::function_ref< llvm::Value *(CodeGenFunction &)> NumIteratorsGen)
Emits internal temp array declarations for the directive with inscan reductions.
static void emitTargetTeamsDistributeParallelForSimdRegion(CodeGenFunction &CGF, const OMPTargetTeamsDistributeParallelForSimdDirective &S, PrePostActionTy &Action)
static void emitTargetTeamsDistributeSimdRegion(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsDistributeSimdDirective &S)
static llvm::MapVector< llvm::Value *, llvm::Value * > GetAlignedMapping(const OMPLoopDirective &S, CodeGenFunction &CGF)
static llvm::omp::ScheduleKind convertClauseKindToSchedKind(OpenMPScheduleClauseKind ScheduleClauseKind)
static void mapParam(CodeGenFunction &CGF, const DeclRefExpr *Helper, const ImplicitParamDecl *PVD, CodeGenFunction::OMPPrivateScope &Privates)
Emit a helper variable and return corresponding lvalue.
static void emitCommonOMPTeamsDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
static void emitTargetParallelGenericLoopRegion(CodeGenFunction &CGF, const OMPTargetParallelGenericLoopDirective &S, PrePostActionTy &Action)
static QualType getCanonicalParamType(ASTContext &C, QualType T)
static void emitCommonSimdLoop(CodeGenFunction &CGF, const OMPLoopDirective &S, const RegionCodeGenTy &SimdInitGen, const RegionCodeGenTy &BodyCodeGen)
static LValue createSectionLVal(CodeGenFunction &CGF, QualType Ty, const Twine &Name, llvm::Value *Init=nullptr)
static void emitOMPAtomicWriteExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, const Expr *X, const Expr *E, SourceLocation Loc)
static llvm::Function * emitOutlinedFunctionPrologue(CodeGenFunction &CGF, FunctionArgList &Args, llvm::MapVector< const Decl *, std::pair< const VarDecl *, Address > > &LocalAddrs, llvm::DenseMap< const Decl *, std::pair< const Expr *, llvm::Value * > > &VLASizes, llvm::Value *&CXXThisValue, const FunctionOptions &FO)
static void emitInnerParallelForWhenCombined(CodeGenFunction &CGF, const OMPLoopDirective &S, CodeGenFunction::JumpDest LoopExit)
static void emitTargetTeamsDistributeRegion(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsDistributeDirective &S)
This file defines OpenMP nodes for declarative directives.
static const Decl * getCanonicalDecl(const Decl *D)
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
Defines the PrettyStackTraceEntry class, which is used to make crashes give more contextual informati...
Defines the SourceManager interface.
This file defines OpenMP AST classes for executable directives and clauses.
This represents clause 'aligned' in the 'pragma omp ...' directives.
This represents 'pragma omp atomic' directive.
Expr * getR()
Get 'r' part of the associated expression/statement.
Expr * getX()
Get 'x' part of the associated expression/statement.
bool isFailOnly() const
Return true if 'v' is updated only when the condition is evaluated false (compare capture only).
bool isPostfixUpdate() const
Return true if 'v' expression must be updated to original value of 'x', false if 'v' must be updated ...
Expr * getExpr()
Get 'expr' part of the associated expression/statement.
Expr * getV()
Get 'v' part of the associated expression/statement.
bool isXLHSInRHSPart() const
Return true if helper update expression has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' and...
Expr * getD()
Get 'd' part of the associated expression/statement.
Expr * getUpdateExpr()
Get helper expression of the form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or 'OpaqueValueExp...
Expr * getCondExpr()
Get the 'cond' part of the source atomic expression.
This represents 'pragma omp barrier' directive.
This represents 'bind' clause in the 'pragma omp ...' directives.
This represents 'pragma omp cancel' directive.
OpenMPDirectiveKind getCancelRegion() const
Get cancellation region for the current cancellation point.
This represents 'pragma omp cancellation point' directive.
OpenMPDirectiveKind getCancelRegion() const
Get cancellation region for the current cancellation point.
This represents clause 'copyin' in the 'pragma omp ...' directives.
This represents clause 'copyprivate' in the 'pragma omp ...' directives.
This represents 'pragma omp critical' directive.
DeclarationNameInfo getDirectiveName() const
Return name of the directive.
This represents implicit clause 'depend' for the 'pragma omp task' directive.
This represents implicit clause 'depobj' for the 'pragma omp depobj' directive. This clause does not ...
This represents 'pragma omp depobj' directive.
This represents 'destroy' clause in the 'pragma omp depobj' directive or the 'pragma omp interop' dir...
This represents 'device' clause in the 'pragma omp ...' directive.
This represents 'dist_schedule' clause in the 'pragma omp ...' directive.
This represents 'pragma omp distribute' directive.
This represents 'pragma omp distribute parallel for' composite directive.
This represents 'pragma omp distribute parallel for simd' composite directive.
This represents 'pragma omp distribute simd' composite directive.
This represents the 'doacross' clause for the 'pragma omp ordered' directive.
This represents 'pragma omp error' directive.
This represents 'filter' clause in the 'pragma omp ...' directive.
This represents implicit clause 'flush' for the 'pragma omp flush' directive. This clause does not ex...
This represents 'pragma omp flush' directive.
This represents 'pragma omp for' directive.
bool hasCancel() const
Return true if current directive has inner cancel directive.
This represents 'pragma omp for simd' directive.
Represents the 'pragma omp fuse' loop transformation directive.
Stmt * getTransformedStmt() const
Gets the associated loops after the transformation.
This represents 'pragma omp loop' directive.
This represents 'grainsize' clause in the 'pragma omp ...' directive.
This represents 'hint' clause in the 'pragma omp ...' directive.
This represents clause 'inclusive' in the 'pragma omp scan' directive.
This represents the 'init' clause in 'pragma omp ...' directives.
Represents the 'pragma omp interchange' loop transformation directive.
Stmt * getTransformedStmt() const
Gets the associated loops after the transformation.
This represents 'pragma omp interop' directive.
This is a common base class for loop directives ('omp simd', 'omp for', 'omp for simd' etc....
Expr * getCombinedUpperBoundVariable() const
Expr * getPreCond() const
Expr * getPrevUpperBoundVariable() const
Expr * getIsLastIterVariable() const
Expr * getCombinedLowerBoundVariable() const
Expr * getCombinedCond() const
Expr * getCombinedInit() const
Expr * getLowerBoundVariable() const
Expr * getCombinedNextLowerBound() const
ArrayRef< Expr * > finals_conditions()
ArrayRef< Expr * > counters()
ArrayRef< Expr * > private_counters()
Expr * getUpperBoundVariable() const
Expr * getCombinedDistCond() const
Expr * getPrevLowerBoundVariable() const
ArrayRef< Expr * > dependent_inits()
Expr * getNextLowerBound() const
Expr * getDistInc() const
ArrayRef< Expr * > updates()
Expr * getNextUpperBound() const
Expr * getLastIteration() const
Expr * getEnsureUpperBound() const
Expr * getCalcLastIteration() const
Expr * getCombinedNextUpperBound() const
Expr * getIterationVariable() const
Expr * getStrideVariable() const
Expr * getNumIterations() const
ArrayRef< Expr * > finals()
Expr * getPrevEnsureUpperBound() const
Expr * getCombinedEnsureUpperBound() const
ArrayRef< Expr * > dependent_counters()
ArrayRef< Expr * > inits()
This represents 'pragma omp masked' directive.
This represents 'pragma omp masked taskloop' directive.
This represents 'pragma omp masked taskloop simd' directive.
This represents 'pragma omp master' directive.
This represents 'pragma omp master taskloop' directive.
This represents 'pragma omp master taskloop simd' directive.
This represents 'nogroup' clause in the 'pragma omp ...' directive.
This represents 'num_tasks' clause in the 'pragma omp ...' directive.
This represents 'num_teams' clause in the 'pragma omp ...' directive.
This represents 'order' clause in the 'pragma omp ...' directive.
This represents block-associated 'pragma omp ordered' directive.
This represents standalone 'pragma omp ordered' directive.
This represents 'pragma omp parallel for' directive.
bool hasCancel() const
Return true if current directive has inner cancel directive.
This represents 'pragma omp parallel for simd' directive.
This represents 'pragma omp parallel masked' directive.
This represents 'pragma omp parallel masked taskloop' directive.
This represents 'pragma omp parallel masked taskloop simd' directive.
This represents 'pragma omp parallel master' directive.
This represents 'pragma omp parallel master taskloop' directive.
This represents 'pragma omp parallel master taskloop simd' directive.
This represents 'pragma omp parallel sections' directive.
This represents 'priority' clause in the 'pragma omp ...' directive.
Represents the 'pragma omp reverse' loop transformation directive.
Stmt * getTransformedStmt() const
Gets/sets the associated loops after the transformation, i.e.
This represents 'simd' clause in the 'pragma omp ...' directive.
This represents 'pragma omp scan' directive.
This represents 'pragma omp scope' directive.
This represents 'pragma omp section' directive.
This represents 'pragma omp sections' directive.
bool hasCancel() const
Return true if current directive has inner cancel directive.
This represents 'pragma omp simd' directive.
This represents 'pragma omp single' directive.
Represents the 'pragma omp split' loop transformation directive.
Stmt * getTransformedStmt() const
Gets/sets the associated loops after the transformation, i.e.
This represents the 'pragma omp stripe' loop transformation directive.
Stmt * getTransformedStmt() const
Gets/sets the associated loops after striping.
This represents 'pragma omp target data' directive.
This represents 'pragma omp target' directive.
This represents 'pragma omp target enter data' directive.
This represents 'pragma omp target exit data' directive.
This represents 'pragma omp target parallel' directive.
This represents 'pragma omp target parallel for' directive.
bool hasCancel() const
Return true if current directive has inner cancel directive.
This represents 'pragma omp target parallel for simd' directive.
This represents 'pragma omp target parallel loop' directive.
This represents 'pragma omp target simd' directive.
This represents 'pragma omp target teams' directive.
This represents 'pragma omp target teams distribute' combined directive.
This represents 'pragma omp target teams distribute parallel for' combined directive.
This represents 'pragma omp target teams distribute parallel for simd' combined directive.
This represents 'pragma omp target teams distribute simd' combined directive.
This represents 'pragma omp target teams loop' directive.
bool canBeParallelFor() const
Return true if current loop directive's associated loop can be a parallel for.
This represents 'pragma omp target update' directive.
This represents 'pragma omp task' directive.
This represents 'pragma omp taskloop' directive.
This represents 'pragma omp taskloop simd' directive.
This represents 'pragma omp taskgroup' directive.
const Expr * getReductionRef() const
Returns reference to the task_reduction return variable.
This represents 'pragma omp taskwait' directive.
This represents 'pragma omp taskyield' directive.
This represents 'pragma omp teams' directive.
This represents 'pragma omp teams distribute' directive.
This represents 'pragma omp teams distribute parallel for' composite directive.
This represents 'pragma omp teams distribute parallel for simd' composite directive.
This represents 'pragma omp teams distribute simd' combined directive.
This represents 'pragma omp teams loop' directive.
This represents 'thread_limit' clause in the 'pragma omp ...' directive.
This represents the 'pragma omp tile' loop transformation directive.
Stmt * getTransformedStmt() const
Gets/sets the associated loops after tiling.
This represents the 'pragma omp unroll' loop transformation directive.
This represents the 'use' clause in 'pragma omp ...' directives.
This represents clause 'use_device_addr' in the 'pragma omp ...' directives.
This represents clause 'use_device_ptr' in the 'pragma omp ...' directives.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
TranslationUnitDecl * getTranslationUnitDecl() const
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.
QualType getUIntPtrType() const
Return a type compatible with "uintptr_t" (C99 7.18.1.4), as defined by the target.
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
unsigned getOpenMPDefaultSimdAlign(QualType T) const
Get default simd alignment of the specified complete type in bits.
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
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.
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
CanQualType getCanonicalTagType(const TagDecl *TD) const
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Represents an attribute applied to a statement.
ArrayRef< const Attr * > getAttrs() const
static BinaryOperator * Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, FPOptionsOverride FPFeatures)
Represents the body of a CapturedStmt, and serves as its DeclContext.
unsigned getNumParams() const
ImplicitParamDecl * getContextParam() const
Retrieve the parameter containing captured variables.
unsigned getContextParamPosition() const
static CapturedDecl * Create(ASTContext &C, DeclContext *DC, unsigned NumParams)
param_iterator param_end() const
Retrieve an iterator one past the last parameter decl.
param_iterator param_begin() const
Retrieve an iterator pointing to the first parameter decl.
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
ImplicitParamDecl * getParam(unsigned i) const
This captures a statement into a function.
SourceLocation getEndLoc() const LLVM_READONLY
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
const RecordDecl * getCapturedRecordDecl() const
Retrieve the record declaration for captured variables.
Stmt * getCapturedStmt()
Retrieve the statement being captured.
capture_init_iterator capture_init_begin()
Retrieve the first initialization argument.
SourceLocation getBeginLoc() const LLVM_READONLY
capture_init_iterator capture_init_end()
Retrieve the iterator pointing one past the last initialization argument.
Expr *const * const_capture_init_iterator
Const iterator that walks over the capture initialization arguments.
CharUnits - This is an opaque type for sizes expressed in character units.
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 ...
std::string SampleProfileFile
Name of the profile file to use with -fprofile-sample-use.
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 withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
Address withAlignment(CharUnits NewAlignment) const
Return address with different alignment, but same pointer and element type.
llvm::PointerType * getType() const
Return the type of the pointer value.
static AggValueSlot ignored()
ignored - Returns an aggregate value slot indicating that the aggregate value is being ignored.
static ApplyDebugLocation CreateDefaultArtificial(CodeGenFunction &CGF, SourceLocation TemporaryLocation)
Apply TemporaryLocation if it is valid.
Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::LoadInst * CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr, CharUnits Align, const llvm::Twine &Name="")
CGFunctionInfo - Class to encapsulate the information about a function definition.
Manages list of lastprivate conditional decls for the specified directive.
static LastprivateConditionalRAII disable(CodeGenFunction &CGF, const OMPExecutableDirective &S)
Manages list of nontemporal decls for the specified directive.
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...
Manages list of nontemporal decls for the specified directive.
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.
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...
virtual void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr)
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
virtual void 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) ...
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...
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 const VarDecl * translateParameter(const FieldDecl *FD, const VarDecl *NativeParam) const
Translates the native parameter of outlined function if this is required for target.
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.
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...
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.
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,...
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.
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 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...
virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false)
Emit an implicit/explicit barrier for OpenMP threads.
virtual void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values)
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.
void emitIfClause(CodeGenFunction &CGF, const Expr *Cond, const RegionCodeGenTy &ThenGen, const RegionCodeGenTy &ElseGen)
Emits code for OpenMP 'if' clause using specified CodeGen function.
virtual llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP parallel directive D.
virtual void 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 bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static non-chunked.
virtual void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc)
Emits a master region.
virtual void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Required to resolve existing problems in the runtime.
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 ...
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 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 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.
virtual void emitInlinedDirective(CodeGenFunction &CGF, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool HasCancel=false)
Emit code for the directive that does not require outlining.
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 isDynamic(OpenMPScheduleClauseKind ScheduleKind) const
Check if the specified ScheduleKind is dynamic.
virtual void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr)
Emits a masked region.
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 getAllocatedAddress() const
Returns the raw, allocated address, which is not necessarily the address of the object itself.
API for captured statement code generation.
virtual const FieldDecl * lookup(const VarDecl *VD) const
Lookup the captured field decl for a variable.
RAII for correct setting/restoring of CapturedStmtInfo.
LValue getReferenceLValue(CodeGenFunction &CGF, const Expr *RefExpr) const
void ForceCleanup()
Force the emission of cleanups now, instead of waiting until this object is destroyed.
RAII for preserving necessary info during inlined region body codegen.
Cleanup action for allocate support.
RAII for preserving necessary info during Outlined region body codegen.
Controls insertion of cancellation exit blocks in worksharing constructs.
Save/restore original map of previously emitted local vars in case when we need to duplicate emission...
The class used to assign some variables some temporarily addresses.
bool apply(CodeGenFunction &CGF)
Applies new addresses to the list of the variables.
void restore(CodeGenFunction &CGF)
Restores original addresses of the variables.
bool setVarAddr(CodeGenFunction &CGF, const VarDecl *LocalVD, Address TempAddr)
Sets the address of the variable LocalVD to be TempAddr in function CGF.
The scope used to remap some variables as private in the OpenMP loop body (or other captured region e...
void restoreMap()
Restore all mapped variables w/o clean up.
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.
Manages parent directive for scan directives.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
void ForceCleanup(std::initializer_list< llvm::Value ** > ValuesToReload={})
Force the emission of cleanups now, instead of waiting until this object is destroyed.
bool requiresCleanups() const
Determine whether this scope requires any cleanups.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void EmitOMPParallelMaskedTaskLoopDirective(const OMPParallelMaskedTaskLoopDirective &S)
void EmitOMPParallelMaskedDirective(const OMPParallelMaskedDirective &S)
void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S)
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 EmitOMPLastprivateClauseFinal(const OMPExecutableDirective &D, bool NoFinals, llvm::Value *IsLastIterCond=nullptr)
Emit final copying of lastprivate values to original variables at the end of the worksharing or simd ...
void processInReduction(const OMPExecutableDirective &S, OMPTaskDataTy &Data, CodeGenFunction &CGF, const CapturedStmt *CS, OMPPrivateScope &Scope)
JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target)
The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...
void EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S)
void emitOMPSimpleStore(LValue LVal, RValue RVal, QualType RValTy, SourceLocation Loc)
static void EmitOMPTargetParallelDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelDirective &S)
void EmitOMPCanonicalLoop(const OMPCanonicalLoop *S)
Emit an OMPCanonicalLoop using the OpenMPIRBuilder.
void EmitOMPGenericLoopDirective(const OMPGenericLoopDirective &S)
void EmitOMPScanDirective(const OMPScanDirective &S)
static bool hasScalarEvaluationKind(QualType T)
llvm::function_ref< std::pair< llvm::Value *, llvm::Value * >(CodeGenFunction &, const OMPExecutableDirective &S, Address LB, Address UB)> CodeGenDispatchBoundsTy
LValue InitCapturedStruct(const CapturedStmt &S)
CGCapturedStmtInfo * CapturedStmtInfo
void EmitOMPDistributeDirective(const OMPDistributeDirective &S)
void EmitOMPParallelForDirective(const OMPParallelForDirective &S)
void EmitOMPMasterDirective(const OMPMasterDirective &S)
void EmitOMPParallelMasterTaskLoopSimdDirective(const OMPParallelMasterTaskLoopSimdDirective &S)
void EmitOMPSimdInit(const OMPLoopDirective &D)
Helpers for the OpenMP loop directives.
const OMPExecutableDirective * OMPParentLoopDirectiveForScan
Parent loop-based directive for scan directive.
void EmitOMPFlushDirective(const OMPFlushDirective &S)
static void EmitOMPTargetDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetDirective &S)
Emit device code for the target directive.
bool EmitOMPFirstprivateClause(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
void EmitOMPTaskgroupDirective(const OMPTaskgroupDirective &S)
void EmitOMPTargetTeamsDistributeParallelForSimdDirective(const OMPTargetTeamsDistributeParallelForSimdDirective &S)
static void EmitOMPTargetTeamsDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDirective &S)
Emit device code for the target teams directive.
void EmitOMPReductionClauseInit(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope, bool ForInscan=false)
Emit initial code for reduction variables.
void EmitOMPDistributeSimdDirective(const OMPDistributeSimdDirective &S)
void EmitAutoVarDecl(const VarDecl &D)
EmitAutoVarDecl - Emit an auto variable declaration.
static void EmitOMPTargetTeamsDistributeDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeDirective &S)
Emit device code for the target teams distribute directive.
llvm::Function * GenerateOpenMPCapturedStmtFunctionAggregate(const CapturedStmt &S, const OMPExecutableDirective &D)
void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
void EmitOMPTargetParallelForDirective(const OMPTargetParallelForDirective &S)
const LangOptions & getLangOpts() const
LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
EmitAutoVarAlloca - Emit the alloca and debug information for a local variable.
void EmitAtomicUpdate(LValue LVal, llvm::AtomicOrdering AO, const llvm::function_ref< RValue(RValue)> &UpdateOp, bool IsVolatile)
Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr)
Load a pointer with type PtrTy stored at address Ptr.
void EmitOMPSplitDirective(const OMPSplitDirective &S)
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
void EmitOMPReductionClauseFinal(const OMPExecutableDirective &D, const OpenMPDirectiveKind ReductionKind)
Emit final update of reduction values to original variables at the end of the directive.
void EmitOMPLoopBody(const OMPLoopDirective &D, JumpDest LoopExit)
Helper for the OpenMP loop directives.
void EmitOMPScopeDirective(const OMPScopeDirective &S)
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
llvm::AssertingVH< llvm::Instruction > AllocaInsertPt
AllocaInsertPoint - This is an instruction in the entry block before which we prefer to insert alloca...
void EmitAggregateAssign(LValue Dest, LValue Src, QualType EltTy)
Emit an aggregate assignment.
CodeGenFunction * ParentCGF
JumpDest ReturnBlock
ReturnBlock - Unified return block.
void EmitOMPTargetTeamsDistributeSimdDirective(const OMPTargetTeamsDistributeSimdDirective &S)
const llvm::function_ref< void(CodeGenFunction &, llvm::Function *, const OMPTaskDataTy &)> TaskGenTy
llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Location)
Converts Location to a DebugLoc, if debug information is enabled.
bool EmitOMPCopyinClause(const OMPExecutableDirective &D)
Emit code for copyin clause in D directive.
void EmitOMPLinearClause(const OMPLoopDirective &D, CodeGenFunction::OMPPrivateScope &PrivateScope)
Emit initial code for linear clauses.
llvm::BasicBlock * OMPBeforeScanBlock
void EmitOMPInterchangeDirective(const OMPInterchangeDirective &S)
void EmitOMPPrivateLoopCounters(const OMPLoopDirective &S, OMPPrivateScope &LoopScope)
Emit initial code for loop counters of loop-based directives.
void GenerateOpenMPCapturedVars(const CapturedStmt &S, SmallVectorImpl< llvm::Value * > &CapturedVars)
void EmitOMPDepobjDirective(const OMPDepobjDirective &S)
void EmitOMPMetaDirective(const OMPMetaDirective &S)
void EmitOMPCriticalDirective(const OMPCriticalDirective &S)
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
void EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S)
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
void EmitOMPCancelDirective(const OMPCancelDirective &S)
void EmitOMPBarrierDirective(const OMPBarrierDirective &S)
llvm::Value * EmitComplexToScalarConversion(ComplexPairTy Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified complex type to the specified destination type,...
bool EmitOMPWorksharingLoop(const OMPLoopDirective &S, Expr *EUB, const CodeGenLoopBoundsTy &CodeGenLoopBounds, const CodeGenDispatchBoundsTy &CGDispatchBounds)
Emit code for the worksharing loop-based directive.
LValue EmitOMPSharedLValue(const Expr *E)
Emits the lvalue for the expression with possibly captured variable.
llvm::CanonicalLoopInfo * EmitOMPCollapsedCanonicalLoopNest(const Stmt *S, int Depth)
Emit the Stmt S and return its topmost canonical loop, if any.
void EmitOMPSectionsDirective(const OMPSectionsDirective &S)
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 EmitOMPInteropDirective(const OMPInteropDirective &S)
void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S)
void EmitOMPTargetParallelDirective(const OMPTargetParallelDirective &S)
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)
void EmitOMPTargetParallelForSimdDirective(const OMPTargetParallelForSimdDirective &S)
void EmitOMPTargetParallelGenericLoopDirective(const OMPTargetParallelGenericLoopDirective &S)
Emit combined directive 'target parallel loop' as if its constituent constructs are 'target',...
void EmitOMPUseDeviceAddrClause(const OMPUseDeviceAddrClause &C, OMPPrivateScope &PrivateScope, const llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap)
void EmitOMPTeamsDistributeParallelForSimdDirective(const OMPTeamsDistributeParallelForSimdDirective &S)
void EmitOMPMaskedDirective(const OMPMaskedDirective &S)
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.
void EmitOMPTeamsDistributeSimdDirective(const OMPTeamsDistributeSimdDirective &S)
RValue EmitAtomicLoad(LValue LV, SourceLocation SL, AggValueSlot Slot=AggValueSlot::ignored())
void EmitOMPOrderedBlockAssocDirective(const OMPOrderedBlockAssocDirective &S)
CGDebugInfo * getDebugInfo()
void EmitOMPDistributeLoop(const OMPLoopDirective &S, const CodeGenLoopTy &CodeGenLoop, Expr *IncExpr)
Emit code for the distribute loop-based directive.
void EmitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective &S)
void EmitOMPReverseDirective(const OMPReverseDirective &S)
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
void EmitOMPCancellationPointDirective(const OMPCancellationPointDirective &S)
void EmitOMPTargetTeamsDistributeParallelForDirective(const OMPTargetTeamsDistributeParallelForDirective &S)
void EmitOMPMaskedTaskLoopDirective(const OMPMaskedTaskLoopDirective &S)
llvm::BasicBlock * OMPScanDispatch
llvm::function_ref< std::pair< LValue, LValue >(CodeGenFunction &, const OMPExecutableDirective &S)> CodeGenLoopBoundsTy
void EmitOMPTargetExitDataDirective(const OMPTargetExitDataDirective &S)
RawAddress CreateMemTempWithoutCast(QualType T, const Twine &Name="tmp")
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen without...
void EmitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &S)
void EmitOMPMaskedTaskLoopSimdDirective(const OMPMaskedTaskLoopSimdDirective &S)
std::pair< bool, RValue > EmitOMPAtomicSimpleUpdateExpr(LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart, llvm::AtomicOrdering AO, SourceLocation Loc, const llvm::function_ref< RValue(RValue)> CommonGen)
Emit atomic update code for constructs: X = X BO E or X = E BO E.
VlaSizePair getVLASize(const VariableArrayType *vla)
Returns an LLVM value that corresponds to the size, in non-variably-sized elements,...
void EmitOMPParallelDirective(const OMPParallelDirective &S)
void EmitOMPTaskDirective(const OMPTaskDirective &S)
void EmitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective &S)
void EmitOMPDistributeParallelForDirective(const OMPDistributeParallelForDirective &S)
void EmitOMPAssumeDirective(const OMPAssumeDirective &S)
int ExpectedOMPLoopDepth
Number of nested loop to be consumed by the last surrounding loop-associated directive.
void EmitOMPPrivateClause(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
void EmitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &S)
ASTContext & getContext() const
void EmitStopPoint(const Stmt *S)
EmitStopPoint - Emit a debug stoppoint if we are emitting debug info.
void EmitOMPTargetUpdateDirective(const OMPTargetUpdateDirective &S)
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 EmitOMPTargetTeamsGenericLoopDirective(const OMPTargetTeamsGenericLoopDirective &S)
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...
SmallVector< llvm::CanonicalLoopInfo *, 4 > OMPLoopNestStack
List of recently emitted OMPCanonicalLoops.
void EmitOMPTeamsDistributeParallelForDirective(const OMPTeamsDistributeParallelForDirective &S)
llvm::AtomicRMWInst * emitAtomicRMWInst(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val, llvm::AtomicOrdering Order=llvm::AtomicOrdering::SequentiallyConsistent, llvm::SyncScope::ID SSID=llvm::SyncScope::System, const AtomicExpr *AE=nullptr)
Emit an atomicrmw instruction, and applying relevant metadata when applicable.
void EmitOMPFuseDirective(const OMPFuseDirective &S)
void EmitOMPTargetTeamsDistributeDirective(const OMPTargetTeamsDistributeDirective &S)
void EmitOMPUseDevicePtrClause(const OMPUseDevicePtrClause &C, OMPPrivateScope &PrivateScope, const llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap)
RValue EmitAnyExpr(const Expr *E, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
EmitAnyExpr - Emit code to compute the specified expression which can have any type.
void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs={})
EmitStmt - Emit the code for the statement.
llvm::DenseMap< const ValueDecl *, FieldDecl * > LambdaCaptureFields
void EmitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &S)
llvm::Type * ConvertTypeForMem(QualType T)
void EmitOMPInnerLoop(const OMPExecutableDirective &S, bool RequiresCleanup, const Expr *LoopCond, const Expr *IncExpr, const llvm::function_ref< void(CodeGenFunction &)> BodyGen, const llvm::function_ref< void(CodeGenFunction &)> PostIncGen)
Emit inner loop of the worksharing/simd construct.
void EmitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective &S)
static void EmitOMPTargetTeamsDistributeParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForDirective &S)
void EmitOMPTargetDirective(const OMPTargetDirective &S)
static void EmitOMPTargetParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForSimdDirective &S)
Emit device code for the target parallel for simd directive.
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
llvm::BasicBlock * OMPScanExitBlock
void EmitOMPTeamsDirective(const OMPTeamsDirective &S)
void EmitSimpleOMPExecutableDirective(const OMPExecutableDirective &D)
Emit simple code for OpenMP directives in Simd-only mode.
void EmitOMPErrorDirective(const OMPErrorDirective &S)
void EmitOMPTargetTaskBasedDirective(const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen, OMPTargetDataInfo &InputInfo)
void EmitOMPParallelMaskedTaskLoopSimdDirective(const OMPParallelMaskedTaskLoopSimdDirective &S)
void EmitOMPTargetTeamsDirective(const OMPTargetTeamsDirective &S)
void EmitOMPTargetDataDirective(const OMPTargetDataDirective &S)
Address GenerateCapturedStmtArgument(const CapturedStmt &S)
bool EmitOMPLastprivateClauseInit(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
Emit initial code for lastprivate variables.
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)
void EmitOMPSimdDirective(const OMPSimdDirective &S)
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 EmitOMPParallelGenericLoopDirective(const OMPLoopDirective &S)
void EmitOMPTargetSimdDirective(const OMPTargetSimdDirective &S)
void EmitOMPTeamsGenericLoopDirective(const OMPTeamsGenericLoopDirective &S)
void EmitOMPOrderedStandaloneDirective(const OMPOrderedStandaloneDirective &S)
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
bool EmitOMPLinearClauseInit(const OMPLoopDirective &D)
Emit initial code for linear variables.
static void EmitOMPTargetParallelGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelGenericLoopDirective &S)
Emit device code for the target parallel loop directive.
void EmitOMPUnrollDirective(const OMPUnrollDirective &S)
void EmitOMPStripeDirective(const OMPStripeDirective &S)
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitOMPSingleDirective(const OMPSingleDirective &S)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
llvm::function_ref< void(CodeGenFunction &, SourceLocation, const unsigned, const bool)> CodeGenOrderedTy
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
llvm::Value * EmitFromMemory(llvm::Value *Value, QualType Ty)
EmitFromMemory - Change a scalar value from its memory representation to its value representation.
static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S)
Emit device code for the target simd directive.
llvm::Function * GenerateCapturedStmtFunction(const CapturedStmt &S)
Creates the outlined function for a CapturedStmt.
static void EmitOMPTargetParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForDirective &S)
Emit device code for the target parallel for directive.
uint64_t getProfileCount(const Stmt *S)
Get the profiler's count for the given statement.
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.
void EmitOMPTileDirective(const OMPTileDirective &S)
void EmitDecl(const Decl &D, bool EvaluateConditionDecl=false)
EmitDecl - Emit a declaration.
void EmitOMPAtomicDirective(const OMPAtomicDirective &S)
llvm::BasicBlock * OMPAfterScanBlock
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
ConstantEmission tryEmitAsConstant(const DeclRefExpr *RefExpr)
Try to emit a reference to the given value without producing it as an l-value.
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
void EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst)
Store of global named registers are always calls to intrinsics.
void EmitOMPParallelMasterTaskLoopDirective(const OMPParallelMasterTaskLoopDirective &S)
void EmitOMPDistributeParallelForSimdDirective(const OMPDistributeParallelForSimdDirective &S)
void EmitOMPSectionDirective(const OMPSectionDirective &S)
void EnsureInsertPoint()
EnsureInsertPoint - Ensure that an insertion point is defined so that emitted IR has a place to go.
void EmitOMPForSimdDirective(const OMPForSimdDirective &S)
llvm::LLVMContext & getLLVMContext()
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
void emitAlignmentAssumption(llvm::Value *PtrValue, QualType Ty, SourceLocation Loc, SourceLocation AssumptionLoc, llvm::Value *Alignment, llvm::Value *OffsetValue=nullptr)
static void EmitOMPTargetTeamsDistributeSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeSimdDirective &S)
Emit device code for the target teams distribute simd directive.
llvm::function_ref< void(CodeGenFunction &, const OMPLoopDirective &, JumpDest)> CodeGenLoopTy
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...
bool isTrivialInitializer(const Expr *Init)
Determine whether the given initializer is trivial in the sense that it requires no code to be genera...
void EmitOMPParallelMasterDirective(const OMPParallelMasterDirective &S)
void EmitOMPTaskBasedDirective(const OMPExecutableDirective &S, const OpenMPDirectiveKind CapturedRegion, const RegionCodeGenTy &BodyGen, const TaskGenTy &TaskGen, OMPTaskDataTy &Data)
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 EmitOMPForDirective(const OMPForDirective &S)
void EmitOMPLinearClauseFinal(const OMPLoopDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
Emit final code for linear clauses.
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...
void EmitOMPSimdFinal(const OMPLoopDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
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
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
CodeGenTypes & getTypes()
const llvm::DataLayout & getDataLayout() const
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
const llvm::Triple & getTriple() const
ASTContext & getContext() const
const CodeGenOptions & getCodeGenOpts() const
StringRef getMangledName(GlobalDecl GD)
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 CGFunctionInfo & arrangeDeviceKernelCallerDeclaration(QualType resultType, const FunctionArgList &args)
A device kernel caller function is an offload device entry point function with a target device depend...
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
llvm::Value * getPointer(CodeGenFunction &CGF) const
Address getAddress() const
void setAddress(Address address)
A stack of loop information corresponding to loop nesting levels.
void setVectorizeWidth(unsigned W)
Set the vectorize width for the next loop pushed.
void setParallel(bool Enable=true)
Set the next pushed loop as parallel.
void push(llvm::BasicBlock *Header, const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc)
Begin a new structured loop.
void setVectorizeEnable(bool Enable=true)
Set the next pushed loop 'vectorize.enable'.
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.
std::pair< llvm::Value *, llvm::Value * > getComplexVal() const
getComplexVal - Return the real/imag components of this complex value.
An abstract representation of an aligned address.
llvm::PointerType * getType() const
Return the type of the pointer value.
llvm::Value * getPointer() const
Class intended to support codegen of all kind of the reduction clauses.
LValue getSharedLValue(unsigned N) const
Returns LValue for the reduction item.
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.
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.
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 setAction(PrePostActionTy &Action) const
Complex values, per C99 6.2.5p11.
CompoundStmt - This represents a group of statements like { stmt stmt }.
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
A reference to a declared variable, function, enum, etc.
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Decl - This represents one declaration (or definition), e.g.
SourceLocation getBodyRBrace() const
getBodyRBrace - Gets the right brace of the body, if a body exists.
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
SourceLocation getLocation() const
The name of a declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreImplicitAsWritten() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
Represents a function declaration or definition.
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin=false, bool isInlineSpecified=false, bool hasWrittenPrototype=true, ConstexprSpecKind ConstexprKind=ConstexprSpecKind::Unspecified, const AssociatedConstraint &TrailingRequiresClause={})
GlobalDecl - represents a global declaration.
One of these records is kept for each identifier that is lexed.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
std::vector< llvm::Triple > OMPTargetTriples
Triples of the OpenMP targets that the host code codegen should take into account in order to generat...
Represents a point when we exit a loop.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
A C++ nested-name-specifier augmented with source location information.
This is a basic class for representing single OpenMP clause.
This represents 'final' clause in the 'pragma omp ...' directive.
Representation of the 'full' clause of the 'pragma omp unroll' directive.
This represents 'if' clause in the 'pragma omp ...' directive.
This represents 'num_threads' clause in the 'pragma omp ...' directive.
Representation of the 'partial' clause of the 'pragma omp unroll' directive.
This represents 'safelen' clause in the 'pragma omp ...' directive.
This represents 'simdlen' clause in the 'pragma omp ...' directive.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
PointerType - C99 6.7.5.1 - Pointer Declarators.
Represents an unpacked "presumed" location which can be presented to the user.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
If a crash happens while one of these objects are live, the message is printed out along with the spe...
A (possibly-)qualified type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Represents a struct/union/class.
unsigned getNumFields() const
Returns the number of fields (non-static data members) in this record.
field_range fields() const
field_iterator field_begin() const
Base for LValueReferenceType and RValueReferenceType.
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
A trivial tuple used to represent a source range.
Stmt - This represents one statement.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
SourceLocation getBeginLoc() const LLVM_READONLY
bool isPointerType() const
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isLValueReferenceType() const
bool isAnyComplexType() const
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
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.
static UnaryOperator * Create(const ASTContext &C, Expr *input, Opcode opc, QualType type, ExprValueKind VK, ExprObjectKind OK, SourceLocation l, bool CanOverflow, FPOptionsOverride FPFeatures)
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.
TLSKind getTLSKind() const
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
@ CInit
C-style initialization with assignment.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
const Expr * getInit() const
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
@ TLS_None
Not a TLS variable.
Represents a C array with a specified size that is not an integer-constant-expression.
Expr * getSizeExpr() const
@ 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 ...
@ Address
A pointer to a ValueDecl.
bool Inc(InterpState &S, CodePtr OpPC, bool CanOverflow)
1) Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value increased by ...
Top level wrappers for InstallAPI frontend operations.
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.
Privates[]
This class represents the 'transparent' clause in the 'pragma omp task' directive.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
@ OK_Ordinary
An ordinary object is located at an address in memory.
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ Tile
'tile' clause, allowed on 'loop' and Combined constructs.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_unknown
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
@ OMPC_DIST_SCHEDULE_unknown
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
bool isOpenMPGenericLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive constitutes a 'loop' directive in the outermost nest.
OpenMPBindClauseKind
OpenMP bindings for the 'bind' clause.
const FunctionProtoType * T
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
@ Dtor_Complete
Complete object dtor.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of the composite or combined directives that need loop ...
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.
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPNumThreadsClauseModifier
@ OMPC_NUMTHREADS_unknown
U cast(CodeGen::Address addr)
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
@ ThreadPrivateVar
Parameter for Thread private variable.
@ Other
Other implicit parameter.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
A jump destination is an abstract label, branching to which may require a jump out through normal cle...
llvm::BasicBlock * getBlock() const
static Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc)
Returns address of the threadprivate variable for the current thread.
llvm::OpenMPIRBuilder::InsertPointTy InsertPointTy
static void EmitOMPOutlinedRegionBody(CodeGenFunction &CGF, const Stmt *RegionBodyStmt, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Twine RegionName)
Emit the body of an OMP region that will be outlined in OpenMPIRBuilder::finalize().
static Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD)
Gets the OpenMP-specific address of the local variable /p VD.
static void EmitCaptureStmt(CodeGenFunction &CGF, InsertPointTy CodeGenIP, llvm::BasicBlock &FiniBB, llvm::Function *Fn, ArrayRef< llvm::Value * > Args)
static std::string getNameWithSeparators(ArrayRef< StringRef > Parts, StringRef FirstSeparator=".", StringRef Separator=".")
Get the platform-specific name separator.
static void FinalizeOMPRegion(CodeGenFunction &CGF, InsertPointTy IP)
Emit the Finalization for an OMP region.
static void EmitOMPInlinedRegionBody(CodeGenFunction &CGF, const Stmt *RegionBodyStmt, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Twine RegionName)
Emit the body of an OMP region.
unsigned NumberOfTargetItems
Address BasePointersArray
llvm::PointerType * VoidPtrTy
llvm::IntegerType * Int64Ty
llvm::IntegerType * SizeTy
SmallVector< const Expr *, 4 > DepExprs
std::string getAsString() const
getAsString - Retrieve the human-readable string for this name.
EvalResult is a struct with detailed info about an evaluated expression.
Extra information about a function prototype.
Scheduling data for loop-based OpenMP directives.
bool UseFusedDistChunkSchedule
Request the fused distr_static_chunk + static_chunkone runtime schedule in for_static_init.
OpenMPScheduleClauseModifier M2
OpenMPScheduleClauseModifier M1
OpenMPScheduleClauseKind Schedule