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/Metadata.h"
39#include "llvm/Support/AtomicOrdering.h"
40#include "llvm/Support/Debug.h"
44using namespace llvm::omp;
46#define TTL_CODEGEN_TYPE "target-teams-loop-codegen"
62 if (DKind == OMPD_teams_loop)
64 if (
const auto *TTLD = dyn_cast<OMPTargetTeamsGenericLoopDirective>(&S);
65 TTLD && !TTLD->canBeParallelFor())
71 S.hasClausesOfKind<OMPReductionClause>() &&
73 !S.getSingleClause<OMPScheduleClause>() &&
74 !S.getSingleClause<OMPOrderedClause>();
81 void emitPreInitStmt(CodeGenFunction &CGF,
const OMPExecutableDirective &S) {
82 for (
const auto *
C : S.clauses()) {
83 if (
const auto *CPI = OMPClauseWithPreInit::get(
C)) {
84 if (
const auto *PreInit =
85 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
86 for (
const auto *I : PreInit->decls()) {
87 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
90 CodeGenFunction::AutoVarEmission Emission =
99 CodeGenFunction::OMPPrivateScope InlinedShareds;
101 static bool isCapturedVar(CodeGenFunction &CGF,
const VarDecl *VD) {
110 CodeGenFunction &CGF,
const OMPExecutableDirective &S,
111 const std::optional<OpenMPDirectiveKind> CapturedRegion = std::nullopt,
112 const bool EmitPreInitStmt =
true)
114 InlinedShareds(CGF) {
116 emitPreInitStmt(CGF, S);
119 assert(S.hasAssociatedStmt() &&
120 "Expected associated statement for inlined directive.");
121 const CapturedStmt *CS = S.getCapturedStmt(*CapturedRegion);
123 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
124 auto *VD =
C.getCapturedVar();
126 "Canonical decl must be captured.");
130 InlinedShareds.isGlobalVarCaptured(VD)),
135 (void)InlinedShareds.Privatize();
141class OMPParallelScope final :
public OMPLexicalScope {
142 bool EmitPreInitStmt(
const OMPExecutableDirective &S) {
150 OMPParallelScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
151 : OMPLexicalScope(CGF, S, std::nullopt,
152 EmitPreInitStmt(S)) {}
157class OMPTeamsScope final :
public OMPLexicalScope {
158 bool EmitPreInitStmt(
const OMPExecutableDirective &S) {
165 OMPTeamsScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
166 : OMPLexicalScope(CGF, S, std::nullopt,
167 EmitPreInitStmt(S)) {}
173 void emitPreInitStmt(CodeGenFunction &CGF,
const OMPLoopBasedDirective &S) {
174 const Stmt *PreInits;
175 CodeGenFunction::OMPMapVars PreCondVars;
176 SmallVector<const Decl *, 4> DoacrossOnlyDecls;
177 if (
auto *LD = dyn_cast<OMPLoopDirective>(&S)) {
179 (void)OMPLoopBasedDirective::doForAllLoops(
180 LD->getInnermostCapturedStmt()->getCapturedStmt(),
181 true, LD->getLoopsNumber(),
182 [&CGF](
unsigned Cnt,
const Stmt *CurStmt) {
183 if (const auto *CXXFor = dyn_cast<CXXForRangeStmt>(CurStmt)) {
184 if (const Stmt *Init = CXXFor->getInit())
186 CGF.EmitStmt(CXXFor->getRangeStmt());
187 CGF.EmitStmt(CXXFor->getBeginStmt());
188 CGF.EmitStmt(CXXFor->getEndStmt());
192 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
193 for (
const auto *E : LD->counters()) {
200 for (
const auto *
C : LD->getClausesOfKind<OMPPrivateClause>()) {
201 for (
const Expr *IRef :
C->varlist()) {
203 const auto *OrigVD = dyn_cast<VarDecl>(OrigDecl);
206 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
207 QualType OrigVDTy = OrigVD->getType().getNonReferenceType();
217 (void)PreCondVars.
apply(CGF);
222 if (
const auto *
C = LD->getSingleClause<OMPOrderedClause>())
223 (void)OMPLoopBasedDirective::doForAllLoops(
224 LD->getInnermostCapturedStmt()->getCapturedStmt(),
226 C->getLoopNumIterations().size(),
227 [&CGF, LD, &DoacrossOnlyDecls](
unsigned Cnt,
const Stmt *CurStmt) {
228 const auto *CXXFor = dyn_cast<CXXForRangeStmt>(CurStmt);
229 if (!CXXFor || Cnt < LD->getLoopsNumber())
231 for (const Stmt *Helper : std::initializer_list<const Stmt *>{
232 CXXFor->getInit(), CXXFor->getRangeStmt(),
233 CXXFor->getBeginStmt(), CXXFor->getEndStmt()}) {
237 if (
const auto *DS = dyn_cast<DeclStmt>(Helper))
238 llvm::append_range(DoacrossOnlyDecls, DS->decls());
242 PreInits = LD->getPreInits();
243 }
else if (
const auto *
Tile = dyn_cast<OMPTileDirective>(&S)) {
244 PreInits =
Tile->getPreInits();
245 }
else if (
const auto *Stripe = dyn_cast<OMPStripeDirective>(&S)) {
246 PreInits = Stripe->getPreInits();
247 }
else if (
const auto *Unroll = dyn_cast<OMPUnrollDirective>(&S)) {
248 PreInits = Unroll->getPreInits();
249 }
else if (
const auto *Reverse = dyn_cast<OMPReverseDirective>(&S)) {
250 PreInits = Reverse->getPreInits();
251 }
else if (
const auto *Split = dyn_cast<OMPSplitDirective>(&S)) {
252 PreInits =
Split->getPreInits();
253 }
else if (
const auto *Interchange =
254 dyn_cast<OMPInterchangeDirective>(&S)) {
255 PreInits = Interchange->getPreInits();
256 }
else if (
const auto *Flatten = dyn_cast<OMPFlattenDirective>(&S)) {
257 PreInits = Flatten->getPreInits();
259 llvm_unreachable(
"Unknown loop-based directive kind.");
261 doEmitPreinits(PreInits);
262 for (
const Decl *D : DoacrossOnlyDecls)
270 const Stmt *PreInits;
271 if (
const auto *Fuse = dyn_cast<OMPFuseDirective>(&S)) {
272 PreInits = Fuse->getPreInits();
275 "Unknown canonical loop sequence transform directive kind.");
277 doEmitPreinits(PreInits);
280 void doEmitPreinits(
const Stmt *PreInits) {
286 if (
auto *PreInitCompound = dyn_cast<CompoundStmt>(PreInits))
287 llvm::append_range(PreInitStmts, PreInitCompound->body());
289 PreInitStmts.push_back(PreInits);
291 for (
const Stmt *S : PreInitStmts) {
294 if (
auto *PreInitDecl = dyn_cast<DeclStmt>(S)) {
295 for (
Decl *I : PreInitDecl->decls())
307 emitPreInitStmt(CGF, S);
312 emitPreInitStmt(CGF, S);
317 CodeGenFunction::OMPPrivateScope InlinedShareds;
319 static bool isCapturedVar(CodeGenFunction &CGF,
const VarDecl *VD) {
327 OMPSimdLexicalScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
329 InlinedShareds(CGF) {
330 for (
const auto *
C : S.clauses()) {
331 if (const auto *CPI = OMPClauseWithPreInit::get(C)) {
332 if (const auto *PreInit =
333 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
334 for (const auto *I : PreInit->decls()) {
335 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
336 CGF.EmitVarDecl(cast<VarDecl>(*I));
338 CodeGenFunction::AutoVarEmission Emission =
339 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
340 CGF.EmitAutoVarCleanups(Emission);
344 }
else if (
const auto *UDP = dyn_cast<OMPUseDevicePtrClause>(
C)) {
345 for (
const Expr *E : UDP->varlist()) {
347 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
350 }
else if (
const auto *UDP = dyn_cast<OMPUseDeviceAddrClause>(
C)) {
351 for (
const Expr *E : UDP->varlist()) {
353 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
360 if (
const auto *TG = dyn_cast<OMPTaskgroupDirective>(&S)) {
361 if (
const Expr *E = TG->getReductionRef())
366 llvm::DenseSet<CanonicalDeclPtr<const Decl>> CopyArrayTemps;
367 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
368 if (C->getModifier() != OMPC_REDUCTION_inscan)
370 for (const Expr *E : C->copy_array_temps())
371 CopyArrayTemps.insert(cast<DeclRefExpr>(E)->getDecl());
373 const auto *CS = cast_or_null<CapturedStmt>(S.getAssociatedStmt());
376 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
377 auto *VD =
C.getCapturedVar();
378 if (CopyArrayTemps.contains(VD))
381 "Canonical decl must be captured.");
382 DeclRefExpr DRE(CGF.
getContext(),
const_cast<VarDecl *
>(VD),
383 isCapturedVar(CGF, VD) ||
385 InlinedShareds.isGlobalVarCaptured(VD)),
393 (void)InlinedShareds.Privatize();
405 if (Kind == OMPD_teams_loop)
406 return OMPD_teams_distribute;
407 if (Kind == OMPD_target_loop)
408 return OMPD_target_simd;
409 if (Kind == OMPD_target_teams_loop)
411 ? OMPD_target_teams_distribute_parallel_for
412 : OMPD_target_teams_distribute;
414 if (Kind != OMPD_loop)
419 BindKind =
C->getBindKind();
422 case OMPC_BIND_parallel:
424 case OMPC_BIND_teams:
425 return OMPD_distribute;
426 case OMPC_BIND_thread:
453 if (
const auto *OrigDRE = dyn_cast<DeclRefExpr>(E)) {
454 if (
const auto *OrigVD = dyn_cast<VarDecl>(OrigDRE->getDecl())) {
455 OrigVD = OrigVD->getCanonicalDecl();
461 OrigDRE->getType(),
VK_LValue, OrigDRE->getExprLoc());
464 if (
const auto *OrigBD = dyn_cast<BindingDecl>(OrigDRE->getDecl())) {
471 IsCaptured, OrigDRE->getType(),
VK_LValue,
472 OrigDRE->getExprLoc());
481 llvm::Value *Size =
nullptr;
482 auto SizeInChars =
C.getTypeSizeInChars(Ty);
483 if (SizeInChars.isZero()) {
491 SizeInChars =
C.getTypeSizeInChars(Ty);
492 if (SizeInChars.isZero())
493 return llvm::ConstantInt::get(
SizeTy, 0);
494 return Builder.CreateNUWMul(Size,
CGM.getSize(SizeInChars));
496 return CGM.getSize(SizeInChars);
506 I != E; ++I, ++CurField, ++CurCap) {
507 if (CurField->hasCapturedVLAType()) {
510 CapturedVars.push_back(Val);
511 }
else if (CurCap->capturesThis()) {
512 CapturedVars.push_back(CXXThisValue);
513 }
else if (CurCap->capturesVariableByCopy()) {
518 if (!CurField->getType()->isAnyPointerType()) {
522 Twine(CurCap->getCapturedVar()->getName(),
".casted"));
538 CapturedVars.push_back(CV);
540 assert(CurCap->capturesVariable() &&
"Expected capture by reference.");
543 llvm::Type *ArgTy =
ConvertType(CurField->getType());
544 if (
Addr->getType() != ArgTy)
546 CapturedVars.push_back(
Addr);
566 if (
T->isLValueReferenceType())
567 return C.getLValueReferenceType(
570 if (
T->isPointerType())
572 if (
const ArrayType *A =
T->getAsArrayTypeUnsafe()) {
573 if (
const auto *VLA = dyn_cast<VariableArrayType>(A))
575 if (!A->isVariablyModifiedType())
576 return C.getCanonicalType(
T);
578 return C.getCanonicalParamType(
T);
583struct FunctionOptions {
585 const CapturedStmt *S =
nullptr;
588 const bool UIntPtrCastRequired =
true;
591 const bool RegisterCastedArgsOnly =
false;
593 const StringRef FunctionName;
596 const bool IsDeviceKernel =
false;
597 explicit FunctionOptions(
const CapturedStmt *S,
bool UIntPtrCastRequired,
598 bool RegisterCastedArgsOnly, StringRef FunctionName,
599 SourceLocation Loc,
bool IsDeviceKernel)
600 : S(S), UIntPtrCastRequired(UIntPtrCastRequired),
601 RegisterCastedArgsOnly(UIntPtrCastRequired && RegisterCastedArgsOnly),
602 FunctionName(FunctionName), Loc(Loc), IsDeviceKernel(IsDeviceKernel) {}
608 llvm::MapVector<
const Decl *, std::pair<const VarDecl *, Address>>
610 llvm::DenseMap<
const Decl *, std::pair<const Expr *, llvm::Value *>>
612 llvm::Value *&CXXThisValue,
const FunctionOptions &FO) {
615 assert(CD->
hasBody() &&
"missing CapturedDecl body");
617 CXXThisValue =
nullptr;
629 if (!FO.UIntPtrCastRequired) {
649 if (FO.UIntPtrCastRequired &&
650 ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) ||
651 I->capturesVariableArrayType()))
654 if (I->capturesVariable() || I->capturesVariableByCopy()) {
655 CapVar = I->getCapturedVar();
657 }
else if (I->capturesThis()) {
660 assert(I->capturesVariableArrayType());
663 if (ArgType->isVariablyModifiedType())
670 }
else if (DebugFunctionDecl && (CapVar || I->capturesThis())) {
672 Ctx, DebugFunctionDecl,
673 CapVar ? CapVar->
getBeginLoc() : FD->getBeginLoc(),
674 CapVar ? CapVar->
getLocation() : FD->getLocation(), II, ArgType,
680 Args.emplace_back(Arg);
682 TargetArgs.emplace_back(
683 FO.UIntPtrCastRequired
704 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
710 if (CGM.
getTriple().isSPIRV() && !FO.IsDeviceKernel)
711 F->setCallingConv(llvm::CallingConv::SPIR_FUNC);
714 F->setDoesNotThrow();
718 F->removeFnAttr(llvm::Attribute::NoInline);
719 F->addFnAttr(llvm::Attribute::AlwaysInline);
722 F->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
726 FO.UIntPtrCastRequired ? FO.Loc : FO.S->
getBeginLoc(),
727 FO.UIntPtrCastRequired ? FO.Loc
734 if (!FO.UIntPtrCastRequired && Args[Cnt] != TargetArgs[Cnt]) {
742 if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
743 const VarDecl *CurVD = I->getCapturedVar();
744 if (!FO.RegisterCastedArgsOnly)
745 LocalAddrs.insert({Args[Cnt], {CurVD, LocalAddr}});
753 if (FD->hasCapturedVLAType()) {
754 if (FO.UIntPtrCastRequired) {
757 Args[Cnt]->getName(), ArgLVal),
762 VLASizes.try_emplace(Args[Cnt], VAT->
getSizeExpr(), ExprArg);
763 }
else if (I->capturesVariable()) {
764 const VarDecl *Var = I->getCapturedVar();
766 Address ArgAddr = ArgLVal.getAddress();
767 if (ArgLVal.getType()->isLValueReferenceType()) {
770 assert(ArgLVal.getType()->isPointerType());
772 ArgAddr, ArgLVal.getType()->castAs<
PointerType>());
774 if (!FO.RegisterCastedArgsOnly) {
778 }
else if (I->capturesVariableByCopy()) {
779 assert(!FD->getType()->isAnyPointerType() &&
780 "Not expecting a captured pointer.");
781 const VarDecl *Var = I->getCapturedVar();
782 LocalAddrs.insert({Args[Cnt],
783 {Var, FO.UIntPtrCastRequired
785 CGF, I->getLocation(), FD->getType(),
786 Args[Cnt]->getName(), ArgLVal)
787 : ArgLVal.getAddress()}});
790 assert(I->capturesThis());
792 LocalAddrs.insert({Args[Cnt], {
nullptr, ArgLVal.getAddress()}});
803 llvm::MapVector<
const Decl *, std::pair<const VarDecl *, Address>>
805 llvm::DenseMap<
const Decl *, std::pair<const Expr *, llvm::Value *>>
807 llvm::Value *&CXXThisValue, llvm::Value *&ContextV,
const CapturedStmt &CS,
812 CXXThisValue =
nullptr;
822 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
826 F->setDoesNotThrow();
833 llvm::Type *PtrTy = CGF.
Builder.getPtrTy();
834 llvm::Align PtrAlign = CGM.
getDataLayout().getPointerABIAlignment(0);
837 for (
auto [FD,
C, FieldIdx] :
840 llvm::Value *SlotPtr =
841 CGF.
Builder.CreateConstInBoundsGEP1_32(PtrTy, ContextV, FieldIdx);
847 if (
C.capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
848 const VarDecl *CurVD =
C.getCapturedVar();
849 Slot->setName(CurVD->
getName());
850 Address SlotAddr(Slot, PtrTy, SlotAlign);
851 LocalAddrs.insert({FD, {CurVD, SlotAddr}});
852 }
else if (FD->hasCapturedVLAType()) {
859 VLASizes.try_emplace(FD, VAT->
getSizeExpr(), ExprArg);
860 }
else if (
C.capturesVariable()) {
861 const VarDecl *Var =
C.getCapturedVar();
865 Slot->setName(Var->
getName() +
".addr");
866 Address SlotAddr(Slot, PtrTy, SlotAlign);
867 LocalAddrs.insert({FD, {Var, SlotAddr}});
870 PtrTy, Slot, PtrAlign, Var->
getName());
871 LocalAddrs.insert({FD,
875 }
else if (
C.capturesVariableByCopy()) {
876 assert(!FD->getType()->isAnyPointerType() &&
877 "Not expecting a captured pointer.");
878 const VarDecl *Var =
C.getCapturedVar();
893 LocalAddrs.insert({FD, {Var, CopyAddr}});
895 assert(
C.capturesThis() &&
"Default case expected to be CXX 'this'");
898 Address SlotAddr(Slot, PtrTy, SlotAlign);
899 LocalAddrs.insert({FD, {
nullptr, SlotAddr}});
911 "CapturedStmtInfo should be set when generating the captured function");
914 bool NeedWrapperFunction =
917 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs,
919 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes,
922 llvm::raw_svector_ostream Out(Buffer);
925 bool IsDeviceKernel =
CGM.getOpenMPRuntime().isGPU() &&
927 D.getCapturedStmt(OMPD_target) == &S;
928 CodeGenFunction WrapperCGF(
CGM,
true);
929 llvm::Function *WrapperF =
nullptr;
930 if (NeedWrapperFunction) {
933 FunctionOptions WrapperFO(&S,
true,
940 WrapperCGF.CXXThisValue, WrapperFO);
943 FunctionOptions FO(&S, !NeedWrapperFunction,
false,
944 Out.str(), Loc, !NeedWrapperFunction && IsDeviceKernel);
946 *
this, WrapperArgs, WrapperLocalAddrs, WrapperVLASizes, CXXThisValue, FO);
948 for (
const auto &LocalAddrPair : WrapperLocalAddrs) {
949 if (LocalAddrPair.second.first) {
950 LocalScope.addPrivate(LocalAddrPair.second.first,
951 LocalAddrPair.second.second);
954 (void)LocalScope.Privatize();
955 for (
const auto &VLASizePair : WrapperVLASizes)
956 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
959 LocalScope.ForceCleanup();
961 if (!NeedWrapperFunction)
965 WrapperF->removeFromParent();
966 F->getParent()->getFunctionList().insertAfter(F->getIterator(), WrapperF);
969 auto *PI = F->arg_begin();
970 for (
const auto *Arg : Args) {
972 auto I = LocalAddrs.find(Arg);
973 if (I != LocalAddrs.end()) {
976 I->second.first ? I->second.first->getType() : Arg->getType(),
982 auto EI = VLASizes.find(Arg);
983 if (EI != VLASizes.end()) {
995 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
1005 "CapturedStmtInfo should be set when generating the captured function");
1009 bool NeedWrapperFunction =
1012 CodeGenFunction WrapperCGF(
CGM,
true);
1013 llvm::Function *WrapperF =
nullptr;
1014 llvm::Value *WrapperContextV =
nullptr;
1015 if (NeedWrapperFunction) {
1018 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>>
1020 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>>
1023 WrapperCGF, WrapperArgs, WrapperLocalAddrs, WrapperVLASizes,
1024 WrapperCGF.CXXThisValue, WrapperContextV, S, Loc, FunctionName);
1028 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs;
1029 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes;
1032 if (NeedWrapperFunction) {
1034 llvm::raw_svector_ostream Out(Buffer);
1035 Out << FunctionName <<
"_debug__";
1037 FunctionOptions FO(&S,
false,
1038 false, Out.str(), Loc,
1043 llvm::Value *ContextV =
nullptr;
1045 CXXThisValue, ContextV, S, Loc,
1054 llvm::Align PtrAlign =
CGM.getDataLayout().getPointerABIAlignment(0);
1055 llvm::Value *SlotPtr =
Builder.CreateConstInBoundsGEP1_32(
1056 Builder.getPtrTy(), ContextV, FieldIdx,
1057 Twine(Param->getName()) +
".addr");
1058 llvm::Value *ParamAddr =
1059 Builder.CreateAlignedLoad(
Builder.getPtrTy(), SlotPtr, PtrAlign);
1060 llvm::Value *ParamVal =
Builder.CreateAlignedLoad(
1061 Builder.getPtrTy(), ParamAddr, PtrAlign, Param->getName());
1064 Builder.CreateStore(ParamVal, ParamLocalAddr);
1065 LocalAddrs.insert({Param, {Param, ParamLocalAddr}});
1071 for (
const auto &LocalAddrPair : LocalAddrs) {
1072 if (LocalAddrPair.second.first)
1073 LocalScope.addPrivate(LocalAddrPair.second.first,
1074 LocalAddrPair.second.second);
1076 (void)LocalScope.Privatize();
1077 for (
const auto &VLASizePair : VLASizes)
1078 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
1079 PGO->assignRegionCounters(
GlobalDecl(CD), F);
1081 (void)LocalScope.ForceCleanup();
1084 if (!NeedWrapperFunction)
1088 WrapperF->removeFromParent();
1089 F->getParent()->getFunctionList().insertAfter(F->getIterator(), WrapperF);
1091 llvm::Align PtrAlign =
CGM.getDataLayout().getPointerABIAlignment(0);
1094 "Expected context param at position 0 for target regions");
1095 assert(RD->
getNumFields() + 1 == F->arg_size() &&
"Argument count mismatch");
1097 for (
auto [FD, InnerParam, SlotIdx] : llvm::zip(
1099 llvm::Value *SlotPtr = WrapperCGF.
Builder.CreateConstInBoundsGEP1_32(
1100 WrapperCGF.
Builder.getPtrTy(), WrapperContextV, SlotIdx);
1102 WrapperCGF.
Builder.getPtrTy(), SlotPtr, PtrAlign);
1104 InnerParam.getType(), Slot, PtrAlign, InnerParam.getName());
1105 CallArgs.push_back(Val);
1110 auto InnerParam = F->arg_begin() + SlotIdx;
1111 llvm::Value *SlotPtr = WrapperCGF.
Builder.CreateConstInBoundsGEP1_32(
1112 WrapperCGF.
Builder.getPtrTy(), WrapperContextV, SlotIdx);
1114 WrapperCGF.
Builder.getPtrTy(), SlotPtr, PtrAlign);
1116 InnerParam->getType(), Slot, PtrAlign, InnerParam->getName());
1117 CallArgs.push_back(Val);
1119 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
1135 llvm::Value *NumElements =
emitArrayLength(ArrayTy, ElementTy, DestAddr);
1142 DestBegin, NumElements);
1147 llvm::Value *IsEmpty =
1148 Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arraycpy.isempty");
1149 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
1152 llvm::BasicBlock *EntryBB =
Builder.GetInsertBlock();
1157 llvm::PHINode *SrcElementPHI =
1158 Builder.CreatePHI(SrcBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
1159 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
1164 llvm::PHINode *DestElementPHI =
Builder.CreatePHI(
1165 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
1166 DestElementPHI->addIncoming(DestBegin, EntryBB);
1172 CopyGen(DestElementCurrent, SrcElementCurrent);
1175 llvm::Value *DestElementNext =
1177 1,
"omp.arraycpy.dest.element");
1178 llvm::Value *SrcElementNext =
1180 1,
"omp.arraycpy.src.element");
1183 Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
1184 Builder.CreateCondBr(Done, DoneBB, BodyBB);
1185 DestElementPHI->addIncoming(DestElementNext,
Builder.GetInsertBlock());
1186 SrcElementPHI->addIncoming(SrcElementNext,
Builder.GetInsertBlock());
1196 const auto *BO = dyn_cast<BinaryOperator>(
Copy);
1197 if (BO && BO->getOpcode() == BO_Assign) {
1206 DestAddr, SrcAddr, OriginalType,
1234 bool DeviceConstTarget =
getLangOpts().OpenMPIsTargetDevice &&
1236 bool FirstprivateIsLastprivate =
false;
1237 llvm::SmallDenseMap<const Decl *, OpenMPLastprivateModifier> Lastprivates;
1238 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1239 for (
const auto *D :
C->varlist()) {
1244 llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
1249 bool MustEmitFirstprivateCopy =
1250 CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown;
1251 for (
const auto *
C : D.getClausesOfKind<OMPFirstprivateClause>()) {
1252 const auto *IRef =
C->varlist_begin();
1253 const auto *InitsRef =
C->inits().begin();
1254 for (
const Expr *IInit :
C->private_copies()) {
1258 if (
const auto *BD = dyn_cast<BindingDecl>(OrigDecl)) {
1260 bool ThisFirstprivateIsLastprivate =
1261 Lastprivates.count(BD->getCanonicalDecl()) > 0;
1265 if (!MustEmitFirstprivateCopy && !ThisFirstprivateIsLastprivate) {
1267 if (!FD->getType()->isReferenceType()) {
1270 assert(IsRegistered &&
1271 "firstprivate var already registered as firstprivate");
1279 const auto *VDInit =
1286 if (
Type->isArrayType()) {
1301 RunCleanupsScope InitScope(*this);
1303 setAddrOfLocalVar(VDInit, SrcElement);
1304 EmitAnyExprToMem(Init, DestElement,
1305 Init->getType().getQualifiers(),
1307 LocalDeclMap.erase(VDInit);
1316 setAddrOfLocalVar(VDInit, OriginalAddr);
1318 LocalDeclMap.erase(VDInit);
1321 IsRegistered = PrivateScope.
addPrivate(BD, VDAddr);
1324 assert(IsRegistered &&
1325 "firstprivate var already registered as firstprivate");
1327 FirstprivateIsLastprivate =
1328 FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate;
1335 const VarDecl *OrigVD = dyn_cast<VarDecl>(OrigDecl);
1336 assert(OrigVD &&
"Expected VarDecl for non-BindingDecl firstprivate");
1337 bool ThisFirstprivateIsLastprivate =
1340 if (!MustEmitFirstprivateCopy && !ThisFirstprivateIsLastprivate && FD &&
1342 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
1352 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
1358 FirstprivateIsLastprivate =
1359 FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate;
1361 const auto *VDInit =
1380 assert(!CE &&
"Expected non-constant firstprivate.");
1387 if (
Type->isArrayType()) {
1403 RunCleanupsScope InitScope(*this);
1405 setAddrOfLocalVar(VDInit, SrcElement);
1406 EmitAnyExprToMem(Init, DestElement,
1407 Init->getType().getQualifiers(),
1409 LocalDeclMap.erase(VDInit);
1420 setAddrOfLocalVar(VDInit, OriginalAddr);
1422 LocalDeclMap.erase(VDInit);
1424 if (ThisFirstprivateIsLastprivate &&
1426 OMPC_LASTPRIVATE_conditional) {
1431 (*IRef)->getExprLoc());
1432 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1436 LocalDeclMap.erase(VD);
1437 setAddrOfLocalVar(VD, VDAddr);
1439 IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1441 assert(IsRegistered &&
1442 "firstprivate var already registered as private");
1450 return FirstprivateIsLastprivate && !EmittedAsFirstprivate.empty();
1458 llvm::SmallDenseSet<const ValueDecl *> EmittedAsPrivate;
1459 for (
const auto *
C : D.getClausesOfKind<OMPPrivateClause>()) {
1460 auto IRef =
C->varlist_begin();
1461 for (
const Expr *IInit :
C->private_copies()) {
1464 if (EmittedAsPrivate.insert(
cast<ValueDecl>(OrigDecl->getCanonicalDecl()))
1469 assert(IsRegistered &&
"private var already registered as private");
1484 llvm::DenseSet<const VarDecl *> CopiedVars;
1485 llvm::BasicBlock *CopyBegin =
nullptr, *CopyEnd =
nullptr;
1487 auto IRef =
C->varlist_begin();
1488 auto ISrcRef =
C->source_exprs().begin();
1489 auto IDestRef =
C->destination_exprs().begin();
1490 for (
const Expr *AssignOp :
C->assignment_ops()) {
1499 getContext().getTargetInfo().isTLSSupported()) {
1501 "Copyin threadprivates should have been captured!");
1505 LocalDeclMap.erase(VD);
1509 :
CGM.GetAddrOfGlobal(VD),
1510 CGM.getTypes().ConvertTypeForMem(VD->
getType()),
1515 if (CopiedVars.size() == 1) {
1521 auto *MasterAddrInt =
Builder.CreatePtrToInt(
1523 auto *PrivateAddrInt =
Builder.CreatePtrToInt(
1526 Builder.CreateICmpNE(MasterAddrInt, PrivateAddrInt), CopyBegin,
1532 const auto *DestVD =
1553 bool HasAtLeastOneLastprivate =
false;
1555 llvm::DenseSet<const VarDecl *> SIMDLCVs;
1558 for (
const Expr *
C : LoopDirective->counters()) {
1563 llvm::SmallDenseSet<const ValueDecl *> AlreadyEmittedVars;
1564 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1565 HasAtLeastOneLastprivate =
true;
1568 const auto *IRef =
C->varlist_begin();
1569 const auto *IDestRef =
C->destination_exprs().begin();
1570 for (
const Expr *IInit :
C->private_copies()) {
1575 if (
const auto *BD = dyn_cast<BindingDecl>(OrigDecl)) {
1576 if (AlreadyEmittedVars.insert(
cast<ValueDecl>(BD->getCanonicalDecl()))
1578 const auto *DestVD =
1590 bool IsRegistered = PrivateScope.
addPrivate(BD, VDAddr);
1591 assert(IsRegistered &&
1592 "lastprivate binding already registered as private");
1603 if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) {
1604 const auto *DestVD =
1609 (*IRef)->getType(),
VK_LValue, (*IRef)->getExprLoc());
1614 if (IInit && !SIMDLCVs.count(OrigVD->getCanonicalDecl())) {
1617 if (
C->getKind() == OMPC_LASTPRIVATE_conditional) {
1618 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1620 setAddrOfLocalVar(VD, VDAddr);
1626 bool IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1627 assert(IsRegistered &&
1628 "lastprivate var already registered as private");
1636 return HasAtLeastOneLastprivate;
1641 llvm::Value *IsLastIterCond) {
1650 llvm::BasicBlock *ThenBB =
nullptr;
1651 llvm::BasicBlock *DoneBB =
nullptr;
1652 if (IsLastIterCond) {
1656 llvm::any_of(D.getClausesOfKind<OMPLastprivateClause>(),
1657 [](
const OMPLastprivateClause *
C) {
1658 return C->getKind() == OMPC_LASTPRIVATE_conditional;
1660 CGM.getOpenMPRuntime().emitBarrierCall(*
this, D.getBeginLoc(),
1667 Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB);
1670 llvm::DenseSet<const ValueDecl *> AlreadyEmittedVars;
1671 llvm::SmallDenseMap<const VarDecl *, const Expr *> LoopCountersAndUpdates;
1672 if (
const auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) {
1673 auto IC = LoopDirective->counters().begin();
1674 for (
const Expr *F : LoopDirective->finals()) {
1678 AlreadyEmittedVars.insert(D);
1680 LoopCountersAndUpdates[D] = F;
1684 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1685 auto IRef =
C->varlist_begin();
1686 auto ISrcRef =
C->source_exprs().begin();
1687 auto IDestRef =
C->destination_exprs().begin();
1688 for (
const Expr *AssignOp :
C->assignment_ops()) {
1693 const VarDecl *PrivateVD =
nullptr;
1695 if ((BD = dyn_cast<BindingDecl>(PrivateDecl))) {
1700 if (LocalDeclMap.count(SrcVD)) {
1703 }
else if (OMPPrivatizedBindings.count(BD)) {
1712 const auto *CanonicalVD =
1718 .insert(PrivateVD ?
static_cast<const ValueDecl *
>(CanonicalVD)
1726 if (
const Expr *FinalExpr =
1727 LoopCountersAndUpdates.lookup(CanonicalVD))
1732 const auto *DestVD =
1740 auto It = OMPPrivatizedBindings.find(BD);
1741 assert(It != OMPPrivatizedBindings.end() &&
1742 "BindingDecl should be privatized");
1743 PrivateAddr = It->second;
1748 Builder.CreateLoad(PrivateAddr),
1749 CGM.getTypes().ConvertTypeForMem(RefTy->getPointeeType()),
1750 CGM.getNaturalTypeAlignment(RefTy->getPointeeType()));
1753 if (
C->getKind() == OMPC_LASTPRIVATE_conditional)
1754 CGM.getOpenMPRuntime().emitLastprivateConditionalFinalUpdate(
1756 (*IRef)->getExprLoc());
1759 EmitOMPCopy(
Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp);
1765 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
1785 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1786 if (ForInscan != (
C->getModifier() == OMPC_REDUCTION_inscan))
1788 Shareds.append(
C->varlist_begin(),
C->varlist_end());
1789 Privates.append(
C->privates().begin(),
C->privates().end());
1790 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1791 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1792 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1793 if (
C->getModifier() == OMPC_REDUCTION_task) {
1794 Data.ReductionVars.append(
C->privates().begin(),
C->privates().end());
1795 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
1796 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
1797 Data.ReductionOps.append(
C->reduction_ops().begin(),
1798 C->reduction_ops().end());
1799 TaskLHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1800 TaskRHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1805 auto *ILHS = LHSs.begin();
1806 auto *IRHS = RHSs.begin();
1808 for (
const Expr *IRef : Shareds) {
1815 [&Emission](CodeGenFunction &CGF) {
1816 CGF.EmitAutoVarInit(Emission);
1824 assert(IsRegistered &&
"private var already registered as private");
1832 if (isaOMPArraySectionExpr &&
Type->isVariablyModifiedType()) {
1837 }
else if ((isaOMPArraySectionExpr &&
Type->isScalarType()) ||
1855 PrivateScope.
addPrivate(LHSVD, OriginalAddr);
1866 if (!
Data.ReductionVars.empty()) {
1868 Data.IsReductionWithTaskMod =
true;
1870 llvm::Value *ReductionDesc =
CGM.getOpenMPRuntime().emitTaskReductionInit(
1871 *
this, D.getBeginLoc(), TaskLHSs, TaskRHSs,
Data);
1872 const Expr *TaskRedRef =
nullptr;
1883 case OMPD_parallel_for:
1886 case OMPD_parallel_master:
1890 case OMPD_parallel_sections:
1894 case OMPD_target_parallel:
1898 case OMPD_target_parallel_for:
1902 case OMPD_distribute_parallel_for:
1906 case OMPD_teams_distribute_parallel_for:
1908 .getTaskReductionRefExpr();
1910 case OMPD_target_teams_distribute_parallel_for:
1912 .getTaskReductionRefExpr();
1920 case OMPD_parallel_for_simd:
1922 case OMPD_taskyield:
1926 case OMPD_taskgroup:
1930 case OMPD_ordered_standalone:
1931 case OMPD_ordered_blockassoc:
1935 case OMPD_cancellation_point:
1937 case OMPD_target_data:
1938 case OMPD_target_enter_data:
1939 case OMPD_target_exit_data:
1941 case OMPD_taskloop_simd:
1942 case OMPD_master_taskloop:
1943 case OMPD_master_taskloop_simd:
1944 case OMPD_parallel_master_taskloop:
1945 case OMPD_parallel_master_taskloop_simd:
1946 case OMPD_distribute:
1947 case OMPD_target_update:
1948 case OMPD_distribute_parallel_for_simd:
1949 case OMPD_distribute_simd:
1950 case OMPD_target_parallel_for_simd:
1951 case OMPD_target_simd:
1952 case OMPD_teams_distribute:
1953 case OMPD_teams_distribute_simd:
1954 case OMPD_teams_distribute_parallel_for_simd:
1955 case OMPD_target_teams:
1956 case OMPD_target_teams_distribute:
1957 case OMPD_target_teams_distribute_parallel_for_simd:
1958 case OMPD_target_teams_distribute_simd:
1959 case OMPD_declare_target:
1960 case OMPD_end_declare_target:
1961 case OMPD_threadprivate:
1963 case OMPD_declare_reduction:
1964 case OMPD_declare_mapper:
1965 case OMPD_declare_simd:
1967 case OMPD_declare_variant:
1968 case OMPD_begin_declare_variant:
1969 case OMPD_end_declare_variant:
1972 llvm_unreachable(
"Unexpected directive with task reductions.");
1978 false, TaskRedRef->
getType());
1991 bool HasAtLeastOneReduction =
false;
1992 bool IsReductionWithTaskMod =
false;
1993 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1995 if (
C->getModifier() == OMPC_REDUCTION_inscan)
1997 HasAtLeastOneReduction =
true;
1998 Privates.append(
C->privates().begin(),
C->privates().end());
1999 LHSExprs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
2000 RHSExprs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
2001 IsPrivateVarReduction.append(
C->private_var_reduction_flags().begin(),
2002 C->private_var_reduction_flags().end());
2003 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
2004 IsReductionWithTaskMod =
2005 IsReductionWithTaskMod ||
C->getModifier() == OMPC_REDUCTION_task;
2007 if (HasAtLeastOneReduction) {
2009 if (IsReductionWithTaskMod) {
2010 CGM.getOpenMPRuntime().emitTaskReductionFini(
2013 bool TeamsLoopCanBeParallel =
false;
2014 if (
auto *TTLD = dyn_cast<OMPTargetTeamsGenericLoopDirective>(&D))
2015 TeamsLoopCanBeParallel = TTLD->canBeParallelFor();
2016 bool WithNowait = D.getSingleClause<OMPNowaitClause>() ||
2018 TeamsLoopCanBeParallel || ReductionKind == OMPD_simd;
2019 bool SimpleReduction = ReductionKind == OMPD_simd;
2022 CGM.getOpenMPRuntime().emitReduction(
2023 *
this, D.getEndLoc(),
Privates, LHSExprs, RHSExprs, ReductionOps,
2024 {WithNowait, SimpleReduction, IsPrivateVarReduction, ReductionKind});
2033 llvm::BasicBlock *DoneBB =
nullptr;
2034 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
2035 if (
const Expr *PostUpdate =
C->getPostUpdateExpr()) {
2037 if (llvm::Value *Cond = CondGen(CGF)) {
2042 CGF.
Builder.CreateCondBr(Cond, ThenBB, DoneBB);
2058 const OMPExecutableDirective &,
2059 llvm::SmallVectorImpl<llvm::Value *> &)>
2060 CodeGenBoundParametersTy;
2068 llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> PrivateDecls;
2069 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
2070 for (
const Expr *Ref :
C->varlist()) {
2071 if (!Ref->getType()->isScalarType())
2073 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
2077 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
2080 PrivateDecls.insert(VD);
2084 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
2085 for (
const Expr *Ref :
C->varlist()) {
2086 if (!Ref->getType()->isScalarType())
2088 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
2093 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
2094 PrivateDecls.insert(VD);
2099 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
2100 for (
const Expr *Ref :
C->varlist()) {
2101 if (!Ref->getType()->isScalarType())
2103 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
2106 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
2107 PrivateDecls.insert(VD);
2116 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
2117 for (
const Expr *Ref :
C->varlist()) {
2118 if (!Ref->getType()->isScalarType())
2120 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
2124 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
2125 PrivateDecls.insert(VD);
2129 CGF, S, PrivateDecls);
2135 const CodeGenBoundParametersTy &CodeGenBoundParameters) {
2136 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
2137 llvm::Value *NumThreads =
nullptr;
2146 llvm::Function *OutlinedFn =
2153 NumThreads = CGF.
EmitScalarExpr(NumThreadsClause->getNumThreads().front(),
2155 Modifier = NumThreadsClause->getPrescriptivenessModifier();
2156 if (
const auto *MessageClause = S.getSingleClause<OMPMessageClause>()) {
2157 Message = MessageClause->getMessageString();
2158 MessageLoc = MessageClause->getBeginLoc();
2160 if (
const auto *SeverityClause = S.getSingleClause<OMPSeverityClause>()) {
2161 Severity = SeverityClause->getSeverityKind();
2162 SeverityLoc = SeverityClause->getBeginLoc();
2165 CGF, NumThreads, NumThreadsClause->getBeginLoc(), Modifier, Severity,
2166 SeverityLoc, Message, MessageLoc);
2168 if (
const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>()) {
2171 CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getBeginLoc());
2173 const Expr *IfCond =
nullptr;
2174 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
2175 if (
C->getNameModifier() == OMPD_unknown ||
2176 C->getNameModifier() == OMPD_parallel) {
2177 IfCond =
C->getCondition();
2182 OMPParallelScope
Scope(CGF, S);
2188 CodeGenBoundParameters(CGF, S, CapturedVars);
2191 CapturedVars, IfCond, NumThreads,
2192 Modifier, Severity, Message);
2197 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
2199 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
2201 return !((AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc ||
2202 AA->getAllocatorType() == OMPAllocateDeclAttr::OMPNullMemAlloc) &&
2203 !AA->getAllocator());
2218 CGF, S.getBeginLoc(), OMPD_unknown,
false,
2224 CodeGenFunction &CGF,
const VarDecl *VD) {
2226 auto &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2238 Size = CGF.
Builder.CreateNUWAdd(
2240 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
2241 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
2247 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
2248 assert(AA->getAllocator() &&
2249 "Expected allocator expression for non-default allocator.");
2253 if (Allocator->getType()->isIntegerTy())
2254 Allocator = CGF.
Builder.CreateIntToPtr(Allocator,
CGM.VoidPtrTy);
2255 else if (Allocator->getType()->isPointerTy())
2259 llvm::Value *
Addr = OMPBuilder.createOMPAlloc(
2262 llvm::CallInst *FreeCI =
2263 OMPBuilder.createOMPFree(CGF.
Builder,
Addr, Allocator);
2277 if (
CGM.getLangOpts().OpenMPUseTLS &&
2278 CGM.getContext().getTargetInfo().isTLSSupported())
2281 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2286 llvm::ConstantInt *Size =
CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy));
2288 llvm::Twine CacheName = Twine(
CGM.getMangledName(VD)).concat(Suffix);
2290 llvm::CallInst *ThreadPrivateCacheCall =
2291 OMPBuilder.createCachedThreadPrivate(CGF.
Builder,
Data, Size, CacheName);
2299 llvm::raw_svector_ostream OS(Buffer);
2300 StringRef Sep = FirstSeparator;
2301 for (StringRef Part : Parts) {
2305 return OS.str().str();
2313 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
2314 "." + RegionName +
".after");
2321 if (
Builder.saveIP().isValid())
2330 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
2331 "." + RegionName +
".after");
2338 if (
Builder.saveIP().isValid())
2343 if (
CGM.getLangOpts().OpenMPIRBuilder) {
2344 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2346 llvm::Value *IfCond =
nullptr;
2351 llvm::Value *NumThreads =
nullptr;
2353 NumThreads =
EmitScalarExpr(NumThreadsClause->getNumThreads().front(),
2356 ProcBindKind ProcBind = OMP_PROC_BIND_default;
2357 if (
const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>())
2358 ProcBind = ProcBindClause->getProcBindKind();
2360 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2364 auto FiniCB = [
this](InsertPointTy IP) {
2366 return llvm::Error::success();
2373 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
2374 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
2385 auto BodyGenCB = [&,
this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
2388 *
this, ParallelRegionBodyStmt, AllocIP, CodeGenIP,
"parallel");
2389 return llvm::Error::success();
2394 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
2396 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2397 cantFail(OMPBuilder.createParallel(
2398 Builder, AllocaIP, {}, BodyGenCB, PrivCB, FiniCB,
2399 IfCond, NumThreads, ProcBind, S.hasCancel()));
2413 CGF.
EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt());
2422 [](CodeGenFunction &) {
return nullptr; });
2435class OMPTransformDirectiveScopeRAII {
2436 OMPLoopScope *
Scope =
nullptr;
2440 OMPTransformDirectiveScopeRAII(
const OMPTransformDirectiveScopeRAII &) =
2442 OMPTransformDirectiveScopeRAII &
2443 operator=(
const OMPTransformDirectiveScopeRAII &) =
delete;
2447 if (
const auto *Dir = dyn_cast<OMPLoopBasedDirective>(S)) {
2448 Scope =
new OMPLoopScope(CGF, *Dir);
2451 }
else if (
const auto *Dir =
2452 dyn_cast<OMPCanonicalLoopSequenceTransformationDirective>(
2457 Scope =
new OMPLoopScope(CGF, *Dir);
2462 ~OMPTransformDirectiveScopeRAII() {
2473 int MaxLevel,
int Level = 0) {
2474 assert(Level < MaxLevel &&
"Too deep lookup during loop body codegen.");
2476 if (
const auto *CS = dyn_cast<CompoundStmt>(SimplifiedS)) {
2479 "LLVM IR generation of compound statement ('{}')");
2483 for (
const Stmt *CurStmt : CS->body())
2484 emitBody(CGF, CurStmt, NextLoop, MaxLevel, Level);
2491 if (SimplifiedS == OMPLoopBasedDirective::ignoreIntraTileHint(NextLoop)) {
2492 if (
auto *Dir = dyn_cast<OMPLoopTransformationDirective>(SimplifiedS))
2493 SimplifiedS = Dir->getTransformedStmt();
2494 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(SimplifiedS))
2495 SimplifiedS = CanonLoop->getLoopStmt();
2496 if (
const auto *For = dyn_cast<ForStmt>(SimplifiedS)) {
2500 "Expected canonical for loop or range-based for loop.");
2502 CGF.
EmitStmt(CXXFor->getLoopVarStmt());
2503 S = CXXFor->getBody();
2505 if (Level + 1 < MaxLevel) {
2506 NextLoop = OMPLoopDirective::tryToFindNextInnerLoop(
2508 emitBody(CGF, S, NextLoop, MaxLevel, Level + 1);
2526 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2527 for (
const Expr *UE :
C->updates())
2534 BreakContinueStack.push_back(BreakContinue(D,
LoopExit, Continue));
2548 bool IsInscanRegion = InscanScope.
Privatize();
2549 if (IsInscanRegion) {
2559 if (EKind != OMPD_simd && !
getLangOpts().OpenMPSimd)
2568 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
2571 OMPLoopBasedDirective::tryToFindNextInnerLoop(
2573 D.getLoopsNumber());
2581 BreakContinueStack.pop_back();
2592 std::unique_ptr<CodeGenFunction::CGCapturedStmtInfo> CSI =
2593 std::make_unique<CodeGenFunction::CGCapturedStmtInfo>(*S);
2597 return {F, CapStruct.getPointer(
ParentCGF)};
2601static llvm::CallInst *
2606 EffectiveArgs.reserve(Args.size() + 1);
2607 llvm::append_range(EffectiveArgs, Args);
2608 EffectiveArgs.push_back(Cap.second);
2613llvm::CanonicalLoopInfo *
2615 assert(Depth == 1 &&
"Nested loops with OpenMPIRBuilder not yet implemented");
2641 const Stmt *SyntacticalLoop = S->getLoopStmt();
2652 const Stmt *BodyStmt;
2653 if (
const auto *For = dyn_cast<ForStmt>(SyntacticalLoop)) {
2654 if (
const Stmt *InitStmt = For->getInit())
2656 BodyStmt = For->getBody();
2657 }
else if (
const auto *RangeFor =
2658 dyn_cast<CXXForRangeStmt>(SyntacticalLoop)) {
2659 if (
const DeclStmt *RangeStmt = RangeFor->getRangeStmt())
2661 if (
const DeclStmt *BeginStmt = RangeFor->getBeginStmt())
2663 if (
const DeclStmt *EndStmt = RangeFor->getEndStmt())
2665 if (
const DeclStmt *LoopVarStmt = RangeFor->getLoopVarStmt())
2667 BodyStmt = RangeFor->getBody();
2669 llvm_unreachable(
"Expected for-stmt or range-based for-stmt");
2672 const CapturedStmt *DistanceFunc = S->getDistanceFunc();
2685 llvm::Value *DistVal =
Builder.CreateLoad(CountAddr,
".count");
2688 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2689 auto BodyGen = [&,
this](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP,
2690 llvm::Value *IndVar) {
2695 const DeclRefExpr *LoopVarRef = S->getLoopVarRef();
2703 return llvm::Error::success();
2706 llvm::CanonicalLoopInfo *
CL =
2707 cantFail(OMPBuilder.createCanonicalLoop(
Builder, BodyGen, DistVal));
2719 const Expr *IncExpr,
2720 const llvm::function_ref<
void(CodeGenFunction &)> BodyGen,
2721 const llvm::function_ref<
void(CodeGenFunction &)> PostIncGen) {
2731 const CapturedStmt *ICS = OMPED.getInnermostCapturedStmt();
2745 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
2746 if (RequiresCleanup)
2753 if (ExitBlock !=
LoopExit.getBlock()) {
2763 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
2771 BreakContinueStack.pop_back();
2782 bool HasLinears =
false;
2783 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2787 if (
const auto *Ref =
2810 if (
const auto *CS = cast_or_null<BinaryOperator>(
C->getCalcStep()))
2822 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2825 llvm::BasicBlock *DoneBB =
nullptr;
2827 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2828 auto IC =
C->varlist_begin();
2829 for (
const Expr *F :
C->finals()) {
2831 if (llvm::Value *Cond = CondGen(*
this)) {
2836 Builder.CreateCondBr(Cond, ThenBB, DoneBB);
2842 if (
const auto *BD = dyn_cast<BindingDecl>(OrigDecl)) {
2848 (*IC)->getType(),
VK_LValue, (*IC)->getExprLoc());
2857 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
2869 llvm::APInt ClauseAlignment(64, 0);
2870 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
2873 ClauseAlignment = AlignmentCI->getValue();
2875 for (
const Expr *E : Clause->varlist()) {
2876 llvm::APInt Alignment(ClauseAlignment);
2877 if (Alignment == 0) {
2884 E->getType()->getPointeeType()))
2887 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2888 "alignment is not power of 2");
2889 if (Alignment != 0) {
2910 LocalDeclMap.erase(PrivateVD);
2916 E->getType(),
VK_LValue, E->getExprLoc());
2924 for (
const auto *
C : S.getClausesOfKind<OMPOrderedClause>()) {
2925 if (!
C->getNumForLoops())
2927 for (
unsigned I = S.getLoopsNumber(), E =
C->getLoopNumIterations().size();
2933 if (DRE->refersToEnclosingVariableOrCapture()) {
2942 const Expr *Cond, llvm::BasicBlock *TrueBlock,
2943 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
2961 assert(!E->getType().getNonReferenceType()->isRecordType() &&
2962 "dependent counter must not be an iterator.");
2966 (void)PreCondVars.
setVarAddr(CGF, VD, CounterAddr);
2968 (void)PreCondVars.
apply(CGF);
2983 llvm::DenseSet<const VarDecl *> SIMDLCVs;
2987 for (
const Expr *
C : LoopDirective->counters()) {
2992 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2993 auto CurPrivate =
C->privates().begin();
2994 for (
const Expr *E :
C->varlist()) {
2996 const auto *PrivateVD =
2998 bool IsSIMDLCV =
false;
2999 if (
const auto *VarD = dyn_cast<VarDecl>(VD))
3000 IsSIMDLCV = SIMDLCVs.count(VarD->getCanonicalDecl());
3005 bool IsRegistered = PrivateScope.
addPrivate(VD, PrivateAddr);
3006 assert(IsRegistered &&
"linear var already registered as private");
3094 if (
const auto *CS = dyn_cast<CapturedStmt>(S))
3112 if (HasOrderedDirective)
3120 const Stmt *AssociatedStmt = D.getAssociatedStmt();
3124 if (
C->getKind() == OMPC_ORDER_concurrent)
3127 if ((EKind == OMPD_simd ||
3129 llvm::any_of(D.getClausesOfKind<OMPReductionClause>(),
3130 [](
const OMPReductionClause *
C) {
3131 return C->getModifier() == OMPC_REDUCTION_inscan;
3139 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
3142 llvm::BasicBlock *DoneBB =
nullptr;
3148 const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
3150 OrigVD->hasGlobalStorage() || CED) {
3152 if (llvm::Value *Cond = CondGen(*
this)) {
3157 Builder.CreateCondBr(Cond, ThenBB, DoneBB);
3200 auto &&ThenGen = [&S, &SimdInitGen, &BodyCodeGen](
CodeGenFunction &CGF,
3214 const Expr *IfCond =
nullptr;
3216 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
3218 (
C->getNameModifier() == OMPD_unknown ||
3219 C->getNameModifier() == OMPD_simd)) {
3220 IfCond =
C->getCondition();
3236 OMPLoopScope PreInitScope(CGF, S);
3258 llvm::BasicBlock *ContBlock =
nullptr;
3310 emitOMPLoopBodyWithStopPoint(CGF, S,
3311 CodeGenFunction::JumpDest());
3317 if (HasLastprivateClause)
3346 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(S.getRawStmt())) {
3347 if (
const Stmt *SyntacticalLoop = CanonLoop->getLoopStmt()) {
3348 for (
const Stmt *SubStmt : SyntacticalLoop->
children()) {
3351 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(SubStmt)) {
3366static llvm::MapVector<llvm::Value *, llvm::Value *>
3368 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars;
3370 llvm::APInt ClauseAlignment(64, 0);
3371 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
3374 ClauseAlignment = AlignmentCI->getValue();
3376 for (
const Expr *E : Clause->varlist()) {
3377 llvm::APInt Alignment(ClauseAlignment);
3378 if (Alignment == 0) {
3385 E->getType()->getPointeeType()))
3388 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
3389 "alignment is not power of 2");
3391 AlignedVars[PtrValue] = CGF.
Builder.getInt64(Alignment.getSExtValue());
3401 bool UseOMPIRBuilder =
3403 if (UseOMPIRBuilder) {
3407 if (UseOMPIRBuilder) {
3408 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars =
3411 const Stmt *Inner = S.getRawStmt();
3412 llvm::CanonicalLoopInfo *CLI =
3413 CGF.EmitOMPCollapsedCanonicalLoopNest(Inner, 1);
3415 llvm::OpenMPIRBuilder &OMPBuilder =
3418 llvm::ConstantInt *Simdlen =
nullptr;
3425 llvm::ConstantInt *Safelen =
nullptr;
3432 llvm::omp::OrderKind Order = llvm::omp::OrderKind::OMP_ORDER_unknown;
3434 if (
C->getKind() == OpenMPOrderClauseKind::OMPC_ORDER_concurrent) {
3435 Order = llvm::omp::OrderKind::OMP_ORDER_concurrent;
3440 OMPBuilder.applySimd(CLI, AlignedVars,
3441 nullptr, Order, Simdlen, Safelen);
3448 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
3463 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
3479 OMPTransformDirectiveScopeRAII
Scope(CGF, &S);
3508 OMPTransformDirectiveScopeRAII FlattenScope(*
this, &S);
3515 OMPTransformDirectiveScopeRAII FuseScope(*
this, &S);
3523 bool UseOMPIRBuilder =
CGM.getLangOpts().OpenMPIRBuilder;
3525 if (UseOMPIRBuilder) {
3527 const Stmt *Inner = S.getRawStmt();
3535 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
3538 llvm::CanonicalLoopInfo *UnrolledCLI =
nullptr;
3542 OMPBuilder.unrollLoopFull(DL, CLI);
3544 uint64_t Factor = 0;
3545 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3547 FactorExpr->EvaluateKnownConstInt(
getContext()).getLimitedValue();
3548 assert(Factor >= 1 &&
"Only positive factors are valid");
3550 OMPBuilder.unrollLoopPartial(DL, CLI, Factor,
3551 NeedsUnrolledCLI ? &UnrolledCLI :
nullptr);
3553 OMPBuilder.unrollLoopHeuristic(DL, CLI);
3556 assert((!NeedsUnrolledCLI || UnrolledCLI) &&
3557 "NeedsUnrolledCLI implies UnrolledCLI to be set");
3574 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3576 FactorExpr->EvaluateKnownConstInt(
getContext()).getLimitedValue();
3577 assert(Factor >= 1 &&
"Only positive factors are valid");
3585void CodeGenFunction::EmitOMPOuterLoop(
3588 const CodeGenFunction::OMPLoopArguments &LoopArgs,
3607 llvm::Value *BoolCondVal =
nullptr;
3608 if (!DynamicOrOrdered) {
3619 RT.
emitForNext(*
this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL,
3620 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST);
3625 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
3630 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
3631 if (ExitBlock !=
LoopExit.getBlock()) {
3639 if (DynamicOrOrdered)
3644 BreakContinueStack.push_back(BreakContinue(S, LoopExit, Continue));
3649 [&S, IsMonotonic, EKind](CodeGenFunction &CGF, PrePostActionTy &) {
3654 if (
const auto *
C = S.getSingleClause<OMPOrderClause>())
3655 if (
C->getKind() == OMPC_ORDER_concurrent)
3661 [&S, &LoopArgs, LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered,
3662 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
3663 SourceLocation Loc = S.getBeginLoc();
3669 CGF.EmitOMPInnerLoop(
3671 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
3672 CodeGenLoop(CGF, S, LoopExit);
3674 [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) {
3675 CodeGenOrdered(CGF, Loc, IVSize, IVSigned);
3680 BreakContinueStack.pop_back();
3681 if (!DynamicOrOrdered) {
3694 auto &&CodeGen = [DynamicOrOrdered, &S, &LoopArgs](CodeGenFunction &CGF) {
3695 if (!DynamicOrOrdered)
3696 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
3699 OMPCancelStack.emitExit(*
this, EKind, CodeGen);
3702void CodeGenFunction::EmitOMPForOuterLoop(
3703 const OpenMPScheduleTy &ScheduleKind,
bool IsMonotonic,
3705 const OMPLoopArguments &LoopArgs,
3707 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3713 LoopArgs.Chunk !=
nullptr)) &&
3714 "static non-chunked schedule does not need outer loop");
3772 if (DynamicOrOrdered) {
3773 const std::pair<llvm::Value *, llvm::Value *> DispatchBounds =
3774 CGDispatchBounds(*
this, S, LoopArgs.LB, LoopArgs.UB);
3775 llvm::Value *LBVal = DispatchBounds.first;
3776 llvm::Value *UBVal = DispatchBounds.second;
3777 CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal,
3780 IVSigned, Ordered, DipatchRTInputValues);
3782 CGOpenMPRuntime::StaticRTInput StaticInit(
3783 IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
3784 LoopArgs.ST, LoopArgs.Chunk);
3790 auto &&CodeGenOrdered = [Ordered](CodeGenFunction &CGF, SourceLocation Loc,
3791 const unsigned IVSize,
3792 const bool IVSigned) {
3799 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST,
3800 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB);
3801 OuterLoopArgs.IncExpr = S.
getInc();
3802 OuterLoopArgs.Init = S.
getInit();
3803 OuterLoopArgs.Cond = S.
getCond();
3806 OuterLoopArgs.DKind = LoopArgs.DKind;
3807 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
3809 if (DynamicOrOrdered) {
3815 const unsigned IVSize,
const bool IVSigned) {}
3817void CodeGenFunction::EmitOMPDistributeOuterLoop(
3822 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3834 CGOpenMPRuntime::StaticRTInput StaticInit(
3835 IVSize, IVSigned,
false, LoopArgs.IL, LoopArgs.LB,
3836 LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
3850 OMPLoopArguments OuterLoopArgs;
3851 OuterLoopArgs.LB = LoopArgs.LB;
3852 OuterLoopArgs.UB = LoopArgs.UB;
3853 OuterLoopArgs.ST = LoopArgs.ST;
3854 OuterLoopArgs.IL = LoopArgs.IL;
3855 OuterLoopArgs.Chunk = LoopArgs.Chunk;
3859 OuterLoopArgs.IncExpr = IncExpr;
3872 OuterLoopArgs.DKind = OMPD_distribute;
3874 EmitOMPOuterLoop(
false,
false, S,
3875 LoopScope, OuterLoopArgs, CodeGenLoopContent,
3879static std::pair<LValue, LValue>
3922static std::pair<llvm::Value *, llvm::Value *>
3933 llvm::Value *LBVal =
3935 llvm::Value *UBVal =
3937 return {LBVal, UBVal};
3946 llvm::Value *LBCast = CGF.
Builder.CreateIntCast(
3948 CapturedVars.push_back(LBCast);
3952 llvm::Value *UBCast = CGF.
Builder.CreateIntCast(
3954 CapturedVars.push_back(UBCast);
3965 bool HasCancel =
false;
3967 if (
const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
3968 HasCancel = D->hasCancel();
3969 else if (
const auto *D = dyn_cast<OMPDistributeParallelForDirective>(&S))
3970 HasCancel = D->hasCancel();
3971 else if (
const auto *D =
3972 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S))
3973 HasCancel = D->hasCancel();
3983 CGInlinedWorksharingLoop,
3993 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3994 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
4003 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
4004 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
4012 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4013 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
4023 llvm::Constant *
Addr;
4025 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
4027 assert(Fn &&
Addr &&
"Target device function emission failed.");
4038struct ScheduleKindModifiersTy {
4045 : Kind(Kind), M1(M1), M2(M2) {}
4069 bool HasLastprivateClause;
4072 OMPLoopScope PreInitScope(*
this, S);
4077 llvm::BasicBlock *ContBlock =
nullptr;
4091 bool Ordered =
false;
4092 if (
const auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) {
4093 if (OrderedClause->getNumForLoops())
4103 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*
this, S);
4104 LValue LB = Bounds.first;
4105 LValue UB = Bounds.second;
4119 CGM.getOpenMPRuntime().emitBarrierCall(
4120 *
this, S.getBeginLoc(), OMPD_unknown,
false,
4132 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
4135 const Expr *ChunkExpr =
nullptr;
4137 if (
const auto *
C = S.getSingleClause<OMPScheduleClause>()) {
4138 ScheduleKind.
Schedule =
C->getScheduleKind();
4139 ScheduleKind.
M1 =
C->getFirstScheduleModifier();
4140 ScheduleKind.
M2 =
C->getSecondScheduleModifier();
4141 ChunkExpr =
C->getChunkSize();
4144 CGM.getOpenMPRuntime().getDefaultScheduleAndChunk(
4145 *
this, S, ScheduleKind.
Schedule, ChunkExpr);
4147 bool HasChunkSizeOne =
false;
4148 llvm::Value *Chunk =
nullptr;
4156 llvm::APSInt EvaluatedChunk =
Result.Val.getInt();
4157 HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
4166 bool StaticChunkedOne =
4168 Chunk !=
nullptr) &&
4180 "fused distribute schedule requires a static chunk-one schedule");
4183 (ScheduleKind.
Schedule == OMPC_SCHEDULE_static &&
4184 !(ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4185 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)) ||
4186 ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
4187 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
4189 Chunk !=
nullptr) ||
4190 StaticChunkedOne) &&
4200 if (
C->getKind() == OMPC_ORDER_concurrent)
4204 [IVSize, IVSigned, Ordered, IL, LB, UB, ST, StaticChunkedOne, Chunk,
4213 IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(),
4214 UB.getAddress(), ST.getAddress(),
4215 StaticChunkedOne ? Chunk :
nullptr);
4217 CGF, S.getBeginLoc(), EKind, ScheduleKind, StaticInit);
4219 if (!StaticChunkedOne)
4238 StaticChunkedOne ? S.getCombinedParForInDistCond()
4240 StaticChunkedOne ? S.getDistInc() : S.getInc(),
4241 [&S,
LoopExit](CodeGenFunction &CGF) {
4242 emitOMPLoopBodyWithStopPoint(CGF, S, LoopExit);
4244 [](CodeGenFunction &) {});
4248 auto &&
CodeGen = [&S](CodeGenFunction &CGF) {
4252 OMPCancelStack.emitExit(*
this, EKind,
CodeGen);
4259 LoopArguments.DKind = OMPD_for;
4260 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
4261 LoopArguments, CGDispatchBounds);
4265 return CGF.
Builder.CreateIsNotNull(
4271 ? OMPD_parallel_for_simd
4275 *
this, S, [IL, &S](CodeGenFunction &CGF) {
4276 return CGF.
Builder.CreateIsNotNull(
4280 if (HasLastprivateClause)
4286 return CGF.
Builder.CreateIsNotNull(
4297 return HasLastprivateClause;
4303static std::pair<LValue, LValue>
4317static std::pair<llvm::Value *, llvm::Value *>
4321 const Expr *IVExpr = LS.getIterationVariable();
4323 llvm::Value *LBVal = CGF.
Builder.getIntN(IVSize, 0);
4325 return {LBVal, UBVal};
4337 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
4338 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4339 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4344 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4345 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4346 "Only inscan reductions are expected.");
4347 Shareds.append(
C->varlist_begin(),
C->varlist_end());
4348 Privates.append(
C->privates().begin(),
C->privates().end());
4349 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
4350 CopyArrayTemps.append(
C->copy_array_temps().begin(),
4351 C->copy_array_temps().end());
4359 auto *ITA = CopyArrayTemps.begin();
4364 if (PrivateVD->getType()->isVariablyModifiedType()) {
4389 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
4390 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4391 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4398 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4399 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4400 "Only inscan reductions are expected.");
4401 Shareds.append(
C->varlist_begin(),
C->varlist_end());
4402 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
4403 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
4404 Privates.append(
C->privates().begin(),
C->privates().end());
4405 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
4406 CopyArrayElems.append(
C->copy_array_elems().begin(),
4407 C->copy_array_elems().end());
4411 llvm::Value *OMPLast = CGF.
Builder.CreateNSWSub(
4412 OMPScanNumIterations,
4413 llvm::ConstantInt::get(CGF.
SizeTy, 1,
false));
4414 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
4416 const Expr *OrigExpr = Shareds[I];
4417 const Expr *CopyArrayElem = CopyArrayElems[I];
4424 LValue SrcLVal = CGF.
EmitLValue(CopyArrayElem);
4426 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
4456 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4457 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4463 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4464 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4465 "Only inscan reductions are expected.");
4466 Privates.append(
C->privates().begin(),
C->privates().end());
4467 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
4468 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
4469 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
4470 CopyArrayElems.append(
C->copy_array_elems().begin(),
4471 C->copy_array_elems().end());
4486 auto &&
CodeGen = [&S, OMPScanNumIterations, &LHSs, &RHSs, &CopyArrayElems,
4493 llvm::BasicBlock *InputBB = CGF.Builder.GetInsertBlock();
4494 llvm::BasicBlock *LoopBB = CGF.createBasicBlock(
"omp.outer.log.scan.body");
4495 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
"omp.outer.log.scan.exit");
4497 CGF.CGM.getIntrinsic(llvm::Intrinsic::log2, CGF.DoubleTy);
4499 CGF.Builder.CreateUIToFP(OMPScanNumIterations, CGF.DoubleTy);
4500 llvm::Value *LogVal = CGF.EmitNounwindRuntimeCall(F, Arg);
4501 F = CGF.CGM.getIntrinsic(llvm::Intrinsic::ceil, CGF.DoubleTy);
4502 LogVal = CGF.EmitNounwindRuntimeCall(F, LogVal);
4503 LogVal = CGF.Builder.CreateFPToUI(LogVal, CGF.IntTy);
4504 llvm::Value *NMin1 = CGF.Builder.CreateNUWSub(
4505 OMPScanNumIterations, llvm::ConstantInt::get(CGF.SizeTy, 1));
4507 CGF.EmitBlock(LoopBB);
4508 auto *Counter = CGF.Builder.CreatePHI(CGF.IntTy, 2);
4510 auto *Pow2K = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
4511 Counter->addIncoming(llvm::ConstantInt::get(CGF.IntTy, 0), InputBB);
4512 Pow2K->addIncoming(llvm::ConstantInt::get(CGF.SizeTy, 1), InputBB);
4515 llvm::BasicBlock *InnerLoopBB =
4516 CGF.createBasicBlock(
"omp.inner.log.scan.body");
4517 llvm::BasicBlock *InnerExitBB =
4518 CGF.createBasicBlock(
"omp.inner.log.scan.exit");
4519 llvm::Value *CmpI = CGF.Builder.CreateICmpUGE(NMin1, Pow2K);
4520 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4521 CGF.EmitBlock(InnerLoopBB);
4522 auto *IVal = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
4523 IVal->addIncoming(NMin1, LoopBB);
4526 auto *ILHS = LHSs.begin();
4527 auto *IRHS = RHSs.begin();
4528 for (
const Expr *CopyArrayElem : CopyArrayElems) {
4538 LHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4543 llvm::Value *OffsetIVal = CGF.Builder.CreateNUWSub(IVal, Pow2K);
4549 RHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4556 CGF.CGM.getOpenMPRuntime().emitReduction(
4557 CGF, S.getEndLoc(),
Privates, LHSs, RHSs, ReductionOps,
4561 llvm::Value *NextIVal =
4562 CGF.Builder.CreateNUWSub(IVal, llvm::ConstantInt::get(CGF.SizeTy, 1));
4563 IVal->addIncoming(NextIVal, CGF.Builder.GetInsertBlock());
4564 CmpI = CGF.Builder.CreateICmpUGE(NextIVal, Pow2K);
4565 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4566 CGF.EmitBlock(InnerExitBB);
4568 CGF.Builder.CreateNUWAdd(Counter, llvm::ConstantInt::get(CGF.IntTy, 1));
4569 Counter->addIncoming(
Next, CGF.Builder.GetInsertBlock());
4571 llvm::Value *NextPow2K =
4572 CGF.Builder.CreateShl(Pow2K, 1,
"",
true);
4573 Pow2K->addIncoming(NextPow2K, CGF.Builder.GetInsertBlock());
4574 llvm::Value *
Cmp = CGF.Builder.CreateICmpNE(
Next, LogVal);
4575 CGF.Builder.CreateCondBr(
Cmp, LoopBB, ExitBB);
4577 CGF.EmitBlock(ExitBB);
4583 CGF, S.getBeginLoc(), OMPD_unknown,
false,
4586 RegionCodeGenTy RCG(CodeGen);
4597 bool HasLastprivates;
4599 if (llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4600 [](
const OMPReductionClause *
C) {
4601 return C->getModifier() == OMPC_REDUCTION_inscan;
4605 OMPLoopScope LoopScope(CGF, S);
4608 const auto &&FirstGen = [&S, HasCancel, EKind](
CodeGenFunction &CGF) {
4617 const auto &&SecondGen = [&S, HasCancel, EKind,
4635 return HasLastprivates;
4648 if (
auto *SC = dyn_cast<OMPScheduleClause>(
C)) {
4653 switch (SC->getScheduleKind()) {
4654 case OMPC_SCHEDULE_auto:
4655 case OMPC_SCHEDULE_dynamic:
4656 case OMPC_SCHEDULE_runtime:
4657 case OMPC_SCHEDULE_guided:
4658 case OMPC_SCHEDULE_static:
4671static llvm::omp::ScheduleKind
4673 switch (ScheduleClauseKind) {
4675 return llvm::omp::OMP_SCHEDULE_Default;
4676 case OMPC_SCHEDULE_auto:
4677 return llvm::omp::OMP_SCHEDULE_Auto;
4678 case OMPC_SCHEDULE_dynamic:
4679 return llvm::omp::OMP_SCHEDULE_Dynamic;
4680 case OMPC_SCHEDULE_guided:
4681 return llvm::omp::OMP_SCHEDULE_Guided;
4682 case OMPC_SCHEDULE_runtime:
4683 return llvm::omp::OMP_SCHEDULE_Runtime;
4684 case OMPC_SCHEDULE_static:
4685 return llvm::omp::OMP_SCHEDULE_Static;
4687 llvm_unreachable(
"Unhandled schedule kind");
4694 bool HasLastprivates =
false;
4697 auto &&
CodeGen = [&S, &
CGM, HasCancel, &HasLastprivates,
4700 if (UseOMPIRBuilder) {
4701 bool NeedsBarrier = !S.getSingleClause<OMPNowaitClause>();
4703 llvm::omp::ScheduleKind SchedKind = llvm::omp::OMP_SCHEDULE_Default;
4704 llvm::Value *ChunkSize =
nullptr;
4705 if (
auto *SchedClause = S.getSingleClause<OMPScheduleClause>()) {
4708 if (
const Expr *ChunkSizeExpr = SchedClause->getChunkSize())
4713 const Stmt *Inner = S.getRawStmt();
4714 llvm::CanonicalLoopInfo *CLI =
4717 llvm::OpenMPIRBuilder &OMPBuilder =
4719 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4721 cantFail(OMPBuilder.applyWorkshareLoop(
4722 CGF.
Builder.getCurrentDebugLocation(), CLI, AllocaIP, NeedsBarrier,
4723 SchedKind, ChunkSize,
false,
4734 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
4739 if (!UseOMPIRBuilder) {
4741 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4753 bool HasLastprivates =
false;
4754 auto &&
CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
4761 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4762 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
4766 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4767 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_for);
4774 llvm::Value *
Init =
nullptr) {
4781void CodeGenFunction::EmitSections(
const OMPExecutableDirective &S) {
4782 const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4783 const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt);
4784 bool HasLastprivates =
false;
4786 auto &&CodeGen = [&S, CapturedStmt, CS, EKind,
4787 &HasLastprivates](CodeGenFunction &CGF, PrePostActionTy &) {
4788 const ASTContext &
C = CGF.getContext();
4789 QualType KmpInt32Ty =
4790 C.getIntTypeForBitwidth(32, 1);
4793 CGF.Builder.getInt32(0));
4794 llvm::ConstantInt *GlobalUBVal = CS !=
nullptr
4795 ? CGF.Builder.getInt32(CS->size() - 1)
4796 : CGF.Builder.getInt32(0);
4800 CGF.Builder.getInt32(1));
4802 CGF.Builder.getInt32(0));
4805 OpaqueValueExpr IVRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4806 CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
4807 OpaqueValueExpr UBRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4808 CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
4812 S.getBeginLoc(), FPOptionsOverride());
4816 S.getBeginLoc(),
true, FPOptionsOverride());
4817 auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
4829 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".omp.sections.exit");
4830 llvm::SwitchInst *SwitchStmt =
4831 CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.
getBeginLoc()),
4832 ExitBB, CS ==
nullptr ? 1 : CS->size());
4834 unsigned CaseNumber = 0;
4835 for (
const Stmt *SubStmt : CS->
children()) {
4836 auto CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4837 CGF.EmitBlock(CaseBB);
4838 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
4839 CGF.EmitStmt(SubStmt);
4840 CGF.EmitBranch(ExitBB);
4844 llvm::BasicBlock *CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4845 CGF.EmitBlock(CaseBB);
4846 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
4847 CGF.EmitStmt(CapturedStmt);
4848 CGF.EmitBranch(ExitBB);
4850 CGF.EmitBlock(ExitBB,
true);
4853 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
4854 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
4858 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
4862 CGF.EmitOMPPrivateClause(S, LoopScope);
4863 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(CGF, S, IV);
4864 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
4865 CGF.EmitOMPReductionClauseInit(S, LoopScope);
4866 (void)LoopScope.Privatize();
4868 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
4871 OpenMPScheduleTy ScheduleKind;
4872 ScheduleKind.
Schedule = OMPC_SCHEDULE_static;
4873 CGOpenMPRuntime::StaticRTInput StaticInit(
4874 32,
true,
false, IL.getAddress(),
4875 LB.getAddress(), UB.getAddress(), ST.getAddress());
4876 CGF.CGM.getOpenMPRuntime().emitForStaticInit(CGF, S.
getBeginLoc(), EKind,
4877 ScheduleKind, StaticInit);
4879 llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.
getBeginLoc());
4880 llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
4881 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
4882 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
4884 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.
getBeginLoc()), IV);
4886 CGF.EmitOMPInnerLoop(S,
false, Cond, Inc, BodyGen,
4887 [](CodeGenFunction &) {});
4889 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
4890 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.
getEndLoc(),
4893 CGF.OMPCancelStack.emitExit(CGF, EKind, CodeGen);
4894 CGF.EmitOMPReductionClauseFinal(S, OMPD_parallel);
4897 return CGF.
Builder.CreateIsNotNull(
4902 if (HasLastprivates)
4909 bool HasCancel =
false;
4910 if (
auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
4911 HasCancel = OSD->hasCancel();
4912 else if (
auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
4913 HasCancel = OPSD->hasCancel();
4915 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_sections, CodeGen,
4920 if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) {
4938 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4943 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4944 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_scope,
CodeGen);
4947 if (!S.getSingleClause<OMPNowaitClause>()) {
4948 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_scope);
4955 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4956 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4957 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4958 using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
4960 auto FiniCB = [](InsertPointTy IP) {
4963 return llvm::Error::success();
4966 const CapturedStmt *ICS = S.getInnermostCapturedStmt();
4967 const Stmt *
CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4972 auto SectionCB = [
this, SubStmt](
4973 InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4976 CodeGenIP,
"section");
4977 return llvm::Error::success();
4979 SectionCBVector.push_back(SectionCB);
4983 [
this,
CapturedStmt](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4987 return llvm::Error::success();
4989 SectionCBVector.push_back(SectionCB);
4996 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
4997 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
5007 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
5009 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5010 cantFail(OMPBuilder.createSections(
5012 S.getSingleClause<OMPNowaitClause>()));
5019 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
5023 if (!S.getSingleClause<OMPNowaitClause>()) {
5024 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(),
5032 if (
CGM.getLangOpts().OpenMPIRBuilder) {
5033 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
5034 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5036 const Stmt *SectionRegionBodyStmt = S.getAssociatedStmt();
5037 auto FiniCB = [
this](InsertPointTy IP) {
5039 return llvm::Error::success();
5042 auto BodyGenCB = [SectionRegionBodyStmt,
5043 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
5046 *
this, SectionRegionBodyStmt, AllocIP, CodeGenIP,
"section");
5047 return llvm::Error::success();
5052 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5053 cantFail(OMPBuilder.createSection(
Builder, BodyGenCB, FiniCB));
5073 CopyprivateVars.append(
C->varlist_begin(),
C->varlist_end());
5074 DestExprs.append(
C->destination_exprs().begin(),
5075 C->destination_exprs().end());
5076 SrcExprs.append(
C->source_exprs().begin(),
C->source_exprs().end());
5077 AssignmentOps.append(
C->assignment_ops().begin(),
5078 C->assignment_ops().end());
5087 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5092 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
5093 CGM.getOpenMPRuntime().emitSingleRegion(*
this,
CodeGen, S.getBeginLoc(),
5094 CopyprivateVars, DestExprs,
5095 SrcExprs, AssignmentOps);
5099 if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) {
5100 CGM.getOpenMPRuntime().emitBarrierCall(
5101 *
this, S.getBeginLoc(),
5102 S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);
5117 if (
CGM.getLangOpts().OpenMPIRBuilder) {
5118 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
5119 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5121 const Stmt *MasterRegionBodyStmt = S.getAssociatedStmt();
5123 auto FiniCB = [
this](InsertPointTy IP) {
5125 return llvm::Error::success();
5128 auto BodyGenCB = [MasterRegionBodyStmt,
5129 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
5132 *
this, MasterRegionBodyStmt, AllocIP, CodeGenIP,
"master");
5133 return llvm::Error::success();
5138 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5139 cantFail(OMPBuilder.createMaster(
Builder, BodyGenCB, FiniCB));
5154 Expr *Filter =
nullptr;
5156 Filter = FilterClause->getThreadID();
5162 if (
CGM.getLangOpts().OpenMPIRBuilder) {
5163 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
5164 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5166 const Stmt *MaskedRegionBodyStmt = S.getAssociatedStmt();
5167 const Expr *Filter =
nullptr;
5169 Filter = FilterClause->getThreadID();
5170 llvm::Value *FilterVal = Filter
5172 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
5174 auto FiniCB = [
this](InsertPointTy IP) {
5176 return llvm::Error::success();
5179 auto BodyGenCB = [MaskedRegionBodyStmt,
5180 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
5183 *
this, MaskedRegionBodyStmt, AllocIP, CodeGenIP,
"masked");
5184 return llvm::Error::success();
5189 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
5190 OMPBuilder.createMasked(
Builder, BodyGenCB, FiniCB, FilterVal));
5201 if (
CGM.getLangOpts().OpenMPIRBuilder) {
5202 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
5203 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5205 const Stmt *CriticalRegionBodyStmt = S.getAssociatedStmt();
5206 const Expr *Hint =
nullptr;
5207 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
5208 Hint = HintClause->getHint();
5213 llvm::Value *HintInst =
nullptr;
5218 auto FiniCB = [
this](InsertPointTy IP) {
5220 return llvm::Error::success();
5223 auto BodyGenCB = [CriticalRegionBodyStmt,
5224 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
5227 *
this, CriticalRegionBodyStmt, AllocIP, CodeGenIP,
"critical");
5228 return llvm::Error::success();
5233 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5234 cantFail(OMPBuilder.createCritical(
Builder, BodyGenCB, FiniCB,
5244 CGF.
EmitStmt(S.getAssociatedStmt());
5246 const Expr *Hint =
nullptr;
5247 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
5248 Hint = HintClause->getHint();
5251 CGM.getOpenMPRuntime().emitCriticalRegion(*
this,
5253 CodeGen, S.getBeginLoc(), Hint);
5266 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
5270 OMPLoopScope LoopScope(CGF, S);
5273 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
5274 [](
const OMPReductionClause *
C) {
5275 return C->getModifier() == OMPC_REDUCTION_inscan;
5300 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
5304 OMPLoopScope LoopScope(CGF, S);
5307 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
5308 [](
const OMPReductionClause *
C) {
5309 return C->getModifier() == OMPC_REDUCTION_inscan;
5345 [](CodeGenFunction &) {
return nullptr; });
5372 [](CodeGenFunction &) {
return nullptr; });
5385 CGF.EmitSections(S);
5399class CheckVarsEscapingUntiedTaskDeclContext final
5404 explicit CheckVarsEscapingUntiedTaskDeclContext() =
default;
5405 ~CheckVarsEscapingUntiedTaskDeclContext() =
default;
5406 void VisitDeclStmt(
const DeclStmt *S) {
5411 if (
const auto *VD = dyn_cast_or_null<VarDecl>(D))
5413 PrivateDecls.push_back(VD);
5417 void VisitCapturedStmt(
const CapturedStmt *) {}
5419 void VisitBlockExpr(
const BlockExpr *) {}
5420 void VisitStmt(
const Stmt *S) {
5423 for (
const Stmt *Child : S->
children())
5429 ArrayRef<const VarDecl *> getPrivateDecls()
const {
return PrivateDecls; }
5437 bool OmpAllMemory =
false;
5440 return C->getDependencyKind() == OMPC_DEPEND_outallmemory ||
5441 C->getDependencyKind() == OMPC_DEPEND_inoutallmemory;
5443 OmpAllMemory =
true;
5448 Data.Dependences.emplace_back(OMPC_DEPEND_outallmemory,
5457 if (Kind == OMPC_DEPEND_outallmemory || Kind == OMPC_DEPEND_inoutallmemory)
5459 if (OmpAllMemory && (Kind == OMPC_DEPEND_out || Kind == OMPC_DEPEND_inout))
5462 Data.Dependences.emplace_back(
C->getDependencyKind(),
C->getModifier());
5463 DD.
DepExprs.append(
C->varlist_begin(),
C->varlist_end());
5472 const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion);
5474 auto PartId = std::next(I);
5475 auto TaskT = std::next(I, 4);
5480 const Expr *Cond = Clause->getCondition();
5483 Data.Final.setInt(CondConstant);
5488 Data.Final.setInt(
false);
5492 const Expr *Prio = Clause->getPriority();
5493 Data.Priority.setInt(
true);
5501 llvm::DenseSet<const ValueDecl *> EmittedAsPrivate;
5503 for (
const auto *
C : S.getClausesOfKind<OMPPrivateClause>()) {
5504 auto IRef =
C->varlist_begin();
5505 for (
const Expr *IInit :
C->private_copies()) {
5507 if (EmittedAsPrivate.insert(
cast<ValueDecl>(OrigDecl->getCanonicalDecl()))
5509 Data.PrivateVars.push_back(*IRef);
5510 Data.PrivateCopies.push_back(IInit);
5515 EmittedAsPrivate.clear();
5517 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5518 auto IRef =
C->varlist_begin();
5519 auto IElemInitRef =
C->inits().begin();
5520 for (
const Expr *IInit :
C->private_copies()) {
5522 if (EmittedAsPrivate.insert(
cast<ValueDecl>(OrigDecl->getCanonicalDecl()))
5524 Data.FirstprivateVars.push_back(*IRef);
5525 Data.FirstprivateCopies.push_back(IInit);
5526 Data.FirstprivateInits.push_back(*IElemInitRef);
5533 llvm::MapVector<const ValueDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
5534 llvm::MapVector<const ValueDecl *, const DeclRefExpr *> LastprivateSrcsOrigs;
5535 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
5536 auto IRef =
C->varlist_begin();
5537 auto ID =
C->destination_exprs().begin();
5538 auto IS =
C->source_exprs().begin();
5539 for (
const Expr *IInit :
C->private_copies()) {
5541 if (EmittedAsPrivate.insert(
cast<ValueDecl>(OrigDecl->getCanonicalDecl()))
5543 Data.LastprivateVars.push_back(*IRef);
5544 Data.LastprivateCopies.push_back(IInit);
5546 LastprivateDstsOrigs.insert(std::make_pair(
5548 LastprivateSrcsOrigs.insert(std::make_pair(
5557 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
5558 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5559 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5560 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5561 Data.ReductionOps.append(
C->reduction_ops().begin(),
5562 C->reduction_ops().end());
5563 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5564 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5566 Data.Reductions =
CGM.getOpenMPRuntime().emitTaskReductionInit(
5567 *
this, S.getBeginLoc(), LHSs, RHSs,
Data);
5572 CheckVarsEscapingUntiedTaskDeclContext Checker;
5573 Checker.Visit(S.getInnermostCapturedStmt()->getCapturedStmt());
5574 Data.PrivateLocals.append(Checker.getPrivateDecls().begin(),
5575 Checker.getPrivateDecls().end());
5577 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
5578 &LastprivateSrcsOrigs, CapturedRegion](
5580 llvm::MapVector<CanonicalDeclPtr<const VarDecl>,
5581 std::pair<Address, Address>>
5586 if (
auto *DI = CGF.getDebugInfo()) {
5587 llvm::SmallDenseMap<const VarDecl *, FieldDecl *> CaptureFields =
5588 CGF.CapturedStmtInfo->getCaptureFields();
5589 llvm::Value *ContextValue = CGF.CapturedStmtInfo->getContextValue();
5590 if (CaptureFields.size() && ContextValue) {
5591 unsigned CharWidth = CGF.getContext().getCharWidth();
5605 for (
auto It = CaptureFields.begin(); It != CaptureFields.end(); ++It) {
5606 const VarDecl *SharedVar = It->first;
5609 CGF.getContext().getASTRecordLayout(CaptureRecord);
5612 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5613 (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue,
5614 CGF.Builder,
false);
5617 auto UpdateExpr = [](llvm::LLVMContext &Ctx,
auto *
Declare,
5622 Ops.push_back(llvm::dwarf::DW_OP_plus_uconst);
5623 Ops.push_back(Offset);
5625 Ops.push_back(llvm::dwarf::DW_OP_deref);
5626 Declare->setExpression(llvm::DIExpression::get(Ctx, Ops));
5628 llvm::Instruction &
Last = CGF.Builder.GetInsertBlock()->back();
5631 assert(!
Last.isTerminator() &&
"unexpected terminator");
5633 CGF.Builder.GetInsertBlock()->getTrailingDbgRecords()) {
5634 for (llvm::DbgVariableRecord &DVR : llvm::reverse(
5635 llvm::filterDbgVars(Marker->getDbgRecordRange()))) {
5636 UpdateExpr(
Last.getContext(), &DVR, Offset);
5645 if (!
Data.PrivateVars.empty() || !
Data.FirstprivateVars.empty() ||
5646 !
Data.LastprivateVars.empty() || !
Data.PrivateLocals.empty()) {
5647 enum { PrivatesParam = 2, CopyFnParam = 3 };
5648 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5650 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5656 CallArgs.push_back(PrivatesPtr);
5657 ParamTypes.push_back(PrivatesPtr->getType());
5658 for (
const Expr *E :
Data.PrivateVars) {
5660 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5661 CGF.getContext().getPointerType(E->
getType()),
".priv.ptr.addr");
5662 PrivatePtrs.emplace_back(VD, PrivatePtr);
5664 ParamTypes.push_back(PrivatePtr.
getType());
5666 for (
const Expr *E :
Data.FirstprivateVars) {
5668 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5669 CGF.getContext().getPointerType(E->
getType()),
5670 ".firstpriv.ptr.addr");
5671 PrivatePtrs.emplace_back(VD, PrivatePtr);
5672 FirstprivatePtrs.emplace_back(VD, PrivatePtr);
5674 ParamTypes.push_back(PrivatePtr.
getType());
5676 for (
const Expr *E :
Data.LastprivateVars) {
5678 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5679 CGF.getContext().getPointerType(E->
getType()),
5680 ".lastpriv.ptr.addr");
5681 PrivatePtrs.emplace_back(VD, PrivatePtr);
5683 ParamTypes.push_back(PrivatePtr.
getType());
5688 Ty = CGF.getContext().getPointerType(Ty);
5690 Ty = CGF.getContext().getPointerType(Ty);
5691 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5692 CGF.getContext().getPointerType(Ty),
".local.ptr.addr");
5693 auto Result = UntiedLocalVars.insert(
5696 if (
Result.second ==
false)
5697 *
Result.first = std::make_pair(
5700 ParamTypes.push_back(PrivatePtr.
getType());
5702 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5704 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5705 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5706 for (
const auto &Pair : LastprivateDstsOrigs) {
5707 const auto *OrigDecl = Pair.second->getDecl();
5708 if (
const auto *BD = dyn_cast<BindingDecl>(OrigDecl)) {
5711 CGF.EmitOMPBindingOriginalAddr(BD, Pair.second->getExprLoc());
5712 Scope.addPrivate(Pair.first, OrigAddr);
5717 CGF.CapturedStmtInfo->lookup(OrigVD) !=
nullptr,
5719 Pair.second->getExprLoc());
5720 Scope.addPrivate(Pair.first, CGF.EmitLValue(&DRE).getAddress());
5723 for (
const auto &Pair : PrivatePtrs) {
5725 CGF.Builder.CreateLoad(Pair.second),
5726 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5727 CGF.getContext().getDeclAlign(Pair.first));
5728 Scope.addPrivate(Pair.first, Replacement);
5733 for (
const auto &SrcPair : LastprivateSrcsOrigs) {
5734 if (SrcPair.second->getDecl() == Pair.first) {
5735 Scope.addPrivate(SrcPair.first, Replacement);
5741 if (
auto *DI = CGF.getDebugInfo())
5742 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5744 if (
const auto *VD = dyn_cast<VarDecl>(Pair.first))
5745 (void)DI->EmitDeclareOfAutoVariable(
5746 VD, Pair.second.getBasePointer(), CGF.Builder,
5751 for (
auto &Pair : UntiedLocalVars) {
5752 QualType VDType = Pair.first->getType().getNonReferenceType();
5753 if (Pair.first->getType()->isLValueReferenceType())
5754 VDType = CGF.getContext().getPointerType(VDType);
5756 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5759 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(VDType)),
5760 CGF.getPointerAlign());
5761 Pair.second.first = Replacement;
5762 Ptr = CGF.Builder.CreateLoad(Replacement);
5763 Replacement =
Address(Ptr, CGF.ConvertTypeForMem(VDType),
5764 CGF.getContext().getDeclAlign(Pair.first));
5765 Pair.second.second = Replacement;
5767 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5768 Address Replacement(Ptr, CGF.ConvertTypeForMem(VDType),
5769 CGF.getContext().getDeclAlign(Pair.first));
5770 Pair.second.first = Replacement;
5774 if (
Data.Reductions) {
5776 for (
const auto &Pair : FirstprivatePtrs) {
5778 CGF.Builder.CreateLoad(Pair.second),
5779 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5780 CGF.getContext().getDeclAlign(Pair.first));
5781 FirstprivateScope.
addPrivate(Pair.first, Replacement);
5784 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5786 Data.ReductionCopies,
Data.ReductionOps);
5787 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
5789 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5795 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5797 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5800 CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF),
5801 CGF.getContext().VoidPtrTy,
5802 CGF.getContext().getPointerType(
5803 Data.ReductionCopies[Cnt]->getType()),
5804 Data.ReductionCopies[Cnt]->getExprLoc()),
5805 CGF.ConvertTypeForMem(
Data.ReductionCopies[Cnt]->getType()),
5806 Replacement.getAlignment());
5812 (void)
Scope.Privatize();
5817 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5818 auto IPriv =
C->privates().begin();
5819 auto IRed =
C->reduction_ops().begin();
5820 auto ITD =
C->taskgroup_descriptors().begin();
5821 for (
const Expr *Ref :
C->varlist()) {
5822 InRedVars.emplace_back(Ref);
5823 InRedPrivs.emplace_back(*IPriv);
5824 InRedOps.emplace_back(*IRed);
5825 TaskgroupDescriptors.emplace_back(*ITD);
5826 std::advance(IPriv, 1);
5827 std::advance(IRed, 1);
5828 std::advance(ITD, 1);
5834 if (!InRedVars.empty()) {
5836 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5844 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5846 llvm::Value *ReductionsPtr;
5847 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5848 ReductionsPtr = CGF.EmitLoadOfScalar(CGF.EmitLValue(TRExpr),
5849 TRExpr->getExprLoc());
5851 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5853 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5856 CGF.EmitScalarConversion(
5857 Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy,
5858 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
5859 InRedPrivs[Cnt]->getExprLoc()),
5860 CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()),
5861 Replacement.getAlignment());
5874 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5875 S, *I, *PartId, *TaskT, EKind,
CodeGen,
Data.Tied,
Data.NumberOfParts);
5876 OMPLexicalScope
Scope(*
this, S, std::nullopt,
5879 TaskGen(*
this, OutlinedFn,
Data);
5896 QualType ElemType =
C.getBaseElementType(Ty);
5906 Data.FirstprivateVars.emplace_back(OrigRef);
5907 Data.FirstprivateCopies.emplace_back(PrivateRef);
5908 Data.FirstprivateInits.emplace_back(InitRef);
5921 auto PartId = std::next(I);
5922 auto TaskT = std::next(I, 4);
5925 Data.Final.setInt(
false);
5927 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5928 auto IRef =
C->varlist_begin();
5929 auto IElemInitRef =
C->inits().begin();
5930 for (
auto *IInit :
C->private_copies()) {
5931 Data.FirstprivateVars.push_back(*IRef);
5932 Data.FirstprivateCopies.push_back(IInit);
5933 Data.FirstprivateInits.push_back(*IElemInitRef);
5940 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5941 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5942 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5943 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5944 Data.ReductionOps.append(
C->reduction_ops().begin(),
5945 C->reduction_ops().end());
5946 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5947 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5962 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5964 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5976 if (!isa_and_nonnull<llvm::ConstantPointerNull>(
5979 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5986 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, BPVD, PVD, SVD, MVD, EKind,
5990 if (!
Data.FirstprivateVars.empty()) {
5991 enum { PrivatesParam = 2, CopyFnParam = 3 };
5992 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5994 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
6000 CallArgs.push_back(PrivatesPtr);
6001 ParamTypes.push_back(PrivatesPtr->getType());
6002 for (
const Expr *E :
Data.FirstprivateVars) {
6004 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
6005 CGF.getContext().getPointerType(E->
getType()),
6006 ".firstpriv.ptr.addr");
6007 PrivatePtrs.emplace_back(VD, PrivatePtr);
6009 ParamTypes.push_back(PrivatePtr.
getType());
6011 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
6013 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
6014 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
6015 for (
const auto &Pair : PrivatePtrs) {
6017 CGF.Builder.CreateLoad(Pair.second),
6018 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
6019 CGF.getContext().getDeclAlign(Pair.first));
6020 Scope.addPrivate(Pair.first, Replacement);
6023 CGF.processInReduction(S,
Data, CGF, CS,
Scope);
6026 CGF.GetAddrOfLocalVar(BPVD), 0);
6028 CGF.GetAddrOfLocalVar(PVD), 0);
6029 InputInfo.
SizesArray = CGF.Builder.CreateConstArrayGEP(
6030 CGF.GetAddrOfLocalVar(SVD), 0);
6033 InputInfo.
MappersArray = CGF.Builder.CreateConstArrayGEP(
6034 CGF.GetAddrOfLocalVar(MVD), 0);
6038 OMPLexicalScope LexScope(CGF, S, OMPD_task,
false);
6040 if (CGF.CGM.getLangOpts().OpenMP >= 51 &&
6045 CGF.CGM.getOpenMPRuntime().emitThreadLimitClause(
6046 CGF, TL->getThreadLimit().front(), S.getBeginLoc());
6050 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
6051 S, *I, *PartId, *TaskT, EKind,
CodeGen,
true,
6052 Data.NumberOfParts);
6053 llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<OMPNowaitClause>() ? 1 : 0);
6057 CGM.getOpenMPRuntime().emitTaskCall(*
this, S.getBeginLoc(), S, OutlinedFn,
6058 SharedsTy, CapturedStruct, &IfCond,
Data);
6063 CodeGenFunction &CGF,
6067 if (
Data.Reductions) {
6069 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
6071 Data.ReductionCopies,
Data.ReductionOps);
6074 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
6088 Data.ReductionCopies[Cnt]->getType()),
6089 Data.ReductionCopies[Cnt]->getExprLoc()),
6091 Replacement.getAlignment());
6096 (void)
Scope.Privatize();
6101 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
6102 auto IPriv =
C->privates().begin();
6103 auto IRed =
C->reduction_ops().begin();
6104 auto ITD =
C->taskgroup_descriptors().begin();
6105 for (
const Expr *Ref :
C->varlist()) {
6106 InRedVars.emplace_back(Ref);
6107 InRedPrivs.emplace_back(*IPriv);
6108 InRedOps.emplace_back(*IRed);
6109 TaskgroupDescriptors.emplace_back(*ITD);
6110 std::advance(IPriv, 1);
6111 std::advance(IRed, 1);
6112 std::advance(ITD, 1);
6116 if (!InRedVars.empty()) {
6118 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
6126 llvm::Value *ReductionsPtr;
6127 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
6131 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6139 InRedPrivs[Cnt]->getExprLoc()),
6141 Replacement.getAlignment());
6155 const Expr *IfCond =
nullptr;
6156 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
6157 if (
C->getNameModifier() == OMPD_unknown ||
6158 C->getNameModifier() == OMPD_task) {
6159 IfCond =
C->getCondition();
6166 Data.Tied = !S.getSingleClause<OMPUntiedClause>();
6170 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
6171 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
6174 SharedsTy, CapturedStruct, IfCond,
6184 CGM.getOpenMPRuntime().emitTaskyieldCall(*
this, S.getBeginLoc());
6188 const OMPMessageClause *MC = S.getSingleClause<OMPMessageClause>();
6189 Expr *ME = MC ? MC->getMessageString() :
nullptr;
6190 const OMPSeverityClause *SC = S.getSingleClause<OMPSeverityClause>();
6191 bool IsFatal =
false;
6192 if (!SC || SC->getSeverityKind() == OMPC_SEVERITY_fatal)
6194 CGM.getOpenMPRuntime().emitErrorCall(*
this, S.getBeginLoc(), ME, IsFatal);
6198 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_barrier);
6205 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
6206 CGM.getOpenMPRuntime().emitTaskwaitCall(*
this, S.getBeginLoc(),
Data);
6210 return T.clauses().empty();
6215 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6217 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
6218 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6221 auto BodyGenCB = [&,
this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
6224 EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
6225 return llvm::Error::success();
6230 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
6231 cantFail(OMPBuilder.createTaskgroup(
Builder, AllocaIP,
6242 for (
const auto *
C : S.getClausesOfKind<OMPTaskReductionClause>()) {
6243 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
6244 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
6245 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
6246 Data.ReductionOps.append(
C->reduction_ops().begin(),
6247 C->reduction_ops().end());
6248 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
6249 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
6251 llvm::Value *ReductionDesc =
6259 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
6261 CGM.getOpenMPRuntime().emitTaskgroupRegion(*
this,
CodeGen, S.getBeginLoc());
6266 ? llvm::AtomicOrdering::NotAtomic
6267 : llvm::AtomicOrdering::AcquireRelease;
6268 CGM.getOpenMPRuntime().emitFlush(
6271 if (
const auto *FlushClause = S.getSingleClause<
OMPFlushClause>())
6273 FlushClause->varlist_end());
6276 S.getBeginLoc(), AO);
6286 for (
auto &Dep :
Data.Dependences) {
6287 Address DepAddr =
CGM.getOpenMPRuntime().emitDepobjDependClause(
6288 *
this, Dep, DC->getBeginLoc());
6294 CGM.getOpenMPRuntime().emitDestroyClause(*
this, DOLVal, DC->getBeginLoc());
6297 if (
const auto *UC = S.getSingleClause<OMPUpdateDependObjectsClause>()) {
6298 CGM.getOpenMPRuntime().emitUpdateDependObjectsClause(
6299 *
this, DOLVal, UC->getDependencyKind(), UC->getBeginLoc());
6317 for (
const auto *
C : ParentDir.getClausesOfKind<OMPReductionClause>()) {
6318 if (
C->getModifier() != OMPC_REDUCTION_inscan)
6320 Shareds.append(
C->varlist_begin(),
C->varlist_end());
6321 Privates.append(
C->privates().begin(),
C->privates().end());
6322 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
6323 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
6324 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
6325 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
6326 CopyArrayTemps.append(
C->copy_array_temps().begin(),
6327 C->copy_array_temps().end());
6328 CopyArrayElems.append(
C->copy_array_elems().begin(),
6329 C->copy_array_elems().end());
6331 if (ParentDir.getDirectiveKind() == OMPD_simd ||
6373 : BreakContinueStack.back().ContinueBlock.getBlock());
6384 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6386 const Expr *TempExpr = CopyArrayTemps[I];
6398 CGM.getOpenMPRuntime().emitReduction(
6399 *
this, ParentDir.getEndLoc(),
Privates, LHSs, RHSs, ReductionOps,
6402 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6410 const Expr *TempExpr = CopyArrayTemps[I];
6422 ? BreakContinueStack.back().ContinueBlock.getBlock()
6428 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6434 .getIterationVariable()
6435 ->IgnoreParenImpCasts();
6438 IdxVal = Builder.CreateIntCast(IdxVal,
SizeTy,
false);
6439 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6441 const Expr *OrigExpr = Shareds[I];
6442 const Expr *CopyArrayElem = CopyArrayElems[I];
6443 OpaqueValueMapping IdxMapping(
6456 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6459 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6465 .getIterationVariable()
6466 ->IgnoreParenImpCasts();
6470 llvm::BasicBlock *ExclusiveExitBB =
nullptr;
6474 llvm::Value *
Cmp =
Builder.CreateIsNull(IdxVal);
6475 Builder.CreateCondBr(
Cmp, ExclusiveExitBB, ContBB);
6478 IdxVal =
Builder.CreateNUWSub(IdxVal, llvm::ConstantInt::get(
SizeTy, 1));
6480 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6481 const Expr *PrivateExpr =
Privates[I];
6482 const Expr *OrigExpr = Shareds[I];
6483 const Expr *CopyArrayElem = CopyArrayElems[I];
6492 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
6525 bool HasLastprivateClause =
false;
6528 OMPLoopScope PreInitScope(*
this, S);
6533 llvm::BasicBlock *ContBlock =
nullptr;
6569 CGM.getOpenMPRuntime().emitBarrierCall(
6570 *
this, S.getBeginLoc(), OMPD_unknown,
false,
6582 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
6585 llvm::Value *Chunk =
nullptr;
6588 ScheduleKind =
C->getDistScheduleKind();
6589 if (
const Expr *Ch =
C->getChunkSize()) {
6597 CGM.getOpenMPRuntime().getDefaultDistScheduleAndChunk(
6598 *
this, S, ScheduleKind, Chunk);
6619 bool StaticChunked =
6623 Chunk !=
nullptr) ||
6628 StaticChunked ? Chunk :
nullptr);
6679 [&S, &LoopScope, Cond, IncExpr,
LoopExit, &CodeGenLoop,
6682 S, LoopScope.requiresCleanups(), Cond, IncExpr,
6683 [&S,
LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
6684 CodeGenLoop(CGF, S, LoopExit);
6686 [&S, StaticChunked](CodeGenFunction &CGF) {
6687 if (StaticChunked) {
6688 CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound());
6689 CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound());
6690 CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound());
6691 CGF.EmitIgnoredExpr(S.getCombinedInit());
6701 const OMPLoopArguments LoopArguments = {
6704 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments,
6710 return CGF.
Builder.CreateIsNotNull(
6720 *
this, S, [IL, &S](CodeGenFunction &CGF) {
6721 return CGF.
Builder.CreateIsNotNull(
6726 if (HasLastprivateClause) {
6749 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
6758static llvm::Function *
6765 Fn->setDoesNotRecurse();
6769template <
typename T>
6771 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP,
6772 llvm::OpenMPIRBuilder &OMPBuilder) {
6774 unsigned NumLoops =
C->getNumLoops();
6778 for (
unsigned I = 0; I < NumLoops; I++) {
6779 const Expr *CounterVal =
C->getLoopData(I);
6784 StoreValues.emplace_back(StoreValue);
6786 OMPDoacrossKind<T> ODK;
6787 bool IsDependSource = ODK.isSource(
C);
6789 OMPBuilder.createOrderedDepend(CGF.
Builder, AllocaIP, NumLoops,
6790 StoreValues,
".cnt.addr", IsDependSource));
6797 "Standalone ordered directive should have either depend or doacross "
6800 assert(!S.hasAssociatedStmt() &&
"No associated statement must be in "
6801 "ordered depend|doacross construct.");
6803 if (
CGM.getLangOpts().OpenMPIRBuilder) {
6804 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
6805 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6817 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6820 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6826 if (
CGM.getLangOpts().OpenMPIRBuilder) {
6827 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
6828 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6834 auto FiniCB = [
this](InsertPointTy IP) {
6836 return llvm::Error::success();
6839 auto BodyGenCB = [&S,
C,
this](InsertPointTy AllocIP,
6840 InsertPointTy CodeGenIP,
6846 llvm::BasicBlock *CodeGenBB = CodeGenIP.getNodeParent();
6847 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
6848 Builder,
false,
".ordered.after");
6852 assert(S.getBeginLoc().isValid() &&
6853 "Outlined function call location must be valid.");
6856 OutlinedFn, CapturedVars);
6861 return llvm::Error::success();
6864 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6865 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
6866 OMPBuilder.createOrderedThreadsSimd(
Builder, BodyGenCB, FiniCB, !
C));
6872 auto &&
CodeGen = [&S,
C,
this](CodeGenFunction &CGF,
6877 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
6879 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
6880 OutlinedFn, CapturedVars);
6886 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6887 CGM.getOpenMPRuntime().emitOrderedRegion(*
this,
CodeGen, S.getBeginLoc(), !
C);
6894 "DestType must have scalar evaluation kind.");
6895 assert(!Val.
isAggregate() &&
"Must be a scalar or complex.");
6906 "DestType must have complex evaluation kind.");
6915 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
6917 assert(Val.
isComplex() &&
"Must be a scalar or complex.");
6922 Val.
getComplexVal().first, SrcElementType, DestElementType, Loc);
6924 Val.
getComplexVal().second, SrcElementType, DestElementType, Loc);
6930 LValue LVal,
RValue RVal) {
6931 if (LVal.isGlobalReg())
6938 llvm::AtomicOrdering AO, LValue LVal,
6940 if (LVal.isGlobalReg())
6943 LVal, Loc, llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO),
6952 *
this, RVal, RValTy, LVal.
getType(), Loc)),
6961 llvm_unreachable(
"Must be a scalar or complex.");
6969 assert(
V->isLValue() &&
"V of 'omp atomic read' is not lvalue");
6970 assert(
X->isLValue() &&
"X of 'omp atomic read' is not lvalue");
6979 case llvm::AtomicOrdering::Acquire:
6980 case llvm::AtomicOrdering::AcquireRelease:
6981 case llvm::AtomicOrdering::SequentiallyConsistent:
6983 llvm::AtomicOrdering::Acquire);
6985 case llvm::AtomicOrdering::Monotonic:
6986 case llvm::AtomicOrdering::Release:
6988 case llvm::AtomicOrdering::NotAtomic:
6989 case llvm::AtomicOrdering::Unordered:
6990 llvm_unreachable(
"Unexpected ordering.");
6997 llvm::AtomicOrdering AO,
const Expr *
X,
7000 assert(
X->isLValue() &&
"X of 'omp atomic write' is not lvalue");
7008 case llvm::AtomicOrdering::Release:
7009 case llvm::AtomicOrdering::AcquireRelease:
7010 case llvm::AtomicOrdering::SequentiallyConsistent:
7012 llvm::AtomicOrdering::Release);
7014 case llvm::AtomicOrdering::Acquire:
7015 case llvm::AtomicOrdering::Monotonic:
7017 case llvm::AtomicOrdering::NotAtomic:
7018 case llvm::AtomicOrdering::Unordered:
7019 llvm_unreachable(
"Unexpected ordering.");
7026 llvm::AtomicOrdering AO,
7027 bool IsXLHSInRHSPart) {
7032 if (BO == BO_Comma || !
Update.isScalar() || !
X.isSimple() ||
7034 (
Update.getScalarVal()->getType() !=
X.getAddress().getElementType())) ||
7035 !Context.getTargetInfo().hasBuiltinAtomic(
7036 Context.getTypeSize(
X.getType()), Context.toBits(
X.getAlignment())))
7037 return std::make_pair(
false,
RValue::get(
nullptr));
7040 if (
T->isIntegerTy())
7043 if (
T->isFloatingPointTy() && (BO == BO_Add || BO == BO_Sub))
7049 if (!CheckAtomicSupport(
Update.getScalarVal()->getType(), BO) ||
7050 !CheckAtomicSupport(
X.getAddress().getElementType(), BO))
7051 return std::make_pair(
false,
RValue::get(
nullptr));
7053 bool IsInteger =
X.getAddress().getElementType()->isIntegerTy();
7054 llvm::AtomicRMWInst::BinOp RMWOp;
7057 RMWOp = IsInteger ? llvm::AtomicRMWInst::Add : llvm::AtomicRMWInst::FAdd;
7060 if (!IsXLHSInRHSPart)
7061 return std::make_pair(
false,
RValue::get(
nullptr));
7062 RMWOp = IsInteger ? llvm::AtomicRMWInst::Sub : llvm::AtomicRMWInst::FSub;
7065 RMWOp = llvm::AtomicRMWInst::And;
7068 RMWOp = llvm::AtomicRMWInst::Or;
7071 RMWOp = llvm::AtomicRMWInst::Xor;
7075 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
7076 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Min
7077 : llvm::AtomicRMWInst::Max)
7078 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMin
7079 : llvm::AtomicRMWInst::UMax);
7081 RMWOp = IsXLHSInRHSPart ? llvm::AtomicRMWInst::FMin
7082 : llvm::AtomicRMWInst::FMax;
7086 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
7087 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Max
7088 : llvm::AtomicRMWInst::Min)
7089 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMax
7090 : llvm::AtomicRMWInst::UMin);
7092 RMWOp = IsXLHSInRHSPart ? llvm::AtomicRMWInst::FMax
7093 : llvm::AtomicRMWInst::FMin;
7096 RMWOp = llvm::AtomicRMWInst::Xchg;
7105 return std::make_pair(
false,
RValue::get(
nullptr));
7124 llvm_unreachable(
"Unsupported atomic update operation");
7126 llvm::Value *UpdateVal =
Update.getScalarVal();
7127 if (
auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
7129 UpdateVal = CGF.
Builder.CreateIntCast(
7130 IC,
X.getAddress().getElementType(),
7131 X.getType()->hasSignedIntegerRepresentation());
7133 UpdateVal = CGF.
Builder.CreateCast(llvm::Instruction::CastOps::UIToFP, IC,
7134 X.getAddress().getElementType());
7136 llvm::AtomicRMWInst *Res =
7153 if (
X.isGlobalReg()) {
7166 llvm::AtomicOrdering AO,
const Expr *
X,
7170 "Update expr in 'atomic update' must be a binary operator.");
7178 assert(
X->isLValue() &&
"X of 'omp atomic update' is not lvalue");
7185 auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](
RValue XRValue) {
7191 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
7198 case llvm::AtomicOrdering::Release:
7199 case llvm::AtomicOrdering::AcquireRelease:
7200 case llvm::AtomicOrdering::SequentiallyConsistent:
7202 llvm::AtomicOrdering::Release);
7204 case llvm::AtomicOrdering::Acquire:
7205 case llvm::AtomicOrdering::Monotonic:
7207 case llvm::AtomicOrdering::NotAtomic:
7208 case llvm::AtomicOrdering::Unordered:
7209 llvm_unreachable(
"Unexpected ordering.");
7227 llvm_unreachable(
"Must be a scalar or complex.");
7231 llvm::AtomicOrdering AO,
7232 bool IsPostfixUpdate,
const Expr *
V,
7234 const Expr *UE,
bool IsXLHSInRHSPart,
7236 assert(
X->isLValue() &&
"X of 'omp atomic capture' is not lvalue");
7237 assert(
V->isLValue() &&
"V of 'omp atomic capture' is not lvalue");
7246 "Update expr in 'atomic capture' must be a binary operator.");
7257 NewVValType = XRValExpr->
getType();
7259 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
7260 IsPostfixUpdate](
RValue XRValue) {
7264 NewVVal = IsPostfixUpdate ? XRValue : Res;
7268 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
7272 if (IsPostfixUpdate) {
7274 NewVVal = Res.second;
7285 NewVValType =
X->getType().getNonReferenceType();
7287 X->getType().getNonReferenceType(), Loc);
7288 auto &&Gen = [&NewVVal, ExprRValue](
RValue XRValue) {
7294 XLValue, ExprRValue, BO_Assign,
false, AO,
7299 NewVVal = IsPostfixUpdate ? Res.second : ExprRValue;
7315 case llvm::AtomicOrdering::Release:
7317 llvm::AtomicOrdering::Release);
7319 case llvm::AtomicOrdering::Acquire:
7321 llvm::AtomicOrdering::Acquire);
7323 case llvm::AtomicOrdering::AcquireRelease:
7324 case llvm::AtomicOrdering::SequentiallyConsistent:
7326 CGF, {}, Loc, llvm::AtomicOrdering::AcquireRelease);
7328 case llvm::AtomicOrdering::Monotonic:
7330 case llvm::AtomicOrdering::NotAtomic:
7331 case llvm::AtomicOrdering::Unordered:
7332 llvm_unreachable(
"Unexpected ordering.");
7338 CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO,
7340 const Expr *CE,
bool IsXBinopExpr,
bool IsPostfixUpdate,
bool IsFailOnly,
7342 llvm::OpenMPIRBuilder &OMPBuilder =
7345 OMPAtomicCompareOp Op;
7349 Op = OMPAtomicCompareOp::EQ;
7352 Op = OMPAtomicCompareOp::MIN;
7355 Op = OMPAtomicCompareOp::MAX;
7358 llvm_unreachable(
"unsupported atomic compare binary operator");
7362 Address XAddr = XLVal.getAddress();
7364 auto EmitRValueWithCastIfNeeded = [&CGF, Loc](
const Expr *
X,
const Expr *E) {
7369 if (NewE->
getType() ==
X->getType())
7374 llvm::Value *EVal = EmitRValueWithCastIfNeeded(
X, E);
7375 llvm::Value *DVal = D ? EmitRValueWithCastIfNeeded(
X, D) :
nullptr;
7376 if (
auto *CI = dyn_cast<llvm::ConstantInt>(EVal))
7377 EVal = CGF.
Builder.CreateIntCast(
7378 CI, XLVal.getAddress().getElementType(),
7381 if (
auto *CI = dyn_cast<llvm::ConstantInt>(DVal))
7382 DVal = CGF.
Builder.CreateIntCast(
7383 CI, XLVal.getAddress().getElementType(),
7386 llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{
7388 X->getType()->hasSignedIntegerRepresentation(),
7389 X->getType().isVolatileQualified()};
7390 llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal;
7394 VOpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
7395 V->getType()->hasSignedIntegerRepresentation(),
7396 V->getType().isVolatileQualified()};
7401 ROpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
7402 R->getType()->hasSignedIntegerRepresentation(),
7403 R->getType().isVolatileQualified()};
7406 if (FailAO == llvm::AtomicOrdering::NotAtomic) {
7409 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
7410 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
7411 IsPostfixUpdate, IsFailOnly));
7413 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
7414 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
7415 IsPostfixUpdate, IsFailOnly, FailAO));
7419 llvm::AtomicOrdering AO,
7420 llvm::AtomicOrdering FailAO,
bool IsPostfixUpdate,
7423 const Expr *CE,
bool IsXLHSInRHSPart,
7438 IsXLHSInRHSPart, Loc);
7440 case OMPC_compare: {
7442 IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly, Loc);
7446 llvm_unreachable(
"Clause is not allowed in 'omp atomic'.");
7451 llvm::AtomicOrdering AO =
CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
7453 llvm::AtomicOrdering FailAO = llvm::AtomicOrdering::NotAtomic;
7454 bool MemOrderingSpecified =
false;
7455 if (S.getSingleClause<OMPSeqCstClause>()) {
7456 AO = llvm::AtomicOrdering::SequentiallyConsistent;
7457 MemOrderingSpecified =
true;
7458 }
else if (S.getSingleClause<OMPAcqRelClause>()) {
7459 AO = llvm::AtomicOrdering::AcquireRelease;
7460 MemOrderingSpecified =
true;
7461 }
else if (S.getSingleClause<OMPAcquireClause>()) {
7462 AO = llvm::AtomicOrdering::Acquire;
7463 MemOrderingSpecified =
true;
7464 }
else if (S.getSingleClause<OMPReleaseClause>()) {
7465 AO = llvm::AtomicOrdering::Release;
7466 MemOrderingSpecified =
true;
7467 }
else if (S.getSingleClause<OMPRelaxedClause>()) {
7468 AO = llvm::AtomicOrdering::Monotonic;
7469 MemOrderingSpecified =
true;
7471 llvm::SmallSet<OpenMPClauseKind, 2> KindsEncountered;
7480 if (K == OMPC_seq_cst || K == OMPC_acq_rel || K == OMPC_acquire ||
7481 K == OMPC_release || K == OMPC_relaxed || K == OMPC_hint)
7484 KindsEncountered.insert(K);
7489 if (KindsEncountered.contains(OMPC_compare) &&
7490 KindsEncountered.contains(OMPC_capture))
7491 Kind = OMPC_compare;
7492 if (!MemOrderingSpecified) {
7493 llvm::AtomicOrdering DefaultOrder =
7494 CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
7495 if (DefaultOrder == llvm::AtomicOrdering::Monotonic ||
7496 DefaultOrder == llvm::AtomicOrdering::SequentiallyConsistent ||
7497 (DefaultOrder == llvm::AtomicOrdering::AcquireRelease &&
7498 Kind == OMPC_capture)) {
7500 }
else if (DefaultOrder == llvm::AtomicOrdering::AcquireRelease) {
7501 if (Kind == OMPC_unknown || Kind == OMPC_update || Kind == OMPC_write) {
7502 AO = llvm::AtomicOrdering::Release;
7503 }
else if (Kind == OMPC_read) {
7504 assert(Kind == OMPC_read &&
"Unexpected atomic kind.");
7505 AO = llvm::AtomicOrdering::Acquire;
7510 if (KindsEncountered.contains(OMPC_compare) &&
7511 KindsEncountered.contains(OMPC_fail)) {
7512 Kind = OMPC_compare;
7513 const auto *FailClause = S.getSingleClause<OMPFailClause>();
7516 if (FailParameter == llvm::omp::OMPC_relaxed)
7517 FailAO = llvm::AtomicOrdering::Monotonic;
7518 else if (FailParameter == llvm::omp::OMPC_acquire)
7519 FailAO = llvm::AtomicOrdering::Acquire;
7520 else if (FailParameter == llvm::omp::OMPC_seq_cst)
7521 FailAO = llvm::AtomicOrdering::SequentiallyConsistent;
7528 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>()) {
7529 uint64_t Hint = HintClause->getHint()
7532 if (Hint & llvm::to_underlying(OMPSyncHint::OMPXSafeFPAtomics))
7534 else if (Hint & llvm::to_underlying(OMPSyncHint::OMPXFastFPAtomics))
7555 OMPLexicalScope
Scope(CGF, S, OMPD_target);
7558 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
7564 llvm::Function *Fn =
nullptr;
7565 llvm::Constant *FnID =
nullptr;
7567 const Expr *IfCond =
nullptr;
7569 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7570 if (
C->getNameModifier() == OMPD_unknown ||
7571 C->getNameModifier() == OMPD_target) {
7572 IfCond =
C->getCondition();
7578 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device(
7581 Device.setPointerAndInt(
C->getDevice(),
C->getModifier());
7586 bool IsOffloadEntry =
true;
7590 IsOffloadEntry =
false;
7593 IsOffloadEntry =
false;
7595 if (
CGM.
getLangOpts().OpenMPOffloadMandatory && !IsOffloadEntry) {
7599 StringRef ParentName;
7604 ParentName = CGF.
CurFn->getName();
7605 else if (
const auto *D = dyn_cast<CXXConstructorDecl>(CGF.
CurFuncDecl))
7607 else if (
const auto *D = dyn_cast<CXXDestructorDecl>(CGF.
CurFuncDecl))
7616 OMPLexicalScope
Scope(CGF, S, OMPD_task);
7617 auto &&SizeEmitter =
7620 if (IsOffloadEntry) {
7621 OMPLoopScope PreInitScope(CGF, D);
7624 NumIterations = CGF.
Builder.CreateIntCast(NumIterations, CGF.
Int64Ty,
7626 return NumIterations;
7644 CGF.
EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
7649 StringRef ParentName,
7655 llvm::Constant *
Addr;
7657 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7659 assert(Fn &&
Addr &&
"Target device function emission failed.");
7673 const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams);
7674 llvm::Function *OutlinedFn =
7679 OMPTeamsScope
Scope(CGF, S);
7684 const Expr *NumTeams = NT ? NT->getNumTeams().front() :
nullptr;
7685 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() :
nullptr;
7692 const Expr *IfCond =
nullptr;
7693 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7694 if (
C->getNameModifier() == OMPD_unknown ||
7695 C->getNameModifier() == OMPD_teams) {
7696 IfCond =
C->getCondition();
7705 const llvm::APInt One(32, 1);
7712 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() :
nullptr;
7738 CGF.
EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt());
7743 [](CodeGenFunction &) {
return nullptr; });
7748 auto *CS = S.getCapturedStmt(OMPD_teams);
7775 llvm::Constant *
Addr;
7777 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7779 assert(Fn &&
Addr &&
"Target device function emission failed.");
7821 llvm::Constant *
Addr;
7823 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7825 assert(Fn &&
Addr &&
"Target device function emission failed.");
7867 llvm::Constant *
Addr;
7869 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7871 assert(Fn &&
Addr &&
"Target device function emission failed.");
7885 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7890 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7902 [](CodeGenFunction &) {
return nullptr; });
7907 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7912 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7924 [](CodeGenFunction &) {
return nullptr; });
7929 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7935 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7947 [](CodeGenFunction &) {
return nullptr; });
7952 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7958 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7965 CGF, OMPD_distribute, CodeGenDistribute,
false);
7971 [](CodeGenFunction &) {
return nullptr; });
7975 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7976 llvm::Value *
Device =
nullptr;
7977 llvm::Value *NumDependences =
nullptr;
7978 llvm::Value *DependenceList =
nullptr;
7986 if (!
Data.Dependences.empty()) {
7988 std::tie(NumDependences, DependenciesArray) =
7989 CGM.getOpenMPRuntime().emitDependClause(*
this,
Data.Dependences,
7993 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
7998 "OMPNowaitClause clause is used separately in OMPInteropDirective.");
8001 if (!ItOMPInitClause.empty()) {
8004 llvm::Value *InteropvarPtr =
8006 llvm::omp::OMPInteropType InteropType =
8007 llvm::omp::OMPInteropType::Unknown;
8008 if (
C->getIsTarget()) {
8009 InteropType = llvm::omp::OMPInteropType::Target;
8011 assert(
C->getIsTargetSync() &&
8012 "Expected interop-type target/targetsync");
8013 InteropType = llvm::omp::OMPInteropType::TargetSync;
8015 OMPBuilder.createOMPInteropInit(
Builder, InteropvarPtr, InteropType,
8016 Device, NumDependences, DependenceList,
8017 Data.HasNowaitClause);
8021 if (!ItOMPDestroyClause.empty()) {
8024 llvm::Value *InteropvarPtr =
8026 OMPBuilder.createOMPInteropDestroy(
Builder, InteropvarPtr,
Device,
8027 NumDependences, DependenceList,
8028 Data.HasNowaitClause);
8031 auto ItOMPUseClause = S.getClausesOfKind<
OMPUseClause>();
8032 if (!ItOMPUseClause.empty()) {
8035 llvm::Value *InteropvarPtr =
8037 OMPBuilder.createOMPInteropUse(
Builder, InteropvarPtr,
Device,
8038 NumDependences, DependenceList,
8039 Data.HasNowaitClause);
8061 CGF, OMPD_distribute, CodeGenDistribute,
false);
8080 llvm::Constant *
Addr;
8082 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8084 assert(Fn &&
Addr &&
"Target device function emission failed.");
8113 CGF, OMPD_distribute, CodeGenDistribute,
false);
8132 llvm::Constant *
Addr;
8134 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8136 assert(Fn &&
Addr &&
"Target device function emission failed.");
8149 CGM.getOpenMPRuntime().emitCancellationPointCall(*
this, S.getBeginLoc(),
8154 const Expr *IfCond =
nullptr;
8155 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
8156 if (
C->getNameModifier() == OMPD_unknown ||
8157 C->getNameModifier() == OMPD_cancel) {
8158 IfCond =
C->getCondition();
8162 if (
CGM.getLangOpts().OpenMPIRBuilder) {
8163 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
8169 llvm::Value *IfCondition =
nullptr;
8173 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
8175 return Builder.restoreIP(AfterIP);
8179 CGM.getOpenMPRuntime().emitCancelCall(*
this, S.getBeginLoc(), IfCond,
8185 if (Kind == OMPD_parallel || Kind == OMPD_target_parallel ||
8188 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
8189 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
8190 Kind == OMPD_distribute_parallel_for ||
8191 Kind == OMPD_target_parallel_for ||
8192 Kind == OMPD_teams_distribute_parallel_for ||
8193 Kind == OMPD_target_teams_distribute_parallel_for);
8194 return OMPCancelStack.getExitBlock();
8199 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
8200 CaptureDeviceAddrMap) {
8201 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
8202 for (
const Expr *OrigVarIt :
C.varlist()) {
8204 if (!Processed.insert(OrigVD).second)
8211 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
8216 "Base should be the current struct!");
8217 MatchingVD = ME->getMemberDecl();
8222 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
8223 if (InitAddrIt == CaptureDeviceAddrMap.end())
8231 Address(InitAddrIt->second, Ty,
8233 assert(IsRegistered &&
"firstprivate var already registered as private");
8241 while (
const auto *OASE = dyn_cast<ArraySectionExpr>(
Base))
8242 Base = OASE->getBase()->IgnoreParenImpCasts();
8243 while (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(
Base))
8244 Base = ASE->getBase()->IgnoreParenImpCasts();
8250 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
8251 CaptureDeviceAddrMap) {
8252 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
8253 for (
const Expr *Ref :
C.varlist()) {
8255 if (!Processed.insert(OrigVD).second)
8261 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
8266 "Base should be the current struct!");
8267 MatchingVD = ME->getMemberDecl();
8272 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
8273 if (InitAddrIt == CaptureDeviceAddrMap.end())
8279 Address(InitAddrIt->second, Ty,
8292 (void)PrivateScope.
addPrivate(OrigVD, PrivAddr);
8300 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
8301 CGM.getOpenMPRuntime().registerVTable(S);
8309 bool PrivatizeDevicePointers =
false;
8311 bool &PrivatizeDevicePointers;
8314 explicit DevicePointerPrivActionTy(
bool &PrivatizeDevicePointers)
8315 : PrivatizeDevicePointers(PrivatizeDevicePointers) {}
8316 void Enter(CodeGenFunction &CGF)
override {
8317 PrivatizeDevicePointers =
true;
8320 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
8323 auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
8324 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
8328 auto &&PrivCodeGen = [&](CodeGenFunction &CGF,
PrePostActionTy &Action) {
8330 PrivatizeDevicePointers =
false;
8336 if (PrivatizeDevicePointers) {
8350 std::optional<OpenMPDirectiveKind> CaptureRegion;
8351 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
8354 for (
const Expr *E :
C->varlist()) {
8356 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
8360 for (
const Expr *E :
C->varlist()) {
8362 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
8366 CaptureRegion = OMPD_unknown;
8369 OMPLexicalScope
Scope(CGF, S, CaptureRegion);
8381 OMPLexicalScope
Scope(CGF, S);
8390 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
8396 const Expr *IfCond =
nullptr;
8398 IfCond =
C->getCondition();
8409 CGM.getOpenMPRuntime().emitTargetDataCalls(*
this, S, IfCond,
Device, RCG,
8417 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8421 const Expr *IfCond =
nullptr;
8423 IfCond =
C->getCondition();
8430 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8431 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8438 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8442 const Expr *IfCond =
nullptr;
8444 IfCond =
C->getCondition();
8451 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8452 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8459 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
8487 llvm::Constant *
Addr;
8489 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8491 assert(Fn &&
Addr &&
"Target device function emission failed.");
8511 CGF, OMPD_target_parallel_for, S.
hasCancel());
8527 llvm::Constant *
Addr;
8529 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8531 assert(Fn &&
Addr &&
"Target device function emission failed.");
8566 llvm::Constant *
Addr;
8568 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8570 assert(Fn &&
Addr &&
"Target device function emission failed.");
8592 const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop);
8595 OMPLexicalScope
Scope(*
this, S, OMPD_taskloop,
false);
8600 const Expr *IfCond =
nullptr;
8601 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
8602 if (
C->getNameModifier() == OMPD_unknown ||
8603 C->getNameModifier() == OMPD_taskloop) {
8604 IfCond =
C->getCondition();
8617 Data.Schedule.setInt(
false);
8620 (Clause->getModifier() == OMPC_GRAINSIZE_strict) ?
true :
false;
8623 Data.Schedule.setInt(
true);
8626 (Clause->getModifier() == OMPC_NUMTASKS_strict) ?
true :
false;
8640 llvm::BasicBlock *ContBlock =
nullptr;
8641 OMPLoopScope PreInitScope(CGF, S);
8642 if (CGF.ConstantFoldsToSimpleInteger(S.
getPreCond(), CondConstant)) {
8646 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock(
"taskloop.if.then");
8647 ContBlock = CGF.createBasicBlock(
"taskloop.if.end");
8649 CGF.getProfileCount(&S));
8650 CGF.EmitBlock(ThenBlock);
8651 CGF.incrementProfileCounter(&S);
8654 (void)CGF.EmitOMPLinearClauseInit(S);
8658 enum { LowerBound = 5, UpperBound, Stride, LastIter };
8660 auto *LBP = std::next(I, LowerBound);
8661 auto *UBP = std::next(I, UpperBound);
8662 auto *STP = std::next(I, Stride);
8663 auto *LIP = std::next(I, LastIter);
8671 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
8672 CGF.EmitOMPLinearClause(S, LoopScope);
8673 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
8678 CGF.EmitVarDecl(*IVDecl);
8679 CGF.EmitIgnoredExpr(S.
getInit());
8691 OMPLexicalScope
Scope(CGF, S, OMPD_taskloop,
false);
8701 [&S](CodeGenFunction &CGF) {
8702 emitOMPLoopBodyWithStopPoint(CGF, S,
8703 CodeGenFunction::JumpDest());
8705 [](CodeGenFunction &) {});
8710 CGF.EmitBranch(ContBlock);
8711 CGF.EmitBlock(ContBlock,
true);
8714 if (HasLastprivateClause) {
8715 CGF.EmitOMPLastprivateClauseFinal(
8717 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
8718 CGF.GetAddrOfLocalVar(*LIP),
false,
8719 (*LIP)->getType(), S.getBeginLoc())));
8722 CGF.EmitOMPLinearClauseFinal(S, [LIP, &S](CodeGenFunction &CGF) {
8723 return CGF.
Builder.CreateIsNotNull(
8725 (*LIP)->
getType(), S.getBeginLoc()));
8728 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
8729 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
8731 auto &&
CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
8733 OMPLoopScope PreInitScope(CGF, S);
8734 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S,
8735 OutlinedFn, SharedsTy,
8736 CapturedStruct, IfCond,
Data);
8738 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
8744 CGM.getOpenMPRuntime().emitTaskgroupRegion(
8746 [&S, &BodyGen, &TaskGen, &
Data](CodeGenFunction &CGF,
8766 OMPLexicalScope
Scope(*
this, S);
8778 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8779 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8790 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8791 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8802 OMPLexicalScope
Scope(*
this, S);
8803 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8814 OMPLexicalScope
Scope(*
this, S);
8815 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8821 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8826 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8827 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8839 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8844 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8845 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8857 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8862 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8863 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8875 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8880 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8881 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8895 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8899 const Expr *IfCond =
nullptr;
8901 IfCond =
C->getCondition();
8908 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8909 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8919 BindKind =
C->getBindKind();
8922 case OMPC_BIND_parallel:
8924 case OMPC_BIND_teams:
8926 case OMPC_BIND_thread:
8937 const auto *ForS = dyn_cast<ForStmt>(CS);
8948 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
8949 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_loop,
CodeGen);
8975 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
8980 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
8992 [](CodeGenFunction &) {
return nullptr; });
8997 std::string StatusMsg,
9001 StatusMsg +=
": DEVICE";
9003 StatusMsg +=
": HOST";
9010 llvm::dbgs() << StatusMsg <<
": " <<
FileName <<
": " << LineNo <<
"\n";
9033 CGF, OMPD_distribute, CodeGenDistribute,
false);
9062 CGF, OMPD_distribute, CodeGenDistribute,
false);
9095 llvm::Constant *
Addr;
9097 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
9099 assert(Fn &&
Addr &&
9100 "Target device function emission failed for 'target teams loop'.");
9111 CGF, OMPD_target_parallel_loop,
false);
9127 llvm::Constant *
Addr;
9129 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
9131 assert(Fn &&
Addr &&
"Target device function emission failed.");
9146 if (
const auto *SD = dyn_cast<OMPScanDirective>(&D)) {
9151 if (
const auto *MD = dyn_cast<OMPMetaDirective>(&D)) {
9155 if (!D.hasAssociatedStmt() || !D.getAssociatedStmt())
9161 for (
const auto *
C : D.getClausesOfKind<OMPFirstprivateClause>()) {
9162 for (
const Expr *Ref :
C->varlist()) {
9166 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
9169 if (!CGF.LocalDeclMap.count(VD)) {
9181 if (
const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
9182 for (
const Expr *E : LD->counters()) {
9190 if (!CGF.LocalDeclMap.count(VD))
9194 for (
const auto *
C : D.getClausesOfKind<OMPOrderedClause>()) {
9195 if (!
C->getNumForLoops())
9197 for (
unsigned I = LD->getLoopsNumber(),
9198 E =
C->getLoopNumIterations().size();
9200 if (
const auto *VD = dyn_cast<OMPCapturedExprDecl>(
9203 if (!CGF.LocalDeclMap.count(VD))
9210 CGF.
EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
9213 if (D.getDirectiveKind() == OMPD_atomic ||
9214 D.getDirectiveKind() == OMPD_critical ||
9215 D.getDirectiveKind() == OMPD_section ||
9216 D.getDirectiveKind() == OMPD_master ||
9217 D.getDirectiveKind() == OMPD_masked ||
9218 D.getDirectiveKind() == OMPD_assume ||
9224 OMPSimdLexicalScope
Scope(*
this, D);
9225 CGM.getOpenMPRuntime().emitInlinedDirective(
9228 : D.getDirectiveKind(),
9236 for (
const auto *
C : S.getClausesOfKind<OMPHoldsClause>()) {
9237 const Expr *E =
C->getExpr();
9238 assert(E &&
"holds clause requires an expression");
Defines the clang::ASTContext interface.
static bool isAllocatableDecl(const VarDecl *VD)
static const VarDecl * getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE)
static void emitTargetRegion(CodeGenFunction &CGF, const OMPTargetDirective &S, PrePostActionTy &Action)
static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S, PrePostActionTy &Action)
static const VarDecl * getBaseDecl(const Expr *Ref)
static void emitTargetTeamsGenericLoopRegionAsParallel(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsGenericLoopDirective &S)
static void emitOMPAtomicReadExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, const Expr *X, const Expr *V, SourceLocation Loc)
static void emitOMPAtomicCaptureExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, bool IsPostfixUpdate, const Expr *V, const Expr *X, const Expr *E, const Expr *UE, bool IsXLHSInRHSPart, SourceLocation Loc)
static void emitScanBasedDirective(CodeGenFunction &CGF, const OMPLoopDirective &S, llvm::function_ref< llvm::Value *(CodeGenFunction &)> NumIteratorsGen, llvm::function_ref< void(CodeGenFunction &)> FirstGen, llvm::function_ref< void(CodeGenFunction &)> SecondGen)
Emits the code for the directive with inscan reductions.
static void emitSimpleAtomicStore(CodeGenFunction &CGF, llvm::AtomicOrdering AO, LValue LVal, RValue RVal)
static bool isSupportedByOpenMPIRBuilder(const OMPTaskgroupDirective &T)
static Address castValueFromUintptr(CodeGenFunction &CGF, SourceLocation Loc, QualType DstType, StringRef Name, LValue AddrLV)
static void emitLoopNestTransformation(CodeGenFunction &CGF, const OMPCanonicalLoopNestTransformationDirective &S)
Emit a loop-nest transformation followed by its loop variable finalization, which restores the loop-e...
static bool canEmitGPUFusedDistSchedule(const CodeGenModule &CGM, const OMPLoopDirective &S, OpenMPDirectiveKind DKind)
Whether a combined distribute parallel for may use the fused distr_static_chunk + static_chunkone sch...
static void emitDistributeParallelForDistributeInnerBoundParams(CodeGenFunction &CGF, const OMPExecutableDirective &S, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars)
static void emitScanBasedDirectiveFinals(CodeGenFunction &CGF, const OMPLoopDirective &S, llvm::function_ref< llvm::Value *(CodeGenFunction &)> NumIteratorsGen)
Copies final inscan reductions values to the original variables.
static void checkForLastprivateConditionalUpdate(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static std::pair< LValue, LValue > emitForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S)
The following two functions generate expressions for the loop lower and upper bounds in case of stati...
static void emitTargetParallelForRegion(CodeGenFunction &CGF, const OMPTargetParallelForDirective &S, PrePostActionTy &Action)
static llvm::Function * emitOutlinedFunctionPrologueAggregate(CodeGenFunction &CGF, FunctionArgList &Args, llvm::MapVector< const Decl *, std::pair< const VarDecl *, Address > > &LocalAddrs, llvm::DenseMap< const Decl *, std::pair< const Expr *, llvm::Value * > > &VLASizes, llvm::Value *&CXXThisValue, llvm::Value *&ContextV, const CapturedStmt &CS, SourceLocation Loc, StringRef FunctionName)
static LValue EmitOMPHelperVar(CodeGenFunction &CGF, const DeclRefExpr *Helper)
Emit a helper variable and return corresponding lvalue.
static void emitOMPAtomicUpdateExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, const Expr *X, const Expr *E, const Expr *UE, bool IsXLHSInRHSPart, SourceLocation Loc)
static llvm::Value * convertToScalarValue(CodeGenFunction &CGF, RValue Val, QualType SrcType, QualType DestType, SourceLocation Loc)
static llvm::Function * emitOutlinedOrderedFunction(CodeGenModule &CGM, const CapturedStmt *S, const OMPExecutableDirective &D)
static void emitPreCond(CodeGenFunction &CGF, const OMPLoopDirective &S, const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount)
static std::pair< bool, RValue > emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X, RValue Update, BinaryOperatorKind BO, llvm::AtomicOrdering AO, bool IsXLHSInRHSPart)
static std::pair< LValue, LValue > emitDistributeParallelForInnerBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitTargetTeamsGenericLoopRegionAsDistribute(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsGenericLoopDirective &S)
static void emitTargetParallelRegion(CodeGenFunction &CGF, const OMPTargetParallelDirective &S, PrePostActionTy &Action)
static std::pair< llvm::Value *, llvm::Value * > emitDispatchForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S, Address LB, Address UB)
When dealing with dispatch schedules (e.g.
static void emitMaster(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitRestoreIP(CodeGenFunction &CGF, const T *C, llvm::OpenMPIRBuilder::InsertPointTy AllocaIP, llvm::OpenMPIRBuilder &OMPBuilder)
static void emitCommonOMPTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, const RegionCodeGenTy &CodeGen)
static void emitSimdlenSafelenClause(CodeGenFunction &CGF, const OMPExecutableDirective &D)
static void emitAlignedClause(CodeGenFunction &CGF, const OMPExecutableDirective &D)
static bool isSimdSupportedByOpenMPIRBuilder(const OMPLoopDirective &S)
static void emitCommonOMPParallelDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, const CodeGenBoundParametersTy &CodeGenBoundParameters)
static void applyConservativeSimdOrderedDirective(const Stmt &AssociatedStmt, LoopInfoStack &LoopStack)
static bool emitWorksharingDirective(CodeGenFunction &CGF, const OMPLoopDirective &S, bool HasCancel)
static void emitPostUpdateForReductionClause(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
static void emitEmptyOrdered(CodeGenFunction &, SourceLocation Loc, const unsigned IVSize, const bool IVSigned)
static void emitTargetTeamsLoopCodegenStatus(CodeGenFunction &CGF, std::string StatusMsg, const OMPExecutableDirective &D)
static bool isForSupportedByOpenMPIRBuilder(const OMPLoopDirective &S, bool HasCancel)
static RValue emitSimpleAtomicLoad(CodeGenFunction &CGF, llvm::AtomicOrdering AO, LValue LVal, SourceLocation Loc)
static std::pair< llvm::Value *, llvm::Value * > emitDistributeParallelForDispatchBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S, Address LB, Address UB)
if the 'for' loop has a dispatch schedule (e.g.
static bool hasOrderedBlockAssocDirective(const Stmt *S)
static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO, bool IsPostfixUpdate, const Expr *X, const Expr *V, const Expr *R, const Expr *E, const Expr *UE, const Expr *D, const Expr *CE, bool IsXLHSInRHSPart, bool IsFailOnly, SourceLocation Loc)
static CodeGenFunction::ComplexPairTy convertToComplexValue(CodeGenFunction &CGF, RValue Val, QualType SrcType, QualType DestType, SourceLocation Loc)
static ImplicitParamDecl * createImplicitFirstprivateForType(ASTContext &C, OMPTaskDataTy &Data, QualType Ty, CapturedDecl *CD, SourceLocation Loc)
static EmittedClosureTy emitCapturedStmtFunc(CodeGenFunction &ParentCGF, const CapturedStmt *S)
Emit a captured statement and return the function as well as its captured closure context.
static void emitOMPLoopBodyWithStopPoint(CodeGenFunction &CGF, const OMPLoopDirective &S, CodeGenFunction::JumpDest LoopExit)
static void emitOMPDistributeDirective(const OMPLoopDirective &S, CodeGenFunction &CGF, CodeGenModule &CGM)
static void emitOMPCopyinClause(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitTargetTeamsDistributeParallelForRegion(CodeGenFunction &CGF, const OMPTargetTeamsDistributeParallelForDirective &S, PrePostActionTy &Action)
static llvm::CallInst * emitCapturedStmtCall(CodeGenFunction &ParentCGF, EmittedClosureTy Cap, llvm::ArrayRef< llvm::Value * > Args)
Emit a call to a previously captured closure.
static void emitMasked(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitBody(CodeGenFunction &CGF, const Stmt *S, const Stmt *NextLoop, int MaxLevel, int Level=0)
static void emitOMPForDirective(const OMPLoopDirective &S, CodeGenFunction &CGF, CodeGenModule &CGM, bool HasCancel)
static void emitEmptyBoundParameters(CodeGenFunction &, const OMPExecutableDirective &, llvm::SmallVectorImpl< llvm::Value * > &)
static void emitTargetParallelForSimdRegion(CodeGenFunction &CGF, const OMPTargetParallelForSimdDirective &S, PrePostActionTy &Action)
static void emitOMPSimdDirective(const OMPLoopDirective &S, CodeGenFunction &CGF, CodeGenModule &CGM)
static void emitOMPAtomicCompareExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO, const Expr *X, const Expr *V, const Expr *R, const Expr *E, const Expr *D, const Expr *CE, bool IsXBinopExpr, bool IsPostfixUpdate, bool IsFailOnly, SourceLocation Loc)
std::pair< llvm::Function *, llvm::Value * > EmittedClosureTy
static OpenMPDirectiveKind getEffectiveDirectiveKind(const OMPExecutableDirective &S)
static void emitTargetTeamsRegion(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsDirective &S)
static void buildDependences(const OMPExecutableDirective &S, OMPTaskDataTy &Data)
static RValue convertToType(CodeGenFunction &CGF, RValue Value, QualType SourceType, QualType ResType, SourceLocation Loc)
static void emitScanBasedDirectiveDecls(CodeGenFunction &CGF, const OMPLoopDirective &S, llvm::function_ref< llvm::Value *(CodeGenFunction &)> NumIteratorsGen)
Emits internal temp array declarations for the directive with inscan reductions.
static void emitTargetTeamsDistributeParallelForSimdRegion(CodeGenFunction &CGF, const OMPTargetTeamsDistributeParallelForSimdDirective &S, PrePostActionTy &Action)
static void emitTargetTeamsDistributeSimdRegion(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsDistributeSimdDirective &S)
static llvm::MapVector< llvm::Value *, llvm::Value * > GetAlignedMapping(const OMPLoopDirective &S, CodeGenFunction &CGF)
static llvm::omp::ScheduleKind convertClauseKindToSchedKind(OpenMPScheduleClauseKind ScheduleClauseKind)
static void mapParam(CodeGenFunction &CGF, const DeclRefExpr *Helper, const ImplicitParamDecl *PVD, CodeGenFunction::OMPPrivateScope &Privates)
Emit a helper variable and return corresponding lvalue.
static void emitCommonOMPTeamsDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
static void emitTargetParallelGenericLoopRegion(CodeGenFunction &CGF, const OMPTargetParallelGenericLoopDirective &S, PrePostActionTy &Action)
static QualType getCanonicalParamType(ASTContext &C, QualType T)
static void emitCommonSimdLoop(CodeGenFunction &CGF, const OMPLoopDirective &S, const RegionCodeGenTy &SimdInitGen, const RegionCodeGenTy &BodyCodeGen)
static LValue createSectionLVal(CodeGenFunction &CGF, QualType Ty, const Twine &Name, llvm::Value *Init=nullptr)
static void emitOMPAtomicWriteExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, const Expr *X, const Expr *E, SourceLocation Loc)
static llvm::Function * emitOutlinedFunctionPrologue(CodeGenFunction &CGF, FunctionArgList &Args, llvm::MapVector< const Decl *, std::pair< const VarDecl *, Address > > &LocalAddrs, llvm::DenseMap< const Decl *, std::pair< const Expr *, llvm::Value * > > &VLASizes, llvm::Value *&CXXThisValue, const FunctionOptions &FO)
static void emitInnerParallelForWhenCombined(CodeGenFunction &CGF, const OMPLoopDirective &S, CodeGenFunction::JumpDest LoopExit)
static void emitTargetTeamsDistributeRegion(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsDistributeDirective &S)
This file defines OpenMP nodes for declarative directives.
static const Decl * getCanonicalDecl(const Decl *D)
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
Defines the PrettyStackTraceEntry class, which is used to make crashes give more contextual informati...
Defines the SourceManager interface.
This file defines OpenMP AST classes for executable directives and clauses.
This represents clause 'aligned' in the 'pragma omp ...' directives.
This represents 'pragma omp atomic' directive.
Expr * getR()
Get 'r' part of the associated expression/statement.
Expr * getX()
Get 'x' part of the associated expression/statement.
bool isFailOnly() const
Return true if 'v' is updated only when the condition is evaluated false (compare capture only).
bool isPostfixUpdate() const
Return true if 'v' expression must be updated to original value of 'x', false if 'v' must be updated ...
Expr * getExpr()
Get 'expr' part of the associated expression/statement.
Expr * getV()
Get 'v' part of the associated expression/statement.
bool isXLHSInRHSPart() const
Return true if helper update expression has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' and...
Expr * getD()
Get 'd' part of the associated expression/statement.
Expr * getUpdateExpr()
Get helper expression of the form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or 'OpaqueValueExp...
Expr * getCondExpr()
Get the 'cond' part of the source atomic expression.
This represents 'pragma omp barrier' directive.
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 'pragma omp critical' directive.
DeclarationNameInfo getDirectiveName() const
Return name of the directive.
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 'pragma omp depobj' directive.
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.
Represents the 'pragma omp flatten' loop transformation directive.
Stmt * getTransformedStmt() const
Gets the flattened loop after the transformation.
Stmt * getFinals() const
Return updates to the original loop variables after the flattened loop.
This represents implicit clause 'flush' for the 'pragma omp flush' directive. This clause does not ex...
This represents 'pragma omp flush' directive.
This represents 'pragma omp for' directive.
bool hasCancel() const
Return true if current directive has inner cancel directive.
This represents 'pragma omp for simd' directive.
Represents the 'pragma omp fuse' loop transformation directive.
Stmt * getFinals() const
Return finals statement.
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.
This represents 'pragma omp interop' directive.
This is a common base class for loop directives ('omp simd', 'omp for', 'omp for simd' etc....
Expr * getCombinedUpperBoundVariable() const
Expr * getPreCond() const
Expr * getPrevUpperBoundVariable() const
Expr * getIsLastIterVariable() const
Expr * getCombinedLowerBoundVariable() const
Expr * getCombinedCond() const
Expr * getCombinedInit() const
Expr * getLowerBoundVariable() const
Expr * getCombinedNextLowerBound() const
ArrayRef< Expr * > finals_conditions()
ArrayRef< Expr * > counters()
ArrayRef< Expr * > private_counters()
Expr * getUpperBoundVariable() const
Expr * getCombinedDistCond() const
Expr * getPrevLowerBoundVariable() const
ArrayRef< Expr * > dependent_inits()
Expr * getNextLowerBound() const
Expr * getDistInc() const
ArrayRef< Expr * > updates()
Expr * getNextUpperBound() const
Expr * getLastIteration() const
Expr * getEnsureUpperBound() const
Expr * getCalcLastIteration() const
Expr * getCombinedNextUpperBound() const
Expr * getIterationVariable() const
Expr * getStrideVariable() const
Expr * getNumIterations() const
ArrayRef< Expr * > finals()
Expr * getPrevEnsureUpperBound() const
Expr * getCombinedEnsureUpperBound() const
ArrayRef< Expr * > dependent_counters()
ArrayRef< Expr * > inits()
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' 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 block-associated 'pragma omp ordered' directive.
This represents standalone 'pragma omp ordered' directive.
This represents 'pragma omp parallel for' directive.
bool hasCancel() const
Return true if current directive has inner cancel directive.
This represents 'pragma omp parallel for simd' directive.
This represents 'pragma omp parallel masked' directive.
This represents 'pragma omp parallel masked taskloop' directive.
This represents 'pragma omp parallel masked taskloop simd' directive.
This represents 'pragma omp parallel master' directive.
This represents 'pragma omp parallel master taskloop' directive.
This represents 'pragma omp parallel master taskloop simd' directive.
This represents 'pragma omp parallel sections' directive.
This represents 'priority' clause in the 'pragma omp ...' directive.
Represents the 'pragma omp reverse' loop transformation directive.
This represents 'simd' clause in the 'pragma omp ...' directive.
This represents 'pragma omp scan' directive.
This represents 'pragma omp scope' directive.
This represents 'pragma omp section' directive.
This represents 'pragma omp sections' directive.
bool hasCancel() const
Return true if current directive has inner cancel directive.
This represents 'pragma omp simd' directive.
This represents 'pragma omp single' directive.
Represents the 'pragma omp split' loop transformation directive.
This represents the 'pragma omp stripe' loop transformation directive.
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 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 task' directive.
This represents 'pragma omp taskloop' directive.
This represents 'pragma omp taskloop simd' directive.
This represents 'pragma omp taskgroup' directive.
const Expr * getReductionRef() const
Returns reference to the task_reduction return variable.
This represents 'pragma omp taskwait' directive.
This represents 'pragma omp taskyield' 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.
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)
A binding in a decomposition declaration.
DecompositionDecl * getDecomposedDecl() const
Get the decomposition declaration that this binding represents a decomposition of.
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.
This is an opaque type for sizes expressed in character units.
CharUnits alignTo(CharUnits Align) const
Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is a multiple...
QuantityType getQuantity() const
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)
Construct a CharUnits quantity from a raw integer type.
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 setVarAddr(CodeGenFunction &CGF, const ValueDecl *LocalVD, Address TempAddr)
Sets the address of the variable LocalVD to be TempAddr in function CGF.
bool apply(CodeGenFunction &CGF)
Applies new addresses to the list of the variables.
void restore(CodeGenFunction &CGF)
Restores original addresses of the variables.
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 ValueDecl *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)
llvm::Value * performAddrSpaceCast(llvm::Value *Src, llvm::Type *DestTy)
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::Type * ConvertType(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)
void EmitOMPFlattenDirective(const OMPFlattenDirective &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 eraseLocalDecl(const Decl *D)
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)
static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPLoopDirective &S)
Emit device code for the target simd and target loop directives.
Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr)
Load a pointer with type PtrTy stored at address Ptr.
void EmitOMPSplitDirective(const OMPSplitDirective &S)
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
void EmitOMPReductionClauseFinal(const OMPExecutableDirective &D, const OpenMPDirectiveKind ReductionKind)
Emit final update of reduction values to original variables at the end of the directive.
void EmitOMPLoopBody(const OMPLoopDirective &D, JumpDest LoopExit)
Helper for the OpenMP loop directives.
void EmitOMPScopeDirective(const OMPScopeDirective &S)
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
llvm::AssertingVH< llvm::Instruction > AllocaInsertPt
AllocaInsertPoint - This is an instruction in the entry block before which we prefer to insert alloca...
void EmitAggregateAssign(LValue Dest, LValue Src, QualType EltTy)
Emit an aggregate assignment.
CodeGenFunction * ParentCGF
JumpDest ReturnBlock
ReturnBlock - Unified return block.
void EmitOMPTargetTeamsDistributeSimdDirective(const OMPTargetTeamsDistributeSimdDirective &S)
const llvm::function_ref< void(CodeGenFunction &, llvm::Function *, const OMPTaskDataTy &)> TaskGenTy
llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Location)
Converts Location to a DebugLoc, if debug information is enabled.
bool EmitOMPCopyinClause(const OMPExecutableDirective &D)
Emit code for copyin clause in D directive.
void EmitOMPLinearClause(const OMPLoopDirective &D, CodeGenFunction::OMPPrivateScope &PrivateScope)
Emit initial code for linear clauses.
llvm::BasicBlock * OMPBeforeScanBlock
void EmitOMPInterchangeDirective(const OMPInterchangeDirective &S)
void EmitOMPPrivateLoopCounters(const OMPLoopDirective &S, OMPPrivateScope &LoopScope)
Emit initial code for loop counters of loop-based directives.
void GenerateOpenMPCapturedVars(const CapturedStmt &S, SmallVectorImpl< llvm::Value * > &CapturedVars)
void EmitOMPDepobjDirective(const OMPDepobjDirective &S)
void EmitOMPMetaDirective(const OMPMetaDirective &S)
void EmitOMPCriticalDirective(const OMPCriticalDirective &S)
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
void EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S)
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
void EmitOMPCancelDirective(const OMPCancelDirective &S)
void EmitOMPBarrierDirective(const OMPBarrierDirective &S)
llvm::Value * EmitComplexToScalarConversion(ComplexPairTy Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified complex type to the specified destination type,...
bool EmitOMPWorksharingLoop(const OMPLoopDirective &S, Expr *EUB, const CodeGenLoopBoundsTy &CodeGenLoopBounds, const CodeGenDispatchBoundsTy &CGDispatchBounds)
Emit code for the worksharing loop-based directive.
LValue EmitOMPSharedLValue(const Expr *E)
Emits the lvalue for the expression with possibly captured variable.
llvm::CanonicalLoopInfo * EmitOMPCollapsedCanonicalLoopNest(const Stmt *S, int Depth)
Emit the Stmt S and return its topmost canonical loop, if any.
void EmitOMPSectionsDirective(const OMPSectionsDirective &S)
void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())
Emit code for the start of a function.
void EmitOMPInteropDirective(const OMPInteropDirective &S)
void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S)
void EmitOMPTargetParallelDirective(const OMPTargetParallelDirective &S)
void EmitOMPCopy(QualType OriginalType, Address DestAddr, Address SrcAddr, const VarDecl *DestVD, const VarDecl *SrcVD, const Expr *Copy)
Emit proper copying of data from one variable to another.
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
JumpDest getOMPCancelDestination(OpenMPDirectiveKind Kind)
void EmitOMPTargetParallelForSimdDirective(const OMPTargetParallelForSimdDirective &S)
void EmitOMPTargetParallelGenericLoopDirective(const OMPTargetParallelGenericLoopDirective &S)
Emit combined directive 'target parallel loop' as if its constituent constructs are 'target',...
void EmitOMPUseDeviceAddrClause(const OMPUseDeviceAddrClause &C, OMPPrivateScope &PrivateScope, const llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap)
void EmitOMPTeamsDistributeParallelForSimdDirective(const OMPTeamsDistributeParallelForSimdDirective &S)
void EmitOMPMaskedDirective(const OMPMaskedDirective &S)
llvm::Value * emitArrayLength(const ArrayType *arrayType, QualType &baseType, Address &addr)
emitArrayLength - Compute the length of an array, even if it's a VLA, and drill down to the base elem...
void EmitOMPAggregateAssign(Address DestAddr, Address SrcAddr, QualType OriginalType, const llvm::function_ref< void(Address, Address)> CopyGen)
Perform element by element copying of arrays with type OriginalType from SrcAddr to DestAddr using co...
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
void EmitOMPTeamsDistributeSimdDirective(const OMPTeamsDistributeSimdDirective &S)
RValue EmitAtomicLoad(LValue LV, SourceLocation SL, AggValueSlot Slot=AggValueSlot::ignored())
void EmitOMPOrderedBlockAssocDirective(const OMPOrderedBlockAssocDirective &S)
CGDebugInfo * getDebugInfo()
void EmitOMPDistributeLoop(const OMPLoopDirective &S, const CodeGenLoopTy &CodeGenLoop, Expr *IncExpr)
Emit code for the distribute loop-based directive.
void EmitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective &S)
void EmitOMPReverseDirective(const OMPReverseDirective &S)
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
void EmitOMPCancellationPointDirective(const OMPCancellationPointDirective &S)
void EmitOMPTargetTeamsDistributeParallelForDirective(const OMPTargetTeamsDistributeParallelForDirective &S)
void EmitOMPMaskedTaskLoopDirective(const OMPMaskedTaskLoopDirective &S)
llvm::BasicBlock * OMPScanDispatch
llvm::function_ref< std::pair< LValue, LValue >(CodeGenFunction &, const OMPExecutableDirective &S)> CodeGenLoopBoundsTy
void EmitOMPTargetExitDataDirective(const OMPTargetExitDataDirective &S)
RawAddress CreateMemTempWithoutCast(QualType T, const Twine &Name="tmp")
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen without...
void EmitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &S)
void EmitOMPMaskedTaskLoopSimdDirective(const OMPMaskedTaskLoopSimdDirective &S)
std::pair< bool, RValue > EmitOMPAtomicSimpleUpdateExpr(LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart, llvm::AtomicOrdering AO, SourceLocation Loc, const llvm::function_ref< RValue(RValue)> CommonGen)
Emit atomic update code for constructs: X = X BO E or X = E BO E.
VlaSizePair getVLASize(const VariableArrayType *vla)
Returns an LLVM value that corresponds to the size, in non-variably-sized elements,...
void EmitOMPParallelDirective(const OMPParallelDirective &S)
void EmitOMPTaskDirective(const OMPTaskDirective &S)
void EmitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective &S)
void EmitOMPDistributeParallelForDirective(const OMPDistributeParallelForDirective &S)
void EmitOMPAssumeDirective(const OMPAssumeDirective &S)
int ExpectedOMPLoopDepth
Number of nested loop to be consumed by the last surrounding loop-associated directive.
void EmitOMPPrivateClause(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
void EmitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &S)
ASTContext & getContext() const
void EmitStopPoint(const Stmt *S)
EmitStopPoint - Emit a debug stoppoint if we are emitting debug info.
void EmitOMPTargetUpdateDirective(const OMPTargetUpdateDirective &S)
llvm::Value * EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, AlignmentSource Source=AlignmentSource::Type, bool isNontemporal=false)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
void EmitOMPTargetTeamsGenericLoopDirective(const OMPTargetTeamsGenericLoopDirective &S)
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
void EmitAutoVarCleanups(const AutoVarEmission &emission)
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
SmallVector< llvm::CanonicalLoopInfo *, 4 > OMPLoopNestStack
List of recently emitted OMPCanonicalLoops.
Address EmitOMPBindingOriginalAddr(const BindingDecl *BD, SourceLocation Loc)
Emits the original address for a structured binding.
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)
LValue EmitOMPCapturedBindingLValue(const BindingDecl *BD)
Emit an LValue for a structured binding captured in an OpenMP region.
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 EmitOMPTeamsGenericLoopDirective(const OMPTeamsGenericLoopDirective &S)
void EmitOMPTargetSimdDirective(const OMPLoopDirective &S)
Also emits 'target loop'.
void EmitOMPOrderedStandaloneDirective(const OMPOrderedStandaloneDirective &S)
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
bool EmitOMPLinearClauseInit(const OMPLoopDirective &D)
Emit initial code for linear variables.
static void EmitOMPTargetParallelGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelGenericLoopDirective &S)
Emit device code for the target parallel loop directive.
void EmitOMPUnrollDirective(const OMPUnrollDirective &S)
void EmitOMPStripeDirective(const OMPStripeDirective &S)
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitOMPSingleDirective(const OMPSingleDirective &S)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
llvm::function_ref< void(CodeGenFunction &, SourceLocation, const unsigned, const bool)> CodeGenOrderedTy
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
llvm::Value * EmitFromMemory(llvm::Value *Value, QualType Ty)
EmitFromMemory - Change a scalar value from its memory representation to its value representation.
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.
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
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.
bool isConstant(const ASTContext &Ctx) const
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.
const T * getAs() const
Member-template getAs<specific type>'.
static UnaryOperator * Create(const ASTContext &C, Expr *input, Opcode opc, QualType type, ExprValueKind VK, ExprObjectKind OK, SourceLocation l, bool CanOverflow, FPOptionsOverride FPFeatures)
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
TLSKind getTLSKind() const
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
@ CInit
C-style initialization with assignment.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
const Expr * getInit() const
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
@ TLS_None
Not a TLS variable.
Represents a C array with a specified size that is not an integer-constant-expression.
Expr * getSizeExpr() const
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
@ Address
A pointer to a ValueDecl.
bool Inc(InterpState &S, CodePtr OpPC, bool CanOverflow)
1) Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value increased by ...
Top level wrappers for InstallAPI frontend operations.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool needsTaskBasedThreadLimit(OpenMPDirectiveKind DKind)
Checks if the specified target directive, combined or not, needs task based thread_limit.
@ Ctor_Complete
Complete object ctor.
Privates[]
This class represents the 'transparent' clause in the 'pragma omp task' directive.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
bool isOpenMPLoopTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive.
@ 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 or any taskloop-based dire...
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
bool isOpenMPGenericLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive constitutes a 'loop' directive in the outermost nest.
OpenMPBindClauseKind
OpenMP bindings for the 'bind' clause.
const FunctionProtoType * T
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
@ 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
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.
unsigned ignore_denormal_mode
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 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.
static void EmitCaptureStmt(CodeGenFunction &CGF, llvm::BasicBlock *CodeGenIPBB, llvm::BasicBlock &FiniBB, llvm::Function *Fn, ArrayRef< llvm::Value * > Args)
unsigned NumberOfTargetItems
Address BasePointersArray
llvm::PointerType * VoidPtrTy
llvm::IntegerType * Int64Ty
llvm::IntegerType * SizeTy
SmallVector< const Expr *, 4 > DepExprs
std::string getAsString() const
getAsString - Retrieve the human-readable string for this name.
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