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 *PtrTy = CGF.
Builder.getPtrTy();
756 llvm::Align PtrAlign = CGM.
getDataLayout().getPointerABIAlignment(0);
759 for (
auto [FD,
C, FieldIdx] :
762 llvm::Value *SlotPtr =
763 CGF.
Builder.CreateConstInBoundsGEP1_32(PtrTy, ContextV, FieldIdx);
769 if (
C.capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
770 const VarDecl *CurVD =
C.getCapturedVar();
771 Slot->setName(CurVD->
getName());
772 Address SlotAddr(Slot, PtrTy, SlotAlign);
773 LocalAddrs.insert({FD, {CurVD, SlotAddr}});
774 }
else if (FD->hasCapturedVLAType()) {
781 VLASizes.try_emplace(FD, VAT->
getSizeExpr(), ExprArg);
782 }
else if (
C.capturesVariable()) {
783 const VarDecl *Var =
C.getCapturedVar();
787 Slot->setName(Var->
getName() +
".addr");
788 Address SlotAddr(Slot, PtrTy, SlotAlign);
789 LocalAddrs.insert({FD, {Var, SlotAddr}});
792 PtrTy, Slot, PtrAlign, Var->
getName());
793 LocalAddrs.insert({FD,
797 }
else if (
C.capturesVariableByCopy()) {
798 assert(!FD->getType()->isAnyPointerType() &&
799 "Not expecting a captured pointer.");
800 const VarDecl *Var =
C.getCapturedVar();
815 LocalAddrs.insert({FD, {Var, CopyAddr}});
817 assert(
C.capturesThis() &&
"Default case expected to be CXX 'this'");
820 Address SlotAddr(Slot, PtrTy, SlotAlign);
821 LocalAddrs.insert({FD, {
nullptr, SlotAddr}});
833 "CapturedStmtInfo should be set when generating the captured function");
836 bool NeedWrapperFunction =
839 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs,
841 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes,
844 llvm::raw_svector_ostream Out(Buffer);
847 bool IsDeviceKernel =
CGM.getOpenMPRuntime().isGPU() &&
849 D.getCapturedStmt(OMPD_target) == &S;
850 CodeGenFunction WrapperCGF(
CGM,
true);
851 llvm::Function *WrapperF =
nullptr;
852 if (NeedWrapperFunction) {
855 FunctionOptions WrapperFO(&S,
true,
862 WrapperCGF.CXXThisValue, WrapperFO);
865 FunctionOptions FO(&S, !NeedWrapperFunction,
false,
866 Out.str(), Loc, !NeedWrapperFunction && IsDeviceKernel);
868 *
this, WrapperArgs, WrapperLocalAddrs, WrapperVLASizes, CXXThisValue, FO);
870 for (
const auto &LocalAddrPair : WrapperLocalAddrs) {
871 if (LocalAddrPair.second.first) {
872 LocalScope.addPrivate(LocalAddrPair.second.first,
873 LocalAddrPair.second.second);
876 (void)LocalScope.Privatize();
877 for (
const auto &VLASizePair : WrapperVLASizes)
878 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
881 LocalScope.ForceCleanup();
883 if (!NeedWrapperFunction)
887 WrapperF->removeFromParent();
888 F->getParent()->getFunctionList().insertAfter(F->getIterator(), WrapperF);
891 auto *PI = F->arg_begin();
892 for (
const auto *Arg : Args) {
894 auto I = LocalAddrs.find(Arg);
895 if (I != LocalAddrs.end()) {
898 I->second.first ? I->second.first->getType() : Arg->getType(),
904 auto EI = VLASizes.find(Arg);
905 if (EI != VLASizes.end()) {
917 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
927 "CapturedStmtInfo should be set when generating the captured function");
931 bool NeedWrapperFunction =
934 CodeGenFunction WrapperCGF(
CGM,
true);
935 llvm::Function *WrapperF =
nullptr;
936 llvm::Value *WrapperContextV =
nullptr;
937 if (NeedWrapperFunction) {
940 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>>
942 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>>
945 WrapperCGF, WrapperArgs, WrapperLocalAddrs, WrapperVLASizes,
946 WrapperCGF.CXXThisValue, WrapperContextV, S, Loc, FunctionName);
950 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs;
951 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes;
954 if (NeedWrapperFunction) {
956 llvm::raw_svector_ostream Out(Buffer);
957 Out << FunctionName <<
"_debug__";
959 FunctionOptions FO(&S,
false,
960 false, Out.str(), Loc,
965 llvm::Value *ContextV =
nullptr;
967 CXXThisValue, ContextV, S, Loc,
976 llvm::Align PtrAlign =
CGM.getDataLayout().getPointerABIAlignment(0);
977 llvm::Value *SlotPtr =
Builder.CreateConstInBoundsGEP1_32(
978 Builder.getPtrTy(), ContextV, FieldIdx,
979 Twine(Param->getName()) +
".addr");
980 llvm::Value *ParamAddr =
982 llvm::Value *ParamVal =
Builder.CreateAlignedLoad(
983 Builder.getPtrTy(), ParamAddr, PtrAlign, Param->getName());
986 Builder.CreateStore(ParamVal, ParamLocalAddr);
987 LocalAddrs.insert({Param, {Param, ParamLocalAddr}});
993 for (
const auto &LocalAddrPair : LocalAddrs) {
994 if (LocalAddrPair.second.first)
995 LocalScope.addPrivate(LocalAddrPair.second.first,
996 LocalAddrPair.second.second);
998 (void)LocalScope.Privatize();
999 for (
const auto &VLASizePair : VLASizes)
1000 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
1001 PGO->assignRegionCounters(
GlobalDecl(CD), F);
1003 (void)LocalScope.ForceCleanup();
1006 if (!NeedWrapperFunction)
1010 WrapperF->removeFromParent();
1011 F->getParent()->getFunctionList().insertAfter(F->getIterator(), WrapperF);
1013 llvm::Align PtrAlign =
CGM.getDataLayout().getPointerABIAlignment(0);
1016 "Expected context param at position 0 for target regions");
1017 assert(RD->
getNumFields() + 1 == F->getNumOperands() &&
1018 "Argument count mismatch");
1020 for (
auto [FD, InnerParam, SlotIdx] : llvm::zip(
1022 llvm::Value *SlotPtr = WrapperCGF.
Builder.CreateConstInBoundsGEP1_32(
1023 WrapperCGF.
Builder.getPtrTy(), WrapperContextV, SlotIdx);
1025 WrapperCGF.
Builder.getPtrTy(), SlotPtr, PtrAlign);
1027 InnerParam.getType(), Slot, PtrAlign, InnerParam.getName());
1028 CallArgs.push_back(Val);
1033 auto InnerParam = F->arg_begin() + SlotIdx;
1034 llvm::Value *SlotPtr = WrapperCGF.
Builder.CreateConstInBoundsGEP1_32(
1035 WrapperCGF.
Builder.getPtrTy(), WrapperContextV, SlotIdx);
1037 WrapperCGF.
Builder.getPtrTy(), SlotPtr, PtrAlign);
1039 InnerParam->getType(), Slot, PtrAlign, InnerParam->getName());
1040 CallArgs.push_back(Val);
1042 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
1058 llvm::Value *NumElements =
emitArrayLength(ArrayTy, ElementTy, DestAddr);
1065 DestBegin, NumElements);
1070 llvm::Value *IsEmpty =
1071 Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arraycpy.isempty");
1072 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
1075 llvm::BasicBlock *EntryBB =
Builder.GetInsertBlock();
1080 llvm::PHINode *SrcElementPHI =
1081 Builder.CreatePHI(SrcBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
1082 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
1087 llvm::PHINode *DestElementPHI =
Builder.CreatePHI(
1088 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
1089 DestElementPHI->addIncoming(DestBegin, EntryBB);
1095 CopyGen(DestElementCurrent, SrcElementCurrent);
1098 llvm::Value *DestElementNext =
1100 1,
"omp.arraycpy.dest.element");
1101 llvm::Value *SrcElementNext =
1103 1,
"omp.arraycpy.src.element");
1106 Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
1107 Builder.CreateCondBr(Done, DoneBB, BodyBB);
1108 DestElementPHI->addIncoming(DestElementNext,
Builder.GetInsertBlock());
1109 SrcElementPHI->addIncoming(SrcElementNext,
Builder.GetInsertBlock());
1119 const auto *BO = dyn_cast<BinaryOperator>(
Copy);
1120 if (BO && BO->getOpcode() == BO_Assign) {
1129 DestAddr, SrcAddr, OriginalType,
1157 bool DeviceConstTarget =
getLangOpts().OpenMPIsTargetDevice &&
1159 bool FirstprivateIsLastprivate =
false;
1160 llvm::DenseMap<const VarDecl *, OpenMPLastprivateModifier> Lastprivates;
1161 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1162 for (
const auto *D :
C->varlist())
1163 Lastprivates.try_emplace(
1167 llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
1172 bool MustEmitFirstprivateCopy =
1173 CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown;
1174 for (
const auto *
C : D.getClausesOfKind<OMPFirstprivateClause>()) {
1175 const auto *IRef =
C->varlist_begin();
1176 const auto *InitsRef =
C->inits().begin();
1177 for (
const Expr *IInit :
C->private_copies()) {
1179 bool ThisFirstprivateIsLastprivate =
1180 Lastprivates.count(OrigVD->getCanonicalDecl()) > 0;
1183 if (!MustEmitFirstprivateCopy && !ThisFirstprivateIsLastprivate && FD &&
1185 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
1186 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
1193 if (DeviceConstTarget && OrigVD->getType().isConstant(
getContext()) &&
1195 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
1196 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
1201 FirstprivateIsLastprivate =
1202 FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate;
1203 if (EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()).second) {
1204 const auto *VDInit =
1223 assert(!CE &&
"Expected non-constant firstprivate.");
1230 if (
Type->isArrayType()) {
1246 RunCleanupsScope InitScope(*this);
1248 setAddrOfLocalVar(VDInit, SrcElement);
1249 EmitAnyExprToMem(Init, DestElement,
1250 Init->getType().getQualifiers(),
1252 LocalDeclMap.erase(VDInit);
1263 setAddrOfLocalVar(VDInit, OriginalAddr);
1265 LocalDeclMap.erase(VDInit);
1267 if (ThisFirstprivateIsLastprivate &&
1268 Lastprivates[OrigVD->getCanonicalDecl()] ==
1269 OMPC_LASTPRIVATE_conditional) {
1274 (*IRef)->getExprLoc());
1275 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1279 LocalDeclMap.erase(VD);
1280 setAddrOfLocalVar(VD, VDAddr);
1282 IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1284 assert(IsRegistered &&
1285 "firstprivate var already registered as private");
1293 return FirstprivateIsLastprivate && !EmittedAsFirstprivate.empty();
1301 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
1302 for (
const auto *
C : D.getClausesOfKind<OMPPrivateClause>()) {
1303 auto IRef =
C->varlist_begin();
1304 for (
const Expr *IInit :
C->private_copies()) {
1306 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
1312 assert(IsRegistered &&
"private var already registered as private");
1328 llvm::DenseSet<const VarDecl *> CopiedVars;
1329 llvm::BasicBlock *CopyBegin =
nullptr, *CopyEnd =
nullptr;
1331 auto IRef =
C->varlist_begin();
1332 auto ISrcRef =
C->source_exprs().begin();
1333 auto IDestRef =
C->destination_exprs().begin();
1334 for (
const Expr *AssignOp :
C->assignment_ops()) {
1343 getContext().getTargetInfo().isTLSSupported()) {
1345 "Copyin threadprivates should have been captured!");
1349 LocalDeclMap.erase(VD);
1353 :
CGM.GetAddrOfGlobal(VD),
1354 CGM.getTypes().ConvertTypeForMem(VD->
getType()),
1359 if (CopiedVars.size() == 1) {
1365 auto *MasterAddrInt =
Builder.CreatePtrToInt(
1367 auto *PrivateAddrInt =
Builder.CreatePtrToInt(
1370 Builder.CreateICmpNE(MasterAddrInt, PrivateAddrInt), CopyBegin,
1376 const auto *DestVD =
1397 bool HasAtLeastOneLastprivate =
false;
1399 llvm::DenseSet<const VarDecl *> SIMDLCVs;
1402 for (
const Expr *
C : LoopDirective->counters()) {
1407 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1408 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1409 HasAtLeastOneLastprivate =
true;
1412 const auto *IRef =
C->varlist_begin();
1413 const auto *IDestRef =
C->destination_exprs().begin();
1414 for (
const Expr *IInit :
C->private_copies()) {
1420 if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) {
1421 const auto *DestVD =
1426 (*IRef)->getType(),
VK_LValue, (*IRef)->getExprLoc());
1431 if (IInit && !SIMDLCVs.count(OrigVD->getCanonicalDecl())) {
1434 if (
C->getKind() == OMPC_LASTPRIVATE_conditional) {
1435 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1437 setAddrOfLocalVar(VD, VDAddr);
1443 bool IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1444 assert(IsRegistered &&
1445 "lastprivate var already registered as private");
1453 return HasAtLeastOneLastprivate;
1458 llvm::Value *IsLastIterCond) {
1467 llvm::BasicBlock *ThenBB =
nullptr;
1468 llvm::BasicBlock *DoneBB =
nullptr;
1469 if (IsLastIterCond) {
1473 llvm::any_of(D.getClausesOfKind<OMPLastprivateClause>(),
1474 [](
const OMPLastprivateClause *
C) {
1475 return C->getKind() == OMPC_LASTPRIVATE_conditional;
1477 CGM.getOpenMPRuntime().emitBarrierCall(*
this, D.getBeginLoc(),
1484 Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB);
1487 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1488 llvm::DenseMap<const VarDecl *, const Expr *> LoopCountersAndUpdates;
1489 if (
const auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) {
1490 auto IC = LoopDirective->counters().begin();
1491 for (
const Expr *F : LoopDirective->finals()) {
1495 AlreadyEmittedVars.insert(D);
1497 LoopCountersAndUpdates[D] = F;
1501 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1502 auto IRef =
C->varlist_begin();
1503 auto ISrcRef =
C->source_exprs().begin();
1504 auto IDestRef =
C->destination_exprs().begin();
1505 for (
const Expr *AssignOp :
C->assignment_ops()) {
1506 const auto *PrivateVD =
1509 const auto *CanonicalVD = PrivateVD->getCanonicalDecl();
1510 if (AlreadyEmittedVars.insert(CanonicalVD).second) {
1514 if (
const Expr *FinalExpr = LoopCountersAndUpdates.lookup(CanonicalVD))
1518 const auto *DestVD =
1522 if (
const auto *RefTy = PrivateVD->getType()->getAs<
ReferenceType>())
1524 Builder.CreateLoad(PrivateAddr),
1525 CGM.getTypes().ConvertTypeForMem(RefTy->getPointeeType()),
1526 CGM.getNaturalTypeAlignment(RefTy->getPointeeType()));
1528 if (
C->getKind() == OMPC_LASTPRIVATE_conditional)
1529 CGM.getOpenMPRuntime().emitLastprivateConditionalFinalUpdate(
1531 (*IRef)->getExprLoc());
1534 EmitOMPCopy(
Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp);
1540 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
1560 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1561 if (ForInscan != (
C->getModifier() == OMPC_REDUCTION_inscan))
1563 Shareds.append(
C->varlist_begin(),
C->varlist_end());
1564 Privates.append(
C->privates().begin(),
C->privates().end());
1565 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1566 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1567 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1568 if (
C->getModifier() == OMPC_REDUCTION_task) {
1569 Data.ReductionVars.append(
C->privates().begin(),
C->privates().end());
1570 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
1571 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
1572 Data.ReductionOps.append(
C->reduction_ops().begin(),
1573 C->reduction_ops().end());
1574 TaskLHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1575 TaskRHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1580 auto *ILHS = LHSs.begin();
1581 auto *IRHS = RHSs.begin();
1583 for (
const Expr *IRef : Shareds) {
1591 [&Emission](CodeGenFunction &CGF) {
1592 CGF.EmitAutoVarInit(Emission);
1600 assert(IsRegistered &&
"private var already registered as private");
1608 if (isaOMPArraySectionExpr &&
Type->isVariablyModifiedType()) {
1613 }
else if ((isaOMPArraySectionExpr &&
Type->isScalarType()) ||
1631 PrivateScope.
addPrivate(LHSVD, OriginalAddr);
1642 if (!
Data.ReductionVars.empty()) {
1644 Data.IsReductionWithTaskMod =
true;
1646 llvm::Value *ReductionDesc =
CGM.getOpenMPRuntime().emitTaskReductionInit(
1647 *
this, D.getBeginLoc(), TaskLHSs, TaskRHSs,
Data);
1648 const Expr *TaskRedRef =
nullptr;
1659 case OMPD_parallel_for:
1662 case OMPD_parallel_master:
1666 case OMPD_parallel_sections:
1670 case OMPD_target_parallel:
1674 case OMPD_target_parallel_for:
1678 case OMPD_distribute_parallel_for:
1682 case OMPD_teams_distribute_parallel_for:
1684 .getTaskReductionRefExpr();
1686 case OMPD_target_teams_distribute_parallel_for:
1688 .getTaskReductionRefExpr();
1696 case OMPD_parallel_for_simd:
1698 case OMPD_taskyield:
1702 case OMPD_taskgroup:
1710 case OMPD_cancellation_point:
1712 case OMPD_target_data:
1713 case OMPD_target_enter_data:
1714 case OMPD_target_exit_data:
1716 case OMPD_taskloop_simd:
1717 case OMPD_master_taskloop:
1718 case OMPD_master_taskloop_simd:
1719 case OMPD_parallel_master_taskloop:
1720 case OMPD_parallel_master_taskloop_simd:
1721 case OMPD_distribute:
1722 case OMPD_target_update:
1723 case OMPD_distribute_parallel_for_simd:
1724 case OMPD_distribute_simd:
1725 case OMPD_target_parallel_for_simd:
1726 case OMPD_target_simd:
1727 case OMPD_teams_distribute:
1728 case OMPD_teams_distribute_simd:
1729 case OMPD_teams_distribute_parallel_for_simd:
1730 case OMPD_target_teams:
1731 case OMPD_target_teams_distribute:
1732 case OMPD_target_teams_distribute_parallel_for_simd:
1733 case OMPD_target_teams_distribute_simd:
1734 case OMPD_declare_target:
1735 case OMPD_end_declare_target:
1736 case OMPD_threadprivate:
1738 case OMPD_declare_reduction:
1739 case OMPD_declare_mapper:
1740 case OMPD_declare_simd:
1742 case OMPD_declare_variant:
1743 case OMPD_begin_declare_variant:
1744 case OMPD_end_declare_variant:
1747 llvm_unreachable(
"Unexpected directive with task reductions.");
1753 false, TaskRedRef->
getType());
1766 bool HasAtLeastOneReduction =
false;
1767 bool IsReductionWithTaskMod =
false;
1768 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1770 if (
C->getModifier() == OMPC_REDUCTION_inscan)
1772 HasAtLeastOneReduction =
true;
1773 Privates.append(
C->privates().begin(),
C->privates().end());
1774 LHSExprs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1775 RHSExprs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1776 IsPrivateVarReduction.append(
C->private_var_reduction_flags().begin(),
1777 C->private_var_reduction_flags().end());
1778 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1779 IsReductionWithTaskMod =
1780 IsReductionWithTaskMod ||
C->getModifier() == OMPC_REDUCTION_task;
1782 if (HasAtLeastOneReduction) {
1784 if (IsReductionWithTaskMod) {
1785 CGM.getOpenMPRuntime().emitTaskReductionFini(
1788 bool TeamsLoopCanBeParallel =
false;
1789 if (
auto *TTLD = dyn_cast<OMPTargetTeamsGenericLoopDirective>(&D))
1790 TeamsLoopCanBeParallel = TTLD->canBeParallelFor();
1791 bool WithNowait = D.getSingleClause<OMPNowaitClause>() ||
1793 TeamsLoopCanBeParallel || ReductionKind == OMPD_simd;
1794 bool SimpleReduction = ReductionKind == OMPD_simd;
1797 CGM.getOpenMPRuntime().emitReduction(
1798 *
this, D.getEndLoc(),
Privates, LHSExprs, RHSExprs, ReductionOps,
1799 {WithNowait, SimpleReduction, IsPrivateVarReduction, ReductionKind});
1808 llvm::BasicBlock *DoneBB =
nullptr;
1809 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1810 if (
const Expr *PostUpdate =
C->getPostUpdateExpr()) {
1812 if (llvm::Value *
Cond = CondGen(CGF)) {
1833 const OMPExecutableDirective &,
1834 llvm::SmallVectorImpl<llvm::Value *> &)>
1835 CodeGenBoundParametersTy;
1843 llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> PrivateDecls;
1844 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
1845 for (
const Expr *Ref :
C->varlist()) {
1846 if (!Ref->getType()->isScalarType())
1848 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1855 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
1856 for (
const Expr *Ref :
C->varlist()) {
1857 if (!Ref->getType()->isScalarType())
1859 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1866 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
1867 for (
const Expr *Ref :
C->varlist()) {
1868 if (!Ref->getType()->isScalarType())
1870 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1881 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
1882 for (
const Expr *Ref :
C->varlist()) {
1883 if (!Ref->getType()->isScalarType())
1885 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1892 CGF, S, PrivateDecls);
1898 const CodeGenBoundParametersTy &CodeGenBoundParameters) {
1899 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
1900 llvm::Value *NumThreads =
nullptr;
1909 llvm::Function *OutlinedFn =
1916 NumThreads = CGF.
EmitScalarExpr(NumThreadsClause->getNumThreads(),
1918 Modifier = NumThreadsClause->getModifier();
1919 if (
const auto *MessageClause = S.getSingleClause<OMPMessageClause>()) {
1920 Message = MessageClause->getMessageString();
1921 MessageLoc = MessageClause->getBeginLoc();
1923 if (
const auto *SeverityClause = S.getSingleClause<OMPSeverityClause>()) {
1924 Severity = SeverityClause->getSeverityKind();
1925 SeverityLoc = SeverityClause->getBeginLoc();
1928 CGF, NumThreads, NumThreadsClause->getBeginLoc(), Modifier, Severity,
1929 SeverityLoc, Message, MessageLoc);
1931 if (
const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>()) {
1934 CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getBeginLoc());
1936 const Expr *IfCond =
nullptr;
1937 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
1938 if (
C->getNameModifier() == OMPD_unknown ||
1939 C->getNameModifier() == OMPD_parallel) {
1940 IfCond =
C->getCondition();
1945 OMPParallelScope
Scope(CGF, S);
1951 CodeGenBoundParameters(CGF, S, CapturedVars);
1954 CapturedVars, IfCond, NumThreads,
1955 Modifier, Severity, Message);
1960 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
1962 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
1964 return !((AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc ||
1965 AA->getAllocatorType() == OMPAllocateDeclAttr::OMPNullMemAlloc) &&
1966 !AA->getAllocator());
1981 CGF, S.getBeginLoc(), OMPD_unknown,
false,
1987 CodeGenFunction &CGF,
const VarDecl *VD) {
1989 auto &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2001 Size = CGF.
Builder.CreateNUWAdd(
2003 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
2004 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
2010 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
2011 assert(AA->getAllocator() &&
2012 "Expected allocator expression for non-default allocator.");
2016 if (Allocator->getType()->isIntegerTy())
2017 Allocator = CGF.
Builder.CreateIntToPtr(Allocator,
CGM.VoidPtrTy);
2018 else if (Allocator->getType()->isPointerTy())
2022 llvm::Value *
Addr = OMPBuilder.createOMPAlloc(
2025 llvm::CallInst *FreeCI =
2026 OMPBuilder.createOMPFree(CGF.
Builder,
Addr, Allocator);
2040 if (
CGM.getLangOpts().OpenMPUseTLS &&
2041 CGM.getContext().getTargetInfo().isTLSSupported())
2044 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2049 llvm::ConstantInt *Size =
CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy));
2051 llvm::Twine CacheName = Twine(
CGM.getMangledName(VD)).concat(Suffix);
2053 llvm::CallInst *ThreadPrivateCacheCall =
2054 OMPBuilder.createCachedThreadPrivate(CGF.
Builder,
Data, Size, CacheName);
2062 llvm::raw_svector_ostream OS(Buffer);
2063 StringRef Sep = FirstSeparator;
2064 for (StringRef Part : Parts) {
2068 return OS.str().str();
2076 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
2077 "." + RegionName +
".after");
2093 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
2094 "." + RegionName +
".after");
2106 if (
CGM.getLangOpts().OpenMPIRBuilder) {
2107 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2109 llvm::Value *IfCond =
nullptr;
2114 llvm::Value *NumThreads =
nullptr;
2119 ProcBindKind ProcBind = OMP_PROC_BIND_default;
2120 if (
const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>())
2121 ProcBind = ProcBindClause->getProcBindKind();
2123 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2127 auto FiniCB = [
this](InsertPointTy IP) {
2129 return llvm::Error::success();
2136 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
2137 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
2148 auto BodyGenCB = [&,
this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
2151 *
this, ParallelRegionBodyStmt, AllocIP, CodeGenIP,
"parallel");
2152 return llvm::Error::success();
2157 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
2159 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2160 cantFail(OMPBuilder.createParallel(
2161 Builder, AllocaIP, {}, BodyGenCB, PrivCB, FiniCB,
2162 IfCond, NumThreads, ProcBind, S.hasCancel()));
2176 CGF.
EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt());
2185 [](CodeGenFunction &) {
return nullptr; });
2197class OMPTransformDirectiveScopeRAII {
2198 OMPLoopScope *
Scope =
nullptr;
2202 OMPTransformDirectiveScopeRAII(
const OMPTransformDirectiveScopeRAII &) =
2204 OMPTransformDirectiveScopeRAII &
2205 operator=(
const OMPTransformDirectiveScopeRAII &) =
delete;
2209 if (
const auto *Dir = dyn_cast<OMPLoopBasedDirective>(S)) {
2210 Scope =
new OMPLoopScope(CGF, *Dir);
2213 }
else if (
const auto *Dir =
2214 dyn_cast<OMPCanonicalLoopSequenceTransformationDirective>(
2219 Scope =
new OMPLoopScope(CGF, *Dir);
2224 ~OMPTransformDirectiveScopeRAII() {
2235 int MaxLevel,
int Level = 0) {
2236 assert(Level < MaxLevel &&
"Too deep lookup during loop body codegen.");
2238 if (
const auto *CS = dyn_cast<CompoundStmt>(SimplifiedS)) {
2241 "LLVM IR generation of compound statement ('{}')");
2245 for (
const Stmt *CurStmt : CS->body())
2246 emitBody(CGF, CurStmt, NextLoop, MaxLevel, Level);
2249 if (SimplifiedS == NextLoop) {
2250 if (
auto *Dir = dyn_cast<OMPLoopTransformationDirective>(SimplifiedS))
2251 SimplifiedS = Dir->getTransformedStmt();
2252 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(SimplifiedS))
2253 SimplifiedS = CanonLoop->getLoopStmt();
2254 if (
const auto *For = dyn_cast<ForStmt>(SimplifiedS)) {
2258 "Expected canonical for loop or range-based for loop.");
2260 CGF.
EmitStmt(CXXFor->getLoopVarStmt());
2261 S = CXXFor->getBody();
2263 if (Level + 1 < MaxLevel) {
2264 NextLoop = OMPLoopDirective::tryToFindNextInnerLoop(
2266 emitBody(CGF, S, NextLoop, MaxLevel, Level + 1);
2277 for (
const Expr *UE : D.updates())
2284 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2285 for (
const Expr *UE :
C->updates())
2292 BreakContinueStack.push_back(BreakContinue(D,
LoopExit, Continue));
2293 for (
const Expr *E : D.finals_conditions()) {
2306 bool IsInscanRegion = InscanScope.
Privatize();
2307 if (IsInscanRegion) {
2317 if (EKind != OMPD_simd && !
getLangOpts().OpenMPSimd)
2326 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
2329 OMPLoopBasedDirective::tryToFindNextInnerLoop(
2331 D.getLoopsNumber());
2339 BreakContinueStack.pop_back();
2350 std::unique_ptr<CodeGenFunction::CGCapturedStmtInfo> CSI =
2351 std::make_unique<CodeGenFunction::CGCapturedStmtInfo>(*S);
2355 return {F, CapStruct.getPointer(
ParentCGF)};
2359static llvm::CallInst *
2364 EffectiveArgs.reserve(Args.size() + 1);
2365 llvm::append_range(EffectiveArgs, Args);
2366 EffectiveArgs.push_back(Cap.second);
2371llvm::CanonicalLoopInfo *
2373 assert(Depth == 1 &&
"Nested loops with OpenMPIRBuilder not yet implemented");
2399 const Stmt *SyntacticalLoop = S->getLoopStmt();
2410 const Stmt *BodyStmt;
2411 if (
const auto *For = dyn_cast<ForStmt>(SyntacticalLoop)) {
2412 if (
const Stmt *InitStmt = For->getInit())
2414 BodyStmt = For->getBody();
2415 }
else if (
const auto *RangeFor =
2416 dyn_cast<CXXForRangeStmt>(SyntacticalLoop)) {
2417 if (
const DeclStmt *RangeStmt = RangeFor->getRangeStmt())
2419 if (
const DeclStmt *BeginStmt = RangeFor->getBeginStmt())
2421 if (
const DeclStmt *EndStmt = RangeFor->getEndStmt())
2423 if (
const DeclStmt *LoopVarStmt = RangeFor->getLoopVarStmt())
2425 BodyStmt = RangeFor->getBody();
2427 llvm_unreachable(
"Expected for-stmt or range-based for-stmt");
2430 const CapturedStmt *DistanceFunc = S->getDistanceFunc();
2443 llvm::Value *DistVal =
Builder.CreateLoad(CountAddr,
".count");
2446 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2447 auto BodyGen = [&,
this](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP,
2448 llvm::Value *IndVar) {
2453 const DeclRefExpr *LoopVarRef = S->getLoopVarRef();
2461 return llvm::Error::success();
2464 llvm::CanonicalLoopInfo *
CL =
2465 cantFail(OMPBuilder.createCanonicalLoop(
Builder, BodyGen, DistVal));
2477 const Expr *IncExpr,
2478 const llvm::function_ref<
void(CodeGenFunction &)> BodyGen,
2479 const llvm::function_ref<
void(CodeGenFunction &)> PostIncGen) {
2489 const CapturedStmt *ICS = OMPED.getInnermostCapturedStmt();
2503 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
2504 if (RequiresCleanup)
2511 if (ExitBlock !=
LoopExit.getBlock()) {
2521 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
2529 BreakContinueStack.pop_back();
2540 bool HasLinears =
false;
2541 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2545 if (
const auto *Ref =
2564 if (
const auto *CS = cast_or_null<BinaryOperator>(
C->getCalcStep()))
2576 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2579 llvm::BasicBlock *DoneBB =
nullptr;
2581 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2582 auto IC =
C->varlist_begin();
2583 for (
const Expr *F :
C->finals()) {
2585 if (llvm::Value *
Cond = CondGen(*
this)) {
2597 (*IC)->getType(),
VK_LValue, (*IC)->getExprLoc());
2605 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
2617 llvm::APInt ClauseAlignment(64, 0);
2618 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
2621 ClauseAlignment = AlignmentCI->getValue();
2623 for (
const Expr *E : Clause->varlist()) {
2624 llvm::APInt Alignment(ClauseAlignment);
2625 if (Alignment == 0) {
2632 E->getType()->getPointeeType()))
2635 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2636 "alignment is not power of 2");
2637 if (Alignment != 0) {
2651 auto I = S.private_counters().begin();
2652 for (
const Expr *E : S.counters()) {
2658 LocalDeclMap.erase(PrivateVD);
2664 E->getType(),
VK_LValue, E->getExprLoc());
2672 for (
const auto *
C : S.getClausesOfKind<OMPOrderedClause>()) {
2673 if (!
C->getNumForLoops())
2675 for (
unsigned I = S.getLoopsNumber(), E =
C->getLoopNumIterations().size();
2681 if (DRE->refersToEnclosingVariableOrCapture()) {
2690 const Expr *
Cond, llvm::BasicBlock *TrueBlock,
2691 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
2699 for (
const Expr *I : S.inits()) {
2706 for (
const Expr *E : S.dependent_counters()) {
2709 assert(!E->getType().getNonReferenceType()->isRecordType() &&
2710 "dependent counter must not be an iterator.");
2714 (void)PreCondVars.
setVarAddr(CGF, VD, CounterAddr);
2716 (void)PreCondVars.
apply(CGF);
2717 for (
const Expr *E : S.dependent_inits()) {
2731 llvm::DenseSet<const VarDecl *> SIMDLCVs;
2735 for (
const Expr *
C : LoopDirective->counters()) {
2740 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2741 auto CurPrivate =
C->privates().begin();
2742 for (
const Expr *E :
C->varlist()) {
2744 const auto *PrivateVD =
2751 assert(IsRegistered &&
"linear var already registered as private");
2839 if (
const auto *CS = dyn_cast<CapturedStmt>(S))
2857 if (HasOrderedDirective)
2865 const Stmt *AssociatedStmt = D.getAssociatedStmt();
2869 if (
C->getKind() == OMPC_ORDER_concurrent)
2872 if ((EKind == OMPD_simd ||
2874 llvm::any_of(D.getClausesOfKind<OMPReductionClause>(),
2875 [](
const OMPReductionClause *
C) {
2876 return C->getModifier() == OMPC_REDUCTION_inscan;
2884 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2887 llvm::BasicBlock *DoneBB =
nullptr;
2888 auto IC = D.counters().begin();
2889 auto IPC = D.private_counters().begin();
2890 for (
const Expr *F : D.finals()) {
2893 const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
2895 OrigVD->hasGlobalStorage() || CED) {
2897 if (llvm::Value *
Cond = CondGen(*
this)) {
2945 auto &&ThenGen = [&S, &SimdInitGen, &BodyCodeGen](
CodeGenFunction &CGF,
2959 const Expr *IfCond =
nullptr;
2962 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
2964 (
C->getNameModifier() == OMPD_unknown ||
2965 C->getNameModifier() == OMPD_simd)) {
2966 IfCond =
C->getCondition();
2982 OMPLoopScope PreInitScope(CGF, S);
3004 llvm::BasicBlock *ContBlock =
nullptr;
3011 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
3018 const Expr *IVExpr = S.getIterationVariable();
3026 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
3041 CGF, S, CGF.
EmitLValue(S.getIterationVariable()));
3056 emitOMPLoopBodyWithStopPoint(CGF, S,
3057 CodeGenFunction::JumpDest());
3063 if (HasLastprivateClause)
3092 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(S.getRawStmt())) {
3093 if (
const Stmt *SyntacticalLoop = CanonLoop->getLoopStmt()) {
3094 for (
const Stmt *SubStmt : SyntacticalLoop->
children()) {
3097 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(SubStmt)) {
3112static llvm::MapVector<llvm::Value *, llvm::Value *>
3114 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars;
3116 llvm::APInt ClauseAlignment(64, 0);
3117 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
3120 ClauseAlignment = AlignmentCI->getValue();
3122 for (
const Expr *E : Clause->varlist()) {
3123 llvm::APInt Alignment(ClauseAlignment);
3124 if (Alignment == 0) {
3131 E->getType()->getPointeeType()))
3134 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
3135 "alignment is not power of 2");
3137 AlignedVars[PtrValue] = CGF.
Builder.getInt64(Alignment.getSExtValue());
3147 bool UseOMPIRBuilder =
3149 if (UseOMPIRBuilder) {
3153 if (UseOMPIRBuilder) {
3154 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars =
3157 const Stmt *Inner = S.getRawStmt();
3158 llvm::CanonicalLoopInfo *CLI =
3159 CGF.EmitOMPCollapsedCanonicalLoopNest(Inner, 1);
3161 llvm::OpenMPIRBuilder &OMPBuilder =
3164 llvm::ConstantInt *Simdlen =
nullptr;
3171 llvm::ConstantInt *Safelen =
nullptr;
3178 llvm::omp::OrderKind Order = llvm::omp::OrderKind::OMP_ORDER_unknown;
3180 if (
C->getKind() == OpenMPOrderClauseKind::OMPC_ORDER_concurrent) {
3181 Order = llvm::omp::OrderKind::OMP_ORDER_concurrent;
3186 OMPBuilder.applySimd(CLI, AlignedVars,
3187 nullptr, Order, Simdlen, Safelen);
3194 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
3209 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
3222 OMPTransformDirectiveScopeRAII TileScope(*
this, &S);
3228 OMPTransformDirectiveScopeRAII StripeScope(*
this, &S);
3234 OMPTransformDirectiveScopeRAII ReverseScope(*
this, &S);
3240 OMPTransformDirectiveScopeRAII SplitScope(*
this, &S);
3247 OMPTransformDirectiveScopeRAII InterchangeScope(*
this, &S);
3253 OMPTransformDirectiveScopeRAII FuseScope(*
this, &S);
3258 bool UseOMPIRBuilder =
CGM.getLangOpts().OpenMPIRBuilder;
3260 if (UseOMPIRBuilder) {
3262 const Stmt *Inner = S.getRawStmt();
3270 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
3273 llvm::CanonicalLoopInfo *UnrolledCLI =
nullptr;
3277 OMPBuilder.unrollLoopFull(DL, CLI);
3279 uint64_t Factor = 0;
3280 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3281 Factor = FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
3282 assert(Factor >= 1 &&
"Only positive factors are valid");
3284 OMPBuilder.unrollLoopPartial(DL, CLI, Factor,
3285 NeedsUnrolledCLI ? &UnrolledCLI :
nullptr);
3287 OMPBuilder.unrollLoopHeuristic(DL, CLI);
3290 assert((!NeedsUnrolledCLI || UnrolledCLI) &&
3291 "NeedsUnrolledCLI implies UnrolledCLI to be set");
3308 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3310 FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
3311 assert(Factor >= 1 &&
"Only positive factors are valid");
3319void CodeGenFunction::EmitOMPOuterLoop(
3322 const CodeGenFunction::OMPLoopArguments &LoopArgs,
3327 const Expr *IVExpr = S.getIterationVariable();
3341 llvm::Value *BoolCondVal =
nullptr;
3342 if (!DynamicOrOrdered) {
3353 RT.
emitForNext(*
this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL,
3354 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST);
3359 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
3364 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
3365 if (ExitBlock !=
LoopExit.getBlock()) {
3373 if (DynamicOrOrdered)
3378 BreakContinueStack.push_back(BreakContinue(S, LoopExit, Continue));
3383 [&S, IsMonotonic, EKind](CodeGenFunction &CGF, PrePostActionTy &) {
3388 if (
const auto *
C = S.getSingleClause<OMPOrderClause>())
3389 if (
C->getKind() == OMPC_ORDER_concurrent)
3395 [&S, &LoopArgs, LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered,
3396 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
3397 SourceLocation Loc = S.getBeginLoc();
3403 CGF.EmitOMPInnerLoop(
3405 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
3406 CodeGenLoop(CGF, S, LoopExit);
3408 [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) {
3409 CodeGenOrdered(CGF, Loc, IVSize, IVSigned);
3414 BreakContinueStack.pop_back();
3415 if (!DynamicOrOrdered) {
3428 auto &&CodeGen = [DynamicOrOrdered, &S, &LoopArgs](CodeGenFunction &CGF) {
3429 if (!DynamicOrOrdered)
3430 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
3433 OMPCancelStack.emitExit(*
this, EKind, CodeGen);
3436void CodeGenFunction::EmitOMPForOuterLoop(
3437 const OpenMPScheduleTy &ScheduleKind,
bool IsMonotonic,
3439 const OMPLoopArguments &LoopArgs,
3441 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3447 LoopArgs.Chunk !=
nullptr)) &&
3448 "static non-chunked schedule does not need outer loop");
3502 const Expr *IVExpr = S.getIterationVariable();
3506 if (DynamicOrOrdered) {
3507 const std::pair<llvm::Value *, llvm::Value *> DispatchBounds =
3508 CGDispatchBounds(*
this, S, LoopArgs.LB, LoopArgs.UB);
3509 llvm::Value *LBVal = DispatchBounds.first;
3510 llvm::Value *UBVal = DispatchBounds.second;
3511 CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal,
3514 IVSigned, Ordered, DipatchRTInputValues);
3516 CGOpenMPRuntime::StaticRTInput StaticInit(
3517 IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
3518 LoopArgs.ST, LoopArgs.Chunk);
3524 auto &&CodeGenOrdered = [Ordered](CodeGenFunction &CGF, SourceLocation Loc,
3525 const unsigned IVSize,
3526 const bool IVSigned) {
3533 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST,
3534 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB);
3535 OuterLoopArgs.IncExpr = S.getInc();
3536 OuterLoopArgs.Init = S.getInit();
3537 OuterLoopArgs.Cond = S.getCond();
3538 OuterLoopArgs.NextLB = S.getNextLowerBound();
3539 OuterLoopArgs.NextUB = S.getNextUpperBound();
3540 OuterLoopArgs.DKind = LoopArgs.DKind;
3541 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
3543 if (DynamicOrOrdered) {
3549 const unsigned IVSize,
const bool IVSigned) {}
3551void CodeGenFunction::EmitOMPDistributeOuterLoop(
3556 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3563 const Expr *IVExpr = S.getIterationVariable();
3568 CGOpenMPRuntime::StaticRTInput StaticInit(
3569 IVSize, IVSigned,
false, LoopArgs.IL, LoopArgs.LB,
3570 LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
3577 IncExpr = S.getDistInc();
3579 IncExpr = S.getInc();
3584 OMPLoopArguments OuterLoopArgs;
3585 OuterLoopArgs.LB = LoopArgs.LB;
3586 OuterLoopArgs.UB = LoopArgs.UB;
3587 OuterLoopArgs.ST = LoopArgs.ST;
3588 OuterLoopArgs.IL = LoopArgs.IL;
3589 OuterLoopArgs.Chunk = LoopArgs.Chunk;
3591 ? S.getCombinedEnsureUpperBound()
3592 : S.getEnsureUpperBound();
3593 OuterLoopArgs.IncExpr = IncExpr;
3595 ? S.getCombinedInit()
3598 ? S.getCombinedCond()
3601 ? S.getCombinedNextLowerBound()
3602 : S.getNextLowerBound();
3604 ? S.getCombinedNextUpperBound()
3605 : S.getNextUpperBound();
3606 OuterLoopArgs.DKind = OMPD_distribute;
3608 EmitOMPOuterLoop(
false,
false, S,
3609 LoopScope, OuterLoopArgs, CodeGenLoopContent,
3613static std::pair<LValue, LValue>
3628 LValue PrevLB = CGF.
EmitLValue(LS.getPrevLowerBoundVariable());
3629 LValue PrevUB = CGF.
EmitLValue(LS.getPrevUpperBoundVariable());
3631 PrevLB, LS.getPrevLowerBoundVariable()->getExprLoc());
3633 PrevLBVal, LS.getPrevLowerBoundVariable()->getType(),
3634 LS.getIterationVariable()->getType(),
3635 LS.getPrevLowerBoundVariable()->getExprLoc());
3637 PrevUB, LS.getPrevUpperBoundVariable()->getExprLoc());
3639 PrevUBVal, LS.getPrevUpperBoundVariable()->getType(),
3640 LS.getIterationVariable()->getType(),
3641 LS.getPrevUpperBoundVariable()->getExprLoc());
3656static std::pair<llvm::Value *, llvm::Value *>
3661 const Expr *IVExpr = LS.getIterationVariable();
3667 llvm::Value *LBVal =
3669 llvm::Value *UBVal =
3671 return {LBVal, UBVal};
3680 llvm::Value *LBCast = CGF.
Builder.CreateIntCast(
3682 CapturedVars.push_back(LBCast);
3686 llvm::Value *UBCast = CGF.
Builder.CreateIntCast(
3688 CapturedVars.push_back(UBCast);
3699 bool HasCancel =
false;
3701 if (
const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
3702 HasCancel = D->hasCancel();
3703 else if (
const auto *D = dyn_cast<OMPDistributeParallelForDirective>(&S))
3704 HasCancel = D->hasCancel();
3705 else if (
const auto *D =
3706 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S))
3707 HasCancel = D->hasCancel();
3717 CGInlinedWorksharingLoop,
3727 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3728 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3737 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3738 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3746 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
3747 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
3757 llvm::Constant *
Addr;
3759 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
3761 assert(Fn &&
Addr &&
"Target device function emission failed.");
3773struct ScheduleKindModifiersTy {
3780 : Kind(Kind), M1(M1), M2(M2) {}
3796 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
3804 bool HasLastprivateClause;
3807 OMPLoopScope PreInitScope(*
this, S);
3812 llvm::BasicBlock *ContBlock =
nullptr;
3819 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
3826 bool Ordered =
false;
3827 if (
const auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) {
3828 if (OrderedClause->getNumForLoops())
3838 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*
this, S);
3839 LValue LB = Bounds.first;
3840 LValue UB = Bounds.second;
3854 CGM.getOpenMPRuntime().emitBarrierCall(
3855 *
this, S.getBeginLoc(), OMPD_unknown,
false,
3860 *
this, S,
EmitLValue(S.getIterationVariable()));
3867 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
3870 const Expr *ChunkExpr =
nullptr;
3872 if (
const auto *
C = S.getSingleClause<OMPScheduleClause>()) {
3873 ScheduleKind.
Schedule =
C->getScheduleKind();
3874 ScheduleKind.
M1 =
C->getFirstScheduleModifier();
3875 ScheduleKind.
M2 =
C->getSecondScheduleModifier();
3876 ChunkExpr =
C->getChunkSize();
3879 CGM.getOpenMPRuntime().getDefaultScheduleAndChunk(
3880 *
this, S, ScheduleKind.
Schedule, ChunkExpr);
3882 bool HasChunkSizeOne =
false;
3883 llvm::Value *Chunk =
nullptr;
3887 S.getIterationVariable()->getType(),
3891 llvm::APSInt EvaluatedChunk =
Result.Val.getInt();
3892 HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
3901 bool StaticChunkedOne =
3903 Chunk !=
nullptr) &&
3915 "fused distribute schedule requires a static chunk-one schedule");
3918 (ScheduleKind.
Schedule == OMPC_SCHEDULE_static &&
3919 !(ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
3920 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)) ||
3921 ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
3922 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
3924 Chunk !=
nullptr) ||
3925 StaticChunkedOne) &&
3935 if (
C->getKind() == OMPC_ORDER_concurrent)
3939 [IVSize, IVSigned, Ordered, IL, LB, UB, ST, StaticChunkedOne, Chunk,
3948 IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(),
3949 UB.getAddress(), ST.getAddress(),
3950 StaticChunkedOne ? Chunk :
nullptr);
3952 CGF, S.getBeginLoc(), EKind, ScheduleKind, StaticInit);
3954 if (!StaticChunkedOne)
3973 StaticChunkedOne ? S.getCombinedParForInDistCond()
3975 StaticChunkedOne ? S.getDistInc() : S.getInc(),
3976 [&S,
LoopExit](CodeGenFunction &CGF) {
3977 emitOMPLoopBodyWithStopPoint(CGF, S, LoopExit);
3979 [](CodeGenFunction &) {});
3983 auto &&
CodeGen = [&S](CodeGenFunction &CGF) {
3987 OMPCancelStack.emitExit(*
this, EKind,
CodeGen);
3994 LoopArguments.DKind = OMPD_for;
3995 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
3996 LoopArguments, CGDispatchBounds);
4000 return CGF.
Builder.CreateIsNotNull(
4006 ? OMPD_parallel_for_simd
4010 *
this, S, [IL, &S](CodeGenFunction &CGF) {
4011 return CGF.
Builder.CreateIsNotNull(
4015 if (HasLastprivateClause)
4021 return CGF.
Builder.CreateIsNotNull(
4032 return HasLastprivateClause;
4038static std::pair<LValue, LValue>
4052static std::pair<llvm::Value *, llvm::Value *>
4056 const Expr *IVExpr = LS.getIterationVariable();
4058 llvm::Value *LBVal = CGF.
Builder.getIntN(IVSize, 0);
4060 return {LBVal, UBVal};
4072 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
4073 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4074 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4079 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4080 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4081 "Only inscan reductions are expected.");
4082 Shareds.append(
C->varlist_begin(),
C->varlist_end());
4083 Privates.append(
C->privates().begin(),
C->privates().end());
4084 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
4085 CopyArrayTemps.append(
C->copy_array_temps().begin(),
4086 C->copy_array_temps().end());
4094 auto *ITA = CopyArrayTemps.begin();
4099 if (PrivateVD->getType()->isVariablyModifiedType()) {
4124 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
4125 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4126 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4133 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4134 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4135 "Only inscan reductions are expected.");
4136 Shareds.append(
C->varlist_begin(),
C->varlist_end());
4137 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
4138 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
4139 Privates.append(
C->privates().begin(),
C->privates().end());
4140 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
4141 CopyArrayElems.append(
C->copy_array_elems().begin(),
4142 C->copy_array_elems().end());
4146 llvm::Value *OMPLast = CGF.
Builder.CreateNSWSub(
4147 OMPScanNumIterations,
4148 llvm::ConstantInt::get(CGF.
SizeTy, 1,
false));
4149 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
4151 const Expr *OrigExpr = Shareds[I];
4152 const Expr *CopyArrayElem = CopyArrayElems[I];
4159 LValue SrcLVal = CGF.
EmitLValue(CopyArrayElem);
4161 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
4191 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4192 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4198 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4199 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4200 "Only inscan reductions are expected.");
4201 Privates.append(
C->privates().begin(),
C->privates().end());
4202 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
4203 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
4204 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
4205 CopyArrayElems.append(
C->copy_array_elems().begin(),
4206 C->copy_array_elems().end());
4221 auto &&
CodeGen = [&S, OMPScanNumIterations, &LHSs, &RHSs, &CopyArrayElems,
4228 llvm::BasicBlock *InputBB = CGF.Builder.GetInsertBlock();
4229 llvm::BasicBlock *LoopBB = CGF.createBasicBlock(
"omp.outer.log.scan.body");
4230 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
"omp.outer.log.scan.exit");
4232 CGF.CGM.getIntrinsic(llvm::Intrinsic::log2, CGF.DoubleTy);
4234 CGF.Builder.CreateUIToFP(OMPScanNumIterations, CGF.DoubleTy);
4235 llvm::Value *LogVal = CGF.EmitNounwindRuntimeCall(F, Arg);
4236 F = CGF.CGM.getIntrinsic(llvm::Intrinsic::ceil, CGF.DoubleTy);
4237 LogVal = CGF.EmitNounwindRuntimeCall(F, LogVal);
4238 LogVal = CGF.Builder.CreateFPToUI(LogVal, CGF.IntTy);
4239 llvm::Value *NMin1 = CGF.Builder.CreateNUWSub(
4240 OMPScanNumIterations, llvm::ConstantInt::get(CGF.SizeTy, 1));
4242 CGF.EmitBlock(LoopBB);
4243 auto *Counter = CGF.Builder.CreatePHI(CGF.IntTy, 2);
4245 auto *Pow2K = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
4246 Counter->addIncoming(llvm::ConstantInt::get(CGF.IntTy, 0), InputBB);
4247 Pow2K->addIncoming(llvm::ConstantInt::get(CGF.SizeTy, 1), InputBB);
4250 llvm::BasicBlock *InnerLoopBB =
4251 CGF.createBasicBlock(
"omp.inner.log.scan.body");
4252 llvm::BasicBlock *InnerExitBB =
4253 CGF.createBasicBlock(
"omp.inner.log.scan.exit");
4254 llvm::Value *CmpI = CGF.Builder.CreateICmpUGE(NMin1, Pow2K);
4255 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4256 CGF.EmitBlock(InnerLoopBB);
4257 auto *IVal = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
4258 IVal->addIncoming(NMin1, LoopBB);
4261 auto *ILHS = LHSs.begin();
4262 auto *IRHS = RHSs.begin();
4263 for (
const Expr *CopyArrayElem : CopyArrayElems) {
4273 LHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4278 llvm::Value *OffsetIVal = CGF.Builder.CreateNUWSub(IVal, Pow2K);
4284 RHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4291 CGF.CGM.getOpenMPRuntime().emitReduction(
4292 CGF, S.getEndLoc(),
Privates, LHSs, RHSs, ReductionOps,
4296 llvm::Value *NextIVal =
4297 CGF.Builder.CreateNUWSub(IVal, llvm::ConstantInt::get(CGF.SizeTy, 1));
4298 IVal->addIncoming(NextIVal, CGF.Builder.GetInsertBlock());
4299 CmpI = CGF.Builder.CreateICmpUGE(NextIVal, Pow2K);
4300 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4301 CGF.EmitBlock(InnerExitBB);
4303 CGF.Builder.CreateNUWAdd(Counter, llvm::ConstantInt::get(CGF.IntTy, 1));
4304 Counter->addIncoming(
Next, CGF.Builder.GetInsertBlock());
4306 llvm::Value *NextPow2K =
4307 CGF.Builder.CreateShl(Pow2K, 1,
"",
true);
4308 Pow2K->addIncoming(NextPow2K, CGF.Builder.GetInsertBlock());
4309 llvm::Value *
Cmp = CGF.Builder.CreateICmpNE(
Next, LogVal);
4310 CGF.Builder.CreateCondBr(
Cmp, LoopBB, ExitBB);
4312 CGF.EmitBlock(ExitBB);
4318 CGF, S.getBeginLoc(), OMPD_unknown,
false,
4321 RegionCodeGenTy RCG(CodeGen);
4332 bool HasLastprivates;
4334 if (llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4335 [](
const OMPReductionClause *
C) {
4336 return C->getModifier() == OMPC_REDUCTION_inscan;
4340 OMPLoopScope LoopScope(CGF, S);
4343 const auto &&FirstGen = [&S, HasCancel, EKind](
CodeGenFunction &CGF) {
4352 const auto &&SecondGen = [&S, HasCancel, EKind,
4370 return HasLastprivates;
4383 if (
auto *SC = dyn_cast<OMPScheduleClause>(
C)) {
4388 switch (SC->getScheduleKind()) {
4389 case OMPC_SCHEDULE_auto:
4390 case OMPC_SCHEDULE_dynamic:
4391 case OMPC_SCHEDULE_runtime:
4392 case OMPC_SCHEDULE_guided:
4393 case OMPC_SCHEDULE_static:
4406static llvm::omp::ScheduleKind
4408 switch (ScheduleClauseKind) {
4410 return llvm::omp::OMP_SCHEDULE_Default;
4411 case OMPC_SCHEDULE_auto:
4412 return llvm::omp::OMP_SCHEDULE_Auto;
4413 case OMPC_SCHEDULE_dynamic:
4414 return llvm::omp::OMP_SCHEDULE_Dynamic;
4415 case OMPC_SCHEDULE_guided:
4416 return llvm::omp::OMP_SCHEDULE_Guided;
4417 case OMPC_SCHEDULE_runtime:
4418 return llvm::omp::OMP_SCHEDULE_Runtime;
4419 case OMPC_SCHEDULE_static:
4420 return llvm::omp::OMP_SCHEDULE_Static;
4422 llvm_unreachable(
"Unhandled schedule kind");
4429 bool HasLastprivates =
false;
4432 auto &&
CodeGen = [&S, &
CGM, HasCancel, &HasLastprivates,
4435 if (UseOMPIRBuilder) {
4436 bool NeedsBarrier = !S.getSingleClause<OMPNowaitClause>();
4438 llvm::omp::ScheduleKind SchedKind = llvm::omp::OMP_SCHEDULE_Default;
4439 llvm::Value *ChunkSize =
nullptr;
4440 if (
auto *SchedClause = S.getSingleClause<OMPScheduleClause>()) {
4443 if (
const Expr *ChunkSizeExpr = SchedClause->getChunkSize())
4448 const Stmt *Inner = S.getRawStmt();
4449 llvm::CanonicalLoopInfo *CLI =
4452 llvm::OpenMPIRBuilder &OMPBuilder =
4454 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4456 cantFail(OMPBuilder.applyWorkshareLoop(
4457 CGF.
Builder.getCurrentDebugLocation(), CLI, AllocaIP, NeedsBarrier,
4458 SchedKind, ChunkSize,
false,
4469 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
4474 if (!UseOMPIRBuilder) {
4476 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4488 bool HasLastprivates =
false;
4489 auto &&
CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
4496 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4497 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
4501 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4502 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_for);
4509 llvm::Value *
Init =
nullptr) {
4516void CodeGenFunction::EmitSections(
const OMPExecutableDirective &S) {
4517 const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4518 const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt);
4519 bool HasLastprivates =
false;
4521 auto &&CodeGen = [&S, CapturedStmt, CS, EKind,
4522 &HasLastprivates](CodeGenFunction &CGF, PrePostActionTy &) {
4523 const ASTContext &
C = CGF.getContext();
4524 QualType KmpInt32Ty =
4525 C.getIntTypeForBitwidth(32, 1);
4528 CGF.Builder.getInt32(0));
4529 llvm::ConstantInt *GlobalUBVal = CS !=
nullptr
4530 ? CGF.Builder.getInt32(CS->size() - 1)
4531 : CGF.Builder.getInt32(0);
4535 CGF.Builder.getInt32(1));
4537 CGF.Builder.getInt32(0));
4540 OpaqueValueExpr IVRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4541 CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
4542 OpaqueValueExpr UBRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4543 CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
4547 S.getBeginLoc(), FPOptionsOverride());
4551 S.getBeginLoc(),
true, FPOptionsOverride());
4552 auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
4564 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".omp.sections.exit");
4565 llvm::SwitchInst *SwitchStmt =
4566 CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.
getBeginLoc()),
4567 ExitBB, CS ==
nullptr ? 1 : CS->size());
4569 unsigned CaseNumber = 0;
4570 for (
const Stmt *SubStmt : CS->
children()) {
4571 auto CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4572 CGF.EmitBlock(CaseBB);
4573 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
4574 CGF.EmitStmt(SubStmt);
4575 CGF.EmitBranch(ExitBB);
4579 llvm::BasicBlock *CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4580 CGF.EmitBlock(CaseBB);
4581 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
4582 CGF.EmitStmt(CapturedStmt);
4583 CGF.EmitBranch(ExitBB);
4585 CGF.EmitBlock(ExitBB,
true);
4588 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
4589 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
4593 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
4597 CGF.EmitOMPPrivateClause(S, LoopScope);
4598 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(CGF, S, IV);
4599 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
4600 CGF.EmitOMPReductionClauseInit(S, LoopScope);
4601 (void)LoopScope.Privatize();
4603 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
4606 OpenMPScheduleTy ScheduleKind;
4607 ScheduleKind.
Schedule = OMPC_SCHEDULE_static;
4608 CGOpenMPRuntime::StaticRTInput StaticInit(
4609 32,
true,
false, IL.getAddress(),
4610 LB.getAddress(), UB.getAddress(), ST.getAddress());
4611 CGF.CGM.getOpenMPRuntime().emitForStaticInit(CGF, S.
getBeginLoc(), EKind,
4612 ScheduleKind, StaticInit);
4614 llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.
getBeginLoc());
4615 llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
4616 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
4617 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
4619 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.
getBeginLoc()), IV);
4621 CGF.EmitOMPInnerLoop(S,
false,
Cond, Inc, BodyGen,
4622 [](CodeGenFunction &) {});
4624 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
4625 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.
getEndLoc(),
4628 CGF.OMPCancelStack.emitExit(CGF, EKind, CodeGen);
4629 CGF.EmitOMPReductionClauseFinal(S, OMPD_parallel);
4632 return CGF.
Builder.CreateIsNotNull(
4637 if (HasLastprivates)
4644 bool HasCancel =
false;
4645 if (
auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
4646 HasCancel = OSD->hasCancel();
4647 else if (
auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
4648 HasCancel = OPSD->hasCancel();
4650 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_sections, CodeGen,
4655 if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) {
4673 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4678 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4679 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_scope,
CodeGen);
4682 if (!S.getSingleClause<OMPNowaitClause>()) {
4683 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_scope);
4690 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4691 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4692 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4693 using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
4695 auto FiniCB = [](InsertPointTy IP) {
4698 return llvm::Error::success();
4701 const CapturedStmt *ICS = S.getInnermostCapturedStmt();
4707 auto SectionCB = [
this, SubStmt](
4708 InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4711 CodeGenIP,
"section");
4712 return llvm::Error::success();
4714 SectionCBVector.push_back(SectionCB);
4718 [
this,
CapturedStmt](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4722 return llvm::Error::success();
4724 SectionCBVector.push_back(SectionCB);
4731 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
4732 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
4742 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4744 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4745 cantFail(OMPBuilder.createSections(
4746 Builder, AllocaIP, SectionCBVector, PrivCB, FiniCB, S.hasCancel(),
4747 S.getSingleClause<OMPNowaitClause>()));
4754 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4758 if (!S.getSingleClause<OMPNowaitClause>()) {
4759 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(),
4767 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4768 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4769 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4771 const Stmt *SectionRegionBodyStmt = S.getAssociatedStmt();
4772 auto FiniCB = [
this](InsertPointTy IP) {
4774 return llvm::Error::success();
4777 auto BodyGenCB = [SectionRegionBodyStmt,
4778 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4781 *
this, SectionRegionBodyStmt, AllocIP, CodeGenIP,
"section");
4782 return llvm::Error::success();
4787 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4788 cantFail(OMPBuilder.createSection(
Builder, BodyGenCB, FiniCB));
4808 CopyprivateVars.append(
C->varlist_begin(),
C->varlist_end());
4809 DestExprs.append(
C->destination_exprs().begin(),
4810 C->destination_exprs().end());
4811 SrcExprs.append(
C->source_exprs().begin(),
C->source_exprs().end());
4812 AssignmentOps.append(
C->assignment_ops().begin(),
4813 C->assignment_ops().end());
4822 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4827 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4828 CGM.getOpenMPRuntime().emitSingleRegion(*
this,
CodeGen, S.getBeginLoc(),
4829 CopyprivateVars, DestExprs,
4830 SrcExprs, AssignmentOps);
4834 if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) {
4835 CGM.getOpenMPRuntime().emitBarrierCall(
4836 *
this, S.getBeginLoc(),
4837 S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);
4852 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4853 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4854 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4856 const Stmt *MasterRegionBodyStmt = S.getAssociatedStmt();
4858 auto FiniCB = [
this](InsertPointTy IP) {
4860 return llvm::Error::success();
4863 auto BodyGenCB = [MasterRegionBodyStmt,
4864 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4867 *
this, MasterRegionBodyStmt, AllocIP, CodeGenIP,
"master");
4868 return llvm::Error::success();
4873 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4874 cantFail(OMPBuilder.createMaster(
Builder, BodyGenCB, FiniCB));
4889 Expr *Filter =
nullptr;
4891 Filter = FilterClause->getThreadID();
4897 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4898 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4899 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4901 const Stmt *MaskedRegionBodyStmt = S.getAssociatedStmt();
4902 const Expr *Filter =
nullptr;
4904 Filter = FilterClause->getThreadID();
4905 llvm::Value *FilterVal = Filter
4907 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
4909 auto FiniCB = [
this](InsertPointTy IP) {
4911 return llvm::Error::success();
4914 auto BodyGenCB = [MaskedRegionBodyStmt,
4915 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4918 *
this, MaskedRegionBodyStmt, AllocIP, CodeGenIP,
"masked");
4919 return llvm::Error::success();
4924 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
4925 OMPBuilder.createMasked(
Builder, BodyGenCB, FiniCB, FilterVal));
4936 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4937 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4938 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4940 const Stmt *CriticalRegionBodyStmt = S.getAssociatedStmt();
4941 const Expr *Hint =
nullptr;
4942 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4943 Hint = HintClause->getHint();
4948 llvm::Value *HintInst =
nullptr;
4953 auto FiniCB = [
this](InsertPointTy IP) {
4955 return llvm::Error::success();
4958 auto BodyGenCB = [CriticalRegionBodyStmt,
4959 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4962 *
this, CriticalRegionBodyStmt, AllocIP, CodeGenIP,
"critical");
4963 return llvm::Error::success();
4968 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4969 cantFail(OMPBuilder.createCritical(
Builder, BodyGenCB, FiniCB,
4970 S.getDirectiveName().getAsString(),
4979 CGF.
EmitStmt(S.getAssociatedStmt());
4981 const Expr *Hint =
nullptr;
4982 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4983 Hint = HintClause->getHint();
4986 CGM.getOpenMPRuntime().emitCriticalRegion(*
this,
4987 S.getDirectiveName().getAsString(),
4988 CodeGen, S.getBeginLoc(), Hint);
4992 const OMPParallelForDirective &S) {
5001 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
5005 OMPLoopScope LoopScope(CGF, S);
5008 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
5009 [](
const OMPReductionClause *
C) {
5010 return C->getModifier() == OMPC_REDUCTION_inscan;
5026 const OMPParallelForSimdDirective &S) {
5035 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
5039 OMPLoopScope LoopScope(CGF, S);
5042 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
5043 [](
const OMPReductionClause *
C) {
5044 return C->getModifier() == OMPC_REDUCTION_inscan;
5060 const OMPParallelMasterDirective &S) {
5080 [](CodeGenFunction &) {
return nullptr; });
5087 const OMPParallelMaskedDirective &S) {
5107 [](CodeGenFunction &) {
return nullptr; });
5114 const OMPParallelSectionsDirective &S) {
5120 CGF.EmitSections(S);
5134class CheckVarsEscapingUntiedTaskDeclContext final
5139 explicit CheckVarsEscapingUntiedTaskDeclContext() =
default;
5140 ~CheckVarsEscapingUntiedTaskDeclContext() =
default;
5141 void VisitDeclStmt(
const DeclStmt *S) {
5146 if (
const auto *VD = dyn_cast_or_null<VarDecl>(D))
5148 PrivateDecls.push_back(VD);
5152 void VisitCapturedStmt(
const CapturedStmt *) {}
5154 void VisitBlockExpr(
const BlockExpr *) {}
5155 void VisitStmt(
const Stmt *S) {
5158 for (
const Stmt *Child : S->
children())
5164 ArrayRef<const VarDecl *> getPrivateDecls()
const {
return PrivateDecls; }
5172 bool OmpAllMemory =
false;
5175 return C->getDependencyKind() == OMPC_DEPEND_outallmemory ||
5176 C->getDependencyKind() == OMPC_DEPEND_inoutallmemory;
5178 OmpAllMemory =
true;
5183 Data.Dependences.emplace_back(OMPC_DEPEND_outallmemory,
5192 if (Kind == OMPC_DEPEND_outallmemory || Kind == OMPC_DEPEND_inoutallmemory)
5194 if (OmpAllMemory && (Kind == OMPC_DEPEND_out || Kind == OMPC_DEPEND_inout))
5197 Data.Dependences.emplace_back(
C->getDependencyKind(),
C->getModifier());
5198 DD.
DepExprs.append(
C->varlist_begin(),
C->varlist_end());
5207 const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion);
5209 auto PartId = std::next(I);
5210 auto TaskT = std::next(I, 4);
5215 const Expr *
Cond = Clause->getCondition();
5218 Data.Final.setInt(CondConstant);
5223 Data.Final.setInt(
false);
5227 const Expr *Prio = Clause->getPriority();
5228 Data.Priority.setInt(
true);
5236 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
5238 for (
const auto *
C : S.getClausesOfKind<OMPPrivateClause>()) {
5239 auto IRef =
C->varlist_begin();
5240 for (
const Expr *IInit :
C->private_copies()) {
5242 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
5243 Data.PrivateVars.push_back(*IRef);
5244 Data.PrivateCopies.push_back(IInit);
5249 EmittedAsPrivate.clear();
5251 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5252 auto IRef =
C->varlist_begin();
5253 auto IElemInitRef =
C->inits().begin();
5254 for (
const Expr *IInit :
C->private_copies()) {
5256 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
5257 Data.FirstprivateVars.push_back(*IRef);
5258 Data.FirstprivateCopies.push_back(IInit);
5259 Data.FirstprivateInits.push_back(*IElemInitRef);
5266 llvm::MapVector<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
5267 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
5268 auto IRef =
C->varlist_begin();
5269 auto ID =
C->destination_exprs().begin();
5270 for (
const Expr *IInit :
C->private_copies()) {
5272 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
5273 Data.LastprivateVars.push_back(*IRef);
5274 Data.LastprivateCopies.push_back(IInit);
5276 LastprivateDstsOrigs.insert(
5285 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
5286 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5287 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5288 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5289 Data.ReductionOps.append(
C->reduction_ops().begin(),
5290 C->reduction_ops().end());
5291 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5292 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5294 Data.Reductions =
CGM.getOpenMPRuntime().emitTaskReductionInit(
5295 *
this, S.getBeginLoc(), LHSs, RHSs,
Data);
5300 CheckVarsEscapingUntiedTaskDeclContext Checker;
5301 Checker.Visit(S.getInnermostCapturedStmt()->getCapturedStmt());
5302 Data.PrivateLocals.append(Checker.getPrivateDecls().begin(),
5303 Checker.getPrivateDecls().end());
5305 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
5306 CapturedRegion](CodeGenFunction &CGF,
5308 llvm::MapVector<CanonicalDeclPtr<const VarDecl>,
5309 std::pair<Address, Address>>
5314 if (
auto *DI = CGF.getDebugInfo()) {
5315 llvm::SmallDenseMap<const VarDecl *, FieldDecl *> CaptureFields =
5316 CGF.CapturedStmtInfo->getCaptureFields();
5317 llvm::Value *ContextValue = CGF.CapturedStmtInfo->getContextValue();
5318 if (CaptureFields.size() && ContextValue) {
5319 unsigned CharWidth = CGF.getContext().getCharWidth();
5333 for (
auto It = CaptureFields.begin(); It != CaptureFields.end(); ++It) {
5334 const VarDecl *SharedVar = It->first;
5337 CGF.getContext().getASTRecordLayout(CaptureRecord);
5340 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5341 (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue,
5342 CGF.Builder,
false);
5345 auto UpdateExpr = [](llvm::LLVMContext &Ctx,
auto *
Declare,
5350 Ops.push_back(llvm::dwarf::DW_OP_plus_uconst);
5351 Ops.push_back(Offset);
5353 Ops.push_back(llvm::dwarf::DW_OP_deref);
5354 Declare->setExpression(llvm::DIExpression::get(Ctx, Ops));
5356 llvm::Instruction &
Last = CGF.Builder.GetInsertBlock()->back();
5357 if (
auto DDI = dyn_cast<llvm::DbgVariableIntrinsic>(&
Last))
5358 UpdateExpr(DDI->getContext(), DDI, Offset);
5361 assert(!
Last.isTerminator() &&
"unexpected terminator");
5363 CGF.Builder.GetInsertBlock()->getTrailingDbgRecords()) {
5364 for (llvm::DbgVariableRecord &DVR : llvm::reverse(
5365 llvm::filterDbgVars(Marker->getDbgRecordRange()))) {
5366 UpdateExpr(
Last.getContext(), &DVR, Offset);
5374 if (!
Data.PrivateVars.empty() || !
Data.FirstprivateVars.empty() ||
5375 !
Data.LastprivateVars.empty() || !
Data.PrivateLocals.empty()) {
5376 enum { PrivatesParam = 2, CopyFnParam = 3 };
5377 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5379 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5385 CallArgs.push_back(PrivatesPtr);
5386 ParamTypes.push_back(PrivatesPtr->getType());
5387 for (
const Expr *E :
Data.PrivateVars) {
5389 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5390 CGF.getContext().getPointerType(E->
getType()),
".priv.ptr.addr");
5391 PrivatePtrs.emplace_back(VD, PrivatePtr);
5393 ParamTypes.push_back(PrivatePtr.
getType());
5395 for (
const Expr *E :
Data.FirstprivateVars) {
5397 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5398 CGF.getContext().getPointerType(E->
getType()),
5399 ".firstpriv.ptr.addr");
5400 PrivatePtrs.emplace_back(VD, PrivatePtr);
5401 FirstprivatePtrs.emplace_back(VD, PrivatePtr);
5403 ParamTypes.push_back(PrivatePtr.
getType());
5405 for (
const Expr *E :
Data.LastprivateVars) {
5407 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5408 CGF.getContext().getPointerType(E->
getType()),
5409 ".lastpriv.ptr.addr");
5410 PrivatePtrs.emplace_back(VD, PrivatePtr);
5412 ParamTypes.push_back(PrivatePtr.
getType());
5417 Ty = CGF.getContext().getPointerType(Ty);
5419 Ty = CGF.getContext().getPointerType(Ty);
5420 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5421 CGF.getContext().getPointerType(Ty),
".local.ptr.addr");
5422 auto Result = UntiedLocalVars.insert(
5425 if (
Result.second ==
false)
5426 *
Result.first = std::make_pair(
5429 ParamTypes.push_back(PrivatePtr.
getType());
5431 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5433 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5434 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5435 for (
const auto &Pair : LastprivateDstsOrigs) {
5439 CGF.CapturedStmtInfo->lookup(OrigVD) !=
nullptr,
5441 Pair.second->getExprLoc());
5442 Scope.addPrivate(Pair.first, CGF.EmitLValue(&DRE).getAddress());
5444 for (
const auto &Pair : PrivatePtrs) {
5446 CGF.Builder.CreateLoad(Pair.second),
5447 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5448 CGF.getContext().getDeclAlign(Pair.first));
5449 Scope.addPrivate(Pair.first, Replacement);
5450 if (
auto *DI = CGF.getDebugInfo())
5451 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5452 (void)DI->EmitDeclareOfAutoVariable(
5453 Pair.first, Pair.second.getBasePointer(), CGF.Builder,
5458 for (
auto &Pair : UntiedLocalVars) {
5459 QualType VDType = Pair.first->getType().getNonReferenceType();
5460 if (Pair.first->getType()->isLValueReferenceType())
5461 VDType = CGF.getContext().getPointerType(VDType);
5463 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5466 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(VDType)),
5467 CGF.getPointerAlign());
5468 Pair.second.first = Replacement;
5469 Ptr = CGF.Builder.CreateLoad(Replacement);
5470 Replacement =
Address(Ptr, CGF.ConvertTypeForMem(VDType),
5471 CGF.getContext().getDeclAlign(Pair.first));
5472 Pair.second.second = Replacement;
5474 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5475 Address Replacement(Ptr, CGF.ConvertTypeForMem(VDType),
5476 CGF.getContext().getDeclAlign(Pair.first));
5477 Pair.second.first = Replacement;
5481 if (
Data.Reductions) {
5483 for (
const auto &Pair : FirstprivatePtrs) {
5485 CGF.Builder.CreateLoad(Pair.second),
5486 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5487 CGF.getContext().getDeclAlign(Pair.first));
5488 FirstprivateScope.
addPrivate(Pair.first, Replacement);
5491 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5493 Data.ReductionCopies,
Data.ReductionOps);
5494 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
5496 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5502 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5504 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5507 CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF),
5508 CGF.getContext().VoidPtrTy,
5509 CGF.getContext().getPointerType(
5510 Data.ReductionCopies[Cnt]->getType()),
5511 Data.ReductionCopies[Cnt]->getExprLoc()),
5512 CGF.ConvertTypeForMem(
Data.ReductionCopies[Cnt]->getType()),
5513 Replacement.getAlignment());
5519 (void)
Scope.Privatize();
5524 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5525 auto IPriv =
C->privates().begin();
5526 auto IRed =
C->reduction_ops().begin();
5527 auto ITD =
C->taskgroup_descriptors().begin();
5528 for (
const Expr *Ref :
C->varlist()) {
5529 InRedVars.emplace_back(Ref);
5530 InRedPrivs.emplace_back(*IPriv);
5531 InRedOps.emplace_back(*IRed);
5532 TaskgroupDescriptors.emplace_back(*ITD);
5533 std::advance(IPriv, 1);
5534 std::advance(IRed, 1);
5535 std::advance(ITD, 1);
5541 if (!InRedVars.empty()) {
5543 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5551 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5553 llvm::Value *ReductionsPtr;
5554 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5555 ReductionsPtr = CGF.EmitLoadOfScalar(CGF.EmitLValue(TRExpr),
5556 TRExpr->getExprLoc());
5558 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5560 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5563 CGF.EmitScalarConversion(
5564 Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy,
5565 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
5566 InRedPrivs[Cnt]->getExprLoc()),
5567 CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()),
5568 Replacement.getAlignment());
5581 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5582 S, *I, *PartId, *TaskT, EKind,
CodeGen,
Data.Tied,
Data.NumberOfParts);
5583 OMPLexicalScope
Scope(*
this, S, std::nullopt,
5586 TaskGen(*
this, OutlinedFn,
Data);
5603 QualType ElemType =
C.getBaseElementType(Ty);
5613 Data.FirstprivateVars.emplace_back(OrigRef);
5614 Data.FirstprivateCopies.emplace_back(PrivateRef);
5615 Data.FirstprivateInits.emplace_back(InitRef);
5628 auto PartId = std::next(I);
5629 auto TaskT = std::next(I, 4);
5632 Data.Final.setInt(
false);
5634 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5635 auto IRef =
C->varlist_begin();
5636 auto IElemInitRef =
C->inits().begin();
5637 for (
auto *IInit :
C->private_copies()) {
5638 Data.FirstprivateVars.push_back(*IRef);
5639 Data.FirstprivateCopies.push_back(IInit);
5640 Data.FirstprivateInits.push_back(*IElemInitRef);
5647 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5648 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5649 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5650 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5651 Data.ReductionOps.append(
C->reduction_ops().begin(),
5652 C->reduction_ops().end());
5653 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5654 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5669 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5671 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5683 if (!isa_and_nonnull<llvm::ConstantPointerNull>(
5686 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5693 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, BPVD, PVD, SVD, MVD, EKind,
5697 if (!
Data.FirstprivateVars.empty()) {
5698 enum { PrivatesParam = 2, CopyFnParam = 3 };
5699 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5701 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5707 CallArgs.push_back(PrivatesPtr);
5708 ParamTypes.push_back(PrivatesPtr->getType());
5709 for (
const Expr *E :
Data.FirstprivateVars) {
5711 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5712 CGF.getContext().getPointerType(E->
getType()),
5713 ".firstpriv.ptr.addr");
5714 PrivatePtrs.emplace_back(VD, PrivatePtr);
5716 ParamTypes.push_back(PrivatePtr.
getType());
5718 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5720 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5721 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5722 for (
const auto &Pair : PrivatePtrs) {
5724 CGF.Builder.CreateLoad(Pair.second),
5725 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5726 CGF.getContext().getDeclAlign(Pair.first));
5727 Scope.addPrivate(Pair.first, Replacement);
5730 CGF.processInReduction(S,
Data, CGF, CS,
Scope);
5733 CGF.GetAddrOfLocalVar(BPVD), 0);
5735 CGF.GetAddrOfLocalVar(PVD), 0);
5736 InputInfo.
SizesArray = CGF.Builder.CreateConstArrayGEP(
5737 CGF.GetAddrOfLocalVar(SVD), 0);
5740 InputInfo.
MappersArray = CGF.Builder.CreateConstArrayGEP(
5741 CGF.GetAddrOfLocalVar(MVD), 0);
5745 OMPLexicalScope LexScope(CGF, S, OMPD_task,
false);
5747 if (CGF.CGM.getLangOpts().OpenMP >= 51 &&
5752 CGF.CGM.getOpenMPRuntime().emitThreadLimitClause(
5753 CGF, TL->getThreadLimit().front(), S.getBeginLoc());
5757 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5758 S, *I, *PartId, *TaskT, EKind,
CodeGen,
true,
5759 Data.NumberOfParts);
5760 llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<OMPNowaitClause>() ? 1 : 0);
5764 CGM.getOpenMPRuntime().emitTaskCall(*
this, S.getBeginLoc(), S, OutlinedFn,
5765 SharedsTy, CapturedStruct, &IfCond,
Data);
5770 CodeGenFunction &CGF,
5774 if (
Data.Reductions) {
5776 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5778 Data.ReductionCopies,
Data.ReductionOps);
5781 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5795 Data.ReductionCopies[Cnt]->getType()),
5796 Data.ReductionCopies[Cnt]->getExprLoc()),
5798 Replacement.getAlignment());
5803 (void)
Scope.Privatize();
5808 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5809 auto IPriv =
C->privates().begin();
5810 auto IRed =
C->reduction_ops().begin();
5811 auto ITD =
C->taskgroup_descriptors().begin();
5812 for (
const Expr *Ref :
C->varlist()) {
5813 InRedVars.emplace_back(Ref);
5814 InRedPrivs.emplace_back(*IPriv);
5815 InRedOps.emplace_back(*IRed);
5816 TaskgroupDescriptors.emplace_back(*ITD);
5817 std::advance(IPriv, 1);
5818 std::advance(IRed, 1);
5819 std::advance(ITD, 1);
5823 if (!InRedVars.empty()) {
5825 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5833 llvm::Value *ReductionsPtr;
5834 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5838 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
5846 InRedPrivs[Cnt]->getExprLoc()),
5848 Replacement.getAlignment());
5862 const Expr *IfCond =
nullptr;
5863 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
5864 if (
C->getNameModifier() == OMPD_unknown ||
5865 C->getNameModifier() == OMPD_task) {
5866 IfCond =
C->getCondition();
5873 Data.Tied = !S.getSingleClause<OMPUntiedClause>();
5877 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
5878 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
5881 SharedsTy, CapturedStruct, IfCond,
5890 const OMPTaskyieldDirective &S) {
5891 CGM.getOpenMPRuntime().emitTaskyieldCall(*
this, S.getBeginLoc());
5895 const OMPMessageClause *MC = S.getSingleClause<OMPMessageClause>();
5896 Expr *ME = MC ? MC->getMessageString() :
nullptr;
5897 const OMPSeverityClause *SC = S.getSingleClause<OMPSeverityClause>();
5898 bool IsFatal =
false;
5899 if (!SC || SC->getSeverityKind() == OMPC_SEVERITY_fatal)
5901 CGM.getOpenMPRuntime().emitErrorCall(*
this, S.getBeginLoc(), ME, IsFatal);
5905 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_barrier);
5912 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
5913 CGM.getOpenMPRuntime().emitTaskwaitCall(*
this, S.getBeginLoc(),
Data);
5917 return T.clauses().empty();
5921 const OMPTaskgroupDirective &S) {
5922 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
5924 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
5925 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5929 auto BodyGenCB = [&,
this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
5932 EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5933 return llvm::Error::success();
5938 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5939 cantFail(OMPBuilder.createTaskgroup(
Builder, AllocaIP,
5946 if (
const Expr *E = S.getReductionRef()) {
5950 for (
const auto *
C : S.getClausesOfKind<OMPTaskReductionClause>()) {
5951 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5952 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5953 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5954 Data.ReductionOps.append(
C->reduction_ops().begin(),
5955 C->reduction_ops().end());
5956 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5957 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5959 llvm::Value *ReductionDesc =
5967 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5969 CGM.getOpenMPRuntime().emitTaskgroupRegion(*
this,
CodeGen, S.getBeginLoc());
5974 ? llvm::AtomicOrdering::NotAtomic
5975 : llvm::AtomicOrdering::AcquireRelease;
5976 CGM.getOpenMPRuntime().emitFlush(
5979 if (
const auto *FlushClause = S.getSingleClause<
OMPFlushClause>())
5981 FlushClause->varlist_end());
5984 S.getBeginLoc(), AO);
5994 for (
auto &Dep :
Data.Dependences) {
5995 Address DepAddr =
CGM.getOpenMPRuntime().emitDepobjDependClause(
5996 *
this, Dep, DC->getBeginLoc());
6002 CGM.getOpenMPRuntime().emitDestroyClause(*
this, DOLVal, DC->getBeginLoc());
6005 if (
const auto *UC = S.getSingleClause<OMPUpdateClause>()) {
6006 CGM.getOpenMPRuntime().emitUpdateClause(
6007 *
this, DOLVal, UC->getDependencyKind(), UC->getBeginLoc());
6025 for (
const auto *
C : ParentDir.getClausesOfKind<OMPReductionClause>()) {
6026 if (
C->getModifier() != OMPC_REDUCTION_inscan)
6028 Shareds.append(
C->varlist_begin(),
C->varlist_end());
6029 Privates.append(
C->privates().begin(),
C->privates().end());
6030 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
6031 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
6032 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
6033 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
6034 CopyArrayTemps.append(
C->copy_array_temps().begin(),
6035 C->copy_array_temps().end());
6036 CopyArrayElems.append(
C->copy_array_elems().begin(),
6037 C->copy_array_elems().end());
6039 if (ParentDir.getDirectiveKind() == OMPD_simd ||
6081 : BreakContinueStack.back().ContinueBlock.getBlock());
6092 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6094 const Expr *TempExpr = CopyArrayTemps[I];
6106 CGM.getOpenMPRuntime().emitReduction(
6107 *
this, ParentDir.getEndLoc(),
Privates, LHSs, RHSs, ReductionOps,
6110 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6118 const Expr *TempExpr = CopyArrayTemps[I];
6130 ? BreakContinueStack.back().ContinueBlock.getBlock()
6136 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6142 .getIterationVariable()
6143 ->IgnoreParenImpCasts();
6146 IdxVal = Builder.CreateIntCast(IdxVal,
SizeTy,
false);
6147 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6149 const Expr *OrigExpr = Shareds[I];
6150 const Expr *CopyArrayElem = CopyArrayElems[I];
6151 OpaqueValueMapping IdxMapping(
6164 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6167 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6173 .getIterationVariable()
6174 ->IgnoreParenImpCasts();
6178 llvm::BasicBlock *ExclusiveExitBB =
nullptr;
6182 llvm::Value *
Cmp =
Builder.CreateIsNull(IdxVal);
6183 Builder.CreateCondBr(
Cmp, ExclusiveExitBB, ContBB);
6186 IdxVal =
Builder.CreateNUWSub(IdxVal, llvm::ConstantInt::get(
SizeTy, 1));
6188 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6189 const Expr *PrivateExpr =
Privates[I];
6190 const Expr *OrigExpr = Shareds[I];
6191 const Expr *CopyArrayElem = CopyArrayElems[I];
6200 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
6224 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
6232 bool HasLastprivateClause =
false;
6235 OMPLoopScope PreInitScope(*
this, S);
6240 llvm::BasicBlock *ContBlock =
nullptr;
6247 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
6261 ? S.getCombinedLowerBoundVariable()
6262 : S.getLowerBoundVariable())));
6266 ? S.getCombinedUpperBoundVariable()
6267 : S.getUpperBoundVariable())));
6278 CGM.getOpenMPRuntime().emitBarrierCall(
6279 *
this, S.getBeginLoc(), OMPD_unknown,
false,
6291 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
6294 llvm::Value *Chunk =
nullptr;
6297 ScheduleKind =
C->getDistScheduleKind();
6298 if (
const Expr *Ch =
C->getChunkSize()) {
6301 S.getIterationVariable()->getType(),
6306 CGM.getOpenMPRuntime().getDefaultDistScheduleAndChunk(
6307 *
this, S, ScheduleKind, Chunk);
6328 bool StaticChunked =
6332 Chunk !=
nullptr) ||
6337 StaticChunked ? Chunk :
nullptr);
6345 ? S.getCombinedEnsureUpperBound()
6346 : S.getEnsureUpperBound());
6350 ? S.getCombinedInit()
6355 ? S.getCombinedCond()
6359 Cond = S.getCombinedDistCond();
6391 [&S, &LoopScope,
Cond, IncExpr,
LoopExit, &CodeGenLoop,
6394 S, LoopScope.requiresCleanups(),
Cond, IncExpr,
6395 [&S,
LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
6396 CodeGenLoop(CGF, S, LoopExit);
6398 [&S, StaticChunked](CodeGenFunction &CGF) {
6399 if (StaticChunked) {
6400 CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound());
6401 CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound());
6402 CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound());
6403 CGF.EmitIgnoredExpr(S.getCombinedInit());
6413 const OMPLoopArguments LoopArguments = {
6416 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments,
6422 return CGF.
Builder.CreateIsNotNull(
6432 *
this, S, [IL, &S](CodeGenFunction &CGF) {
6433 return CGF.
Builder.CreateIsNotNull(
6438 if (HasLastprivateClause) {
6461 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
6470static llvm::Function *
6477 Fn->setDoesNotRecurse();
6481template <
typename T>
6483 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP,
6484 llvm::OpenMPIRBuilder &OMPBuilder) {
6486 unsigned NumLoops =
C->getNumLoops();
6490 for (
unsigned I = 0; I < NumLoops; I++) {
6491 const Expr *CounterVal =
C->getLoopData(I);
6496 StoreValues.emplace_back(StoreValue);
6498 OMPDoacrossKind<T> ODK;
6499 bool IsDependSource = ODK.isSource(
C);
6501 OMPBuilder.createOrderedDepend(CGF.
Builder, AllocaIP, NumLoops,
6502 StoreValues,
".cnt.addr", IsDependSource));
6506 if (
CGM.getLangOpts().OpenMPIRBuilder) {
6507 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
6508 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6513 assert(!S.hasAssociatedStmt() &&
"No associated statement must be in "
6514 "ordered depend|doacross construct.");
6526 auto FiniCB = [
this](InsertPointTy IP) {
6528 return llvm::Error::success();
6531 auto BodyGenCB = [&S,
C,
6532 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
6538 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
6539 Builder,
false,
".ordered.after");
6543 assert(S.getBeginLoc().isValid() &&
6544 "Outlined function call location must be valid.");
6547 OutlinedFn, CapturedVars);
6552 return llvm::Error::success();
6555 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6556 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
6557 OMPBuilder.createOrderedThreadsSimd(
Builder, BodyGenCB, FiniCB, !
C));
6564 assert(!S.hasAssociatedStmt() &&
6565 "No associated statement must be in ordered depend construct.");
6567 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6571 assert(!S.hasAssociatedStmt() &&
6572 "No associated statement must be in ordered doacross construct.");
6574 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6578 auto &&
CodeGen = [&S,
C,
this](CodeGenFunction &CGF,
6583 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
6585 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
6586 OutlinedFn, CapturedVars);
6592 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6593 CGM.getOpenMPRuntime().emitOrderedRegion(*
this,
CodeGen, S.getBeginLoc(), !
C);
6600 "DestType must have scalar evaluation kind.");
6601 assert(!Val.
isAggregate() &&
"Must be a scalar or complex.");
6612 "DestType must have complex evaluation kind.");
6621 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
6623 assert(Val.
isComplex() &&
"Must be a scalar or complex.");
6628 Val.
getComplexVal().first, SrcElementType, DestElementType, Loc);
6630 Val.
getComplexVal().second, SrcElementType, DestElementType, Loc);
6636 LValue LVal,
RValue RVal) {
6637 if (LVal.isGlobalReg())
6644 llvm::AtomicOrdering AO, LValue LVal,
6646 if (LVal.isGlobalReg())
6649 LVal, Loc, llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO),
6658 *
this, RVal, RValTy, LVal.
getType(), Loc)),
6667 llvm_unreachable(
"Must be a scalar or complex.");
6675 assert(
V->isLValue() &&
"V of 'omp atomic read' is not lvalue");
6676 assert(
X->isLValue() &&
"X of 'omp atomic read' is not lvalue");
6685 case llvm::AtomicOrdering::Acquire:
6686 case llvm::AtomicOrdering::AcquireRelease:
6687 case llvm::AtomicOrdering::SequentiallyConsistent:
6689 llvm::AtomicOrdering::Acquire);
6691 case llvm::AtomicOrdering::Monotonic:
6692 case llvm::AtomicOrdering::Release:
6694 case llvm::AtomicOrdering::NotAtomic:
6695 case llvm::AtomicOrdering::Unordered:
6696 llvm_unreachable(
"Unexpected ordering.");
6703 llvm::AtomicOrdering AO,
const Expr *
X,
6706 assert(
X->isLValue() &&
"X of 'omp atomic write' is not lvalue");
6714 case llvm::AtomicOrdering::Release:
6715 case llvm::AtomicOrdering::AcquireRelease:
6716 case llvm::AtomicOrdering::SequentiallyConsistent:
6718 llvm::AtomicOrdering::Release);
6720 case llvm::AtomicOrdering::Acquire:
6721 case llvm::AtomicOrdering::Monotonic:
6723 case llvm::AtomicOrdering::NotAtomic:
6724 case llvm::AtomicOrdering::Unordered:
6725 llvm_unreachable(
"Unexpected ordering.");
6732 llvm::AtomicOrdering AO,
6738 if (BO == BO_Comma || !
Update.isScalar() || !
X.isSimple() ||
6740 (
Update.getScalarVal()->getType() !=
X.getAddress().getElementType())) ||
6741 !Context.getTargetInfo().hasBuiltinAtomic(
6742 Context.getTypeSize(
X.getType()), Context.toBits(
X.getAlignment())))
6743 return std::make_pair(
false,
RValue::get(
nullptr));
6746 if (T->isIntegerTy())
6749 if (T->isFloatingPointTy() && (BO == BO_Add || BO == BO_Sub))
6755 if (!CheckAtomicSupport(
Update.getScalarVal()->getType(), BO) ||
6756 !CheckAtomicSupport(
X.getAddress().getElementType(), BO))
6757 return std::make_pair(
false,
RValue::get(
nullptr));
6759 bool IsInteger =
X.getAddress().getElementType()->isIntegerTy();
6760 llvm::AtomicRMWInst::BinOp RMWOp;
6763 RMWOp = IsInteger ? llvm::AtomicRMWInst::Add : llvm::AtomicRMWInst::FAdd;
6767 return std::make_pair(
false,
RValue::get(
nullptr));
6768 RMWOp = IsInteger ? llvm::AtomicRMWInst::Sub : llvm::AtomicRMWInst::FSub;
6771 RMWOp = llvm::AtomicRMWInst::And;
6774 RMWOp = llvm::AtomicRMWInst::Or;
6777 RMWOp = llvm::AtomicRMWInst::Xor;
6781 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6783 : llvm::AtomicRMWInst::Max)
6785 : llvm::AtomicRMWInst::UMax);
6788 : llvm::AtomicRMWInst::FMax;
6792 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6794 : llvm::AtomicRMWInst::Min)
6796 : llvm::AtomicRMWInst::UMin);
6799 : llvm::AtomicRMWInst::FMin;
6802 RMWOp = llvm::AtomicRMWInst::Xchg;
6811 return std::make_pair(
false,
RValue::get(
nullptr));
6830 llvm_unreachable(
"Unsupported atomic update operation");
6832 llvm::Value *UpdateVal =
Update.getScalarVal();
6833 if (
auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
6835 UpdateVal = CGF.
Builder.CreateIntCast(
6836 IC,
X.getAddress().getElementType(),
6837 X.getType()->hasSignedIntegerRepresentation());
6839 UpdateVal = CGF.
Builder.CreateCast(llvm::Instruction::CastOps::UIToFP, IC,
6840 X.getAddress().getElementType());
6842 llvm::AtomicRMWInst *Res =
6859 if (
X.isGlobalReg()) {
6872 llvm::AtomicOrdering AO,
const Expr *
X,
6876 "Update expr in 'atomic update' must be a binary operator.");
6884 assert(
X->isLValue() &&
"X of 'omp atomic update' is not lvalue");
6891 auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](
RValue XRValue) {
6897 XLValue, ExprRValue, BOUE->getOpcode(),
IsXLHSInRHSPart, AO, Loc, Gen);
6904 case llvm::AtomicOrdering::Release:
6905 case llvm::AtomicOrdering::AcquireRelease:
6906 case llvm::AtomicOrdering::SequentiallyConsistent:
6908 llvm::AtomicOrdering::Release);
6910 case llvm::AtomicOrdering::Acquire:
6911 case llvm::AtomicOrdering::Monotonic:
6913 case llvm::AtomicOrdering::NotAtomic:
6914 case llvm::AtomicOrdering::Unordered:
6915 llvm_unreachable(
"Unexpected ordering.");
6933 llvm_unreachable(
"Must be a scalar or complex.");
6937 llvm::AtomicOrdering AO,
6942 assert(
X->isLValue() &&
"X of 'omp atomic capture' is not lvalue");
6943 assert(
V->isLValue() &&
"V of 'omp atomic capture' is not lvalue");
6952 "Update expr in 'atomic capture' must be a binary operator.");
6963 NewVValType = XRValExpr->
getType();
6965 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
6974 XLValue, ExprRValue, BOUE->getOpcode(),
IsXLHSInRHSPart, AO, Loc, Gen);
6980 NewVVal = Res.second;
6991 NewVValType =
X->getType().getNonReferenceType();
6993 X->getType().getNonReferenceType(), Loc);
6994 auto &&Gen = [&NewVVal, ExprRValue](
RValue XRValue) {
7000 XLValue, ExprRValue, BO_Assign,
false, AO,
7021 case llvm::AtomicOrdering::Release:
7023 llvm::AtomicOrdering::Release);
7025 case llvm::AtomicOrdering::Acquire:
7027 llvm::AtomicOrdering::Acquire);
7029 case llvm::AtomicOrdering::AcquireRelease:
7030 case llvm::AtomicOrdering::SequentiallyConsistent:
7032 CGF, {}, Loc, llvm::AtomicOrdering::AcquireRelease);
7034 case llvm::AtomicOrdering::Monotonic:
7036 case llvm::AtomicOrdering::NotAtomic:
7037 case llvm::AtomicOrdering::Unordered:
7038 llvm_unreachable(
"Unexpected ordering.");
7044 CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO,
7048 llvm::OpenMPIRBuilder &OMPBuilder =
7051 OMPAtomicCompareOp Op;
7055 Op = OMPAtomicCompareOp::EQ;
7058 Op = OMPAtomicCompareOp::MIN;
7061 Op = OMPAtomicCompareOp::MAX;
7064 llvm_unreachable(
"unsupported atomic compare binary operator");
7068 Address XAddr = XLVal.getAddress();
7070 auto EmitRValueWithCastIfNeeded = [&CGF, Loc](
const Expr *
X,
const Expr *E) {
7075 if (NewE->
getType() ==
X->getType())
7080 llvm::Value *EVal = EmitRValueWithCastIfNeeded(
X, E);
7081 llvm::Value *DVal = D ? EmitRValueWithCastIfNeeded(
X, D) :
nullptr;
7082 if (
auto *CI = dyn_cast<llvm::ConstantInt>(EVal))
7083 EVal = CGF.
Builder.CreateIntCast(
7084 CI, XLVal.getAddress().getElementType(),
7087 if (
auto *CI = dyn_cast<llvm::ConstantInt>(DVal))
7088 DVal = CGF.
Builder.CreateIntCast(
7089 CI, XLVal.getAddress().getElementType(),
7092 llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{
7094 X->getType()->hasSignedIntegerRepresentation(),
7095 X->getType().isVolatileQualified()};
7096 llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal;
7100 VOpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
7101 V->getType()->hasSignedIntegerRepresentation(),
7102 V->getType().isVolatileQualified()};
7107 ROpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
7108 R->getType()->hasSignedIntegerRepresentation(),
7109 R->getType().isVolatileQualified()};
7112 if (FailAO == llvm::AtomicOrdering::NotAtomic) {
7115 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
7116 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
7119 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
7120 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
7125 llvm::AtomicOrdering AO,
7146 case OMPC_compare: {
7152 llvm_unreachable(
"Clause is not allowed in 'omp atomic'.");
7157 llvm::AtomicOrdering AO =
CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
7159 llvm::AtomicOrdering FailAO = llvm::AtomicOrdering::NotAtomic;
7160 bool MemOrderingSpecified =
false;
7161 if (S.getSingleClause<OMPSeqCstClause>()) {
7162 AO = llvm::AtomicOrdering::SequentiallyConsistent;
7163 MemOrderingSpecified =
true;
7164 }
else if (S.getSingleClause<OMPAcqRelClause>()) {
7165 AO = llvm::AtomicOrdering::AcquireRelease;
7166 MemOrderingSpecified =
true;
7167 }
else if (S.getSingleClause<OMPAcquireClause>()) {
7168 AO = llvm::AtomicOrdering::Acquire;
7169 MemOrderingSpecified =
true;
7170 }
else if (S.getSingleClause<OMPReleaseClause>()) {
7171 AO = llvm::AtomicOrdering::Release;
7172 MemOrderingSpecified =
true;
7173 }
else if (S.getSingleClause<OMPRelaxedClause>()) {
7174 AO = llvm::AtomicOrdering::Monotonic;
7175 MemOrderingSpecified =
true;
7177 llvm::SmallSet<OpenMPClauseKind, 2> KindsEncountered;
7186 if (K == OMPC_seq_cst || K == OMPC_acq_rel || K == OMPC_acquire ||
7187 K == OMPC_release || K == OMPC_relaxed || K == OMPC_hint)
7190 KindsEncountered.insert(K);
7195 if (KindsEncountered.contains(OMPC_compare) &&
7196 KindsEncountered.contains(OMPC_capture))
7197 Kind = OMPC_compare;
7198 if (!MemOrderingSpecified) {
7199 llvm::AtomicOrdering DefaultOrder =
7200 CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
7201 if (DefaultOrder == llvm::AtomicOrdering::Monotonic ||
7202 DefaultOrder == llvm::AtomicOrdering::SequentiallyConsistent ||
7203 (DefaultOrder == llvm::AtomicOrdering::AcquireRelease &&
7204 Kind == OMPC_capture)) {
7206 }
else if (DefaultOrder == llvm::AtomicOrdering::AcquireRelease) {
7207 if (Kind == OMPC_unknown || Kind == OMPC_update || Kind == OMPC_write) {
7208 AO = llvm::AtomicOrdering::Release;
7209 }
else if (Kind == OMPC_read) {
7210 assert(Kind == OMPC_read &&
"Unexpected atomic kind.");
7211 AO = llvm::AtomicOrdering::Acquire;
7216 if (KindsEncountered.contains(OMPC_compare) &&
7217 KindsEncountered.contains(OMPC_fail)) {
7218 Kind = OMPC_compare;
7219 const auto *FailClause = S.getSingleClause<OMPFailClause>();
7222 if (FailParameter == llvm::omp::OMPC_relaxed)
7223 FailAO = llvm::AtomicOrdering::Monotonic;
7224 else if (FailParameter == llvm::omp::OMPC_acquire)
7225 FailAO = llvm::AtomicOrdering::Acquire;
7226 else if (FailParameter == llvm::omp::OMPC_seq_cst)
7227 FailAO = llvm::AtomicOrdering::SequentiallyConsistent;
7234 S.getV(), S.getR(), S.getExpr(), S.getUpdateExpr(),
7235 S.getD(), S.getCondExpr(), S.isXLHSInRHSPart(),
7236 S.isFailOnly(), S.getBeginLoc());
7247 OMPLexicalScope
Scope(CGF, S, OMPD_target);
7250 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
7256 llvm::Function *Fn =
nullptr;
7257 llvm::Constant *FnID =
nullptr;
7259 const Expr *IfCond =
nullptr;
7261 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7262 if (
C->getNameModifier() == OMPD_unknown ||
7263 C->getNameModifier() == OMPD_target) {
7264 IfCond =
C->getCondition();
7270 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device(
7273 Device.setPointerAndInt(
C->getDevice(),
C->getModifier());
7278 bool IsOffloadEntry =
true;
7282 IsOffloadEntry =
false;
7285 IsOffloadEntry =
false;
7287 if (
CGM.
getLangOpts().OpenMPOffloadMandatory && !IsOffloadEntry) {
7291 assert(CGF.
CurFuncDecl &&
"No parent declaration for target region!");
7292 StringRef ParentName;
7295 if (
const auto *D = dyn_cast<CXXConstructorDecl>(CGF.
CurFuncDecl))
7297 else if (
const auto *D = dyn_cast<CXXDestructorDecl>(CGF.
CurFuncDecl))
7306 OMPLexicalScope
Scope(CGF, S, OMPD_task);
7307 auto &&SizeEmitter =
7310 if (IsOffloadEntry) {
7311 OMPLoopScope(CGF, D);
7313 llvm::Value *NumIterations = CGF.
EmitScalarExpr(D.getNumIterations());
7314 NumIterations = CGF.
Builder.CreateIntCast(NumIterations, CGF.
Int64Ty,
7316 return NumIterations;
7334 CGF.
EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
7339 StringRef ParentName,
7345 llvm::Constant *
Addr;
7347 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7349 assert(Fn &&
Addr &&
"Target device function emission failed.");
7363 const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams);
7364 llvm::Function *OutlinedFn =
7369 OMPTeamsScope
Scope(CGF, S);
7374 const Expr *NumTeams = NT ? NT->getNumTeams().front() :
nullptr;
7375 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() :
nullptr;
7382 const Expr *IfCond =
nullptr;
7383 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7384 if (
C->getNameModifier() == OMPD_unknown ||
7385 C->getNameModifier() == OMPD_teams) {
7386 IfCond =
C->getCondition();
7395 const llvm::APInt One(32, 1);
7402 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() :
nullptr;
7428 CGF.
EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt());
7433 [](CodeGenFunction &) {
return nullptr; });
7438 auto *CS = S.getCapturedStmt(OMPD_teams);
7465 llvm::Constant *
Addr;
7467 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7469 assert(Fn &&
Addr &&
"Target device function emission failed.");
7511 llvm::Constant *
Addr;
7513 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7515 assert(Fn &&
Addr &&
"Target device function emission failed.");
7557 llvm::Constant *
Addr;
7559 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7561 assert(Fn &&
Addr &&
"Target device function emission failed.");
7575 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7580 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7592 [](CodeGenFunction &) {
return nullptr; });
7597 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7602 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7614 [](CodeGenFunction &) {
return nullptr; });
7619 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7625 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7637 [](CodeGenFunction &) {
return nullptr; });
7642 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7648 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7655 CGF, OMPD_distribute, CodeGenDistribute,
false);
7661 [](CodeGenFunction &) {
return nullptr; });
7665 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7666 llvm::Value *
Device =
nullptr;
7667 llvm::Value *NumDependences =
nullptr;
7668 llvm::Value *DependenceList =
nullptr;
7676 if (!
Data.Dependences.empty()) {
7678 std::tie(NumDependences, DependenciesArray) =
7679 CGM.getOpenMPRuntime().emitDependClause(*
this,
Data.Dependences,
7683 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
7688 "OMPNowaitClause clause is used separately in OMPInteropDirective.");
7691 if (!ItOMPInitClause.empty()) {
7694 llvm::Value *InteropvarPtr =
7696 llvm::omp::OMPInteropType InteropType =
7697 llvm::omp::OMPInteropType::Unknown;
7698 if (
C->getIsTarget()) {
7699 InteropType = llvm::omp::OMPInteropType::Target;
7701 assert(
C->getIsTargetSync() &&
7702 "Expected interop-type target/targetsync");
7703 InteropType = llvm::omp::OMPInteropType::TargetSync;
7705 OMPBuilder.createOMPInteropInit(
Builder, InteropvarPtr, InteropType,
7706 Device, NumDependences, DependenceList,
7707 Data.HasNowaitClause);
7711 if (!ItOMPDestroyClause.empty()) {
7714 llvm::Value *InteropvarPtr =
7716 OMPBuilder.createOMPInteropDestroy(
Builder, InteropvarPtr,
Device,
7717 NumDependences, DependenceList,
7718 Data.HasNowaitClause);
7721 auto ItOMPUseClause = S.getClausesOfKind<
OMPUseClause>();
7722 if (!ItOMPUseClause.empty()) {
7725 llvm::Value *InteropvarPtr =
7727 OMPBuilder.createOMPInteropUse(
Builder, InteropvarPtr,
Device,
7728 NumDependences, DependenceList,
7729 Data.HasNowaitClause);
7751 CGF, OMPD_distribute, CodeGenDistribute,
false);
7770 llvm::Constant *
Addr;
7772 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7774 assert(Fn &&
Addr &&
"Target device function emission failed.");
7803 CGF, OMPD_distribute, CodeGenDistribute,
false);
7822 llvm::Constant *
Addr;
7824 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7826 assert(Fn &&
Addr &&
"Target device function emission failed.");
7839 CGM.getOpenMPRuntime().emitCancellationPointCall(*
this, S.getBeginLoc(),
7844 const Expr *IfCond =
nullptr;
7845 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7846 if (
C->getNameModifier() == OMPD_unknown ||
7847 C->getNameModifier() == OMPD_cancel) {
7848 IfCond =
C->getCondition();
7852 if (
CGM.getLangOpts().OpenMPIRBuilder) {
7853 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7859 llvm::Value *IfCondition =
nullptr;
7863 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
7865 return Builder.restoreIP(AfterIP);
7869 CGM.getOpenMPRuntime().emitCancelCall(*
this, S.getBeginLoc(), IfCond,
7875 if (Kind == OMPD_parallel || Kind == OMPD_task ||
7876 Kind == OMPD_target_parallel || Kind == OMPD_taskloop ||
7877 Kind == OMPD_master_taskloop || Kind == OMPD_parallel_master_taskloop)
7879 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
7880 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
7881 Kind == OMPD_distribute_parallel_for ||
7882 Kind == OMPD_target_parallel_for ||
7883 Kind == OMPD_teams_distribute_parallel_for ||
7884 Kind == OMPD_target_teams_distribute_parallel_for);
7885 return OMPCancelStack.getExitBlock();
7890 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7891 CaptureDeviceAddrMap) {
7892 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7893 for (
const Expr *OrigVarIt :
C.varlist()) {
7895 if (!Processed.insert(OrigVD).second)
7902 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7907 "Base should be the current struct!");
7908 MatchingVD = ME->getMemberDecl();
7913 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7914 if (InitAddrIt == CaptureDeviceAddrMap.end())
7922 Address(InitAddrIt->second, Ty,
7924 assert(IsRegistered &&
"firstprivate var already registered as private");
7932 while (
const auto *OASE = dyn_cast<ArraySectionExpr>(
Base))
7933 Base = OASE->getBase()->IgnoreParenImpCasts();
7934 while (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(
Base))
7935 Base = ASE->getBase()->IgnoreParenImpCasts();
7941 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7942 CaptureDeviceAddrMap) {
7943 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7944 for (
const Expr *Ref :
C.varlist()) {
7946 if (!Processed.insert(OrigVD).second)
7952 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7957 "Base should be the current struct!");
7958 MatchingVD = ME->getMemberDecl();
7963 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7964 if (InitAddrIt == CaptureDeviceAddrMap.end())
7970 Address(InitAddrIt->second, Ty,
7983 (void)PrivateScope.
addPrivate(OrigVD, PrivAddr);
7991 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
7992 CGM.getOpenMPRuntime().registerVTable(S);
8000 bool PrivatizeDevicePointers =
false;
8002 bool &PrivatizeDevicePointers;
8005 explicit DevicePointerPrivActionTy(
bool &PrivatizeDevicePointers)
8006 : PrivatizeDevicePointers(PrivatizeDevicePointers) {}
8007 void Enter(CodeGenFunction &CGF)
override {
8008 PrivatizeDevicePointers =
true;
8011 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
8014 auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
8015 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
8019 auto &&PrivCodeGen = [&](CodeGenFunction &CGF,
PrePostActionTy &Action) {
8021 PrivatizeDevicePointers =
false;
8027 if (PrivatizeDevicePointers) {
8041 std::optional<OpenMPDirectiveKind> CaptureRegion;
8042 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
8045 for (
const Expr *E :
C->varlist()) {
8047 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
8051 for (
const Expr *E :
C->varlist()) {
8053 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
8057 CaptureRegion = OMPD_unknown;
8060 OMPLexicalScope
Scope(CGF, S, CaptureRegion);
8072 OMPLexicalScope
Scope(CGF, S);
8081 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
8087 const Expr *IfCond =
nullptr;
8089 IfCond =
C->getCondition();
8100 CGM.getOpenMPRuntime().emitTargetDataCalls(*
this, S, IfCond,
Device, RCG,
8108 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8112 const Expr *IfCond =
nullptr;
8114 IfCond =
C->getCondition();
8121 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8122 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8129 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8133 const Expr *IfCond =
nullptr;
8135 IfCond =
C->getCondition();
8142 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8143 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8150 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
8178 llvm::Constant *
Addr;
8180 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8182 assert(Fn &&
Addr &&
"Target device function emission failed.");
8202 CGF, OMPD_target_parallel_for, S.
hasCancel());
8218 llvm::Constant *
Addr;
8220 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8222 assert(Fn &&
Addr &&
"Target device function emission failed.");
8257 llvm::Constant *
Addr;
8259 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8261 assert(Fn &&
Addr &&
"Target device function emission failed.");
8283 const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop);
8286 OMPLexicalScope
Scope(*
this, S, OMPD_taskloop,
false);
8291 const Expr *IfCond =
nullptr;
8292 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
8293 if (
C->getNameModifier() == OMPD_unknown ||
8294 C->getNameModifier() == OMPD_taskloop) {
8295 IfCond =
C->getCondition();
8308 Data.Schedule.setInt(
false);
8311 (Clause->getModifier() == OMPC_GRAINSIZE_strict) ?
true :
false;
8314 Data.Schedule.setInt(
true);
8317 (Clause->getModifier() == OMPC_NUMTASKS_strict) ?
true :
false;
8331 llvm::BasicBlock *ContBlock =
nullptr;
8332 OMPLoopScope PreInitScope(CGF, S);
8333 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
8337 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock(
"taskloop.if.then");
8338 ContBlock = CGF.createBasicBlock(
"taskloop.if.end");
8339 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
8340 CGF.getProfileCount(&S));
8341 CGF.EmitBlock(ThenBlock);
8342 CGF.incrementProfileCounter(&S);
8345 (void)CGF.EmitOMPLinearClauseInit(S);
8349 enum { LowerBound = 5, UpperBound, Stride, LastIter };
8351 auto *LBP = std::next(I, LowerBound);
8352 auto *UBP = std::next(I, UpperBound);
8353 auto *STP = std::next(I, Stride);
8354 auto *LIP = std::next(I, LastIter);
8362 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
8363 CGF.EmitOMPLinearClause(S, LoopScope);
8364 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
8367 const Expr *IVExpr = S.getIterationVariable();
8369 CGF.EmitVarDecl(*IVDecl);
8370 CGF.EmitIgnoredExpr(S.getInit());
8375 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
8378 CGF.EmitIgnoredExpr(S.getCalcLastIteration());
8382 OMPLexicalScope
Scope(CGF, S, OMPD_taskloop,
false);
8392 [&S](CodeGenFunction &CGF) {
8393 emitOMPLoopBodyWithStopPoint(CGF, S,
8394 CodeGenFunction::JumpDest());
8396 [](CodeGenFunction &) {});
8401 CGF.EmitBranch(ContBlock);
8402 CGF.EmitBlock(ContBlock,
true);
8405 if (HasLastprivateClause) {
8406 CGF.EmitOMPLastprivateClauseFinal(
8408 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
8409 CGF.GetAddrOfLocalVar(*LIP),
false,
8410 (*LIP)->getType(), S.getBeginLoc())));
8413 CGF.EmitOMPLinearClauseFinal(S, [LIP, &S](CodeGenFunction &CGF) {
8414 return CGF.
Builder.CreateIsNotNull(
8416 (*LIP)->
getType(), S.getBeginLoc()));
8419 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
8420 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
8422 auto &&
CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
8424 OMPLoopScope PreInitScope(CGF, S);
8425 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S,
8426 OutlinedFn, SharedsTy,
8427 CapturedStruct, IfCond,
Data);
8429 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
8435 CGM.getOpenMPRuntime().emitTaskgroupRegion(
8437 [&S, &BodyGen, &TaskGen, &
Data](CodeGenFunction &CGF,
8457 OMPLexicalScope
Scope(*
this, S);
8469 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8470 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8481 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8482 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8493 OMPLexicalScope
Scope(*
this, S);
8494 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8505 OMPLexicalScope
Scope(*
this, S);
8506 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8512 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8517 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8518 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8530 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8535 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8536 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8548 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8553 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8554 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8566 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8571 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8572 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8586 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8590 const Expr *IfCond =
nullptr;
8592 IfCond =
C->getCondition();
8599 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8600 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8610 BindKind =
C->getBindKind();
8613 case OMPC_BIND_parallel:
8615 case OMPC_BIND_teams:
8617 case OMPC_BIND_thread:
8628 const auto *ForS = dyn_cast<ForStmt>(CS);
8639 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
8640 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_loop,
CodeGen);
8666 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
8671 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
8683 [](CodeGenFunction &) {
return nullptr; });
8688 std::string StatusMsg,
8692 StatusMsg +=
": DEVICE";
8694 StatusMsg +=
": HOST";
8701 llvm::dbgs() << StatusMsg <<
": " <<
FileName <<
": " << LineNo <<
"\n";
8724 CGF, OMPD_distribute, CodeGenDistribute,
false);
8753 CGF, OMPD_distribute, CodeGenDistribute,
false);
8786 llvm::Constant *
Addr;
8788 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8790 assert(Fn &&
Addr &&
8791 "Target device function emission failed for 'target teams loop'.");
8802 CGF, OMPD_target_parallel_loop,
false);
8818 llvm::Constant *
Addr;
8820 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8822 assert(Fn &&
Addr &&
"Target device function emission failed.");
8837 if (
const auto *SD = dyn_cast<OMPScanDirective>(&D)) {
8841 if (!D.hasAssociatedStmt() || !D.getAssociatedStmt())
8847 for (
const auto *
C : D.getClausesOfKind<OMPFirstprivateClause>()) {
8848 for (
const Expr *Ref :
C->varlist()) {
8852 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
8855 if (!CGF.LocalDeclMap.count(VD)) {
8867 if (
const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
8868 for (
const Expr *E : LD->counters()) {
8876 if (!CGF.LocalDeclMap.count(VD))
8880 for (
const auto *
C : D.getClausesOfKind<OMPOrderedClause>()) {
8881 if (!
C->getNumForLoops())
8883 for (
unsigned I = LD->getLoopsNumber(),
8884 E =
C->getLoopNumIterations().size();
8886 if (
const auto *VD = dyn_cast<OMPCapturedExprDecl>(
8889 if (!CGF.LocalDeclMap.count(VD))
8896 CGF.
EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
8899 if (D.getDirectiveKind() == OMPD_atomic ||
8900 D.getDirectiveKind() == OMPD_critical ||
8901 D.getDirectiveKind() == OMPD_section ||
8902 D.getDirectiveKind() == OMPD_master ||
8903 D.getDirectiveKind() == OMPD_masked ||
8904 D.getDirectiveKind() == OMPD_unroll ||
8905 D.getDirectiveKind() == OMPD_assume) {
8910 OMPSimdLexicalScope
Scope(*
this, D);
8911 CGM.getOpenMPRuntime().emitInlinedDirective(
8914 : 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
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