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 AllocIP, InsertPointTy CodeGenIP,
2128 *
this, ParallelRegionBodyStmt, AllocIP, CodeGenIP,
"parallel");
2129 return llvm::Error::success();
2134 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
2136 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2137 cantFail(OMPBuilder.createParallel(
2138 Builder, AllocaIP, {}, BodyGenCB, PrivCB, FiniCB,
2139 IfCond, NumThreads, ProcBind, S.hasCancel()));
2153 CGF.
EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt());
2162 [](CodeGenFunction &) {
return nullptr; });
2174class OMPTransformDirectiveScopeRAII {
2175 OMPLoopScope *
Scope =
nullptr;
2179 OMPTransformDirectiveScopeRAII(
const OMPTransformDirectiveScopeRAII &) =
2181 OMPTransformDirectiveScopeRAII &
2182 operator=(
const OMPTransformDirectiveScopeRAII &) =
delete;
2186 if (
const auto *Dir = dyn_cast<OMPLoopBasedDirective>(S)) {
2187 Scope =
new OMPLoopScope(CGF, *Dir);
2190 }
else if (
const auto *Dir =
2191 dyn_cast<OMPCanonicalLoopSequenceTransformationDirective>(
2196 Scope =
new OMPLoopScope(CGF, *Dir);
2201 ~OMPTransformDirectiveScopeRAII() {
2212 int MaxLevel,
int Level = 0) {
2213 assert(Level < MaxLevel &&
"Too deep lookup during loop body codegen.");
2215 if (
const auto *CS = dyn_cast<CompoundStmt>(SimplifiedS)) {
2218 "LLVM IR generation of compound statement ('{}')");
2222 for (
const Stmt *CurStmt : CS->body())
2223 emitBody(CGF, CurStmt, NextLoop, MaxLevel, Level);
2226 if (SimplifiedS == NextLoop) {
2227 if (
auto *Dir = dyn_cast<OMPLoopTransformationDirective>(SimplifiedS))
2228 SimplifiedS = Dir->getTransformedStmt();
2229 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(SimplifiedS))
2230 SimplifiedS = CanonLoop->getLoopStmt();
2231 if (
const auto *For = dyn_cast<ForStmt>(SimplifiedS)) {
2235 "Expected canonical for loop or range-based for loop.");
2237 CGF.
EmitStmt(CXXFor->getLoopVarStmt());
2238 S = CXXFor->getBody();
2240 if (Level + 1 < MaxLevel) {
2241 NextLoop = OMPLoopDirective::tryToFindNextInnerLoop(
2243 emitBody(CGF, S, NextLoop, MaxLevel, Level + 1);
2254 for (
const Expr *UE : D.updates())
2261 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2262 for (
const Expr *UE :
C->updates())
2269 BreakContinueStack.push_back(BreakContinue(D,
LoopExit, Continue));
2270 for (
const Expr *E : D.finals_conditions()) {
2283 bool IsInscanRegion = InscanScope.
Privatize();
2284 if (IsInscanRegion) {
2294 if (EKind != OMPD_simd && !
getLangOpts().OpenMPSimd)
2303 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
2306 OMPLoopBasedDirective::tryToFindNextInnerLoop(
2308 D.getLoopsNumber());
2316 BreakContinueStack.pop_back();
2327 std::unique_ptr<CodeGenFunction::CGCapturedStmtInfo> CSI =
2328 std::make_unique<CodeGenFunction::CGCapturedStmtInfo>(*S);
2332 return {F, CapStruct.getPointer(
ParentCGF)};
2336static llvm::CallInst *
2341 EffectiveArgs.reserve(Args.size() + 1);
2342 llvm::append_range(EffectiveArgs, Args);
2343 EffectiveArgs.push_back(Cap.second);
2348llvm::CanonicalLoopInfo *
2350 assert(Depth == 1 &&
"Nested loops with OpenMPIRBuilder not yet implemented");
2376 const Stmt *SyntacticalLoop = S->getLoopStmt();
2387 const Stmt *BodyStmt;
2388 if (
const auto *For = dyn_cast<ForStmt>(SyntacticalLoop)) {
2389 if (
const Stmt *InitStmt = For->getInit())
2391 BodyStmt = For->getBody();
2392 }
else if (
const auto *RangeFor =
2393 dyn_cast<CXXForRangeStmt>(SyntacticalLoop)) {
2394 if (
const DeclStmt *RangeStmt = RangeFor->getRangeStmt())
2396 if (
const DeclStmt *BeginStmt = RangeFor->getBeginStmt())
2398 if (
const DeclStmt *EndStmt = RangeFor->getEndStmt())
2400 if (
const DeclStmt *LoopVarStmt = RangeFor->getLoopVarStmt())
2402 BodyStmt = RangeFor->getBody();
2404 llvm_unreachable(
"Expected for-stmt or range-based for-stmt");
2407 const CapturedStmt *DistanceFunc = S->getDistanceFunc();
2420 llvm::Value *DistVal =
Builder.CreateLoad(CountAddr,
".count");
2423 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2424 auto BodyGen = [&,
this](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP,
2425 llvm::Value *IndVar) {
2430 const DeclRefExpr *LoopVarRef = S->getLoopVarRef();
2438 return llvm::Error::success();
2441 llvm::CanonicalLoopInfo *
CL =
2442 cantFail(OMPBuilder.createCanonicalLoop(
Builder, BodyGen, DistVal));
2454 const Expr *IncExpr,
2455 const llvm::function_ref<
void(CodeGenFunction &)> BodyGen,
2456 const llvm::function_ref<
void(CodeGenFunction &)> PostIncGen) {
2466 const CapturedStmt *ICS = OMPED.getInnermostCapturedStmt();
2480 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
2481 if (RequiresCleanup)
2488 if (ExitBlock !=
LoopExit.getBlock()) {
2498 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
2506 BreakContinueStack.pop_back();
2517 bool HasLinears =
false;
2518 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2522 if (
const auto *Ref =
2541 if (
const auto *CS = cast_or_null<BinaryOperator>(
C->getCalcStep()))
2553 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2556 llvm::BasicBlock *DoneBB =
nullptr;
2558 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2559 auto IC =
C->varlist_begin();
2560 for (
const Expr *F :
C->finals()) {
2562 if (llvm::Value *
Cond = CondGen(*
this)) {
2574 (*IC)->getType(),
VK_LValue, (*IC)->getExprLoc());
2582 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
2594 llvm::APInt ClauseAlignment(64, 0);
2595 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
2598 ClauseAlignment = AlignmentCI->getValue();
2600 for (
const Expr *E : Clause->varlist()) {
2601 llvm::APInt Alignment(ClauseAlignment);
2602 if (Alignment == 0) {
2609 E->getType()->getPointeeType()))
2612 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2613 "alignment is not power of 2");
2614 if (Alignment != 0) {
2628 auto I = S.private_counters().begin();
2629 for (
const Expr *E : S.counters()) {
2635 LocalDeclMap.erase(PrivateVD);
2641 E->getType(),
VK_LValue, E->getExprLoc());
2649 for (
const auto *
C : S.getClausesOfKind<OMPOrderedClause>()) {
2650 if (!
C->getNumForLoops())
2652 for (
unsigned I = S.getLoopsNumber(), E =
C->getLoopNumIterations().size();
2658 if (DRE->refersToEnclosingVariableOrCapture()) {
2667 const Expr *
Cond, llvm::BasicBlock *TrueBlock,
2668 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
2676 for (
const Expr *I : S.inits()) {
2683 for (
const Expr *E : S.dependent_counters()) {
2686 assert(!E->getType().getNonReferenceType()->isRecordType() &&
2687 "dependent counter must not be an iterator.");
2691 (void)PreCondVars.
setVarAddr(CGF, VD, CounterAddr);
2693 (void)PreCondVars.
apply(CGF);
2694 for (
const Expr *E : S.dependent_inits()) {
2708 llvm::DenseSet<const VarDecl *> SIMDLCVs;
2712 for (
const Expr *
C : LoopDirective->counters()) {
2717 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2718 auto CurPrivate =
C->privates().begin();
2719 for (
const Expr *E :
C->varlist()) {
2721 const auto *PrivateVD =
2728 assert(IsRegistered &&
"linear var already registered as private");
2816 if (
const auto *CS = dyn_cast<CapturedStmt>(S))
2834 if (HasOrderedDirective)
2842 const Stmt *AssociatedStmt = D.getAssociatedStmt();
2846 if (
C->getKind() == OMPC_ORDER_concurrent)
2849 if ((EKind == OMPD_simd ||
2851 llvm::any_of(D.getClausesOfKind<OMPReductionClause>(),
2852 [](
const OMPReductionClause *
C) {
2853 return C->getModifier() == OMPC_REDUCTION_inscan;
2861 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2864 llvm::BasicBlock *DoneBB =
nullptr;
2865 auto IC = D.counters().begin();
2866 auto IPC = D.private_counters().begin();
2867 for (
const Expr *F : D.finals()) {
2870 const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
2872 OrigVD->hasGlobalStorage() || CED) {
2874 if (llvm::Value *
Cond = CondGen(*
this)) {
2922 auto &&ThenGen = [&S, &SimdInitGen, &BodyCodeGen](
CodeGenFunction &CGF,
2936 const Expr *IfCond =
nullptr;
2939 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
2941 (
C->getNameModifier() == OMPD_unknown ||
2942 C->getNameModifier() == OMPD_simd)) {
2943 IfCond =
C->getCondition();
2959 OMPLoopScope PreInitScope(CGF, S);
2981 llvm::BasicBlock *ContBlock =
nullptr;
2988 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
2995 const Expr *IVExpr = S.getIterationVariable();
3003 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
3018 CGF, S, CGF.
EmitLValue(S.getIterationVariable()));
3033 emitOMPLoopBodyWithStopPoint(CGF, S,
3034 CodeGenFunction::JumpDest());
3040 if (HasLastprivateClause)
3069 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(S.getRawStmt())) {
3070 if (
const Stmt *SyntacticalLoop = CanonLoop->getLoopStmt()) {
3071 for (
const Stmt *SubStmt : SyntacticalLoop->
children()) {
3074 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(SubStmt)) {
3089static llvm::MapVector<llvm::Value *, llvm::Value *>
3091 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars;
3093 llvm::APInt ClauseAlignment(64, 0);
3094 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
3097 ClauseAlignment = AlignmentCI->getValue();
3099 for (
const Expr *E : Clause->varlist()) {
3100 llvm::APInt Alignment(ClauseAlignment);
3101 if (Alignment == 0) {
3108 E->getType()->getPointeeType()))
3111 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
3112 "alignment is not power of 2");
3114 AlignedVars[PtrValue] = CGF.
Builder.getInt64(Alignment.getSExtValue());
3124 bool UseOMPIRBuilder =
3126 if (UseOMPIRBuilder) {
3130 if (UseOMPIRBuilder) {
3131 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars =
3134 const Stmt *Inner = S.getRawStmt();
3135 llvm::CanonicalLoopInfo *CLI =
3136 CGF.EmitOMPCollapsedCanonicalLoopNest(Inner, 1);
3138 llvm::OpenMPIRBuilder &OMPBuilder =
3141 llvm::ConstantInt *Simdlen =
nullptr;
3148 llvm::ConstantInt *Safelen =
nullptr;
3155 llvm::omp::OrderKind Order = llvm::omp::OrderKind::OMP_ORDER_unknown;
3157 if (
C->getKind() == OpenMPOrderClauseKind::OMPC_ORDER_concurrent) {
3158 Order = llvm::omp::OrderKind::OMP_ORDER_concurrent;
3163 OMPBuilder.applySimd(CLI, AlignedVars,
3164 nullptr, Order, Simdlen, Safelen);
3171 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
3186 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
3199 OMPTransformDirectiveScopeRAII TileScope(*
this, &S);
3205 OMPTransformDirectiveScopeRAII StripeScope(*
this, &S);
3211 OMPTransformDirectiveScopeRAII ReverseScope(*
this, &S);
3217 OMPTransformDirectiveScopeRAII SplitScope(*
this, &S);
3224 OMPTransformDirectiveScopeRAII InterchangeScope(*
this, &S);
3230 OMPTransformDirectiveScopeRAII FuseScope(*
this, &S);
3235 bool UseOMPIRBuilder =
CGM.getLangOpts().OpenMPIRBuilder;
3237 if (UseOMPIRBuilder) {
3239 const Stmt *Inner = S.getRawStmt();
3247 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
3250 llvm::CanonicalLoopInfo *UnrolledCLI =
nullptr;
3254 OMPBuilder.unrollLoopFull(DL, CLI);
3256 uint64_t Factor = 0;
3257 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3258 Factor = FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
3259 assert(Factor >= 1 &&
"Only positive factors are valid");
3261 OMPBuilder.unrollLoopPartial(DL, CLI, Factor,
3262 NeedsUnrolledCLI ? &UnrolledCLI :
nullptr);
3264 OMPBuilder.unrollLoopHeuristic(DL, CLI);
3267 assert((!NeedsUnrolledCLI || UnrolledCLI) &&
3268 "NeedsUnrolledCLI implies UnrolledCLI to be set");
3285 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3287 FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
3288 assert(Factor >= 1 &&
"Only positive factors are valid");
3296void CodeGenFunction::EmitOMPOuterLoop(
3299 const CodeGenFunction::OMPLoopArguments &LoopArgs,
3304 const Expr *IVExpr = S.getIterationVariable();
3318 llvm::Value *BoolCondVal =
nullptr;
3319 if (!DynamicOrOrdered) {
3330 RT.
emitForNext(*
this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL,
3331 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST);
3336 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
3341 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
3342 if (ExitBlock !=
LoopExit.getBlock()) {
3350 if (DynamicOrOrdered)
3355 BreakContinueStack.push_back(BreakContinue(S, LoopExit, Continue));
3360 [&S, IsMonotonic, EKind](CodeGenFunction &CGF, PrePostActionTy &) {
3365 if (
const auto *
C = S.getSingleClause<OMPOrderClause>())
3366 if (
C->getKind() == OMPC_ORDER_concurrent)
3372 [&S, &LoopArgs, LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered,
3373 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
3374 SourceLocation Loc = S.getBeginLoc();
3380 CGF.EmitOMPInnerLoop(
3382 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
3383 CodeGenLoop(CGF, S, LoopExit);
3385 [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) {
3386 CodeGenOrdered(CGF, Loc, IVSize, IVSigned);
3391 BreakContinueStack.pop_back();
3392 if (!DynamicOrOrdered) {
3405 auto &&CodeGen = [DynamicOrOrdered, &S, &LoopArgs](CodeGenFunction &CGF) {
3406 if (!DynamicOrOrdered)
3407 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
3410 OMPCancelStack.emitExit(*
this, EKind, CodeGen);
3413void CodeGenFunction::EmitOMPForOuterLoop(
3414 const OpenMPScheduleTy &ScheduleKind,
bool IsMonotonic,
3416 const OMPLoopArguments &LoopArgs,
3418 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3424 LoopArgs.Chunk !=
nullptr)) &&
3425 "static non-chunked schedule does not need outer loop");
3479 const Expr *IVExpr = S.getIterationVariable();
3483 if (DynamicOrOrdered) {
3484 const std::pair<llvm::Value *, llvm::Value *> DispatchBounds =
3485 CGDispatchBounds(*
this, S, LoopArgs.LB, LoopArgs.UB);
3486 llvm::Value *LBVal = DispatchBounds.first;
3487 llvm::Value *UBVal = DispatchBounds.second;
3488 CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal,
3491 IVSigned, Ordered, DipatchRTInputValues);
3493 CGOpenMPRuntime::StaticRTInput StaticInit(
3494 IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
3495 LoopArgs.ST, LoopArgs.Chunk);
3501 auto &&CodeGenOrdered = [Ordered](CodeGenFunction &CGF, SourceLocation Loc,
3502 const unsigned IVSize,
3503 const bool IVSigned) {
3510 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST,
3511 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB);
3512 OuterLoopArgs.IncExpr = S.getInc();
3513 OuterLoopArgs.Init = S.getInit();
3514 OuterLoopArgs.Cond = S.getCond();
3515 OuterLoopArgs.NextLB = S.getNextLowerBound();
3516 OuterLoopArgs.NextUB = S.getNextUpperBound();
3517 OuterLoopArgs.DKind = LoopArgs.DKind;
3518 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
3520 if (DynamicOrOrdered) {
3526 const unsigned IVSize,
const bool IVSigned) {}
3528void CodeGenFunction::EmitOMPDistributeOuterLoop(
3533 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3540 const Expr *IVExpr = S.getIterationVariable();
3545 CGOpenMPRuntime::StaticRTInput StaticInit(
3546 IVSize, IVSigned,
false, LoopArgs.IL, LoopArgs.LB,
3547 LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
3554 IncExpr = S.getDistInc();
3556 IncExpr = S.getInc();
3561 OMPLoopArguments OuterLoopArgs;
3562 OuterLoopArgs.LB = LoopArgs.LB;
3563 OuterLoopArgs.UB = LoopArgs.UB;
3564 OuterLoopArgs.ST = LoopArgs.ST;
3565 OuterLoopArgs.IL = LoopArgs.IL;
3566 OuterLoopArgs.Chunk = LoopArgs.Chunk;
3568 ? S.getCombinedEnsureUpperBound()
3569 : S.getEnsureUpperBound();
3570 OuterLoopArgs.IncExpr = IncExpr;
3572 ? S.getCombinedInit()
3575 ? S.getCombinedCond()
3578 ? S.getCombinedNextLowerBound()
3579 : S.getNextLowerBound();
3581 ? S.getCombinedNextUpperBound()
3582 : S.getNextUpperBound();
3583 OuterLoopArgs.DKind = OMPD_distribute;
3585 EmitOMPOuterLoop(
false,
false, S,
3586 LoopScope, OuterLoopArgs, CodeGenLoopContent,
3590static std::pair<LValue, LValue>
3605 LValue PrevLB = CGF.
EmitLValue(LS.getPrevLowerBoundVariable());
3606 LValue PrevUB = CGF.
EmitLValue(LS.getPrevUpperBoundVariable());
3608 PrevLB, LS.getPrevLowerBoundVariable()->getExprLoc());
3610 PrevLBVal, LS.getPrevLowerBoundVariable()->getType(),
3611 LS.getIterationVariable()->getType(),
3612 LS.getPrevLowerBoundVariable()->getExprLoc());
3614 PrevUB, LS.getPrevUpperBoundVariable()->getExprLoc());
3616 PrevUBVal, LS.getPrevUpperBoundVariable()->getType(),
3617 LS.getIterationVariable()->getType(),
3618 LS.getPrevUpperBoundVariable()->getExprLoc());
3633static std::pair<llvm::Value *, llvm::Value *>
3638 const Expr *IVExpr = LS.getIterationVariable();
3644 llvm::Value *LBVal =
3646 llvm::Value *UBVal =
3648 return {LBVal, UBVal};
3657 llvm::Value *LBCast = CGF.
Builder.CreateIntCast(
3659 CapturedVars.push_back(LBCast);
3663 llvm::Value *UBCast = CGF.
Builder.CreateIntCast(
3665 CapturedVars.push_back(UBCast);
3676 bool HasCancel =
false;
3678 if (
const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
3679 HasCancel = D->hasCancel();
3680 else if (
const auto *D = dyn_cast<OMPDistributeParallelForDirective>(&S))
3681 HasCancel = D->hasCancel();
3682 else if (
const auto *D =
3683 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S))
3684 HasCancel = D->hasCancel();
3694 CGInlinedWorksharingLoop,
3704 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3705 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3714 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3715 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3723 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
3724 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
3734 llvm::Constant *
Addr;
3736 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
3738 assert(Fn &&
Addr &&
"Target device function emission failed.");
3750struct ScheduleKindModifiersTy {
3757 : Kind(Kind), M1(M1), M2(M2) {}
3773 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
3781 bool HasLastprivateClause;
3784 OMPLoopScope PreInitScope(*
this, S);
3789 llvm::BasicBlock *ContBlock =
nullptr;
3796 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
3803 bool Ordered =
false;
3804 if (
const auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) {
3805 if (OrderedClause->getNumForLoops())
3815 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*
this, S);
3816 LValue LB = Bounds.first;
3817 LValue UB = Bounds.second;
3831 CGM.getOpenMPRuntime().emitBarrierCall(
3832 *
this, S.getBeginLoc(), OMPD_unknown,
false,
3837 *
this, S,
EmitLValue(S.getIterationVariable()));
3844 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
3847 const Expr *ChunkExpr =
nullptr;
3849 if (
const auto *
C = S.getSingleClause<OMPScheduleClause>()) {
3850 ScheduleKind.
Schedule =
C->getScheduleKind();
3851 ScheduleKind.
M1 =
C->getFirstScheduleModifier();
3852 ScheduleKind.
M2 =
C->getSecondScheduleModifier();
3853 ChunkExpr =
C->getChunkSize();
3856 CGM.getOpenMPRuntime().getDefaultScheduleAndChunk(
3857 *
this, S, ScheduleKind.
Schedule, ChunkExpr);
3859 bool HasChunkSizeOne =
false;
3860 llvm::Value *Chunk =
nullptr;
3864 S.getIterationVariable()->getType(),
3868 llvm::APSInt EvaluatedChunk =
Result.Val.getInt();
3869 HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
3878 bool StaticChunkedOne =
3880 Chunk !=
nullptr) &&
3884 (ScheduleKind.
Schedule == OMPC_SCHEDULE_static &&
3885 !(ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
3886 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)) ||
3887 ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
3888 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
3890 Chunk !=
nullptr) ||
3891 StaticChunkedOne) &&
3901 if (
C->getKind() == OMPC_ORDER_concurrent)
3905 [IVSize, IVSigned, Ordered, IL, LB, UB, ST, StaticChunkedOne, Chunk,
3914 IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(),
3915 UB.getAddress(), ST.getAddress(),
3916 StaticChunkedOne ? Chunk :
nullptr);
3918 CGF, S.getBeginLoc(), EKind, ScheduleKind, StaticInit);
3920 if (!StaticChunkedOne)
3939 StaticChunkedOne ? S.getCombinedParForInDistCond()
3941 StaticChunkedOne ? S.getDistInc() : S.getInc(),
3942 [&S,
LoopExit](CodeGenFunction &CGF) {
3943 emitOMPLoopBodyWithStopPoint(CGF, S, LoopExit);
3945 [](CodeGenFunction &) {});
3949 auto &&
CodeGen = [&S](CodeGenFunction &CGF) {
3953 OMPCancelStack.emitExit(*
this, EKind,
CodeGen);
3960 LoopArguments.DKind = OMPD_for;
3961 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
3962 LoopArguments, CGDispatchBounds);
3966 return CGF.
Builder.CreateIsNotNull(
3972 ? OMPD_parallel_for_simd
3976 *
this, S, [IL, &S](CodeGenFunction &CGF) {
3977 return CGF.
Builder.CreateIsNotNull(
3981 if (HasLastprivateClause)
3987 return CGF.
Builder.CreateIsNotNull(
3998 return HasLastprivateClause;
4004static std::pair<LValue, LValue>
4018static std::pair<llvm::Value *, llvm::Value *>
4022 const Expr *IVExpr = LS.getIterationVariable();
4024 llvm::Value *LBVal = CGF.
Builder.getIntN(IVSize, 0);
4026 return {LBVal, UBVal};
4038 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
4039 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4040 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4045 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4046 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4047 "Only inscan reductions are expected.");
4048 Shareds.append(
C->varlist_begin(),
C->varlist_end());
4049 Privates.append(
C->privates().begin(),
C->privates().end());
4050 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
4051 CopyArrayTemps.append(
C->copy_array_temps().begin(),
4052 C->copy_array_temps().end());
4060 auto *ITA = CopyArrayTemps.begin();
4065 if (PrivateVD->getType()->isVariablyModifiedType()) {
4090 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
4091 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4092 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4099 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4100 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4101 "Only inscan reductions are expected.");
4102 Shareds.append(
C->varlist_begin(),
C->varlist_end());
4103 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
4104 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
4105 Privates.append(
C->privates().begin(),
C->privates().end());
4106 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
4107 CopyArrayElems.append(
C->copy_array_elems().begin(),
4108 C->copy_array_elems().end());
4112 llvm::Value *OMPLast = CGF.
Builder.CreateNSWSub(
4113 OMPScanNumIterations,
4114 llvm::ConstantInt::get(CGF.
SizeTy, 1,
false));
4115 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
4117 const Expr *OrigExpr = Shareds[I];
4118 const Expr *CopyArrayElem = CopyArrayElems[I];
4125 LValue SrcLVal = CGF.
EmitLValue(CopyArrayElem);
4127 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
4157 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4158 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4164 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4165 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4166 "Only inscan reductions are expected.");
4167 Privates.append(
C->privates().begin(),
C->privates().end());
4168 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
4169 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
4170 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
4171 CopyArrayElems.append(
C->copy_array_elems().begin(),
4172 C->copy_array_elems().end());
4187 auto &&
CodeGen = [&S, OMPScanNumIterations, &LHSs, &RHSs, &CopyArrayElems,
4194 llvm::BasicBlock *InputBB = CGF.Builder.GetInsertBlock();
4195 llvm::BasicBlock *LoopBB = CGF.createBasicBlock(
"omp.outer.log.scan.body");
4196 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
"omp.outer.log.scan.exit");
4198 CGF.CGM.getIntrinsic(llvm::Intrinsic::log2, CGF.DoubleTy);
4200 CGF.Builder.CreateUIToFP(OMPScanNumIterations, CGF.DoubleTy);
4201 llvm::Value *LogVal = CGF.EmitNounwindRuntimeCall(F, Arg);
4202 F = CGF.CGM.getIntrinsic(llvm::Intrinsic::ceil, CGF.DoubleTy);
4203 LogVal = CGF.EmitNounwindRuntimeCall(F, LogVal);
4204 LogVal = CGF.Builder.CreateFPToUI(LogVal, CGF.IntTy);
4205 llvm::Value *NMin1 = CGF.Builder.CreateNUWSub(
4206 OMPScanNumIterations, llvm::ConstantInt::get(CGF.SizeTy, 1));
4208 CGF.EmitBlock(LoopBB);
4209 auto *Counter = CGF.Builder.CreatePHI(CGF.IntTy, 2);
4211 auto *Pow2K = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
4212 Counter->addIncoming(llvm::ConstantInt::get(CGF.IntTy, 0), InputBB);
4213 Pow2K->addIncoming(llvm::ConstantInt::get(CGF.SizeTy, 1), InputBB);
4216 llvm::BasicBlock *InnerLoopBB =
4217 CGF.createBasicBlock(
"omp.inner.log.scan.body");
4218 llvm::BasicBlock *InnerExitBB =
4219 CGF.createBasicBlock(
"omp.inner.log.scan.exit");
4220 llvm::Value *CmpI = CGF.Builder.CreateICmpUGE(NMin1, Pow2K);
4221 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4222 CGF.EmitBlock(InnerLoopBB);
4223 auto *IVal = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
4224 IVal->addIncoming(NMin1, LoopBB);
4227 auto *ILHS = LHSs.begin();
4228 auto *IRHS = RHSs.begin();
4229 for (
const Expr *CopyArrayElem : CopyArrayElems) {
4239 LHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4244 llvm::Value *OffsetIVal = CGF.Builder.CreateNUWSub(IVal, Pow2K);
4250 RHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4257 CGF.CGM.getOpenMPRuntime().emitReduction(
4258 CGF, S.getEndLoc(),
Privates, LHSs, RHSs, ReductionOps,
4262 llvm::Value *NextIVal =
4263 CGF.Builder.CreateNUWSub(IVal, llvm::ConstantInt::get(CGF.SizeTy, 1));
4264 IVal->addIncoming(NextIVal, CGF.Builder.GetInsertBlock());
4265 CmpI = CGF.Builder.CreateICmpUGE(NextIVal, Pow2K);
4266 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4267 CGF.EmitBlock(InnerExitBB);
4269 CGF.Builder.CreateNUWAdd(Counter, llvm::ConstantInt::get(CGF.IntTy, 1));
4270 Counter->addIncoming(
Next, CGF.Builder.GetInsertBlock());
4272 llvm::Value *NextPow2K =
4273 CGF.Builder.CreateShl(Pow2K, 1,
"",
true);
4274 Pow2K->addIncoming(NextPow2K, CGF.Builder.GetInsertBlock());
4275 llvm::Value *
Cmp = CGF.Builder.CreateICmpNE(
Next, LogVal);
4276 CGF.Builder.CreateCondBr(
Cmp, LoopBB, ExitBB);
4278 CGF.EmitBlock(ExitBB);
4284 CGF, S.getBeginLoc(), OMPD_unknown,
false,
4287 RegionCodeGenTy RCG(CodeGen);
4298 bool HasLastprivates;
4300 if (llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4301 [](
const OMPReductionClause *
C) {
4302 return C->getModifier() == OMPC_REDUCTION_inscan;
4306 OMPLoopScope LoopScope(CGF, S);
4309 const auto &&FirstGen = [&S, HasCancel, EKind](
CodeGenFunction &CGF) {
4318 const auto &&SecondGen = [&S, HasCancel, EKind,
4336 return HasLastprivates;
4349 if (
auto *SC = dyn_cast<OMPScheduleClause>(
C)) {
4354 switch (SC->getScheduleKind()) {
4355 case OMPC_SCHEDULE_auto:
4356 case OMPC_SCHEDULE_dynamic:
4357 case OMPC_SCHEDULE_runtime:
4358 case OMPC_SCHEDULE_guided:
4359 case OMPC_SCHEDULE_static:
4372static llvm::omp::ScheduleKind
4374 switch (ScheduleClauseKind) {
4376 return llvm::omp::OMP_SCHEDULE_Default;
4377 case OMPC_SCHEDULE_auto:
4378 return llvm::omp::OMP_SCHEDULE_Auto;
4379 case OMPC_SCHEDULE_dynamic:
4380 return llvm::omp::OMP_SCHEDULE_Dynamic;
4381 case OMPC_SCHEDULE_guided:
4382 return llvm::omp::OMP_SCHEDULE_Guided;
4383 case OMPC_SCHEDULE_runtime:
4384 return llvm::omp::OMP_SCHEDULE_Runtime;
4385 case OMPC_SCHEDULE_static:
4386 return llvm::omp::OMP_SCHEDULE_Static;
4388 llvm_unreachable(
"Unhandled schedule kind");
4395 bool HasLastprivates =
false;
4398 auto &&
CodeGen = [&S, &
CGM, HasCancel, &HasLastprivates,
4401 if (UseOMPIRBuilder) {
4402 bool NeedsBarrier = !S.getSingleClause<OMPNowaitClause>();
4404 llvm::omp::ScheduleKind SchedKind = llvm::omp::OMP_SCHEDULE_Default;
4405 llvm::Value *ChunkSize =
nullptr;
4406 if (
auto *SchedClause = S.getSingleClause<OMPScheduleClause>()) {
4409 if (
const Expr *ChunkSizeExpr = SchedClause->getChunkSize())
4414 const Stmt *Inner = S.getRawStmt();
4415 llvm::CanonicalLoopInfo *CLI =
4418 llvm::OpenMPIRBuilder &OMPBuilder =
4420 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4422 cantFail(OMPBuilder.applyWorkshareLoop(
4423 CGF.
Builder.getCurrentDebugLocation(), CLI, AllocaIP, NeedsBarrier,
4424 SchedKind, ChunkSize,
false,
4435 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
4440 if (!UseOMPIRBuilder) {
4442 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4454 bool HasLastprivates =
false;
4455 auto &&
CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
4462 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4463 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
4467 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4468 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_for);
4475 llvm::Value *
Init =
nullptr) {
4482void CodeGenFunction::EmitSections(
const OMPExecutableDirective &S) {
4483 const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4484 const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt);
4485 bool HasLastprivates =
false;
4487 auto &&CodeGen = [&S, CapturedStmt, CS, EKind,
4488 &HasLastprivates](CodeGenFunction &CGF, PrePostActionTy &) {
4489 const ASTContext &
C = CGF.getContext();
4490 QualType KmpInt32Ty =
4491 C.getIntTypeForBitwidth(32, 1);
4494 CGF.Builder.getInt32(0));
4495 llvm::ConstantInt *GlobalUBVal = CS !=
nullptr
4496 ? CGF.Builder.getInt32(CS->size() - 1)
4497 : CGF.Builder.getInt32(0);
4501 CGF.Builder.getInt32(1));
4503 CGF.Builder.getInt32(0));
4506 OpaqueValueExpr IVRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4507 CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
4508 OpaqueValueExpr UBRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4509 CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
4513 S.getBeginLoc(), FPOptionsOverride());
4517 S.getBeginLoc(),
true, FPOptionsOverride());
4518 auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
4530 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".omp.sections.exit");
4531 llvm::SwitchInst *SwitchStmt =
4532 CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.
getBeginLoc()),
4533 ExitBB, CS ==
nullptr ? 1 : CS->size());
4535 unsigned CaseNumber = 0;
4536 for (
const Stmt *SubStmt : CS->
children()) {
4537 auto CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4538 CGF.EmitBlock(CaseBB);
4539 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
4540 CGF.EmitStmt(SubStmt);
4541 CGF.EmitBranch(ExitBB);
4545 llvm::BasicBlock *CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4546 CGF.EmitBlock(CaseBB);
4547 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
4548 CGF.EmitStmt(CapturedStmt);
4549 CGF.EmitBranch(ExitBB);
4551 CGF.EmitBlock(ExitBB,
true);
4554 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
4555 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
4559 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
4563 CGF.EmitOMPPrivateClause(S, LoopScope);
4564 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(CGF, S, IV);
4565 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
4566 CGF.EmitOMPReductionClauseInit(S, LoopScope);
4567 (void)LoopScope.Privatize();
4569 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
4572 OpenMPScheduleTy ScheduleKind;
4573 ScheduleKind.
Schedule = OMPC_SCHEDULE_static;
4574 CGOpenMPRuntime::StaticRTInput StaticInit(
4575 32,
true,
false, IL.getAddress(),
4576 LB.getAddress(), UB.getAddress(), ST.getAddress());
4577 CGF.CGM.getOpenMPRuntime().emitForStaticInit(CGF, S.
getBeginLoc(), EKind,
4578 ScheduleKind, StaticInit);
4580 llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.
getBeginLoc());
4581 llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
4582 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
4583 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
4585 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.
getBeginLoc()), IV);
4587 CGF.EmitOMPInnerLoop(S,
false,
Cond, Inc, BodyGen,
4588 [](CodeGenFunction &) {});
4590 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
4591 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.
getEndLoc(),
4594 CGF.OMPCancelStack.emitExit(CGF, EKind, CodeGen);
4595 CGF.EmitOMPReductionClauseFinal(S, OMPD_parallel);
4598 return CGF.
Builder.CreateIsNotNull(
4603 if (HasLastprivates)
4610 bool HasCancel =
false;
4611 if (
auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
4612 HasCancel = OSD->hasCancel();
4613 else if (
auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
4614 HasCancel = OPSD->hasCancel();
4616 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_sections, CodeGen,
4621 if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) {
4639 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4644 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4645 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_scope,
CodeGen);
4648 if (!S.getSingleClause<OMPNowaitClause>()) {
4649 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_scope);
4656 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4657 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4658 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4659 using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
4661 auto FiniCB = [](InsertPointTy IP) {
4664 return llvm::Error::success();
4667 const CapturedStmt *ICS = S.getInnermostCapturedStmt();
4673 auto SectionCB = [
this, SubStmt](
4674 InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4677 CodeGenIP,
"section");
4678 return llvm::Error::success();
4680 SectionCBVector.push_back(SectionCB);
4684 [
this,
CapturedStmt](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4688 return llvm::Error::success();
4690 SectionCBVector.push_back(SectionCB);
4697 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
4698 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
4708 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4710 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4711 cantFail(OMPBuilder.createSections(
4712 Builder, AllocaIP, SectionCBVector, PrivCB, FiniCB, S.hasCancel(),
4713 S.getSingleClause<OMPNowaitClause>()));
4720 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4724 if (!S.getSingleClause<OMPNowaitClause>()) {
4725 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(),
4733 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4734 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4735 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4737 const Stmt *SectionRegionBodyStmt = S.getAssociatedStmt();
4738 auto FiniCB = [
this](InsertPointTy IP) {
4740 return llvm::Error::success();
4743 auto BodyGenCB = [SectionRegionBodyStmt,
4744 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4747 *
this, SectionRegionBodyStmt, AllocIP, CodeGenIP,
"section");
4748 return llvm::Error::success();
4753 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4754 cantFail(OMPBuilder.createSection(
Builder, BodyGenCB, FiniCB));
4774 CopyprivateVars.append(
C->varlist_begin(),
C->varlist_end());
4775 DestExprs.append(
C->destination_exprs().begin(),
4776 C->destination_exprs().end());
4777 SrcExprs.append(
C->source_exprs().begin(),
C->source_exprs().end());
4778 AssignmentOps.append(
C->assignment_ops().begin(),
4779 C->assignment_ops().end());
4788 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4793 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4794 CGM.getOpenMPRuntime().emitSingleRegion(*
this,
CodeGen, S.getBeginLoc(),
4795 CopyprivateVars, DestExprs,
4796 SrcExprs, AssignmentOps);
4800 if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) {
4801 CGM.getOpenMPRuntime().emitBarrierCall(
4802 *
this, S.getBeginLoc(),
4803 S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);
4818 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4819 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4820 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4822 const Stmt *MasterRegionBodyStmt = S.getAssociatedStmt();
4824 auto FiniCB = [
this](InsertPointTy IP) {
4826 return llvm::Error::success();
4829 auto BodyGenCB = [MasterRegionBodyStmt,
4830 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4833 *
this, MasterRegionBodyStmt, AllocIP, CodeGenIP,
"master");
4834 return llvm::Error::success();
4839 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4840 cantFail(OMPBuilder.createMaster(
Builder, BodyGenCB, FiniCB));
4855 Expr *Filter =
nullptr;
4857 Filter = FilterClause->getThreadID();
4863 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4864 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4865 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4867 const Stmt *MaskedRegionBodyStmt = S.getAssociatedStmt();
4868 const Expr *Filter =
nullptr;
4870 Filter = FilterClause->getThreadID();
4871 llvm::Value *FilterVal = Filter
4873 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
4875 auto FiniCB = [
this](InsertPointTy IP) {
4877 return llvm::Error::success();
4880 auto BodyGenCB = [MaskedRegionBodyStmt,
4881 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4884 *
this, MaskedRegionBodyStmt, AllocIP, CodeGenIP,
"masked");
4885 return llvm::Error::success();
4890 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
4891 OMPBuilder.createMasked(
Builder, BodyGenCB, FiniCB, FilterVal));
4902 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4903 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4904 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4906 const Stmt *CriticalRegionBodyStmt = S.getAssociatedStmt();
4907 const Expr *Hint =
nullptr;
4908 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4909 Hint = HintClause->getHint();
4914 llvm::Value *HintInst =
nullptr;
4919 auto FiniCB = [
this](InsertPointTy IP) {
4921 return llvm::Error::success();
4924 auto BodyGenCB = [CriticalRegionBodyStmt,
4925 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4928 *
this, CriticalRegionBodyStmt, AllocIP, CodeGenIP,
"critical");
4929 return llvm::Error::success();
4934 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4935 cantFail(OMPBuilder.createCritical(
Builder, BodyGenCB, FiniCB,
4936 S.getDirectiveName().getAsString(),
4945 CGF.
EmitStmt(S.getAssociatedStmt());
4947 const Expr *Hint =
nullptr;
4948 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4949 Hint = HintClause->getHint();
4952 CGM.getOpenMPRuntime().emitCriticalRegion(*
this,
4953 S.getDirectiveName().getAsString(),
4954 CodeGen, S.getBeginLoc(), Hint);
4958 const OMPParallelForDirective &S) {
4967 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
4971 OMPLoopScope LoopScope(CGF, S);
4974 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4975 [](
const OMPReductionClause *
C) {
4976 return C->getModifier() == OMPC_REDUCTION_inscan;
4992 const OMPParallelForSimdDirective &S) {
5001 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
5005 OMPLoopScope LoopScope(CGF, S);
5008 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
5009 [](
const OMPReductionClause *
C) {
5010 return C->getModifier() == OMPC_REDUCTION_inscan;
5026 const OMPParallelMasterDirective &S) {
5046 [](CodeGenFunction &) {
return nullptr; });
5053 const OMPParallelMaskedDirective &S) {
5073 [](CodeGenFunction &) {
return nullptr; });
5080 const OMPParallelSectionsDirective &S) {
5086 CGF.EmitSections(S);
5100class CheckVarsEscapingUntiedTaskDeclContext final
5105 explicit CheckVarsEscapingUntiedTaskDeclContext() =
default;
5106 ~CheckVarsEscapingUntiedTaskDeclContext() =
default;
5107 void VisitDeclStmt(
const DeclStmt *S) {
5112 if (
const auto *VD = dyn_cast_or_null<VarDecl>(D))
5114 PrivateDecls.push_back(VD);
5118 void VisitCapturedStmt(
const CapturedStmt *) {}
5120 void VisitBlockExpr(
const BlockExpr *) {}
5121 void VisitStmt(
const Stmt *S) {
5124 for (
const Stmt *Child : S->
children())
5130 ArrayRef<const VarDecl *> getPrivateDecls()
const {
return PrivateDecls; }
5138 bool OmpAllMemory =
false;
5141 return C->getDependencyKind() == OMPC_DEPEND_outallmemory ||
5142 C->getDependencyKind() == OMPC_DEPEND_inoutallmemory;
5144 OmpAllMemory =
true;
5149 Data.Dependences.emplace_back(OMPC_DEPEND_outallmemory,
5158 if (Kind == OMPC_DEPEND_outallmemory || Kind == OMPC_DEPEND_inoutallmemory)
5160 if (OmpAllMemory && (Kind == OMPC_DEPEND_out || Kind == OMPC_DEPEND_inout))
5163 Data.Dependences.emplace_back(
C->getDependencyKind(),
C->getModifier());
5164 DD.
DepExprs.append(
C->varlist_begin(),
C->varlist_end());
5173 const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion);
5175 auto PartId = std::next(I);
5176 auto TaskT = std::next(I, 4);
5181 const Expr *
Cond = Clause->getCondition();
5184 Data.Final.setInt(CondConstant);
5189 Data.Final.setInt(
false);
5193 const Expr *Prio = Clause->getPriority();
5194 Data.Priority.setInt(
true);
5202 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
5204 for (
const auto *
C : S.getClausesOfKind<OMPPrivateClause>()) {
5205 auto IRef =
C->varlist_begin();
5206 for (
const Expr *IInit :
C->private_copies()) {
5208 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
5209 Data.PrivateVars.push_back(*IRef);
5210 Data.PrivateCopies.push_back(IInit);
5215 EmittedAsPrivate.clear();
5217 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5218 auto IRef =
C->varlist_begin();
5219 auto IElemInitRef =
C->inits().begin();
5220 for (
const Expr *IInit :
C->private_copies()) {
5222 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
5223 Data.FirstprivateVars.push_back(*IRef);
5224 Data.FirstprivateCopies.push_back(IInit);
5225 Data.FirstprivateInits.push_back(*IElemInitRef);
5232 llvm::MapVector<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
5233 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
5234 auto IRef =
C->varlist_begin();
5235 auto ID =
C->destination_exprs().begin();
5236 for (
const Expr *IInit :
C->private_copies()) {
5238 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
5239 Data.LastprivateVars.push_back(*IRef);
5240 Data.LastprivateCopies.push_back(IInit);
5242 LastprivateDstsOrigs.insert(
5251 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
5252 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5253 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5254 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5255 Data.ReductionOps.append(
C->reduction_ops().begin(),
5256 C->reduction_ops().end());
5257 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5258 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5260 Data.Reductions =
CGM.getOpenMPRuntime().emitTaskReductionInit(
5261 *
this, S.getBeginLoc(), LHSs, RHSs,
Data);
5266 CheckVarsEscapingUntiedTaskDeclContext Checker;
5267 Checker.Visit(S.getInnermostCapturedStmt()->getCapturedStmt());
5268 Data.PrivateLocals.append(Checker.getPrivateDecls().begin(),
5269 Checker.getPrivateDecls().end());
5271 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
5272 CapturedRegion](CodeGenFunction &CGF,
5274 llvm::MapVector<CanonicalDeclPtr<const VarDecl>,
5275 std::pair<Address, Address>>
5280 if (
auto *DI = CGF.getDebugInfo()) {
5281 llvm::SmallDenseMap<const VarDecl *, FieldDecl *> CaptureFields =
5282 CGF.CapturedStmtInfo->getCaptureFields();
5283 llvm::Value *ContextValue = CGF.CapturedStmtInfo->getContextValue();
5284 if (CaptureFields.size() && ContextValue) {
5285 unsigned CharWidth = CGF.getContext().getCharWidth();
5299 for (
auto It = CaptureFields.begin(); It != CaptureFields.end(); ++It) {
5300 const VarDecl *SharedVar = It->first;
5303 CGF.getContext().getASTRecordLayout(CaptureRecord);
5306 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5307 (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue,
5308 CGF.Builder,
false);
5311 auto UpdateExpr = [](llvm::LLVMContext &Ctx,
auto *
Declare,
5316 Ops.push_back(llvm::dwarf::DW_OP_plus_uconst);
5317 Ops.push_back(Offset);
5319 Ops.push_back(llvm::dwarf::DW_OP_deref);
5320 Declare->setExpression(llvm::DIExpression::get(Ctx, Ops));
5322 llvm::Instruction &
Last = CGF.Builder.GetInsertBlock()->back();
5323 if (
auto DDI = dyn_cast<llvm::DbgVariableIntrinsic>(&
Last))
5324 UpdateExpr(DDI->getContext(), DDI, Offset);
5327 assert(!
Last.isTerminator() &&
"unexpected terminator");
5329 CGF.Builder.GetInsertBlock()->getTrailingDbgRecords()) {
5330 for (llvm::DbgVariableRecord &DVR : llvm::reverse(
5331 llvm::filterDbgVars(Marker->getDbgRecordRange()))) {
5332 UpdateExpr(
Last.getContext(), &DVR, Offset);
5340 if (!
Data.PrivateVars.empty() || !
Data.FirstprivateVars.empty() ||
5341 !
Data.LastprivateVars.empty() || !
Data.PrivateLocals.empty()) {
5342 enum { PrivatesParam = 2, CopyFnParam = 3 };
5343 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5345 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5351 CallArgs.push_back(PrivatesPtr);
5352 ParamTypes.push_back(PrivatesPtr->getType());
5353 for (
const Expr *E :
Data.PrivateVars) {
5356 CGF.getContext().getPointerType(E->
getType()),
".priv.ptr.addr");
5357 PrivatePtrs.emplace_back(VD, PrivatePtr);
5359 ParamTypes.push_back(PrivatePtr.
getType());
5361 for (
const Expr *E :
Data.FirstprivateVars) {
5364 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
5365 ".firstpriv.ptr.addr");
5366 PrivatePtrs.emplace_back(VD, PrivatePtr);
5367 FirstprivatePtrs.emplace_back(VD, PrivatePtr);
5369 ParamTypes.push_back(PrivatePtr.
getType());
5371 for (
const Expr *E :
Data.LastprivateVars) {
5374 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
5375 ".lastpriv.ptr.addr");
5376 PrivatePtrs.emplace_back(VD, PrivatePtr);
5378 ParamTypes.push_back(PrivatePtr.
getType());
5383 Ty = CGF.getContext().getPointerType(Ty);
5385 Ty = CGF.getContext().getPointerType(Ty);
5387 CGF.getContext().getPointerType(Ty),
".local.ptr.addr");
5388 auto Result = UntiedLocalVars.insert(
5391 if (
Result.second ==
false)
5392 *
Result.first = std::make_pair(
5395 ParamTypes.push_back(PrivatePtr.
getType());
5397 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5399 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5400 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5401 for (
const auto &Pair : LastprivateDstsOrigs) {
5405 CGF.CapturedStmtInfo->lookup(OrigVD) !=
nullptr,
5407 Pair.second->getExprLoc());
5408 Scope.addPrivate(Pair.first, CGF.EmitLValue(&DRE).getAddress());
5410 for (
const auto &Pair : PrivatePtrs) {
5412 CGF.Builder.CreateLoad(Pair.second),
5413 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5414 CGF.getContext().getDeclAlign(Pair.first));
5415 Scope.addPrivate(Pair.first, Replacement);
5416 if (
auto *DI = CGF.getDebugInfo())
5417 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5418 (void)DI->EmitDeclareOfAutoVariable(
5419 Pair.first, Pair.second.getBasePointer(), CGF.Builder,
5424 for (
auto &Pair : UntiedLocalVars) {
5425 QualType VDType = Pair.first->getType().getNonReferenceType();
5426 if (Pair.first->getType()->isLValueReferenceType())
5427 VDType = CGF.getContext().getPointerType(VDType);
5429 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5432 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(VDType)),
5433 CGF.getPointerAlign());
5434 Pair.second.first = Replacement;
5435 Ptr = CGF.Builder.CreateLoad(Replacement);
5436 Replacement =
Address(Ptr, CGF.ConvertTypeForMem(VDType),
5437 CGF.getContext().getDeclAlign(Pair.first));
5438 Pair.second.second = Replacement;
5440 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5441 Address Replacement(Ptr, CGF.ConvertTypeForMem(VDType),
5442 CGF.getContext().getDeclAlign(Pair.first));
5443 Pair.second.first = Replacement;
5447 if (
Data.Reductions) {
5449 for (
const auto &Pair : FirstprivatePtrs) {
5451 CGF.Builder.CreateLoad(Pair.second),
5452 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5453 CGF.getContext().getDeclAlign(Pair.first));
5454 FirstprivateScope.
addPrivate(Pair.first, Replacement);
5457 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5459 Data.ReductionCopies,
Data.ReductionOps);
5460 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
5462 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5468 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5470 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5473 CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF),
5474 CGF.getContext().VoidPtrTy,
5475 CGF.getContext().getPointerType(
5476 Data.ReductionCopies[Cnt]->getType()),
5477 Data.ReductionCopies[Cnt]->getExprLoc()),
5478 CGF.ConvertTypeForMem(
Data.ReductionCopies[Cnt]->getType()),
5479 Replacement.getAlignment());
5485 (void)
Scope.Privatize();
5490 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5491 auto IPriv =
C->privates().begin();
5492 auto IRed =
C->reduction_ops().begin();
5493 auto ITD =
C->taskgroup_descriptors().begin();
5494 for (
const Expr *Ref :
C->varlist()) {
5495 InRedVars.emplace_back(Ref);
5496 InRedPrivs.emplace_back(*IPriv);
5497 InRedOps.emplace_back(*IRed);
5498 TaskgroupDescriptors.emplace_back(*ITD);
5499 std::advance(IPriv, 1);
5500 std::advance(IRed, 1);
5501 std::advance(ITD, 1);
5507 if (!InRedVars.empty()) {
5509 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5517 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5519 llvm::Value *ReductionsPtr;
5520 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5521 ReductionsPtr = CGF.EmitLoadOfScalar(CGF.EmitLValue(TRExpr),
5522 TRExpr->getExprLoc());
5524 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5526 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5529 CGF.EmitScalarConversion(
5530 Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy,
5531 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
5532 InRedPrivs[Cnt]->getExprLoc()),
5533 CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()),
5534 Replacement.getAlignment());
5547 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5548 S, *I, *PartId, *TaskT, EKind,
CodeGen,
Data.Tied,
Data.NumberOfParts);
5549 OMPLexicalScope
Scope(*
this, S, std::nullopt,
5552 TaskGen(*
this, OutlinedFn,
Data);
5569 QualType ElemType =
C.getBaseElementType(Ty);
5579 Data.FirstprivateVars.emplace_back(OrigRef);
5580 Data.FirstprivateCopies.emplace_back(PrivateRef);
5581 Data.FirstprivateInits.emplace_back(InitRef);
5594 auto PartId = std::next(I);
5595 auto TaskT = std::next(I, 4);
5598 Data.Final.setInt(
false);
5600 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5601 auto IRef =
C->varlist_begin();
5602 auto IElemInitRef =
C->inits().begin();
5603 for (
auto *IInit :
C->private_copies()) {
5604 Data.FirstprivateVars.push_back(*IRef);
5605 Data.FirstprivateCopies.push_back(IInit);
5606 Data.FirstprivateInits.push_back(*IElemInitRef);
5613 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5614 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5615 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5616 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5617 Data.ReductionOps.append(
C->reduction_ops().begin(),
5618 C->reduction_ops().end());
5619 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5620 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5635 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5637 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5649 if (!isa_and_nonnull<llvm::ConstantPointerNull>(
5652 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5659 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, BPVD, PVD, SVD, MVD, EKind,
5663 if (!
Data.FirstprivateVars.empty()) {
5664 enum { PrivatesParam = 2, CopyFnParam = 3 };
5665 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5667 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5673 CallArgs.push_back(PrivatesPtr);
5674 ParamTypes.push_back(PrivatesPtr->getType());
5675 for (
const Expr *E :
Data.FirstprivateVars) {
5678 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
5679 ".firstpriv.ptr.addr");
5680 PrivatePtrs.emplace_back(VD, PrivatePtr);
5682 ParamTypes.push_back(PrivatePtr.
getType());
5684 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5686 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5687 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5688 for (
const auto &Pair : PrivatePtrs) {
5690 CGF.Builder.CreateLoad(Pair.second),
5691 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5692 CGF.getContext().getDeclAlign(Pair.first));
5693 Scope.addPrivate(Pair.first, Replacement);
5696 CGF.processInReduction(S,
Data, CGF, CS,
Scope);
5699 CGF.GetAddrOfLocalVar(BPVD), 0);
5701 CGF.GetAddrOfLocalVar(PVD), 0);
5702 InputInfo.
SizesArray = CGF.Builder.CreateConstArrayGEP(
5703 CGF.GetAddrOfLocalVar(SVD), 0);
5706 InputInfo.
MappersArray = CGF.Builder.CreateConstArrayGEP(
5707 CGF.GetAddrOfLocalVar(MVD), 0);
5711 OMPLexicalScope LexScope(CGF, S, OMPD_task,
false);
5713 if (CGF.CGM.getLangOpts().OpenMP >= 51 &&
5718 CGF.CGM.getOpenMPRuntime().emitThreadLimitClause(
5719 CGF, TL->getThreadLimit().front(), S.getBeginLoc());
5723 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5724 S, *I, *PartId, *TaskT, EKind,
CodeGen,
true,
5725 Data.NumberOfParts);
5726 llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<OMPNowaitClause>() ? 1 : 0);
5730 CGM.getOpenMPRuntime().emitTaskCall(*
this, S.getBeginLoc(), S, OutlinedFn,
5731 SharedsTy, CapturedStruct, &IfCond,
Data);
5736 CodeGenFunction &CGF,
5740 if (
Data.Reductions) {
5742 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5744 Data.ReductionCopies,
Data.ReductionOps);
5747 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5761 Data.ReductionCopies[Cnt]->getType()),
5762 Data.ReductionCopies[Cnt]->getExprLoc()),
5764 Replacement.getAlignment());
5769 (void)
Scope.Privatize();
5774 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5775 auto IPriv =
C->privates().begin();
5776 auto IRed =
C->reduction_ops().begin();
5777 auto ITD =
C->taskgroup_descriptors().begin();
5778 for (
const Expr *Ref :
C->varlist()) {
5779 InRedVars.emplace_back(Ref);
5780 InRedPrivs.emplace_back(*IPriv);
5781 InRedOps.emplace_back(*IRed);
5782 TaskgroupDescriptors.emplace_back(*ITD);
5783 std::advance(IPriv, 1);
5784 std::advance(IRed, 1);
5785 std::advance(ITD, 1);
5789 if (!InRedVars.empty()) {
5791 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5799 llvm::Value *ReductionsPtr;
5800 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5804 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
5812 InRedPrivs[Cnt]->getExprLoc()),
5814 Replacement.getAlignment());
5828 const Expr *IfCond =
nullptr;
5829 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
5830 if (
C->getNameModifier() == OMPD_unknown ||
5831 C->getNameModifier() == OMPD_task) {
5832 IfCond =
C->getCondition();
5839 Data.Tied = !S.getSingleClause<OMPUntiedClause>();
5843 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
5844 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
5847 SharedsTy, CapturedStruct, IfCond,
5856 const OMPTaskyieldDirective &S) {
5857 CGM.getOpenMPRuntime().emitTaskyieldCall(*
this, S.getBeginLoc());
5861 const OMPMessageClause *MC = S.getSingleClause<OMPMessageClause>();
5862 Expr *ME = MC ? MC->getMessageString() :
nullptr;
5863 const OMPSeverityClause *SC = S.getSingleClause<OMPSeverityClause>();
5864 bool IsFatal =
false;
5865 if (!SC || SC->getSeverityKind() == OMPC_SEVERITY_fatal)
5867 CGM.getOpenMPRuntime().emitErrorCall(*
this, S.getBeginLoc(), ME, IsFatal);
5871 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_barrier);
5878 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
5879 CGM.getOpenMPRuntime().emitTaskwaitCall(*
this, S.getBeginLoc(),
Data);
5883 return T.clauses().empty();
5887 const OMPTaskgroupDirective &S) {
5888 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
5890 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
5891 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5895 auto BodyGenCB = [&,
this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
5898 EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5899 return llvm::Error::success();
5904 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5905 cantFail(OMPBuilder.createTaskgroup(
Builder, AllocaIP,
5912 if (
const Expr *E = S.getReductionRef()) {
5916 for (
const auto *
C : S.getClausesOfKind<OMPTaskReductionClause>()) {
5917 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5918 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5919 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5920 Data.ReductionOps.append(
C->reduction_ops().begin(),
5921 C->reduction_ops().end());
5922 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5923 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5925 llvm::Value *ReductionDesc =
5933 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5935 CGM.getOpenMPRuntime().emitTaskgroupRegion(*
this,
CodeGen, S.getBeginLoc());
5940 ? llvm::AtomicOrdering::NotAtomic
5941 : llvm::AtomicOrdering::AcquireRelease;
5942 CGM.getOpenMPRuntime().emitFlush(
5945 if (
const auto *FlushClause = S.getSingleClause<
OMPFlushClause>())
5947 FlushClause->varlist_end());
5950 S.getBeginLoc(), AO);
5960 for (
auto &Dep :
Data.Dependences) {
5961 Address DepAddr =
CGM.getOpenMPRuntime().emitDepobjDependClause(
5962 *
this, Dep, DC->getBeginLoc());
5968 CGM.getOpenMPRuntime().emitDestroyClause(*
this, DOLVal, DC->getBeginLoc());
5971 if (
const auto *UC = S.getSingleClause<OMPUpdateClause>()) {
5972 CGM.getOpenMPRuntime().emitUpdateClause(
5973 *
this, DOLVal, UC->getDependencyKind(), UC->getBeginLoc());
5991 for (
const auto *
C : ParentDir.getClausesOfKind<OMPReductionClause>()) {
5992 if (
C->getModifier() != OMPC_REDUCTION_inscan)
5994 Shareds.append(
C->varlist_begin(),
C->varlist_end());
5995 Privates.append(
C->privates().begin(),
C->privates().end());
5996 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5997 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5998 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
5999 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
6000 CopyArrayTemps.append(
C->copy_array_temps().begin(),
6001 C->copy_array_temps().end());
6002 CopyArrayElems.append(
C->copy_array_elems().begin(),
6003 C->copy_array_elems().end());
6005 if (ParentDir.getDirectiveKind() == OMPD_simd ||
6047 : BreakContinueStack.back().ContinueBlock.getBlock());
6058 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6060 const Expr *TempExpr = CopyArrayTemps[I];
6072 CGM.getOpenMPRuntime().emitReduction(
6073 *
this, ParentDir.getEndLoc(),
Privates, LHSs, RHSs, ReductionOps,
6076 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6084 const Expr *TempExpr = CopyArrayTemps[I];
6096 ? BreakContinueStack.back().ContinueBlock.getBlock()
6102 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6108 .getIterationVariable()
6109 ->IgnoreParenImpCasts();
6112 IdxVal = Builder.CreateIntCast(IdxVal,
SizeTy,
false);
6113 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6115 const Expr *OrigExpr = Shareds[I];
6116 const Expr *CopyArrayElem = CopyArrayElems[I];
6117 OpaqueValueMapping IdxMapping(
6130 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6133 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6139 .getIterationVariable()
6140 ->IgnoreParenImpCasts();
6144 llvm::BasicBlock *ExclusiveExitBB =
nullptr;
6148 llvm::Value *
Cmp =
Builder.CreateIsNull(IdxVal);
6149 Builder.CreateCondBr(
Cmp, ExclusiveExitBB, ContBB);
6152 IdxVal =
Builder.CreateNUWSub(IdxVal, llvm::ConstantInt::get(
SizeTy, 1));
6154 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6155 const Expr *PrivateExpr =
Privates[I];
6156 const Expr *OrigExpr = Shareds[I];
6157 const Expr *CopyArrayElem = CopyArrayElems[I];
6166 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
6190 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
6198 bool HasLastprivateClause =
false;
6201 OMPLoopScope PreInitScope(*
this, S);
6206 llvm::BasicBlock *ContBlock =
nullptr;
6213 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
6227 ? S.getCombinedLowerBoundVariable()
6228 : S.getLowerBoundVariable())));
6232 ? S.getCombinedUpperBoundVariable()
6233 : S.getUpperBoundVariable())));
6244 CGM.getOpenMPRuntime().emitBarrierCall(
6245 *
this, S.getBeginLoc(), OMPD_unknown,
false,
6257 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
6260 llvm::Value *Chunk =
nullptr;
6263 ScheduleKind =
C->getDistScheduleKind();
6264 if (
const Expr *Ch =
C->getChunkSize()) {
6267 S.getIterationVariable()->getType(),
6272 CGM.getOpenMPRuntime().getDefaultDistScheduleAndChunk(
6273 *
this, S, ScheduleKind, Chunk);
6286 bool StaticChunked =
6290 Chunk !=
nullptr) ||
6295 StaticChunked ? Chunk :
nullptr);
6302 ? S.getCombinedEnsureUpperBound()
6303 : S.getEnsureUpperBound());
6306 ? S.getCombinedInit()
6311 ? S.getCombinedCond()
6315 Cond = S.getCombinedDistCond();
6347 [&S, &LoopScope,
Cond, IncExpr,
LoopExit, &CodeGenLoop,
6350 S, LoopScope.requiresCleanups(),
Cond, IncExpr,
6351 [&S,
LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
6352 CodeGenLoop(CGF, S, LoopExit);
6354 [&S, StaticChunked](CodeGenFunction &CGF) {
6355 if (StaticChunked) {
6356 CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound());
6357 CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound());
6358 CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound());
6359 CGF.EmitIgnoredExpr(S.getCombinedInit());
6369 const OMPLoopArguments LoopArguments = {
6370 LB.getAddress(), UB.getAddress(), ST.getAddress(), IL.getAddress(),
6372 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments,
6377 return CGF.
Builder.CreateIsNotNull(
6387 *
this, S, [IL, &S](CodeGenFunction &CGF) {
6388 return CGF.
Builder.CreateIsNotNull(
6393 if (HasLastprivateClause) {
6416 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
6425static llvm::Function *
6432 Fn->setDoesNotRecurse();
6436template <
typename T>
6438 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP,
6439 llvm::OpenMPIRBuilder &OMPBuilder) {
6441 unsigned NumLoops =
C->getNumLoops();
6445 for (
unsigned I = 0; I < NumLoops; I++) {
6446 const Expr *CounterVal =
C->getLoopData(I);
6451 StoreValues.emplace_back(StoreValue);
6453 OMPDoacrossKind<T> ODK;
6454 bool IsDependSource = ODK.isSource(
C);
6456 OMPBuilder.createOrderedDepend(CGF.
Builder, AllocaIP, NumLoops,
6457 StoreValues,
".cnt.addr", IsDependSource));
6461 if (
CGM.getLangOpts().OpenMPIRBuilder) {
6462 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
6463 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6468 assert(!S.hasAssociatedStmt() &&
"No associated statement must be in "
6469 "ordered depend|doacross construct.");
6481 auto FiniCB = [
this](InsertPointTy IP) {
6483 return llvm::Error::success();
6486 auto BodyGenCB = [&S,
C,
6487 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
6493 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
6494 Builder,
false,
".ordered.after");
6498 assert(S.getBeginLoc().isValid() &&
6499 "Outlined function call location must be valid.");
6502 OutlinedFn, CapturedVars);
6507 return llvm::Error::success();
6510 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6511 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
6512 OMPBuilder.createOrderedThreadsSimd(
Builder, BodyGenCB, FiniCB, !
C));
6519 assert(!S.hasAssociatedStmt() &&
6520 "No associated statement must be in ordered depend construct.");
6522 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6526 assert(!S.hasAssociatedStmt() &&
6527 "No associated statement must be in ordered doacross construct.");
6529 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6533 auto &&
CodeGen = [&S,
C,
this](CodeGenFunction &CGF,
6538 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
6540 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
6541 OutlinedFn, CapturedVars);
6547 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6548 CGM.getOpenMPRuntime().emitOrderedRegion(*
this,
CodeGen, S.getBeginLoc(), !
C);
6555 "DestType must have scalar evaluation kind.");
6556 assert(!Val.
isAggregate() &&
"Must be a scalar or complex.");
6567 "DestType must have complex evaluation kind.");
6576 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
6578 assert(Val.
isComplex() &&
"Must be a scalar or complex.");
6583 Val.
getComplexVal().first, SrcElementType, DestElementType, Loc);
6585 Val.
getComplexVal().second, SrcElementType, DestElementType, Loc);
6591 LValue LVal,
RValue RVal) {
6592 if (LVal.isGlobalReg())
6599 llvm::AtomicOrdering AO, LValue LVal,
6601 if (LVal.isGlobalReg())
6604 LVal, Loc, llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO),
6613 *
this, RVal, RValTy, LVal.
getType(), Loc)),
6622 llvm_unreachable(
"Must be a scalar or complex.");
6630 assert(
V->isLValue() &&
"V of 'omp atomic read' is not lvalue");
6631 assert(
X->isLValue() &&
"X of 'omp atomic read' is not lvalue");
6640 case llvm::AtomicOrdering::Acquire:
6641 case llvm::AtomicOrdering::AcquireRelease:
6642 case llvm::AtomicOrdering::SequentiallyConsistent:
6644 llvm::AtomicOrdering::Acquire);
6646 case llvm::AtomicOrdering::Monotonic:
6647 case llvm::AtomicOrdering::Release:
6649 case llvm::AtomicOrdering::NotAtomic:
6650 case llvm::AtomicOrdering::Unordered:
6651 llvm_unreachable(
"Unexpected ordering.");
6658 llvm::AtomicOrdering AO,
const Expr *
X,
6661 assert(
X->isLValue() &&
"X of 'omp atomic write' is not lvalue");
6669 case llvm::AtomicOrdering::Release:
6670 case llvm::AtomicOrdering::AcquireRelease:
6671 case llvm::AtomicOrdering::SequentiallyConsistent:
6673 llvm::AtomicOrdering::Release);
6675 case llvm::AtomicOrdering::Acquire:
6676 case llvm::AtomicOrdering::Monotonic:
6678 case llvm::AtomicOrdering::NotAtomic:
6679 case llvm::AtomicOrdering::Unordered:
6680 llvm_unreachable(
"Unexpected ordering.");
6687 llvm::AtomicOrdering AO,
6693 if (BO == BO_Comma || !
Update.isScalar() || !
X.isSimple() ||
6695 (
Update.getScalarVal()->getType() !=
X.getAddress().getElementType())) ||
6696 !Context.getTargetInfo().hasBuiltinAtomic(
6697 Context.getTypeSize(
X.getType()), Context.toBits(
X.getAlignment())))
6698 return std::make_pair(
false,
RValue::get(
nullptr));
6701 if (T->isIntegerTy())
6704 if (T->isFloatingPointTy() && (BO == BO_Add || BO == BO_Sub))
6710 if (!CheckAtomicSupport(
Update.getScalarVal()->getType(), BO) ||
6711 !CheckAtomicSupport(
X.getAddress().getElementType(), BO))
6712 return std::make_pair(
false,
RValue::get(
nullptr));
6714 bool IsInteger =
X.getAddress().getElementType()->isIntegerTy();
6715 llvm::AtomicRMWInst::BinOp RMWOp;
6718 RMWOp = IsInteger ? llvm::AtomicRMWInst::Add : llvm::AtomicRMWInst::FAdd;
6722 return std::make_pair(
false,
RValue::get(
nullptr));
6723 RMWOp = IsInteger ? llvm::AtomicRMWInst::Sub : llvm::AtomicRMWInst::FSub;
6726 RMWOp = llvm::AtomicRMWInst::And;
6729 RMWOp = llvm::AtomicRMWInst::Or;
6732 RMWOp = llvm::AtomicRMWInst::Xor;
6736 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6738 : llvm::AtomicRMWInst::Max)
6740 : llvm::AtomicRMWInst::UMax);
6743 : llvm::AtomicRMWInst::FMax;
6747 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6749 : llvm::AtomicRMWInst::Min)
6751 : llvm::AtomicRMWInst::UMin);
6754 : llvm::AtomicRMWInst::FMin;
6757 RMWOp = llvm::AtomicRMWInst::Xchg;
6766 return std::make_pair(
false,
RValue::get(
nullptr));
6785 llvm_unreachable(
"Unsupported atomic update operation");
6787 llvm::Value *UpdateVal =
Update.getScalarVal();
6788 if (
auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
6790 UpdateVal = CGF.
Builder.CreateIntCast(
6791 IC,
X.getAddress().getElementType(),
6792 X.getType()->hasSignedIntegerRepresentation());
6794 UpdateVal = CGF.
Builder.CreateCast(llvm::Instruction::CastOps::UIToFP, IC,
6795 X.getAddress().getElementType());
6797 llvm::AtomicRMWInst *Res =
6814 if (
X.isGlobalReg()) {
6827 llvm::AtomicOrdering AO,
const Expr *
X,
6831 "Update expr in 'atomic update' must be a binary operator.");
6839 assert(
X->isLValue() &&
"X of 'omp atomic update' is not lvalue");
6846 auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](
RValue XRValue) {
6852 XLValue, ExprRValue, BOUE->getOpcode(),
IsXLHSInRHSPart, AO, Loc, Gen);
6859 case llvm::AtomicOrdering::Release:
6860 case llvm::AtomicOrdering::AcquireRelease:
6861 case llvm::AtomicOrdering::SequentiallyConsistent:
6863 llvm::AtomicOrdering::Release);
6865 case llvm::AtomicOrdering::Acquire:
6866 case llvm::AtomicOrdering::Monotonic:
6868 case llvm::AtomicOrdering::NotAtomic:
6869 case llvm::AtomicOrdering::Unordered:
6870 llvm_unreachable(
"Unexpected ordering.");
6888 llvm_unreachable(
"Must be a scalar or complex.");
6892 llvm::AtomicOrdering AO,
6897 assert(
X->isLValue() &&
"X of 'omp atomic capture' is not lvalue");
6898 assert(
V->isLValue() &&
"V of 'omp atomic capture' is not lvalue");
6907 "Update expr in 'atomic capture' must be a binary operator.");
6918 NewVValType = XRValExpr->
getType();
6920 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
6929 XLValue, ExprRValue, BOUE->getOpcode(),
IsXLHSInRHSPart, AO, Loc, Gen);
6935 NewVVal = Res.second;
6946 NewVValType =
X->getType().getNonReferenceType();
6948 X->getType().getNonReferenceType(), Loc);
6949 auto &&Gen = [&NewVVal, ExprRValue](
RValue XRValue) {
6955 XLValue, ExprRValue, BO_Assign,
false, AO,
6976 case llvm::AtomicOrdering::Release:
6978 llvm::AtomicOrdering::Release);
6980 case llvm::AtomicOrdering::Acquire:
6982 llvm::AtomicOrdering::Acquire);
6984 case llvm::AtomicOrdering::AcquireRelease:
6985 case llvm::AtomicOrdering::SequentiallyConsistent:
6987 CGF, {}, Loc, llvm::AtomicOrdering::AcquireRelease);
6989 case llvm::AtomicOrdering::Monotonic:
6991 case llvm::AtomicOrdering::NotAtomic:
6992 case llvm::AtomicOrdering::Unordered:
6993 llvm_unreachable(
"Unexpected ordering.");
6999 CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO,
7003 llvm::OpenMPIRBuilder &OMPBuilder =
7006 OMPAtomicCompareOp Op;
7010 Op = OMPAtomicCompareOp::EQ;
7013 Op = OMPAtomicCompareOp::MIN;
7016 Op = OMPAtomicCompareOp::MAX;
7019 llvm_unreachable(
"unsupported atomic compare binary operator");
7023 Address XAddr = XLVal.getAddress();
7025 auto EmitRValueWithCastIfNeeded = [&CGF, Loc](
const Expr *
X,
const Expr *E) {
7030 if (NewE->
getType() ==
X->getType())
7035 llvm::Value *EVal = EmitRValueWithCastIfNeeded(
X, E);
7036 llvm::Value *DVal = D ? EmitRValueWithCastIfNeeded(
X, D) :
nullptr;
7037 if (
auto *CI = dyn_cast<llvm::ConstantInt>(EVal))
7038 EVal = CGF.
Builder.CreateIntCast(
7039 CI, XLVal.getAddress().getElementType(),
7042 if (
auto *CI = dyn_cast<llvm::ConstantInt>(DVal))
7043 DVal = CGF.
Builder.CreateIntCast(
7044 CI, XLVal.getAddress().getElementType(),
7047 llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{
7049 X->getType()->hasSignedIntegerRepresentation(),
7050 X->getType().isVolatileQualified()};
7051 llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal;
7055 VOpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
7056 V->getType()->hasSignedIntegerRepresentation(),
7057 V->getType().isVolatileQualified()};
7062 ROpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
7063 R->getType()->hasSignedIntegerRepresentation(),
7064 R->getType().isVolatileQualified()};
7067 if (FailAO == llvm::AtomicOrdering::NotAtomic) {
7070 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
7071 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
7074 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
7075 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
7080 llvm::AtomicOrdering AO,
7101 case OMPC_compare: {
7107 llvm_unreachable(
"Clause is not allowed in 'omp atomic'.");
7112 llvm::AtomicOrdering AO =
CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
7114 llvm::AtomicOrdering FailAO = llvm::AtomicOrdering::NotAtomic;
7115 bool MemOrderingSpecified =
false;
7116 if (S.getSingleClause<OMPSeqCstClause>()) {
7117 AO = llvm::AtomicOrdering::SequentiallyConsistent;
7118 MemOrderingSpecified =
true;
7119 }
else if (S.getSingleClause<OMPAcqRelClause>()) {
7120 AO = llvm::AtomicOrdering::AcquireRelease;
7121 MemOrderingSpecified =
true;
7122 }
else if (S.getSingleClause<OMPAcquireClause>()) {
7123 AO = llvm::AtomicOrdering::Acquire;
7124 MemOrderingSpecified =
true;
7125 }
else if (S.getSingleClause<OMPReleaseClause>()) {
7126 AO = llvm::AtomicOrdering::Release;
7127 MemOrderingSpecified =
true;
7128 }
else if (S.getSingleClause<OMPRelaxedClause>()) {
7129 AO = llvm::AtomicOrdering::Monotonic;
7130 MemOrderingSpecified =
true;
7132 llvm::SmallSet<OpenMPClauseKind, 2> KindsEncountered;
7141 if (K == OMPC_seq_cst || K == OMPC_acq_rel || K == OMPC_acquire ||
7142 K == OMPC_release || K == OMPC_relaxed || K == OMPC_hint)
7145 KindsEncountered.insert(K);
7150 if (KindsEncountered.contains(OMPC_compare) &&
7151 KindsEncountered.contains(OMPC_capture))
7152 Kind = OMPC_compare;
7153 if (!MemOrderingSpecified) {
7154 llvm::AtomicOrdering DefaultOrder =
7155 CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
7156 if (DefaultOrder == llvm::AtomicOrdering::Monotonic ||
7157 DefaultOrder == llvm::AtomicOrdering::SequentiallyConsistent ||
7158 (DefaultOrder == llvm::AtomicOrdering::AcquireRelease &&
7159 Kind == OMPC_capture)) {
7161 }
else if (DefaultOrder == llvm::AtomicOrdering::AcquireRelease) {
7162 if (Kind == OMPC_unknown || Kind == OMPC_update || Kind == OMPC_write) {
7163 AO = llvm::AtomicOrdering::Release;
7164 }
else if (Kind == OMPC_read) {
7165 assert(Kind == OMPC_read &&
"Unexpected atomic kind.");
7166 AO = llvm::AtomicOrdering::Acquire;
7171 if (KindsEncountered.contains(OMPC_compare) &&
7172 KindsEncountered.contains(OMPC_fail)) {
7173 Kind = OMPC_compare;
7174 const auto *FailClause = S.getSingleClause<OMPFailClause>();
7177 if (FailParameter == llvm::omp::OMPC_relaxed)
7178 FailAO = llvm::AtomicOrdering::Monotonic;
7179 else if (FailParameter == llvm::omp::OMPC_acquire)
7180 FailAO = llvm::AtomicOrdering::Acquire;
7181 else if (FailParameter == llvm::omp::OMPC_seq_cst)
7182 FailAO = llvm::AtomicOrdering::SequentiallyConsistent;
7189 S.getV(), S.getR(), S.getExpr(), S.getUpdateExpr(),
7190 S.getD(), S.getCondExpr(), S.isXLHSInRHSPart(),
7191 S.isFailOnly(), S.getBeginLoc());
7202 OMPLexicalScope
Scope(CGF, S, OMPD_target);
7205 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
7211 llvm::Function *Fn =
nullptr;
7212 llvm::Constant *FnID =
nullptr;
7214 const Expr *IfCond =
nullptr;
7216 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7217 if (
C->getNameModifier() == OMPD_unknown ||
7218 C->getNameModifier() == OMPD_target) {
7219 IfCond =
C->getCondition();
7225 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device(
7228 Device.setPointerAndInt(
C->getDevice(),
C->getModifier());
7233 bool IsOffloadEntry =
true;
7237 IsOffloadEntry =
false;
7240 IsOffloadEntry =
false;
7242 if (
CGM.
getLangOpts().OpenMPOffloadMandatory && !IsOffloadEntry) {
7246 assert(CGF.
CurFuncDecl &&
"No parent declaration for target region!");
7247 StringRef ParentName;
7250 if (
const auto *D = dyn_cast<CXXConstructorDecl>(CGF.
CurFuncDecl))
7252 else if (
const auto *D = dyn_cast<CXXDestructorDecl>(CGF.
CurFuncDecl))
7261 OMPLexicalScope
Scope(CGF, S, OMPD_task);
7262 auto &&SizeEmitter =
7265 if (IsOffloadEntry) {
7266 OMPLoopScope(CGF, D);
7268 llvm::Value *NumIterations = CGF.
EmitScalarExpr(D.getNumIterations());
7269 NumIterations = CGF.
Builder.CreateIntCast(NumIterations, CGF.
Int64Ty,
7271 return NumIterations;
7289 CGF.
EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
7294 StringRef ParentName,
7300 llvm::Constant *
Addr;
7302 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7304 assert(Fn &&
Addr &&
"Target device function emission failed.");
7318 const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams);
7319 llvm::Function *OutlinedFn =
7327 const Expr *NumTeams = NT ? NT->getNumTeams().front() :
nullptr;
7328 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() :
nullptr;
7334 OMPTeamsScope
Scope(CGF, S);
7350 CGF.
EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt());
7355 [](CodeGenFunction &) {
return nullptr; });
7360 auto *CS = S.getCapturedStmt(OMPD_teams);
7387 llvm::Constant *
Addr;
7389 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7391 assert(Fn &&
Addr &&
"Target device function emission failed.");
7433 llvm::Constant *
Addr;
7435 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7437 assert(Fn &&
Addr &&
"Target device function emission failed.");
7479 llvm::Constant *
Addr;
7481 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7483 assert(Fn &&
Addr &&
"Target device function emission failed.");
7497 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7502 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7514 [](CodeGenFunction &) {
return nullptr; });
7519 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7524 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7536 [](CodeGenFunction &) {
return nullptr; });
7541 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7547 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7559 [](CodeGenFunction &) {
return nullptr; });
7564 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7570 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7577 CGF, OMPD_distribute, CodeGenDistribute,
false);
7583 [](CodeGenFunction &) {
return nullptr; });
7587 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7588 llvm::Value *
Device =
nullptr;
7589 llvm::Value *NumDependences =
nullptr;
7590 llvm::Value *DependenceList =
nullptr;
7598 if (!
Data.Dependences.empty()) {
7600 std::tie(NumDependences, DependenciesArray) =
7601 CGM.getOpenMPRuntime().emitDependClause(*
this,
Data.Dependences,
7605 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
7610 "OMPNowaitClause clause is used separately in OMPInteropDirective.");
7613 if (!ItOMPInitClause.empty()) {
7616 llvm::Value *InteropvarPtr =
7618 llvm::omp::OMPInteropType InteropType =
7619 llvm::omp::OMPInteropType::Unknown;
7620 if (
C->getIsTarget()) {
7621 InteropType = llvm::omp::OMPInteropType::Target;
7623 assert(
C->getIsTargetSync() &&
7624 "Expected interop-type target/targetsync");
7625 InteropType = llvm::omp::OMPInteropType::TargetSync;
7627 OMPBuilder.createOMPInteropInit(
Builder, InteropvarPtr, InteropType,
7628 Device, NumDependences, DependenceList,
7629 Data.HasNowaitClause);
7633 if (!ItOMPDestroyClause.empty()) {
7636 llvm::Value *InteropvarPtr =
7638 OMPBuilder.createOMPInteropDestroy(
Builder, InteropvarPtr,
Device,
7639 NumDependences, DependenceList,
7640 Data.HasNowaitClause);
7643 auto ItOMPUseClause = S.getClausesOfKind<
OMPUseClause>();
7644 if (!ItOMPUseClause.empty()) {
7647 llvm::Value *InteropvarPtr =
7649 OMPBuilder.createOMPInteropUse(
Builder, InteropvarPtr,
Device,
7650 NumDependences, DependenceList,
7651 Data.HasNowaitClause);
7673 CGF, OMPD_distribute, CodeGenDistribute,
false);
7692 llvm::Constant *
Addr;
7694 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7696 assert(Fn &&
Addr &&
"Target device function emission failed.");
7725 CGF, OMPD_distribute, CodeGenDistribute,
false);
7744 llvm::Constant *
Addr;
7746 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7748 assert(Fn &&
Addr &&
"Target device function emission failed.");
7761 CGM.getOpenMPRuntime().emitCancellationPointCall(*
this, S.getBeginLoc(),
7766 const Expr *IfCond =
nullptr;
7767 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7768 if (
C->getNameModifier() == OMPD_unknown ||
7769 C->getNameModifier() == OMPD_cancel) {
7770 IfCond =
C->getCondition();
7774 if (
CGM.getLangOpts().OpenMPIRBuilder) {
7775 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7781 llvm::Value *IfCondition =
nullptr;
7785 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
7787 return Builder.restoreIP(AfterIP);
7791 CGM.getOpenMPRuntime().emitCancelCall(*
this, S.getBeginLoc(), IfCond,
7797 if (Kind == OMPD_parallel || Kind == OMPD_task ||
7798 Kind == OMPD_target_parallel || Kind == OMPD_taskloop ||
7799 Kind == OMPD_master_taskloop || Kind == OMPD_parallel_master_taskloop)
7801 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
7802 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
7803 Kind == OMPD_distribute_parallel_for ||
7804 Kind == OMPD_target_parallel_for ||
7805 Kind == OMPD_teams_distribute_parallel_for ||
7806 Kind == OMPD_target_teams_distribute_parallel_for);
7807 return OMPCancelStack.getExitBlock();
7812 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7813 CaptureDeviceAddrMap) {
7814 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7815 for (
const Expr *OrigVarIt :
C.varlist()) {
7817 if (!Processed.insert(OrigVD).second)
7824 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7829 "Base should be the current struct!");
7830 MatchingVD = ME->getMemberDecl();
7835 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7836 if (InitAddrIt == CaptureDeviceAddrMap.end())
7844 Address(InitAddrIt->second, Ty,
7846 assert(IsRegistered &&
"firstprivate var already registered as private");
7854 while (
const auto *OASE = dyn_cast<ArraySectionExpr>(
Base))
7855 Base = OASE->getBase()->IgnoreParenImpCasts();
7856 while (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(
Base))
7857 Base = ASE->getBase()->IgnoreParenImpCasts();
7863 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7864 CaptureDeviceAddrMap) {
7865 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7866 for (
const Expr *Ref :
C.varlist()) {
7868 if (!Processed.insert(OrigVD).second)
7874 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7879 "Base should be the current struct!");
7880 MatchingVD = ME->getMemberDecl();
7885 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7886 if (InitAddrIt == CaptureDeviceAddrMap.end())
7892 Address(InitAddrIt->second, Ty,
7905 (void)PrivateScope.
addPrivate(OrigVD, PrivAddr);
7913 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
7914 CGM.getOpenMPRuntime().registerVTable(S);
7922 bool PrivatizeDevicePointers =
false;
7924 bool &PrivatizeDevicePointers;
7927 explicit DevicePointerPrivActionTy(
bool &PrivatizeDevicePointers)
7928 : PrivatizeDevicePointers(PrivatizeDevicePointers) {}
7929 void Enter(CodeGenFunction &CGF)
override {
7930 PrivatizeDevicePointers =
true;
7933 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
7936 auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7937 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
7941 auto &&PrivCodeGen = [&](CodeGenFunction &CGF,
PrePostActionTy &Action) {
7943 PrivatizeDevicePointers =
false;
7949 if (PrivatizeDevicePointers) {
7963 std::optional<OpenMPDirectiveKind> CaptureRegion;
7964 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
7967 for (
const Expr *E :
C->varlist()) {
7969 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
7973 for (
const Expr *E :
C->varlist()) {
7975 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
7979 CaptureRegion = OMPD_unknown;
7982 OMPLexicalScope
Scope(CGF, S, CaptureRegion);
7994 OMPLexicalScope
Scope(CGF, S);
8003 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
8009 const Expr *IfCond =
nullptr;
8011 IfCond =
C->getCondition();
8022 CGM.getOpenMPRuntime().emitTargetDataCalls(*
this, S, IfCond,
Device, RCG,
8030 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8034 const Expr *IfCond =
nullptr;
8036 IfCond =
C->getCondition();
8043 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8044 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8051 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8055 const Expr *IfCond =
nullptr;
8057 IfCond =
C->getCondition();
8064 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8065 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8072 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
8100 llvm::Constant *
Addr;
8102 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8104 assert(Fn &&
Addr &&
"Target device function emission failed.");
8124 CGF, OMPD_target_parallel_for, S.
hasCancel());
8140 llvm::Constant *
Addr;
8142 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8144 assert(Fn &&
Addr &&
"Target device function emission failed.");
8179 llvm::Constant *
Addr;
8181 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8183 assert(Fn &&
Addr &&
"Target device function emission failed.");
8205 const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop);
8208 OMPLexicalScope
Scope(*
this, S, OMPD_taskloop,
false);
8213 const Expr *IfCond =
nullptr;
8214 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
8215 if (
C->getNameModifier() == OMPD_unknown ||
8216 C->getNameModifier() == OMPD_taskloop) {
8217 IfCond =
C->getCondition();
8230 Data.Schedule.setInt(
false);
8233 (Clause->getModifier() == OMPC_GRAINSIZE_strict) ?
true :
false;
8236 Data.Schedule.setInt(
true);
8239 (Clause->getModifier() == OMPC_NUMTASKS_strict) ?
true :
false;
8253 llvm::BasicBlock *ContBlock =
nullptr;
8254 OMPLoopScope PreInitScope(CGF, S);
8255 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
8259 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock(
"taskloop.if.then");
8260 ContBlock = CGF.createBasicBlock(
"taskloop.if.end");
8261 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
8262 CGF.getProfileCount(&S));
8263 CGF.EmitBlock(ThenBlock);
8264 CGF.incrementProfileCounter(&S);
8267 (void)CGF.EmitOMPLinearClauseInit(S);
8271 enum { LowerBound = 5, UpperBound, Stride, LastIter };
8273 auto *LBP = std::next(I, LowerBound);
8274 auto *UBP = std::next(I, UpperBound);
8275 auto *STP = std::next(I, Stride);
8276 auto *LIP = std::next(I, LastIter);
8284 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
8285 CGF.EmitOMPLinearClause(S, LoopScope);
8286 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
8289 const Expr *IVExpr = S.getIterationVariable();
8291 CGF.EmitVarDecl(*IVDecl);
8292 CGF.EmitIgnoredExpr(S.getInit());
8297 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
8300 CGF.EmitIgnoredExpr(S.getCalcLastIteration());
8304 OMPLexicalScope
Scope(CGF, S, OMPD_taskloop,
false);
8314 [&S](CodeGenFunction &CGF) {
8315 emitOMPLoopBodyWithStopPoint(CGF, S,
8316 CodeGenFunction::JumpDest());
8318 [](CodeGenFunction &) {});
8323 CGF.EmitBranch(ContBlock);
8324 CGF.EmitBlock(ContBlock,
true);
8327 if (HasLastprivateClause) {
8328 CGF.EmitOMPLastprivateClauseFinal(
8330 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
8331 CGF.GetAddrOfLocalVar(*LIP),
false,
8332 (*LIP)->getType(), S.getBeginLoc())));
8335 CGF.EmitOMPLinearClauseFinal(S, [LIP, &S](CodeGenFunction &CGF) {
8336 return CGF.
Builder.CreateIsNotNull(
8338 (*LIP)->
getType(), S.getBeginLoc()));
8341 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
8342 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
8344 auto &&
CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
8346 OMPLoopScope PreInitScope(CGF, S);
8347 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S,
8348 OutlinedFn, SharedsTy,
8349 CapturedStruct, IfCond,
Data);
8351 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
8357 CGM.getOpenMPRuntime().emitTaskgroupRegion(
8359 [&S, &BodyGen, &TaskGen, &
Data](CodeGenFunction &CGF,
8379 OMPLexicalScope
Scope(*
this, S);
8391 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8392 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8403 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8404 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8415 OMPLexicalScope
Scope(*
this, S);
8416 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8427 OMPLexicalScope
Scope(*
this, S);
8428 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8434 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8439 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8440 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8452 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8457 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8458 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8470 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8475 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8476 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8488 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8493 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8494 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8508 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8512 const Expr *IfCond =
nullptr;
8514 IfCond =
C->getCondition();
8521 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8522 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8532 BindKind =
C->getBindKind();
8535 case OMPC_BIND_parallel:
8537 case OMPC_BIND_teams:
8539 case OMPC_BIND_thread:
8550 const auto *ForS = dyn_cast<ForStmt>(CS);
8561 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
8562 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_loop,
CodeGen);
8588 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
8593 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
8605 [](CodeGenFunction &) {
return nullptr; });
8610 std::string StatusMsg,
8614 StatusMsg +=
": DEVICE";
8616 StatusMsg +=
": HOST";
8623 llvm::dbgs() << StatusMsg <<
": " <<
FileName <<
": " << LineNo <<
"\n";
8646 CGF, OMPD_distribute, CodeGenDistribute,
false);
8675 CGF, OMPD_distribute, CodeGenDistribute,
false);
8708 llvm::Constant *
Addr;
8710 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8712 assert(Fn &&
Addr &&
8713 "Target device function emission failed for 'target teams loop'.");
8724 CGF, OMPD_target_parallel_loop,
false);
8740 llvm::Constant *
Addr;
8742 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8744 assert(Fn &&
Addr &&
"Target device function emission failed.");
8759 if (
const auto *SD = dyn_cast<OMPScanDirective>(&D)) {
8763 if (!D.hasAssociatedStmt() || !D.getAssociatedStmt())
8769 for (
const auto *
C : D.getClausesOfKind<OMPFirstprivateClause>()) {
8770 for (
const Expr *Ref :
C->varlist()) {
8774 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
8777 if (!CGF.LocalDeclMap.count(VD)) {
8789 if (
const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
8790 for (
const Expr *E : LD->counters()) {
8798 if (!CGF.LocalDeclMap.count(VD))
8802 for (
const auto *
C : D.getClausesOfKind<OMPOrderedClause>()) {
8803 if (!
C->getNumForLoops())
8805 for (
unsigned I = LD->getLoopsNumber(),
8806 E =
C->getLoopNumIterations().size();
8808 if (
const auto *VD = dyn_cast<OMPCapturedExprDecl>(
8811 if (!CGF.LocalDeclMap.count(VD))
8818 CGF.
EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
8821 if (D.getDirectiveKind() == OMPD_atomic ||
8822 D.getDirectiveKind() == OMPD_critical ||
8823 D.getDirectiveKind() == OMPD_section ||
8824 D.getDirectiveKind() == OMPD_master ||
8825 D.getDirectiveKind() == OMPD_masked ||
8826 D.getDirectiveKind() == OMPD_unroll ||
8827 D.getDirectiveKind() == OMPD_assume) {
8832 OMPSimdLexicalScope
Scope(*
this, D);
8833 CGM.getOpenMPRuntime().emitInlinedDirective(
8836 : 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