31#include "llvm/ADT/SmallSet.h"
32#include "llvm/BinaryFormat/Dwarf.h"
33#include "llvm/Frontend/OpenMP/OMPConstants.h"
34#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
35#include "llvm/IR/Constants.h"
36#include "llvm/IR/DebugInfoMetadata.h"
37#include "llvm/IR/Instructions.h"
38#include "llvm/IR/IntrinsicInst.h"
39#include "llvm/IR/Metadata.h"
40#include "llvm/Support/AtomicOrdering.h"
41#include "llvm/Support/Debug.h"
45using namespace llvm::omp;
47#define TTL_CODEGEN_TYPE "target-teams-loop-codegen"
63 S.hasClausesOfKind<OMPReductionClause>() &&
65 !S.getSingleClause<OMPScheduleClause>() &&
66 !S.getSingleClause<OMPOrderedClause>();
73 void emitPreInitStmt(CodeGenFunction &CGF,
const OMPExecutableDirective &S) {
74 for (
const auto *
C : S.clauses()) {
75 if (
const auto *CPI = OMPClauseWithPreInit::get(
C)) {
76 if (
const auto *PreInit =
77 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
78 for (
const auto *I : PreInit->decls()) {
79 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
82 CodeGenFunction::AutoVarEmission Emission =
91 CodeGenFunction::OMPPrivateScope InlinedShareds;
93 static bool isCapturedVar(CodeGenFunction &CGF,
const VarDecl *VD) {
102 CodeGenFunction &CGF,
const OMPExecutableDirective &S,
103 const std::optional<OpenMPDirectiveKind> CapturedRegion = std::nullopt,
104 const bool EmitPreInitStmt =
true)
106 InlinedShareds(CGF) {
108 emitPreInitStmt(CGF, S);
111 assert(S.hasAssociatedStmt() &&
112 "Expected associated statement for inlined directive.");
113 const CapturedStmt *CS = S.getCapturedStmt(*CapturedRegion);
115 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
116 auto *VD =
C.getCapturedVar();
118 "Canonical decl must be captured.");
122 InlinedShareds.isGlobalVarCaptured(VD)),
127 (void)InlinedShareds.Privatize();
133class OMPParallelScope final :
public OMPLexicalScope {
134 bool EmitPreInitStmt(
const OMPExecutableDirective &S) {
142 OMPParallelScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
143 : OMPLexicalScope(CGF, S, std::nullopt,
144 EmitPreInitStmt(S)) {}
149class OMPTeamsScope final :
public OMPLexicalScope {
150 bool EmitPreInitStmt(
const OMPExecutableDirective &S) {
157 OMPTeamsScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
158 : OMPLexicalScope(CGF, S, std::nullopt,
159 EmitPreInitStmt(S)) {}
165 void emitPreInitStmt(CodeGenFunction &CGF,
const OMPLoopBasedDirective &S) {
166 const Stmt *PreInits;
167 CodeGenFunction::OMPMapVars PreCondVars;
168 if (
auto *LD = dyn_cast<OMPLoopDirective>(&S)) {
170 (void)OMPLoopBasedDirective::doForAllLoops(
171 LD->getInnermostCapturedStmt()->getCapturedStmt(),
172 true, LD->getLoopsNumber(),
173 [&CGF](
unsigned Cnt,
const Stmt *CurStmt) {
174 if (const auto *CXXFor = dyn_cast<CXXForRangeStmt>(CurStmt)) {
175 if (const Stmt *Init = CXXFor->getInit())
177 CGF.EmitStmt(CXXFor->getRangeStmt());
178 CGF.EmitStmt(CXXFor->getBeginStmt());
179 CGF.EmitStmt(CXXFor->getEndStmt());
183 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
184 for (
const auto *E : LD->counters()) {
191 for (
const auto *
C : LD->getClausesOfKind<OMPPrivateClause>()) {
192 for (
const Expr *IRef :
C->varlist()) {
195 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
196 QualType OrigVDTy = OrigVD->getType().getNonReferenceType();
206 (void)PreCondVars.
apply(CGF);
207 PreInits = LD->getPreInits();
208 }
else if (
const auto *
Tile = dyn_cast<OMPTileDirective>(&S)) {
209 PreInits =
Tile->getPreInits();
210 }
else if (
const auto *Stripe = dyn_cast<OMPStripeDirective>(&S)) {
211 PreInits = Stripe->getPreInits();
212 }
else if (
const auto *Unroll = dyn_cast<OMPUnrollDirective>(&S)) {
213 PreInits = Unroll->getPreInits();
214 }
else if (
const auto *Reverse = dyn_cast<OMPReverseDirective>(&S)) {
215 PreInits = Reverse->getPreInits();
216 }
else if (
const auto *Split = dyn_cast<OMPSplitDirective>(&S)) {
217 PreInits =
Split->getPreInits();
218 }
else if (
const auto *Interchange =
219 dyn_cast<OMPInterchangeDirective>(&S)) {
220 PreInits = Interchange->getPreInits();
222 llvm_unreachable(
"Unknown loop-based directive kind.");
224 doEmitPreinits(PreInits);
231 const Stmt *PreInits;
232 if (
const auto *Fuse = dyn_cast<OMPFuseDirective>(&S)) {
233 PreInits = Fuse->getPreInits();
236 "Unknown canonical loop sequence transform directive kind.");
238 doEmitPreinits(PreInits);
241 void doEmitPreinits(
const Stmt *PreInits) {
247 if (
auto *PreInitCompound = dyn_cast<CompoundStmt>(PreInits))
248 llvm::append_range(PreInitStmts, PreInitCompound->body());
250 PreInitStmts.push_back(PreInits);
252 for (
const Stmt *S : PreInitStmts) {
255 if (
auto *PreInitDecl = dyn_cast<DeclStmt>(S)) {
256 for (
Decl *I : PreInitDecl->decls())
268 emitPreInitStmt(CGF, S);
273 emitPreInitStmt(CGF, S);
278 CodeGenFunction::OMPPrivateScope InlinedShareds;
280 static bool isCapturedVar(CodeGenFunction &CGF,
const VarDecl *VD) {
288 OMPSimdLexicalScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
290 InlinedShareds(CGF) {
291 for (
const auto *
C : S.clauses()) {
292 if (const auto *CPI = OMPClauseWithPreInit::get(C)) {
293 if (const auto *PreInit =
294 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
295 for (const auto *I : PreInit->decls()) {
296 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
297 CGF.EmitVarDecl(cast<VarDecl>(*I));
299 CodeGenFunction::AutoVarEmission Emission =
300 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
301 CGF.EmitAutoVarCleanups(Emission);
305 }
else if (
const auto *UDP = dyn_cast<OMPUseDevicePtrClause>(
C)) {
306 for (
const Expr *E : UDP->varlist()) {
308 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
311 }
else if (
const auto *UDP = dyn_cast<OMPUseDeviceAddrClause>(
C)) {
312 for (
const Expr *E : UDP->varlist()) {
314 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
321 if (
const auto *TG = dyn_cast<OMPTaskgroupDirective>(&S)) {
322 if (
const Expr *E = TG->getReductionRef())
327 llvm::DenseSet<CanonicalDeclPtr<const Decl>> CopyArrayTemps;
328 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
329 if (C->getModifier() != OMPC_REDUCTION_inscan)
331 for (const Expr *E : C->copy_array_temps())
332 CopyArrayTemps.insert(cast<DeclRefExpr>(E)->getDecl());
334 const auto *CS = cast_or_null<CapturedStmt>(S.getAssociatedStmt());
337 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
338 auto *VD =
C.getCapturedVar();
339 if (CopyArrayTemps.contains(VD))
342 "Canonical decl must be captured.");
343 DeclRefExpr DRE(CGF.
getContext(),
const_cast<VarDecl *
>(VD),
344 isCapturedVar(CGF, VD) ||
346 InlinedShareds.isGlobalVarCaptured(VD)),
354 (void)InlinedShareds.Privatize();
365 if (Kind != OMPD_loop)
370 BindKind =
C->getBindKind();
373 case OMPC_BIND_parallel:
375 case OMPC_BIND_teams:
376 return OMPD_distribute;
377 case OMPC_BIND_thread:
389 if (
const auto *OrigDRE = dyn_cast<DeclRefExpr>(E)) {
390 if (
const auto *OrigVD = dyn_cast<VarDecl>(OrigDRE->getDecl())) {
391 OrigVD = OrigVD->getCanonicalDecl();
397 OrigDRE->getType(),
VK_LValue, OrigDRE->getExprLoc());
406 llvm::Value *Size =
nullptr;
407 auto SizeInChars =
C.getTypeSizeInChars(Ty);
408 if (SizeInChars.isZero()) {
416 SizeInChars =
C.getTypeSizeInChars(Ty);
417 if (SizeInChars.isZero())
418 return llvm::ConstantInt::get(
SizeTy, 0);
419 return Builder.CreateNUWMul(Size,
CGM.getSize(SizeInChars));
421 return CGM.getSize(SizeInChars);
431 I != E; ++I, ++CurField, ++CurCap) {
432 if (CurField->hasCapturedVLAType()) {
435 CapturedVars.push_back(Val);
436 }
else if (CurCap->capturesThis()) {
437 CapturedVars.push_back(CXXThisValue);
438 }
else if (CurCap->capturesVariableByCopy()) {
443 if (!CurField->getType()->isAnyPointerType()) {
447 Twine(CurCap->getCapturedVar()->getName(),
".casted"));
463 CapturedVars.push_back(CV);
465 assert(CurCap->capturesVariable() &&
"Expected capture by reference.");
486 if (T->isLValueReferenceType())
487 return C.getLValueReferenceType(
490 if (T->isPointerType())
493 if (
const auto *VLA = dyn_cast<VariableArrayType>(A))
495 if (!A->isVariablyModifiedType())
496 return C.getCanonicalType(T);
498 return C.getCanonicalParamType(T);
503struct FunctionOptions {
505 const CapturedStmt *S =
nullptr;
508 const bool UIntPtrCastRequired =
true;
511 const bool RegisterCastedArgsOnly =
false;
513 const StringRef FunctionName;
516 const bool IsDeviceKernel =
false;
517 explicit FunctionOptions(
const CapturedStmt *S,
bool UIntPtrCastRequired,
518 bool RegisterCastedArgsOnly, StringRef FunctionName,
519 SourceLocation Loc,
bool IsDeviceKernel)
520 : S(S), UIntPtrCastRequired(UIntPtrCastRequired),
521 RegisterCastedArgsOnly(UIntPtrCastRequired && RegisterCastedArgsOnly),
522 FunctionName(FunctionName), Loc(Loc), IsDeviceKernel(IsDeviceKernel) {}
528 llvm::MapVector<
const Decl *, std::pair<const VarDecl *, Address>>
530 llvm::DenseMap<
const Decl *, std::pair<const Expr *, llvm::Value *>>
532 llvm::Value *&CXXThisValue,
const FunctionOptions &FO) {
535 assert(CD->
hasBody() &&
"missing CapturedDecl body");
537 CXXThisValue =
nullptr;
549 if (!FO.UIntPtrCastRequired) {
569 if (FO.UIntPtrCastRequired &&
570 ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) ||
571 I->capturesVariableArrayType()))
574 if (I->capturesVariable() || I->capturesVariableByCopy()) {
575 CapVar = I->getCapturedVar();
577 }
else if (I->capturesThis()) {
580 assert(I->capturesVariableArrayType());
583 if (ArgType->isVariablyModifiedType())
590 }
else if (DebugFunctionDecl && (CapVar || I->capturesThis())) {
592 Ctx, DebugFunctionDecl,
593 CapVar ? CapVar->
getBeginLoc() : FD->getBeginLoc(),
594 CapVar ? CapVar->
getLocation() : FD->getLocation(), II, ArgType,
600 Args.emplace_back(Arg);
602 TargetArgs.emplace_back(
603 FO.UIntPtrCastRequired
624 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
630 if (CGM.
getTriple().isSPIRV() && !FO.IsDeviceKernel)
631 F->setCallingConv(llvm::CallingConv::SPIR_FUNC);
634 F->setDoesNotThrow();
635 F->setDoesNotRecurse();
639 F->removeFnAttr(llvm::Attribute::NoInline);
640 F->addFnAttr(llvm::Attribute::AlwaysInline);
643 F->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
647 FO.UIntPtrCastRequired ? FO.Loc : FO.S->
getBeginLoc(),
648 FO.UIntPtrCastRequired ? FO.Loc
655 if (!FO.UIntPtrCastRequired && Args[Cnt] != TargetArgs[Cnt]) {
663 if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
664 const VarDecl *CurVD = I->getCapturedVar();
665 if (!FO.RegisterCastedArgsOnly)
666 LocalAddrs.insert({Args[Cnt], {CurVD, LocalAddr}});
674 if (FD->hasCapturedVLAType()) {
675 if (FO.UIntPtrCastRequired) {
678 Args[Cnt]->getName(), ArgLVal),
683 VLASizes.try_emplace(Args[Cnt], VAT->
getSizeExpr(), ExprArg);
684 }
else if (I->capturesVariable()) {
685 const VarDecl *Var = I->getCapturedVar();
687 Address ArgAddr = ArgLVal.getAddress();
688 if (ArgLVal.getType()->isLValueReferenceType()) {
691 assert(ArgLVal.getType()->isPointerType());
693 ArgAddr, ArgLVal.getType()->castAs<
PointerType>());
695 if (!FO.RegisterCastedArgsOnly) {
699 }
else if (I->capturesVariableByCopy()) {
700 assert(!FD->getType()->isAnyPointerType() &&
701 "Not expecting a captured pointer.");
702 const VarDecl *Var = I->getCapturedVar();
703 LocalAddrs.insert({Args[Cnt],
704 {Var, FO.UIntPtrCastRequired
706 CGF, I->getLocation(), FD->getType(),
707 Args[Cnt]->getName(), ArgLVal)
708 : ArgLVal.getAddress()}});
711 assert(I->capturesThis());
713 LocalAddrs.insert({Args[Cnt], {
nullptr, ArgLVal.getAddress()}});
724 llvm::MapVector<
const Decl *, std::pair<const VarDecl *, Address>>
726 llvm::DenseMap<
const Decl *, std::pair<const Expr *, llvm::Value *>>
728 llvm::Value *&CXXThisValue, llvm::Value *&ContextV,
const CapturedStmt &CS,
733 CXXThisValue =
nullptr;
743 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
747 F->setDoesNotThrow();
748 F->setDoesNotRecurse();
755 llvm::Type *IntPtrTy = CGF.
IntPtrTy;
756 llvm::Type *PtrTy = CGF.
Builder.getPtrTy();
757 llvm::Align PtrAlign = CGM.
getDataLayout().getPointerABIAlignment(0);
760 for (
auto [FD,
C, FieldIdx] :
764 CGF.
Builder.CreateConstInBoundsGEP1_32(IntPtrTy, ContextV, FieldIdx);
769 if (
C.capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
770 const VarDecl *CurVD =
C.getCapturedVar();
771 Slot->setName(CurVD->
getName());
772 Address SlotAddr(Slot, PtrTy, SlotAlign);
773 LocalAddrs.insert({FD, {CurVD, SlotAddr}});
774 }
else if (FD->hasCapturedVLAType()) {
781 VLASizes.try_emplace(FD, VAT->
getSizeExpr(), ExprArg);
782 }
else if (
C.capturesVariable()) {
783 const VarDecl *Var =
C.getCapturedVar();
787 Slot->setName(Var->
getName() +
".addr");
788 Address SlotAddr(Slot, PtrTy, SlotAlign);
789 LocalAddrs.insert({FD, {Var, SlotAddr}});
792 PtrTy, Slot, PtrAlign, Var->
getName());
793 LocalAddrs.insert({FD,
797 }
else if (
C.capturesVariableByCopy()) {
798 assert(!FD->getType()->isAnyPointerType() &&
799 "Not expecting a captured pointer.");
800 const VarDecl *Var =
C.getCapturedVar();
815 LocalAddrs.insert({FD, {Var, CopyAddr}});
817 assert(
C.capturesThis() &&
"Default case expected to be CXX 'this'");
820 Address SlotAddr(Slot, PtrTy, SlotAlign);
821 LocalAddrs.insert({FD, {
nullptr, SlotAddr}});
833 "CapturedStmtInfo should be set when generating the captured function");
836 bool NeedWrapperFunction =
839 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs,
841 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes,
844 llvm::raw_svector_ostream Out(Buffer);
847 bool IsDeviceKernel =
CGM.getOpenMPRuntime().isGPU() &&
849 D.getCapturedStmt(OMPD_target) == &S;
850 CodeGenFunction WrapperCGF(
CGM,
true);
851 llvm::Function *WrapperF =
nullptr;
852 if (NeedWrapperFunction) {
855 FunctionOptions WrapperFO(&S,
true,
862 WrapperCGF.CXXThisValue, WrapperFO);
865 FunctionOptions FO(&S, !NeedWrapperFunction,
false,
866 Out.str(), Loc, !NeedWrapperFunction && IsDeviceKernel);
868 *
this, WrapperArgs, WrapperLocalAddrs, WrapperVLASizes, CXXThisValue, FO);
870 for (
const auto &LocalAddrPair : WrapperLocalAddrs) {
871 if (LocalAddrPair.second.first) {
872 LocalScope.addPrivate(LocalAddrPair.second.first,
873 LocalAddrPair.second.second);
876 (void)LocalScope.Privatize();
877 for (
const auto &VLASizePair : WrapperVLASizes)
878 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
881 LocalScope.ForceCleanup();
883 if (!NeedWrapperFunction)
887 WrapperF->removeFromParent();
888 F->getParent()->getFunctionList().insertAfter(F->getIterator(), WrapperF);
891 auto *PI = F->arg_begin();
892 for (
const auto *Arg : Args) {
894 auto I = LocalAddrs.find(Arg);
895 if (I != LocalAddrs.end()) {
898 I->second.first ? I->second.first->getType() : Arg->getType(),
904 auto EI = VLASizes.find(Arg);
905 if (EI != VLASizes.end()) {
917 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
927 "CapturedStmtInfo should be set when generating the captured function");
931 bool NeedWrapperFunction =
934 CodeGenFunction WrapperCGF(
CGM,
true);
935 llvm::Function *WrapperF =
nullptr;
936 llvm::Value *WrapperContextV =
nullptr;
937 if (NeedWrapperFunction) {
940 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>>
942 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>>
945 WrapperCGF, WrapperArgs, WrapperLocalAddrs, WrapperVLASizes,
946 WrapperCGF.CXXThisValue, WrapperContextV, S, Loc, FunctionName);
950 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs;
951 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes;
954 if (NeedWrapperFunction) {
956 llvm::raw_svector_ostream Out(Buffer);
957 Out << FunctionName <<
"_debug__";
959 FunctionOptions FO(&S,
false,
960 false, Out.str(), Loc,
965 llvm::Value *ContextV =
nullptr;
967 CXXThisValue, ContextV, S, Loc,
976 llvm::Value *ParamAddr =
Builder.CreateConstInBoundsGEP1_32(
977 IntPtrTy, ContextV, FieldIdx, Twine(Param->getName()) +
".addr");
978 llvm::Value *ParamVal =
Builder.CreateAlignedLoad(
980 CGM.getDataLayout().getPointerABIAlignment(0), Param->getName());
983 Builder.CreateStore(ParamVal, ParamLocalAddr);
984 LocalAddrs.insert({Param, {Param, ParamLocalAddr}});
990 for (
const auto &LocalAddrPair : LocalAddrs) {
991 if (LocalAddrPair.second.first)
992 LocalScope.addPrivate(LocalAddrPair.second.first,
993 LocalAddrPair.second.second);
995 (void)LocalScope.Privatize();
996 for (
const auto &VLASizePair : VLASizes)
997 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
1000 (void)LocalScope.ForceCleanup();
1003 if (!NeedWrapperFunction)
1007 WrapperF->removeFromParent();
1008 F->getParent()->getFunctionList().insertAfter(F->getIterator(), WrapperF);
1010 llvm::Align PtrAlign =
CGM.getDataLayout().getPointerABIAlignment(0);
1013 "Expected context param at position 0 for target regions");
1014 assert(RD->
getNumFields() + 1 == F->getNumOperands() &&
1015 "Argument count mismatch");
1017 for (
auto [FD, InnerParam, SlotIdx] : llvm::zip(
1019 llvm::Value *Slot = WrapperCGF.
Builder.CreateConstInBoundsGEP1_32(
1020 WrapperCGF.
IntPtrTy, WrapperContextV, SlotIdx);
1022 InnerParam.getType(), Slot, PtrAlign, InnerParam.getName());
1023 CallArgs.push_back(Val);
1028 auto InnerParam = F->arg_begin() + SlotIdx;
1029 llvm::Value *Slot = WrapperCGF.
Builder.CreateConstInBoundsGEP1_32(
1030 WrapperCGF.
IntPtrTy, WrapperContextV, SlotIdx);
1032 InnerParam->getType(), Slot, PtrAlign, InnerParam->getName());
1033 CallArgs.push_back(Val);
1035 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
1051 llvm::Value *NumElements =
emitArrayLength(ArrayTy, ElementTy, DestAddr);
1058 DestBegin, NumElements);
1063 llvm::Value *IsEmpty =
1064 Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arraycpy.isempty");
1065 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
1068 llvm::BasicBlock *EntryBB =
Builder.GetInsertBlock();
1073 llvm::PHINode *SrcElementPHI =
1074 Builder.CreatePHI(SrcBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
1075 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
1080 llvm::PHINode *DestElementPHI =
Builder.CreatePHI(
1081 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
1082 DestElementPHI->addIncoming(DestBegin, EntryBB);
1088 CopyGen(DestElementCurrent, SrcElementCurrent);
1091 llvm::Value *DestElementNext =
1093 1,
"omp.arraycpy.dest.element");
1094 llvm::Value *SrcElementNext =
1096 1,
"omp.arraycpy.src.element");
1099 Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
1100 Builder.CreateCondBr(Done, DoneBB, BodyBB);
1101 DestElementPHI->addIncoming(DestElementNext,
Builder.GetInsertBlock());
1102 SrcElementPHI->addIncoming(SrcElementNext,
Builder.GetInsertBlock());
1112 const auto *BO = dyn_cast<BinaryOperator>(
Copy);
1113 if (BO && BO->getOpcode() == BO_Assign) {
1122 DestAddr, SrcAddr, OriginalType,
1150 bool DeviceConstTarget =
getLangOpts().OpenMPIsTargetDevice &&
1152 bool FirstprivateIsLastprivate =
false;
1153 llvm::DenseMap<const VarDecl *, OpenMPLastprivateModifier> Lastprivates;
1154 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1155 for (
const auto *D :
C->varlist())
1156 Lastprivates.try_emplace(
1160 llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
1165 bool MustEmitFirstprivateCopy =
1166 CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown;
1167 for (
const auto *
C : D.getClausesOfKind<OMPFirstprivateClause>()) {
1168 const auto *IRef =
C->varlist_begin();
1169 const auto *InitsRef =
C->inits().begin();
1170 for (
const Expr *IInit :
C->private_copies()) {
1172 bool ThisFirstprivateIsLastprivate =
1173 Lastprivates.count(OrigVD->getCanonicalDecl()) > 0;
1176 if (!MustEmitFirstprivateCopy && !ThisFirstprivateIsLastprivate && FD &&
1178 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
1179 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
1186 if (DeviceConstTarget && OrigVD->getType().isConstant(
getContext()) &&
1188 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
1189 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
1194 FirstprivateIsLastprivate =
1195 FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate;
1196 if (EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()).second) {
1197 const auto *VDInit =
1216 assert(!CE &&
"Expected non-constant firstprivate.");
1223 if (
Type->isArrayType()) {
1239 RunCleanupsScope InitScope(*this);
1241 setAddrOfLocalVar(VDInit, SrcElement);
1242 EmitAnyExprToMem(Init, DestElement,
1243 Init->getType().getQualifiers(),
1245 LocalDeclMap.erase(VDInit);
1256 setAddrOfLocalVar(VDInit, OriginalAddr);
1258 LocalDeclMap.erase(VDInit);
1260 if (ThisFirstprivateIsLastprivate &&
1261 Lastprivates[OrigVD->getCanonicalDecl()] ==
1262 OMPC_LASTPRIVATE_conditional) {
1267 (*IRef)->getExprLoc());
1268 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1272 LocalDeclMap.erase(VD);
1273 setAddrOfLocalVar(VD, VDAddr);
1275 IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1277 assert(IsRegistered &&
1278 "firstprivate var already registered as private");
1286 return FirstprivateIsLastprivate && !EmittedAsFirstprivate.empty();
1294 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
1295 for (
const auto *
C : D.getClausesOfKind<OMPPrivateClause>()) {
1296 auto IRef =
C->varlist_begin();
1297 for (
const Expr *IInit :
C->private_copies()) {
1299 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
1305 assert(IsRegistered &&
"private var already registered as private");
1321 llvm::DenseSet<const VarDecl *> CopiedVars;
1322 llvm::BasicBlock *CopyBegin =
nullptr, *CopyEnd =
nullptr;
1324 auto IRef =
C->varlist_begin();
1325 auto ISrcRef =
C->source_exprs().begin();
1326 auto IDestRef =
C->destination_exprs().begin();
1327 for (
const Expr *AssignOp :
C->assignment_ops()) {
1336 getContext().getTargetInfo().isTLSSupported()) {
1338 "Copyin threadprivates should have been captured!");
1342 LocalDeclMap.erase(VD);
1346 :
CGM.GetAddrOfGlobal(VD),
1347 CGM.getTypes().ConvertTypeForMem(VD->
getType()),
1352 if (CopiedVars.size() == 1) {
1358 auto *MasterAddrInt =
Builder.CreatePtrToInt(
1360 auto *PrivateAddrInt =
Builder.CreatePtrToInt(
1363 Builder.CreateICmpNE(MasterAddrInt, PrivateAddrInt), CopyBegin,
1369 const auto *DestVD =
1390 bool HasAtLeastOneLastprivate =
false;
1392 llvm::DenseSet<const VarDecl *> SIMDLCVs;
1395 for (
const Expr *
C : LoopDirective->counters()) {
1400 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1401 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1402 HasAtLeastOneLastprivate =
true;
1405 const auto *IRef =
C->varlist_begin();
1406 const auto *IDestRef =
C->destination_exprs().begin();
1407 for (
const Expr *IInit :
C->private_copies()) {
1413 if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) {
1414 const auto *DestVD =
1419 (*IRef)->getType(),
VK_LValue, (*IRef)->getExprLoc());
1424 if (IInit && !SIMDLCVs.count(OrigVD->getCanonicalDecl())) {
1427 if (
C->getKind() == OMPC_LASTPRIVATE_conditional) {
1428 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1430 setAddrOfLocalVar(VD, VDAddr);
1436 bool IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1437 assert(IsRegistered &&
1438 "lastprivate var already registered as private");
1446 return HasAtLeastOneLastprivate;
1451 llvm::Value *IsLastIterCond) {
1460 llvm::BasicBlock *ThenBB =
nullptr;
1461 llvm::BasicBlock *DoneBB =
nullptr;
1462 if (IsLastIterCond) {
1466 llvm::any_of(D.getClausesOfKind<OMPLastprivateClause>(),
1467 [](
const OMPLastprivateClause *
C) {
1468 return C->getKind() == OMPC_LASTPRIVATE_conditional;
1470 CGM.getOpenMPRuntime().emitBarrierCall(*
this, D.getBeginLoc(),
1477 Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB);
1480 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1481 llvm::DenseMap<const VarDecl *, const Expr *> LoopCountersAndUpdates;
1482 if (
const auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) {
1483 auto IC = LoopDirective->counters().begin();
1484 for (
const Expr *F : LoopDirective->finals()) {
1488 AlreadyEmittedVars.insert(D);
1490 LoopCountersAndUpdates[D] = F;
1494 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1495 auto IRef =
C->varlist_begin();
1496 auto ISrcRef =
C->source_exprs().begin();
1497 auto IDestRef =
C->destination_exprs().begin();
1498 for (
const Expr *AssignOp :
C->assignment_ops()) {
1499 const auto *PrivateVD =
1502 const auto *CanonicalVD = PrivateVD->getCanonicalDecl();
1503 if (AlreadyEmittedVars.insert(CanonicalVD).second) {
1507 if (
const Expr *FinalExpr = LoopCountersAndUpdates.lookup(CanonicalVD))
1511 const auto *DestVD =
1515 if (
const auto *RefTy = PrivateVD->getType()->getAs<
ReferenceType>())
1517 Builder.CreateLoad(PrivateAddr),
1518 CGM.getTypes().ConvertTypeForMem(RefTy->getPointeeType()),
1519 CGM.getNaturalTypeAlignment(RefTy->getPointeeType()));
1521 if (
C->getKind() == OMPC_LASTPRIVATE_conditional)
1522 CGM.getOpenMPRuntime().emitLastprivateConditionalFinalUpdate(
1524 (*IRef)->getExprLoc());
1527 EmitOMPCopy(
Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp);
1533 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
1553 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1554 if (ForInscan != (
C->getModifier() == OMPC_REDUCTION_inscan))
1556 Shareds.append(
C->varlist_begin(),
C->varlist_end());
1557 Privates.append(
C->privates().begin(),
C->privates().end());
1558 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1559 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1560 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1561 if (
C->getModifier() == OMPC_REDUCTION_task) {
1562 Data.ReductionVars.append(
C->privates().begin(),
C->privates().end());
1563 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
1564 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
1565 Data.ReductionOps.append(
C->reduction_ops().begin(),
1566 C->reduction_ops().end());
1567 TaskLHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1568 TaskRHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1573 auto *ILHS = LHSs.begin();
1574 auto *IRHS = RHSs.begin();
1576 for (
const Expr *IRef : Shareds) {
1584 [&Emission](CodeGenFunction &CGF) {
1585 CGF.EmitAutoVarInit(Emission);
1593 assert(IsRegistered &&
"private var already registered as private");
1601 if (isaOMPArraySectionExpr &&
Type->isVariablyModifiedType()) {
1606 }
else if ((isaOMPArraySectionExpr &&
Type->isScalarType()) ||
1624 PrivateScope.
addPrivate(LHSVD, OriginalAddr);
1635 if (!
Data.ReductionVars.empty()) {
1637 Data.IsReductionWithTaskMod =
true;
1639 llvm::Value *ReductionDesc =
CGM.getOpenMPRuntime().emitTaskReductionInit(
1640 *
this, D.getBeginLoc(), TaskLHSs, TaskRHSs,
Data);
1641 const Expr *TaskRedRef =
nullptr;
1652 case OMPD_parallel_for:
1655 case OMPD_parallel_master:
1659 case OMPD_parallel_sections:
1663 case OMPD_target_parallel:
1667 case OMPD_target_parallel_for:
1671 case OMPD_distribute_parallel_for:
1675 case OMPD_teams_distribute_parallel_for:
1677 .getTaskReductionRefExpr();
1679 case OMPD_target_teams_distribute_parallel_for:
1681 .getTaskReductionRefExpr();
1689 case OMPD_parallel_for_simd:
1691 case OMPD_taskyield:
1695 case OMPD_taskgroup:
1703 case OMPD_cancellation_point:
1705 case OMPD_target_data:
1706 case OMPD_target_enter_data:
1707 case OMPD_target_exit_data:
1709 case OMPD_taskloop_simd:
1710 case OMPD_master_taskloop:
1711 case OMPD_master_taskloop_simd:
1712 case OMPD_parallel_master_taskloop:
1713 case OMPD_parallel_master_taskloop_simd:
1714 case OMPD_distribute:
1715 case OMPD_target_update:
1716 case OMPD_distribute_parallel_for_simd:
1717 case OMPD_distribute_simd:
1718 case OMPD_target_parallel_for_simd:
1719 case OMPD_target_simd:
1720 case OMPD_teams_distribute:
1721 case OMPD_teams_distribute_simd:
1722 case OMPD_teams_distribute_parallel_for_simd:
1723 case OMPD_target_teams:
1724 case OMPD_target_teams_distribute:
1725 case OMPD_target_teams_distribute_parallel_for_simd:
1726 case OMPD_target_teams_distribute_simd:
1727 case OMPD_declare_target:
1728 case OMPD_end_declare_target:
1729 case OMPD_threadprivate:
1731 case OMPD_declare_reduction:
1732 case OMPD_declare_mapper:
1733 case OMPD_declare_simd:
1735 case OMPD_declare_variant:
1736 case OMPD_begin_declare_variant:
1737 case OMPD_end_declare_variant:
1740 llvm_unreachable(
"Unexpected directive with task reductions.");
1746 false, TaskRedRef->
getType());
1759 bool HasAtLeastOneReduction =
false;
1760 bool IsReductionWithTaskMod =
false;
1761 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1763 if (
C->getModifier() == OMPC_REDUCTION_inscan)
1765 HasAtLeastOneReduction =
true;
1766 Privates.append(
C->privates().begin(),
C->privates().end());
1767 LHSExprs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1768 RHSExprs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1769 IsPrivateVarReduction.append(
C->private_var_reduction_flags().begin(),
1770 C->private_var_reduction_flags().end());
1771 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1772 IsReductionWithTaskMod =
1773 IsReductionWithTaskMod ||
C->getModifier() == OMPC_REDUCTION_task;
1775 if (HasAtLeastOneReduction) {
1777 if (IsReductionWithTaskMod) {
1778 CGM.getOpenMPRuntime().emitTaskReductionFini(
1781 bool TeamsLoopCanBeParallel =
false;
1782 if (
auto *TTLD = dyn_cast<OMPTargetTeamsGenericLoopDirective>(&D))
1783 TeamsLoopCanBeParallel = TTLD->canBeParallelFor();
1784 bool WithNowait = D.getSingleClause<OMPNowaitClause>() ||
1786 TeamsLoopCanBeParallel || ReductionKind == OMPD_simd;
1787 bool SimpleReduction = ReductionKind == OMPD_simd;
1790 CGM.getOpenMPRuntime().emitReduction(
1791 *
this, D.getEndLoc(),
Privates, LHSExprs, RHSExprs, ReductionOps,
1792 {WithNowait, SimpleReduction, IsPrivateVarReduction, ReductionKind});
1801 llvm::BasicBlock *DoneBB =
nullptr;
1802 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1803 if (
const Expr *PostUpdate =
C->getPostUpdateExpr()) {
1805 if (llvm::Value *
Cond = CondGen(CGF)) {
1826 const OMPExecutableDirective &,
1827 llvm::SmallVectorImpl<llvm::Value *> &)>
1828 CodeGenBoundParametersTy;
1836 llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> PrivateDecls;
1837 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
1838 for (
const Expr *Ref :
C->varlist()) {
1839 if (!Ref->getType()->isScalarType())
1841 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1848 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
1849 for (
const Expr *Ref :
C->varlist()) {
1850 if (!Ref->getType()->isScalarType())
1852 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1859 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
1860 for (
const Expr *Ref :
C->varlist()) {
1861 if (!Ref->getType()->isScalarType())
1863 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1874 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
1875 for (
const Expr *Ref :
C->varlist()) {
1876 if (!Ref->getType()->isScalarType())
1878 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1885 CGF, S, PrivateDecls);
1891 const CodeGenBoundParametersTy &CodeGenBoundParameters) {
1892 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
1893 llvm::Value *NumThreads =
nullptr;
1902 llvm::Function *OutlinedFn =
1909 NumThreads = CGF.
EmitScalarExpr(NumThreadsClause->getNumThreads(),
1911 Modifier = NumThreadsClause->getModifier();
1912 if (
const auto *MessageClause = S.getSingleClause<OMPMessageClause>()) {
1913 Message = MessageClause->getMessageString();
1914 MessageLoc = MessageClause->getBeginLoc();
1916 if (
const auto *SeverityClause = S.getSingleClause<OMPSeverityClause>()) {
1917 Severity = SeverityClause->getSeverityKind();
1918 SeverityLoc = SeverityClause->getBeginLoc();
1921 CGF, NumThreads, NumThreadsClause->getBeginLoc(), Modifier, Severity,
1922 SeverityLoc, Message, MessageLoc);
1924 if (
const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>()) {
1927 CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getBeginLoc());
1929 const Expr *IfCond =
nullptr;
1930 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
1931 if (
C->getNameModifier() == OMPD_unknown ||
1932 C->getNameModifier() == OMPD_parallel) {
1933 IfCond =
C->getCondition();
1938 OMPParallelScope
Scope(CGF, S);
1944 CodeGenBoundParameters(CGF, S, CapturedVars);
1947 CapturedVars, IfCond, NumThreads,
1948 Modifier, Severity, Message);
1953 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
1955 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
1957 return !((AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc ||
1958 AA->getAllocatorType() == OMPAllocateDeclAttr::OMPNullMemAlloc) &&
1959 !AA->getAllocator());
1974 CGF, S.getBeginLoc(), OMPD_unknown,
false,
1980 CodeGenFunction &CGF,
const VarDecl *VD) {
1982 auto &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1994 Size = CGF.
Builder.CreateNUWAdd(
1996 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
1997 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
2003 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
2004 assert(AA->getAllocator() &&
2005 "Expected allocator expression for non-default allocator.");
2009 if (Allocator->getType()->isIntegerTy())
2010 Allocator = CGF.
Builder.CreateIntToPtr(Allocator,
CGM.VoidPtrTy);
2011 else if (Allocator->getType()->isPointerTy())
2015 llvm::Value *
Addr = OMPBuilder.createOMPAlloc(
2018 llvm::CallInst *FreeCI =
2019 OMPBuilder.createOMPFree(CGF.
Builder,
Addr, Allocator);
2033 if (
CGM.getLangOpts().OpenMPUseTLS &&
2034 CGM.getContext().getTargetInfo().isTLSSupported())
2037 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2042 llvm::ConstantInt *Size =
CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy));
2044 llvm::Twine CacheName = Twine(
CGM.getMangledName(VD)).concat(Suffix);
2046 llvm::CallInst *ThreadPrivateCacheCall =
2047 OMPBuilder.createCachedThreadPrivate(CGF.
Builder,
Data, Size, CacheName);
2055 llvm::raw_svector_ostream OS(Buffer);
2056 StringRef Sep = FirstSeparator;
2057 for (StringRef Part : Parts) {
2061 return OS.str().str();
2069 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
2070 "." + RegionName +
".after");
2086 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
2087 "." + RegionName +
".after");
2099 if (
CGM.getLangOpts().OpenMPIRBuilder) {
2100 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2102 llvm::Value *IfCond =
nullptr;
2107 llvm::Value *NumThreads =
nullptr;
2112 ProcBindKind ProcBind = OMP_PROC_BIND_default;
2113 if (
const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>())
2114 ProcBind = ProcBindClause->getProcBindKind();
2116 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2120 auto FiniCB = [
this](InsertPointTy IP) {
2122 return llvm::Error::success();
2129 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
2130 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
2141 auto BodyGenCB = [&,
this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
2144 *
this, ParallelRegionBodyStmt, AllocIP, CodeGenIP,
"parallel");
2145 return llvm::Error::success();
2150 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
2152 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2153 cantFail(OMPBuilder.createParallel(
2154 Builder, AllocaIP, {}, BodyGenCB, PrivCB, FiniCB,
2155 IfCond, NumThreads, ProcBind, S.hasCancel()));
2169 CGF.
EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt());
2178 [](CodeGenFunction &) {
return nullptr; });
2190class OMPTransformDirectiveScopeRAII {
2191 OMPLoopScope *
Scope =
nullptr;
2195 OMPTransformDirectiveScopeRAII(
const OMPTransformDirectiveScopeRAII &) =
2197 OMPTransformDirectiveScopeRAII &
2198 operator=(
const OMPTransformDirectiveScopeRAII &) =
delete;
2202 if (
const auto *Dir = dyn_cast<OMPLoopBasedDirective>(S)) {
2203 Scope =
new OMPLoopScope(CGF, *Dir);
2206 }
else if (
const auto *Dir =
2207 dyn_cast<OMPCanonicalLoopSequenceTransformationDirective>(
2212 Scope =
new OMPLoopScope(CGF, *Dir);
2217 ~OMPTransformDirectiveScopeRAII() {
2228 int MaxLevel,
int Level = 0) {
2229 assert(Level < MaxLevel &&
"Too deep lookup during loop body codegen.");
2231 if (
const auto *CS = dyn_cast<CompoundStmt>(SimplifiedS)) {
2234 "LLVM IR generation of compound statement ('{}')");
2238 for (
const Stmt *CurStmt : CS->body())
2239 emitBody(CGF, CurStmt, NextLoop, MaxLevel, Level);
2242 if (SimplifiedS == NextLoop) {
2243 if (
auto *Dir = dyn_cast<OMPLoopTransformationDirective>(SimplifiedS))
2244 SimplifiedS = Dir->getTransformedStmt();
2245 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(SimplifiedS))
2246 SimplifiedS = CanonLoop->getLoopStmt();
2247 if (
const auto *For = dyn_cast<ForStmt>(SimplifiedS)) {
2251 "Expected canonical for loop or range-based for loop.");
2253 CGF.
EmitStmt(CXXFor->getLoopVarStmt());
2254 S = CXXFor->getBody();
2256 if (Level + 1 < MaxLevel) {
2257 NextLoop = OMPLoopDirective::tryToFindNextInnerLoop(
2259 emitBody(CGF, S, NextLoop, MaxLevel, Level + 1);
2270 for (
const Expr *UE : D.updates())
2277 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2278 for (
const Expr *UE :
C->updates())
2285 BreakContinueStack.push_back(BreakContinue(D,
LoopExit, Continue));
2286 for (
const Expr *E : D.finals_conditions()) {
2299 bool IsInscanRegion = InscanScope.
Privatize();
2300 if (IsInscanRegion) {
2310 if (EKind != OMPD_simd && !
getLangOpts().OpenMPSimd)
2319 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
2322 OMPLoopBasedDirective::tryToFindNextInnerLoop(
2324 D.getLoopsNumber());
2332 BreakContinueStack.pop_back();
2343 std::unique_ptr<CodeGenFunction::CGCapturedStmtInfo> CSI =
2344 std::make_unique<CodeGenFunction::CGCapturedStmtInfo>(*S);
2348 return {F, CapStruct.getPointer(
ParentCGF)};
2352static llvm::CallInst *
2357 EffectiveArgs.reserve(Args.size() + 1);
2358 llvm::append_range(EffectiveArgs, Args);
2359 EffectiveArgs.push_back(Cap.second);
2364llvm::CanonicalLoopInfo *
2366 assert(Depth == 1 &&
"Nested loops with OpenMPIRBuilder not yet implemented");
2392 const Stmt *SyntacticalLoop = S->getLoopStmt();
2403 const Stmt *BodyStmt;
2404 if (
const auto *For = dyn_cast<ForStmt>(SyntacticalLoop)) {
2405 if (
const Stmt *InitStmt = For->getInit())
2407 BodyStmt = For->getBody();
2408 }
else if (
const auto *RangeFor =
2409 dyn_cast<CXXForRangeStmt>(SyntacticalLoop)) {
2410 if (
const DeclStmt *RangeStmt = RangeFor->getRangeStmt())
2412 if (
const DeclStmt *BeginStmt = RangeFor->getBeginStmt())
2414 if (
const DeclStmt *EndStmt = RangeFor->getEndStmt())
2416 if (
const DeclStmt *LoopVarStmt = RangeFor->getLoopVarStmt())
2418 BodyStmt = RangeFor->getBody();
2420 llvm_unreachable(
"Expected for-stmt or range-based for-stmt");
2423 const CapturedStmt *DistanceFunc = S->getDistanceFunc();
2436 llvm::Value *DistVal =
Builder.CreateLoad(CountAddr,
".count");
2439 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2440 auto BodyGen = [&,
this](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP,
2441 llvm::Value *IndVar) {
2446 const DeclRefExpr *LoopVarRef = S->getLoopVarRef();
2454 return llvm::Error::success();
2457 llvm::CanonicalLoopInfo *
CL =
2458 cantFail(OMPBuilder.createCanonicalLoop(
Builder, BodyGen, DistVal));
2470 const Expr *IncExpr,
2471 const llvm::function_ref<
void(CodeGenFunction &)> BodyGen,
2472 const llvm::function_ref<
void(CodeGenFunction &)> PostIncGen) {
2482 const CapturedStmt *ICS = OMPED.getInnermostCapturedStmt();
2496 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
2497 if (RequiresCleanup)
2504 if (ExitBlock !=
LoopExit.getBlock()) {
2514 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
2522 BreakContinueStack.pop_back();
2533 bool HasLinears =
false;
2534 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2538 if (
const auto *Ref =
2557 if (
const auto *CS = cast_or_null<BinaryOperator>(
C->getCalcStep()))
2569 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2572 llvm::BasicBlock *DoneBB =
nullptr;
2574 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2575 auto IC =
C->varlist_begin();
2576 for (
const Expr *F :
C->finals()) {
2578 if (llvm::Value *
Cond = CondGen(*
this)) {
2590 (*IC)->getType(),
VK_LValue, (*IC)->getExprLoc());
2598 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
2610 llvm::APInt ClauseAlignment(64, 0);
2611 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
2614 ClauseAlignment = AlignmentCI->getValue();
2616 for (
const Expr *E : Clause->varlist()) {
2617 llvm::APInt Alignment(ClauseAlignment);
2618 if (Alignment == 0) {
2625 E->getType()->getPointeeType()))
2628 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2629 "alignment is not power of 2");
2630 if (Alignment != 0) {
2644 auto I = S.private_counters().begin();
2645 for (
const Expr *E : S.counters()) {
2651 LocalDeclMap.erase(PrivateVD);
2657 E->getType(),
VK_LValue, E->getExprLoc());
2665 for (
const auto *
C : S.getClausesOfKind<OMPOrderedClause>()) {
2666 if (!
C->getNumForLoops())
2668 for (
unsigned I = S.getLoopsNumber(), E =
C->getLoopNumIterations().size();
2674 if (DRE->refersToEnclosingVariableOrCapture()) {
2683 const Expr *
Cond, llvm::BasicBlock *TrueBlock,
2684 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
2692 for (
const Expr *I : S.inits()) {
2699 for (
const Expr *E : S.dependent_counters()) {
2702 assert(!E->getType().getNonReferenceType()->isRecordType() &&
2703 "dependent counter must not be an iterator.");
2707 (void)PreCondVars.
setVarAddr(CGF, VD, CounterAddr);
2709 (void)PreCondVars.
apply(CGF);
2710 for (
const Expr *E : S.dependent_inits()) {
2724 llvm::DenseSet<const VarDecl *> SIMDLCVs;
2728 for (
const Expr *
C : LoopDirective->counters()) {
2733 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2734 auto CurPrivate =
C->privates().begin();
2735 for (
const Expr *E :
C->varlist()) {
2737 const auto *PrivateVD =
2744 assert(IsRegistered &&
"linear var already registered as private");
2832 if (
const auto *CS = dyn_cast<CapturedStmt>(S))
2850 if (HasOrderedDirective)
2858 const Stmt *AssociatedStmt = D.getAssociatedStmt();
2862 if (
C->getKind() == OMPC_ORDER_concurrent)
2865 if ((EKind == OMPD_simd ||
2867 llvm::any_of(D.getClausesOfKind<OMPReductionClause>(),
2868 [](
const OMPReductionClause *
C) {
2869 return C->getModifier() == OMPC_REDUCTION_inscan;
2877 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2880 llvm::BasicBlock *DoneBB =
nullptr;
2881 auto IC = D.counters().begin();
2882 auto IPC = D.private_counters().begin();
2883 for (
const Expr *F : D.finals()) {
2886 const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
2888 OrigVD->hasGlobalStorage() || CED) {
2890 if (llvm::Value *
Cond = CondGen(*
this)) {
2938 auto &&ThenGen = [&S, &SimdInitGen, &BodyCodeGen](
CodeGenFunction &CGF,
2952 const Expr *IfCond =
nullptr;
2955 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
2957 (
C->getNameModifier() == OMPD_unknown ||
2958 C->getNameModifier() == OMPD_simd)) {
2959 IfCond =
C->getCondition();
2975 OMPLoopScope PreInitScope(CGF, S);
2997 llvm::BasicBlock *ContBlock =
nullptr;
3004 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
3011 const Expr *IVExpr = S.getIterationVariable();
3019 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
3034 CGF, S, CGF.
EmitLValue(S.getIterationVariable()));
3049 emitOMPLoopBodyWithStopPoint(CGF, S,
3050 CodeGenFunction::JumpDest());
3056 if (HasLastprivateClause)
3085 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(S.getRawStmt())) {
3086 if (
const Stmt *SyntacticalLoop = CanonLoop->getLoopStmt()) {
3087 for (
const Stmt *SubStmt : SyntacticalLoop->
children()) {
3090 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(SubStmt)) {
3105static llvm::MapVector<llvm::Value *, llvm::Value *>
3107 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars;
3109 llvm::APInt ClauseAlignment(64, 0);
3110 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
3113 ClauseAlignment = AlignmentCI->getValue();
3115 for (
const Expr *E : Clause->varlist()) {
3116 llvm::APInt Alignment(ClauseAlignment);
3117 if (Alignment == 0) {
3124 E->getType()->getPointeeType()))
3127 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
3128 "alignment is not power of 2");
3130 AlignedVars[PtrValue] = CGF.
Builder.getInt64(Alignment.getSExtValue());
3140 bool UseOMPIRBuilder =
3142 if (UseOMPIRBuilder) {
3146 if (UseOMPIRBuilder) {
3147 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars =
3150 const Stmt *Inner = S.getRawStmt();
3151 llvm::CanonicalLoopInfo *CLI =
3152 CGF.EmitOMPCollapsedCanonicalLoopNest(Inner, 1);
3154 llvm::OpenMPIRBuilder &OMPBuilder =
3157 llvm::ConstantInt *Simdlen =
nullptr;
3164 llvm::ConstantInt *Safelen =
nullptr;
3171 llvm::omp::OrderKind Order = llvm::omp::OrderKind::OMP_ORDER_unknown;
3173 if (
C->getKind() == OpenMPOrderClauseKind::OMPC_ORDER_concurrent) {
3174 Order = llvm::omp::OrderKind::OMP_ORDER_concurrent;
3179 OMPBuilder.applySimd(CLI, AlignedVars,
3180 nullptr, Order, Simdlen, Safelen);
3187 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
3202 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
3215 OMPTransformDirectiveScopeRAII TileScope(*
this, &S);
3221 OMPTransformDirectiveScopeRAII StripeScope(*
this, &S);
3227 OMPTransformDirectiveScopeRAII ReverseScope(*
this, &S);
3233 OMPTransformDirectiveScopeRAII SplitScope(*
this, &S);
3240 OMPTransformDirectiveScopeRAII InterchangeScope(*
this, &S);
3246 OMPTransformDirectiveScopeRAII FuseScope(*
this, &S);
3251 bool UseOMPIRBuilder =
CGM.getLangOpts().OpenMPIRBuilder;
3253 if (UseOMPIRBuilder) {
3255 const Stmt *Inner = S.getRawStmt();
3263 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
3266 llvm::CanonicalLoopInfo *UnrolledCLI =
nullptr;
3270 OMPBuilder.unrollLoopFull(DL, CLI);
3272 uint64_t Factor = 0;
3273 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3274 Factor = FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
3275 assert(Factor >= 1 &&
"Only positive factors are valid");
3277 OMPBuilder.unrollLoopPartial(DL, CLI, Factor,
3278 NeedsUnrolledCLI ? &UnrolledCLI :
nullptr);
3280 OMPBuilder.unrollLoopHeuristic(DL, CLI);
3283 assert((!NeedsUnrolledCLI || UnrolledCLI) &&
3284 "NeedsUnrolledCLI implies UnrolledCLI to be set");
3301 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3303 FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
3304 assert(Factor >= 1 &&
"Only positive factors are valid");
3312void CodeGenFunction::EmitOMPOuterLoop(
3315 const CodeGenFunction::OMPLoopArguments &LoopArgs,
3320 const Expr *IVExpr = S.getIterationVariable();
3334 llvm::Value *BoolCondVal =
nullptr;
3335 if (!DynamicOrOrdered) {
3346 RT.
emitForNext(*
this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL,
3347 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST);
3352 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
3357 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
3358 if (ExitBlock !=
LoopExit.getBlock()) {
3366 if (DynamicOrOrdered)
3371 BreakContinueStack.push_back(BreakContinue(S, LoopExit, Continue));
3376 [&S, IsMonotonic, EKind](CodeGenFunction &CGF, PrePostActionTy &) {
3381 if (
const auto *
C = S.getSingleClause<OMPOrderClause>())
3382 if (
C->getKind() == OMPC_ORDER_concurrent)
3388 [&S, &LoopArgs, LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered,
3389 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
3390 SourceLocation Loc = S.getBeginLoc();
3396 CGF.EmitOMPInnerLoop(
3398 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
3399 CodeGenLoop(CGF, S, LoopExit);
3401 [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) {
3402 CodeGenOrdered(CGF, Loc, IVSize, IVSigned);
3407 BreakContinueStack.pop_back();
3408 if (!DynamicOrOrdered) {
3421 auto &&CodeGen = [DynamicOrOrdered, &S, &LoopArgs](CodeGenFunction &CGF) {
3422 if (!DynamicOrOrdered)
3423 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
3426 OMPCancelStack.emitExit(*
this, EKind, CodeGen);
3429void CodeGenFunction::EmitOMPForOuterLoop(
3430 const OpenMPScheduleTy &ScheduleKind,
bool IsMonotonic,
3432 const OMPLoopArguments &LoopArgs,
3434 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3440 LoopArgs.Chunk !=
nullptr)) &&
3441 "static non-chunked schedule does not need outer loop");
3495 const Expr *IVExpr = S.getIterationVariable();
3499 if (DynamicOrOrdered) {
3500 const std::pair<llvm::Value *, llvm::Value *> DispatchBounds =
3501 CGDispatchBounds(*
this, S, LoopArgs.LB, LoopArgs.UB);
3502 llvm::Value *LBVal = DispatchBounds.first;
3503 llvm::Value *UBVal = DispatchBounds.second;
3504 CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal,
3507 IVSigned, Ordered, DipatchRTInputValues);
3509 CGOpenMPRuntime::StaticRTInput StaticInit(
3510 IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
3511 LoopArgs.ST, LoopArgs.Chunk);
3517 auto &&CodeGenOrdered = [Ordered](CodeGenFunction &CGF, SourceLocation Loc,
3518 const unsigned IVSize,
3519 const bool IVSigned) {
3526 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST,
3527 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB);
3528 OuterLoopArgs.IncExpr = S.getInc();
3529 OuterLoopArgs.Init = S.getInit();
3530 OuterLoopArgs.Cond = S.getCond();
3531 OuterLoopArgs.NextLB = S.getNextLowerBound();
3532 OuterLoopArgs.NextUB = S.getNextUpperBound();
3533 OuterLoopArgs.DKind = LoopArgs.DKind;
3534 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
3536 if (DynamicOrOrdered) {
3542 const unsigned IVSize,
const bool IVSigned) {}
3544void CodeGenFunction::EmitOMPDistributeOuterLoop(
3549 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3556 const Expr *IVExpr = S.getIterationVariable();
3561 CGOpenMPRuntime::StaticRTInput StaticInit(
3562 IVSize, IVSigned,
false, LoopArgs.IL, LoopArgs.LB,
3563 LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
3570 IncExpr = S.getDistInc();
3572 IncExpr = S.getInc();
3577 OMPLoopArguments OuterLoopArgs;
3578 OuterLoopArgs.LB = LoopArgs.LB;
3579 OuterLoopArgs.UB = LoopArgs.UB;
3580 OuterLoopArgs.ST = LoopArgs.ST;
3581 OuterLoopArgs.IL = LoopArgs.IL;
3582 OuterLoopArgs.Chunk = LoopArgs.Chunk;
3584 ? S.getCombinedEnsureUpperBound()
3585 : S.getEnsureUpperBound();
3586 OuterLoopArgs.IncExpr = IncExpr;
3588 ? S.getCombinedInit()
3591 ? S.getCombinedCond()
3594 ? S.getCombinedNextLowerBound()
3595 : S.getNextLowerBound();
3597 ? S.getCombinedNextUpperBound()
3598 : S.getNextUpperBound();
3599 OuterLoopArgs.DKind = OMPD_distribute;
3601 EmitOMPOuterLoop(
false,
false, S,
3602 LoopScope, OuterLoopArgs, CodeGenLoopContent,
3606static std::pair<LValue, LValue>
3621 LValue PrevLB = CGF.
EmitLValue(LS.getPrevLowerBoundVariable());
3622 LValue PrevUB = CGF.
EmitLValue(LS.getPrevUpperBoundVariable());
3624 PrevLB, LS.getPrevLowerBoundVariable()->getExprLoc());
3626 PrevLBVal, LS.getPrevLowerBoundVariable()->getType(),
3627 LS.getIterationVariable()->getType(),
3628 LS.getPrevLowerBoundVariable()->getExprLoc());
3630 PrevUB, LS.getPrevUpperBoundVariable()->getExprLoc());
3632 PrevUBVal, LS.getPrevUpperBoundVariable()->getType(),
3633 LS.getIterationVariable()->getType(),
3634 LS.getPrevUpperBoundVariable()->getExprLoc());
3649static std::pair<llvm::Value *, llvm::Value *>
3654 const Expr *IVExpr = LS.getIterationVariable();
3660 llvm::Value *LBVal =
3662 llvm::Value *UBVal =
3664 return {LBVal, UBVal};
3673 llvm::Value *LBCast = CGF.
Builder.CreateIntCast(
3675 CapturedVars.push_back(LBCast);
3679 llvm::Value *UBCast = CGF.
Builder.CreateIntCast(
3681 CapturedVars.push_back(UBCast);
3692 bool HasCancel =
false;
3694 if (
const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
3695 HasCancel = D->hasCancel();
3696 else if (
const auto *D = dyn_cast<OMPDistributeParallelForDirective>(&S))
3697 HasCancel = D->hasCancel();
3698 else if (
const auto *D =
3699 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S))
3700 HasCancel = D->hasCancel();
3710 CGInlinedWorksharingLoop,
3720 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3721 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3730 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3731 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3739 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
3740 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
3750 llvm::Constant *
Addr;
3752 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
3754 assert(Fn &&
Addr &&
"Target device function emission failed.");
3766struct ScheduleKindModifiersTy {
3773 : Kind(Kind), M1(M1), M2(M2) {}
3789 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
3797 bool HasLastprivateClause;
3800 OMPLoopScope PreInitScope(*
this, S);
3805 llvm::BasicBlock *ContBlock =
nullptr;
3812 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
3819 bool Ordered =
false;
3820 if (
const auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) {
3821 if (OrderedClause->getNumForLoops())
3831 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*
this, S);
3832 LValue LB = Bounds.first;
3833 LValue UB = Bounds.second;
3847 CGM.getOpenMPRuntime().emitBarrierCall(
3848 *
this, S.getBeginLoc(), OMPD_unknown,
false,
3853 *
this, S,
EmitLValue(S.getIterationVariable()));
3860 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
3863 const Expr *ChunkExpr =
nullptr;
3865 if (
const auto *
C = S.getSingleClause<OMPScheduleClause>()) {
3866 ScheduleKind.
Schedule =
C->getScheduleKind();
3867 ScheduleKind.
M1 =
C->getFirstScheduleModifier();
3868 ScheduleKind.
M2 =
C->getSecondScheduleModifier();
3869 ChunkExpr =
C->getChunkSize();
3872 CGM.getOpenMPRuntime().getDefaultScheduleAndChunk(
3873 *
this, S, ScheduleKind.
Schedule, ChunkExpr);
3875 bool HasChunkSizeOne =
false;
3876 llvm::Value *Chunk =
nullptr;
3880 S.getIterationVariable()->getType(),
3884 llvm::APSInt EvaluatedChunk =
Result.Val.getInt();
3885 HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
3894 bool StaticChunkedOne =
3896 Chunk !=
nullptr) &&
3906 (ScheduleKind.
Schedule == OMPC_SCHEDULE_static &&
3907 !(ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
3908 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)) ||
3909 ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
3910 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
3912 Chunk !=
nullptr) ||
3913 StaticChunkedOne) &&
3923 if (
C->getKind() == OMPC_ORDER_concurrent)
3927 [IVSize, IVSigned, Ordered, IL, LB, UB, ST, StaticChunkedOne, Chunk,
3936 IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(),
3937 UB.getAddress(), ST.getAddress(),
3938 StaticChunkedOne ? Chunk :
nullptr);
3940 CGF, S.getBeginLoc(), EKind, ScheduleKind, StaticInit);
3942 if (!StaticChunkedOne)
3961 StaticChunkedOne ? S.getCombinedParForInDistCond()
3963 StaticChunkedOne ? S.getDistInc() : S.getInc(),
3964 [&S,
LoopExit](CodeGenFunction &CGF) {
3965 emitOMPLoopBodyWithStopPoint(CGF, S, LoopExit);
3967 [](CodeGenFunction &) {});
3971 auto &&
CodeGen = [&S](CodeGenFunction &CGF) {
3975 OMPCancelStack.emitExit(*
this, EKind,
CodeGen);
3982 LoopArguments.DKind = OMPD_for;
3983 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
3984 LoopArguments, CGDispatchBounds);
3988 return CGF.
Builder.CreateIsNotNull(
3994 ? OMPD_parallel_for_simd
3998 *
this, S, [IL, &S](CodeGenFunction &CGF) {
3999 return CGF.
Builder.CreateIsNotNull(
4003 if (HasLastprivateClause)
4009 return CGF.
Builder.CreateIsNotNull(
4020 return HasLastprivateClause;
4026static std::pair<LValue, LValue>
4040static std::pair<llvm::Value *, llvm::Value *>
4044 const Expr *IVExpr = LS.getIterationVariable();
4046 llvm::Value *LBVal = CGF.
Builder.getIntN(IVSize, 0);
4048 return {LBVal, UBVal};
4060 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
4061 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4062 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4067 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4068 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4069 "Only inscan reductions are expected.");
4070 Shareds.append(
C->varlist_begin(),
C->varlist_end());
4071 Privates.append(
C->privates().begin(),
C->privates().end());
4072 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
4073 CopyArrayTemps.append(
C->copy_array_temps().begin(),
4074 C->copy_array_temps().end());
4082 auto *ITA = CopyArrayTemps.begin();
4087 if (PrivateVD->getType()->isVariablyModifiedType()) {
4112 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
4113 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4114 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4121 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4122 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4123 "Only inscan reductions are expected.");
4124 Shareds.append(
C->varlist_begin(),
C->varlist_end());
4125 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
4126 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
4127 Privates.append(
C->privates().begin(),
C->privates().end());
4128 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
4129 CopyArrayElems.append(
C->copy_array_elems().begin(),
4130 C->copy_array_elems().end());
4134 llvm::Value *OMPLast = CGF.
Builder.CreateNSWSub(
4135 OMPScanNumIterations,
4136 llvm::ConstantInt::get(CGF.
SizeTy, 1,
false));
4137 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
4139 const Expr *OrigExpr = Shareds[I];
4140 const Expr *CopyArrayElem = CopyArrayElems[I];
4147 LValue SrcLVal = CGF.
EmitLValue(CopyArrayElem);
4149 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
4179 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4180 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4186 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4187 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4188 "Only inscan reductions are expected.");
4189 Privates.append(
C->privates().begin(),
C->privates().end());
4190 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
4191 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
4192 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
4193 CopyArrayElems.append(
C->copy_array_elems().begin(),
4194 C->copy_array_elems().end());
4209 auto &&
CodeGen = [&S, OMPScanNumIterations, &LHSs, &RHSs, &CopyArrayElems,
4216 llvm::BasicBlock *InputBB = CGF.Builder.GetInsertBlock();
4217 llvm::BasicBlock *LoopBB = CGF.createBasicBlock(
"omp.outer.log.scan.body");
4218 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
"omp.outer.log.scan.exit");
4220 CGF.CGM.getIntrinsic(llvm::Intrinsic::log2, CGF.DoubleTy);
4222 CGF.Builder.CreateUIToFP(OMPScanNumIterations, CGF.DoubleTy);
4223 llvm::Value *LogVal = CGF.EmitNounwindRuntimeCall(F, Arg);
4224 F = CGF.CGM.getIntrinsic(llvm::Intrinsic::ceil, CGF.DoubleTy);
4225 LogVal = CGF.EmitNounwindRuntimeCall(F, LogVal);
4226 LogVal = CGF.Builder.CreateFPToUI(LogVal, CGF.IntTy);
4227 llvm::Value *NMin1 = CGF.Builder.CreateNUWSub(
4228 OMPScanNumIterations, llvm::ConstantInt::get(CGF.SizeTy, 1));
4230 CGF.EmitBlock(LoopBB);
4231 auto *Counter = CGF.Builder.CreatePHI(CGF.IntTy, 2);
4233 auto *Pow2K = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
4234 Counter->addIncoming(llvm::ConstantInt::get(CGF.IntTy, 0), InputBB);
4235 Pow2K->addIncoming(llvm::ConstantInt::get(CGF.SizeTy, 1), InputBB);
4238 llvm::BasicBlock *InnerLoopBB =
4239 CGF.createBasicBlock(
"omp.inner.log.scan.body");
4240 llvm::BasicBlock *InnerExitBB =
4241 CGF.createBasicBlock(
"omp.inner.log.scan.exit");
4242 llvm::Value *CmpI = CGF.Builder.CreateICmpUGE(NMin1, Pow2K);
4243 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4244 CGF.EmitBlock(InnerLoopBB);
4245 auto *IVal = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
4246 IVal->addIncoming(NMin1, LoopBB);
4249 auto *ILHS = LHSs.begin();
4250 auto *IRHS = RHSs.begin();
4251 for (
const Expr *CopyArrayElem : CopyArrayElems) {
4261 LHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4266 llvm::Value *OffsetIVal = CGF.Builder.CreateNUWSub(IVal, Pow2K);
4272 RHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4279 CGF.CGM.getOpenMPRuntime().emitReduction(
4280 CGF, S.getEndLoc(),
Privates, LHSs, RHSs, ReductionOps,
4284 llvm::Value *NextIVal =
4285 CGF.Builder.CreateNUWSub(IVal, llvm::ConstantInt::get(CGF.SizeTy, 1));
4286 IVal->addIncoming(NextIVal, CGF.Builder.GetInsertBlock());
4287 CmpI = CGF.Builder.CreateICmpUGE(NextIVal, Pow2K);
4288 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4289 CGF.EmitBlock(InnerExitBB);
4291 CGF.Builder.CreateNUWAdd(Counter, llvm::ConstantInt::get(CGF.IntTy, 1));
4292 Counter->addIncoming(
Next, CGF.Builder.GetInsertBlock());
4294 llvm::Value *NextPow2K =
4295 CGF.Builder.CreateShl(Pow2K, 1,
"",
true);
4296 Pow2K->addIncoming(NextPow2K, CGF.Builder.GetInsertBlock());
4297 llvm::Value *
Cmp = CGF.Builder.CreateICmpNE(
Next, LogVal);
4298 CGF.Builder.CreateCondBr(
Cmp, LoopBB, ExitBB);
4300 CGF.EmitBlock(ExitBB);
4306 CGF, S.getBeginLoc(), OMPD_unknown,
false,
4309 RegionCodeGenTy RCG(CodeGen);
4320 bool HasLastprivates;
4322 if (llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4323 [](
const OMPReductionClause *
C) {
4324 return C->getModifier() == OMPC_REDUCTION_inscan;
4328 OMPLoopScope LoopScope(CGF, S);
4331 const auto &&FirstGen = [&S, HasCancel, EKind](
CodeGenFunction &CGF) {
4340 const auto &&SecondGen = [&S, HasCancel, EKind,
4358 return HasLastprivates;
4371 if (
auto *SC = dyn_cast<OMPScheduleClause>(
C)) {
4376 switch (SC->getScheduleKind()) {
4377 case OMPC_SCHEDULE_auto:
4378 case OMPC_SCHEDULE_dynamic:
4379 case OMPC_SCHEDULE_runtime:
4380 case OMPC_SCHEDULE_guided:
4381 case OMPC_SCHEDULE_static:
4394static llvm::omp::ScheduleKind
4396 switch (ScheduleClauseKind) {
4398 return llvm::omp::OMP_SCHEDULE_Default;
4399 case OMPC_SCHEDULE_auto:
4400 return llvm::omp::OMP_SCHEDULE_Auto;
4401 case OMPC_SCHEDULE_dynamic:
4402 return llvm::omp::OMP_SCHEDULE_Dynamic;
4403 case OMPC_SCHEDULE_guided:
4404 return llvm::omp::OMP_SCHEDULE_Guided;
4405 case OMPC_SCHEDULE_runtime:
4406 return llvm::omp::OMP_SCHEDULE_Runtime;
4407 case OMPC_SCHEDULE_static:
4408 return llvm::omp::OMP_SCHEDULE_Static;
4410 llvm_unreachable(
"Unhandled schedule kind");
4417 bool HasLastprivates =
false;
4420 auto &&
CodeGen = [&S, &
CGM, HasCancel, &HasLastprivates,
4423 if (UseOMPIRBuilder) {
4424 bool NeedsBarrier = !S.getSingleClause<OMPNowaitClause>();
4426 llvm::omp::ScheduleKind SchedKind = llvm::omp::OMP_SCHEDULE_Default;
4427 llvm::Value *ChunkSize =
nullptr;
4428 if (
auto *SchedClause = S.getSingleClause<OMPScheduleClause>()) {
4431 if (
const Expr *ChunkSizeExpr = SchedClause->getChunkSize())
4436 const Stmt *Inner = S.getRawStmt();
4437 llvm::CanonicalLoopInfo *CLI =
4440 llvm::OpenMPIRBuilder &OMPBuilder =
4442 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4444 cantFail(OMPBuilder.applyWorkshareLoop(
4445 CGF.
Builder.getCurrentDebugLocation(), CLI, AllocaIP, NeedsBarrier,
4446 SchedKind, ChunkSize,
false,
4457 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
4462 if (!UseOMPIRBuilder) {
4464 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4476 bool HasLastprivates =
false;
4477 auto &&
CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
4484 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4485 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
4489 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4490 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_for);
4497 llvm::Value *
Init =
nullptr) {
4504void CodeGenFunction::EmitSections(
const OMPExecutableDirective &S) {
4505 const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4506 const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt);
4507 bool HasLastprivates =
false;
4509 auto &&CodeGen = [&S, CapturedStmt, CS, EKind,
4510 &HasLastprivates](CodeGenFunction &CGF, PrePostActionTy &) {
4511 const ASTContext &
C = CGF.getContext();
4512 QualType KmpInt32Ty =
4513 C.getIntTypeForBitwidth(32, 1);
4516 CGF.Builder.getInt32(0));
4517 llvm::ConstantInt *GlobalUBVal = CS !=
nullptr
4518 ? CGF.Builder.getInt32(CS->size() - 1)
4519 : CGF.Builder.getInt32(0);
4523 CGF.Builder.getInt32(1));
4525 CGF.Builder.getInt32(0));
4528 OpaqueValueExpr IVRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4529 CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
4530 OpaqueValueExpr UBRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4531 CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
4535 S.getBeginLoc(), FPOptionsOverride());
4539 S.getBeginLoc(),
true, FPOptionsOverride());
4540 auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
4552 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".omp.sections.exit");
4553 llvm::SwitchInst *SwitchStmt =
4554 CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.
getBeginLoc()),
4555 ExitBB, CS ==
nullptr ? 1 : CS->size());
4557 unsigned CaseNumber = 0;
4558 for (
const Stmt *SubStmt : CS->
children()) {
4559 auto CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4560 CGF.EmitBlock(CaseBB);
4561 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
4562 CGF.EmitStmt(SubStmt);
4563 CGF.EmitBranch(ExitBB);
4567 llvm::BasicBlock *CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4568 CGF.EmitBlock(CaseBB);
4569 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
4570 CGF.EmitStmt(CapturedStmt);
4571 CGF.EmitBranch(ExitBB);
4573 CGF.EmitBlock(ExitBB,
true);
4576 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
4577 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
4581 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
4585 CGF.EmitOMPPrivateClause(S, LoopScope);
4586 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(CGF, S, IV);
4587 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
4588 CGF.EmitOMPReductionClauseInit(S, LoopScope);
4589 (void)LoopScope.Privatize();
4591 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
4594 OpenMPScheduleTy ScheduleKind;
4595 ScheduleKind.
Schedule = OMPC_SCHEDULE_static;
4596 CGOpenMPRuntime::StaticRTInput StaticInit(
4597 32,
true,
false, IL.getAddress(),
4598 LB.getAddress(), UB.getAddress(), ST.getAddress());
4599 CGF.CGM.getOpenMPRuntime().emitForStaticInit(CGF, S.
getBeginLoc(), EKind,
4600 ScheduleKind, StaticInit);
4602 llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.
getBeginLoc());
4603 llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
4604 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
4605 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
4607 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.
getBeginLoc()), IV);
4609 CGF.EmitOMPInnerLoop(S,
false,
Cond, Inc, BodyGen,
4610 [](CodeGenFunction &) {});
4612 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
4613 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.
getEndLoc(),
4616 CGF.OMPCancelStack.emitExit(CGF, EKind, CodeGen);
4617 CGF.EmitOMPReductionClauseFinal(S, OMPD_parallel);
4620 return CGF.
Builder.CreateIsNotNull(
4625 if (HasLastprivates)
4632 bool HasCancel =
false;
4633 if (
auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
4634 HasCancel = OSD->hasCancel();
4635 else if (
auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
4636 HasCancel = OPSD->hasCancel();
4638 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_sections, CodeGen,
4643 if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) {
4661 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4666 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4667 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_scope,
CodeGen);
4670 if (!S.getSingleClause<OMPNowaitClause>()) {
4671 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_scope);
4678 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4679 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4680 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4681 using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
4683 auto FiniCB = [](InsertPointTy IP) {
4686 return llvm::Error::success();
4689 const CapturedStmt *ICS = S.getInnermostCapturedStmt();
4695 auto SectionCB = [
this, SubStmt](
4696 InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4699 CodeGenIP,
"section");
4700 return llvm::Error::success();
4702 SectionCBVector.push_back(SectionCB);
4706 [
this,
CapturedStmt](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4710 return llvm::Error::success();
4712 SectionCBVector.push_back(SectionCB);
4719 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
4720 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
4730 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4732 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4733 cantFail(OMPBuilder.createSections(
4734 Builder, AllocaIP, SectionCBVector, PrivCB, FiniCB, S.hasCancel(),
4735 S.getSingleClause<OMPNowaitClause>()));
4742 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4746 if (!S.getSingleClause<OMPNowaitClause>()) {
4747 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(),
4755 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4756 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4757 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4759 const Stmt *SectionRegionBodyStmt = S.getAssociatedStmt();
4760 auto FiniCB = [
this](InsertPointTy IP) {
4762 return llvm::Error::success();
4765 auto BodyGenCB = [SectionRegionBodyStmt,
4766 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4769 *
this, SectionRegionBodyStmt, AllocIP, CodeGenIP,
"section");
4770 return llvm::Error::success();
4775 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4776 cantFail(OMPBuilder.createSection(
Builder, BodyGenCB, FiniCB));
4796 CopyprivateVars.append(
C->varlist_begin(),
C->varlist_end());
4797 DestExprs.append(
C->destination_exprs().begin(),
4798 C->destination_exprs().end());
4799 SrcExprs.append(
C->source_exprs().begin(),
C->source_exprs().end());
4800 AssignmentOps.append(
C->assignment_ops().begin(),
4801 C->assignment_ops().end());
4810 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4815 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4816 CGM.getOpenMPRuntime().emitSingleRegion(*
this,
CodeGen, S.getBeginLoc(),
4817 CopyprivateVars, DestExprs,
4818 SrcExprs, AssignmentOps);
4822 if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) {
4823 CGM.getOpenMPRuntime().emitBarrierCall(
4824 *
this, S.getBeginLoc(),
4825 S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);
4840 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4841 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4842 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4844 const Stmt *MasterRegionBodyStmt = S.getAssociatedStmt();
4846 auto FiniCB = [
this](InsertPointTy IP) {
4848 return llvm::Error::success();
4851 auto BodyGenCB = [MasterRegionBodyStmt,
4852 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4855 *
this, MasterRegionBodyStmt, AllocIP, CodeGenIP,
"master");
4856 return llvm::Error::success();
4861 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4862 cantFail(OMPBuilder.createMaster(
Builder, BodyGenCB, FiniCB));
4877 Expr *Filter =
nullptr;
4879 Filter = FilterClause->getThreadID();
4885 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4886 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4887 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4889 const Stmt *MaskedRegionBodyStmt = S.getAssociatedStmt();
4890 const Expr *Filter =
nullptr;
4892 Filter = FilterClause->getThreadID();
4893 llvm::Value *FilterVal = Filter
4895 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
4897 auto FiniCB = [
this](InsertPointTy IP) {
4899 return llvm::Error::success();
4902 auto BodyGenCB = [MaskedRegionBodyStmt,
4903 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4906 *
this, MaskedRegionBodyStmt, AllocIP, CodeGenIP,
"masked");
4907 return llvm::Error::success();
4912 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
4913 OMPBuilder.createMasked(
Builder, BodyGenCB, FiniCB, FilterVal));
4924 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4925 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4926 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4928 const Stmt *CriticalRegionBodyStmt = S.getAssociatedStmt();
4929 const Expr *Hint =
nullptr;
4930 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4931 Hint = HintClause->getHint();
4936 llvm::Value *HintInst =
nullptr;
4941 auto FiniCB = [
this](InsertPointTy IP) {
4943 return llvm::Error::success();
4946 auto BodyGenCB = [CriticalRegionBodyStmt,
4947 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4950 *
this, CriticalRegionBodyStmt, AllocIP, CodeGenIP,
"critical");
4951 return llvm::Error::success();
4956 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4957 cantFail(OMPBuilder.createCritical(
Builder, BodyGenCB, FiniCB,
4958 S.getDirectiveName().getAsString(),
4967 CGF.
EmitStmt(S.getAssociatedStmt());
4969 const Expr *Hint =
nullptr;
4970 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4971 Hint = HintClause->getHint();
4974 CGM.getOpenMPRuntime().emitCriticalRegion(*
this,
4975 S.getDirectiveName().getAsString(),
4976 CodeGen, S.getBeginLoc(), Hint);
4980 const OMPParallelForDirective &S) {
4989 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
4993 OMPLoopScope LoopScope(CGF, S);
4996 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4997 [](
const OMPReductionClause *
C) {
4998 return C->getModifier() == OMPC_REDUCTION_inscan;
5014 const OMPParallelForSimdDirective &S) {
5023 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
5027 OMPLoopScope LoopScope(CGF, S);
5030 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
5031 [](
const OMPReductionClause *
C) {
5032 return C->getModifier() == OMPC_REDUCTION_inscan;
5048 const OMPParallelMasterDirective &S) {
5068 [](CodeGenFunction &) {
return nullptr; });
5075 const OMPParallelMaskedDirective &S) {
5095 [](CodeGenFunction &) {
return nullptr; });
5102 const OMPParallelSectionsDirective &S) {
5108 CGF.EmitSections(S);
5122class CheckVarsEscapingUntiedTaskDeclContext final
5127 explicit CheckVarsEscapingUntiedTaskDeclContext() =
default;
5128 ~CheckVarsEscapingUntiedTaskDeclContext() =
default;
5129 void VisitDeclStmt(
const DeclStmt *S) {
5134 if (
const auto *VD = dyn_cast_or_null<VarDecl>(D))
5136 PrivateDecls.push_back(VD);
5140 void VisitCapturedStmt(
const CapturedStmt *) {}
5142 void VisitBlockExpr(
const BlockExpr *) {}
5143 void VisitStmt(
const Stmt *S) {
5146 for (
const Stmt *Child : S->
children())
5152 ArrayRef<const VarDecl *> getPrivateDecls()
const {
return PrivateDecls; }
5160 bool OmpAllMemory =
false;
5163 return C->getDependencyKind() == OMPC_DEPEND_outallmemory ||
5164 C->getDependencyKind() == OMPC_DEPEND_inoutallmemory;
5166 OmpAllMemory =
true;
5171 Data.Dependences.emplace_back(OMPC_DEPEND_outallmemory,
5180 if (Kind == OMPC_DEPEND_outallmemory || Kind == OMPC_DEPEND_inoutallmemory)
5182 if (OmpAllMemory && (Kind == OMPC_DEPEND_out || Kind == OMPC_DEPEND_inout))
5185 Data.Dependences.emplace_back(
C->getDependencyKind(),
C->getModifier());
5186 DD.
DepExprs.append(
C->varlist_begin(),
C->varlist_end());
5195 const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion);
5197 auto PartId = std::next(I);
5198 auto TaskT = std::next(I, 4);
5203 const Expr *
Cond = Clause->getCondition();
5206 Data.Final.setInt(CondConstant);
5211 Data.Final.setInt(
false);
5215 const Expr *Prio = Clause->getPriority();
5216 Data.Priority.setInt(
true);
5224 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
5226 for (
const auto *
C : S.getClausesOfKind<OMPPrivateClause>()) {
5227 auto IRef =
C->varlist_begin();
5228 for (
const Expr *IInit :
C->private_copies()) {
5230 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
5231 Data.PrivateVars.push_back(*IRef);
5232 Data.PrivateCopies.push_back(IInit);
5237 EmittedAsPrivate.clear();
5239 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5240 auto IRef =
C->varlist_begin();
5241 auto IElemInitRef =
C->inits().begin();
5242 for (
const Expr *IInit :
C->private_copies()) {
5244 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
5245 Data.FirstprivateVars.push_back(*IRef);
5246 Data.FirstprivateCopies.push_back(IInit);
5247 Data.FirstprivateInits.push_back(*IElemInitRef);
5254 llvm::MapVector<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
5255 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
5256 auto IRef =
C->varlist_begin();
5257 auto ID =
C->destination_exprs().begin();
5258 for (
const Expr *IInit :
C->private_copies()) {
5260 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
5261 Data.LastprivateVars.push_back(*IRef);
5262 Data.LastprivateCopies.push_back(IInit);
5264 LastprivateDstsOrigs.insert(
5273 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
5274 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5275 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5276 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5277 Data.ReductionOps.append(
C->reduction_ops().begin(),
5278 C->reduction_ops().end());
5279 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5280 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5282 Data.Reductions =
CGM.getOpenMPRuntime().emitTaskReductionInit(
5283 *
this, S.getBeginLoc(), LHSs, RHSs,
Data);
5288 CheckVarsEscapingUntiedTaskDeclContext Checker;
5289 Checker.Visit(S.getInnermostCapturedStmt()->getCapturedStmt());
5290 Data.PrivateLocals.append(Checker.getPrivateDecls().begin(),
5291 Checker.getPrivateDecls().end());
5293 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
5294 CapturedRegion](CodeGenFunction &CGF,
5296 llvm::MapVector<CanonicalDeclPtr<const VarDecl>,
5297 std::pair<Address, Address>>
5302 if (
auto *DI = CGF.getDebugInfo()) {
5303 llvm::SmallDenseMap<const VarDecl *, FieldDecl *> CaptureFields =
5304 CGF.CapturedStmtInfo->getCaptureFields();
5305 llvm::Value *ContextValue = CGF.CapturedStmtInfo->getContextValue();
5306 if (CaptureFields.size() && ContextValue) {
5307 unsigned CharWidth = CGF.getContext().getCharWidth();
5321 for (
auto It = CaptureFields.begin(); It != CaptureFields.end(); ++It) {
5322 const VarDecl *SharedVar = It->first;
5325 CGF.getContext().getASTRecordLayout(CaptureRecord);
5328 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5329 (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue,
5330 CGF.Builder,
false);
5333 auto UpdateExpr = [](llvm::LLVMContext &Ctx,
auto *
Declare,
5338 Ops.push_back(llvm::dwarf::DW_OP_plus_uconst);
5339 Ops.push_back(Offset);
5341 Ops.push_back(llvm::dwarf::DW_OP_deref);
5342 Declare->setExpression(llvm::DIExpression::get(Ctx, Ops));
5344 llvm::Instruction &
Last = CGF.Builder.GetInsertBlock()->back();
5345 if (
auto DDI = dyn_cast<llvm::DbgVariableIntrinsic>(&
Last))
5346 UpdateExpr(DDI->getContext(), DDI, Offset);
5349 assert(!
Last.isTerminator() &&
"unexpected terminator");
5351 CGF.Builder.GetInsertBlock()->getTrailingDbgRecords()) {
5352 for (llvm::DbgVariableRecord &DVR : llvm::reverse(
5353 llvm::filterDbgVars(Marker->getDbgRecordRange()))) {
5354 UpdateExpr(
Last.getContext(), &DVR, Offset);
5362 if (!
Data.PrivateVars.empty() || !
Data.FirstprivateVars.empty() ||
5363 !
Data.LastprivateVars.empty() || !
Data.PrivateLocals.empty()) {
5364 enum { PrivatesParam = 2, CopyFnParam = 3 };
5365 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5367 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5373 CallArgs.push_back(PrivatesPtr);
5374 ParamTypes.push_back(PrivatesPtr->getType());
5375 for (
const Expr *E :
Data.PrivateVars) {
5377 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5378 CGF.getContext().getPointerType(E->
getType()),
".priv.ptr.addr");
5379 PrivatePtrs.emplace_back(VD, PrivatePtr);
5381 ParamTypes.push_back(PrivatePtr.
getType());
5383 for (
const Expr *E :
Data.FirstprivateVars) {
5385 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5386 CGF.getContext().getPointerType(E->
getType()),
5387 ".firstpriv.ptr.addr");
5388 PrivatePtrs.emplace_back(VD, PrivatePtr);
5389 FirstprivatePtrs.emplace_back(VD, PrivatePtr);
5391 ParamTypes.push_back(PrivatePtr.
getType());
5393 for (
const Expr *E :
Data.LastprivateVars) {
5395 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5396 CGF.getContext().getPointerType(E->
getType()),
5397 ".lastpriv.ptr.addr");
5398 PrivatePtrs.emplace_back(VD, PrivatePtr);
5400 ParamTypes.push_back(PrivatePtr.
getType());
5405 Ty = CGF.getContext().getPointerType(Ty);
5407 Ty = CGF.getContext().getPointerType(Ty);
5408 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5409 CGF.getContext().getPointerType(Ty),
".local.ptr.addr");
5410 auto Result = UntiedLocalVars.insert(
5413 if (
Result.second ==
false)
5414 *
Result.first = std::make_pair(
5417 ParamTypes.push_back(PrivatePtr.
getType());
5419 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5421 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5422 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5423 for (
const auto &Pair : LastprivateDstsOrigs) {
5427 CGF.CapturedStmtInfo->lookup(OrigVD) !=
nullptr,
5429 Pair.second->getExprLoc());
5430 Scope.addPrivate(Pair.first, CGF.EmitLValue(&DRE).getAddress());
5432 for (
const auto &Pair : PrivatePtrs) {
5434 CGF.Builder.CreateLoad(Pair.second),
5435 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5436 CGF.getContext().getDeclAlign(Pair.first));
5437 Scope.addPrivate(Pair.first, Replacement);
5438 if (
auto *DI = CGF.getDebugInfo())
5439 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5440 (void)DI->EmitDeclareOfAutoVariable(
5441 Pair.first, Pair.second.getBasePointer(), CGF.Builder,
5446 for (
auto &Pair : UntiedLocalVars) {
5447 QualType VDType = Pair.first->getType().getNonReferenceType();
5448 if (Pair.first->getType()->isLValueReferenceType())
5449 VDType = CGF.getContext().getPointerType(VDType);
5451 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5454 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(VDType)),
5455 CGF.getPointerAlign());
5456 Pair.second.first = Replacement;
5457 Ptr = CGF.Builder.CreateLoad(Replacement);
5458 Replacement =
Address(Ptr, CGF.ConvertTypeForMem(VDType),
5459 CGF.getContext().getDeclAlign(Pair.first));
5460 Pair.second.second = Replacement;
5462 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5463 Address Replacement(Ptr, CGF.ConvertTypeForMem(VDType),
5464 CGF.getContext().getDeclAlign(Pair.first));
5465 Pair.second.first = Replacement;
5469 if (
Data.Reductions) {
5471 for (
const auto &Pair : FirstprivatePtrs) {
5473 CGF.Builder.CreateLoad(Pair.second),
5474 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5475 CGF.getContext().getDeclAlign(Pair.first));
5476 FirstprivateScope.
addPrivate(Pair.first, Replacement);
5479 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5481 Data.ReductionCopies,
Data.ReductionOps);
5482 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
5484 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5490 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5492 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5495 CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF),
5496 CGF.getContext().VoidPtrTy,
5497 CGF.getContext().getPointerType(
5498 Data.ReductionCopies[Cnt]->getType()),
5499 Data.ReductionCopies[Cnt]->getExprLoc()),
5500 CGF.ConvertTypeForMem(
Data.ReductionCopies[Cnt]->getType()),
5501 Replacement.getAlignment());
5507 (void)
Scope.Privatize();
5512 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5513 auto IPriv =
C->privates().begin();
5514 auto IRed =
C->reduction_ops().begin();
5515 auto ITD =
C->taskgroup_descriptors().begin();
5516 for (
const Expr *Ref :
C->varlist()) {
5517 InRedVars.emplace_back(Ref);
5518 InRedPrivs.emplace_back(*IPriv);
5519 InRedOps.emplace_back(*IRed);
5520 TaskgroupDescriptors.emplace_back(*ITD);
5521 std::advance(IPriv, 1);
5522 std::advance(IRed, 1);
5523 std::advance(ITD, 1);
5529 if (!InRedVars.empty()) {
5531 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5539 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5541 llvm::Value *ReductionsPtr;
5542 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5543 ReductionsPtr = CGF.EmitLoadOfScalar(CGF.EmitLValue(TRExpr),
5544 TRExpr->getExprLoc());
5546 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5548 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5551 CGF.EmitScalarConversion(
5552 Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy,
5553 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
5554 InRedPrivs[Cnt]->getExprLoc()),
5555 CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()),
5556 Replacement.getAlignment());
5569 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5570 S, *I, *PartId, *TaskT, EKind,
CodeGen,
Data.Tied,
Data.NumberOfParts);
5571 OMPLexicalScope
Scope(*
this, S, std::nullopt,
5574 TaskGen(*
this, OutlinedFn,
Data);
5591 QualType ElemType =
C.getBaseElementType(Ty);
5601 Data.FirstprivateVars.emplace_back(OrigRef);
5602 Data.FirstprivateCopies.emplace_back(PrivateRef);
5603 Data.FirstprivateInits.emplace_back(InitRef);
5616 auto PartId = std::next(I);
5617 auto TaskT = std::next(I, 4);
5620 Data.Final.setInt(
false);
5622 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5623 auto IRef =
C->varlist_begin();
5624 auto IElemInitRef =
C->inits().begin();
5625 for (
auto *IInit :
C->private_copies()) {
5626 Data.FirstprivateVars.push_back(*IRef);
5627 Data.FirstprivateCopies.push_back(IInit);
5628 Data.FirstprivateInits.push_back(*IElemInitRef);
5635 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5636 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5637 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5638 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5639 Data.ReductionOps.append(
C->reduction_ops().begin(),
5640 C->reduction_ops().end());
5641 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5642 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5657 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5659 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5671 if (!isa_and_nonnull<llvm::ConstantPointerNull>(
5674 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5681 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, BPVD, PVD, SVD, MVD, EKind,
5685 if (!
Data.FirstprivateVars.empty()) {
5686 enum { PrivatesParam = 2, CopyFnParam = 3 };
5687 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5689 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5695 CallArgs.push_back(PrivatesPtr);
5696 ParamTypes.push_back(PrivatesPtr->getType());
5697 for (
const Expr *E :
Data.FirstprivateVars) {
5699 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5700 CGF.getContext().getPointerType(E->
getType()),
5701 ".firstpriv.ptr.addr");
5702 PrivatePtrs.emplace_back(VD, PrivatePtr);
5704 ParamTypes.push_back(PrivatePtr.
getType());
5706 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5708 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5709 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5710 for (
const auto &Pair : PrivatePtrs) {
5712 CGF.Builder.CreateLoad(Pair.second),
5713 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5714 CGF.getContext().getDeclAlign(Pair.first));
5715 Scope.addPrivate(Pair.first, Replacement);
5718 CGF.processInReduction(S,
Data, CGF, CS,
Scope);
5721 CGF.GetAddrOfLocalVar(BPVD), 0);
5723 CGF.GetAddrOfLocalVar(PVD), 0);
5724 InputInfo.
SizesArray = CGF.Builder.CreateConstArrayGEP(
5725 CGF.GetAddrOfLocalVar(SVD), 0);
5728 InputInfo.
MappersArray = CGF.Builder.CreateConstArrayGEP(
5729 CGF.GetAddrOfLocalVar(MVD), 0);
5733 OMPLexicalScope LexScope(CGF, S, OMPD_task,
false);
5735 if (CGF.CGM.getLangOpts().OpenMP >= 51 &&
5740 CGF.CGM.getOpenMPRuntime().emitThreadLimitClause(
5741 CGF, TL->getThreadLimit().front(), S.getBeginLoc());
5745 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5746 S, *I, *PartId, *TaskT, EKind,
CodeGen,
true,
5747 Data.NumberOfParts);
5748 llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<OMPNowaitClause>() ? 1 : 0);
5752 CGM.getOpenMPRuntime().emitTaskCall(*
this, S.getBeginLoc(), S, OutlinedFn,
5753 SharedsTy, CapturedStruct, &IfCond,
Data);
5758 CodeGenFunction &CGF,
5762 if (
Data.Reductions) {
5764 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5766 Data.ReductionCopies,
Data.ReductionOps);
5769 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5783 Data.ReductionCopies[Cnt]->getType()),
5784 Data.ReductionCopies[Cnt]->getExprLoc()),
5786 Replacement.getAlignment());
5791 (void)
Scope.Privatize();
5796 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5797 auto IPriv =
C->privates().begin();
5798 auto IRed =
C->reduction_ops().begin();
5799 auto ITD =
C->taskgroup_descriptors().begin();
5800 for (
const Expr *Ref :
C->varlist()) {
5801 InRedVars.emplace_back(Ref);
5802 InRedPrivs.emplace_back(*IPriv);
5803 InRedOps.emplace_back(*IRed);
5804 TaskgroupDescriptors.emplace_back(*ITD);
5805 std::advance(IPriv, 1);
5806 std::advance(IRed, 1);
5807 std::advance(ITD, 1);
5811 if (!InRedVars.empty()) {
5813 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5821 llvm::Value *ReductionsPtr;
5822 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5826 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
5834 InRedPrivs[Cnt]->getExprLoc()),
5836 Replacement.getAlignment());
5850 const Expr *IfCond =
nullptr;
5851 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
5852 if (
C->getNameModifier() == OMPD_unknown ||
5853 C->getNameModifier() == OMPD_task) {
5854 IfCond =
C->getCondition();
5861 Data.Tied = !S.getSingleClause<OMPUntiedClause>();
5865 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
5866 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
5869 SharedsTy, CapturedStruct, IfCond,
5878 const OMPTaskyieldDirective &S) {
5879 CGM.getOpenMPRuntime().emitTaskyieldCall(*
this, S.getBeginLoc());
5883 const OMPMessageClause *MC = S.getSingleClause<OMPMessageClause>();
5884 Expr *ME = MC ? MC->getMessageString() :
nullptr;
5885 const OMPSeverityClause *SC = S.getSingleClause<OMPSeverityClause>();
5886 bool IsFatal =
false;
5887 if (!SC || SC->getSeverityKind() == OMPC_SEVERITY_fatal)
5889 CGM.getOpenMPRuntime().emitErrorCall(*
this, S.getBeginLoc(), ME, IsFatal);
5893 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_barrier);
5900 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
5901 CGM.getOpenMPRuntime().emitTaskwaitCall(*
this, S.getBeginLoc(),
Data);
5905 return T.clauses().empty();
5909 const OMPTaskgroupDirective &S) {
5910 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
5912 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
5913 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5917 auto BodyGenCB = [&,
this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
5920 EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5921 return llvm::Error::success();
5926 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5927 cantFail(OMPBuilder.createTaskgroup(
Builder, AllocaIP,
5934 if (
const Expr *E = S.getReductionRef()) {
5938 for (
const auto *
C : S.getClausesOfKind<OMPTaskReductionClause>()) {
5939 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5940 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5941 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5942 Data.ReductionOps.append(
C->reduction_ops().begin(),
5943 C->reduction_ops().end());
5944 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5945 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5947 llvm::Value *ReductionDesc =
5955 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5957 CGM.getOpenMPRuntime().emitTaskgroupRegion(*
this,
CodeGen, S.getBeginLoc());
5962 ? llvm::AtomicOrdering::NotAtomic
5963 : llvm::AtomicOrdering::AcquireRelease;
5964 CGM.getOpenMPRuntime().emitFlush(
5967 if (
const auto *FlushClause = S.getSingleClause<
OMPFlushClause>())
5969 FlushClause->varlist_end());
5972 S.getBeginLoc(), AO);
5982 for (
auto &Dep :
Data.Dependences) {
5983 Address DepAddr =
CGM.getOpenMPRuntime().emitDepobjDependClause(
5984 *
this, Dep, DC->getBeginLoc());
5990 CGM.getOpenMPRuntime().emitDestroyClause(*
this, DOLVal, DC->getBeginLoc());
5993 if (
const auto *UC = S.getSingleClause<OMPUpdateClause>()) {
5994 CGM.getOpenMPRuntime().emitUpdateClause(
5995 *
this, DOLVal, UC->getDependencyKind(), UC->getBeginLoc());
6013 for (
const auto *
C : ParentDir.getClausesOfKind<OMPReductionClause>()) {
6014 if (
C->getModifier() != OMPC_REDUCTION_inscan)
6016 Shareds.append(
C->varlist_begin(),
C->varlist_end());
6017 Privates.append(
C->privates().begin(),
C->privates().end());
6018 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
6019 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
6020 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
6021 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
6022 CopyArrayTemps.append(
C->copy_array_temps().begin(),
6023 C->copy_array_temps().end());
6024 CopyArrayElems.append(
C->copy_array_elems().begin(),
6025 C->copy_array_elems().end());
6027 if (ParentDir.getDirectiveKind() == OMPD_simd ||
6069 : BreakContinueStack.back().ContinueBlock.getBlock());
6080 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6082 const Expr *TempExpr = CopyArrayTemps[I];
6094 CGM.getOpenMPRuntime().emitReduction(
6095 *
this, ParentDir.getEndLoc(),
Privates, LHSs, RHSs, ReductionOps,
6098 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6106 const Expr *TempExpr = CopyArrayTemps[I];
6118 ? BreakContinueStack.back().ContinueBlock.getBlock()
6124 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6130 .getIterationVariable()
6131 ->IgnoreParenImpCasts();
6134 IdxVal = Builder.CreateIntCast(IdxVal,
SizeTy,
false);
6135 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6137 const Expr *OrigExpr = Shareds[I];
6138 const Expr *CopyArrayElem = CopyArrayElems[I];
6139 OpaqueValueMapping IdxMapping(
6152 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6155 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6161 .getIterationVariable()
6162 ->IgnoreParenImpCasts();
6166 llvm::BasicBlock *ExclusiveExitBB =
nullptr;
6170 llvm::Value *
Cmp =
Builder.CreateIsNull(IdxVal);
6171 Builder.CreateCondBr(
Cmp, ExclusiveExitBB, ContBB);
6174 IdxVal =
Builder.CreateNUWSub(IdxVal, llvm::ConstantInt::get(
SizeTy, 1));
6176 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6177 const Expr *PrivateExpr =
Privates[I];
6178 const Expr *OrigExpr = Shareds[I];
6179 const Expr *CopyArrayElem = CopyArrayElems[I];
6188 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
6212 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
6220 bool HasLastprivateClause =
false;
6223 OMPLoopScope PreInitScope(*
this, S);
6228 llvm::BasicBlock *ContBlock =
nullptr;
6235 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
6249 ? S.getCombinedLowerBoundVariable()
6250 : S.getLowerBoundVariable())));
6254 ? S.getCombinedUpperBoundVariable()
6255 : S.getUpperBoundVariable())));
6266 CGM.getOpenMPRuntime().emitBarrierCall(
6267 *
this, S.getBeginLoc(), OMPD_unknown,
false,
6279 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
6282 llvm::Value *Chunk =
nullptr;
6285 ScheduleKind =
C->getDistScheduleKind();
6286 if (
const Expr *Ch =
C->getChunkSize()) {
6289 S.getIterationVariable()->getType(),
6294 CGM.getOpenMPRuntime().getDefaultDistScheduleAndChunk(
6295 *
this, S, ScheduleKind, Chunk);
6316 bool StaticChunked =
6320 Chunk !=
nullptr) ||
6325 StaticChunked ? Chunk :
nullptr);
6333 ? S.getCombinedEnsureUpperBound()
6334 : S.getEnsureUpperBound());
6338 ? S.getCombinedInit()
6343 ? S.getCombinedCond()
6347 Cond = S.getCombinedDistCond();
6379 [&S, &LoopScope,
Cond, IncExpr,
LoopExit, &CodeGenLoop,
6382 S, LoopScope.requiresCleanups(),
Cond, IncExpr,
6383 [&S,
LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
6384 CodeGenLoop(CGF, S, LoopExit);
6386 [&S, StaticChunked](CodeGenFunction &CGF) {
6387 if (StaticChunked) {
6388 CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound());
6389 CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound());
6390 CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound());
6391 CGF.EmitIgnoredExpr(S.getCombinedInit());
6401 const OMPLoopArguments LoopArguments = {
6404 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments,
6410 return CGF.
Builder.CreateIsNotNull(
6420 *
this, S, [IL, &S](CodeGenFunction &CGF) {
6421 return CGF.
Builder.CreateIsNotNull(
6426 if (HasLastprivateClause) {
6449 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
6458static llvm::Function *
6465 Fn->setDoesNotRecurse();
6469template <
typename T>
6471 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP,
6472 llvm::OpenMPIRBuilder &OMPBuilder) {
6474 unsigned NumLoops =
C->getNumLoops();
6478 for (
unsigned I = 0; I < NumLoops; I++) {
6479 const Expr *CounterVal =
C->getLoopData(I);
6484 StoreValues.emplace_back(StoreValue);
6486 OMPDoacrossKind<T> ODK;
6487 bool IsDependSource = ODK.isSource(
C);
6489 OMPBuilder.createOrderedDepend(CGF.
Builder, AllocaIP, NumLoops,
6490 StoreValues,
".cnt.addr", IsDependSource));
6494 if (
CGM.getLangOpts().OpenMPIRBuilder) {
6495 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
6496 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6501 assert(!S.hasAssociatedStmt() &&
"No associated statement must be in "
6502 "ordered depend|doacross construct.");
6514 auto FiniCB = [
this](InsertPointTy IP) {
6516 return llvm::Error::success();
6519 auto BodyGenCB = [&S,
C,
6520 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
6526 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
6527 Builder,
false,
".ordered.after");
6531 assert(S.getBeginLoc().isValid() &&
6532 "Outlined function call location must be valid.");
6535 OutlinedFn, CapturedVars);
6540 return llvm::Error::success();
6543 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6544 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
6545 OMPBuilder.createOrderedThreadsSimd(
Builder, BodyGenCB, FiniCB, !
C));
6552 assert(!S.hasAssociatedStmt() &&
6553 "No associated statement must be in ordered depend construct.");
6555 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6559 assert(!S.hasAssociatedStmt() &&
6560 "No associated statement must be in ordered doacross construct.");
6562 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6566 auto &&
CodeGen = [&S,
C,
this](CodeGenFunction &CGF,
6571 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
6573 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
6574 OutlinedFn, CapturedVars);
6580 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6581 CGM.getOpenMPRuntime().emitOrderedRegion(*
this,
CodeGen, S.getBeginLoc(), !
C);
6588 "DestType must have scalar evaluation kind.");
6589 assert(!Val.
isAggregate() &&
"Must be a scalar or complex.");
6600 "DestType must have complex evaluation kind.");
6609 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
6611 assert(Val.
isComplex() &&
"Must be a scalar or complex.");
6616 Val.
getComplexVal().first, SrcElementType, DestElementType, Loc);
6618 Val.
getComplexVal().second, SrcElementType, DestElementType, Loc);
6624 LValue LVal,
RValue RVal) {
6625 if (LVal.isGlobalReg())
6632 llvm::AtomicOrdering AO, LValue LVal,
6634 if (LVal.isGlobalReg())
6637 LVal, Loc, llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO),
6646 *
this, RVal, RValTy, LVal.
getType(), Loc)),
6655 llvm_unreachable(
"Must be a scalar or complex.");
6663 assert(
V->isLValue() &&
"V of 'omp atomic read' is not lvalue");
6664 assert(
X->isLValue() &&
"X of 'omp atomic read' is not lvalue");
6673 case llvm::AtomicOrdering::Acquire:
6674 case llvm::AtomicOrdering::AcquireRelease:
6675 case llvm::AtomicOrdering::SequentiallyConsistent:
6677 llvm::AtomicOrdering::Acquire);
6679 case llvm::AtomicOrdering::Monotonic:
6680 case llvm::AtomicOrdering::Release:
6682 case llvm::AtomicOrdering::NotAtomic:
6683 case llvm::AtomicOrdering::Unordered:
6684 llvm_unreachable(
"Unexpected ordering.");
6691 llvm::AtomicOrdering AO,
const Expr *
X,
6694 assert(
X->isLValue() &&
"X of 'omp atomic write' is not lvalue");
6702 case llvm::AtomicOrdering::Release:
6703 case llvm::AtomicOrdering::AcquireRelease:
6704 case llvm::AtomicOrdering::SequentiallyConsistent:
6706 llvm::AtomicOrdering::Release);
6708 case llvm::AtomicOrdering::Acquire:
6709 case llvm::AtomicOrdering::Monotonic:
6711 case llvm::AtomicOrdering::NotAtomic:
6712 case llvm::AtomicOrdering::Unordered:
6713 llvm_unreachable(
"Unexpected ordering.");
6720 llvm::AtomicOrdering AO,
6726 if (BO == BO_Comma || !
Update.isScalar() || !
X.isSimple() ||
6728 (
Update.getScalarVal()->getType() !=
X.getAddress().getElementType())) ||
6729 !Context.getTargetInfo().hasBuiltinAtomic(
6730 Context.getTypeSize(
X.getType()), Context.toBits(
X.getAlignment())))
6731 return std::make_pair(
false,
RValue::get(
nullptr));
6734 if (T->isIntegerTy())
6737 if (T->isFloatingPointTy() && (BO == BO_Add || BO == BO_Sub))
6743 if (!CheckAtomicSupport(
Update.getScalarVal()->getType(), BO) ||
6744 !CheckAtomicSupport(
X.getAddress().getElementType(), BO))
6745 return std::make_pair(
false,
RValue::get(
nullptr));
6747 bool IsInteger =
X.getAddress().getElementType()->isIntegerTy();
6748 llvm::AtomicRMWInst::BinOp RMWOp;
6751 RMWOp = IsInteger ? llvm::AtomicRMWInst::Add : llvm::AtomicRMWInst::FAdd;
6755 return std::make_pair(
false,
RValue::get(
nullptr));
6756 RMWOp = IsInteger ? llvm::AtomicRMWInst::Sub : llvm::AtomicRMWInst::FSub;
6759 RMWOp = llvm::AtomicRMWInst::And;
6762 RMWOp = llvm::AtomicRMWInst::Or;
6765 RMWOp = llvm::AtomicRMWInst::Xor;
6769 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6771 : llvm::AtomicRMWInst::Max)
6773 : llvm::AtomicRMWInst::UMax);
6776 : llvm::AtomicRMWInst::FMax;
6780 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6782 : llvm::AtomicRMWInst::Min)
6784 : llvm::AtomicRMWInst::UMin);
6787 : llvm::AtomicRMWInst::FMin;
6790 RMWOp = llvm::AtomicRMWInst::Xchg;
6799 return std::make_pair(
false,
RValue::get(
nullptr));
6818 llvm_unreachable(
"Unsupported atomic update operation");
6820 llvm::Value *UpdateVal =
Update.getScalarVal();
6821 if (
auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
6823 UpdateVal = CGF.
Builder.CreateIntCast(
6824 IC,
X.getAddress().getElementType(),
6825 X.getType()->hasSignedIntegerRepresentation());
6827 UpdateVal = CGF.
Builder.CreateCast(llvm::Instruction::CastOps::UIToFP, IC,
6828 X.getAddress().getElementType());
6830 llvm::AtomicRMWInst *Res =
6847 if (
X.isGlobalReg()) {
6860 llvm::AtomicOrdering AO,
const Expr *
X,
6864 "Update expr in 'atomic update' must be a binary operator.");
6872 assert(
X->isLValue() &&
"X of 'omp atomic update' is not lvalue");
6879 auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](
RValue XRValue) {
6885 XLValue, ExprRValue, BOUE->getOpcode(),
IsXLHSInRHSPart, AO, Loc, Gen);
6892 case llvm::AtomicOrdering::Release:
6893 case llvm::AtomicOrdering::AcquireRelease:
6894 case llvm::AtomicOrdering::SequentiallyConsistent:
6896 llvm::AtomicOrdering::Release);
6898 case llvm::AtomicOrdering::Acquire:
6899 case llvm::AtomicOrdering::Monotonic:
6901 case llvm::AtomicOrdering::NotAtomic:
6902 case llvm::AtomicOrdering::Unordered:
6903 llvm_unreachable(
"Unexpected ordering.");
6921 llvm_unreachable(
"Must be a scalar or complex.");
6925 llvm::AtomicOrdering AO,
6930 assert(
X->isLValue() &&
"X of 'omp atomic capture' is not lvalue");
6931 assert(
V->isLValue() &&
"V of 'omp atomic capture' is not lvalue");
6940 "Update expr in 'atomic capture' must be a binary operator.");
6951 NewVValType = XRValExpr->
getType();
6953 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
6962 XLValue, ExprRValue, BOUE->getOpcode(),
IsXLHSInRHSPart, AO, Loc, Gen);
6968 NewVVal = Res.second;
6979 NewVValType =
X->getType().getNonReferenceType();
6981 X->getType().getNonReferenceType(), Loc);
6982 auto &&Gen = [&NewVVal, ExprRValue](
RValue XRValue) {
6988 XLValue, ExprRValue, BO_Assign,
false, AO,
7009 case llvm::AtomicOrdering::Release:
7011 llvm::AtomicOrdering::Release);
7013 case llvm::AtomicOrdering::Acquire:
7015 llvm::AtomicOrdering::Acquire);
7017 case llvm::AtomicOrdering::AcquireRelease:
7018 case llvm::AtomicOrdering::SequentiallyConsistent:
7020 CGF, {}, Loc, llvm::AtomicOrdering::AcquireRelease);
7022 case llvm::AtomicOrdering::Monotonic:
7024 case llvm::AtomicOrdering::NotAtomic:
7025 case llvm::AtomicOrdering::Unordered:
7026 llvm_unreachable(
"Unexpected ordering.");
7032 CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO,
7036 llvm::OpenMPIRBuilder &OMPBuilder =
7039 OMPAtomicCompareOp Op;
7043 Op = OMPAtomicCompareOp::EQ;
7046 Op = OMPAtomicCompareOp::MIN;
7049 Op = OMPAtomicCompareOp::MAX;
7052 llvm_unreachable(
"unsupported atomic compare binary operator");
7056 Address XAddr = XLVal.getAddress();
7058 auto EmitRValueWithCastIfNeeded = [&CGF, Loc](
const Expr *
X,
const Expr *E) {
7063 if (NewE->
getType() ==
X->getType())
7068 llvm::Value *EVal = EmitRValueWithCastIfNeeded(
X, E);
7069 llvm::Value *DVal = D ? EmitRValueWithCastIfNeeded(
X, D) :
nullptr;
7070 if (
auto *CI = dyn_cast<llvm::ConstantInt>(EVal))
7071 EVal = CGF.
Builder.CreateIntCast(
7072 CI, XLVal.getAddress().getElementType(),
7075 if (
auto *CI = dyn_cast<llvm::ConstantInt>(DVal))
7076 DVal = CGF.
Builder.CreateIntCast(
7077 CI, XLVal.getAddress().getElementType(),
7080 llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{
7082 X->getType()->hasSignedIntegerRepresentation(),
7083 X->getType().isVolatileQualified()};
7084 llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal;
7088 VOpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
7089 V->getType()->hasSignedIntegerRepresentation(),
7090 V->getType().isVolatileQualified()};
7095 ROpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
7096 R->getType()->hasSignedIntegerRepresentation(),
7097 R->getType().isVolatileQualified()};
7100 if (FailAO == llvm::AtomicOrdering::NotAtomic) {
7103 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
7104 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
7107 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
7108 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
7113 llvm::AtomicOrdering AO,
7134 case OMPC_compare: {
7140 llvm_unreachable(
"Clause is not allowed in 'omp atomic'.");
7145 llvm::AtomicOrdering AO =
CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
7147 llvm::AtomicOrdering FailAO = llvm::AtomicOrdering::NotAtomic;
7148 bool MemOrderingSpecified =
false;
7149 if (S.getSingleClause<OMPSeqCstClause>()) {
7150 AO = llvm::AtomicOrdering::SequentiallyConsistent;
7151 MemOrderingSpecified =
true;
7152 }
else if (S.getSingleClause<OMPAcqRelClause>()) {
7153 AO = llvm::AtomicOrdering::AcquireRelease;
7154 MemOrderingSpecified =
true;
7155 }
else if (S.getSingleClause<OMPAcquireClause>()) {
7156 AO = llvm::AtomicOrdering::Acquire;
7157 MemOrderingSpecified =
true;
7158 }
else if (S.getSingleClause<OMPReleaseClause>()) {
7159 AO = llvm::AtomicOrdering::Release;
7160 MemOrderingSpecified =
true;
7161 }
else if (S.getSingleClause<OMPRelaxedClause>()) {
7162 AO = llvm::AtomicOrdering::Monotonic;
7163 MemOrderingSpecified =
true;
7165 llvm::SmallSet<OpenMPClauseKind, 2> KindsEncountered;
7174 if (K == OMPC_seq_cst || K == OMPC_acq_rel || K == OMPC_acquire ||
7175 K == OMPC_release || K == OMPC_relaxed || K == OMPC_hint)
7178 KindsEncountered.insert(K);
7183 if (KindsEncountered.contains(OMPC_compare) &&
7184 KindsEncountered.contains(OMPC_capture))
7185 Kind = OMPC_compare;
7186 if (!MemOrderingSpecified) {
7187 llvm::AtomicOrdering DefaultOrder =
7188 CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
7189 if (DefaultOrder == llvm::AtomicOrdering::Monotonic ||
7190 DefaultOrder == llvm::AtomicOrdering::SequentiallyConsistent ||
7191 (DefaultOrder == llvm::AtomicOrdering::AcquireRelease &&
7192 Kind == OMPC_capture)) {
7194 }
else if (DefaultOrder == llvm::AtomicOrdering::AcquireRelease) {
7195 if (Kind == OMPC_unknown || Kind == OMPC_update || Kind == OMPC_write) {
7196 AO = llvm::AtomicOrdering::Release;
7197 }
else if (Kind == OMPC_read) {
7198 assert(Kind == OMPC_read &&
"Unexpected atomic kind.");
7199 AO = llvm::AtomicOrdering::Acquire;
7204 if (KindsEncountered.contains(OMPC_compare) &&
7205 KindsEncountered.contains(OMPC_fail)) {
7206 Kind = OMPC_compare;
7207 const auto *FailClause = S.getSingleClause<OMPFailClause>();
7210 if (FailParameter == llvm::omp::OMPC_relaxed)
7211 FailAO = llvm::AtomicOrdering::Monotonic;
7212 else if (FailParameter == llvm::omp::OMPC_acquire)
7213 FailAO = llvm::AtomicOrdering::Acquire;
7214 else if (FailParameter == llvm::omp::OMPC_seq_cst)
7215 FailAO = llvm::AtomicOrdering::SequentiallyConsistent;
7222 S.getV(), S.getR(), S.getExpr(), S.getUpdateExpr(),
7223 S.getD(), S.getCondExpr(), S.isXLHSInRHSPart(),
7224 S.isFailOnly(), S.getBeginLoc());
7235 OMPLexicalScope
Scope(CGF, S, OMPD_target);
7238 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
7244 llvm::Function *Fn =
nullptr;
7245 llvm::Constant *FnID =
nullptr;
7247 const Expr *IfCond =
nullptr;
7249 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7250 if (
C->getNameModifier() == OMPD_unknown ||
7251 C->getNameModifier() == OMPD_target) {
7252 IfCond =
C->getCondition();
7258 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device(
7261 Device.setPointerAndInt(
C->getDevice(),
C->getModifier());
7266 bool IsOffloadEntry =
true;
7270 IsOffloadEntry =
false;
7273 IsOffloadEntry =
false;
7275 if (
CGM.
getLangOpts().OpenMPOffloadMandatory && !IsOffloadEntry) {
7279 assert(CGF.
CurFuncDecl &&
"No parent declaration for target region!");
7280 StringRef ParentName;
7283 if (
const auto *D = dyn_cast<CXXConstructorDecl>(CGF.
CurFuncDecl))
7285 else if (
const auto *D = dyn_cast<CXXDestructorDecl>(CGF.
CurFuncDecl))
7294 OMPLexicalScope
Scope(CGF, S, OMPD_task);
7295 auto &&SizeEmitter =
7298 if (IsOffloadEntry) {
7299 OMPLoopScope(CGF, D);
7301 llvm::Value *NumIterations = CGF.
EmitScalarExpr(D.getNumIterations());
7302 NumIterations = CGF.
Builder.CreateIntCast(NumIterations, CGF.
Int64Ty,
7304 return NumIterations;
7322 CGF.
EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
7327 StringRef ParentName,
7333 llvm::Constant *
Addr;
7335 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7337 assert(Fn &&
Addr &&
"Target device function emission failed.");
7351 const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams);
7352 llvm::Function *OutlinedFn =
7360 const Expr *NumTeams = NT ? NT->getNumTeams().front() :
nullptr;
7361 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() :
nullptr;
7367 OMPTeamsScope
Scope(CGF, S);
7383 CGF.
EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt());
7388 [](CodeGenFunction &) {
return nullptr; });
7393 auto *CS = S.getCapturedStmt(OMPD_teams);
7420 llvm::Constant *
Addr;
7422 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7424 assert(Fn &&
Addr &&
"Target device function emission failed.");
7466 llvm::Constant *
Addr;
7468 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7470 assert(Fn &&
Addr &&
"Target device function emission failed.");
7512 llvm::Constant *
Addr;
7514 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7516 assert(Fn &&
Addr &&
"Target device function emission failed.");
7530 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7535 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7547 [](CodeGenFunction &) {
return nullptr; });
7552 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7557 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7569 [](CodeGenFunction &) {
return nullptr; });
7574 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7580 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7592 [](CodeGenFunction &) {
return nullptr; });
7597 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7603 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7610 CGF, OMPD_distribute, CodeGenDistribute,
false);
7616 [](CodeGenFunction &) {
return nullptr; });
7620 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7621 llvm::Value *
Device =
nullptr;
7622 llvm::Value *NumDependences =
nullptr;
7623 llvm::Value *DependenceList =
nullptr;
7631 if (!
Data.Dependences.empty()) {
7633 std::tie(NumDependences, DependenciesArray) =
7634 CGM.getOpenMPRuntime().emitDependClause(*
this,
Data.Dependences,
7638 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
7643 "OMPNowaitClause clause is used separately in OMPInteropDirective.");
7646 if (!ItOMPInitClause.empty()) {
7649 llvm::Value *InteropvarPtr =
7651 llvm::omp::OMPInteropType InteropType =
7652 llvm::omp::OMPInteropType::Unknown;
7653 if (
C->getIsTarget()) {
7654 InteropType = llvm::omp::OMPInteropType::Target;
7656 assert(
C->getIsTargetSync() &&
7657 "Expected interop-type target/targetsync");
7658 InteropType = llvm::omp::OMPInteropType::TargetSync;
7660 OMPBuilder.createOMPInteropInit(
Builder, InteropvarPtr, InteropType,
7661 Device, NumDependences, DependenceList,
7662 Data.HasNowaitClause);
7666 if (!ItOMPDestroyClause.empty()) {
7669 llvm::Value *InteropvarPtr =
7671 OMPBuilder.createOMPInteropDestroy(
Builder, InteropvarPtr,
Device,
7672 NumDependences, DependenceList,
7673 Data.HasNowaitClause);
7676 auto ItOMPUseClause = S.getClausesOfKind<
OMPUseClause>();
7677 if (!ItOMPUseClause.empty()) {
7680 llvm::Value *InteropvarPtr =
7682 OMPBuilder.createOMPInteropUse(
Builder, InteropvarPtr,
Device,
7683 NumDependences, DependenceList,
7684 Data.HasNowaitClause);
7706 CGF, OMPD_distribute, CodeGenDistribute,
false);
7725 llvm::Constant *
Addr;
7727 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7729 assert(Fn &&
Addr &&
"Target device function emission failed.");
7758 CGF, OMPD_distribute, CodeGenDistribute,
false);
7777 llvm::Constant *
Addr;
7779 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7781 assert(Fn &&
Addr &&
"Target device function emission failed.");
7794 CGM.getOpenMPRuntime().emitCancellationPointCall(*
this, S.getBeginLoc(),
7799 const Expr *IfCond =
nullptr;
7800 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7801 if (
C->getNameModifier() == OMPD_unknown ||
7802 C->getNameModifier() == OMPD_cancel) {
7803 IfCond =
C->getCondition();
7807 if (
CGM.getLangOpts().OpenMPIRBuilder) {
7808 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7814 llvm::Value *IfCondition =
nullptr;
7818 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
7820 return Builder.restoreIP(AfterIP);
7824 CGM.getOpenMPRuntime().emitCancelCall(*
this, S.getBeginLoc(), IfCond,
7830 if (Kind == OMPD_parallel || Kind == OMPD_task ||
7831 Kind == OMPD_target_parallel || Kind == OMPD_taskloop ||
7832 Kind == OMPD_master_taskloop || Kind == OMPD_parallel_master_taskloop)
7834 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
7835 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
7836 Kind == OMPD_distribute_parallel_for ||
7837 Kind == OMPD_target_parallel_for ||
7838 Kind == OMPD_teams_distribute_parallel_for ||
7839 Kind == OMPD_target_teams_distribute_parallel_for);
7840 return OMPCancelStack.getExitBlock();
7845 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7846 CaptureDeviceAddrMap) {
7847 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7848 for (
const Expr *OrigVarIt :
C.varlist()) {
7850 if (!Processed.insert(OrigVD).second)
7857 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7862 "Base should be the current struct!");
7863 MatchingVD = ME->getMemberDecl();
7868 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7869 if (InitAddrIt == CaptureDeviceAddrMap.end())
7877 Address(InitAddrIt->second, Ty,
7879 assert(IsRegistered &&
"firstprivate var already registered as private");
7887 while (
const auto *OASE = dyn_cast<ArraySectionExpr>(
Base))
7888 Base = OASE->getBase()->IgnoreParenImpCasts();
7889 while (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(
Base))
7890 Base = ASE->getBase()->IgnoreParenImpCasts();
7896 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7897 CaptureDeviceAddrMap) {
7898 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7899 for (
const Expr *Ref :
C.varlist()) {
7901 if (!Processed.insert(OrigVD).second)
7907 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7912 "Base should be the current struct!");
7913 MatchingVD = ME->getMemberDecl();
7918 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7919 if (InitAddrIt == CaptureDeviceAddrMap.end())
7925 Address(InitAddrIt->second, Ty,
7938 (void)PrivateScope.
addPrivate(OrigVD, PrivAddr);
7946 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
7947 CGM.getOpenMPRuntime().registerVTable(S);
7955 bool PrivatizeDevicePointers =
false;
7957 bool &PrivatizeDevicePointers;
7960 explicit DevicePointerPrivActionTy(
bool &PrivatizeDevicePointers)
7961 : PrivatizeDevicePointers(PrivatizeDevicePointers) {}
7962 void Enter(CodeGenFunction &CGF)
override {
7963 PrivatizeDevicePointers =
true;
7966 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
7969 auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7970 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
7974 auto &&PrivCodeGen = [&](CodeGenFunction &CGF,
PrePostActionTy &Action) {
7976 PrivatizeDevicePointers =
false;
7982 if (PrivatizeDevicePointers) {
7996 std::optional<OpenMPDirectiveKind> CaptureRegion;
7997 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
8000 for (
const Expr *E :
C->varlist()) {
8002 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
8006 for (
const Expr *E :
C->varlist()) {
8008 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
8012 CaptureRegion = OMPD_unknown;
8015 OMPLexicalScope
Scope(CGF, S, CaptureRegion);
8027 OMPLexicalScope
Scope(CGF, S);
8036 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
8042 const Expr *IfCond =
nullptr;
8044 IfCond =
C->getCondition();
8055 CGM.getOpenMPRuntime().emitTargetDataCalls(*
this, S, IfCond,
Device, RCG,
8063 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8067 const Expr *IfCond =
nullptr;
8069 IfCond =
C->getCondition();
8076 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8077 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8084 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8088 const Expr *IfCond =
nullptr;
8090 IfCond =
C->getCondition();
8097 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8098 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8105 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
8133 llvm::Constant *
Addr;
8135 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8137 assert(Fn &&
Addr &&
"Target device function emission failed.");
8157 CGF, OMPD_target_parallel_for, S.
hasCancel());
8173 llvm::Constant *
Addr;
8175 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8177 assert(Fn &&
Addr &&
"Target device function emission failed.");
8212 llvm::Constant *
Addr;
8214 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8216 assert(Fn &&
Addr &&
"Target device function emission failed.");
8238 const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop);
8241 OMPLexicalScope
Scope(*
this, S, OMPD_taskloop,
false);
8246 const Expr *IfCond =
nullptr;
8247 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
8248 if (
C->getNameModifier() == OMPD_unknown ||
8249 C->getNameModifier() == OMPD_taskloop) {
8250 IfCond =
C->getCondition();
8263 Data.Schedule.setInt(
false);
8266 (Clause->getModifier() == OMPC_GRAINSIZE_strict) ?
true :
false;
8269 Data.Schedule.setInt(
true);
8272 (Clause->getModifier() == OMPC_NUMTASKS_strict) ?
true :
false;
8286 llvm::BasicBlock *ContBlock =
nullptr;
8287 OMPLoopScope PreInitScope(CGF, S);
8288 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
8292 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock(
"taskloop.if.then");
8293 ContBlock = CGF.createBasicBlock(
"taskloop.if.end");
8294 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
8295 CGF.getProfileCount(&S));
8296 CGF.EmitBlock(ThenBlock);
8297 CGF.incrementProfileCounter(&S);
8300 (void)CGF.EmitOMPLinearClauseInit(S);
8304 enum { LowerBound = 5, UpperBound, Stride, LastIter };
8306 auto *LBP = std::next(I, LowerBound);
8307 auto *UBP = std::next(I, UpperBound);
8308 auto *STP = std::next(I, Stride);
8309 auto *LIP = std::next(I, LastIter);
8317 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
8318 CGF.EmitOMPLinearClause(S, LoopScope);
8319 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
8322 const Expr *IVExpr = S.getIterationVariable();
8324 CGF.EmitVarDecl(*IVDecl);
8325 CGF.EmitIgnoredExpr(S.getInit());
8330 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
8333 CGF.EmitIgnoredExpr(S.getCalcLastIteration());
8337 OMPLexicalScope
Scope(CGF, S, OMPD_taskloop,
false);
8347 [&S](CodeGenFunction &CGF) {
8348 emitOMPLoopBodyWithStopPoint(CGF, S,
8349 CodeGenFunction::JumpDest());
8351 [](CodeGenFunction &) {});
8356 CGF.EmitBranch(ContBlock);
8357 CGF.EmitBlock(ContBlock,
true);
8360 if (HasLastprivateClause) {
8361 CGF.EmitOMPLastprivateClauseFinal(
8363 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
8364 CGF.GetAddrOfLocalVar(*LIP),
false,
8365 (*LIP)->getType(), S.getBeginLoc())));
8368 CGF.EmitOMPLinearClauseFinal(S, [LIP, &S](CodeGenFunction &CGF) {
8369 return CGF.
Builder.CreateIsNotNull(
8371 (*LIP)->
getType(), S.getBeginLoc()));
8374 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
8375 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
8377 auto &&
CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
8379 OMPLoopScope PreInitScope(CGF, S);
8380 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S,
8381 OutlinedFn, SharedsTy,
8382 CapturedStruct, IfCond,
Data);
8384 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
8390 CGM.getOpenMPRuntime().emitTaskgroupRegion(
8392 [&S, &BodyGen, &TaskGen, &
Data](CodeGenFunction &CGF,
8412 OMPLexicalScope
Scope(*
this, S);
8424 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8425 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8436 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8437 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8448 OMPLexicalScope
Scope(*
this, S);
8449 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8460 OMPLexicalScope
Scope(*
this, S);
8461 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8467 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8472 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8473 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8485 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8490 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8491 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8503 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8508 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8509 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8521 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8526 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8527 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8541 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8545 const Expr *IfCond =
nullptr;
8547 IfCond =
C->getCondition();
8554 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8555 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8565 BindKind =
C->getBindKind();
8568 case OMPC_BIND_parallel:
8570 case OMPC_BIND_teams:
8572 case OMPC_BIND_thread:
8583 const auto *ForS = dyn_cast<ForStmt>(CS);
8594 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
8595 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_loop,
CodeGen);
8621 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
8626 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
8638 [](CodeGenFunction &) {
return nullptr; });
8643 std::string StatusMsg,
8647 StatusMsg +=
": DEVICE";
8649 StatusMsg +=
": HOST";
8656 llvm::dbgs() << StatusMsg <<
": " <<
FileName <<
": " << LineNo <<
"\n";
8679 CGF, OMPD_distribute, CodeGenDistribute,
false);
8708 CGF, OMPD_distribute, CodeGenDistribute,
false);
8741 llvm::Constant *
Addr;
8743 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8745 assert(Fn &&
Addr &&
8746 "Target device function emission failed for 'target teams loop'.");
8757 CGF, OMPD_target_parallel_loop,
false);
8773 llvm::Constant *
Addr;
8775 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8777 assert(Fn &&
Addr &&
"Target device function emission failed.");
8792 if (
const auto *SD = dyn_cast<OMPScanDirective>(&D)) {
8796 if (!D.hasAssociatedStmt() || !D.getAssociatedStmt())
8802 for (
const auto *
C : D.getClausesOfKind<OMPFirstprivateClause>()) {
8803 for (
const Expr *Ref :
C->varlist()) {
8807 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
8810 if (!CGF.LocalDeclMap.count(VD)) {
8822 if (
const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
8823 for (
const Expr *E : LD->counters()) {
8831 if (!CGF.LocalDeclMap.count(VD))
8835 for (
const auto *
C : D.getClausesOfKind<OMPOrderedClause>()) {
8836 if (!
C->getNumForLoops())
8838 for (
unsigned I = LD->getLoopsNumber(),
8839 E =
C->getLoopNumIterations().size();
8841 if (
const auto *VD = dyn_cast<OMPCapturedExprDecl>(
8844 if (!CGF.LocalDeclMap.count(VD))
8851 CGF.
EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
8854 if (D.getDirectiveKind() == OMPD_atomic ||
8855 D.getDirectiveKind() == OMPD_critical ||
8856 D.getDirectiveKind() == OMPD_section ||
8857 D.getDirectiveKind() == OMPD_master ||
8858 D.getDirectiveKind() == OMPD_masked ||
8859 D.getDirectiveKind() == OMPD_unroll ||
8860 D.getDirectiveKind() == OMPD_assume) {
8865 OMPSimdLexicalScope
Scope(*
this, D);
8866 CGM.getOpenMPRuntime().emitInlinedDirective(
8869 : D.getDirectiveKind(),
Defines the clang::ASTContext interface.
static bool isAllocatableDecl(const VarDecl *VD)
static const VarDecl * getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE)
static void emitTargetRegion(CodeGenFunction &CGF, const OMPTargetDirective &S, PrePostActionTy &Action)
static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S, PrePostActionTy &Action)
static const VarDecl * getBaseDecl(const Expr *Ref)
static void emitTargetTeamsGenericLoopRegionAsParallel(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsGenericLoopDirective &S)
static void emitOMPAtomicReadExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, const Expr *X, const Expr *V, SourceLocation Loc)
static void emitOMPAtomicCaptureExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, bool IsPostfixUpdate, const Expr *V, const Expr *X, const Expr *E, const Expr *UE, bool IsXLHSInRHSPart, SourceLocation Loc)
static void emitScanBasedDirective(CodeGenFunction &CGF, const OMPLoopDirective &S, llvm::function_ref< llvm::Value *(CodeGenFunction &)> NumIteratorsGen, llvm::function_ref< void(CodeGenFunction &)> FirstGen, llvm::function_ref< void(CodeGenFunction &)> SecondGen)
Emits the code for the directive with inscan reductions.
static void emitSimpleAtomicStore(CodeGenFunction &CGF, llvm::AtomicOrdering AO, LValue LVal, RValue RVal)
static bool isSupportedByOpenMPIRBuilder(const OMPTaskgroupDirective &T)
static Address castValueFromUintptr(CodeGenFunction &CGF, SourceLocation Loc, QualType DstType, StringRef Name, LValue AddrLV)
static bool canEmitGPUFusedDistSchedule(const CodeGenModule &CGM, const OMPLoopDirective &S, OpenMPDirectiveKind DKind)
Whether a combined distribute parallel for may use the fused distr_static_chunk + static_chunkone sch...
static void emitDistributeParallelForDistributeInnerBoundParams(CodeGenFunction &CGF, const OMPExecutableDirective &S, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars)
static void emitScanBasedDirectiveFinals(CodeGenFunction &CGF, const OMPLoopDirective &S, llvm::function_ref< llvm::Value *(CodeGenFunction &)> NumIteratorsGen)
Copies final inscan reductions values to the original variables.
static void checkForLastprivateConditionalUpdate(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static std::pair< LValue, LValue > emitForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S)
The following two functions generate expressions for the loop lower and upper bounds in case of stati...
static void emitTargetParallelForRegion(CodeGenFunction &CGF, const OMPTargetParallelForDirective &S, PrePostActionTy &Action)
static llvm::Function * emitOutlinedFunctionPrologueAggregate(CodeGenFunction &CGF, FunctionArgList &Args, llvm::MapVector< const Decl *, std::pair< const VarDecl *, Address > > &LocalAddrs, llvm::DenseMap< const Decl *, std::pair< const Expr *, llvm::Value * > > &VLASizes, llvm::Value *&CXXThisValue, llvm::Value *&ContextV, const CapturedStmt &CS, SourceLocation Loc, StringRef FunctionName)
static LValue EmitOMPHelperVar(CodeGenFunction &CGF, const DeclRefExpr *Helper)
Emit a helper variable and return corresponding lvalue.
static void emitOMPAtomicUpdateExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, const Expr *X, const Expr *E, const Expr *UE, bool IsXLHSInRHSPart, SourceLocation Loc)
static llvm::Value * convertToScalarValue(CodeGenFunction &CGF, RValue Val, QualType SrcType, QualType DestType, SourceLocation Loc)
static llvm::Function * emitOutlinedOrderedFunction(CodeGenModule &CGM, const CapturedStmt *S, const OMPExecutableDirective &D)
static void emitPreCond(CodeGenFunction &CGF, const OMPLoopDirective &S, const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount)
static std::pair< bool, RValue > emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X, RValue Update, BinaryOperatorKind BO, llvm::AtomicOrdering AO, bool IsXLHSInRHSPart)
static std::pair< LValue, LValue > emitDistributeParallelForInnerBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitTargetTeamsGenericLoopRegionAsDistribute(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsGenericLoopDirective &S)
static void emitTargetParallelRegion(CodeGenFunction &CGF, const OMPTargetParallelDirective &S, PrePostActionTy &Action)
static std::pair< llvm::Value *, llvm::Value * > emitDispatchForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S, Address LB, Address UB)
When dealing with dispatch schedules (e.g.
static void emitMaster(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitRestoreIP(CodeGenFunction &CGF, const T *C, llvm::OpenMPIRBuilder::InsertPointTy AllocaIP, llvm::OpenMPIRBuilder &OMPBuilder)
static void emitCommonOMPTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, const RegionCodeGenTy &CodeGen)
static void emitSimdlenSafelenClause(CodeGenFunction &CGF, const OMPExecutableDirective &D)
static void emitAlignedClause(CodeGenFunction &CGF, const OMPExecutableDirective &D)
static bool isSimdSupportedByOpenMPIRBuilder(const OMPLoopDirective &S)
static void emitCommonOMPParallelDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, const CodeGenBoundParametersTy &CodeGenBoundParameters)
static void applyConservativeSimdOrderedDirective(const Stmt &AssociatedStmt, LoopInfoStack &LoopStack)
static bool emitWorksharingDirective(CodeGenFunction &CGF, const OMPLoopDirective &S, bool HasCancel)
static void emitPostUpdateForReductionClause(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
static void emitEmptyOrdered(CodeGenFunction &, SourceLocation Loc, const unsigned IVSize, const bool IVSigned)
static void emitTargetTeamsLoopCodegenStatus(CodeGenFunction &CGF, std::string StatusMsg, const OMPExecutableDirective &D)
static bool isForSupportedByOpenMPIRBuilder(const OMPLoopDirective &S, bool HasCancel)
static RValue emitSimpleAtomicLoad(CodeGenFunction &CGF, llvm::AtomicOrdering AO, LValue LVal, SourceLocation Loc)
static std::pair< llvm::Value *, llvm::Value * > emitDistributeParallelForDispatchBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S, Address LB, Address UB)
if the 'for' loop has a dispatch schedule (e.g.
static 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)
RawAddress CreateMemTempWithoutCast(QualType T, const Twine &Name="tmp")
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen without...
void EmitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &S)
void EmitOMPMaskedTaskLoopSimdDirective(const OMPMaskedTaskLoopSimdDirective &S)
std::pair< bool, RValue > EmitOMPAtomicSimpleUpdateExpr(LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart, llvm::AtomicOrdering AO, SourceLocation Loc, const llvm::function_ref< RValue(RValue)> CommonGen)
Emit atomic update code for constructs: X = X BO E or X = E BO E.
VlaSizePair getVLASize(const VariableArrayType *vla)
Returns an LLVM value that corresponds to the size, in non-variably-sized elements,...
void EmitOMPParallelDirective(const OMPParallelDirective &S)
void EmitOMPTaskDirective(const OMPTaskDirective &S)
void EmitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective &S)
void EmitOMPDistributeParallelForDirective(const OMPDistributeParallelForDirective &S)
void EmitOMPAssumeDirective(const OMPAssumeDirective &S)
int ExpectedOMPLoopDepth
Number of nested loop to be consumed by the last surrounding loop-associated directive.
void EmitOMPPrivateClause(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
void EmitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &S)
ASTContext & getContext() const
void EmitStopPoint(const Stmt *S)
EmitStopPoint - Emit a debug stoppoint if we are emitting debug info.
void EmitOMPTargetUpdateDirective(const OMPTargetUpdateDirective &S)
llvm::Value * EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, AlignmentSource Source=AlignmentSource::Type, bool isNontemporal=false)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
void EmitOMPTargetTeamsGenericLoopDirective(const OMPTargetTeamsGenericLoopDirective &S)
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
void EmitAutoVarCleanups(const AutoVarEmission &emission)
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
SmallVector< llvm::CanonicalLoopInfo *, 4 > OMPLoopNestStack
List of recently emitted OMPCanonicalLoops.
void EmitOMPTeamsDistributeParallelForDirective(const OMPTeamsDistributeParallelForDirective &S)
llvm::AtomicRMWInst * emitAtomicRMWInst(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val, llvm::AtomicOrdering Order=llvm::AtomicOrdering::SequentiallyConsistent, llvm::SyncScope::ID SSID=llvm::SyncScope::System, const AtomicExpr *AE=nullptr)
Emit an atomicrmw instruction, and applying relevant metadata when applicable.
void EmitOMPFuseDirective(const OMPFuseDirective &S)
void EmitOMPTargetTeamsDistributeDirective(const OMPTargetTeamsDistributeDirective &S)
void EmitOMPUseDevicePtrClause(const OMPUseDevicePtrClause &C, OMPPrivateScope &PrivateScope, const llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap)
RValue EmitAnyExpr(const Expr *E, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
EmitAnyExpr - Emit code to compute the specified expression which can have any type.
void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs={})
EmitStmt - Emit the code for the statement.
llvm::DenseMap< const ValueDecl *, FieldDecl * > LambdaCaptureFields
void EmitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &S)
llvm::Type * ConvertTypeForMem(QualType T)
void EmitOMPInnerLoop(const OMPExecutableDirective &S, bool RequiresCleanup, const Expr *LoopCond, const Expr *IncExpr, const llvm::function_ref< void(CodeGenFunction &)> BodyGen, const llvm::function_ref< void(CodeGenFunction &)> PostIncGen)
Emit inner loop of the worksharing/simd construct.
void EmitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective &S)
static void EmitOMPTargetTeamsDistributeParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForDirective &S)
void EmitOMPTargetDirective(const OMPTargetDirective &S)
static void EmitOMPTargetParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForSimdDirective &S)
Emit device code for the target parallel for simd directive.
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
llvm::BasicBlock * OMPScanExitBlock
void EmitOMPTeamsDirective(const OMPTeamsDirective &S)
void EmitSimpleOMPExecutableDirective(const OMPExecutableDirective &D)
Emit simple code for OpenMP directives in Simd-only mode.
void EmitOMPErrorDirective(const OMPErrorDirective &S)
void EmitOMPTargetTaskBasedDirective(const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen, OMPTargetDataInfo &InputInfo)
void EmitOMPParallelMaskedTaskLoopSimdDirective(const OMPParallelMaskedTaskLoopSimdDirective &S)
void EmitOMPTargetTeamsDirective(const OMPTargetTeamsDirective &S)
void EmitOMPTargetDataDirective(const OMPTargetDataDirective &S)
Address GenerateCapturedStmtArgument(const CapturedStmt &S)
bool EmitOMPLastprivateClauseInit(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
Emit initial code for lastprivate variables.
static void EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForSimdDirective &S)
Emit device code for the target teams distribute parallel for simd directive.
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
llvm::Function * GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S, const OMPExecutableDirective &D)
void EmitOMPSimdDirective(const OMPSimdDirective &S)
RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
Address EmitLoadOfReference(LValue RefLVal, LValueBaseInfo *PointeeBaseInfo=nullptr, TBAAAccessInfo *PointeeTBAAInfo=nullptr)
void EmitOMPParallelGenericLoopDirective(const OMPLoopDirective &S)
void EmitOMPTargetSimdDirective(const OMPTargetSimdDirective &S)
void EmitOMPTeamsGenericLoopDirective(const OMPTeamsGenericLoopDirective &S)
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
bool EmitOMPLinearClauseInit(const OMPLoopDirective &D)
Emit initial code for linear variables.
static void EmitOMPTargetParallelGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelGenericLoopDirective &S)
Emit device code for the target parallel loop directive.
void EmitOMPUnrollDirective(const OMPUnrollDirective &S)
void EmitOMPStripeDirective(const OMPStripeDirective &S)
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitOMPSingleDirective(const OMPSingleDirective &S)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
llvm::function_ref< void(CodeGenFunction &, SourceLocation, const unsigned, const bool)> CodeGenOrderedTy
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
llvm::Value * EmitFromMemory(llvm::Value *Value, QualType Ty)
EmitFromMemory - Change a scalar value from its memory representation to its value representation.
static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S)
Emit device code for the target simd directive.
llvm::Function * GenerateCapturedStmtFunction(const CapturedStmt &S)
Creates the outlined function for a CapturedStmt.
static void EmitOMPTargetParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForDirective &S)
Emit device code for the target parallel for directive.
uint64_t getProfileCount(const Stmt *S)
Get the profiler's count for the given statement.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)
ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant,...
static void EmitOMPTargetTeamsGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsGenericLoopDirective &S)
Emit device code for the target teams loop directive.
void EmitOMPTileDirective(const OMPTileDirective &S)
void EmitDecl(const Decl &D, bool EvaluateConditionDecl=false)
EmitDecl - Emit a declaration.
void EmitOMPAtomicDirective(const OMPAtomicDirective &S)
llvm::BasicBlock * OMPAfterScanBlock
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
ConstantEmission tryEmitAsConstant(const DeclRefExpr *RefExpr)
Try to emit a reference to the given value without producing it as an l-value.
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
void EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst)
Store of global named registers are always calls to intrinsics.
void EmitOMPParallelMasterTaskLoopDirective(const OMPParallelMasterTaskLoopDirective &S)
void EmitOMPDistributeParallelForSimdDirective(const OMPDistributeParallelForSimdDirective &S)
void EmitOMPSectionDirective(const OMPSectionDirective &S)
void EnsureInsertPoint()
EnsureInsertPoint - Ensure that an insertion point is defined so that emitted IR has a place to go.
void EmitOMPForSimdDirective(const OMPForSimdDirective &S)
llvm::LLVMContext & getLLVMContext()
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
void emitAlignmentAssumption(llvm::Value *PtrValue, QualType Ty, SourceLocation Loc, SourceLocation AssumptionLoc, llvm::Value *Alignment, llvm::Value *OffsetValue=nullptr)
static void EmitOMPTargetTeamsDistributeSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeSimdDirective &S)
Emit device code for the target teams distribute simd directive.
llvm::function_ref< void(CodeGenFunction &, const OMPLoopDirective &, JumpDest)> CodeGenLoopTy
llvm::Value * EmitScalarConversion(llvm::Value *Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified type to the specified destination type, both of which are LLVM s...
bool isTrivialInitializer(const Expr *Init)
Determine whether the given initializer is trivial in the sense that it requires no code to be genera...
void EmitOMPParallelMasterDirective(const OMPParallelMasterDirective &S)
void EmitOMPTaskBasedDirective(const OMPExecutableDirective &S, const OpenMPDirectiveKind CapturedRegion, const RegionCodeGenTy &BodyGen, const TaskGenTy &TaskGen, OMPTaskDataTy &Data)
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
void EmitOMPForDirective(const OMPForDirective &S)
void EmitOMPLinearClauseFinal(const OMPLoopDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
Emit final code for linear clauses.
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
void EmitExprAsInit(const Expr *init, const ValueDecl *D, LValue lvalue, bool capturedByInit)
EmitExprAsInit - Emits the code necessary to initialize a location in memory with the given initializ...
void EmitOMPSimdFinal(const OMPLoopDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
This class organizes the cross-function state that is used while generating LLVM code.
void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)
Set the attributes on the LLVM function for the given decl and function info.
llvm::Module & getModule() const
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
CodeGenTypes & getTypes()
const llvm::DataLayout & getDataLayout() const
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
const llvm::Triple & getTriple() const
ASTContext & getContext() const
const CodeGenOptions & getCodeGenOpts() const
StringRef getMangledName(GlobalDecl GD)
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
const CGFunctionInfo & arrangeDeviceKernelCallerDeclaration(QualType resultType, const FunctionArgList &args)
A device kernel caller function is an offload device entry point function with a target device depend...
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
llvm::Value * getPointer(CodeGenFunction &CGF) const
Address getAddress() const
void setAddress(Address address)
A stack of loop information corresponding to loop nesting levels.
void setVectorizeWidth(unsigned W)
Set the vectorize width for the next loop pushed.
void setParallel(bool Enable=true)
Set the next pushed loop as parallel.
void push(llvm::BasicBlock *Header, const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc)
Begin a new structured loop.
void setVectorizeEnable(bool Enable=true)
Set the next pushed loop 'vectorize.enable'.
A basic class for pre|post-action for advanced codegen sequence for OpenMP region.
virtual void Enter(CodeGenFunction &CGF)
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
static RValue getComplex(llvm::Value *V1, llvm::Value *V2)
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
std::pair< llvm::Value *, llvm::Value * > getComplexVal() const
getComplexVal - Return the real/imag components of this complex value.
An abstract representation of an aligned address.
llvm::PointerType * getType() const
Return the type of the pointer value.
llvm::Value * getPointer() const
Class intended to support codegen of all kind of the reduction clauses.
LValue getSharedLValue(unsigned N) const
Returns LValue for the reduction item.
void emitAggregateType(CodeGenFunction &CGF, unsigned N)
Emits the code for the variable-modified type, if required.
const VarDecl * getBaseDecl(unsigned N) const
Returns the base declaration of the reduction item.
void emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N)
Emits lvalue for the shared and original reduction item.
void emitInitialization(CodeGenFunction &CGF, unsigned N, Address PrivateAddr, Address SharedAddr, llvm::function_ref< bool(CodeGenFunction &)> DefaultInit)
Performs initialization of the private copy for the reduction item.
Address adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Adjusts PrivatedAddr for using instead of the original variable address in normal operations.
Class provides a way to call simple version of codegen for OpenMP region, or an advanced with possibl...
void setAction(PrePostActionTy &Action) const
Complex values, per C99 6.2.5p11.
CompoundStmt - This represents a group of statements like { stmt stmt }.
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
A reference to a declared variable, function, enum, etc.
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Decl - This represents one declaration (or definition), e.g.
SourceLocation getBodyRBrace() const
getBodyRBrace - Gets the right brace of the body, if a body exists.
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
SourceLocation getLocation() const
The name of a declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreImplicitAsWritten() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
Represents a function declaration or definition.
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin=false, bool isInlineSpecified=false, bool hasWrittenPrototype=true, ConstexprSpecKind ConstexprKind=ConstexprSpecKind::Unspecified, const AssociatedConstraint &TrailingRequiresClause={})
GlobalDecl - represents a global declaration.
One of these records is kept for each identifier that is lexed.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
std::vector< llvm::Triple > OMPTargetTriples
Triples of the OpenMP targets that the host code codegen should take into account in order to generat...
Represents a point when we exit a loop.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
A C++ nested-name-specifier augmented with source location information.
This is a basic class for representing single OpenMP clause.
This represents 'final' clause in the 'pragma omp ...' directive.
Representation of the 'full' clause of the 'pragma omp unroll' directive.
This represents 'if' clause in the 'pragma omp ...' directive.
This represents 'num_threads' clause in the 'pragma omp ...' directive.
Representation of the 'partial' clause of the 'pragma omp unroll' directive.
This represents 'safelen' clause in the 'pragma omp ...' directive.
This represents 'simdlen' clause in the 'pragma omp ...' directive.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
PointerType - C99 6.7.5.1 - Pointer Declarators.
Represents an unpacked "presumed" location which can be presented to the user.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
If a crash happens while one of these objects are live, the message is printed out along with the spe...
A (possibly-)qualified type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Represents a struct/union/class.
unsigned getNumFields() const
Returns the number of fields (non-static data members) in this record.
field_range fields() const
field_iterator field_begin() const
Base for LValueReferenceType and RValueReferenceType.
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
A trivial tuple used to represent a source range.
Stmt - This represents one statement.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
SourceLocation getBeginLoc() const LLVM_READONLY
bool isPointerType() const
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isLValueReferenceType() const
bool isAnyComplexType() const
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
static UnaryOperator * Create(const ASTContext &C, Expr *input, Opcode opc, QualType type, ExprValueKind VK, ExprObjectKind OK, SourceLocation l, bool CanOverflow, FPOptionsOverride FPFeatures)
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
TLSKind getTLSKind() const
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
@ CInit
C-style initialization with assignment.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
const Expr * getInit() const
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
@ TLS_None
Not a TLS variable.
Represents a C array with a specified size that is not an integer-constant-expression.
Expr * getSizeExpr() const
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
@ Address
A pointer to a ValueDecl.
bool Inc(InterpState &S, CodePtr OpPC, bool CanOverflow)
1) Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value increased by ...
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.
bool UseFusedDistChunkSchedule
Request the fused distr_static_chunk + static_chunkone runtime schedule in for_static_init.
OpenMPScheduleClauseModifier M2
OpenMPScheduleClauseModifier M1
OpenMPScheduleClauseKind Schedule