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"
58 for (
const auto *
C : S.clauses()) {
60 if (
const auto *PreInit =
61 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
62 for (
const auto *I : PreInit->decls()) {
63 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
66 CodeGenFunction::AutoVarEmission Emission =
75 CodeGenFunction::OMPPrivateScope InlinedShareds;
77 static bool isCapturedVar(CodeGenFunction &CGF,
const VarDecl *VD) {
86 CodeGenFunction &CGF,
const OMPExecutableDirective &S,
87 const std::optional<OpenMPDirectiveKind> CapturedRegion = std::nullopt,
88 const bool EmitPreInitStmt =
true)
92 emitPreInitStmt(CGF, S);
95 assert(S.hasAssociatedStmt() &&
96 "Expected associated statement for inlined directive.");
97 const CapturedStmt *CS = S.getCapturedStmt(*CapturedRegion);
99 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
100 auto *VD =
C.getCapturedVar();
102 "Canonical decl must be captured.");
106 InlinedShareds.isGlobalVarCaptured(VD)),
111 (void)InlinedShareds.Privatize();
117class OMPParallelScope final :
public OMPLexicalScope {
118 bool EmitPreInitStmt(
const OMPExecutableDirective &S) {
126 OMPParallelScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
127 : OMPLexicalScope(CGF, S, std::nullopt,
128 EmitPreInitStmt(S)) {}
133class OMPTeamsScope final :
public OMPLexicalScope {
134 bool EmitPreInitStmt(
const OMPExecutableDirective &S) {
141 OMPTeamsScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
142 : OMPLexicalScope(CGF, S, std::nullopt,
143 EmitPreInitStmt(S)) {}
149 void emitPreInitStmt(CodeGenFunction &CGF,
const OMPLoopBasedDirective &S) {
150 const Stmt *PreInits;
151 CodeGenFunction::OMPMapVars PreCondVars;
152 if (
auto *LD = dyn_cast<OMPLoopDirective>(&S)) {
154 (void)OMPLoopBasedDirective::doForAllLoops(
155 LD->getInnermostCapturedStmt()->getCapturedStmt(),
156 true, LD->getLoopsNumber(),
157 [&CGF](
unsigned Cnt,
const Stmt *CurStmt) {
158 if (const auto *CXXFor = dyn_cast<CXXForRangeStmt>(CurStmt)) {
159 if (const Stmt *Init = CXXFor->getInit())
161 CGF.EmitStmt(CXXFor->getRangeStmt());
162 CGF.EmitStmt(CXXFor->getBeginStmt());
163 CGF.EmitStmt(CXXFor->getEndStmt());
167 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
168 for (
const auto *E : LD->counters()) {
175 for (
const auto *
C : LD->getClausesOfKind<OMPPrivateClause>()) {
176 for (
const Expr *IRef :
C->varlist()) {
179 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
180 QualType OrigVDTy = OrigVD->getType().getNonReferenceType();
190 (void)PreCondVars.
apply(CGF);
191 PreInits = LD->getPreInits();
192 }
else if (
const auto *
Tile = dyn_cast<OMPTileDirective>(&S)) {
193 PreInits =
Tile->getPreInits();
194 }
else if (
const auto *Stripe = dyn_cast<OMPStripeDirective>(&S)) {
195 PreInits = Stripe->getPreInits();
196 }
else if (
const auto *Unroll = dyn_cast<OMPUnrollDirective>(&S)) {
197 PreInits = Unroll->getPreInits();
198 }
else if (
const auto *Reverse = dyn_cast<OMPReverseDirective>(&S)) {
199 PreInits = Reverse->getPreInits();
200 }
else if (
const auto *Split = dyn_cast<OMPSplitDirective>(&S)) {
201 PreInits =
Split->getPreInits();
202 }
else if (
const auto *Interchange =
203 dyn_cast<OMPInterchangeDirective>(&S)) {
204 PreInits = Interchange->getPreInits();
206 llvm_unreachable(
"Unknown loop-based directive kind.");
208 doEmitPreinits(PreInits);
215 const Stmt *PreInits;
216 if (
const auto *Fuse = dyn_cast<OMPFuseDirective>(&S)) {
217 PreInits = Fuse->getPreInits();
220 "Unknown canonical loop sequence transform directive kind.");
222 doEmitPreinits(PreInits);
225 void doEmitPreinits(
const Stmt *PreInits) {
231 if (
auto *PreInitCompound = dyn_cast<CompoundStmt>(PreInits))
232 llvm::append_range(PreInitStmts, PreInitCompound->body());
234 PreInitStmts.push_back(PreInits);
236 for (
const Stmt *S : PreInitStmts) {
239 if (
auto *PreInitDecl = dyn_cast<DeclStmt>(S)) {
240 for (
Decl *I : PreInitDecl->decls())
252 emitPreInitStmt(CGF, S);
257 emitPreInitStmt(CGF, S);
262 CodeGenFunction::OMPPrivateScope InlinedShareds;
264 static bool isCapturedVar(CodeGenFunction &CGF,
const VarDecl *VD) {
272 OMPSimdLexicalScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
274 InlinedShareds(CGF) {
275 for (
const auto *
C : S.clauses()) {
276 if (const auto *CPI = OMPClauseWithPreInit::get(C)) {
277 if (const auto *PreInit =
278 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
279 for (const auto *I : PreInit->decls()) {
280 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
281 CGF.EmitVarDecl(cast<VarDecl>(*I));
283 CodeGenFunction::AutoVarEmission Emission =
284 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
285 CGF.EmitAutoVarCleanups(Emission);
289 }
else if (
const auto *UDP = dyn_cast<OMPUseDevicePtrClause>(
C)) {
290 for (
const Expr *E : UDP->varlist()) {
292 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
295 }
else if (
const auto *UDP = dyn_cast<OMPUseDeviceAddrClause>(
C)) {
296 for (
const Expr *E : UDP->varlist()) {
298 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
305 if (
const auto *TG = dyn_cast<OMPTaskgroupDirective>(&S)) {
306 if (
const Expr *E = TG->getReductionRef())
311 llvm::DenseSet<CanonicalDeclPtr<const Decl>> CopyArrayTemps;
312 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
313 if (C->getModifier() != OMPC_REDUCTION_inscan)
315 for (const Expr *E : C->copy_array_temps())
316 CopyArrayTemps.insert(cast<DeclRefExpr>(E)->getDecl());
318 const auto *CS = cast_or_null<CapturedStmt>(S.getAssociatedStmt());
321 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
322 auto *VD =
C.getCapturedVar();
323 if (CopyArrayTemps.contains(VD))
326 "Canonical decl must be captured.");
327 DeclRefExpr DRE(CGF.
getContext(),
const_cast<VarDecl *
>(VD),
328 isCapturedVar(CGF, VD) ||
330 InlinedShareds.isGlobalVarCaptured(VD)),
338 (void)InlinedShareds.Privatize();
349 if (Kind != OMPD_loop)
354 BindKind =
C->getBindKind();
357 case OMPC_BIND_parallel:
359 case OMPC_BIND_teams:
360 return OMPD_distribute;
361 case OMPC_BIND_thread:
373 if (
const auto *OrigDRE = dyn_cast<DeclRefExpr>(E)) {
374 if (
const auto *OrigVD = dyn_cast<VarDecl>(OrigDRE->getDecl())) {
375 OrigVD = OrigVD->getCanonicalDecl();
381 OrigDRE->getType(),
VK_LValue, OrigDRE->getExprLoc());
390 llvm::Value *Size =
nullptr;
391 auto SizeInChars =
C.getTypeSizeInChars(Ty);
392 if (SizeInChars.isZero()) {
400 SizeInChars =
C.getTypeSizeInChars(Ty);
401 if (SizeInChars.isZero())
402 return llvm::ConstantInt::get(
SizeTy, 0);
403 return Builder.CreateNUWMul(Size,
CGM.getSize(SizeInChars));
405 return CGM.getSize(SizeInChars);
415 I != E; ++I, ++CurField, ++CurCap) {
416 if (CurField->hasCapturedVLAType()) {
419 CapturedVars.push_back(Val);
420 }
else if (CurCap->capturesThis()) {
421 CapturedVars.push_back(CXXThisValue);
422 }
else if (CurCap->capturesVariableByCopy()) {
427 if (!CurField->getType()->isAnyPointerType()) {
431 Twine(CurCap->getCapturedVar()->getName(),
".casted"));
447 CapturedVars.push_back(CV);
449 assert(CurCap->capturesVariable() &&
"Expected capture by reference.");
470 if (T->isLValueReferenceType())
471 return C.getLValueReferenceType(
474 if (T->isPointerType())
477 if (
const auto *VLA = dyn_cast<VariableArrayType>(A))
479 if (!A->isVariablyModifiedType())
480 return C.getCanonicalType(T);
482 return C.getCanonicalParamType(T);
487struct FunctionOptions {
489 const CapturedStmt *S =
nullptr;
492 const bool UIntPtrCastRequired =
true;
495 const bool RegisterCastedArgsOnly =
false;
497 const StringRef FunctionName;
500 const bool IsDeviceKernel =
false;
501 explicit FunctionOptions(
const CapturedStmt *S,
bool UIntPtrCastRequired,
502 bool RegisterCastedArgsOnly, StringRef FunctionName,
503 SourceLocation Loc,
bool IsDeviceKernel)
504 : S(S), UIntPtrCastRequired(UIntPtrCastRequired),
505 RegisterCastedArgsOnly(UIntPtrCastRequired && RegisterCastedArgsOnly),
506 FunctionName(FunctionName), Loc(Loc), IsDeviceKernel(IsDeviceKernel) {}
512 llvm::MapVector<
const Decl *, std::pair<const VarDecl *, Address>>
514 llvm::DenseMap<
const Decl *, std::pair<const Expr *, llvm::Value *>>
516 llvm::Value *&CXXThisValue,
const FunctionOptions &FO) {
519 assert(CD->
hasBody() &&
"missing CapturedDecl body");
521 CXXThisValue =
nullptr;
533 if (!FO.UIntPtrCastRequired) {
553 if (FO.UIntPtrCastRequired &&
554 ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) ||
555 I->capturesVariableArrayType()))
558 if (I->capturesVariable() || I->capturesVariableByCopy()) {
559 CapVar = I->getCapturedVar();
561 }
else if (I->capturesThis()) {
564 assert(I->capturesVariableArrayType());
567 if (ArgType->isVariablyModifiedType())
574 }
else if (DebugFunctionDecl && (CapVar || I->capturesThis())) {
576 Ctx, DebugFunctionDecl,
577 CapVar ? CapVar->
getBeginLoc() : FD->getBeginLoc(),
578 CapVar ? CapVar->
getLocation() : FD->getLocation(), II, ArgType,
584 Args.emplace_back(Arg);
586 TargetArgs.emplace_back(
587 FO.UIntPtrCastRequired
608 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
614 if (CGM.
getTriple().isSPIRV() && !FO.IsDeviceKernel)
615 F->setCallingConv(llvm::CallingConv::SPIR_FUNC);
618 F->setDoesNotThrow();
619 F->setDoesNotRecurse();
623 F->removeFnAttr(llvm::Attribute::NoInline);
624 F->addFnAttr(llvm::Attribute::AlwaysInline);
627 F->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
631 FO.UIntPtrCastRequired ? FO.Loc : FO.S->
getBeginLoc(),
632 FO.UIntPtrCastRequired ? FO.Loc
639 if (!FO.UIntPtrCastRequired && Args[Cnt] != TargetArgs[Cnt]) {
647 if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
648 const VarDecl *CurVD = I->getCapturedVar();
649 if (!FO.RegisterCastedArgsOnly)
650 LocalAddrs.insert({Args[Cnt], {CurVD, LocalAddr}});
658 if (FD->hasCapturedVLAType()) {
659 if (FO.UIntPtrCastRequired) {
662 Args[Cnt]->getName(), ArgLVal),
667 VLASizes.try_emplace(Args[Cnt], VAT->
getSizeExpr(), ExprArg);
668 }
else if (I->capturesVariable()) {
669 const VarDecl *Var = I->getCapturedVar();
671 Address ArgAddr = ArgLVal.getAddress();
672 if (ArgLVal.getType()->isLValueReferenceType()) {
675 assert(ArgLVal.getType()->isPointerType());
677 ArgAddr, ArgLVal.getType()->castAs<
PointerType>());
679 if (!FO.RegisterCastedArgsOnly) {
683 }
else if (I->capturesVariableByCopy()) {
684 assert(!FD->getType()->isAnyPointerType() &&
685 "Not expecting a captured pointer.");
686 const VarDecl *Var = I->getCapturedVar();
687 LocalAddrs.insert({Args[Cnt],
688 {Var, FO.UIntPtrCastRequired
690 CGF, I->getLocation(), FD->getType(),
691 Args[Cnt]->getName(), ArgLVal)
692 : ArgLVal.getAddress()}});
695 assert(I->capturesThis());
697 LocalAddrs.insert({Args[Cnt], {
nullptr, ArgLVal.getAddress()}});
708 llvm::MapVector<
const Decl *, std::pair<const VarDecl *, Address>>
710 llvm::DenseMap<
const Decl *, std::pair<const Expr *, llvm::Value *>>
712 llvm::Value *&CXXThisValue, llvm::Value *&ContextV,
const CapturedStmt &CS,
717 CXXThisValue =
nullptr;
727 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
731 F->setDoesNotThrow();
732 F->setDoesNotRecurse();
739 llvm::Type *IntPtrTy = CGF.
IntPtrTy;
740 llvm::Type *PtrTy = CGF.
Builder.getPtrTy();
741 llvm::Align PtrAlign = CGM.
getDataLayout().getPointerABIAlignment(0);
744 for (
auto [FD,
C, FieldIdx] :
748 CGF.
Builder.CreateConstInBoundsGEP1_32(IntPtrTy, ContextV, FieldIdx);
753 if (
C.capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
754 const VarDecl *CurVD =
C.getCapturedVar();
755 Slot->setName(CurVD->
getName());
756 Address SlotAddr(Slot, PtrTy, SlotAlign);
757 LocalAddrs.insert({FD, {CurVD, SlotAddr}});
758 }
else if (FD->hasCapturedVLAType()) {
765 VLASizes.try_emplace(FD, VAT->
getSizeExpr(), ExprArg);
766 }
else if (
C.capturesVariable()) {
767 const VarDecl *Var =
C.getCapturedVar();
771 Slot->setName(Var->
getName() +
".addr");
772 Address SlotAddr(Slot, PtrTy, SlotAlign);
773 LocalAddrs.insert({FD, {Var, SlotAddr}});
776 PtrTy, Slot, PtrAlign, Var->
getName());
777 LocalAddrs.insert({FD,
781 }
else if (
C.capturesVariableByCopy()) {
782 assert(!FD->getType()->isAnyPointerType() &&
783 "Not expecting a captured pointer.");
784 const VarDecl *Var =
C.getCapturedVar();
799 LocalAddrs.insert({FD, {Var, CopyAddr}});
801 assert(
C.capturesThis() &&
"Default case expected to be CXX 'this'");
804 Address SlotAddr(Slot, PtrTy, SlotAlign);
805 LocalAddrs.insert({FD, {
nullptr, SlotAddr}});
817 "CapturedStmtInfo should be set when generating the captured function");
820 bool NeedWrapperFunction =
823 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs,
825 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes,
828 llvm::raw_svector_ostream Out(Buffer);
831 bool IsDeviceKernel =
CGM.getOpenMPRuntime().isGPU() &&
833 D.getCapturedStmt(OMPD_target) == &S;
834 CodeGenFunction WrapperCGF(
CGM,
true);
835 llvm::Function *WrapperF =
nullptr;
836 if (NeedWrapperFunction) {
839 FunctionOptions WrapperFO(&S,
true,
846 WrapperCGF.CXXThisValue, WrapperFO);
849 FunctionOptions FO(&S, !NeedWrapperFunction,
false,
850 Out.str(), Loc, !NeedWrapperFunction && IsDeviceKernel);
852 *
this, WrapperArgs, WrapperLocalAddrs, WrapperVLASizes, CXXThisValue, FO);
854 for (
const auto &LocalAddrPair : WrapperLocalAddrs) {
855 if (LocalAddrPair.second.first) {
856 LocalScope.addPrivate(LocalAddrPair.second.first,
857 LocalAddrPair.second.second);
860 (void)LocalScope.Privatize();
861 for (
const auto &VLASizePair : WrapperVLASizes)
862 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
865 LocalScope.ForceCleanup();
867 if (!NeedWrapperFunction)
871 WrapperF->removeFromParent();
872 F->getParent()->getFunctionList().insertAfter(F->getIterator(), WrapperF);
875 auto *PI = F->arg_begin();
876 for (
const auto *Arg : Args) {
878 auto I = LocalAddrs.find(Arg);
879 if (I != LocalAddrs.end()) {
882 I->second.first ? I->second.first->getType() : Arg->getType(),
888 auto EI = VLASizes.find(Arg);
889 if (EI != VLASizes.end()) {
901 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
911 "CapturedStmtInfo should be set when generating the captured function");
915 bool NeedWrapperFunction =
918 CodeGenFunction WrapperCGF(
CGM,
true);
919 llvm::Function *WrapperF =
nullptr;
920 llvm::Value *WrapperContextV =
nullptr;
921 if (NeedWrapperFunction) {
924 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>>
926 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>>
929 WrapperCGF, WrapperArgs, WrapperLocalAddrs, WrapperVLASizes,
930 WrapperCGF.CXXThisValue, WrapperContextV, S, Loc, FunctionName);
934 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs;
935 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes;
938 if (NeedWrapperFunction) {
940 llvm::raw_svector_ostream Out(Buffer);
941 Out << FunctionName <<
"_debug__";
943 FunctionOptions FO(&S,
false,
944 false, Out.str(), Loc,
949 llvm::Value *ContextV =
nullptr;
951 CXXThisValue, ContextV, S, Loc,
960 llvm::Value *ParamAddr =
Builder.CreateConstInBoundsGEP1_32(
961 IntPtrTy, ContextV, FieldIdx, Twine(Param->getName()) +
".addr");
962 llvm::Value *ParamVal =
Builder.CreateAlignedLoad(
964 CGM.getDataLayout().getPointerABIAlignment(0), Param->getName());
967 Builder.CreateStore(ParamVal, ParamLocalAddr);
968 LocalAddrs.insert({Param, {Param, ParamLocalAddr}});
974 for (
const auto &LocalAddrPair : LocalAddrs) {
975 if (LocalAddrPair.second.first)
976 LocalScope.addPrivate(LocalAddrPair.second.first,
977 LocalAddrPair.second.second);
979 (void)LocalScope.Privatize();
980 for (
const auto &VLASizePair : VLASizes)
981 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
984 (void)LocalScope.ForceCleanup();
987 if (!NeedWrapperFunction)
991 WrapperF->removeFromParent();
992 F->getParent()->getFunctionList().insertAfter(F->getIterator(), WrapperF);
994 llvm::Align PtrAlign =
CGM.getDataLayout().getPointerABIAlignment(0);
997 "Expected context param at position 0 for target regions");
999 "Argument count mismatch");
1001 for (
auto [FD, InnerParam, SlotIdx] : llvm::zip(
1003 llvm::Value *Slot = WrapperCGF.
Builder.CreateConstInBoundsGEP1_32(
1004 WrapperCGF.
IntPtrTy, WrapperContextV, SlotIdx);
1006 InnerParam.getType(), Slot, PtrAlign, InnerParam.getName());
1007 CallArgs.push_back(Val);
1012 auto InnerParam = F->arg_begin() + SlotIdx;
1013 llvm::Value *Slot = WrapperCGF.
Builder.CreateConstInBoundsGEP1_32(
1014 WrapperCGF.
IntPtrTy, WrapperContextV, SlotIdx);
1016 InnerParam->getType(), Slot, PtrAlign, InnerParam->getName());
1017 CallArgs.push_back(Val);
1019 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
1035 llvm::Value *NumElements =
emitArrayLength(ArrayTy, ElementTy, DestAddr);
1042 DestBegin, NumElements);
1047 llvm::Value *IsEmpty =
1048 Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arraycpy.isempty");
1049 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
1052 llvm::BasicBlock *EntryBB =
Builder.GetInsertBlock();
1057 llvm::PHINode *SrcElementPHI =
1058 Builder.CreatePHI(SrcBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
1059 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
1064 llvm::PHINode *DestElementPHI =
Builder.CreatePHI(
1065 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
1066 DestElementPHI->addIncoming(DestBegin, EntryBB);
1072 CopyGen(DestElementCurrent, SrcElementCurrent);
1075 llvm::Value *DestElementNext =
1077 1,
"omp.arraycpy.dest.element");
1078 llvm::Value *SrcElementNext =
1080 1,
"omp.arraycpy.src.element");
1083 Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
1084 Builder.CreateCondBr(Done, DoneBB, BodyBB);
1085 DestElementPHI->addIncoming(DestElementNext,
Builder.GetInsertBlock());
1086 SrcElementPHI->addIncoming(SrcElementNext,
Builder.GetInsertBlock());
1096 const auto *BO = dyn_cast<BinaryOperator>(
Copy);
1097 if (BO && BO->getOpcode() == BO_Assign) {
1106 DestAddr, SrcAddr, OriginalType,
1134 bool DeviceConstTarget =
getLangOpts().OpenMPIsTargetDevice &&
1136 bool FirstprivateIsLastprivate =
false;
1137 llvm::DenseMap<const VarDecl *, OpenMPLastprivateModifier> Lastprivates;
1138 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1139 for (
const auto *D :
C->varlist())
1140 Lastprivates.try_emplace(
1144 llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
1149 bool MustEmitFirstprivateCopy =
1150 CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown;
1151 for (
const auto *
C : D.getClausesOfKind<OMPFirstprivateClause>()) {
1152 const auto *IRef =
C->varlist_begin();
1153 const auto *InitsRef =
C->inits().begin();
1154 for (
const Expr *IInit :
C->private_copies()) {
1156 bool ThisFirstprivateIsLastprivate =
1157 Lastprivates.count(OrigVD->getCanonicalDecl()) > 0;
1160 if (!MustEmitFirstprivateCopy && !ThisFirstprivateIsLastprivate && FD &&
1162 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
1163 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
1170 if (DeviceConstTarget && OrigVD->getType().isConstant(
getContext()) &&
1172 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
1173 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
1178 FirstprivateIsLastprivate =
1179 FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate;
1180 if (EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()).second) {
1181 const auto *VDInit =
1200 assert(!CE &&
"Expected non-constant firstprivate.");
1207 if (
Type->isArrayType()) {
1223 RunCleanupsScope InitScope(*this);
1225 setAddrOfLocalVar(VDInit, SrcElement);
1226 EmitAnyExprToMem(Init, DestElement,
1227 Init->getType().getQualifiers(),
1229 LocalDeclMap.erase(VDInit);
1240 setAddrOfLocalVar(VDInit, OriginalAddr);
1242 LocalDeclMap.erase(VDInit);
1244 if (ThisFirstprivateIsLastprivate &&
1245 Lastprivates[OrigVD->getCanonicalDecl()] ==
1246 OMPC_LASTPRIVATE_conditional) {
1251 (*IRef)->getExprLoc());
1252 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1256 LocalDeclMap.erase(VD);
1257 setAddrOfLocalVar(VD, VDAddr);
1259 IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1261 assert(IsRegistered &&
1262 "firstprivate var already registered as private");
1270 return FirstprivateIsLastprivate && !EmittedAsFirstprivate.empty();
1278 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
1279 for (
const auto *
C : D.getClausesOfKind<OMPPrivateClause>()) {
1280 auto IRef =
C->varlist_begin();
1281 for (
const Expr *IInit :
C->private_copies()) {
1283 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
1289 assert(IsRegistered &&
"private var already registered as private");
1305 llvm::DenseSet<const VarDecl *> CopiedVars;
1306 llvm::BasicBlock *CopyBegin =
nullptr, *CopyEnd =
nullptr;
1308 auto IRef =
C->varlist_begin();
1309 auto ISrcRef =
C->source_exprs().begin();
1310 auto IDestRef =
C->destination_exprs().begin();
1311 for (
const Expr *AssignOp :
C->assignment_ops()) {
1320 getContext().getTargetInfo().isTLSSupported()) {
1322 "Copyin threadprivates should have been captured!");
1326 LocalDeclMap.erase(VD);
1330 :
CGM.GetAddrOfGlobal(VD),
1331 CGM.getTypes().ConvertTypeForMem(VD->
getType()),
1336 if (CopiedVars.size() == 1) {
1342 auto *MasterAddrInt =
Builder.CreatePtrToInt(
1344 auto *PrivateAddrInt =
Builder.CreatePtrToInt(
1347 Builder.CreateICmpNE(MasterAddrInt, PrivateAddrInt), CopyBegin,
1353 const auto *DestVD =
1374 bool HasAtLeastOneLastprivate =
false;
1376 llvm::DenseSet<const VarDecl *> SIMDLCVs;
1379 for (
const Expr *
C : LoopDirective->counters()) {
1384 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1385 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1386 HasAtLeastOneLastprivate =
true;
1389 const auto *IRef =
C->varlist_begin();
1390 const auto *IDestRef =
C->destination_exprs().begin();
1391 for (
const Expr *IInit :
C->private_copies()) {
1397 if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) {
1398 const auto *DestVD =
1403 (*IRef)->getType(),
VK_LValue, (*IRef)->getExprLoc());
1408 if (IInit && !SIMDLCVs.count(OrigVD->getCanonicalDecl())) {
1411 if (
C->getKind() == OMPC_LASTPRIVATE_conditional) {
1412 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1414 setAddrOfLocalVar(VD, VDAddr);
1420 bool IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1421 assert(IsRegistered &&
1422 "lastprivate var already registered as private");
1430 return HasAtLeastOneLastprivate;
1435 llvm::Value *IsLastIterCond) {
1444 llvm::BasicBlock *ThenBB =
nullptr;
1445 llvm::BasicBlock *DoneBB =
nullptr;
1446 if (IsLastIterCond) {
1450 llvm::any_of(D.getClausesOfKind<OMPLastprivateClause>(),
1451 [](
const OMPLastprivateClause *
C) {
1452 return C->getKind() == OMPC_LASTPRIVATE_conditional;
1454 CGM.getOpenMPRuntime().emitBarrierCall(*
this, D.getBeginLoc(),
1461 Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB);
1464 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1465 llvm::DenseMap<const VarDecl *, const Expr *> LoopCountersAndUpdates;
1466 if (
const auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) {
1467 auto IC = LoopDirective->counters().begin();
1468 for (
const Expr *F : LoopDirective->finals()) {
1472 AlreadyEmittedVars.insert(D);
1474 LoopCountersAndUpdates[D] = F;
1478 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1479 auto IRef =
C->varlist_begin();
1480 auto ISrcRef =
C->source_exprs().begin();
1481 auto IDestRef =
C->destination_exprs().begin();
1482 for (
const Expr *AssignOp :
C->assignment_ops()) {
1483 const auto *PrivateVD =
1486 const auto *CanonicalVD = PrivateVD->getCanonicalDecl();
1487 if (AlreadyEmittedVars.insert(CanonicalVD).second) {
1491 if (
const Expr *FinalExpr = LoopCountersAndUpdates.lookup(CanonicalVD))
1495 const auto *DestVD =
1499 if (
const auto *RefTy = PrivateVD->getType()->getAs<
ReferenceType>())
1501 Builder.CreateLoad(PrivateAddr),
1502 CGM.getTypes().ConvertTypeForMem(RefTy->getPointeeType()),
1503 CGM.getNaturalTypeAlignment(RefTy->getPointeeType()));
1505 if (
C->getKind() == OMPC_LASTPRIVATE_conditional)
1506 CGM.getOpenMPRuntime().emitLastprivateConditionalFinalUpdate(
1508 (*IRef)->getExprLoc());
1511 EmitOMPCopy(
Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp);
1517 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
1537 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1538 if (ForInscan != (
C->getModifier() == OMPC_REDUCTION_inscan))
1540 Shareds.append(
C->varlist_begin(),
C->varlist_end());
1541 Privates.append(
C->privates().begin(),
C->privates().end());
1542 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1543 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1544 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1545 if (
C->getModifier() == OMPC_REDUCTION_task) {
1546 Data.ReductionVars.append(
C->privates().begin(),
C->privates().end());
1547 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
1548 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
1549 Data.ReductionOps.append(
C->reduction_ops().begin(),
1550 C->reduction_ops().end());
1551 TaskLHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1552 TaskRHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1557 auto *ILHS = LHSs.begin();
1558 auto *IRHS = RHSs.begin();
1560 for (
const Expr *IRef : Shareds) {
1568 [&Emission](CodeGenFunction &CGF) {
1569 CGF.EmitAutoVarInit(Emission);
1577 assert(IsRegistered &&
"private var already registered as private");
1585 if (isaOMPArraySectionExpr &&
Type->isVariablyModifiedType()) {
1590 }
else if ((isaOMPArraySectionExpr &&
Type->isScalarType()) ||
1608 PrivateScope.
addPrivate(LHSVD, OriginalAddr);
1619 if (!
Data.ReductionVars.empty()) {
1621 Data.IsReductionWithTaskMod =
true;
1623 llvm::Value *ReductionDesc =
CGM.getOpenMPRuntime().emitTaskReductionInit(
1624 *
this, D.getBeginLoc(), TaskLHSs, TaskRHSs,
Data);
1625 const Expr *TaskRedRef =
nullptr;
1636 case OMPD_parallel_for:
1639 case OMPD_parallel_master:
1643 case OMPD_parallel_sections:
1647 case OMPD_target_parallel:
1651 case OMPD_target_parallel_for:
1655 case OMPD_distribute_parallel_for:
1659 case OMPD_teams_distribute_parallel_for:
1661 .getTaskReductionRefExpr();
1663 case OMPD_target_teams_distribute_parallel_for:
1665 .getTaskReductionRefExpr();
1673 case OMPD_parallel_for_simd:
1675 case OMPD_taskyield:
1679 case OMPD_taskgroup:
1687 case OMPD_cancellation_point:
1689 case OMPD_target_data:
1690 case OMPD_target_enter_data:
1691 case OMPD_target_exit_data:
1693 case OMPD_taskloop_simd:
1694 case OMPD_master_taskloop:
1695 case OMPD_master_taskloop_simd:
1696 case OMPD_parallel_master_taskloop:
1697 case OMPD_parallel_master_taskloop_simd:
1698 case OMPD_distribute:
1699 case OMPD_target_update:
1700 case OMPD_distribute_parallel_for_simd:
1701 case OMPD_distribute_simd:
1702 case OMPD_target_parallel_for_simd:
1703 case OMPD_target_simd:
1704 case OMPD_teams_distribute:
1705 case OMPD_teams_distribute_simd:
1706 case OMPD_teams_distribute_parallel_for_simd:
1707 case OMPD_target_teams:
1708 case OMPD_target_teams_distribute:
1709 case OMPD_target_teams_distribute_parallel_for_simd:
1710 case OMPD_target_teams_distribute_simd:
1711 case OMPD_declare_target:
1712 case OMPD_end_declare_target:
1713 case OMPD_threadprivate:
1715 case OMPD_declare_reduction:
1716 case OMPD_declare_mapper:
1717 case OMPD_declare_simd:
1719 case OMPD_declare_variant:
1720 case OMPD_begin_declare_variant:
1721 case OMPD_end_declare_variant:
1724 llvm_unreachable(
"Unexpected directive with task reductions.");
1730 false, TaskRedRef->
getType());
1743 bool HasAtLeastOneReduction =
false;
1744 bool IsReductionWithTaskMod =
false;
1745 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1747 if (
C->getModifier() == OMPC_REDUCTION_inscan)
1749 HasAtLeastOneReduction =
true;
1750 Privates.append(
C->privates().begin(),
C->privates().end());
1751 LHSExprs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1752 RHSExprs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1753 IsPrivateVarReduction.append(
C->private_var_reduction_flags().begin(),
1754 C->private_var_reduction_flags().end());
1755 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1756 IsReductionWithTaskMod =
1757 IsReductionWithTaskMod ||
C->getModifier() == OMPC_REDUCTION_task;
1759 if (HasAtLeastOneReduction) {
1761 if (IsReductionWithTaskMod) {
1762 CGM.getOpenMPRuntime().emitTaskReductionFini(
1765 bool TeamsLoopCanBeParallel =
false;
1766 if (
auto *TTLD = dyn_cast<OMPTargetTeamsGenericLoopDirective>(&D))
1767 TeamsLoopCanBeParallel = TTLD->canBeParallelFor();
1768 bool WithNowait = D.getSingleClause<OMPNowaitClause>() ||
1770 TeamsLoopCanBeParallel || ReductionKind == OMPD_simd;
1771 bool SimpleReduction = ReductionKind == OMPD_simd;
1774 CGM.getOpenMPRuntime().emitReduction(
1775 *
this, D.getEndLoc(),
Privates, LHSExprs, RHSExprs, ReductionOps,
1776 {WithNowait, SimpleReduction, IsPrivateVarReduction, ReductionKind});
1785 llvm::BasicBlock *DoneBB =
nullptr;
1786 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1787 if (
const Expr *PostUpdate =
C->getPostUpdateExpr()) {
1789 if (llvm::Value *
Cond = CondGen(CGF)) {
1810 const OMPExecutableDirective &,
1811 llvm::SmallVectorImpl<llvm::Value *> &)>
1812 CodeGenBoundParametersTy;
1820 llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> PrivateDecls;
1821 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
1822 for (
const Expr *Ref :
C->varlist()) {
1823 if (!Ref->getType()->isScalarType())
1825 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1832 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
1833 for (
const Expr *Ref :
C->varlist()) {
1834 if (!Ref->getType()->isScalarType())
1836 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1843 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
1844 for (
const Expr *Ref :
C->varlist()) {
1845 if (!Ref->getType()->isScalarType())
1847 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1858 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
1859 for (
const Expr *Ref :
C->varlist()) {
1860 if (!Ref->getType()->isScalarType())
1862 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1869 CGF, S, PrivateDecls);
1875 const CodeGenBoundParametersTy &CodeGenBoundParameters) {
1876 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
1877 llvm::Value *NumThreads =
nullptr;
1886 llvm::Function *OutlinedFn =
1893 NumThreads = CGF.
EmitScalarExpr(NumThreadsClause->getNumThreads(),
1895 Modifier = NumThreadsClause->getModifier();
1896 if (
const auto *MessageClause = S.getSingleClause<OMPMessageClause>()) {
1897 Message = MessageClause->getMessageString();
1898 MessageLoc = MessageClause->getBeginLoc();
1900 if (
const auto *SeverityClause = S.getSingleClause<OMPSeverityClause>()) {
1901 Severity = SeverityClause->getSeverityKind();
1902 SeverityLoc = SeverityClause->getBeginLoc();
1905 CGF, NumThreads, NumThreadsClause->getBeginLoc(), Modifier, Severity,
1906 SeverityLoc, Message, MessageLoc);
1908 if (
const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>()) {
1911 CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getBeginLoc());
1913 const Expr *IfCond =
nullptr;
1914 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
1915 if (
C->getNameModifier() == OMPD_unknown ||
1916 C->getNameModifier() == OMPD_parallel) {
1917 IfCond =
C->getCondition();
1922 OMPParallelScope
Scope(CGF, S);
1928 CodeGenBoundParameters(CGF, S, CapturedVars);
1931 CapturedVars, IfCond, NumThreads,
1932 Modifier, Severity, Message);
1937 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
1939 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
1941 return !((AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc ||
1942 AA->getAllocatorType() == OMPAllocateDeclAttr::OMPNullMemAlloc) &&
1943 !AA->getAllocator());
1958 CGF, S.getBeginLoc(), OMPD_unknown,
false,
1964 CodeGenFunction &CGF,
const VarDecl *VD) {
1966 auto &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1978 Size = CGF.
Builder.CreateNUWAdd(
1980 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
1981 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
1987 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
1988 assert(AA->getAllocator() &&
1989 "Expected allocator expression for non-default allocator.");
1993 if (Allocator->getType()->isIntegerTy())
1994 Allocator = CGF.
Builder.CreateIntToPtr(Allocator,
CGM.VoidPtrTy);
1995 else if (Allocator->getType()->isPointerTy())
1999 llvm::Value *
Addr = OMPBuilder.createOMPAlloc(
2002 llvm::CallInst *FreeCI =
2003 OMPBuilder.createOMPFree(CGF.
Builder,
Addr, Allocator);
2017 if (
CGM.getLangOpts().OpenMPUseTLS &&
2018 CGM.getContext().getTargetInfo().isTLSSupported())
2021 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2026 llvm::ConstantInt *Size =
CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy));
2028 llvm::Twine CacheName = Twine(
CGM.getMangledName(VD)).concat(Suffix);
2030 llvm::CallInst *ThreadPrivateCacheCall =
2031 OMPBuilder.createCachedThreadPrivate(CGF.
Builder,
Data, Size, CacheName);
2039 llvm::raw_svector_ostream OS(Buffer);
2040 StringRef Sep = FirstSeparator;
2041 for (StringRef Part : Parts) {
2045 return OS.str().str();
2053 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
2054 "." + RegionName +
".after");
2070 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
2071 "." + RegionName +
".after");
2083 if (
CGM.getLangOpts().OpenMPIRBuilder) {
2084 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2086 llvm::Value *IfCond =
nullptr;
2091 llvm::Value *NumThreads =
nullptr;
2096 ProcBindKind ProcBind = OMP_PROC_BIND_default;
2097 if (
const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>())
2098 ProcBind = ProcBindClause->getProcBindKind();
2100 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2104 auto FiniCB = [
this](InsertPointTy IP) {
2106 return llvm::Error::success();
2113 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
2114 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
2125 auto BodyGenCB = [&,
this](InsertPointTy AllocaIP,
2126 InsertPointTy CodeGenIP) {
2128 *
this, ParallelRegionBodyStmt, AllocaIP, CodeGenIP,
"parallel");
2129 return llvm::Error::success();
2134 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
2136 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
2137 OMPBuilder.createParallel(
Builder, AllocaIP, BodyGenCB, PrivCB, FiniCB,
2138 IfCond, NumThreads, ProcBind, S.hasCancel()));
2152 CGF.
EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt());
2161 [](CodeGenFunction &) {
return nullptr; });
2173class OMPTransformDirectiveScopeRAII {
2174 OMPLoopScope *
Scope =
nullptr;
2178 OMPTransformDirectiveScopeRAII(
const OMPTransformDirectiveScopeRAII &) =
2180 OMPTransformDirectiveScopeRAII &
2181 operator=(
const OMPTransformDirectiveScopeRAII &) =
delete;
2185 if (
const auto *Dir = dyn_cast<OMPLoopBasedDirective>(S)) {
2186 Scope =
new OMPLoopScope(CGF, *Dir);
2189 }
else if (
const auto *Dir =
2190 dyn_cast<OMPCanonicalLoopSequenceTransformationDirective>(
2195 Scope =
new OMPLoopScope(CGF, *Dir);
2200 ~OMPTransformDirectiveScopeRAII() {
2211 int MaxLevel,
int Level = 0) {
2212 assert(Level < MaxLevel &&
"Too deep lookup during loop body codegen.");
2214 if (
const auto *CS = dyn_cast<CompoundStmt>(SimplifiedS)) {
2217 "LLVM IR generation of compound statement ('{}')");
2221 for (
const Stmt *CurStmt : CS->body())
2222 emitBody(CGF, CurStmt, NextLoop, MaxLevel, Level);
2225 if (SimplifiedS == NextLoop) {
2226 if (
auto *Dir = dyn_cast<OMPLoopTransformationDirective>(SimplifiedS))
2227 SimplifiedS = Dir->getTransformedStmt();
2228 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(SimplifiedS))
2229 SimplifiedS = CanonLoop->getLoopStmt();
2230 if (
const auto *For = dyn_cast<ForStmt>(SimplifiedS)) {
2234 "Expected canonical for loop or range-based for loop.");
2236 CGF.
EmitStmt(CXXFor->getLoopVarStmt());
2237 S = CXXFor->getBody();
2239 if (Level + 1 < MaxLevel) {
2240 NextLoop = OMPLoopDirective::tryToFindNextInnerLoop(
2242 emitBody(CGF, S, NextLoop, MaxLevel, Level + 1);
2253 for (
const Expr *UE : D.updates())
2260 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2261 for (
const Expr *UE :
C->updates())
2268 BreakContinueStack.push_back(BreakContinue(D,
LoopExit, Continue));
2269 for (
const Expr *E : D.finals_conditions()) {
2282 bool IsInscanRegion = InscanScope.
Privatize();
2283 if (IsInscanRegion) {
2293 if (EKind != OMPD_simd && !
getLangOpts().OpenMPSimd)
2302 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
2305 OMPLoopBasedDirective::tryToFindNextInnerLoop(
2307 D.getLoopsNumber());
2315 BreakContinueStack.pop_back();
2326 std::unique_ptr<CodeGenFunction::CGCapturedStmtInfo> CSI =
2327 std::make_unique<CodeGenFunction::CGCapturedStmtInfo>(*S);
2331 return {F, CapStruct.getPointer(
ParentCGF)};
2335static llvm::CallInst *
2340 EffectiveArgs.reserve(Args.size() + 1);
2341 llvm::append_range(EffectiveArgs, Args);
2342 EffectiveArgs.push_back(Cap.second);
2347llvm::CanonicalLoopInfo *
2349 assert(Depth == 1 &&
"Nested loops with OpenMPIRBuilder not yet implemented");
2375 const Stmt *SyntacticalLoop = S->getLoopStmt();
2386 const Stmt *BodyStmt;
2387 if (
const auto *For = dyn_cast<ForStmt>(SyntacticalLoop)) {
2388 if (
const Stmt *InitStmt = For->getInit())
2390 BodyStmt = For->getBody();
2391 }
else if (
const auto *RangeFor =
2392 dyn_cast<CXXForRangeStmt>(SyntacticalLoop)) {
2393 if (
const DeclStmt *RangeStmt = RangeFor->getRangeStmt())
2395 if (
const DeclStmt *BeginStmt = RangeFor->getBeginStmt())
2397 if (
const DeclStmt *EndStmt = RangeFor->getEndStmt())
2399 if (
const DeclStmt *LoopVarStmt = RangeFor->getLoopVarStmt())
2401 BodyStmt = RangeFor->getBody();
2403 llvm_unreachable(
"Expected for-stmt or range-based for-stmt");
2406 const CapturedStmt *DistanceFunc = S->getDistanceFunc();
2419 llvm::Value *DistVal =
Builder.CreateLoad(CountAddr,
".count");
2422 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2423 auto BodyGen = [&,
this](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP,
2424 llvm::Value *IndVar) {
2429 const DeclRefExpr *LoopVarRef = S->getLoopVarRef();
2437 return llvm::Error::success();
2440 llvm::CanonicalLoopInfo *
CL =
2441 cantFail(OMPBuilder.createCanonicalLoop(
Builder, BodyGen, DistVal));
2453 const Expr *IncExpr,
2454 const llvm::function_ref<
void(CodeGenFunction &)> BodyGen,
2455 const llvm::function_ref<
void(CodeGenFunction &)> PostIncGen) {
2465 const CapturedStmt *ICS = OMPED.getInnermostCapturedStmt();
2479 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
2480 if (RequiresCleanup)
2487 if (ExitBlock !=
LoopExit.getBlock()) {
2497 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
2505 BreakContinueStack.pop_back();
2516 bool HasLinears =
false;
2517 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2521 if (
const auto *Ref =
2540 if (
const auto *CS = cast_or_null<BinaryOperator>(
C->getCalcStep()))
2552 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2555 llvm::BasicBlock *DoneBB =
nullptr;
2557 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2558 auto IC =
C->varlist_begin();
2559 for (
const Expr *F :
C->finals()) {
2561 if (llvm::Value *
Cond = CondGen(*
this)) {
2573 (*IC)->getType(),
VK_LValue, (*IC)->getExprLoc());
2581 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
2593 llvm::APInt ClauseAlignment(64, 0);
2594 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
2597 ClauseAlignment = AlignmentCI->getValue();
2599 for (
const Expr *E : Clause->varlist()) {
2600 llvm::APInt Alignment(ClauseAlignment);
2601 if (Alignment == 0) {
2608 E->getType()->getPointeeType()))
2611 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2612 "alignment is not power of 2");
2613 if (Alignment != 0) {
2627 auto I = S.private_counters().begin();
2628 for (
const Expr *E : S.counters()) {
2634 LocalDeclMap.erase(PrivateVD);
2640 E->getType(),
VK_LValue, E->getExprLoc());
2648 for (
const auto *
C : S.getClausesOfKind<OMPOrderedClause>()) {
2649 if (!
C->getNumForLoops())
2651 for (
unsigned I = S.getLoopsNumber(), E =
C->getLoopNumIterations().size();
2657 if (DRE->refersToEnclosingVariableOrCapture()) {
2666 const Expr *
Cond, llvm::BasicBlock *TrueBlock,
2667 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
2675 for (
const Expr *I : S.inits()) {
2682 for (
const Expr *E : S.dependent_counters()) {
2685 assert(!E->getType().getNonReferenceType()->isRecordType() &&
2686 "dependent counter must not be an iterator.");
2690 (void)PreCondVars.
setVarAddr(CGF, VD, CounterAddr);
2692 (void)PreCondVars.
apply(CGF);
2693 for (
const Expr *E : S.dependent_inits()) {
2707 llvm::DenseSet<const VarDecl *> SIMDLCVs;
2711 for (
const Expr *
C : LoopDirective->counters()) {
2716 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2717 auto CurPrivate =
C->privates().begin();
2718 for (
const Expr *E :
C->varlist()) {
2720 const auto *PrivateVD =
2727 assert(IsRegistered &&
"linear var already registered as private");
2815 if (
const auto *CS = dyn_cast<CapturedStmt>(S))
2833 if (HasOrderedDirective)
2841 const Stmt *AssociatedStmt = D.getAssociatedStmt();
2845 if (
C->getKind() == OMPC_ORDER_concurrent)
2848 if ((EKind == OMPD_simd ||
2850 llvm::any_of(D.getClausesOfKind<OMPReductionClause>(),
2851 [](
const OMPReductionClause *
C) {
2852 return C->getModifier() == OMPC_REDUCTION_inscan;
2860 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2863 llvm::BasicBlock *DoneBB =
nullptr;
2864 auto IC = D.counters().begin();
2865 auto IPC = D.private_counters().begin();
2866 for (
const Expr *F : D.finals()) {
2869 const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
2871 OrigVD->hasGlobalStorage() || CED) {
2873 if (llvm::Value *
Cond = CondGen(*
this)) {
2921 auto &&ThenGen = [&S, &SimdInitGen, &BodyCodeGen](
CodeGenFunction &CGF,
2935 const Expr *IfCond =
nullptr;
2938 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
2940 (
C->getNameModifier() == OMPD_unknown ||
2941 C->getNameModifier() == OMPD_simd)) {
2942 IfCond =
C->getCondition();
2958 OMPLoopScope PreInitScope(CGF, S);
2980 llvm::BasicBlock *ContBlock =
nullptr;
2987 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
2994 const Expr *IVExpr = S.getIterationVariable();
3002 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
3017 CGF, S, CGF.
EmitLValue(S.getIterationVariable()));
3032 emitOMPLoopBodyWithStopPoint(CGF, S,
3033 CodeGenFunction::JumpDest());
3039 if (HasLastprivateClause)
3068 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(S.getRawStmt())) {
3069 if (
const Stmt *SyntacticalLoop = CanonLoop->getLoopStmt()) {
3070 for (
const Stmt *SubStmt : SyntacticalLoop->
children()) {
3073 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(SubStmt)) {
3088static llvm::MapVector<llvm::Value *, llvm::Value *>
3090 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars;
3092 llvm::APInt ClauseAlignment(64, 0);
3093 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
3096 ClauseAlignment = AlignmentCI->getValue();
3098 for (
const Expr *E : Clause->varlist()) {
3099 llvm::APInt Alignment(ClauseAlignment);
3100 if (Alignment == 0) {
3107 E->getType()->getPointeeType()))
3110 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
3111 "alignment is not power of 2");
3113 AlignedVars[PtrValue] = CGF.
Builder.getInt64(Alignment.getSExtValue());
3123 bool UseOMPIRBuilder =
3125 if (UseOMPIRBuilder) {
3129 if (UseOMPIRBuilder) {
3130 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars =
3133 const Stmt *Inner = S.getRawStmt();
3134 llvm::CanonicalLoopInfo *CLI =
3135 CGF.EmitOMPCollapsedCanonicalLoopNest(Inner, 1);
3137 llvm::OpenMPIRBuilder &OMPBuilder =
3140 llvm::ConstantInt *Simdlen =
nullptr;
3147 llvm::ConstantInt *Safelen =
nullptr;
3154 llvm::omp::OrderKind Order = llvm::omp::OrderKind::OMP_ORDER_unknown;
3156 if (
C->getKind() == OpenMPOrderClauseKind::OMPC_ORDER_concurrent) {
3157 Order = llvm::omp::OrderKind::OMP_ORDER_concurrent;
3162 OMPBuilder.applySimd(CLI, AlignedVars,
3163 nullptr, Order, Simdlen, Safelen);
3170 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
3185 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
3198 OMPTransformDirectiveScopeRAII TileScope(*
this, &S);
3204 OMPTransformDirectiveScopeRAII StripeScope(*
this, &S);
3210 OMPTransformDirectiveScopeRAII ReverseScope(*
this, &S);
3216 OMPTransformDirectiveScopeRAII SplitScope(*
this, &S);
3223 OMPTransformDirectiveScopeRAII InterchangeScope(*
this, &S);
3229 OMPTransformDirectiveScopeRAII FuseScope(*
this, &S);
3234 bool UseOMPIRBuilder =
CGM.getLangOpts().OpenMPIRBuilder;
3236 if (UseOMPIRBuilder) {
3238 const Stmt *Inner = S.getRawStmt();
3246 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
3249 llvm::CanonicalLoopInfo *UnrolledCLI =
nullptr;
3253 OMPBuilder.unrollLoopFull(DL, CLI);
3255 uint64_t Factor = 0;
3256 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3257 Factor = FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
3258 assert(Factor >= 1 &&
"Only positive factors are valid");
3260 OMPBuilder.unrollLoopPartial(DL, CLI, Factor,
3261 NeedsUnrolledCLI ? &UnrolledCLI :
nullptr);
3263 OMPBuilder.unrollLoopHeuristic(DL, CLI);
3266 assert((!NeedsUnrolledCLI || UnrolledCLI) &&
3267 "NeedsUnrolledCLI implies UnrolledCLI to be set");
3284 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3286 FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
3287 assert(Factor >= 1 &&
"Only positive factors are valid");
3295void CodeGenFunction::EmitOMPOuterLoop(
3298 const CodeGenFunction::OMPLoopArguments &LoopArgs,
3303 const Expr *IVExpr = S.getIterationVariable();
3317 llvm::Value *BoolCondVal =
nullptr;
3318 if (!DynamicOrOrdered) {
3329 RT.
emitForNext(*
this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL,
3330 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST);
3335 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
3340 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
3341 if (ExitBlock !=
LoopExit.getBlock()) {
3349 if (DynamicOrOrdered)
3354 BreakContinueStack.push_back(BreakContinue(S, LoopExit, Continue));
3359 [&S, IsMonotonic, EKind](CodeGenFunction &CGF, PrePostActionTy &) {
3364 if (
const auto *
C = S.getSingleClause<OMPOrderClause>())
3365 if (
C->getKind() == OMPC_ORDER_concurrent)
3371 [&S, &LoopArgs, LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered,
3372 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
3373 SourceLocation Loc = S.getBeginLoc();
3379 CGF.EmitOMPInnerLoop(
3381 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
3382 CodeGenLoop(CGF, S, LoopExit);
3384 [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) {
3385 CodeGenOrdered(CGF, Loc, IVSize, IVSigned);
3390 BreakContinueStack.pop_back();
3391 if (!DynamicOrOrdered) {
3404 auto &&CodeGen = [DynamicOrOrdered, &S, &LoopArgs](CodeGenFunction &CGF) {
3405 if (!DynamicOrOrdered)
3406 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
3409 OMPCancelStack.emitExit(*
this, EKind, CodeGen);
3412void CodeGenFunction::EmitOMPForOuterLoop(
3413 const OpenMPScheduleTy &ScheduleKind,
bool IsMonotonic,
3415 const OMPLoopArguments &LoopArgs,
3417 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3423 LoopArgs.Chunk !=
nullptr)) &&
3424 "static non-chunked schedule does not need outer loop");
3478 const Expr *IVExpr = S.getIterationVariable();
3482 if (DynamicOrOrdered) {
3483 const std::pair<llvm::Value *, llvm::Value *> DispatchBounds =
3484 CGDispatchBounds(*
this, S, LoopArgs.LB, LoopArgs.UB);
3485 llvm::Value *LBVal = DispatchBounds.first;
3486 llvm::Value *UBVal = DispatchBounds.second;
3487 CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal,
3490 IVSigned, Ordered, DipatchRTInputValues);
3492 CGOpenMPRuntime::StaticRTInput StaticInit(
3493 IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
3494 LoopArgs.ST, LoopArgs.Chunk);
3500 auto &&CodeGenOrdered = [Ordered](CodeGenFunction &CGF, SourceLocation Loc,
3501 const unsigned IVSize,
3502 const bool IVSigned) {
3509 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST,
3510 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB);
3511 OuterLoopArgs.IncExpr = S.getInc();
3512 OuterLoopArgs.Init = S.getInit();
3513 OuterLoopArgs.Cond = S.getCond();
3514 OuterLoopArgs.NextLB = S.getNextLowerBound();
3515 OuterLoopArgs.NextUB = S.getNextUpperBound();
3516 OuterLoopArgs.DKind = LoopArgs.DKind;
3517 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
3519 if (DynamicOrOrdered) {
3525 const unsigned IVSize,
const bool IVSigned) {}
3527void CodeGenFunction::EmitOMPDistributeOuterLoop(
3532 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3539 const Expr *IVExpr = S.getIterationVariable();
3544 CGOpenMPRuntime::StaticRTInput StaticInit(
3545 IVSize, IVSigned,
false, LoopArgs.IL, LoopArgs.LB,
3546 LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
3553 IncExpr = S.getDistInc();
3555 IncExpr = S.getInc();
3560 OMPLoopArguments OuterLoopArgs;
3561 OuterLoopArgs.LB = LoopArgs.LB;
3562 OuterLoopArgs.UB = LoopArgs.UB;
3563 OuterLoopArgs.ST = LoopArgs.ST;
3564 OuterLoopArgs.IL = LoopArgs.IL;
3565 OuterLoopArgs.Chunk = LoopArgs.Chunk;
3567 ? S.getCombinedEnsureUpperBound()
3568 : S.getEnsureUpperBound();
3569 OuterLoopArgs.IncExpr = IncExpr;
3571 ? S.getCombinedInit()
3574 ? S.getCombinedCond()
3577 ? S.getCombinedNextLowerBound()
3578 : S.getNextLowerBound();
3580 ? S.getCombinedNextUpperBound()
3581 : S.getNextUpperBound();
3582 OuterLoopArgs.DKind = OMPD_distribute;
3584 EmitOMPOuterLoop(
false,
false, S,
3585 LoopScope, OuterLoopArgs, CodeGenLoopContent,
3589static std::pair<LValue, LValue>
3604 LValue PrevLB = CGF.
EmitLValue(LS.getPrevLowerBoundVariable());
3605 LValue PrevUB = CGF.
EmitLValue(LS.getPrevUpperBoundVariable());
3607 PrevLB, LS.getPrevLowerBoundVariable()->getExprLoc());
3609 PrevLBVal, LS.getPrevLowerBoundVariable()->getType(),
3610 LS.getIterationVariable()->getType(),
3611 LS.getPrevLowerBoundVariable()->getExprLoc());
3613 PrevUB, LS.getPrevUpperBoundVariable()->getExprLoc());
3615 PrevUBVal, LS.getPrevUpperBoundVariable()->getType(),
3616 LS.getIterationVariable()->getType(),
3617 LS.getPrevUpperBoundVariable()->getExprLoc());
3632static std::pair<llvm::Value *, llvm::Value *>
3637 const Expr *IVExpr = LS.getIterationVariable();
3643 llvm::Value *LBVal =
3645 llvm::Value *UBVal =
3647 return {LBVal, UBVal};
3656 llvm::Value *LBCast = CGF.
Builder.CreateIntCast(
3658 CapturedVars.push_back(LBCast);
3662 llvm::Value *UBCast = CGF.
Builder.CreateIntCast(
3664 CapturedVars.push_back(UBCast);
3675 bool HasCancel =
false;
3677 if (
const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
3678 HasCancel = D->hasCancel();
3679 else if (
const auto *D = dyn_cast<OMPDistributeParallelForDirective>(&S))
3680 HasCancel = D->hasCancel();
3681 else if (
const auto *D =
3682 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S))
3683 HasCancel = D->hasCancel();
3693 CGInlinedWorksharingLoop,
3703 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3704 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3713 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3714 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3722 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
3723 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
3733 llvm::Constant *
Addr;
3735 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
3737 assert(Fn &&
Addr &&
"Target device function emission failed.");
3749struct ScheduleKindModifiersTy {
3756 : Kind(Kind), M1(M1), M2(M2) {}
3772 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
3780 bool HasLastprivateClause;
3783 OMPLoopScope PreInitScope(*
this, S);
3788 llvm::BasicBlock *ContBlock =
nullptr;
3795 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
3802 bool Ordered =
false;
3803 if (
const auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) {
3804 if (OrderedClause->getNumForLoops())
3814 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*
this, S);
3815 LValue LB = Bounds.first;
3816 LValue UB = Bounds.second;
3830 CGM.getOpenMPRuntime().emitBarrierCall(
3831 *
this, S.getBeginLoc(), OMPD_unknown,
false,
3836 *
this, S,
EmitLValue(S.getIterationVariable()));
3843 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
3846 const Expr *ChunkExpr =
nullptr;
3848 if (
const auto *
C = S.getSingleClause<OMPScheduleClause>()) {
3849 ScheduleKind.
Schedule =
C->getScheduleKind();
3850 ScheduleKind.
M1 =
C->getFirstScheduleModifier();
3851 ScheduleKind.
M2 =
C->getSecondScheduleModifier();
3852 ChunkExpr =
C->getChunkSize();
3855 CGM.getOpenMPRuntime().getDefaultScheduleAndChunk(
3856 *
this, S, ScheduleKind.
Schedule, ChunkExpr);
3858 bool HasChunkSizeOne =
false;
3859 llvm::Value *Chunk =
nullptr;
3863 S.getIterationVariable()->getType(),
3867 llvm::APSInt EvaluatedChunk =
Result.Val.getInt();
3868 HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
3877 bool StaticChunkedOne =
3879 Chunk !=
nullptr) &&
3883 (ScheduleKind.
Schedule == OMPC_SCHEDULE_static &&
3884 !(ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
3885 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)) ||
3886 ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
3887 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
3889 Chunk !=
nullptr) ||
3890 StaticChunkedOne) &&
3900 if (
C->getKind() == OMPC_ORDER_concurrent)
3904 [IVSize, IVSigned, Ordered, IL, LB, UB, ST, StaticChunkedOne, Chunk,
3913 IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(),
3914 UB.getAddress(), ST.getAddress(),
3915 StaticChunkedOne ? Chunk :
nullptr);
3917 CGF, S.getBeginLoc(), EKind, ScheduleKind, StaticInit);
3919 if (!StaticChunkedOne)
3938 StaticChunkedOne ? S.getCombinedParForInDistCond()
3940 StaticChunkedOne ? S.getDistInc() : S.getInc(),
3941 [&S,
LoopExit](CodeGenFunction &CGF) {
3942 emitOMPLoopBodyWithStopPoint(CGF, S, LoopExit);
3944 [](CodeGenFunction &) {});
3948 auto &&
CodeGen = [&S](CodeGenFunction &CGF) {
3952 OMPCancelStack.emitExit(*
this, EKind,
CodeGen);
3959 LoopArguments.DKind = OMPD_for;
3960 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
3961 LoopArguments, CGDispatchBounds);
3965 return CGF.
Builder.CreateIsNotNull(
3971 ? OMPD_parallel_for_simd
3975 *
this, S, [IL, &S](CodeGenFunction &CGF) {
3976 return CGF.
Builder.CreateIsNotNull(
3980 if (HasLastprivateClause)
3986 return CGF.
Builder.CreateIsNotNull(
3997 return HasLastprivateClause;
4003static std::pair<LValue, LValue>
4017static std::pair<llvm::Value *, llvm::Value *>
4021 const Expr *IVExpr = LS.getIterationVariable();
4023 llvm::Value *LBVal = CGF.
Builder.getIntN(IVSize, 0);
4025 return {LBVal, UBVal};
4037 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
4038 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4039 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4044 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4045 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4046 "Only inscan reductions are expected.");
4047 Shareds.append(
C->varlist_begin(),
C->varlist_end());
4048 Privates.append(
C->privates().begin(),
C->privates().end());
4049 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
4050 CopyArrayTemps.append(
C->copy_array_temps().begin(),
4051 C->copy_array_temps().end());
4059 auto *ITA = CopyArrayTemps.begin();
4064 if (PrivateVD->getType()->isVariablyModifiedType()) {
4089 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
4090 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4091 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4098 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4099 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4100 "Only inscan reductions are expected.");
4101 Shareds.append(
C->varlist_begin(),
C->varlist_end());
4102 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
4103 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
4104 Privates.append(
C->privates().begin(),
C->privates().end());
4105 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
4106 CopyArrayElems.append(
C->copy_array_elems().begin(),
4107 C->copy_array_elems().end());
4111 llvm::Value *OMPLast = CGF.
Builder.CreateNSWSub(
4112 OMPScanNumIterations,
4113 llvm::ConstantInt::get(CGF.
SizeTy, 1,
false));
4114 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
4116 const Expr *OrigExpr = Shareds[I];
4117 const Expr *CopyArrayElem = CopyArrayElems[I];
4124 LValue SrcLVal = CGF.
EmitLValue(CopyArrayElem);
4126 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
4156 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4157 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4163 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4164 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4165 "Only inscan reductions are expected.");
4166 Privates.append(
C->privates().begin(),
C->privates().end());
4167 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
4168 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
4169 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
4170 CopyArrayElems.append(
C->copy_array_elems().begin(),
4171 C->copy_array_elems().end());
4186 auto &&
CodeGen = [&S, OMPScanNumIterations, &LHSs, &RHSs, &CopyArrayElems,
4193 llvm::BasicBlock *InputBB = CGF.Builder.GetInsertBlock();
4194 llvm::BasicBlock *LoopBB = CGF.createBasicBlock(
"omp.outer.log.scan.body");
4195 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
"omp.outer.log.scan.exit");
4197 CGF.CGM.getIntrinsic(llvm::Intrinsic::log2, CGF.DoubleTy);
4199 CGF.Builder.CreateUIToFP(OMPScanNumIterations, CGF.DoubleTy);
4200 llvm::Value *LogVal = CGF.EmitNounwindRuntimeCall(F, Arg);
4201 F = CGF.CGM.getIntrinsic(llvm::Intrinsic::ceil, CGF.DoubleTy);
4202 LogVal = CGF.EmitNounwindRuntimeCall(F, LogVal);
4203 LogVal = CGF.Builder.CreateFPToUI(LogVal, CGF.IntTy);
4204 llvm::Value *NMin1 = CGF.Builder.CreateNUWSub(
4205 OMPScanNumIterations, llvm::ConstantInt::get(CGF.SizeTy, 1));
4207 CGF.EmitBlock(LoopBB);
4208 auto *Counter = CGF.Builder.CreatePHI(CGF.IntTy, 2);
4210 auto *Pow2K = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
4211 Counter->addIncoming(llvm::ConstantInt::get(CGF.IntTy, 0), InputBB);
4212 Pow2K->addIncoming(llvm::ConstantInt::get(CGF.SizeTy, 1), InputBB);
4215 llvm::BasicBlock *InnerLoopBB =
4216 CGF.createBasicBlock(
"omp.inner.log.scan.body");
4217 llvm::BasicBlock *InnerExitBB =
4218 CGF.createBasicBlock(
"omp.inner.log.scan.exit");
4219 llvm::Value *CmpI = CGF.Builder.CreateICmpUGE(NMin1, Pow2K);
4220 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4221 CGF.EmitBlock(InnerLoopBB);
4222 auto *IVal = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
4223 IVal->addIncoming(NMin1, LoopBB);
4226 auto *ILHS = LHSs.begin();
4227 auto *IRHS = RHSs.begin();
4228 for (
const Expr *CopyArrayElem : CopyArrayElems) {
4238 LHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4243 llvm::Value *OffsetIVal = CGF.Builder.CreateNUWSub(IVal, Pow2K);
4249 RHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4256 CGF.CGM.getOpenMPRuntime().emitReduction(
4257 CGF, S.getEndLoc(),
Privates, LHSs, RHSs, ReductionOps,
4261 llvm::Value *NextIVal =
4262 CGF.Builder.CreateNUWSub(IVal, llvm::ConstantInt::get(CGF.SizeTy, 1));
4263 IVal->addIncoming(NextIVal, CGF.Builder.GetInsertBlock());
4264 CmpI = CGF.Builder.CreateICmpUGE(NextIVal, Pow2K);
4265 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4266 CGF.EmitBlock(InnerExitBB);
4268 CGF.Builder.CreateNUWAdd(Counter, llvm::ConstantInt::get(CGF.IntTy, 1));
4269 Counter->addIncoming(
Next, CGF.Builder.GetInsertBlock());
4271 llvm::Value *NextPow2K =
4272 CGF.Builder.CreateShl(Pow2K, 1,
"",
true);
4273 Pow2K->addIncoming(NextPow2K, CGF.Builder.GetInsertBlock());
4274 llvm::Value *
Cmp = CGF.Builder.CreateICmpNE(
Next, LogVal);
4275 CGF.Builder.CreateCondBr(
Cmp, LoopBB, ExitBB);
4277 CGF.EmitBlock(ExitBB);
4283 CGF, S.getBeginLoc(), OMPD_unknown,
false,
4286 RegionCodeGenTy RCG(CodeGen);
4297 bool HasLastprivates;
4299 if (llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4300 [](
const OMPReductionClause *
C) {
4301 return C->getModifier() == OMPC_REDUCTION_inscan;
4305 OMPLoopScope LoopScope(CGF, S);
4308 const auto &&FirstGen = [&S, HasCancel, EKind](
CodeGenFunction &CGF) {
4317 const auto &&SecondGen = [&S, HasCancel, EKind,
4335 return HasLastprivates;
4348 if (
auto *SC = dyn_cast<OMPScheduleClause>(
C)) {
4353 switch (SC->getScheduleKind()) {
4354 case OMPC_SCHEDULE_auto:
4355 case OMPC_SCHEDULE_dynamic:
4356 case OMPC_SCHEDULE_runtime:
4357 case OMPC_SCHEDULE_guided:
4358 case OMPC_SCHEDULE_static:
4371static llvm::omp::ScheduleKind
4373 switch (ScheduleClauseKind) {
4375 return llvm::omp::OMP_SCHEDULE_Default;
4376 case OMPC_SCHEDULE_auto:
4377 return llvm::omp::OMP_SCHEDULE_Auto;
4378 case OMPC_SCHEDULE_dynamic:
4379 return llvm::omp::OMP_SCHEDULE_Dynamic;
4380 case OMPC_SCHEDULE_guided:
4381 return llvm::omp::OMP_SCHEDULE_Guided;
4382 case OMPC_SCHEDULE_runtime:
4383 return llvm::omp::OMP_SCHEDULE_Runtime;
4384 case OMPC_SCHEDULE_static:
4385 return llvm::omp::OMP_SCHEDULE_Static;
4387 llvm_unreachable(
"Unhandled schedule kind");
4394 bool HasLastprivates =
false;
4397 auto &&
CodeGen = [&S, &
CGM, HasCancel, &HasLastprivates,
4400 if (UseOMPIRBuilder) {
4401 bool NeedsBarrier = !S.getSingleClause<OMPNowaitClause>();
4403 llvm::omp::ScheduleKind SchedKind = llvm::omp::OMP_SCHEDULE_Default;
4404 llvm::Value *ChunkSize =
nullptr;
4405 if (
auto *SchedClause = S.getSingleClause<OMPScheduleClause>()) {
4408 if (
const Expr *ChunkSizeExpr = SchedClause->getChunkSize())
4413 const Stmt *Inner = S.getRawStmt();
4414 llvm::CanonicalLoopInfo *CLI =
4417 llvm::OpenMPIRBuilder &OMPBuilder =
4419 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4421 cantFail(OMPBuilder.applyWorkshareLoop(
4422 CGF.
Builder.getCurrentDebugLocation(), CLI, AllocaIP, NeedsBarrier,
4423 SchedKind, ChunkSize,
false,
4434 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
4439 if (!UseOMPIRBuilder) {
4441 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4453 bool HasLastprivates =
false;
4454 auto &&
CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
4461 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4462 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
4466 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4467 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_for);
4474 llvm::Value *
Init =
nullptr) {
4481void CodeGenFunction::EmitSections(
const OMPExecutableDirective &S) {
4482 const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4483 const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt);
4484 bool HasLastprivates =
false;
4486 auto &&CodeGen = [&S, CapturedStmt, CS, EKind,
4487 &HasLastprivates](CodeGenFunction &CGF, PrePostActionTy &) {
4488 const ASTContext &
C = CGF.getContext();
4489 QualType KmpInt32Ty =
4490 C.getIntTypeForBitwidth(32, 1);
4493 CGF.Builder.getInt32(0));
4494 llvm::ConstantInt *GlobalUBVal = CS !=
nullptr
4495 ? CGF.Builder.getInt32(CS->size() - 1)
4496 : CGF.Builder.getInt32(0);
4500 CGF.Builder.getInt32(1));
4502 CGF.Builder.getInt32(0));
4505 OpaqueValueExpr IVRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4506 CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
4507 OpaqueValueExpr UBRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4508 CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
4512 S.getBeginLoc(), FPOptionsOverride());
4516 S.getBeginLoc(),
true, FPOptionsOverride());
4517 auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
4529 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".omp.sections.exit");
4530 llvm::SwitchInst *SwitchStmt =
4531 CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.
getBeginLoc()),
4532 ExitBB, CS ==
nullptr ? 1 : CS->size());
4534 unsigned CaseNumber = 0;
4535 for (
const Stmt *SubStmt : CS->
children()) {
4536 auto CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4537 CGF.EmitBlock(CaseBB);
4538 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
4539 CGF.EmitStmt(SubStmt);
4540 CGF.EmitBranch(ExitBB);
4544 llvm::BasicBlock *CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4545 CGF.EmitBlock(CaseBB);
4546 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
4547 CGF.EmitStmt(CapturedStmt);
4548 CGF.EmitBranch(ExitBB);
4550 CGF.EmitBlock(ExitBB,
true);
4553 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
4554 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
4558 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
4562 CGF.EmitOMPPrivateClause(S, LoopScope);
4563 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(CGF, S, IV);
4564 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
4565 CGF.EmitOMPReductionClauseInit(S, LoopScope);
4566 (void)LoopScope.Privatize();
4568 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
4571 OpenMPScheduleTy ScheduleKind;
4572 ScheduleKind.
Schedule = OMPC_SCHEDULE_static;
4573 CGOpenMPRuntime::StaticRTInput StaticInit(
4574 32,
true,
false, IL.getAddress(),
4575 LB.getAddress(), UB.getAddress(), ST.getAddress());
4576 CGF.CGM.getOpenMPRuntime().emitForStaticInit(CGF, S.
getBeginLoc(), EKind,
4577 ScheduleKind, StaticInit);
4579 llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.
getBeginLoc());
4580 llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
4581 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
4582 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
4584 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.
getBeginLoc()), IV);
4586 CGF.EmitOMPInnerLoop(S,
false,
Cond, Inc, BodyGen,
4587 [](CodeGenFunction &) {});
4589 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
4590 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.
getEndLoc(),
4593 CGF.OMPCancelStack.emitExit(CGF, EKind, CodeGen);
4594 CGF.EmitOMPReductionClauseFinal(S, OMPD_parallel);
4597 return CGF.
Builder.CreateIsNotNull(
4602 if (HasLastprivates)
4609 bool HasCancel =
false;
4610 if (
auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
4611 HasCancel = OSD->hasCancel();
4612 else if (
auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
4613 HasCancel = OPSD->hasCancel();
4615 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_sections, CodeGen,
4620 if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) {
4638 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4643 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4644 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_scope,
CodeGen);
4647 if (!S.getSingleClause<OMPNowaitClause>()) {
4648 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_scope);
4655 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4656 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4657 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4658 using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
4660 auto FiniCB = [](InsertPointTy IP) {
4663 return llvm::Error::success();
4666 const CapturedStmt *ICS = S.getInnermostCapturedStmt();
4672 auto SectionCB = [
this, SubStmt](InsertPointTy AllocaIP,
4673 InsertPointTy CodeGenIP) {
4675 *
this, SubStmt, AllocaIP, CodeGenIP,
"section");
4676 return llvm::Error::success();
4678 SectionCBVector.push_back(SectionCB);
4681 auto SectionCB = [
this,
CapturedStmt](InsertPointTy AllocaIP,
4682 InsertPointTy CodeGenIP) {
4685 return llvm::Error::success();
4687 SectionCBVector.push_back(SectionCB);
4694 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
4695 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
4705 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4707 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4708 cantFail(OMPBuilder.createSections(
4709 Builder, AllocaIP, SectionCBVector, PrivCB, FiniCB, S.hasCancel(),
4710 S.getSingleClause<OMPNowaitClause>()));
4717 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4721 if (!S.getSingleClause<OMPNowaitClause>()) {
4722 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(),
4730 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4731 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4732 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4734 const Stmt *SectionRegionBodyStmt = S.getAssociatedStmt();
4735 auto FiniCB = [
this](InsertPointTy IP) {
4737 return llvm::Error::success();
4740 auto BodyGenCB = [SectionRegionBodyStmt,
this](InsertPointTy AllocaIP,
4741 InsertPointTy CodeGenIP) {
4743 *
this, SectionRegionBodyStmt, AllocaIP, CodeGenIP,
"section");
4744 return llvm::Error::success();
4749 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4750 cantFail(OMPBuilder.createSection(
Builder, BodyGenCB, FiniCB));
4770 CopyprivateVars.append(
C->varlist_begin(),
C->varlist_end());
4771 DestExprs.append(
C->destination_exprs().begin(),
4772 C->destination_exprs().end());
4773 SrcExprs.append(
C->source_exprs().begin(),
C->source_exprs().end());
4774 AssignmentOps.append(
C->assignment_ops().begin(),
4775 C->assignment_ops().end());
4784 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4789 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4790 CGM.getOpenMPRuntime().emitSingleRegion(*
this,
CodeGen, S.getBeginLoc(),
4791 CopyprivateVars, DestExprs,
4792 SrcExprs, AssignmentOps);
4796 if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) {
4797 CGM.getOpenMPRuntime().emitBarrierCall(
4798 *
this, S.getBeginLoc(),
4799 S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);
4814 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4815 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4816 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4818 const Stmt *MasterRegionBodyStmt = S.getAssociatedStmt();
4820 auto FiniCB = [
this](InsertPointTy IP) {
4822 return llvm::Error::success();
4825 auto BodyGenCB = [MasterRegionBodyStmt,
this](InsertPointTy AllocaIP,
4826 InsertPointTy CodeGenIP) {
4828 *
this, MasterRegionBodyStmt, AllocaIP, CodeGenIP,
"master");
4829 return llvm::Error::success();
4834 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4835 cantFail(OMPBuilder.createMaster(
Builder, BodyGenCB, FiniCB));
4850 Expr *Filter =
nullptr;
4852 Filter = FilterClause->getThreadID();
4858 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4859 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4860 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4862 const Stmt *MaskedRegionBodyStmt = S.getAssociatedStmt();
4863 const Expr *Filter =
nullptr;
4865 Filter = FilterClause->getThreadID();
4866 llvm::Value *FilterVal = Filter
4868 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
4870 auto FiniCB = [
this](InsertPointTy IP) {
4872 return llvm::Error::success();
4875 auto BodyGenCB = [MaskedRegionBodyStmt,
this](InsertPointTy AllocaIP,
4876 InsertPointTy CodeGenIP) {
4878 *
this, MaskedRegionBodyStmt, AllocaIP, CodeGenIP,
"masked");
4879 return llvm::Error::success();
4884 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
4885 OMPBuilder.createMasked(
Builder, BodyGenCB, FiniCB, FilterVal));
4896 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4897 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4898 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4900 const Stmt *CriticalRegionBodyStmt = S.getAssociatedStmt();
4901 const Expr *Hint =
nullptr;
4902 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4903 Hint = HintClause->getHint();
4908 llvm::Value *HintInst =
nullptr;
4913 auto FiniCB = [
this](InsertPointTy IP) {
4915 return llvm::Error::success();
4918 auto BodyGenCB = [CriticalRegionBodyStmt,
this](InsertPointTy AllocaIP,
4919 InsertPointTy CodeGenIP) {
4921 *
this, CriticalRegionBodyStmt, AllocaIP, CodeGenIP,
"critical");
4922 return llvm::Error::success();
4927 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4928 cantFail(OMPBuilder.createCritical(
Builder, BodyGenCB, FiniCB,
4929 S.getDirectiveName().getAsString(),
4938 CGF.
EmitStmt(S.getAssociatedStmt());
4940 const Expr *Hint =
nullptr;
4941 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4942 Hint = HintClause->getHint();
4945 CGM.getOpenMPRuntime().emitCriticalRegion(*
this,
4946 S.getDirectiveName().getAsString(),
4947 CodeGen, S.getBeginLoc(), Hint);
4951 const OMPParallelForDirective &S) {
4960 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
4964 OMPLoopScope LoopScope(CGF, S);
4967 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4968 [](
const OMPReductionClause *
C) {
4969 return C->getModifier() == OMPC_REDUCTION_inscan;
4985 const OMPParallelForSimdDirective &S) {
4994 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
4998 OMPLoopScope LoopScope(CGF, S);
5001 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
5002 [](
const OMPReductionClause *
C) {
5003 return C->getModifier() == OMPC_REDUCTION_inscan;
5019 const OMPParallelMasterDirective &S) {
5039 [](CodeGenFunction &) {
return nullptr; });
5046 const OMPParallelMaskedDirective &S) {
5066 [](CodeGenFunction &) {
return nullptr; });
5073 const OMPParallelSectionsDirective &S) {
5079 CGF.EmitSections(S);
5093class CheckVarsEscapingUntiedTaskDeclContext final
5098 explicit CheckVarsEscapingUntiedTaskDeclContext() =
default;
5099 ~CheckVarsEscapingUntiedTaskDeclContext() =
default;
5100 void VisitDeclStmt(
const DeclStmt *S) {
5105 if (
const auto *VD = dyn_cast_or_null<VarDecl>(D))
5107 PrivateDecls.push_back(VD);
5111 void VisitCapturedStmt(
const CapturedStmt *) {}
5113 void VisitBlockExpr(
const BlockExpr *) {}
5114 void VisitStmt(
const Stmt *S) {
5117 for (
const Stmt *Child : S->
children())
5123 ArrayRef<const VarDecl *> getPrivateDecls()
const {
return PrivateDecls; }
5131 bool OmpAllMemory =
false;
5134 return C->getDependencyKind() == OMPC_DEPEND_outallmemory ||
5135 C->getDependencyKind() == OMPC_DEPEND_inoutallmemory;
5137 OmpAllMemory =
true;
5142 Data.Dependences.emplace_back(OMPC_DEPEND_outallmemory,
5151 if (Kind == OMPC_DEPEND_outallmemory || Kind == OMPC_DEPEND_inoutallmemory)
5153 if (OmpAllMemory && (Kind == OMPC_DEPEND_out || Kind == OMPC_DEPEND_inout))
5156 Data.Dependences.emplace_back(
C->getDependencyKind(),
C->getModifier());
5157 DD.
DepExprs.append(
C->varlist_begin(),
C->varlist_end());
5166 const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion);
5168 auto PartId = std::next(I);
5169 auto TaskT = std::next(I, 4);
5174 const Expr *
Cond = Clause->getCondition();
5177 Data.Final.setInt(CondConstant);
5182 Data.Final.setInt(
false);
5186 const Expr *Prio = Clause->getPriority();
5187 Data.Priority.setInt(
true);
5195 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
5197 for (
const auto *
C : S.getClausesOfKind<OMPPrivateClause>()) {
5198 auto IRef =
C->varlist_begin();
5199 for (
const Expr *IInit :
C->private_copies()) {
5201 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
5202 Data.PrivateVars.push_back(*IRef);
5203 Data.PrivateCopies.push_back(IInit);
5208 EmittedAsPrivate.clear();
5210 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5211 auto IRef =
C->varlist_begin();
5212 auto IElemInitRef =
C->inits().begin();
5213 for (
const Expr *IInit :
C->private_copies()) {
5215 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
5216 Data.FirstprivateVars.push_back(*IRef);
5217 Data.FirstprivateCopies.push_back(IInit);
5218 Data.FirstprivateInits.push_back(*IElemInitRef);
5225 llvm::MapVector<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
5226 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
5227 auto IRef =
C->varlist_begin();
5228 auto ID =
C->destination_exprs().begin();
5229 for (
const Expr *IInit :
C->private_copies()) {
5231 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
5232 Data.LastprivateVars.push_back(*IRef);
5233 Data.LastprivateCopies.push_back(IInit);
5235 LastprivateDstsOrigs.insert(
5244 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
5245 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5246 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5247 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5248 Data.ReductionOps.append(
C->reduction_ops().begin(),
5249 C->reduction_ops().end());
5250 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5251 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5253 Data.Reductions =
CGM.getOpenMPRuntime().emitTaskReductionInit(
5254 *
this, S.getBeginLoc(), LHSs, RHSs,
Data);
5259 CheckVarsEscapingUntiedTaskDeclContext Checker;
5260 Checker.Visit(S.getInnermostCapturedStmt()->getCapturedStmt());
5261 Data.PrivateLocals.append(Checker.getPrivateDecls().begin(),
5262 Checker.getPrivateDecls().end());
5264 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
5265 CapturedRegion](CodeGenFunction &CGF,
5267 llvm::MapVector<CanonicalDeclPtr<const VarDecl>,
5268 std::pair<Address, Address>>
5273 if (
auto *DI = CGF.getDebugInfo()) {
5274 llvm::SmallDenseMap<const VarDecl *, FieldDecl *> CaptureFields =
5275 CGF.CapturedStmtInfo->getCaptureFields();
5276 llvm::Value *ContextValue = CGF.CapturedStmtInfo->getContextValue();
5277 if (CaptureFields.size() && ContextValue) {
5278 unsigned CharWidth = CGF.getContext().getCharWidth();
5292 for (
auto It = CaptureFields.begin(); It != CaptureFields.end(); ++It) {
5293 const VarDecl *SharedVar = It->first;
5296 CGF.getContext().getASTRecordLayout(CaptureRecord);
5299 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5300 (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue,
5301 CGF.Builder,
false);
5304 auto UpdateExpr = [](llvm::LLVMContext &Ctx,
auto *
Declare,
5309 Ops.push_back(llvm::dwarf::DW_OP_plus_uconst);
5310 Ops.push_back(Offset);
5312 Ops.push_back(llvm::dwarf::DW_OP_deref);
5313 Declare->setExpression(llvm::DIExpression::get(Ctx, Ops));
5315 llvm::Instruction &
Last = CGF.Builder.GetInsertBlock()->back();
5316 if (
auto DDI = dyn_cast<llvm::DbgVariableIntrinsic>(&
Last))
5317 UpdateExpr(DDI->getContext(), DDI, Offset);
5320 assert(!
Last.isTerminator() &&
"unexpected terminator");
5322 CGF.Builder.GetInsertBlock()->getTrailingDbgRecords()) {
5323 for (llvm::DbgVariableRecord &DVR : llvm::reverse(
5324 llvm::filterDbgVars(Marker->getDbgRecordRange()))) {
5325 UpdateExpr(
Last.getContext(), &DVR, Offset);
5333 if (!
Data.PrivateVars.empty() || !
Data.FirstprivateVars.empty() ||
5334 !
Data.LastprivateVars.empty() || !
Data.PrivateLocals.empty()) {
5335 enum { PrivatesParam = 2, CopyFnParam = 3 };
5336 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5338 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5344 CallArgs.push_back(PrivatesPtr);
5345 ParamTypes.push_back(PrivatesPtr->getType());
5346 for (
const Expr *E :
Data.PrivateVars) {
5349 CGF.getContext().getPointerType(E->
getType()),
".priv.ptr.addr");
5350 PrivatePtrs.emplace_back(VD, PrivatePtr);
5352 ParamTypes.push_back(PrivatePtr.
getType());
5354 for (
const Expr *E :
Data.FirstprivateVars) {
5357 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
5358 ".firstpriv.ptr.addr");
5359 PrivatePtrs.emplace_back(VD, PrivatePtr);
5360 FirstprivatePtrs.emplace_back(VD, PrivatePtr);
5362 ParamTypes.push_back(PrivatePtr.
getType());
5364 for (
const Expr *E :
Data.LastprivateVars) {
5367 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
5368 ".lastpriv.ptr.addr");
5369 PrivatePtrs.emplace_back(VD, PrivatePtr);
5371 ParamTypes.push_back(PrivatePtr.
getType());
5376 Ty = CGF.getContext().getPointerType(Ty);
5378 Ty = CGF.getContext().getPointerType(Ty);
5380 CGF.getContext().getPointerType(Ty),
".local.ptr.addr");
5381 auto Result = UntiedLocalVars.insert(
5384 if (
Result.second ==
false)
5385 *
Result.first = std::make_pair(
5388 ParamTypes.push_back(PrivatePtr.
getType());
5390 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5392 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5393 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5394 for (
const auto &Pair : LastprivateDstsOrigs) {
5398 CGF.CapturedStmtInfo->lookup(OrigVD) !=
nullptr,
5400 Pair.second->getExprLoc());
5401 Scope.addPrivate(Pair.first, CGF.EmitLValue(&DRE).getAddress());
5403 for (
const auto &Pair : PrivatePtrs) {
5405 CGF.Builder.CreateLoad(Pair.second),
5406 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5407 CGF.getContext().getDeclAlign(Pair.first));
5408 Scope.addPrivate(Pair.first, Replacement);
5409 if (
auto *DI = CGF.getDebugInfo())
5410 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5411 (void)DI->EmitDeclareOfAutoVariable(
5412 Pair.first, Pair.second.getBasePointer(), CGF.Builder,
5417 for (
auto &Pair : UntiedLocalVars) {
5418 QualType VDType = Pair.first->getType().getNonReferenceType();
5419 if (Pair.first->getType()->isLValueReferenceType())
5420 VDType = CGF.getContext().getPointerType(VDType);
5422 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5425 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(VDType)),
5426 CGF.getPointerAlign());
5427 Pair.second.first = Replacement;
5428 Ptr = CGF.Builder.CreateLoad(Replacement);
5429 Replacement =
Address(Ptr, CGF.ConvertTypeForMem(VDType),
5430 CGF.getContext().getDeclAlign(Pair.first));
5431 Pair.second.second = Replacement;
5433 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5434 Address Replacement(Ptr, CGF.ConvertTypeForMem(VDType),
5435 CGF.getContext().getDeclAlign(Pair.first));
5436 Pair.second.first = Replacement;
5440 if (
Data.Reductions) {
5442 for (
const auto &Pair : FirstprivatePtrs) {
5444 CGF.Builder.CreateLoad(Pair.second),
5445 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5446 CGF.getContext().getDeclAlign(Pair.first));
5447 FirstprivateScope.
addPrivate(Pair.first, Replacement);
5450 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5452 Data.ReductionCopies,
Data.ReductionOps);
5453 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
5455 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5461 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5463 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5466 CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF),
5467 CGF.getContext().VoidPtrTy,
5468 CGF.getContext().getPointerType(
5469 Data.ReductionCopies[Cnt]->getType()),
5470 Data.ReductionCopies[Cnt]->getExprLoc()),
5471 CGF.ConvertTypeForMem(
Data.ReductionCopies[Cnt]->getType()),
5472 Replacement.getAlignment());
5478 (void)
Scope.Privatize();
5483 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5484 auto IPriv =
C->privates().begin();
5485 auto IRed =
C->reduction_ops().begin();
5486 auto ITD =
C->taskgroup_descriptors().begin();
5487 for (
const Expr *Ref :
C->varlist()) {
5488 InRedVars.emplace_back(Ref);
5489 InRedPrivs.emplace_back(*IPriv);
5490 InRedOps.emplace_back(*IRed);
5491 TaskgroupDescriptors.emplace_back(*ITD);
5492 std::advance(IPriv, 1);
5493 std::advance(IRed, 1);
5494 std::advance(ITD, 1);
5500 if (!InRedVars.empty()) {
5502 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5510 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5512 llvm::Value *ReductionsPtr;
5513 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5514 ReductionsPtr = CGF.EmitLoadOfScalar(CGF.EmitLValue(TRExpr),
5515 TRExpr->getExprLoc());
5517 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5519 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5522 CGF.EmitScalarConversion(
5523 Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy,
5524 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
5525 InRedPrivs[Cnt]->getExprLoc()),
5526 CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()),
5527 Replacement.getAlignment());
5540 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5541 S, *I, *PartId, *TaskT, EKind,
CodeGen,
Data.Tied,
Data.NumberOfParts);
5542 OMPLexicalScope
Scope(*
this, S, std::nullopt,
5545 TaskGen(*
this, OutlinedFn,
Data);
5562 QualType ElemType =
C.getBaseElementType(Ty);
5572 Data.FirstprivateVars.emplace_back(OrigRef);
5573 Data.FirstprivateCopies.emplace_back(PrivateRef);
5574 Data.FirstprivateInits.emplace_back(InitRef);
5587 auto PartId = std::next(I);
5588 auto TaskT = std::next(I, 4);
5591 Data.Final.setInt(
false);
5593 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5594 auto IRef =
C->varlist_begin();
5595 auto IElemInitRef =
C->inits().begin();
5596 for (
auto *IInit :
C->private_copies()) {
5597 Data.FirstprivateVars.push_back(*IRef);
5598 Data.FirstprivateCopies.push_back(IInit);
5599 Data.FirstprivateInits.push_back(*IElemInitRef);
5606 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5607 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5608 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5609 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5610 Data.ReductionOps.append(
C->reduction_ops().begin(),
5611 C->reduction_ops().end());
5612 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5613 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5628 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5630 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5642 if (!isa_and_nonnull<llvm::ConstantPointerNull>(
5645 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5652 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, BPVD, PVD, SVD, MVD, EKind,
5656 if (!
Data.FirstprivateVars.empty()) {
5657 enum { PrivatesParam = 2, CopyFnParam = 3 };
5658 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5660 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5666 CallArgs.push_back(PrivatesPtr);
5667 ParamTypes.push_back(PrivatesPtr->getType());
5668 for (
const Expr *E :
Data.FirstprivateVars) {
5671 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
5672 ".firstpriv.ptr.addr");
5673 PrivatePtrs.emplace_back(VD, PrivatePtr);
5675 ParamTypes.push_back(PrivatePtr.
getType());
5677 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5679 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5680 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5681 for (
const auto &Pair : PrivatePtrs) {
5683 CGF.Builder.CreateLoad(Pair.second),
5684 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5685 CGF.getContext().getDeclAlign(Pair.first));
5686 Scope.addPrivate(Pair.first, Replacement);
5689 CGF.processInReduction(S,
Data, CGF, CS,
Scope);
5692 CGF.GetAddrOfLocalVar(BPVD), 0);
5694 CGF.GetAddrOfLocalVar(PVD), 0);
5695 InputInfo.
SizesArray = CGF.Builder.CreateConstArrayGEP(
5696 CGF.GetAddrOfLocalVar(SVD), 0);
5699 InputInfo.
MappersArray = CGF.Builder.CreateConstArrayGEP(
5700 CGF.GetAddrOfLocalVar(MVD), 0);
5704 OMPLexicalScope LexScope(CGF, S, OMPD_task,
false);
5706 if (CGF.CGM.getLangOpts().OpenMP >= 51 &&
5711 CGF.CGM.getOpenMPRuntime().emitThreadLimitClause(
5712 CGF, TL->getThreadLimit().front(), S.getBeginLoc());
5716 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5717 S, *I, *PartId, *TaskT, EKind,
CodeGen,
true,
5718 Data.NumberOfParts);
5719 llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<OMPNowaitClause>() ? 1 : 0);
5723 CGM.getOpenMPRuntime().emitTaskCall(*
this, S.getBeginLoc(), S, OutlinedFn,
5724 SharedsTy, CapturedStruct, &IfCond,
Data);
5729 CodeGenFunction &CGF,
5733 if (
Data.Reductions) {
5735 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5737 Data.ReductionCopies,
Data.ReductionOps);
5740 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5754 Data.ReductionCopies[Cnt]->getType()),
5755 Data.ReductionCopies[Cnt]->getExprLoc()),
5757 Replacement.getAlignment());
5762 (void)
Scope.Privatize();
5767 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5768 auto IPriv =
C->privates().begin();
5769 auto IRed =
C->reduction_ops().begin();
5770 auto ITD =
C->taskgroup_descriptors().begin();
5771 for (
const Expr *Ref :
C->varlist()) {
5772 InRedVars.emplace_back(Ref);
5773 InRedPrivs.emplace_back(*IPriv);
5774 InRedOps.emplace_back(*IRed);
5775 TaskgroupDescriptors.emplace_back(*ITD);
5776 std::advance(IPriv, 1);
5777 std::advance(IRed, 1);
5778 std::advance(ITD, 1);
5782 if (!InRedVars.empty()) {
5784 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5792 llvm::Value *ReductionsPtr;
5793 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5797 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
5805 InRedPrivs[Cnt]->getExprLoc()),
5807 Replacement.getAlignment());
5821 const Expr *IfCond =
nullptr;
5822 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
5823 if (
C->getNameModifier() == OMPD_unknown ||
5824 C->getNameModifier() == OMPD_task) {
5825 IfCond =
C->getCondition();
5832 Data.Tied = !S.getSingleClause<OMPUntiedClause>();
5836 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
5837 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
5840 SharedsTy, CapturedStruct, IfCond,
5849 const OMPTaskyieldDirective &S) {
5850 CGM.getOpenMPRuntime().emitTaskyieldCall(*
this, S.getBeginLoc());
5854 const OMPMessageClause *MC = S.getSingleClause<OMPMessageClause>();
5855 Expr *ME = MC ? MC->getMessageString() :
nullptr;
5856 const OMPSeverityClause *SC = S.getSingleClause<OMPSeverityClause>();
5857 bool IsFatal =
false;
5858 if (!SC || SC->getSeverityKind() == OMPC_SEVERITY_fatal)
5860 CGM.getOpenMPRuntime().emitErrorCall(*
this, S.getBeginLoc(), ME, IsFatal);
5864 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_barrier);
5871 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
5872 CGM.getOpenMPRuntime().emitTaskwaitCall(*
this, S.getBeginLoc(),
Data);
5876 return T.clauses().empty();
5880 const OMPTaskgroupDirective &S) {
5881 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
5883 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
5884 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5888 auto BodyGenCB = [&,
this](InsertPointTy AllocaIP,
5889 InsertPointTy CodeGenIP) {
5891 EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5892 return llvm::Error::success();
5897 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5898 cantFail(OMPBuilder.createTaskgroup(
Builder, AllocaIP, BodyGenCB));
5904 if (
const Expr *E = S.getReductionRef()) {
5908 for (
const auto *
C : S.getClausesOfKind<OMPTaskReductionClause>()) {
5909 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5910 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5911 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5912 Data.ReductionOps.append(
C->reduction_ops().begin(),
5913 C->reduction_ops().end());
5914 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5915 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5917 llvm::Value *ReductionDesc =
5925 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5927 CGM.getOpenMPRuntime().emitTaskgroupRegion(*
this,
CodeGen, S.getBeginLoc());
5932 ? llvm::AtomicOrdering::NotAtomic
5933 : llvm::AtomicOrdering::AcquireRelease;
5934 CGM.getOpenMPRuntime().emitFlush(
5937 if (
const auto *FlushClause = S.getSingleClause<
OMPFlushClause>())
5939 FlushClause->varlist_end());
5942 S.getBeginLoc(), AO);
5952 for (
auto &Dep :
Data.Dependences) {
5953 Address DepAddr =
CGM.getOpenMPRuntime().emitDepobjDependClause(
5954 *
this, Dep, DC->getBeginLoc());
5960 CGM.getOpenMPRuntime().emitDestroyClause(*
this, DOLVal, DC->getBeginLoc());
5963 if (
const auto *UC = S.getSingleClause<OMPUpdateClause>()) {
5964 CGM.getOpenMPRuntime().emitUpdateClause(
5965 *
this, DOLVal, UC->getDependencyKind(), UC->getBeginLoc());
5983 for (
const auto *
C : ParentDir.getClausesOfKind<OMPReductionClause>()) {
5984 if (
C->getModifier() != OMPC_REDUCTION_inscan)
5986 Shareds.append(
C->varlist_begin(),
C->varlist_end());
5987 Privates.append(
C->privates().begin(),
C->privates().end());
5988 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5989 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5990 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
5991 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
5992 CopyArrayTemps.append(
C->copy_array_temps().begin(),
5993 C->copy_array_temps().end());
5994 CopyArrayElems.append(
C->copy_array_elems().begin(),
5995 C->copy_array_elems().end());
5997 if (ParentDir.getDirectiveKind() == OMPD_simd ||
6039 : BreakContinueStack.back().ContinueBlock.getBlock());
6050 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6052 const Expr *TempExpr = CopyArrayTemps[I];
6064 CGM.getOpenMPRuntime().emitReduction(
6065 *
this, ParentDir.getEndLoc(),
Privates, LHSs, RHSs, ReductionOps,
6068 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6076 const Expr *TempExpr = CopyArrayTemps[I];
6088 ? BreakContinueStack.back().ContinueBlock.getBlock()
6094 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6100 .getIterationVariable()
6101 ->IgnoreParenImpCasts();
6104 IdxVal = Builder.CreateIntCast(IdxVal,
SizeTy,
false);
6105 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6107 const Expr *OrigExpr = Shareds[I];
6108 const Expr *CopyArrayElem = CopyArrayElems[I];
6109 OpaqueValueMapping IdxMapping(
6122 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6125 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6131 .getIterationVariable()
6132 ->IgnoreParenImpCasts();
6136 llvm::BasicBlock *ExclusiveExitBB =
nullptr;
6140 llvm::Value *
Cmp =
Builder.CreateIsNull(IdxVal);
6141 Builder.CreateCondBr(
Cmp, ExclusiveExitBB, ContBB);
6144 IdxVal =
Builder.CreateNUWSub(IdxVal, llvm::ConstantInt::get(
SizeTy, 1));
6146 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6147 const Expr *PrivateExpr =
Privates[I];
6148 const Expr *OrigExpr = Shareds[I];
6149 const Expr *CopyArrayElem = CopyArrayElems[I];
6158 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
6182 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
6190 bool HasLastprivateClause =
false;
6193 OMPLoopScope PreInitScope(*
this, S);
6198 llvm::BasicBlock *ContBlock =
nullptr;
6205 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
6219 ? S.getCombinedLowerBoundVariable()
6220 : S.getLowerBoundVariable())));
6224 ? S.getCombinedUpperBoundVariable()
6225 : S.getUpperBoundVariable())));
6236 CGM.getOpenMPRuntime().emitBarrierCall(
6237 *
this, S.getBeginLoc(), OMPD_unknown,
false,
6249 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
6252 llvm::Value *Chunk =
nullptr;
6255 ScheduleKind =
C->getDistScheduleKind();
6256 if (
const Expr *Ch =
C->getChunkSize()) {
6259 S.getIterationVariable()->getType(),
6264 CGM.getOpenMPRuntime().getDefaultDistScheduleAndChunk(
6265 *
this, S, ScheduleKind, Chunk);
6278 bool StaticChunked =
6282 Chunk !=
nullptr) ||
6287 StaticChunked ? Chunk :
nullptr);
6294 ? S.getCombinedEnsureUpperBound()
6295 : S.getEnsureUpperBound());
6298 ? S.getCombinedInit()
6303 ? S.getCombinedCond()
6307 Cond = S.getCombinedDistCond();
6339 [&S, &LoopScope,
Cond, IncExpr,
LoopExit, &CodeGenLoop,
6342 S, LoopScope.requiresCleanups(),
Cond, IncExpr,
6343 [&S,
LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
6344 CodeGenLoop(CGF, S, LoopExit);
6346 [&S, StaticChunked](CodeGenFunction &CGF) {
6347 if (StaticChunked) {
6348 CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound());
6349 CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound());
6350 CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound());
6351 CGF.EmitIgnoredExpr(S.getCombinedInit());
6361 const OMPLoopArguments LoopArguments = {
6362 LB.getAddress(), UB.getAddress(), ST.getAddress(), IL.getAddress(),
6364 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments,
6369 return CGF.
Builder.CreateIsNotNull(
6379 *
this, S, [IL, &S](CodeGenFunction &CGF) {
6380 return CGF.
Builder.CreateIsNotNull(
6385 if (HasLastprivateClause) {
6408 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
6417static llvm::Function *
6424 Fn->setDoesNotRecurse();
6428template <
typename T>
6430 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP,
6431 llvm::OpenMPIRBuilder &OMPBuilder) {
6433 unsigned NumLoops =
C->getNumLoops();
6437 for (
unsigned I = 0; I < NumLoops; I++) {
6438 const Expr *CounterVal =
C->getLoopData(I);
6443 StoreValues.emplace_back(StoreValue);
6445 OMPDoacrossKind<T> ODK;
6446 bool IsDependSource = ODK.isSource(
C);
6448 OMPBuilder.createOrderedDepend(CGF.
Builder, AllocaIP, NumLoops,
6449 StoreValues,
".cnt.addr", IsDependSource));
6453 if (
CGM.getLangOpts().OpenMPIRBuilder) {
6454 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
6455 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6460 assert(!S.hasAssociatedStmt() &&
"No associated statement must be in "
6461 "ordered depend|doacross construct.");
6473 auto FiniCB = [
this](InsertPointTy IP) {
6475 return llvm::Error::success();
6478 auto BodyGenCB = [&S,
C,
this](InsertPointTy AllocaIP,
6479 InsertPointTy CodeGenIP) {
6484 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
6485 Builder,
false,
".ordered.after");
6489 assert(S.getBeginLoc().isValid() &&
6490 "Outlined function call location must be valid.");
6493 OutlinedFn, CapturedVars);
6498 return llvm::Error::success();
6501 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6502 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
6503 OMPBuilder.createOrderedThreadsSimd(
Builder, BodyGenCB, FiniCB, !
C));
6510 assert(!S.hasAssociatedStmt() &&
6511 "No associated statement must be in ordered depend construct.");
6513 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6517 assert(!S.hasAssociatedStmt() &&
6518 "No associated statement must be in ordered doacross construct.");
6520 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6524 auto &&
CodeGen = [&S,
C,
this](CodeGenFunction &CGF,
6529 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
6531 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
6532 OutlinedFn, CapturedVars);
6538 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6539 CGM.getOpenMPRuntime().emitOrderedRegion(*
this,
CodeGen, S.getBeginLoc(), !
C);
6546 "DestType must have scalar evaluation kind.");
6547 assert(!Val.
isAggregate() &&
"Must be a scalar or complex.");
6558 "DestType must have complex evaluation kind.");
6567 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
6569 assert(Val.
isComplex() &&
"Must be a scalar or complex.");
6574 Val.
getComplexVal().first, SrcElementType, DestElementType, Loc);
6576 Val.
getComplexVal().second, SrcElementType, DestElementType, Loc);
6582 LValue LVal,
RValue RVal) {
6583 if (LVal.isGlobalReg())
6590 llvm::AtomicOrdering AO, LValue LVal,
6592 if (LVal.isGlobalReg())
6595 LVal, Loc, llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO),
6604 *
this, RVal, RValTy, LVal.
getType(), Loc)),
6613 llvm_unreachable(
"Must be a scalar or complex.");
6621 assert(
V->isLValue() &&
"V of 'omp atomic read' is not lvalue");
6622 assert(
X->isLValue() &&
"X of 'omp atomic read' is not lvalue");
6631 case llvm::AtomicOrdering::Acquire:
6632 case llvm::AtomicOrdering::AcquireRelease:
6633 case llvm::AtomicOrdering::SequentiallyConsistent:
6635 llvm::AtomicOrdering::Acquire);
6637 case llvm::AtomicOrdering::Monotonic:
6638 case llvm::AtomicOrdering::Release:
6640 case llvm::AtomicOrdering::NotAtomic:
6641 case llvm::AtomicOrdering::Unordered:
6642 llvm_unreachable(
"Unexpected ordering.");
6649 llvm::AtomicOrdering AO,
const Expr *
X,
6652 assert(
X->isLValue() &&
"X of 'omp atomic write' is not lvalue");
6660 case llvm::AtomicOrdering::Release:
6661 case llvm::AtomicOrdering::AcquireRelease:
6662 case llvm::AtomicOrdering::SequentiallyConsistent:
6664 llvm::AtomicOrdering::Release);
6666 case llvm::AtomicOrdering::Acquire:
6667 case llvm::AtomicOrdering::Monotonic:
6669 case llvm::AtomicOrdering::NotAtomic:
6670 case llvm::AtomicOrdering::Unordered:
6671 llvm_unreachable(
"Unexpected ordering.");
6678 llvm::AtomicOrdering AO,
6684 if (BO == BO_Comma || !
Update.isScalar() || !
X.isSimple() ||
6686 (
Update.getScalarVal()->getType() !=
X.getAddress().getElementType())) ||
6687 !Context.getTargetInfo().hasBuiltinAtomic(
6688 Context.getTypeSize(
X.getType()), Context.toBits(
X.getAlignment())))
6689 return std::make_pair(
false,
RValue::get(
nullptr));
6692 if (T->isIntegerTy())
6695 if (T->isFloatingPointTy() && (BO == BO_Add || BO == BO_Sub))
6701 if (!CheckAtomicSupport(
Update.getScalarVal()->getType(), BO) ||
6702 !CheckAtomicSupport(
X.getAddress().getElementType(), BO))
6703 return std::make_pair(
false,
RValue::get(
nullptr));
6705 bool IsInteger =
X.getAddress().getElementType()->isIntegerTy();
6706 llvm::AtomicRMWInst::BinOp RMWOp;
6709 RMWOp = IsInteger ? llvm::AtomicRMWInst::Add : llvm::AtomicRMWInst::FAdd;
6713 return std::make_pair(
false,
RValue::get(
nullptr));
6714 RMWOp = IsInteger ? llvm::AtomicRMWInst::Sub : llvm::AtomicRMWInst::FSub;
6717 RMWOp = llvm::AtomicRMWInst::And;
6720 RMWOp = llvm::AtomicRMWInst::Or;
6723 RMWOp = llvm::AtomicRMWInst::Xor;
6727 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6729 : llvm::AtomicRMWInst::Max)
6731 : llvm::AtomicRMWInst::UMax);
6734 : llvm::AtomicRMWInst::FMax;
6738 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6740 : llvm::AtomicRMWInst::Min)
6742 : llvm::AtomicRMWInst::UMin);
6745 : llvm::AtomicRMWInst::FMin;
6748 RMWOp = llvm::AtomicRMWInst::Xchg;
6757 return std::make_pair(
false,
RValue::get(
nullptr));
6776 llvm_unreachable(
"Unsupported atomic update operation");
6778 llvm::Value *UpdateVal =
Update.getScalarVal();
6779 if (
auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
6781 UpdateVal = CGF.
Builder.CreateIntCast(
6782 IC,
X.getAddress().getElementType(),
6783 X.getType()->hasSignedIntegerRepresentation());
6785 UpdateVal = CGF.
Builder.CreateCast(llvm::Instruction::CastOps::UIToFP, IC,
6786 X.getAddress().getElementType());
6788 llvm::AtomicRMWInst *Res =
6805 if (
X.isGlobalReg()) {
6818 llvm::AtomicOrdering AO,
const Expr *
X,
6822 "Update expr in 'atomic update' must be a binary operator.");
6830 assert(
X->isLValue() &&
"X of 'omp atomic update' is not lvalue");
6837 auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](
RValue XRValue) {
6843 XLValue, ExprRValue, BOUE->getOpcode(),
IsXLHSInRHSPart, AO, Loc, Gen);
6850 case llvm::AtomicOrdering::Release:
6851 case llvm::AtomicOrdering::AcquireRelease:
6852 case llvm::AtomicOrdering::SequentiallyConsistent:
6854 llvm::AtomicOrdering::Release);
6856 case llvm::AtomicOrdering::Acquire:
6857 case llvm::AtomicOrdering::Monotonic:
6859 case llvm::AtomicOrdering::NotAtomic:
6860 case llvm::AtomicOrdering::Unordered:
6861 llvm_unreachable(
"Unexpected ordering.");
6879 llvm_unreachable(
"Must be a scalar or complex.");
6883 llvm::AtomicOrdering AO,
6888 assert(
X->isLValue() &&
"X of 'omp atomic capture' is not lvalue");
6889 assert(
V->isLValue() &&
"V of 'omp atomic capture' is not lvalue");
6898 "Update expr in 'atomic capture' must be a binary operator.");
6909 NewVValType = XRValExpr->
getType();
6911 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
6920 XLValue, ExprRValue, BOUE->getOpcode(),
IsXLHSInRHSPart, AO, Loc, Gen);
6926 NewVVal = Res.second;
6937 NewVValType =
X->getType().getNonReferenceType();
6939 X->getType().getNonReferenceType(), Loc);
6940 auto &&Gen = [&NewVVal, ExprRValue](
RValue XRValue) {
6946 XLValue, ExprRValue, BO_Assign,
false, AO,
6967 case llvm::AtomicOrdering::Release:
6969 llvm::AtomicOrdering::Release);
6971 case llvm::AtomicOrdering::Acquire:
6973 llvm::AtomicOrdering::Acquire);
6975 case llvm::AtomicOrdering::AcquireRelease:
6976 case llvm::AtomicOrdering::SequentiallyConsistent:
6978 CGF, {}, Loc, llvm::AtomicOrdering::AcquireRelease);
6980 case llvm::AtomicOrdering::Monotonic:
6982 case llvm::AtomicOrdering::NotAtomic:
6983 case llvm::AtomicOrdering::Unordered:
6984 llvm_unreachable(
"Unexpected ordering.");
6990 CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO,
6994 llvm::OpenMPIRBuilder &OMPBuilder =
6997 OMPAtomicCompareOp Op;
7001 Op = OMPAtomicCompareOp::EQ;
7004 Op = OMPAtomicCompareOp::MIN;
7007 Op = OMPAtomicCompareOp::MAX;
7010 llvm_unreachable(
"unsupported atomic compare binary operator");
7014 Address XAddr = XLVal.getAddress();
7016 auto EmitRValueWithCastIfNeeded = [&CGF, Loc](
const Expr *
X,
const Expr *E) {
7021 if (NewE->
getType() ==
X->getType())
7026 llvm::Value *EVal = EmitRValueWithCastIfNeeded(
X, E);
7027 llvm::Value *DVal = D ? EmitRValueWithCastIfNeeded(
X, D) :
nullptr;
7028 if (
auto *CI = dyn_cast<llvm::ConstantInt>(EVal))
7029 EVal = CGF.
Builder.CreateIntCast(
7030 CI, XLVal.getAddress().getElementType(),
7033 if (
auto *CI = dyn_cast<llvm::ConstantInt>(DVal))
7034 DVal = CGF.
Builder.CreateIntCast(
7035 CI, XLVal.getAddress().getElementType(),
7038 llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{
7040 X->getType()->hasSignedIntegerRepresentation(),
7041 X->getType().isVolatileQualified()};
7042 llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal;
7046 VOpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
7047 V->getType()->hasSignedIntegerRepresentation(),
7048 V->getType().isVolatileQualified()};
7053 ROpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
7054 R->getType()->hasSignedIntegerRepresentation(),
7055 R->getType().isVolatileQualified()};
7058 if (FailAO == llvm::AtomicOrdering::NotAtomic) {
7061 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
7062 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
7065 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
7066 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
7071 llvm::AtomicOrdering AO,
7092 case OMPC_compare: {
7098 llvm_unreachable(
"Clause is not allowed in 'omp atomic'.");
7103 llvm::AtomicOrdering AO =
CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
7105 llvm::AtomicOrdering FailAO = llvm::AtomicOrdering::NotAtomic;
7106 bool MemOrderingSpecified =
false;
7107 if (S.getSingleClause<OMPSeqCstClause>()) {
7108 AO = llvm::AtomicOrdering::SequentiallyConsistent;
7109 MemOrderingSpecified =
true;
7110 }
else if (S.getSingleClause<OMPAcqRelClause>()) {
7111 AO = llvm::AtomicOrdering::AcquireRelease;
7112 MemOrderingSpecified =
true;
7113 }
else if (S.getSingleClause<OMPAcquireClause>()) {
7114 AO = llvm::AtomicOrdering::Acquire;
7115 MemOrderingSpecified =
true;
7116 }
else if (S.getSingleClause<OMPReleaseClause>()) {
7117 AO = llvm::AtomicOrdering::Release;
7118 MemOrderingSpecified =
true;
7119 }
else if (S.getSingleClause<OMPRelaxedClause>()) {
7120 AO = llvm::AtomicOrdering::Monotonic;
7121 MemOrderingSpecified =
true;
7123 llvm::SmallSet<OpenMPClauseKind, 2> KindsEncountered;
7132 if (K == OMPC_seq_cst || K == OMPC_acq_rel || K == OMPC_acquire ||
7133 K == OMPC_release || K == OMPC_relaxed || K == OMPC_hint)
7136 KindsEncountered.insert(K);
7141 if (KindsEncountered.contains(OMPC_compare) &&
7142 KindsEncountered.contains(OMPC_capture))
7143 Kind = OMPC_compare;
7144 if (!MemOrderingSpecified) {
7145 llvm::AtomicOrdering DefaultOrder =
7146 CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
7147 if (DefaultOrder == llvm::AtomicOrdering::Monotonic ||
7148 DefaultOrder == llvm::AtomicOrdering::SequentiallyConsistent ||
7149 (DefaultOrder == llvm::AtomicOrdering::AcquireRelease &&
7150 Kind == OMPC_capture)) {
7152 }
else if (DefaultOrder == llvm::AtomicOrdering::AcquireRelease) {
7153 if (Kind == OMPC_unknown || Kind == OMPC_update || Kind == OMPC_write) {
7154 AO = llvm::AtomicOrdering::Release;
7155 }
else if (Kind == OMPC_read) {
7156 assert(Kind == OMPC_read &&
"Unexpected atomic kind.");
7157 AO = llvm::AtomicOrdering::Acquire;
7162 if (KindsEncountered.contains(OMPC_compare) &&
7163 KindsEncountered.contains(OMPC_fail)) {
7164 Kind = OMPC_compare;
7165 const auto *FailClause = S.getSingleClause<OMPFailClause>();
7168 if (FailParameter == llvm::omp::OMPC_relaxed)
7169 FailAO = llvm::AtomicOrdering::Monotonic;
7170 else if (FailParameter == llvm::omp::OMPC_acquire)
7171 FailAO = llvm::AtomicOrdering::Acquire;
7172 else if (FailParameter == llvm::omp::OMPC_seq_cst)
7173 FailAO = llvm::AtomicOrdering::SequentiallyConsistent;
7180 S.getV(), S.getR(), S.getExpr(), S.getUpdateExpr(),
7181 S.getD(), S.getCondExpr(), S.isXLHSInRHSPart(),
7182 S.isFailOnly(), S.getBeginLoc());
7193 OMPLexicalScope
Scope(CGF, S, OMPD_target);
7196 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
7202 llvm::Function *Fn =
nullptr;
7203 llvm::Constant *FnID =
nullptr;
7205 const Expr *IfCond =
nullptr;
7207 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7208 if (
C->getNameModifier() == OMPD_unknown ||
7209 C->getNameModifier() == OMPD_target) {
7210 IfCond =
C->getCondition();
7216 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device(
7219 Device.setPointerAndInt(
C->getDevice(),
C->getModifier());
7224 bool IsOffloadEntry =
true;
7228 IsOffloadEntry =
false;
7231 IsOffloadEntry =
false;
7233 if (
CGM.
getLangOpts().OpenMPOffloadMandatory && !IsOffloadEntry) {
7237 assert(CGF.
CurFuncDecl &&
"No parent declaration for target region!");
7238 StringRef ParentName;
7241 if (
const auto *D = dyn_cast<CXXConstructorDecl>(CGF.
CurFuncDecl))
7243 else if (
const auto *D = dyn_cast<CXXDestructorDecl>(CGF.
CurFuncDecl))
7252 OMPLexicalScope
Scope(CGF, S, OMPD_task);
7253 auto &&SizeEmitter =
7256 if (IsOffloadEntry) {
7257 OMPLoopScope(CGF, D);
7259 llvm::Value *NumIterations = CGF.
EmitScalarExpr(D.getNumIterations());
7260 NumIterations = CGF.
Builder.CreateIntCast(NumIterations, CGF.
Int64Ty,
7262 return NumIterations;
7280 CGF.
EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
7285 StringRef ParentName,
7291 llvm::Constant *
Addr;
7293 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7295 assert(Fn &&
Addr &&
"Target device function emission failed.");
7309 const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams);
7310 llvm::Function *OutlinedFn =
7318 const Expr *NumTeams = NT ? NT->getNumTeams().front() :
nullptr;
7319 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() :
nullptr;
7325 OMPTeamsScope
Scope(CGF, S);
7341 CGF.
EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt());
7346 [](CodeGenFunction &) {
return nullptr; });
7351 auto *CS = S.getCapturedStmt(OMPD_teams);
7378 llvm::Constant *
Addr;
7380 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7382 assert(Fn &&
Addr &&
"Target device function emission failed.");
7424 llvm::Constant *
Addr;
7426 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7428 assert(Fn &&
Addr &&
"Target device function emission failed.");
7470 llvm::Constant *
Addr;
7472 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7474 assert(Fn &&
Addr &&
"Target device function emission failed.");
7488 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7493 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7505 [](CodeGenFunction &) {
return nullptr; });
7510 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7515 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7527 [](CodeGenFunction &) {
return nullptr; });
7532 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7538 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7550 [](CodeGenFunction &) {
return nullptr; });
7555 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7561 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7568 CGF, OMPD_distribute, CodeGenDistribute,
false);
7574 [](CodeGenFunction &) {
return nullptr; });
7578 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7579 llvm::Value *
Device =
nullptr;
7580 llvm::Value *NumDependences =
nullptr;
7581 llvm::Value *DependenceList =
nullptr;
7589 if (!
Data.Dependences.empty()) {
7591 std::tie(NumDependences, DependenciesArray) =
7592 CGM.getOpenMPRuntime().emitDependClause(*
this,
Data.Dependences,
7596 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
7601 "OMPNowaitClause clause is used separately in OMPInteropDirective.");
7604 if (!ItOMPInitClause.empty()) {
7607 llvm::Value *InteropvarPtr =
7609 llvm::omp::OMPInteropType InteropType =
7610 llvm::omp::OMPInteropType::Unknown;
7611 if (
C->getIsTarget()) {
7612 InteropType = llvm::omp::OMPInteropType::Target;
7614 assert(
C->getIsTargetSync() &&
7615 "Expected interop-type target/targetsync");
7616 InteropType = llvm::omp::OMPInteropType::TargetSync;
7618 OMPBuilder.createOMPInteropInit(
Builder, InteropvarPtr, InteropType,
7619 Device, NumDependences, DependenceList,
7620 Data.HasNowaitClause);
7624 if (!ItOMPDestroyClause.empty()) {
7627 llvm::Value *InteropvarPtr =
7629 OMPBuilder.createOMPInteropDestroy(
Builder, InteropvarPtr,
Device,
7630 NumDependences, DependenceList,
7631 Data.HasNowaitClause);
7634 auto ItOMPUseClause = S.getClausesOfKind<
OMPUseClause>();
7635 if (!ItOMPUseClause.empty()) {
7638 llvm::Value *InteropvarPtr =
7640 OMPBuilder.createOMPInteropUse(
Builder, InteropvarPtr,
Device,
7641 NumDependences, DependenceList,
7642 Data.HasNowaitClause);
7664 CGF, OMPD_distribute, CodeGenDistribute,
false);
7683 llvm::Constant *
Addr;
7685 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7687 assert(Fn &&
Addr &&
"Target device function emission failed.");
7716 CGF, OMPD_distribute, CodeGenDistribute,
false);
7735 llvm::Constant *
Addr;
7737 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7739 assert(Fn &&
Addr &&
"Target device function emission failed.");
7752 CGM.getOpenMPRuntime().emitCancellationPointCall(*
this, S.getBeginLoc(),
7757 const Expr *IfCond =
nullptr;
7758 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7759 if (
C->getNameModifier() == OMPD_unknown ||
7760 C->getNameModifier() == OMPD_cancel) {
7761 IfCond =
C->getCondition();
7765 if (
CGM.getLangOpts().OpenMPIRBuilder) {
7766 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7772 llvm::Value *IfCondition =
nullptr;
7776 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
7778 return Builder.restoreIP(AfterIP);
7782 CGM.getOpenMPRuntime().emitCancelCall(*
this, S.getBeginLoc(), IfCond,
7788 if (Kind == OMPD_parallel || Kind == OMPD_task ||
7789 Kind == OMPD_target_parallel || Kind == OMPD_taskloop ||
7790 Kind == OMPD_master_taskloop || Kind == OMPD_parallel_master_taskloop)
7792 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
7793 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
7794 Kind == OMPD_distribute_parallel_for ||
7795 Kind == OMPD_target_parallel_for ||
7796 Kind == OMPD_teams_distribute_parallel_for ||
7797 Kind == OMPD_target_teams_distribute_parallel_for);
7798 return OMPCancelStack.getExitBlock();
7803 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7804 CaptureDeviceAddrMap) {
7805 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7806 for (
const Expr *OrigVarIt :
C.varlist()) {
7808 if (!Processed.insert(OrigVD).second)
7815 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7820 "Base should be the current struct!");
7821 MatchingVD = ME->getMemberDecl();
7826 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7827 if (InitAddrIt == CaptureDeviceAddrMap.end())
7835 Address(InitAddrIt->second, Ty,
7837 assert(IsRegistered &&
"firstprivate var already registered as private");
7845 while (
const auto *OASE = dyn_cast<ArraySectionExpr>(
Base))
7846 Base = OASE->getBase()->IgnoreParenImpCasts();
7847 while (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(
Base))
7848 Base = ASE->getBase()->IgnoreParenImpCasts();
7854 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7855 CaptureDeviceAddrMap) {
7856 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7857 for (
const Expr *Ref :
C.varlist()) {
7859 if (!Processed.insert(OrigVD).second)
7865 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7870 "Base should be the current struct!");
7871 MatchingVD = ME->getMemberDecl();
7876 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7877 if (InitAddrIt == CaptureDeviceAddrMap.end())
7883 Address(InitAddrIt->second, Ty,
7896 (void)PrivateScope.
addPrivate(OrigVD, PrivAddr);
7904 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
7905 CGM.getOpenMPRuntime().registerVTable(S);
7913 bool PrivatizeDevicePointers =
false;
7915 bool &PrivatizeDevicePointers;
7918 explicit DevicePointerPrivActionTy(
bool &PrivatizeDevicePointers)
7919 : PrivatizeDevicePointers(PrivatizeDevicePointers) {}
7920 void Enter(CodeGenFunction &CGF)
override {
7921 PrivatizeDevicePointers =
true;
7924 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
7927 auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7928 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
7932 auto &&PrivCodeGen = [&](CodeGenFunction &CGF,
PrePostActionTy &Action) {
7934 PrivatizeDevicePointers =
false;
7940 if (PrivatizeDevicePointers) {
7954 std::optional<OpenMPDirectiveKind> CaptureRegion;
7955 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
7958 for (
const Expr *E :
C->varlist()) {
7960 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
7964 for (
const Expr *E :
C->varlist()) {
7966 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
7970 CaptureRegion = OMPD_unknown;
7973 OMPLexicalScope
Scope(CGF, S, CaptureRegion);
7985 OMPLexicalScope
Scope(CGF, S);
7994 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
8000 const Expr *IfCond =
nullptr;
8002 IfCond =
C->getCondition();
8013 CGM.getOpenMPRuntime().emitTargetDataCalls(*
this, S, IfCond,
Device, RCG,
8021 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8025 const Expr *IfCond =
nullptr;
8027 IfCond =
C->getCondition();
8034 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8035 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8042 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8046 const Expr *IfCond =
nullptr;
8048 IfCond =
C->getCondition();
8055 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8056 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8063 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
8091 llvm::Constant *
Addr;
8093 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8095 assert(Fn &&
Addr &&
"Target device function emission failed.");
8115 CGF, OMPD_target_parallel_for, S.
hasCancel());
8131 llvm::Constant *
Addr;
8133 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8135 assert(Fn &&
Addr &&
"Target device function emission failed.");
8170 llvm::Constant *
Addr;
8172 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8174 assert(Fn &&
Addr &&
"Target device function emission failed.");
8196 const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop);
8199 OMPLexicalScope
Scope(*
this, S, OMPD_taskloop,
false);
8204 const Expr *IfCond =
nullptr;
8205 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
8206 if (
C->getNameModifier() == OMPD_unknown ||
8207 C->getNameModifier() == OMPD_taskloop) {
8208 IfCond =
C->getCondition();
8221 Data.Schedule.setInt(
false);
8224 (Clause->getModifier() == OMPC_GRAINSIZE_strict) ?
true :
false;
8227 Data.Schedule.setInt(
true);
8230 (Clause->getModifier() == OMPC_NUMTASKS_strict) ?
true :
false;
8244 llvm::BasicBlock *ContBlock =
nullptr;
8245 OMPLoopScope PreInitScope(CGF, S);
8246 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
8250 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock(
"taskloop.if.then");
8251 ContBlock = CGF.createBasicBlock(
"taskloop.if.end");
8252 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
8253 CGF.getProfileCount(&S));
8254 CGF.EmitBlock(ThenBlock);
8255 CGF.incrementProfileCounter(&S);
8258 (void)CGF.EmitOMPLinearClauseInit(S);
8262 enum { LowerBound = 5, UpperBound, Stride, LastIter };
8264 auto *LBP = std::next(I, LowerBound);
8265 auto *UBP = std::next(I, UpperBound);
8266 auto *STP = std::next(I, Stride);
8267 auto *LIP = std::next(I, LastIter);
8275 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
8276 CGF.EmitOMPLinearClause(S, LoopScope);
8277 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
8280 const Expr *IVExpr = S.getIterationVariable();
8282 CGF.EmitVarDecl(*IVDecl);
8283 CGF.EmitIgnoredExpr(S.getInit());
8288 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
8291 CGF.EmitIgnoredExpr(S.getCalcLastIteration());
8295 OMPLexicalScope
Scope(CGF, S, OMPD_taskloop,
false);
8305 [&S](CodeGenFunction &CGF) {
8306 emitOMPLoopBodyWithStopPoint(CGF, S,
8307 CodeGenFunction::JumpDest());
8309 [](CodeGenFunction &) {});
8314 CGF.EmitBranch(ContBlock);
8315 CGF.EmitBlock(ContBlock,
true);
8318 if (HasLastprivateClause) {
8319 CGF.EmitOMPLastprivateClauseFinal(
8321 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
8322 CGF.GetAddrOfLocalVar(*LIP),
false,
8323 (*LIP)->getType(), S.getBeginLoc())));
8326 CGF.EmitOMPLinearClauseFinal(S, [LIP, &S](CodeGenFunction &CGF) {
8327 return CGF.
Builder.CreateIsNotNull(
8329 (*LIP)->
getType(), S.getBeginLoc()));
8332 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
8333 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
8335 auto &&
CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
8337 OMPLoopScope PreInitScope(CGF, S);
8338 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S,
8339 OutlinedFn, SharedsTy,
8340 CapturedStruct, IfCond,
Data);
8342 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
8348 CGM.getOpenMPRuntime().emitTaskgroupRegion(
8350 [&S, &BodyGen, &TaskGen, &
Data](CodeGenFunction &CGF,
8370 OMPLexicalScope
Scope(*
this, S);
8382 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8383 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8394 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8395 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8406 OMPLexicalScope
Scope(*
this, S);
8407 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8418 OMPLexicalScope
Scope(*
this, S);
8419 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8425 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8430 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8431 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8443 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8448 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8449 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8461 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8466 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8467 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8479 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8484 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8485 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8499 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8503 const Expr *IfCond =
nullptr;
8505 IfCond =
C->getCondition();
8512 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8513 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8523 BindKind =
C->getBindKind();
8526 case OMPC_BIND_parallel:
8528 case OMPC_BIND_teams:
8530 case OMPC_BIND_thread:
8541 const auto *ForS = dyn_cast<ForStmt>(CS);
8552 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
8553 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_loop,
CodeGen);
8579 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
8584 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
8596 [](CodeGenFunction &) {
return nullptr; });
8601 std::string StatusMsg,
8605 StatusMsg +=
": DEVICE";
8607 StatusMsg +=
": HOST";
8614 llvm::dbgs() << StatusMsg <<
": " <<
FileName <<
": " << LineNo <<
"\n";
8637 CGF, OMPD_distribute, CodeGenDistribute,
false);
8666 CGF, OMPD_distribute, CodeGenDistribute,
false);
8699 llvm::Constant *
Addr;
8701 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8703 assert(Fn &&
Addr &&
8704 "Target device function emission failed for 'target teams loop'.");
8715 CGF, OMPD_target_parallel_loop,
false);
8731 llvm::Constant *
Addr;
8733 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8735 assert(Fn &&
Addr &&
"Target device function emission failed.");
8750 if (
const auto *SD = dyn_cast<OMPScanDirective>(&D)) {
8754 if (!D.hasAssociatedStmt() || !D.getAssociatedStmt())
8760 for (
const auto *
C : D.getClausesOfKind<OMPFirstprivateClause>()) {
8761 for (
const Expr *Ref :
C->varlist()) {
8765 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
8768 if (!CGF.LocalDeclMap.count(VD)) {
8780 if (
const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
8781 for (
const Expr *E : LD->counters()) {
8789 if (!CGF.LocalDeclMap.count(VD))
8793 for (
const auto *
C : D.getClausesOfKind<OMPOrderedClause>()) {
8794 if (!
C->getNumForLoops())
8796 for (
unsigned I = LD->getLoopsNumber(),
8797 E =
C->getLoopNumIterations().size();
8799 if (
const auto *VD = dyn_cast<OMPCapturedExprDecl>(
8802 if (!CGF.LocalDeclMap.count(VD))
8809 CGF.
EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
8812 if (D.getDirectiveKind() == OMPD_atomic ||
8813 D.getDirectiveKind() == OMPD_critical ||
8814 D.getDirectiveKind() == OMPD_section ||
8815 D.getDirectiveKind() == OMPD_master ||
8816 D.getDirectiveKind() == OMPD_masked ||
8817 D.getDirectiveKind() == OMPD_unroll ||
8818 D.getDirectiveKind() == OMPD_assume) {
8823 OMPSimdLexicalScope
Scope(*
this, D);
8824 CGM.getOpenMPRuntime().emitInlinedDirective(
8827 : 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 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 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 bool hasOrderedDirective(const Stmt *S)
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,...
void EmitOMPOrderedDirective(const OMPOrderedDirective &S)
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())
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)
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 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, 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.
static OMPClauseWithPreInit * get(OMPClause *C)
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 ...
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool needsTaskBasedThreadLimit(OpenMPDirectiveKind DKind)
Checks if the specified target directive, combined or not, needs task based thread_limit.
@ Ctor_Complete
Complete object ctor.
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.
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
llvm::IntegerType * IntPtrTy
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.
OpenMPScheduleClauseModifier M2
OpenMPScheduleClauseModifier M1
OpenMPScheduleClauseKind Schedule