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();
635 F->setDoesNotRecurse();
639 F->removeFnAttr(llvm::Attribute::NoInline);
640 F->addFnAttr(llvm::Attribute::AlwaysInline);
643 F->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
647 FO.UIntPtrCastRequired ? FO.Loc : FO.S->
getBeginLoc(),
648 FO.UIntPtrCastRequired ? FO.Loc
655 if (!FO.UIntPtrCastRequired && Args[Cnt] != TargetArgs[Cnt]) {
663 if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
664 const VarDecl *CurVD = I->getCapturedVar();
665 if (!FO.RegisterCastedArgsOnly)
666 LocalAddrs.insert({Args[Cnt], {CurVD, LocalAddr}});
674 if (FD->hasCapturedVLAType()) {
675 if (FO.UIntPtrCastRequired) {
678 Args[Cnt]->getName(), ArgLVal),
683 VLASizes.try_emplace(Args[Cnt], VAT->
getSizeExpr(), ExprArg);
684 }
else if (I->capturesVariable()) {
685 const VarDecl *Var = I->getCapturedVar();
687 Address ArgAddr = ArgLVal.getAddress();
688 if (ArgLVal.getType()->isLValueReferenceType()) {
691 assert(ArgLVal.getType()->isPointerType());
693 ArgAddr, ArgLVal.getType()->castAs<
PointerType>());
695 if (!FO.RegisterCastedArgsOnly) {
699 }
else if (I->capturesVariableByCopy()) {
700 assert(!FD->getType()->isAnyPointerType() &&
701 "Not expecting a captured pointer.");
702 const VarDecl *Var = I->getCapturedVar();
703 LocalAddrs.insert({Args[Cnt],
704 {Var, FO.UIntPtrCastRequired
706 CGF, I->getLocation(), FD->getType(),
707 Args[Cnt]->getName(), ArgLVal)
708 : ArgLVal.getAddress()}});
711 assert(I->capturesThis());
713 LocalAddrs.insert({Args[Cnt], {
nullptr, ArgLVal.getAddress()}});
724 llvm::MapVector<
const Decl *, std::pair<const VarDecl *, Address>>
726 llvm::DenseMap<
const Decl *, std::pair<const Expr *, llvm::Value *>>
728 llvm::Value *&CXXThisValue, llvm::Value *&ContextV,
const CapturedStmt &CS,
733 CXXThisValue =
nullptr;
743 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
747 F->setDoesNotThrow();
748 F->setDoesNotRecurse();
755 llvm::Type *PtrTy = CGF.
Builder.getPtrTy();
756 llvm::Align PtrAlign = CGM.
getDataLayout().getPointerABIAlignment(0);
759 for (
auto [FD,
C, FieldIdx] :
762 llvm::Value *SlotPtr =
763 CGF.
Builder.CreateConstInBoundsGEP1_32(PtrTy, ContextV, FieldIdx);
769 if (
C.capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
770 const VarDecl *CurVD =
C.getCapturedVar();
771 Slot->setName(CurVD->
getName());
772 Address SlotAddr(Slot, PtrTy, SlotAlign);
773 LocalAddrs.insert({FD, {CurVD, SlotAddr}});
774 }
else if (FD->hasCapturedVLAType()) {
781 VLASizes.try_emplace(FD, VAT->
getSizeExpr(), ExprArg);
782 }
else if (
C.capturesVariable()) {
783 const VarDecl *Var =
C.getCapturedVar();
787 Slot->setName(Var->
getName() +
".addr");
788 Address SlotAddr(Slot, PtrTy, SlotAlign);
789 LocalAddrs.insert({FD, {Var, SlotAddr}});
792 PtrTy, Slot, PtrAlign, Var->
getName());
793 LocalAddrs.insert({FD,
797 }
else if (
C.capturesVariableByCopy()) {
798 assert(!FD->getType()->isAnyPointerType() &&
799 "Not expecting a captured pointer.");
800 const VarDecl *Var =
C.getCapturedVar();
815 LocalAddrs.insert({FD, {Var, CopyAddr}});
817 assert(
C.capturesThis() &&
"Default case expected to be CXX 'this'");
820 Address SlotAddr(Slot, PtrTy, SlotAlign);
821 LocalAddrs.insert({FD, {
nullptr, SlotAddr}});
833 "CapturedStmtInfo should be set when generating the captured function");
836 bool NeedWrapperFunction =
839 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs,
841 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes,
844 llvm::raw_svector_ostream Out(Buffer);
847 bool IsDeviceKernel =
CGM.getOpenMPRuntime().isGPU() &&
849 D.getCapturedStmt(OMPD_target) == &S;
850 CodeGenFunction WrapperCGF(
CGM,
true);
851 llvm::Function *WrapperF =
nullptr;
852 if (NeedWrapperFunction) {
855 FunctionOptions WrapperFO(&S,
true,
862 WrapperCGF.CXXThisValue, WrapperFO);
865 FunctionOptions FO(&S, !NeedWrapperFunction,
false,
866 Out.str(), Loc, !NeedWrapperFunction && IsDeviceKernel);
868 *
this, WrapperArgs, WrapperLocalAddrs, WrapperVLASizes, CXXThisValue, FO);
870 for (
const auto &LocalAddrPair : WrapperLocalAddrs) {
871 if (LocalAddrPair.second.first) {
872 LocalScope.addPrivate(LocalAddrPair.second.first,
873 LocalAddrPair.second.second);
876 (void)LocalScope.Privatize();
877 for (
const auto &VLASizePair : WrapperVLASizes)
878 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
881 LocalScope.ForceCleanup();
883 if (!NeedWrapperFunction)
887 WrapperF->removeFromParent();
888 F->getParent()->getFunctionList().insertAfter(F->getIterator(), WrapperF);
891 auto *PI = F->arg_begin();
892 for (
const auto *Arg : Args) {
894 auto I = LocalAddrs.find(Arg);
895 if (I != LocalAddrs.end()) {
898 I->second.first ? I->second.first->getType() : Arg->getType(),
904 auto EI = VLASizes.find(Arg);
905 if (EI != VLASizes.end()) {
917 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
927 "CapturedStmtInfo should be set when generating the captured function");
931 bool NeedWrapperFunction =
934 CodeGenFunction WrapperCGF(
CGM,
true);
935 llvm::Function *WrapperF =
nullptr;
936 llvm::Value *WrapperContextV =
nullptr;
937 if (NeedWrapperFunction) {
940 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>>
942 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>>
945 WrapperCGF, WrapperArgs, WrapperLocalAddrs, WrapperVLASizes,
946 WrapperCGF.CXXThisValue, WrapperContextV, S, Loc, FunctionName);
950 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs;
951 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes;
954 if (NeedWrapperFunction) {
956 llvm::raw_svector_ostream Out(Buffer);
957 Out << FunctionName <<
"_debug__";
959 FunctionOptions FO(&S,
false,
960 false, Out.str(), Loc,
965 llvm::Value *ContextV =
nullptr;
967 CXXThisValue, ContextV, S, Loc,
976 llvm::Align PtrAlign =
CGM.getDataLayout().getPointerABIAlignment(0);
977 llvm::Value *SlotPtr =
Builder.CreateConstInBoundsGEP1_32(
978 Builder.getPtrTy(), ContextV, FieldIdx,
979 Twine(Param->getName()) +
".addr");
980 llvm::Value *ParamAddr =
982 llvm::Value *ParamVal =
Builder.CreateAlignedLoad(
983 Builder.getPtrTy(), ParamAddr, PtrAlign, Param->getName());
986 Builder.CreateStore(ParamVal, ParamLocalAddr);
987 LocalAddrs.insert({Param, {Param, ParamLocalAddr}});
993 for (
const auto &LocalAddrPair : LocalAddrs) {
994 if (LocalAddrPair.second.first)
995 LocalScope.addPrivate(LocalAddrPair.second.first,
996 LocalAddrPair.second.second);
998 (void)LocalScope.Privatize();
999 for (
const auto &VLASizePair : VLASizes)
1000 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
1001 PGO->assignRegionCounters(
GlobalDecl(CD), F);
1003 (void)LocalScope.ForceCleanup();
1006 if (!NeedWrapperFunction)
1010 WrapperF->removeFromParent();
1011 F->getParent()->getFunctionList().insertAfter(F->getIterator(), WrapperF);
1013 llvm::Align PtrAlign =
CGM.getDataLayout().getPointerABIAlignment(0);
1016 "Expected context param at position 0 for target regions");
1017 assert(RD->
getNumFields() + 1 == F->getNumOperands() &&
1018 "Argument count mismatch");
1020 for (
auto [FD, InnerParam, SlotIdx] : llvm::zip(
1022 llvm::Value *SlotPtr = WrapperCGF.
Builder.CreateConstInBoundsGEP1_32(
1023 WrapperCGF.
Builder.getPtrTy(), WrapperContextV, SlotIdx);
1025 WrapperCGF.
Builder.getPtrTy(), SlotPtr, PtrAlign);
1027 InnerParam.getType(), Slot, PtrAlign, InnerParam.getName());
1028 CallArgs.push_back(Val);
1033 auto InnerParam = F->arg_begin() + SlotIdx;
1034 llvm::Value *SlotPtr = WrapperCGF.
Builder.CreateConstInBoundsGEP1_32(
1035 WrapperCGF.
Builder.getPtrTy(), WrapperContextV, SlotIdx);
1037 WrapperCGF.
Builder.getPtrTy(), SlotPtr, PtrAlign);
1039 InnerParam->getType(), Slot, PtrAlign, InnerParam->getName());
1040 CallArgs.push_back(Val);
1042 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
1058 llvm::Value *NumElements =
emitArrayLength(ArrayTy, ElementTy, DestAddr);
1065 DestBegin, NumElements);
1070 llvm::Value *IsEmpty =
1071 Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arraycpy.isempty");
1072 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
1075 llvm::BasicBlock *EntryBB =
Builder.GetInsertBlock();
1080 llvm::PHINode *SrcElementPHI =
1081 Builder.CreatePHI(SrcBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
1082 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
1087 llvm::PHINode *DestElementPHI =
Builder.CreatePHI(
1088 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
1089 DestElementPHI->addIncoming(DestBegin, EntryBB);
1095 CopyGen(DestElementCurrent, SrcElementCurrent);
1098 llvm::Value *DestElementNext =
1100 1,
"omp.arraycpy.dest.element");
1101 llvm::Value *SrcElementNext =
1103 1,
"omp.arraycpy.src.element");
1106 Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
1107 Builder.CreateCondBr(Done, DoneBB, BodyBB);
1108 DestElementPHI->addIncoming(DestElementNext,
Builder.GetInsertBlock());
1109 SrcElementPHI->addIncoming(SrcElementNext,
Builder.GetInsertBlock());
1119 const auto *BO = dyn_cast<BinaryOperator>(
Copy);
1120 if (BO && BO->getOpcode() == BO_Assign) {
1129 DestAddr, SrcAddr, OriginalType,
1157 bool DeviceConstTarget =
getLangOpts().OpenMPIsTargetDevice &&
1159 bool FirstprivateIsLastprivate =
false;
1160 llvm::DenseMap<const VarDecl *, OpenMPLastprivateModifier> Lastprivates;
1161 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1162 for (
const auto *D :
C->varlist())
1163 Lastprivates.try_emplace(
1167 llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
1172 bool MustEmitFirstprivateCopy =
1173 CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown;
1174 for (
const auto *
C : D.getClausesOfKind<OMPFirstprivateClause>()) {
1175 const auto *IRef =
C->varlist_begin();
1176 const auto *InitsRef =
C->inits().begin();
1177 for (
const Expr *IInit :
C->private_copies()) {
1179 bool ThisFirstprivateIsLastprivate =
1180 Lastprivates.count(OrigVD->getCanonicalDecl()) > 0;
1183 if (!MustEmitFirstprivateCopy && !ThisFirstprivateIsLastprivate && FD &&
1185 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
1186 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
1193 if (DeviceConstTarget && OrigVD->getType().isConstant(
getContext()) &&
1195 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
1196 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
1201 FirstprivateIsLastprivate =
1202 FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate;
1203 if (EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()).second) {
1204 const auto *VDInit =
1223 assert(!CE &&
"Expected non-constant firstprivate.");
1230 if (
Type->isArrayType()) {
1246 RunCleanupsScope InitScope(*this);
1248 setAddrOfLocalVar(VDInit, SrcElement);
1249 EmitAnyExprToMem(Init, DestElement,
1250 Init->getType().getQualifiers(),
1252 LocalDeclMap.erase(VDInit);
1263 setAddrOfLocalVar(VDInit, OriginalAddr);
1265 LocalDeclMap.erase(VDInit);
1267 if (ThisFirstprivateIsLastprivate &&
1268 Lastprivates[OrigVD->getCanonicalDecl()] ==
1269 OMPC_LASTPRIVATE_conditional) {
1274 (*IRef)->getExprLoc());
1275 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1279 LocalDeclMap.erase(VD);
1280 setAddrOfLocalVar(VD, VDAddr);
1282 IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1284 assert(IsRegistered &&
1285 "firstprivate var already registered as private");
1293 return FirstprivateIsLastprivate && !EmittedAsFirstprivate.empty();
1301 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
1302 for (
const auto *
C : D.getClausesOfKind<OMPPrivateClause>()) {
1303 auto IRef =
C->varlist_begin();
1304 for (
const Expr *IInit :
C->private_copies()) {
1306 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
1312 assert(IsRegistered &&
"private var already registered as private");
1328 llvm::DenseSet<const VarDecl *> CopiedVars;
1329 llvm::BasicBlock *CopyBegin =
nullptr, *CopyEnd =
nullptr;
1331 auto IRef =
C->varlist_begin();
1332 auto ISrcRef =
C->source_exprs().begin();
1333 auto IDestRef =
C->destination_exprs().begin();
1334 for (
const Expr *AssignOp :
C->assignment_ops()) {
1343 getContext().getTargetInfo().isTLSSupported()) {
1345 "Copyin threadprivates should have been captured!");
1349 LocalDeclMap.erase(VD);
1353 :
CGM.GetAddrOfGlobal(VD),
1354 CGM.getTypes().ConvertTypeForMem(VD->
getType()),
1359 if (CopiedVars.size() == 1) {
1365 auto *MasterAddrInt =
Builder.CreatePtrToInt(
1367 auto *PrivateAddrInt =
Builder.CreatePtrToInt(
1370 Builder.CreateICmpNE(MasterAddrInt, PrivateAddrInt), CopyBegin,
1376 const auto *DestVD =
1397 bool HasAtLeastOneLastprivate =
false;
1399 llvm::DenseSet<const VarDecl *> SIMDLCVs;
1402 for (
const Expr *
C : LoopDirective->counters()) {
1407 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1408 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1409 HasAtLeastOneLastprivate =
true;
1412 const auto *IRef =
C->varlist_begin();
1413 const auto *IDestRef =
C->destination_exprs().begin();
1414 for (
const Expr *IInit :
C->private_copies()) {
1420 if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) {
1421 const auto *DestVD =
1426 (*IRef)->getType(),
VK_LValue, (*IRef)->getExprLoc());
1431 if (IInit && !SIMDLCVs.count(OrigVD->getCanonicalDecl())) {
1434 if (
C->getKind() == OMPC_LASTPRIVATE_conditional) {
1435 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1437 setAddrOfLocalVar(VD, VDAddr);
1443 bool IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1444 assert(IsRegistered &&
1445 "lastprivate var already registered as private");
1453 return HasAtLeastOneLastprivate;
1458 llvm::Value *IsLastIterCond) {
1467 llvm::BasicBlock *ThenBB =
nullptr;
1468 llvm::BasicBlock *DoneBB =
nullptr;
1469 if (IsLastIterCond) {
1473 llvm::any_of(D.getClausesOfKind<OMPLastprivateClause>(),
1474 [](
const OMPLastprivateClause *
C) {
1475 return C->getKind() == OMPC_LASTPRIVATE_conditional;
1477 CGM.getOpenMPRuntime().emitBarrierCall(*
this, D.getBeginLoc(),
1484 Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB);
1487 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1488 llvm::DenseMap<const VarDecl *, const Expr *> LoopCountersAndUpdates;
1489 if (
const auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) {
1490 auto IC = LoopDirective->counters().begin();
1491 for (
const Expr *F : LoopDirective->finals()) {
1495 AlreadyEmittedVars.insert(D);
1497 LoopCountersAndUpdates[D] = F;
1501 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1502 auto IRef =
C->varlist_begin();
1503 auto ISrcRef =
C->source_exprs().begin();
1504 auto IDestRef =
C->destination_exprs().begin();
1505 for (
const Expr *AssignOp :
C->assignment_ops()) {
1506 const auto *PrivateVD =
1509 const auto *CanonicalVD = PrivateVD->getCanonicalDecl();
1510 if (AlreadyEmittedVars.insert(CanonicalVD).second) {
1514 if (
const Expr *FinalExpr = LoopCountersAndUpdates.lookup(CanonicalVD))
1518 const auto *DestVD =
1522 if (
const auto *RefTy = PrivateVD->getType()->getAs<
ReferenceType>())
1524 Builder.CreateLoad(PrivateAddr),
1525 CGM.getTypes().ConvertTypeForMem(RefTy->getPointeeType()),
1526 CGM.getNaturalTypeAlignment(RefTy->getPointeeType()));
1528 if (
C->getKind() == OMPC_LASTPRIVATE_conditional)
1529 CGM.getOpenMPRuntime().emitLastprivateConditionalFinalUpdate(
1531 (*IRef)->getExprLoc());
1534 EmitOMPCopy(
Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp);
1540 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
1560 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1561 if (ForInscan != (
C->getModifier() == OMPC_REDUCTION_inscan))
1563 Shareds.append(
C->varlist_begin(),
C->varlist_end());
1564 Privates.append(
C->privates().begin(),
C->privates().end());
1565 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1566 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1567 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1568 if (
C->getModifier() == OMPC_REDUCTION_task) {
1569 Data.ReductionVars.append(
C->privates().begin(),
C->privates().end());
1570 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
1571 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
1572 Data.ReductionOps.append(
C->reduction_ops().begin(),
1573 C->reduction_ops().end());
1574 TaskLHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1575 TaskRHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1580 auto *ILHS = LHSs.begin();
1581 auto *IRHS = RHSs.begin();
1583 for (
const Expr *IRef : Shareds) {
1591 [&Emission](CodeGenFunction &CGF) {
1592 CGF.EmitAutoVarInit(Emission);
1600 assert(IsRegistered &&
"private var already registered as private");
1608 if (isaOMPArraySectionExpr &&
Type->isVariablyModifiedType()) {
1613 }
else if ((isaOMPArraySectionExpr &&
Type->isScalarType()) ||
1631 PrivateScope.
addPrivate(LHSVD, OriginalAddr);
1642 if (!
Data.ReductionVars.empty()) {
1644 Data.IsReductionWithTaskMod =
true;
1646 llvm::Value *ReductionDesc =
CGM.getOpenMPRuntime().emitTaskReductionInit(
1647 *
this, D.getBeginLoc(), TaskLHSs, TaskRHSs,
Data);
1648 const Expr *TaskRedRef =
nullptr;
1659 case OMPD_parallel_for:
1662 case OMPD_parallel_master:
1666 case OMPD_parallel_sections:
1670 case OMPD_target_parallel:
1674 case OMPD_target_parallel_for:
1678 case OMPD_distribute_parallel_for:
1682 case OMPD_teams_distribute_parallel_for:
1684 .getTaskReductionRefExpr();
1686 case OMPD_target_teams_distribute_parallel_for:
1688 .getTaskReductionRefExpr();
1696 case OMPD_parallel_for_simd:
1698 case OMPD_taskyield:
1702 case OMPD_taskgroup:
1706 case OMPD_ordered_standalone:
1707 case OMPD_ordered_blockassoc:
1711 case OMPD_cancellation_point:
1713 case OMPD_target_data:
1714 case OMPD_target_enter_data:
1715 case OMPD_target_exit_data:
1717 case OMPD_taskloop_simd:
1718 case OMPD_master_taskloop:
1719 case OMPD_master_taskloop_simd:
1720 case OMPD_parallel_master_taskloop:
1721 case OMPD_parallel_master_taskloop_simd:
1722 case OMPD_distribute:
1723 case OMPD_target_update:
1724 case OMPD_distribute_parallel_for_simd:
1725 case OMPD_distribute_simd:
1726 case OMPD_target_parallel_for_simd:
1727 case OMPD_target_simd:
1728 case OMPD_teams_distribute:
1729 case OMPD_teams_distribute_simd:
1730 case OMPD_teams_distribute_parallel_for_simd:
1731 case OMPD_target_teams:
1732 case OMPD_target_teams_distribute:
1733 case OMPD_target_teams_distribute_parallel_for_simd:
1734 case OMPD_target_teams_distribute_simd:
1735 case OMPD_declare_target:
1736 case OMPD_end_declare_target:
1737 case OMPD_threadprivate:
1739 case OMPD_declare_reduction:
1740 case OMPD_declare_mapper:
1741 case OMPD_declare_simd:
1743 case OMPD_declare_variant:
1744 case OMPD_begin_declare_variant:
1745 case OMPD_end_declare_variant:
1748 llvm_unreachable(
"Unexpected directive with task reductions.");
1754 false, TaskRedRef->
getType());
1767 bool HasAtLeastOneReduction =
false;
1768 bool IsReductionWithTaskMod =
false;
1769 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1771 if (
C->getModifier() == OMPC_REDUCTION_inscan)
1773 HasAtLeastOneReduction =
true;
1774 Privates.append(
C->privates().begin(),
C->privates().end());
1775 LHSExprs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1776 RHSExprs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1777 IsPrivateVarReduction.append(
C->private_var_reduction_flags().begin(),
1778 C->private_var_reduction_flags().end());
1779 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1780 IsReductionWithTaskMod =
1781 IsReductionWithTaskMod ||
C->getModifier() == OMPC_REDUCTION_task;
1783 if (HasAtLeastOneReduction) {
1785 if (IsReductionWithTaskMod) {
1786 CGM.getOpenMPRuntime().emitTaskReductionFini(
1789 bool TeamsLoopCanBeParallel =
false;
1790 if (
auto *TTLD = dyn_cast<OMPTargetTeamsGenericLoopDirective>(&D))
1791 TeamsLoopCanBeParallel = TTLD->canBeParallelFor();
1792 bool WithNowait = D.getSingleClause<OMPNowaitClause>() ||
1794 TeamsLoopCanBeParallel || ReductionKind == OMPD_simd;
1795 bool SimpleReduction = ReductionKind == OMPD_simd;
1798 CGM.getOpenMPRuntime().emitReduction(
1799 *
this, D.getEndLoc(),
Privates, LHSExprs, RHSExprs, ReductionOps,
1800 {WithNowait, SimpleReduction, IsPrivateVarReduction, ReductionKind});
1809 llvm::BasicBlock *DoneBB =
nullptr;
1810 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1811 if (
const Expr *PostUpdate =
C->getPostUpdateExpr()) {
1813 if (llvm::Value *
Cond = CondGen(CGF)) {
1834 const OMPExecutableDirective &,
1835 llvm::SmallVectorImpl<llvm::Value *> &)>
1836 CodeGenBoundParametersTy;
1844 llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> PrivateDecls;
1845 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
1846 for (
const Expr *Ref :
C->varlist()) {
1847 if (!Ref->getType()->isScalarType())
1849 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1856 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
1857 for (
const Expr *Ref :
C->varlist()) {
1858 if (!Ref->getType()->isScalarType())
1860 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1867 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
1868 for (
const Expr *Ref :
C->varlist()) {
1869 if (!Ref->getType()->isScalarType())
1871 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1882 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
1883 for (
const Expr *Ref :
C->varlist()) {
1884 if (!Ref->getType()->isScalarType())
1886 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1893 CGF, S, PrivateDecls);
1899 const CodeGenBoundParametersTy &CodeGenBoundParameters) {
1900 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
1901 llvm::Value *NumThreads =
nullptr;
1910 llvm::Function *OutlinedFn =
1917 NumThreads = CGF.
EmitScalarExpr(NumThreadsClause->getNumThreads(),
1919 Modifier = NumThreadsClause->getModifier();
1920 if (
const auto *MessageClause = S.getSingleClause<OMPMessageClause>()) {
1921 Message = MessageClause->getMessageString();
1922 MessageLoc = MessageClause->getBeginLoc();
1924 if (
const auto *SeverityClause = S.getSingleClause<OMPSeverityClause>()) {
1925 Severity = SeverityClause->getSeverityKind();
1926 SeverityLoc = SeverityClause->getBeginLoc();
1929 CGF, NumThreads, NumThreadsClause->getBeginLoc(), Modifier, Severity,
1930 SeverityLoc, Message, MessageLoc);
1932 if (
const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>()) {
1935 CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getBeginLoc());
1937 const Expr *IfCond =
nullptr;
1938 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
1939 if (
C->getNameModifier() == OMPD_unknown ||
1940 C->getNameModifier() == OMPD_parallel) {
1941 IfCond =
C->getCondition();
1946 OMPParallelScope
Scope(CGF, S);
1952 CodeGenBoundParameters(CGF, S, CapturedVars);
1955 CapturedVars, IfCond, NumThreads,
1956 Modifier, Severity, Message);
1961 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
1963 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
1965 return !((AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc ||
1966 AA->getAllocatorType() == OMPAllocateDeclAttr::OMPNullMemAlloc) &&
1967 !AA->getAllocator());
1982 CGF, S.getBeginLoc(), OMPD_unknown,
false,
1988 CodeGenFunction &CGF,
const VarDecl *VD) {
1990 auto &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2002 Size = CGF.
Builder.CreateNUWAdd(
2004 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
2005 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
2011 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
2012 assert(AA->getAllocator() &&
2013 "Expected allocator expression for non-default allocator.");
2017 if (Allocator->getType()->isIntegerTy())
2018 Allocator = CGF.
Builder.CreateIntToPtr(Allocator,
CGM.VoidPtrTy);
2019 else if (Allocator->getType()->isPointerTy())
2023 llvm::Value *
Addr = OMPBuilder.createOMPAlloc(
2026 llvm::CallInst *FreeCI =
2027 OMPBuilder.createOMPFree(CGF.
Builder,
Addr, Allocator);
2041 if (
CGM.getLangOpts().OpenMPUseTLS &&
2042 CGM.getContext().getTargetInfo().isTLSSupported())
2045 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2050 llvm::ConstantInt *Size =
CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy));
2052 llvm::Twine CacheName = Twine(
CGM.getMangledName(VD)).concat(Suffix);
2054 llvm::CallInst *ThreadPrivateCacheCall =
2055 OMPBuilder.createCachedThreadPrivate(CGF.
Builder,
Data, Size, CacheName);
2063 llvm::raw_svector_ostream OS(Buffer);
2064 StringRef Sep = FirstSeparator;
2065 for (StringRef Part : Parts) {
2069 return OS.str().str();
2077 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
2078 "." + RegionName +
".after");
2094 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
2095 "." + RegionName +
".after");
2107 if (
CGM.getLangOpts().OpenMPIRBuilder) {
2108 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2110 llvm::Value *IfCond =
nullptr;
2115 llvm::Value *NumThreads =
nullptr;
2120 ProcBindKind ProcBind = OMP_PROC_BIND_default;
2121 if (
const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>())
2122 ProcBind = ProcBindClause->getProcBindKind();
2124 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2128 auto FiniCB = [
this](InsertPointTy IP) {
2130 return llvm::Error::success();
2137 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
2138 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
2149 auto BodyGenCB = [&,
this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
2152 *
this, ParallelRegionBodyStmt, AllocIP, CodeGenIP,
"parallel");
2153 return llvm::Error::success();
2158 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
2160 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2161 cantFail(OMPBuilder.createParallel(
2162 Builder, AllocaIP, {}, BodyGenCB, PrivCB, FiniCB,
2163 IfCond, NumThreads, ProcBind, S.hasCancel()));
2177 CGF.
EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt());
2186 [](CodeGenFunction &) {
return nullptr; });
2198class OMPTransformDirectiveScopeRAII {
2199 OMPLoopScope *
Scope =
nullptr;
2203 OMPTransformDirectiveScopeRAII(
const OMPTransformDirectiveScopeRAII &) =
2205 OMPTransformDirectiveScopeRAII &
2206 operator=(
const OMPTransformDirectiveScopeRAII &) =
delete;
2210 if (
const auto *Dir = dyn_cast<OMPLoopBasedDirective>(S)) {
2211 Scope =
new OMPLoopScope(CGF, *Dir);
2214 }
else if (
const auto *Dir =
2215 dyn_cast<OMPCanonicalLoopSequenceTransformationDirective>(
2220 Scope =
new OMPLoopScope(CGF, *Dir);
2225 ~OMPTransformDirectiveScopeRAII() {
2236 int MaxLevel,
int Level = 0) {
2237 assert(Level < MaxLevel &&
"Too deep lookup during loop body codegen.");
2239 if (
const auto *CS = dyn_cast<CompoundStmt>(SimplifiedS)) {
2242 "LLVM IR generation of compound statement ('{}')");
2246 for (
const Stmt *CurStmt : CS->body())
2247 emitBody(CGF, CurStmt, NextLoop, MaxLevel, Level);
2250 if (SimplifiedS == NextLoop) {
2251 if (
auto *Dir = dyn_cast<OMPLoopTransformationDirective>(SimplifiedS))
2252 SimplifiedS = Dir->getTransformedStmt();
2253 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(SimplifiedS))
2254 SimplifiedS = CanonLoop->getLoopStmt();
2255 if (
const auto *For = dyn_cast<ForStmt>(SimplifiedS)) {
2259 "Expected canonical for loop or range-based for loop.");
2261 CGF.
EmitStmt(CXXFor->getLoopVarStmt());
2262 S = CXXFor->getBody();
2264 if (Level + 1 < MaxLevel) {
2265 NextLoop = OMPLoopDirective::tryToFindNextInnerLoop(
2267 emitBody(CGF, S, NextLoop, MaxLevel, Level + 1);
2278 for (
const Expr *UE : D.updates())
2285 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2286 for (
const Expr *UE :
C->updates())
2293 BreakContinueStack.push_back(BreakContinue(D,
LoopExit, Continue));
2294 for (
const Expr *E : D.finals_conditions()) {
2307 bool IsInscanRegion = InscanScope.
Privatize();
2308 if (IsInscanRegion) {
2318 if (EKind != OMPD_simd && !
getLangOpts().OpenMPSimd)
2327 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
2330 OMPLoopBasedDirective::tryToFindNextInnerLoop(
2332 D.getLoopsNumber());
2340 BreakContinueStack.pop_back();
2351 std::unique_ptr<CodeGenFunction::CGCapturedStmtInfo> CSI =
2352 std::make_unique<CodeGenFunction::CGCapturedStmtInfo>(*S);
2356 return {F, CapStruct.getPointer(
ParentCGF)};
2360static llvm::CallInst *
2365 EffectiveArgs.reserve(Args.size() + 1);
2366 llvm::append_range(EffectiveArgs, Args);
2367 EffectiveArgs.push_back(Cap.second);
2372llvm::CanonicalLoopInfo *
2374 assert(Depth == 1 &&
"Nested loops with OpenMPIRBuilder not yet implemented");
2400 const Stmt *SyntacticalLoop = S->getLoopStmt();
2411 const Stmt *BodyStmt;
2412 if (
const auto *For = dyn_cast<ForStmt>(SyntacticalLoop)) {
2413 if (
const Stmt *InitStmt = For->getInit())
2415 BodyStmt = For->getBody();
2416 }
else if (
const auto *RangeFor =
2417 dyn_cast<CXXForRangeStmt>(SyntacticalLoop)) {
2418 if (
const DeclStmt *RangeStmt = RangeFor->getRangeStmt())
2420 if (
const DeclStmt *BeginStmt = RangeFor->getBeginStmt())
2422 if (
const DeclStmt *EndStmt = RangeFor->getEndStmt())
2424 if (
const DeclStmt *LoopVarStmt = RangeFor->getLoopVarStmt())
2426 BodyStmt = RangeFor->getBody();
2428 llvm_unreachable(
"Expected for-stmt or range-based for-stmt");
2431 const CapturedStmt *DistanceFunc = S->getDistanceFunc();
2444 llvm::Value *DistVal =
Builder.CreateLoad(CountAddr,
".count");
2447 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2448 auto BodyGen = [&,
this](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP,
2449 llvm::Value *IndVar) {
2454 const DeclRefExpr *LoopVarRef = S->getLoopVarRef();
2462 return llvm::Error::success();
2465 llvm::CanonicalLoopInfo *
CL =
2466 cantFail(OMPBuilder.createCanonicalLoop(
Builder, BodyGen, DistVal));
2478 const Expr *IncExpr,
2479 const llvm::function_ref<
void(CodeGenFunction &)> BodyGen,
2480 const llvm::function_ref<
void(CodeGenFunction &)> PostIncGen) {
2490 const CapturedStmt *ICS = OMPED.getInnermostCapturedStmt();
2504 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
2505 if (RequiresCleanup)
2512 if (ExitBlock !=
LoopExit.getBlock()) {
2522 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
2530 BreakContinueStack.pop_back();
2541 bool HasLinears =
false;
2542 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2546 if (
const auto *Ref =
2565 if (
const auto *CS = cast_or_null<BinaryOperator>(
C->getCalcStep()))
2577 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2580 llvm::BasicBlock *DoneBB =
nullptr;
2582 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2583 auto IC =
C->varlist_begin();
2584 for (
const Expr *F :
C->finals()) {
2586 if (llvm::Value *
Cond = CondGen(*
this)) {
2598 (*IC)->getType(),
VK_LValue, (*IC)->getExprLoc());
2606 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
2618 llvm::APInt ClauseAlignment(64, 0);
2619 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
2622 ClauseAlignment = AlignmentCI->getValue();
2624 for (
const Expr *E : Clause->varlist()) {
2625 llvm::APInt Alignment(ClauseAlignment);
2626 if (Alignment == 0) {
2633 E->getType()->getPointeeType()))
2636 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2637 "alignment is not power of 2");
2638 if (Alignment != 0) {
2652 auto I = S.private_counters().begin();
2653 for (
const Expr *E : S.counters()) {
2659 LocalDeclMap.erase(PrivateVD);
2665 E->getType(),
VK_LValue, E->getExprLoc());
2673 for (
const auto *
C : S.getClausesOfKind<OMPOrderedClause>()) {
2674 if (!
C->getNumForLoops())
2676 for (
unsigned I = S.getLoopsNumber(), E =
C->getLoopNumIterations().size();
2682 if (DRE->refersToEnclosingVariableOrCapture()) {
2691 const Expr *
Cond, llvm::BasicBlock *TrueBlock,
2692 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
2700 for (
const Expr *I : S.inits()) {
2707 for (
const Expr *E : S.dependent_counters()) {
2710 assert(!E->getType().getNonReferenceType()->isRecordType() &&
2711 "dependent counter must not be an iterator.");
2715 (void)PreCondVars.
setVarAddr(CGF, VD, CounterAddr);
2717 (void)PreCondVars.
apply(CGF);
2718 for (
const Expr *E : S.dependent_inits()) {
2732 llvm::DenseSet<const VarDecl *> SIMDLCVs;
2736 for (
const Expr *
C : LoopDirective->counters()) {
2741 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2742 auto CurPrivate =
C->privates().begin();
2743 for (
const Expr *E :
C->varlist()) {
2745 const auto *PrivateVD =
2752 assert(IsRegistered &&
"linear var already registered as private");
2840 if (
const auto *CS = dyn_cast<CapturedStmt>(S))
2858 if (HasOrderedDirective)
2866 const Stmt *AssociatedStmt = D.getAssociatedStmt();
2870 if (
C->getKind() == OMPC_ORDER_concurrent)
2873 if ((EKind == OMPD_simd ||
2875 llvm::any_of(D.getClausesOfKind<OMPReductionClause>(),
2876 [](
const OMPReductionClause *
C) {
2877 return C->getModifier() == OMPC_REDUCTION_inscan;
2885 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2888 llvm::BasicBlock *DoneBB =
nullptr;
2889 auto IC = D.counters().begin();
2890 auto IPC = D.private_counters().begin();
2891 for (
const Expr *F : D.finals()) {
2894 const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
2896 OrigVD->hasGlobalStorage() || CED) {
2898 if (llvm::Value *
Cond = CondGen(*
this)) {
2946 auto &&ThenGen = [&S, &SimdInitGen, &BodyCodeGen](
CodeGenFunction &CGF,
2960 const Expr *IfCond =
nullptr;
2963 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
2965 (
C->getNameModifier() == OMPD_unknown ||
2966 C->getNameModifier() == OMPD_simd)) {
2967 IfCond =
C->getCondition();
2983 OMPLoopScope PreInitScope(CGF, S);
3005 llvm::BasicBlock *ContBlock =
nullptr;
3012 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
3019 const Expr *IVExpr = S.getIterationVariable();
3027 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
3042 CGF, S, CGF.
EmitLValue(S.getIterationVariable()));
3057 emitOMPLoopBodyWithStopPoint(CGF, S,
3058 CodeGenFunction::JumpDest());
3064 if (HasLastprivateClause)
3093 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(S.getRawStmt())) {
3094 if (
const Stmt *SyntacticalLoop = CanonLoop->getLoopStmt()) {
3095 for (
const Stmt *SubStmt : SyntacticalLoop->
children()) {
3098 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(SubStmt)) {
3113static llvm::MapVector<llvm::Value *, llvm::Value *>
3115 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars;
3117 llvm::APInt ClauseAlignment(64, 0);
3118 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
3121 ClauseAlignment = AlignmentCI->getValue();
3123 for (
const Expr *E : Clause->varlist()) {
3124 llvm::APInt Alignment(ClauseAlignment);
3125 if (Alignment == 0) {
3132 E->getType()->getPointeeType()))
3135 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
3136 "alignment is not power of 2");
3138 AlignedVars[PtrValue] = CGF.
Builder.getInt64(Alignment.getSExtValue());
3148 bool UseOMPIRBuilder =
3150 if (UseOMPIRBuilder) {
3154 if (UseOMPIRBuilder) {
3155 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars =
3158 const Stmt *Inner = S.getRawStmt();
3159 llvm::CanonicalLoopInfo *CLI =
3160 CGF.EmitOMPCollapsedCanonicalLoopNest(Inner, 1);
3162 llvm::OpenMPIRBuilder &OMPBuilder =
3165 llvm::ConstantInt *Simdlen =
nullptr;
3172 llvm::ConstantInt *Safelen =
nullptr;
3179 llvm::omp::OrderKind Order = llvm::omp::OrderKind::OMP_ORDER_unknown;
3181 if (
C->getKind() == OpenMPOrderClauseKind::OMPC_ORDER_concurrent) {
3182 Order = llvm::omp::OrderKind::OMP_ORDER_concurrent;
3187 OMPBuilder.applySimd(CLI, AlignedVars,
3188 nullptr, Order, Simdlen, Safelen);
3195 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
3210 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
3223 OMPTransformDirectiveScopeRAII TileScope(*
this, &S);
3229 OMPTransformDirectiveScopeRAII StripeScope(*
this, &S);
3235 OMPTransformDirectiveScopeRAII ReverseScope(*
this, &S);
3241 OMPTransformDirectiveScopeRAII SplitScope(*
this, &S);
3248 OMPTransformDirectiveScopeRAII InterchangeScope(*
this, &S);
3254 OMPTransformDirectiveScopeRAII FuseScope(*
this, &S);
3259 bool UseOMPIRBuilder =
CGM.getLangOpts().OpenMPIRBuilder;
3261 if (UseOMPIRBuilder) {
3263 const Stmt *Inner = S.getRawStmt();
3271 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
3274 llvm::CanonicalLoopInfo *UnrolledCLI =
nullptr;
3278 OMPBuilder.unrollLoopFull(DL, CLI);
3280 uint64_t Factor = 0;
3281 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3282 Factor = FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
3283 assert(Factor >= 1 &&
"Only positive factors are valid");
3285 OMPBuilder.unrollLoopPartial(DL, CLI, Factor,
3286 NeedsUnrolledCLI ? &UnrolledCLI :
nullptr);
3288 OMPBuilder.unrollLoopHeuristic(DL, CLI);
3291 assert((!NeedsUnrolledCLI || UnrolledCLI) &&
3292 "NeedsUnrolledCLI implies UnrolledCLI to be set");
3309 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3311 FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
3312 assert(Factor >= 1 &&
"Only positive factors are valid");
3320void CodeGenFunction::EmitOMPOuterLoop(
3323 const CodeGenFunction::OMPLoopArguments &LoopArgs,
3328 const Expr *IVExpr = S.getIterationVariable();
3342 llvm::Value *BoolCondVal =
nullptr;
3343 if (!DynamicOrOrdered) {
3354 RT.
emitForNext(*
this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL,
3355 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST);
3360 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
3365 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
3366 if (ExitBlock !=
LoopExit.getBlock()) {
3374 if (DynamicOrOrdered)
3379 BreakContinueStack.push_back(BreakContinue(S, LoopExit, Continue));
3384 [&S, IsMonotonic, EKind](CodeGenFunction &CGF, PrePostActionTy &) {
3389 if (
const auto *
C = S.getSingleClause<OMPOrderClause>())
3390 if (
C->getKind() == OMPC_ORDER_concurrent)
3396 [&S, &LoopArgs, LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered,
3397 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
3398 SourceLocation Loc = S.getBeginLoc();
3404 CGF.EmitOMPInnerLoop(
3406 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
3407 CodeGenLoop(CGF, S, LoopExit);
3409 [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) {
3410 CodeGenOrdered(CGF, Loc, IVSize, IVSigned);
3415 BreakContinueStack.pop_back();
3416 if (!DynamicOrOrdered) {
3429 auto &&CodeGen = [DynamicOrOrdered, &S, &LoopArgs](CodeGenFunction &CGF) {
3430 if (!DynamicOrOrdered)
3431 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
3434 OMPCancelStack.emitExit(*
this, EKind, CodeGen);
3437void CodeGenFunction::EmitOMPForOuterLoop(
3438 const OpenMPScheduleTy &ScheduleKind,
bool IsMonotonic,
3440 const OMPLoopArguments &LoopArgs,
3442 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3448 LoopArgs.Chunk !=
nullptr)) &&
3449 "static non-chunked schedule does not need outer loop");
3503 const Expr *IVExpr = S.getIterationVariable();
3507 if (DynamicOrOrdered) {
3508 const std::pair<llvm::Value *, llvm::Value *> DispatchBounds =
3509 CGDispatchBounds(*
this, S, LoopArgs.LB, LoopArgs.UB);
3510 llvm::Value *LBVal = DispatchBounds.first;
3511 llvm::Value *UBVal = DispatchBounds.second;
3512 CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal,
3515 IVSigned, Ordered, DipatchRTInputValues);
3517 CGOpenMPRuntime::StaticRTInput StaticInit(
3518 IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
3519 LoopArgs.ST, LoopArgs.Chunk);
3525 auto &&CodeGenOrdered = [Ordered](CodeGenFunction &CGF, SourceLocation Loc,
3526 const unsigned IVSize,
3527 const bool IVSigned) {
3534 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST,
3535 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB);
3536 OuterLoopArgs.IncExpr = S.getInc();
3537 OuterLoopArgs.Init = S.getInit();
3538 OuterLoopArgs.Cond = S.getCond();
3539 OuterLoopArgs.NextLB = S.getNextLowerBound();
3540 OuterLoopArgs.NextUB = S.getNextUpperBound();
3541 OuterLoopArgs.DKind = LoopArgs.DKind;
3542 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
3544 if (DynamicOrOrdered) {
3550 const unsigned IVSize,
const bool IVSigned) {}
3552void CodeGenFunction::EmitOMPDistributeOuterLoop(
3557 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3564 const Expr *IVExpr = S.getIterationVariable();
3569 CGOpenMPRuntime::StaticRTInput StaticInit(
3570 IVSize, IVSigned,
false, LoopArgs.IL, LoopArgs.LB,
3571 LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
3578 IncExpr = S.getDistInc();
3580 IncExpr = S.getInc();
3585 OMPLoopArguments OuterLoopArgs;
3586 OuterLoopArgs.LB = LoopArgs.LB;
3587 OuterLoopArgs.UB = LoopArgs.UB;
3588 OuterLoopArgs.ST = LoopArgs.ST;
3589 OuterLoopArgs.IL = LoopArgs.IL;
3590 OuterLoopArgs.Chunk = LoopArgs.Chunk;
3592 ? S.getCombinedEnsureUpperBound()
3593 : S.getEnsureUpperBound();
3594 OuterLoopArgs.IncExpr = IncExpr;
3596 ? S.getCombinedInit()
3599 ? S.getCombinedCond()
3602 ? S.getCombinedNextLowerBound()
3603 : S.getNextLowerBound();
3605 ? S.getCombinedNextUpperBound()
3606 : S.getNextUpperBound();
3607 OuterLoopArgs.DKind = OMPD_distribute;
3609 EmitOMPOuterLoop(
false,
false, S,
3610 LoopScope, OuterLoopArgs, CodeGenLoopContent,
3614static std::pair<LValue, LValue>
3629 LValue PrevLB = CGF.
EmitLValue(LS.getPrevLowerBoundVariable());
3630 LValue PrevUB = CGF.
EmitLValue(LS.getPrevUpperBoundVariable());
3632 PrevLB, LS.getPrevLowerBoundVariable()->getExprLoc());
3634 PrevLBVal, LS.getPrevLowerBoundVariable()->getType(),
3635 LS.getIterationVariable()->getType(),
3636 LS.getPrevLowerBoundVariable()->getExprLoc());
3638 PrevUB, LS.getPrevUpperBoundVariable()->getExprLoc());
3640 PrevUBVal, LS.getPrevUpperBoundVariable()->getType(),
3641 LS.getIterationVariable()->getType(),
3642 LS.getPrevUpperBoundVariable()->getExprLoc());
3657static std::pair<llvm::Value *, llvm::Value *>
3662 const Expr *IVExpr = LS.getIterationVariable();
3668 llvm::Value *LBVal =
3670 llvm::Value *UBVal =
3672 return {LBVal, UBVal};
3681 llvm::Value *LBCast = CGF.
Builder.CreateIntCast(
3683 CapturedVars.push_back(LBCast);
3687 llvm::Value *UBCast = CGF.
Builder.CreateIntCast(
3689 CapturedVars.push_back(UBCast);
3700 bool HasCancel =
false;
3702 if (
const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
3703 HasCancel = D->hasCancel();
3704 else if (
const auto *D = dyn_cast<OMPDistributeParallelForDirective>(&S))
3705 HasCancel = D->hasCancel();
3706 else if (
const auto *D =
3707 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S))
3708 HasCancel = D->hasCancel();
3718 CGInlinedWorksharingLoop,
3728 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3729 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3738 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3739 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3747 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
3748 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
3758 llvm::Constant *
Addr;
3760 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
3762 assert(Fn &&
Addr &&
"Target device function emission failed.");
3774struct ScheduleKindModifiersTy {
3781 : Kind(Kind), M1(M1), M2(M2) {}
3797 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
3805 bool HasLastprivateClause;
3808 OMPLoopScope PreInitScope(*
this, S);
3813 llvm::BasicBlock *ContBlock =
nullptr;
3820 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
3827 bool Ordered =
false;
3828 if (
const auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) {
3829 if (OrderedClause->getNumForLoops())
3839 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*
this, S);
3840 LValue LB = Bounds.first;
3841 LValue UB = Bounds.second;
3855 CGM.getOpenMPRuntime().emitBarrierCall(
3856 *
this, S.getBeginLoc(), OMPD_unknown,
false,
3861 *
this, S,
EmitLValue(S.getIterationVariable()));
3868 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
3871 const Expr *ChunkExpr =
nullptr;
3873 if (
const auto *
C = S.getSingleClause<OMPScheduleClause>()) {
3874 ScheduleKind.
Schedule =
C->getScheduleKind();
3875 ScheduleKind.
M1 =
C->getFirstScheduleModifier();
3876 ScheduleKind.
M2 =
C->getSecondScheduleModifier();
3877 ChunkExpr =
C->getChunkSize();
3880 CGM.getOpenMPRuntime().getDefaultScheduleAndChunk(
3881 *
this, S, ScheduleKind.
Schedule, ChunkExpr);
3883 bool HasChunkSizeOne =
false;
3884 llvm::Value *Chunk =
nullptr;
3888 S.getIterationVariable()->getType(),
3892 llvm::APSInt EvaluatedChunk =
Result.Val.getInt();
3893 HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
3902 bool StaticChunkedOne =
3904 Chunk !=
nullptr) &&
3916 "fused distribute schedule requires a static chunk-one schedule");
3919 (ScheduleKind.
Schedule == OMPC_SCHEDULE_static &&
3920 !(ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
3921 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)) ||
3922 ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
3923 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
3925 Chunk !=
nullptr) ||
3926 StaticChunkedOne) &&
3936 if (
C->getKind() == OMPC_ORDER_concurrent)
3940 [IVSize, IVSigned, Ordered, IL, LB, UB, ST, StaticChunkedOne, Chunk,
3949 IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(),
3950 UB.getAddress(), ST.getAddress(),
3951 StaticChunkedOne ? Chunk :
nullptr);
3953 CGF, S.getBeginLoc(), EKind, ScheduleKind, StaticInit);
3955 if (!StaticChunkedOne)
3974 StaticChunkedOne ? S.getCombinedParForInDistCond()
3976 StaticChunkedOne ? S.getDistInc() : S.getInc(),
3977 [&S,
LoopExit](CodeGenFunction &CGF) {
3978 emitOMPLoopBodyWithStopPoint(CGF, S, LoopExit);
3980 [](CodeGenFunction &) {});
3984 auto &&
CodeGen = [&S](CodeGenFunction &CGF) {
3988 OMPCancelStack.emitExit(*
this, EKind,
CodeGen);
3995 LoopArguments.DKind = OMPD_for;
3996 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
3997 LoopArguments, CGDispatchBounds);
4001 return CGF.
Builder.CreateIsNotNull(
4007 ? OMPD_parallel_for_simd
4011 *
this, S, [IL, &S](CodeGenFunction &CGF) {
4012 return CGF.
Builder.CreateIsNotNull(
4016 if (HasLastprivateClause)
4022 return CGF.
Builder.CreateIsNotNull(
4033 return HasLastprivateClause;
4039static std::pair<LValue, LValue>
4053static std::pair<llvm::Value *, llvm::Value *>
4057 const Expr *IVExpr = LS.getIterationVariable();
4059 llvm::Value *LBVal = CGF.
Builder.getIntN(IVSize, 0);
4061 return {LBVal, UBVal};
4073 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
4074 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4075 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4080 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4081 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4082 "Only inscan reductions are expected.");
4083 Shareds.append(
C->varlist_begin(),
C->varlist_end());
4084 Privates.append(
C->privates().begin(),
C->privates().end());
4085 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
4086 CopyArrayTemps.append(
C->copy_array_temps().begin(),
4087 C->copy_array_temps().end());
4095 auto *ITA = CopyArrayTemps.begin();
4100 if (PrivateVD->getType()->isVariablyModifiedType()) {
4125 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
4126 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4127 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4134 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4135 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4136 "Only inscan reductions are expected.");
4137 Shareds.append(
C->varlist_begin(),
C->varlist_end());
4138 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
4139 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
4140 Privates.append(
C->privates().begin(),
C->privates().end());
4141 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
4142 CopyArrayElems.append(
C->copy_array_elems().begin(),
4143 C->copy_array_elems().end());
4147 llvm::Value *OMPLast = CGF.
Builder.CreateNSWSub(
4148 OMPScanNumIterations,
4149 llvm::ConstantInt::get(CGF.
SizeTy, 1,
false));
4150 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
4152 const Expr *OrigExpr = Shareds[I];
4153 const Expr *CopyArrayElem = CopyArrayElems[I];
4160 LValue SrcLVal = CGF.
EmitLValue(CopyArrayElem);
4162 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
4192 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4193 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4199 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4200 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4201 "Only inscan reductions are expected.");
4202 Privates.append(
C->privates().begin(),
C->privates().end());
4203 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
4204 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
4205 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
4206 CopyArrayElems.append(
C->copy_array_elems().begin(),
4207 C->copy_array_elems().end());
4222 auto &&
CodeGen = [&S, OMPScanNumIterations, &LHSs, &RHSs, &CopyArrayElems,
4229 llvm::BasicBlock *InputBB = CGF.Builder.GetInsertBlock();
4230 llvm::BasicBlock *LoopBB = CGF.createBasicBlock(
"omp.outer.log.scan.body");
4231 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
"omp.outer.log.scan.exit");
4233 CGF.CGM.getIntrinsic(llvm::Intrinsic::log2, CGF.DoubleTy);
4235 CGF.Builder.CreateUIToFP(OMPScanNumIterations, CGF.DoubleTy);
4236 llvm::Value *LogVal = CGF.EmitNounwindRuntimeCall(F, Arg);
4237 F = CGF.CGM.getIntrinsic(llvm::Intrinsic::ceil, CGF.DoubleTy);
4238 LogVal = CGF.EmitNounwindRuntimeCall(F, LogVal);
4239 LogVal = CGF.Builder.CreateFPToUI(LogVal, CGF.IntTy);
4240 llvm::Value *NMin1 = CGF.Builder.CreateNUWSub(
4241 OMPScanNumIterations, llvm::ConstantInt::get(CGF.SizeTy, 1));
4243 CGF.EmitBlock(LoopBB);
4244 auto *Counter = CGF.Builder.CreatePHI(CGF.IntTy, 2);
4246 auto *Pow2K = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
4247 Counter->addIncoming(llvm::ConstantInt::get(CGF.IntTy, 0), InputBB);
4248 Pow2K->addIncoming(llvm::ConstantInt::get(CGF.SizeTy, 1), InputBB);
4251 llvm::BasicBlock *InnerLoopBB =
4252 CGF.createBasicBlock(
"omp.inner.log.scan.body");
4253 llvm::BasicBlock *InnerExitBB =
4254 CGF.createBasicBlock(
"omp.inner.log.scan.exit");
4255 llvm::Value *CmpI = CGF.Builder.CreateICmpUGE(NMin1, Pow2K);
4256 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4257 CGF.EmitBlock(InnerLoopBB);
4258 auto *IVal = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
4259 IVal->addIncoming(NMin1, LoopBB);
4262 auto *ILHS = LHSs.begin();
4263 auto *IRHS = RHSs.begin();
4264 for (
const Expr *CopyArrayElem : CopyArrayElems) {
4274 LHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4279 llvm::Value *OffsetIVal = CGF.Builder.CreateNUWSub(IVal, Pow2K);
4285 RHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4292 CGF.CGM.getOpenMPRuntime().emitReduction(
4293 CGF, S.getEndLoc(),
Privates, LHSs, RHSs, ReductionOps,
4297 llvm::Value *NextIVal =
4298 CGF.Builder.CreateNUWSub(IVal, llvm::ConstantInt::get(CGF.SizeTy, 1));
4299 IVal->addIncoming(NextIVal, CGF.Builder.GetInsertBlock());
4300 CmpI = CGF.Builder.CreateICmpUGE(NextIVal, Pow2K);
4301 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4302 CGF.EmitBlock(InnerExitBB);
4304 CGF.Builder.CreateNUWAdd(Counter, llvm::ConstantInt::get(CGF.IntTy, 1));
4305 Counter->addIncoming(
Next, CGF.Builder.GetInsertBlock());
4307 llvm::Value *NextPow2K =
4308 CGF.Builder.CreateShl(Pow2K, 1,
"",
true);
4309 Pow2K->addIncoming(NextPow2K, CGF.Builder.GetInsertBlock());
4310 llvm::Value *
Cmp = CGF.Builder.CreateICmpNE(
Next, LogVal);
4311 CGF.Builder.CreateCondBr(
Cmp, LoopBB, ExitBB);
4313 CGF.EmitBlock(ExitBB);
4319 CGF, S.getBeginLoc(), OMPD_unknown,
false,
4322 RegionCodeGenTy RCG(CodeGen);
4333 bool HasLastprivates;
4335 if (llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4336 [](
const OMPReductionClause *
C) {
4337 return C->getModifier() == OMPC_REDUCTION_inscan;
4341 OMPLoopScope LoopScope(CGF, S);
4344 const auto &&FirstGen = [&S, HasCancel, EKind](
CodeGenFunction &CGF) {
4353 const auto &&SecondGen = [&S, HasCancel, EKind,
4371 return HasLastprivates;
4384 if (
auto *SC = dyn_cast<OMPScheduleClause>(
C)) {
4389 switch (SC->getScheduleKind()) {
4390 case OMPC_SCHEDULE_auto:
4391 case OMPC_SCHEDULE_dynamic:
4392 case OMPC_SCHEDULE_runtime:
4393 case OMPC_SCHEDULE_guided:
4394 case OMPC_SCHEDULE_static:
4407static llvm::omp::ScheduleKind
4409 switch (ScheduleClauseKind) {
4411 return llvm::omp::OMP_SCHEDULE_Default;
4412 case OMPC_SCHEDULE_auto:
4413 return llvm::omp::OMP_SCHEDULE_Auto;
4414 case OMPC_SCHEDULE_dynamic:
4415 return llvm::omp::OMP_SCHEDULE_Dynamic;
4416 case OMPC_SCHEDULE_guided:
4417 return llvm::omp::OMP_SCHEDULE_Guided;
4418 case OMPC_SCHEDULE_runtime:
4419 return llvm::omp::OMP_SCHEDULE_Runtime;
4420 case OMPC_SCHEDULE_static:
4421 return llvm::omp::OMP_SCHEDULE_Static;
4423 llvm_unreachable(
"Unhandled schedule kind");
4430 bool HasLastprivates =
false;
4433 auto &&
CodeGen = [&S, &
CGM, HasCancel, &HasLastprivates,
4436 if (UseOMPIRBuilder) {
4437 bool NeedsBarrier = !S.getSingleClause<OMPNowaitClause>();
4439 llvm::omp::ScheduleKind SchedKind = llvm::omp::OMP_SCHEDULE_Default;
4440 llvm::Value *ChunkSize =
nullptr;
4441 if (
auto *SchedClause = S.getSingleClause<OMPScheduleClause>()) {
4444 if (
const Expr *ChunkSizeExpr = SchedClause->getChunkSize())
4449 const Stmt *Inner = S.getRawStmt();
4450 llvm::CanonicalLoopInfo *CLI =
4453 llvm::OpenMPIRBuilder &OMPBuilder =
4455 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4457 cantFail(OMPBuilder.applyWorkshareLoop(
4458 CGF.
Builder.getCurrentDebugLocation(), CLI, AllocaIP, NeedsBarrier,
4459 SchedKind, ChunkSize,
false,
4470 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
4475 if (!UseOMPIRBuilder) {
4477 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4489 bool HasLastprivates =
false;
4490 auto &&
CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
4497 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4498 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
4502 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4503 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_for);
4510 llvm::Value *
Init =
nullptr) {
4517void CodeGenFunction::EmitSections(
const OMPExecutableDirective &S) {
4518 const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4519 const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt);
4520 bool HasLastprivates =
false;
4522 auto &&CodeGen = [&S, CapturedStmt, CS, EKind,
4523 &HasLastprivates](CodeGenFunction &CGF, PrePostActionTy &) {
4524 const ASTContext &
C = CGF.getContext();
4525 QualType KmpInt32Ty =
4526 C.getIntTypeForBitwidth(32, 1);
4529 CGF.Builder.getInt32(0));
4530 llvm::ConstantInt *GlobalUBVal = CS !=
nullptr
4531 ? CGF.Builder.getInt32(CS->size() - 1)
4532 : CGF.Builder.getInt32(0);
4536 CGF.Builder.getInt32(1));
4538 CGF.Builder.getInt32(0));
4541 OpaqueValueExpr IVRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4542 CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
4543 OpaqueValueExpr UBRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4544 CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
4548 S.getBeginLoc(), FPOptionsOverride());
4552 S.getBeginLoc(),
true, FPOptionsOverride());
4553 auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
4565 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".omp.sections.exit");
4566 llvm::SwitchInst *SwitchStmt =
4567 CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.
getBeginLoc()),
4568 ExitBB, CS ==
nullptr ? 1 : CS->size());
4570 unsigned CaseNumber = 0;
4571 for (
const Stmt *SubStmt : CS->
children()) {
4572 auto CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4573 CGF.EmitBlock(CaseBB);
4574 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
4575 CGF.EmitStmt(SubStmt);
4576 CGF.EmitBranch(ExitBB);
4580 llvm::BasicBlock *CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4581 CGF.EmitBlock(CaseBB);
4582 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
4583 CGF.EmitStmt(CapturedStmt);
4584 CGF.EmitBranch(ExitBB);
4586 CGF.EmitBlock(ExitBB,
true);
4589 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
4590 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
4594 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
4598 CGF.EmitOMPPrivateClause(S, LoopScope);
4599 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(CGF, S, IV);
4600 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
4601 CGF.EmitOMPReductionClauseInit(S, LoopScope);
4602 (void)LoopScope.Privatize();
4604 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
4607 OpenMPScheduleTy ScheduleKind;
4608 ScheduleKind.
Schedule = OMPC_SCHEDULE_static;
4609 CGOpenMPRuntime::StaticRTInput StaticInit(
4610 32,
true,
false, IL.getAddress(),
4611 LB.getAddress(), UB.getAddress(), ST.getAddress());
4612 CGF.CGM.getOpenMPRuntime().emitForStaticInit(CGF, S.
getBeginLoc(), EKind,
4613 ScheduleKind, StaticInit);
4615 llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.
getBeginLoc());
4616 llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
4617 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
4618 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
4620 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.
getBeginLoc()), IV);
4622 CGF.EmitOMPInnerLoop(S,
false,
Cond, Inc, BodyGen,
4623 [](CodeGenFunction &) {});
4625 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
4626 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.
getEndLoc(),
4629 CGF.OMPCancelStack.emitExit(CGF, EKind, CodeGen);
4630 CGF.EmitOMPReductionClauseFinal(S, OMPD_parallel);
4633 return CGF.
Builder.CreateIsNotNull(
4638 if (HasLastprivates)
4645 bool HasCancel =
false;
4646 if (
auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
4647 HasCancel = OSD->hasCancel();
4648 else if (
auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
4649 HasCancel = OPSD->hasCancel();
4651 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_sections, CodeGen,
4656 if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) {
4674 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4679 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4680 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_scope,
CodeGen);
4683 if (!S.getSingleClause<OMPNowaitClause>()) {
4684 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_scope);
4691 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4692 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4693 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4694 using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
4696 auto FiniCB = [](InsertPointTy IP) {
4699 return llvm::Error::success();
4702 const CapturedStmt *ICS = S.getInnermostCapturedStmt();
4708 auto SectionCB = [
this, SubStmt](
4709 InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4712 CodeGenIP,
"section");
4713 return llvm::Error::success();
4715 SectionCBVector.push_back(SectionCB);
4719 [
this,
CapturedStmt](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4723 return llvm::Error::success();
4725 SectionCBVector.push_back(SectionCB);
4732 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
4733 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
4743 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4745 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4746 cantFail(OMPBuilder.createSections(
4747 Builder, AllocaIP, SectionCBVector, PrivCB, FiniCB, S.hasCancel(),
4748 S.getSingleClause<OMPNowaitClause>()));
4755 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4759 if (!S.getSingleClause<OMPNowaitClause>()) {
4760 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(),
4768 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4769 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4770 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4772 const Stmt *SectionRegionBodyStmt = S.getAssociatedStmt();
4773 auto FiniCB = [
this](InsertPointTy IP) {
4775 return llvm::Error::success();
4778 auto BodyGenCB = [SectionRegionBodyStmt,
4779 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4782 *
this, SectionRegionBodyStmt, AllocIP, CodeGenIP,
"section");
4783 return llvm::Error::success();
4788 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4789 cantFail(OMPBuilder.createSection(
Builder, BodyGenCB, FiniCB));
4809 CopyprivateVars.append(
C->varlist_begin(),
C->varlist_end());
4810 DestExprs.append(
C->destination_exprs().begin(),
4811 C->destination_exprs().end());
4812 SrcExprs.append(
C->source_exprs().begin(),
C->source_exprs().end());
4813 AssignmentOps.append(
C->assignment_ops().begin(),
4814 C->assignment_ops().end());
4823 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4828 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4829 CGM.getOpenMPRuntime().emitSingleRegion(*
this,
CodeGen, S.getBeginLoc(),
4830 CopyprivateVars, DestExprs,
4831 SrcExprs, AssignmentOps);
4835 if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) {
4836 CGM.getOpenMPRuntime().emitBarrierCall(
4837 *
this, S.getBeginLoc(),
4838 S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);
4853 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4854 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4855 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4857 const Stmt *MasterRegionBodyStmt = S.getAssociatedStmt();
4859 auto FiniCB = [
this](InsertPointTy IP) {
4861 return llvm::Error::success();
4864 auto BodyGenCB = [MasterRegionBodyStmt,
4865 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4868 *
this, MasterRegionBodyStmt, AllocIP, CodeGenIP,
"master");
4869 return llvm::Error::success();
4874 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4875 cantFail(OMPBuilder.createMaster(
Builder, BodyGenCB, FiniCB));
4890 Expr *Filter =
nullptr;
4892 Filter = FilterClause->getThreadID();
4898 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4899 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4900 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4902 const Stmt *MaskedRegionBodyStmt = S.getAssociatedStmt();
4903 const Expr *Filter =
nullptr;
4905 Filter = FilterClause->getThreadID();
4906 llvm::Value *FilterVal = Filter
4908 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
4910 auto FiniCB = [
this](InsertPointTy IP) {
4912 return llvm::Error::success();
4915 auto BodyGenCB = [MaskedRegionBodyStmt,
4916 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4919 *
this, MaskedRegionBodyStmt, AllocIP, CodeGenIP,
"masked");
4920 return llvm::Error::success();
4925 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
4926 OMPBuilder.createMasked(
Builder, BodyGenCB, FiniCB, FilterVal));
4937 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4938 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4939 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4941 const Stmt *CriticalRegionBodyStmt = S.getAssociatedStmt();
4942 const Expr *Hint =
nullptr;
4943 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4944 Hint = HintClause->getHint();
4949 llvm::Value *HintInst =
nullptr;
4954 auto FiniCB = [
this](InsertPointTy IP) {
4956 return llvm::Error::success();
4959 auto BodyGenCB = [CriticalRegionBodyStmt,
4960 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4963 *
this, CriticalRegionBodyStmt, AllocIP, CodeGenIP,
"critical");
4964 return llvm::Error::success();
4969 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4970 cantFail(OMPBuilder.createCritical(
Builder, BodyGenCB, FiniCB,
4971 S.getDirectiveName().getAsString(),
4980 CGF.
EmitStmt(S.getAssociatedStmt());
4982 const Expr *Hint =
nullptr;
4983 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4984 Hint = HintClause->getHint();
4987 CGM.getOpenMPRuntime().emitCriticalRegion(*
this,
4988 S.getDirectiveName().getAsString(),
4989 CodeGen, S.getBeginLoc(), Hint);
4993 const OMPParallelForDirective &S) {
5002 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
5006 OMPLoopScope LoopScope(CGF, S);
5009 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
5010 [](
const OMPReductionClause *
C) {
5011 return C->getModifier() == OMPC_REDUCTION_inscan;
5027 const OMPParallelForSimdDirective &S) {
5036 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
5040 OMPLoopScope LoopScope(CGF, S);
5043 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
5044 [](
const OMPReductionClause *
C) {
5045 return C->getModifier() == OMPC_REDUCTION_inscan;
5061 const OMPParallelMasterDirective &S) {
5081 [](CodeGenFunction &) {
return nullptr; });
5088 const OMPParallelMaskedDirective &S) {
5108 [](CodeGenFunction &) {
return nullptr; });
5115 const OMPParallelSectionsDirective &S) {
5121 CGF.EmitSections(S);
5135class CheckVarsEscapingUntiedTaskDeclContext final
5140 explicit CheckVarsEscapingUntiedTaskDeclContext() =
default;
5141 ~CheckVarsEscapingUntiedTaskDeclContext() =
default;
5142 void VisitDeclStmt(
const DeclStmt *S) {
5147 if (
const auto *VD = dyn_cast_or_null<VarDecl>(D))
5149 PrivateDecls.push_back(VD);
5153 void VisitCapturedStmt(
const CapturedStmt *) {}
5155 void VisitBlockExpr(
const BlockExpr *) {}
5156 void VisitStmt(
const Stmt *S) {
5159 for (
const Stmt *Child : S->
children())
5165 ArrayRef<const VarDecl *> getPrivateDecls()
const {
return PrivateDecls; }
5173 bool OmpAllMemory =
false;
5176 return C->getDependencyKind() == OMPC_DEPEND_outallmemory ||
5177 C->getDependencyKind() == OMPC_DEPEND_inoutallmemory;
5179 OmpAllMemory =
true;
5184 Data.Dependences.emplace_back(OMPC_DEPEND_outallmemory,
5193 if (Kind == OMPC_DEPEND_outallmemory || Kind == OMPC_DEPEND_inoutallmemory)
5195 if (OmpAllMemory && (Kind == OMPC_DEPEND_out || Kind == OMPC_DEPEND_inout))
5198 Data.Dependences.emplace_back(
C->getDependencyKind(),
C->getModifier());
5199 DD.
DepExprs.append(
C->varlist_begin(),
C->varlist_end());
5208 const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion);
5210 auto PartId = std::next(I);
5211 auto TaskT = std::next(I, 4);
5216 const Expr *
Cond = Clause->getCondition();
5219 Data.Final.setInt(CondConstant);
5224 Data.Final.setInt(
false);
5228 const Expr *Prio = Clause->getPriority();
5229 Data.Priority.setInt(
true);
5237 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
5239 for (
const auto *
C : S.getClausesOfKind<OMPPrivateClause>()) {
5240 auto IRef =
C->varlist_begin();
5241 for (
const Expr *IInit :
C->private_copies()) {
5243 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
5244 Data.PrivateVars.push_back(*IRef);
5245 Data.PrivateCopies.push_back(IInit);
5250 EmittedAsPrivate.clear();
5252 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5253 auto IRef =
C->varlist_begin();
5254 auto IElemInitRef =
C->inits().begin();
5255 for (
const Expr *IInit :
C->private_copies()) {
5257 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
5258 Data.FirstprivateVars.push_back(*IRef);
5259 Data.FirstprivateCopies.push_back(IInit);
5260 Data.FirstprivateInits.push_back(*IElemInitRef);
5267 llvm::MapVector<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
5268 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
5269 auto IRef =
C->varlist_begin();
5270 auto ID =
C->destination_exprs().begin();
5271 for (
const Expr *IInit :
C->private_copies()) {
5273 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
5274 Data.LastprivateVars.push_back(*IRef);
5275 Data.LastprivateCopies.push_back(IInit);
5277 LastprivateDstsOrigs.insert(
5286 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
5287 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5288 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5289 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5290 Data.ReductionOps.append(
C->reduction_ops().begin(),
5291 C->reduction_ops().end());
5292 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5293 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5295 Data.Reductions =
CGM.getOpenMPRuntime().emitTaskReductionInit(
5296 *
this, S.getBeginLoc(), LHSs, RHSs,
Data);
5301 CheckVarsEscapingUntiedTaskDeclContext Checker;
5302 Checker.Visit(S.getInnermostCapturedStmt()->getCapturedStmt());
5303 Data.PrivateLocals.append(Checker.getPrivateDecls().begin(),
5304 Checker.getPrivateDecls().end());
5306 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
5307 CapturedRegion](CodeGenFunction &CGF,
5309 llvm::MapVector<CanonicalDeclPtr<const VarDecl>,
5310 std::pair<Address, Address>>
5315 if (
auto *DI = CGF.getDebugInfo()) {
5316 llvm::SmallDenseMap<const VarDecl *, FieldDecl *> CaptureFields =
5317 CGF.CapturedStmtInfo->getCaptureFields();
5318 llvm::Value *ContextValue = CGF.CapturedStmtInfo->getContextValue();
5319 if (CaptureFields.size() && ContextValue) {
5320 unsigned CharWidth = CGF.getContext().getCharWidth();
5334 for (
auto It = CaptureFields.begin(); It != CaptureFields.end(); ++It) {
5335 const VarDecl *SharedVar = It->first;
5338 CGF.getContext().getASTRecordLayout(CaptureRecord);
5341 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5342 (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue,
5343 CGF.Builder,
false);
5346 auto UpdateExpr = [](llvm::LLVMContext &Ctx,
auto *
Declare,
5351 Ops.push_back(llvm::dwarf::DW_OP_plus_uconst);
5352 Ops.push_back(Offset);
5354 Ops.push_back(llvm::dwarf::DW_OP_deref);
5355 Declare->setExpression(llvm::DIExpression::get(Ctx, Ops));
5357 llvm::Instruction &
Last = CGF.Builder.GetInsertBlock()->back();
5358 if (
auto DDI = dyn_cast<llvm::DbgVariableIntrinsic>(&
Last))
5359 UpdateExpr(DDI->getContext(), DDI, Offset);
5362 assert(!
Last.isTerminator() &&
"unexpected terminator");
5364 CGF.Builder.GetInsertBlock()->getTrailingDbgRecords()) {
5365 for (llvm::DbgVariableRecord &DVR : llvm::reverse(
5366 llvm::filterDbgVars(Marker->getDbgRecordRange()))) {
5367 UpdateExpr(
Last.getContext(), &DVR, Offset);
5375 if (!
Data.PrivateVars.empty() || !
Data.FirstprivateVars.empty() ||
5376 !
Data.LastprivateVars.empty() || !
Data.PrivateLocals.empty()) {
5377 enum { PrivatesParam = 2, CopyFnParam = 3 };
5378 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5380 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5386 CallArgs.push_back(PrivatesPtr);
5387 ParamTypes.push_back(PrivatesPtr->getType());
5388 for (
const Expr *E :
Data.PrivateVars) {
5390 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5391 CGF.getContext().getPointerType(E->
getType()),
".priv.ptr.addr");
5392 PrivatePtrs.emplace_back(VD, PrivatePtr);
5394 ParamTypes.push_back(PrivatePtr.
getType());
5396 for (
const Expr *E :
Data.FirstprivateVars) {
5398 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5399 CGF.getContext().getPointerType(E->
getType()),
5400 ".firstpriv.ptr.addr");
5401 PrivatePtrs.emplace_back(VD, PrivatePtr);
5402 FirstprivatePtrs.emplace_back(VD, PrivatePtr);
5404 ParamTypes.push_back(PrivatePtr.
getType());
5406 for (
const Expr *E :
Data.LastprivateVars) {
5408 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5409 CGF.getContext().getPointerType(E->
getType()),
5410 ".lastpriv.ptr.addr");
5411 PrivatePtrs.emplace_back(VD, PrivatePtr);
5413 ParamTypes.push_back(PrivatePtr.
getType());
5418 Ty = CGF.getContext().getPointerType(Ty);
5420 Ty = CGF.getContext().getPointerType(Ty);
5421 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5422 CGF.getContext().getPointerType(Ty),
".local.ptr.addr");
5423 auto Result = UntiedLocalVars.insert(
5426 if (
Result.second ==
false)
5427 *
Result.first = std::make_pair(
5430 ParamTypes.push_back(PrivatePtr.
getType());
5432 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5434 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5435 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5436 for (
const auto &Pair : LastprivateDstsOrigs) {
5440 CGF.CapturedStmtInfo->lookup(OrigVD) !=
nullptr,
5442 Pair.second->getExprLoc());
5443 Scope.addPrivate(Pair.first, CGF.EmitLValue(&DRE).getAddress());
5445 for (
const auto &Pair : PrivatePtrs) {
5447 CGF.Builder.CreateLoad(Pair.second),
5448 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5449 CGF.getContext().getDeclAlign(Pair.first));
5450 Scope.addPrivate(Pair.first, Replacement);
5451 if (
auto *DI = CGF.getDebugInfo())
5452 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5453 (void)DI->EmitDeclareOfAutoVariable(
5454 Pair.first, Pair.second.getBasePointer(), CGF.Builder,
5459 for (
auto &Pair : UntiedLocalVars) {
5460 QualType VDType = Pair.first->getType().getNonReferenceType();
5461 if (Pair.first->getType()->isLValueReferenceType())
5462 VDType = CGF.getContext().getPointerType(VDType);
5464 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5467 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(VDType)),
5468 CGF.getPointerAlign());
5469 Pair.second.first = Replacement;
5470 Ptr = CGF.Builder.CreateLoad(Replacement);
5471 Replacement =
Address(Ptr, CGF.ConvertTypeForMem(VDType),
5472 CGF.getContext().getDeclAlign(Pair.first));
5473 Pair.second.second = Replacement;
5475 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5476 Address Replacement(Ptr, CGF.ConvertTypeForMem(VDType),
5477 CGF.getContext().getDeclAlign(Pair.first));
5478 Pair.second.first = Replacement;
5482 if (
Data.Reductions) {
5484 for (
const auto &Pair : FirstprivatePtrs) {
5486 CGF.Builder.CreateLoad(Pair.second),
5487 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5488 CGF.getContext().getDeclAlign(Pair.first));
5489 FirstprivateScope.
addPrivate(Pair.first, Replacement);
5492 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5494 Data.ReductionCopies,
Data.ReductionOps);
5495 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
5497 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5503 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5505 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5508 CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF),
5509 CGF.getContext().VoidPtrTy,
5510 CGF.getContext().getPointerType(
5511 Data.ReductionCopies[Cnt]->getType()),
5512 Data.ReductionCopies[Cnt]->getExprLoc()),
5513 CGF.ConvertTypeForMem(
Data.ReductionCopies[Cnt]->getType()),
5514 Replacement.getAlignment());
5520 (void)
Scope.Privatize();
5525 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5526 auto IPriv =
C->privates().begin();
5527 auto IRed =
C->reduction_ops().begin();
5528 auto ITD =
C->taskgroup_descriptors().begin();
5529 for (
const Expr *Ref :
C->varlist()) {
5530 InRedVars.emplace_back(Ref);
5531 InRedPrivs.emplace_back(*IPriv);
5532 InRedOps.emplace_back(*IRed);
5533 TaskgroupDescriptors.emplace_back(*ITD);
5534 std::advance(IPriv, 1);
5535 std::advance(IRed, 1);
5536 std::advance(ITD, 1);
5542 if (!InRedVars.empty()) {
5544 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5552 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5554 llvm::Value *ReductionsPtr;
5555 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5556 ReductionsPtr = CGF.EmitLoadOfScalar(CGF.EmitLValue(TRExpr),
5557 TRExpr->getExprLoc());
5559 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5561 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5564 CGF.EmitScalarConversion(
5565 Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy,
5566 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
5567 InRedPrivs[Cnt]->getExprLoc()),
5568 CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()),
5569 Replacement.getAlignment());
5582 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5583 S, *I, *PartId, *TaskT, EKind,
CodeGen,
Data.Tied,
Data.NumberOfParts);
5584 OMPLexicalScope
Scope(*
this, S, std::nullopt,
5587 TaskGen(*
this, OutlinedFn,
Data);
5604 QualType ElemType =
C.getBaseElementType(Ty);
5614 Data.FirstprivateVars.emplace_back(OrigRef);
5615 Data.FirstprivateCopies.emplace_back(PrivateRef);
5616 Data.FirstprivateInits.emplace_back(InitRef);
5629 auto PartId = std::next(I);
5630 auto TaskT = std::next(I, 4);
5633 Data.Final.setInt(
false);
5635 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5636 auto IRef =
C->varlist_begin();
5637 auto IElemInitRef =
C->inits().begin();
5638 for (
auto *IInit :
C->private_copies()) {
5639 Data.FirstprivateVars.push_back(*IRef);
5640 Data.FirstprivateCopies.push_back(IInit);
5641 Data.FirstprivateInits.push_back(*IElemInitRef);
5648 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5649 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5650 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5651 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5652 Data.ReductionOps.append(
C->reduction_ops().begin(),
5653 C->reduction_ops().end());
5654 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5655 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5670 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5672 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5684 if (!isa_and_nonnull<llvm::ConstantPointerNull>(
5687 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5694 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, BPVD, PVD, SVD, MVD, EKind,
5698 if (!
Data.FirstprivateVars.empty()) {
5699 enum { PrivatesParam = 2, CopyFnParam = 3 };
5700 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5702 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5708 CallArgs.push_back(PrivatesPtr);
5709 ParamTypes.push_back(PrivatesPtr->getType());
5710 for (
const Expr *E :
Data.FirstprivateVars) {
5712 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5713 CGF.getContext().getPointerType(E->
getType()),
5714 ".firstpriv.ptr.addr");
5715 PrivatePtrs.emplace_back(VD, PrivatePtr);
5717 ParamTypes.push_back(PrivatePtr.
getType());
5719 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5721 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5722 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5723 for (
const auto &Pair : PrivatePtrs) {
5725 CGF.Builder.CreateLoad(Pair.second),
5726 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5727 CGF.getContext().getDeclAlign(Pair.first));
5728 Scope.addPrivate(Pair.first, Replacement);
5731 CGF.processInReduction(S,
Data, CGF, CS,
Scope);
5734 CGF.GetAddrOfLocalVar(BPVD), 0);
5736 CGF.GetAddrOfLocalVar(PVD), 0);
5737 InputInfo.
SizesArray = CGF.Builder.CreateConstArrayGEP(
5738 CGF.GetAddrOfLocalVar(SVD), 0);
5741 InputInfo.
MappersArray = CGF.Builder.CreateConstArrayGEP(
5742 CGF.GetAddrOfLocalVar(MVD), 0);
5746 OMPLexicalScope LexScope(CGF, S, OMPD_task,
false);
5748 if (CGF.CGM.getLangOpts().OpenMP >= 51 &&
5753 CGF.CGM.getOpenMPRuntime().emitThreadLimitClause(
5754 CGF, TL->getThreadLimit().front(), S.getBeginLoc());
5758 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5759 S, *I, *PartId, *TaskT, EKind,
CodeGen,
true,
5760 Data.NumberOfParts);
5761 llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<OMPNowaitClause>() ? 1 : 0);
5765 CGM.getOpenMPRuntime().emitTaskCall(*
this, S.getBeginLoc(), S, OutlinedFn,
5766 SharedsTy, CapturedStruct, &IfCond,
Data);
5771 CodeGenFunction &CGF,
5775 if (
Data.Reductions) {
5777 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5779 Data.ReductionCopies,
Data.ReductionOps);
5782 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5796 Data.ReductionCopies[Cnt]->getType()),
5797 Data.ReductionCopies[Cnt]->getExprLoc()),
5799 Replacement.getAlignment());
5804 (void)
Scope.Privatize();
5809 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5810 auto IPriv =
C->privates().begin();
5811 auto IRed =
C->reduction_ops().begin();
5812 auto ITD =
C->taskgroup_descriptors().begin();
5813 for (
const Expr *Ref :
C->varlist()) {
5814 InRedVars.emplace_back(Ref);
5815 InRedPrivs.emplace_back(*IPriv);
5816 InRedOps.emplace_back(*IRed);
5817 TaskgroupDescriptors.emplace_back(*ITD);
5818 std::advance(IPriv, 1);
5819 std::advance(IRed, 1);
5820 std::advance(ITD, 1);
5824 if (!InRedVars.empty()) {
5826 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5834 llvm::Value *ReductionsPtr;
5835 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5839 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
5847 InRedPrivs[Cnt]->getExprLoc()),
5849 Replacement.getAlignment());
5863 const Expr *IfCond =
nullptr;
5864 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
5865 if (
C->getNameModifier() == OMPD_unknown ||
5866 C->getNameModifier() == OMPD_task) {
5867 IfCond =
C->getCondition();
5874 Data.Tied = !S.getSingleClause<OMPUntiedClause>();
5878 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
5879 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
5882 SharedsTy, CapturedStruct, IfCond,
5891 const OMPTaskyieldDirective &S) {
5892 CGM.getOpenMPRuntime().emitTaskyieldCall(*
this, S.getBeginLoc());
5896 const OMPMessageClause *MC = S.getSingleClause<OMPMessageClause>();
5897 Expr *ME = MC ? MC->getMessageString() :
nullptr;
5898 const OMPSeverityClause *SC = S.getSingleClause<OMPSeverityClause>();
5899 bool IsFatal =
false;
5900 if (!SC || SC->getSeverityKind() == OMPC_SEVERITY_fatal)
5902 CGM.getOpenMPRuntime().emitErrorCall(*
this, S.getBeginLoc(), ME, IsFatal);
5906 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_barrier);
5913 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
5914 CGM.getOpenMPRuntime().emitTaskwaitCall(*
this, S.getBeginLoc(),
Data);
5918 return T.clauses().empty();
5922 const OMPTaskgroupDirective &S) {
5923 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
5925 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
5926 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5930 auto BodyGenCB = [&,
this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
5933 EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5934 return llvm::Error::success();
5939 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5940 cantFail(OMPBuilder.createTaskgroup(
Builder, AllocaIP,
5947 if (
const Expr *E = S.getReductionRef()) {
5951 for (
const auto *
C : S.getClausesOfKind<OMPTaskReductionClause>()) {
5952 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5953 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5954 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5955 Data.ReductionOps.append(
C->reduction_ops().begin(),
5956 C->reduction_ops().end());
5957 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5958 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5960 llvm::Value *ReductionDesc =
5968 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5970 CGM.getOpenMPRuntime().emitTaskgroupRegion(*
this,
CodeGen, S.getBeginLoc());
5975 ? llvm::AtomicOrdering::NotAtomic
5976 : llvm::AtomicOrdering::AcquireRelease;
5977 CGM.getOpenMPRuntime().emitFlush(
5980 if (
const auto *FlushClause = S.getSingleClause<
OMPFlushClause>())
5982 FlushClause->varlist_end());
5985 S.getBeginLoc(), AO);
5995 for (
auto &Dep :
Data.Dependences) {
5996 Address DepAddr =
CGM.getOpenMPRuntime().emitDepobjDependClause(
5997 *
this, Dep, DC->getBeginLoc());
6003 CGM.getOpenMPRuntime().emitDestroyClause(*
this, DOLVal, DC->getBeginLoc());
6006 if (
const auto *UC = S.getSingleClause<OMPUpdateDependObjectsClause>()) {
6007 CGM.getOpenMPRuntime().emitUpdateDependObjectsClause(
6008 *
this, DOLVal, UC->getDependencyKind(), UC->getBeginLoc());
6026 for (
const auto *
C : ParentDir.getClausesOfKind<OMPReductionClause>()) {
6027 if (
C->getModifier() != OMPC_REDUCTION_inscan)
6029 Shareds.append(
C->varlist_begin(),
C->varlist_end());
6030 Privates.append(
C->privates().begin(),
C->privates().end());
6031 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
6032 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
6033 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
6034 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
6035 CopyArrayTemps.append(
C->copy_array_temps().begin(),
6036 C->copy_array_temps().end());
6037 CopyArrayElems.append(
C->copy_array_elems().begin(),
6038 C->copy_array_elems().end());
6040 if (ParentDir.getDirectiveKind() == OMPD_simd ||
6082 : BreakContinueStack.back().ContinueBlock.getBlock());
6093 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6095 const Expr *TempExpr = CopyArrayTemps[I];
6107 CGM.getOpenMPRuntime().emitReduction(
6108 *
this, ParentDir.getEndLoc(),
Privates, LHSs, RHSs, ReductionOps,
6111 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6119 const Expr *TempExpr = CopyArrayTemps[I];
6131 ? BreakContinueStack.back().ContinueBlock.getBlock()
6137 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6143 .getIterationVariable()
6144 ->IgnoreParenImpCasts();
6147 IdxVal = Builder.CreateIntCast(IdxVal,
SizeTy,
false);
6148 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6150 const Expr *OrigExpr = Shareds[I];
6151 const Expr *CopyArrayElem = CopyArrayElems[I];
6152 OpaqueValueMapping IdxMapping(
6165 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6168 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6174 .getIterationVariable()
6175 ->IgnoreParenImpCasts();
6179 llvm::BasicBlock *ExclusiveExitBB =
nullptr;
6183 llvm::Value *
Cmp =
Builder.CreateIsNull(IdxVal);
6184 Builder.CreateCondBr(
Cmp, ExclusiveExitBB, ContBB);
6187 IdxVal =
Builder.CreateNUWSub(IdxVal, llvm::ConstantInt::get(
SizeTy, 1));
6189 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6190 const Expr *PrivateExpr =
Privates[I];
6191 const Expr *OrigExpr = Shareds[I];
6192 const Expr *CopyArrayElem = CopyArrayElems[I];
6201 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
6225 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
6233 bool HasLastprivateClause =
false;
6236 OMPLoopScope PreInitScope(*
this, S);
6241 llvm::BasicBlock *ContBlock =
nullptr;
6248 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
6262 ? S.getCombinedLowerBoundVariable()
6263 : S.getLowerBoundVariable())));
6267 ? S.getCombinedUpperBoundVariable()
6268 : S.getUpperBoundVariable())));
6279 CGM.getOpenMPRuntime().emitBarrierCall(
6280 *
this, S.getBeginLoc(), OMPD_unknown,
false,
6292 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
6295 llvm::Value *Chunk =
nullptr;
6298 ScheduleKind =
C->getDistScheduleKind();
6299 if (
const Expr *Ch =
C->getChunkSize()) {
6302 S.getIterationVariable()->getType(),
6307 CGM.getOpenMPRuntime().getDefaultDistScheduleAndChunk(
6308 *
this, S, ScheduleKind, Chunk);
6329 bool StaticChunked =
6333 Chunk !=
nullptr) ||
6338 StaticChunked ? Chunk :
nullptr);
6346 ? S.getCombinedEnsureUpperBound()
6347 : S.getEnsureUpperBound());
6351 ? S.getCombinedInit()
6356 ? S.getCombinedCond()
6360 Cond = S.getCombinedDistCond();
6392 [&S, &LoopScope,
Cond, IncExpr,
LoopExit, &CodeGenLoop,
6395 S, LoopScope.requiresCleanups(),
Cond, IncExpr,
6396 [&S,
LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
6397 CodeGenLoop(CGF, S, LoopExit);
6399 [&S, StaticChunked](CodeGenFunction &CGF) {
6400 if (StaticChunked) {
6401 CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound());
6402 CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound());
6403 CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound());
6404 CGF.EmitIgnoredExpr(S.getCombinedInit());
6414 const OMPLoopArguments LoopArguments = {
6417 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments,
6423 return CGF.
Builder.CreateIsNotNull(
6433 *
this, S, [IL, &S](CodeGenFunction &CGF) {
6434 return CGF.
Builder.CreateIsNotNull(
6439 if (HasLastprivateClause) {
6462 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
6471static llvm::Function *
6478 Fn->setDoesNotRecurse();
6482template <
typename T>
6484 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP,
6485 llvm::OpenMPIRBuilder &OMPBuilder) {
6487 unsigned NumLoops =
C->getNumLoops();
6491 for (
unsigned I = 0; I < NumLoops; I++) {
6492 const Expr *CounterVal =
C->getLoopData(I);
6497 StoreValues.emplace_back(StoreValue);
6499 OMPDoacrossKind<T> ODK;
6500 bool IsDependSource = ODK.isSource(
C);
6502 OMPBuilder.createOrderedDepend(CGF.
Builder, AllocaIP, NumLoops,
6503 StoreValues,
".cnt.addr", IsDependSource));
6507 const OMPOrderedStandaloneDirective &S) {
6510 "Standalone ordered directive should have either depend or doacross "
6513 assert(!S.hasAssociatedStmt() &&
"No associated statement must be in "
6514 "ordered depend|doacross construct.");
6516 if (
CGM.getLangOpts().OpenMPIRBuilder) {
6517 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
6518 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6531 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6534 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6539 const OMPOrderedBlockAssocDirective &S) {
6540 if (
CGM.getLangOpts().OpenMPIRBuilder) {
6541 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
6542 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6548 auto FiniCB = [
this](InsertPointTy IP) {
6550 return llvm::Error::success();
6553 auto BodyGenCB = [&S,
C,
this](InsertPointTy AllocIP,
6554 InsertPointTy CodeGenIP,
6560 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
6561 Builder,
false,
".ordered.after");
6565 assert(S.getBeginLoc().isValid() &&
6566 "Outlined function call location must be valid.");
6569 OutlinedFn, CapturedVars);
6574 return llvm::Error::success();
6577 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6578 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
6579 OMPBuilder.createOrderedThreadsSimd(
Builder, BodyGenCB, FiniCB, !
C));
6585 auto &&
CodeGen = [&S,
C,
this](CodeGenFunction &CGF,
6590 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
6592 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
6593 OutlinedFn, CapturedVars);
6599 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6600 CGM.getOpenMPRuntime().emitOrderedRegion(*
this,
CodeGen, S.getBeginLoc(), !
C);
6607 "DestType must have scalar evaluation kind.");
6608 assert(!Val.
isAggregate() &&
"Must be a scalar or complex.");
6619 "DestType must have complex evaluation kind.");
6628 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
6630 assert(Val.
isComplex() &&
"Must be a scalar or complex.");
6635 Val.
getComplexVal().first, SrcElementType, DestElementType, Loc);
6637 Val.
getComplexVal().second, SrcElementType, DestElementType, Loc);
6643 LValue LVal,
RValue RVal) {
6644 if (LVal.isGlobalReg())
6651 llvm::AtomicOrdering AO, LValue LVal,
6653 if (LVal.isGlobalReg())
6656 LVal, Loc, llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO),
6665 *
this, RVal, RValTy, LVal.
getType(), Loc)),
6674 llvm_unreachable(
"Must be a scalar or complex.");
6682 assert(
V->isLValue() &&
"V of 'omp atomic read' is not lvalue");
6683 assert(
X->isLValue() &&
"X of 'omp atomic read' is not lvalue");
6692 case llvm::AtomicOrdering::Acquire:
6693 case llvm::AtomicOrdering::AcquireRelease:
6694 case llvm::AtomicOrdering::SequentiallyConsistent:
6696 llvm::AtomicOrdering::Acquire);
6698 case llvm::AtomicOrdering::Monotonic:
6699 case llvm::AtomicOrdering::Release:
6701 case llvm::AtomicOrdering::NotAtomic:
6702 case llvm::AtomicOrdering::Unordered:
6703 llvm_unreachable(
"Unexpected ordering.");
6710 llvm::AtomicOrdering AO,
const Expr *
X,
6713 assert(
X->isLValue() &&
"X of 'omp atomic write' is not lvalue");
6721 case llvm::AtomicOrdering::Release:
6722 case llvm::AtomicOrdering::AcquireRelease:
6723 case llvm::AtomicOrdering::SequentiallyConsistent:
6725 llvm::AtomicOrdering::Release);
6727 case llvm::AtomicOrdering::Acquire:
6728 case llvm::AtomicOrdering::Monotonic:
6730 case llvm::AtomicOrdering::NotAtomic:
6731 case llvm::AtomicOrdering::Unordered:
6732 llvm_unreachable(
"Unexpected ordering.");
6739 llvm::AtomicOrdering AO,
6745 if (BO == BO_Comma || !
Update.isScalar() || !
X.isSimple() ||
6747 (
Update.getScalarVal()->getType() !=
X.getAddress().getElementType())) ||
6748 !Context.getTargetInfo().hasBuiltinAtomic(
6749 Context.getTypeSize(
X.getType()), Context.toBits(
X.getAlignment())))
6750 return std::make_pair(
false,
RValue::get(
nullptr));
6753 if (
T->isIntegerTy())
6756 if (
T->isFloatingPointTy() && (BO == BO_Add || BO == BO_Sub))
6762 if (!CheckAtomicSupport(
Update.getScalarVal()->getType(), BO) ||
6763 !CheckAtomicSupport(
X.getAddress().getElementType(), BO))
6764 return std::make_pair(
false,
RValue::get(
nullptr));
6766 bool IsInteger =
X.getAddress().getElementType()->isIntegerTy();
6767 llvm::AtomicRMWInst::BinOp RMWOp;
6770 RMWOp = IsInteger ? llvm::AtomicRMWInst::Add : llvm::AtomicRMWInst::FAdd;
6774 return std::make_pair(
false,
RValue::get(
nullptr));
6775 RMWOp = IsInteger ? llvm::AtomicRMWInst::Sub : llvm::AtomicRMWInst::FSub;
6778 RMWOp = llvm::AtomicRMWInst::And;
6781 RMWOp = llvm::AtomicRMWInst::Or;
6784 RMWOp = llvm::AtomicRMWInst::Xor;
6788 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6790 : llvm::AtomicRMWInst::Max)
6792 : llvm::AtomicRMWInst::UMax);
6795 : llvm::AtomicRMWInst::FMax;
6799 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6801 : llvm::AtomicRMWInst::Min)
6803 : llvm::AtomicRMWInst::UMin);
6806 : llvm::AtomicRMWInst::FMin;
6809 RMWOp = llvm::AtomicRMWInst::Xchg;
6818 return std::make_pair(
false,
RValue::get(
nullptr));
6837 llvm_unreachable(
"Unsupported atomic update operation");
6839 llvm::Value *UpdateVal =
Update.getScalarVal();
6840 if (
auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
6842 UpdateVal = CGF.
Builder.CreateIntCast(
6843 IC,
X.getAddress().getElementType(),
6844 X.getType()->hasSignedIntegerRepresentation());
6846 UpdateVal = CGF.
Builder.CreateCast(llvm::Instruction::CastOps::UIToFP, IC,
6847 X.getAddress().getElementType());
6849 llvm::AtomicRMWInst *Res =
6866 if (
X.isGlobalReg()) {
6879 llvm::AtomicOrdering AO,
const Expr *
X,
6883 "Update expr in 'atomic update' must be a binary operator.");
6891 assert(
X->isLValue() &&
"X of 'omp atomic update' is not lvalue");
6898 auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](
RValue XRValue) {
6904 XLValue, ExprRValue, BOUE->getOpcode(),
IsXLHSInRHSPart, AO, Loc, Gen);
6911 case llvm::AtomicOrdering::Release:
6912 case llvm::AtomicOrdering::AcquireRelease:
6913 case llvm::AtomicOrdering::SequentiallyConsistent:
6915 llvm::AtomicOrdering::Release);
6917 case llvm::AtomicOrdering::Acquire:
6918 case llvm::AtomicOrdering::Monotonic:
6920 case llvm::AtomicOrdering::NotAtomic:
6921 case llvm::AtomicOrdering::Unordered:
6922 llvm_unreachable(
"Unexpected ordering.");
6940 llvm_unreachable(
"Must be a scalar or complex.");
6944 llvm::AtomicOrdering AO,
6949 assert(
X->isLValue() &&
"X of 'omp atomic capture' is not lvalue");
6950 assert(
V->isLValue() &&
"V of 'omp atomic capture' is not lvalue");
6959 "Update expr in 'atomic capture' must be a binary operator.");
6970 NewVValType = XRValExpr->
getType();
6972 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
6981 XLValue, ExprRValue, BOUE->getOpcode(),
IsXLHSInRHSPart, AO, Loc, Gen);
6987 NewVVal = Res.second;
6998 NewVValType =
X->getType().getNonReferenceType();
7000 X->getType().getNonReferenceType(), Loc);
7001 auto &&Gen = [&NewVVal, ExprRValue](
RValue XRValue) {
7007 XLValue, ExprRValue, BO_Assign,
false, AO,
7028 case llvm::AtomicOrdering::Release:
7030 llvm::AtomicOrdering::Release);
7032 case llvm::AtomicOrdering::Acquire:
7034 llvm::AtomicOrdering::Acquire);
7036 case llvm::AtomicOrdering::AcquireRelease:
7037 case llvm::AtomicOrdering::SequentiallyConsistent:
7039 CGF, {}, Loc, llvm::AtomicOrdering::AcquireRelease);
7041 case llvm::AtomicOrdering::Monotonic:
7043 case llvm::AtomicOrdering::NotAtomic:
7044 case llvm::AtomicOrdering::Unordered:
7045 llvm_unreachable(
"Unexpected ordering.");
7051 CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO,
7055 llvm::OpenMPIRBuilder &OMPBuilder =
7058 OMPAtomicCompareOp Op;
7062 Op = OMPAtomicCompareOp::EQ;
7065 Op = OMPAtomicCompareOp::MIN;
7068 Op = OMPAtomicCompareOp::MAX;
7071 llvm_unreachable(
"unsupported atomic compare binary operator");
7075 Address XAddr = XLVal.getAddress();
7077 auto EmitRValueWithCastIfNeeded = [&CGF, Loc](
const Expr *
X,
const Expr *E) {
7082 if (NewE->
getType() ==
X->getType())
7087 llvm::Value *EVal = EmitRValueWithCastIfNeeded(
X, E);
7088 llvm::Value *DVal = D ? EmitRValueWithCastIfNeeded(
X, D) :
nullptr;
7089 if (
auto *CI = dyn_cast<llvm::ConstantInt>(EVal))
7090 EVal = CGF.
Builder.CreateIntCast(
7091 CI, XLVal.getAddress().getElementType(),
7094 if (
auto *CI = dyn_cast<llvm::ConstantInt>(DVal))
7095 DVal = CGF.
Builder.CreateIntCast(
7096 CI, XLVal.getAddress().getElementType(),
7099 llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{
7101 X->getType()->hasSignedIntegerRepresentation(),
7102 X->getType().isVolatileQualified()};
7103 llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal;
7107 VOpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
7108 V->getType()->hasSignedIntegerRepresentation(),
7109 V->getType().isVolatileQualified()};
7114 ROpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
7115 R->getType()->hasSignedIntegerRepresentation(),
7116 R->getType().isVolatileQualified()};
7119 if (FailAO == llvm::AtomicOrdering::NotAtomic) {
7122 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
7123 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
7126 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
7127 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
7132 llvm::AtomicOrdering AO,
7153 case OMPC_compare: {
7159 llvm_unreachable(
"Clause is not allowed in 'omp atomic'.");
7164 llvm::AtomicOrdering AO =
CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
7166 llvm::AtomicOrdering FailAO = llvm::AtomicOrdering::NotAtomic;
7167 bool MemOrderingSpecified =
false;
7168 if (S.getSingleClause<OMPSeqCstClause>()) {
7169 AO = llvm::AtomicOrdering::SequentiallyConsistent;
7170 MemOrderingSpecified =
true;
7171 }
else if (S.getSingleClause<OMPAcqRelClause>()) {
7172 AO = llvm::AtomicOrdering::AcquireRelease;
7173 MemOrderingSpecified =
true;
7174 }
else if (S.getSingleClause<OMPAcquireClause>()) {
7175 AO = llvm::AtomicOrdering::Acquire;
7176 MemOrderingSpecified =
true;
7177 }
else if (S.getSingleClause<OMPReleaseClause>()) {
7178 AO = llvm::AtomicOrdering::Release;
7179 MemOrderingSpecified =
true;
7180 }
else if (S.getSingleClause<OMPRelaxedClause>()) {
7181 AO = llvm::AtomicOrdering::Monotonic;
7182 MemOrderingSpecified =
true;
7184 llvm::SmallSet<OpenMPClauseKind, 2> KindsEncountered;
7193 if (K == OMPC_seq_cst || K == OMPC_acq_rel || K == OMPC_acquire ||
7194 K == OMPC_release || K == OMPC_relaxed || K == OMPC_hint)
7197 KindsEncountered.insert(K);
7202 if (KindsEncountered.contains(OMPC_compare) &&
7203 KindsEncountered.contains(OMPC_capture))
7204 Kind = OMPC_compare;
7205 if (!MemOrderingSpecified) {
7206 llvm::AtomicOrdering DefaultOrder =
7207 CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
7208 if (DefaultOrder == llvm::AtomicOrdering::Monotonic ||
7209 DefaultOrder == llvm::AtomicOrdering::SequentiallyConsistent ||
7210 (DefaultOrder == llvm::AtomicOrdering::AcquireRelease &&
7211 Kind == OMPC_capture)) {
7213 }
else if (DefaultOrder == llvm::AtomicOrdering::AcquireRelease) {
7214 if (Kind == OMPC_unknown || Kind == OMPC_update || Kind == OMPC_write) {
7215 AO = llvm::AtomicOrdering::Release;
7216 }
else if (Kind == OMPC_read) {
7217 assert(Kind == OMPC_read &&
"Unexpected atomic kind.");
7218 AO = llvm::AtomicOrdering::Acquire;
7223 if (KindsEncountered.contains(OMPC_compare) &&
7224 KindsEncountered.contains(OMPC_fail)) {
7225 Kind = OMPC_compare;
7226 const auto *FailClause = S.getSingleClause<OMPFailClause>();
7229 if (FailParameter == llvm::omp::OMPC_relaxed)
7230 FailAO = llvm::AtomicOrdering::Monotonic;
7231 else if (FailParameter == llvm::omp::OMPC_acquire)
7232 FailAO = llvm::AtomicOrdering::Acquire;
7233 else if (FailParameter == llvm::omp::OMPC_seq_cst)
7234 FailAO = llvm::AtomicOrdering::SequentiallyConsistent;
7241 S.getV(), S.getR(), S.getExpr(), S.getUpdateExpr(),
7242 S.getD(), S.getCondExpr(), S.isXLHSInRHSPart(),
7243 S.isFailOnly(), S.getBeginLoc());
7254 OMPLexicalScope
Scope(CGF, S, OMPD_target);
7257 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
7263 llvm::Function *Fn =
nullptr;
7264 llvm::Constant *FnID =
nullptr;
7266 const Expr *IfCond =
nullptr;
7268 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7269 if (
C->getNameModifier() == OMPD_unknown ||
7270 C->getNameModifier() == OMPD_target) {
7271 IfCond =
C->getCondition();
7277 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device(
7280 Device.setPointerAndInt(
C->getDevice(),
C->getModifier());
7285 bool IsOffloadEntry =
true;
7289 IsOffloadEntry =
false;
7292 IsOffloadEntry =
false;
7294 if (
CGM.
getLangOpts().OpenMPOffloadMandatory && !IsOffloadEntry) {
7298 assert(CGF.
CurFuncDecl &&
"No parent declaration for target region!");
7299 StringRef ParentName;
7302 if (
const auto *D = dyn_cast<CXXConstructorDecl>(CGF.
CurFuncDecl))
7304 else if (
const auto *D = dyn_cast<CXXDestructorDecl>(CGF.
CurFuncDecl))
7313 OMPLexicalScope
Scope(CGF, S, OMPD_task);
7314 auto &&SizeEmitter =
7317 if (IsOffloadEntry) {
7318 OMPLoopScope(CGF, D);
7320 llvm::Value *NumIterations = CGF.
EmitScalarExpr(D.getNumIterations());
7321 NumIterations = CGF.
Builder.CreateIntCast(NumIterations, CGF.
Int64Ty,
7323 return NumIterations;
7341 CGF.
EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
7346 StringRef ParentName,
7352 llvm::Constant *
Addr;
7354 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7356 assert(Fn &&
Addr &&
"Target device function emission failed.");
7370 const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams);
7371 llvm::Function *OutlinedFn =
7376 OMPTeamsScope
Scope(CGF, S);
7381 const Expr *NumTeams = NT ? NT->getNumTeams().front() :
nullptr;
7382 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() :
nullptr;
7389 const Expr *IfCond =
nullptr;
7390 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7391 if (
C->getNameModifier() == OMPD_unknown ||
7392 C->getNameModifier() == OMPD_teams) {
7393 IfCond =
C->getCondition();
7402 const llvm::APInt One(32, 1);
7409 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() :
nullptr;
7435 CGF.
EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt());
7440 [](CodeGenFunction &) {
return nullptr; });
7445 auto *CS = S.getCapturedStmt(OMPD_teams);
7472 llvm::Constant *
Addr;
7474 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7476 assert(Fn &&
Addr &&
"Target device function emission failed.");
7518 llvm::Constant *
Addr;
7520 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7522 assert(Fn &&
Addr &&
"Target device function emission failed.");
7564 llvm::Constant *
Addr;
7566 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7568 assert(Fn &&
Addr &&
"Target device function emission failed.");
7582 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7587 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7599 [](CodeGenFunction &) {
return nullptr; });
7604 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7609 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7621 [](CodeGenFunction &) {
return nullptr; });
7626 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7632 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7644 [](CodeGenFunction &) {
return nullptr; });
7649 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7655 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7662 CGF, OMPD_distribute, CodeGenDistribute,
false);
7668 [](CodeGenFunction &) {
return nullptr; });
7672 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7673 llvm::Value *
Device =
nullptr;
7674 llvm::Value *NumDependences =
nullptr;
7675 llvm::Value *DependenceList =
nullptr;
7683 if (!
Data.Dependences.empty()) {
7685 std::tie(NumDependences, DependenciesArray) =
7686 CGM.getOpenMPRuntime().emitDependClause(*
this,
Data.Dependences,
7690 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
7695 "OMPNowaitClause clause is used separately in OMPInteropDirective.");
7698 if (!ItOMPInitClause.empty()) {
7701 llvm::Value *InteropvarPtr =
7703 llvm::omp::OMPInteropType InteropType =
7704 llvm::omp::OMPInteropType::Unknown;
7705 if (
C->getIsTarget()) {
7706 InteropType = llvm::omp::OMPInteropType::Target;
7708 assert(
C->getIsTargetSync() &&
7709 "Expected interop-type target/targetsync");
7710 InteropType = llvm::omp::OMPInteropType::TargetSync;
7712 OMPBuilder.createOMPInteropInit(
Builder, InteropvarPtr, InteropType,
7713 Device, NumDependences, DependenceList,
7714 Data.HasNowaitClause);
7718 if (!ItOMPDestroyClause.empty()) {
7721 llvm::Value *InteropvarPtr =
7723 OMPBuilder.createOMPInteropDestroy(
Builder, InteropvarPtr,
Device,
7724 NumDependences, DependenceList,
7725 Data.HasNowaitClause);
7728 auto ItOMPUseClause = S.getClausesOfKind<
OMPUseClause>();
7729 if (!ItOMPUseClause.empty()) {
7732 llvm::Value *InteropvarPtr =
7734 OMPBuilder.createOMPInteropUse(
Builder, InteropvarPtr,
Device,
7735 NumDependences, DependenceList,
7736 Data.HasNowaitClause);
7758 CGF, OMPD_distribute, CodeGenDistribute,
false);
7777 llvm::Constant *
Addr;
7779 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7781 assert(Fn &&
Addr &&
"Target device function emission failed.");
7810 CGF, OMPD_distribute, CodeGenDistribute,
false);
7829 llvm::Constant *
Addr;
7831 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7833 assert(Fn &&
Addr &&
"Target device function emission failed.");
7846 CGM.getOpenMPRuntime().emitCancellationPointCall(*
this, S.getBeginLoc(),
7851 const Expr *IfCond =
nullptr;
7852 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7853 if (
C->getNameModifier() == OMPD_unknown ||
7854 C->getNameModifier() == OMPD_cancel) {
7855 IfCond =
C->getCondition();
7859 if (
CGM.getLangOpts().OpenMPIRBuilder) {
7860 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7866 llvm::Value *IfCondition =
nullptr;
7870 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
7872 return Builder.restoreIP(AfterIP);
7876 CGM.getOpenMPRuntime().emitCancelCall(*
this, S.getBeginLoc(), IfCond,
7882 if (Kind == OMPD_parallel || Kind == OMPD_task ||
7883 Kind == OMPD_target_parallel || Kind == OMPD_taskloop ||
7884 Kind == OMPD_master_taskloop || Kind == OMPD_parallel_master_taskloop)
7886 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
7887 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
7888 Kind == OMPD_distribute_parallel_for ||
7889 Kind == OMPD_target_parallel_for ||
7890 Kind == OMPD_teams_distribute_parallel_for ||
7891 Kind == OMPD_target_teams_distribute_parallel_for);
7892 return OMPCancelStack.getExitBlock();
7897 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7898 CaptureDeviceAddrMap) {
7899 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7900 for (
const Expr *OrigVarIt :
C.varlist()) {
7902 if (!Processed.insert(OrigVD).second)
7909 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7914 "Base should be the current struct!");
7915 MatchingVD = ME->getMemberDecl();
7920 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7921 if (InitAddrIt == CaptureDeviceAddrMap.end())
7929 Address(InitAddrIt->second, Ty,
7931 assert(IsRegistered &&
"firstprivate var already registered as private");
7939 while (
const auto *OASE = dyn_cast<ArraySectionExpr>(
Base))
7940 Base = OASE->getBase()->IgnoreParenImpCasts();
7941 while (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(
Base))
7942 Base = ASE->getBase()->IgnoreParenImpCasts();
7948 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7949 CaptureDeviceAddrMap) {
7950 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7951 for (
const Expr *Ref :
C.varlist()) {
7953 if (!Processed.insert(OrigVD).second)
7959 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7964 "Base should be the current struct!");
7965 MatchingVD = ME->getMemberDecl();
7970 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7971 if (InitAddrIt == CaptureDeviceAddrMap.end())
7977 Address(InitAddrIt->second, Ty,
7990 (void)PrivateScope.
addPrivate(OrigVD, PrivAddr);
7998 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
7999 CGM.getOpenMPRuntime().registerVTable(S);
8007 bool PrivatizeDevicePointers =
false;
8009 bool &PrivatizeDevicePointers;
8012 explicit DevicePointerPrivActionTy(
bool &PrivatizeDevicePointers)
8013 : PrivatizeDevicePointers(PrivatizeDevicePointers) {}
8014 void Enter(CodeGenFunction &CGF)
override {
8015 PrivatizeDevicePointers =
true;
8018 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
8021 auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
8022 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
8026 auto &&PrivCodeGen = [&](CodeGenFunction &CGF,
PrePostActionTy &Action) {
8028 PrivatizeDevicePointers =
false;
8034 if (PrivatizeDevicePointers) {
8048 std::optional<OpenMPDirectiveKind> CaptureRegion;
8049 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
8052 for (
const Expr *E :
C->varlist()) {
8054 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
8058 for (
const Expr *E :
C->varlist()) {
8060 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
8064 CaptureRegion = OMPD_unknown;
8067 OMPLexicalScope
Scope(CGF, S, CaptureRegion);
8079 OMPLexicalScope
Scope(CGF, S);
8088 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
8094 const Expr *IfCond =
nullptr;
8096 IfCond =
C->getCondition();
8107 CGM.getOpenMPRuntime().emitTargetDataCalls(*
this, S, IfCond,
Device, RCG,
8115 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8119 const Expr *IfCond =
nullptr;
8121 IfCond =
C->getCondition();
8128 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8129 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8136 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8140 const Expr *IfCond =
nullptr;
8142 IfCond =
C->getCondition();
8149 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8150 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8157 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
8185 llvm::Constant *
Addr;
8187 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8189 assert(Fn &&
Addr &&
"Target device function emission failed.");
8209 CGF, OMPD_target_parallel_for, S.
hasCancel());
8225 llvm::Constant *
Addr;
8227 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8229 assert(Fn &&
Addr &&
"Target device function emission failed.");
8264 llvm::Constant *
Addr;
8266 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8268 assert(Fn &&
Addr &&
"Target device function emission failed.");
8290 const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop);
8293 OMPLexicalScope
Scope(*
this, S, OMPD_taskloop,
false);
8298 const Expr *IfCond =
nullptr;
8299 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
8300 if (
C->getNameModifier() == OMPD_unknown ||
8301 C->getNameModifier() == OMPD_taskloop) {
8302 IfCond =
C->getCondition();
8315 Data.Schedule.setInt(
false);
8318 (Clause->getModifier() == OMPC_GRAINSIZE_strict) ?
true :
false;
8321 Data.Schedule.setInt(
true);
8324 (Clause->getModifier() == OMPC_NUMTASKS_strict) ?
true :
false;
8338 llvm::BasicBlock *ContBlock =
nullptr;
8339 OMPLoopScope PreInitScope(CGF, S);
8340 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
8344 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock(
"taskloop.if.then");
8345 ContBlock = CGF.createBasicBlock(
"taskloop.if.end");
8346 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
8347 CGF.getProfileCount(&S));
8348 CGF.EmitBlock(ThenBlock);
8349 CGF.incrementProfileCounter(&S);
8352 (void)CGF.EmitOMPLinearClauseInit(S);
8356 enum { LowerBound = 5, UpperBound, Stride, LastIter };
8358 auto *LBP = std::next(I, LowerBound);
8359 auto *UBP = std::next(I, UpperBound);
8360 auto *STP = std::next(I, Stride);
8361 auto *LIP = std::next(I, LastIter);
8369 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
8370 CGF.EmitOMPLinearClause(S, LoopScope);
8371 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
8374 const Expr *IVExpr = S.getIterationVariable();
8376 CGF.EmitVarDecl(*IVDecl);
8377 CGF.EmitIgnoredExpr(S.getInit());
8382 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
8385 CGF.EmitIgnoredExpr(S.getCalcLastIteration());
8389 OMPLexicalScope
Scope(CGF, S, OMPD_taskloop,
false);
8399 [&S](CodeGenFunction &CGF) {
8400 emitOMPLoopBodyWithStopPoint(CGF, S,
8401 CodeGenFunction::JumpDest());
8403 [](CodeGenFunction &) {});
8408 CGF.EmitBranch(ContBlock);
8409 CGF.EmitBlock(ContBlock,
true);
8412 if (HasLastprivateClause) {
8413 CGF.EmitOMPLastprivateClauseFinal(
8415 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
8416 CGF.GetAddrOfLocalVar(*LIP),
false,
8417 (*LIP)->getType(), S.getBeginLoc())));
8420 CGF.EmitOMPLinearClauseFinal(S, [LIP, &S](CodeGenFunction &CGF) {
8421 return CGF.
Builder.CreateIsNotNull(
8423 (*LIP)->
getType(), S.getBeginLoc()));
8426 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
8427 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
8429 auto &&
CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
8431 OMPLoopScope PreInitScope(CGF, S);
8432 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S,
8433 OutlinedFn, SharedsTy,
8434 CapturedStruct, IfCond,
Data);
8436 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
8442 CGM.getOpenMPRuntime().emitTaskgroupRegion(
8444 [&S, &BodyGen, &TaskGen, &
Data](CodeGenFunction &CGF,
8464 OMPLexicalScope
Scope(*
this, S);
8476 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8477 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8488 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8489 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8500 OMPLexicalScope
Scope(*
this, S);
8501 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8512 OMPLexicalScope
Scope(*
this, S);
8513 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8519 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8524 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8525 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8537 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8542 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8543 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8555 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8560 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8561 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8573 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8578 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8579 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8593 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8597 const Expr *IfCond =
nullptr;
8599 IfCond =
C->getCondition();
8606 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8607 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8617 BindKind =
C->getBindKind();
8620 case OMPC_BIND_parallel:
8622 case OMPC_BIND_teams:
8624 case OMPC_BIND_thread:
8635 const auto *ForS = dyn_cast<ForStmt>(CS);
8646 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
8647 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_loop,
CodeGen);
8673 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
8678 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
8690 [](CodeGenFunction &) {
return nullptr; });
8695 std::string StatusMsg,
8699 StatusMsg +=
": DEVICE";
8701 StatusMsg +=
": HOST";
8708 llvm::dbgs() << StatusMsg <<
": " <<
FileName <<
": " << LineNo <<
"\n";
8731 CGF, OMPD_distribute, CodeGenDistribute,
false);
8760 CGF, OMPD_distribute, CodeGenDistribute,
false);
8793 llvm::Constant *
Addr;
8795 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8797 assert(Fn &&
Addr &&
8798 "Target device function emission failed for 'target teams loop'.");
8809 CGF, OMPD_target_parallel_loop,
false);
8825 llvm::Constant *
Addr;
8827 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8829 assert(Fn &&
Addr &&
"Target device function emission failed.");
8844 if (
const auto *SD = dyn_cast<OMPScanDirective>(&D)) {
8848 if (!D.hasAssociatedStmt() || !D.getAssociatedStmt())
8854 for (
const auto *
C : D.getClausesOfKind<OMPFirstprivateClause>()) {
8855 for (
const Expr *Ref :
C->varlist()) {
8859 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
8862 if (!CGF.LocalDeclMap.count(VD)) {
8874 if (
const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
8875 for (
const Expr *E : LD->counters()) {
8883 if (!CGF.LocalDeclMap.count(VD))
8887 for (
const auto *
C : D.getClausesOfKind<OMPOrderedClause>()) {
8888 if (!
C->getNumForLoops())
8890 for (
unsigned I = LD->getLoopsNumber(),
8891 E =
C->getLoopNumIterations().size();
8893 if (
const auto *VD = dyn_cast<OMPCapturedExprDecl>(
8896 if (!CGF.LocalDeclMap.count(VD))
8903 CGF.
EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
8906 if (D.getDirectiveKind() == OMPD_atomic ||
8907 D.getDirectiveKind() == OMPD_critical ||
8908 D.getDirectiveKind() == OMPD_section ||
8909 D.getDirectiveKind() == OMPD_master ||
8910 D.getDirectiveKind() == OMPD_masked ||
8911 D.getDirectiveKind() == OMPD_unroll ||
8912 D.getDirectiveKind() == OMPD_assume) {
8917 OMPSimdLexicalScope
Scope(*
this, D);
8918 CGM.getOpenMPRuntime().emitInlinedDirective(
8921 : D.getDirectiveKind(),
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 '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 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 '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...
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 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 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 'pragma omp parallel masked taskloop' directive.
This represents 'pragma omp parallel masked taskloop simd' directive.
This represents 'pragma omp parallel master taskloop' directive.
This represents 'pragma omp parallel master taskloop simd' 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.
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 taskloop' directive.
This represents 'pragma omp taskloop simd' 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.
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.
bool IsXLHSInRHSPart
True if UE has the first form and false if the second.
bool IsPostfixUpdate
True if original value of 'x' must be stored in 'v', not an updated one.
@ 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
bool IsFailOnly
True if 'v' is updated only when the condition is false (compare capture only).
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
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