31#include "llvm/ADT/SmallSet.h"
32#include "llvm/BinaryFormat/Dwarf.h"
33#include "llvm/Frontend/OpenMP/OMPConstants.h"
34#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
35#include "llvm/IR/Constants.h"
36#include "llvm/IR/DebugInfoMetadata.h"
37#include "llvm/IR/Instructions.h"
38#include "llvm/IR/IntrinsicInst.h"
39#include "llvm/IR/Metadata.h"
40#include "llvm/Support/AtomicOrdering.h"
41#include "llvm/Support/Debug.h"
45using namespace llvm::omp;
47#define TTL_CODEGEN_TYPE "target-teams-loop-codegen"
63 if (DKind == OMPD_teams_loop)
65 if (
const auto *TTLD = dyn_cast<OMPTargetTeamsGenericLoopDirective>(&S);
66 TTLD && !TTLD->canBeParallelFor())
72 S.hasClausesOfKind<OMPReductionClause>() &&
74 !S.getSingleClause<OMPScheduleClause>() &&
75 !S.getSingleClause<OMPOrderedClause>();
82 void emitPreInitStmt(CodeGenFunction &CGF,
const OMPExecutableDirective &S) {
83 for (
const auto *
C : S.clauses()) {
84 if (
const auto *CPI = OMPClauseWithPreInit::get(
C)) {
85 if (
const auto *PreInit =
86 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
87 for (
const auto *I : PreInit->decls()) {
88 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
91 CodeGenFunction::AutoVarEmission Emission =
100 CodeGenFunction::OMPPrivateScope InlinedShareds;
102 static bool isCapturedVar(CodeGenFunction &CGF,
const VarDecl *VD) {
111 CodeGenFunction &CGF,
const OMPExecutableDirective &S,
112 const std::optional<OpenMPDirectiveKind> CapturedRegion = std::nullopt,
113 const bool EmitPreInitStmt =
true)
115 InlinedShareds(CGF) {
117 emitPreInitStmt(CGF, S);
120 assert(S.hasAssociatedStmt() &&
121 "Expected associated statement for inlined directive.");
122 const CapturedStmt *CS = S.getCapturedStmt(*CapturedRegion);
124 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
125 auto *VD =
C.getCapturedVar();
127 "Canonical decl must be captured.");
131 InlinedShareds.isGlobalVarCaptured(VD)),
136 (void)InlinedShareds.Privatize();
142class OMPParallelScope final :
public OMPLexicalScope {
143 bool EmitPreInitStmt(
const OMPExecutableDirective &S) {
151 OMPParallelScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
152 : OMPLexicalScope(CGF, S, std::nullopt,
153 EmitPreInitStmt(S)) {}
158class OMPTeamsScope final :
public OMPLexicalScope {
159 bool EmitPreInitStmt(
const OMPExecutableDirective &S) {
166 OMPTeamsScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
167 : OMPLexicalScope(CGF, S, std::nullopt,
168 EmitPreInitStmt(S)) {}
174 void emitPreInitStmt(CodeGenFunction &CGF,
const OMPLoopBasedDirective &S) {
175 const Stmt *PreInits;
176 CodeGenFunction::OMPMapVars PreCondVars;
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);
218 PreInits = LD->getPreInits();
219 }
else if (
const auto *
Tile = dyn_cast<OMPTileDirective>(&S)) {
220 PreInits =
Tile->getPreInits();
221 }
else if (
const auto *Stripe = dyn_cast<OMPStripeDirective>(&S)) {
222 PreInits = Stripe->getPreInits();
223 }
else if (
const auto *Unroll = dyn_cast<OMPUnrollDirective>(&S)) {
224 PreInits = Unroll->getPreInits();
225 }
else if (
const auto *Reverse = dyn_cast<OMPReverseDirective>(&S)) {
226 PreInits = Reverse->getPreInits();
227 }
else if (
const auto *Split = dyn_cast<OMPSplitDirective>(&S)) {
228 PreInits =
Split->getPreInits();
229 }
else if (
const auto *Interchange =
230 dyn_cast<OMPInterchangeDirective>(&S)) {
231 PreInits = Interchange->getPreInits();
232 }
else if (
const auto *Flatten = dyn_cast<OMPFlattenDirective>(&S)) {
233 PreInits = Flatten->getPreInits();
235 llvm_unreachable(
"Unknown loop-based directive kind.");
237 doEmitPreinits(PreInits);
244 const Stmt *PreInits;
245 if (
const auto *Fuse = dyn_cast<OMPFuseDirective>(&S)) {
246 PreInits = Fuse->getPreInits();
249 "Unknown canonical loop sequence transform directive kind.");
251 doEmitPreinits(PreInits);
254 void doEmitPreinits(
const Stmt *PreInits) {
260 if (
auto *PreInitCompound = dyn_cast<CompoundStmt>(PreInits))
261 llvm::append_range(PreInitStmts, PreInitCompound->body());
263 PreInitStmts.push_back(PreInits);
265 for (
const Stmt *S : PreInitStmts) {
268 if (
auto *PreInitDecl = dyn_cast<DeclStmt>(S)) {
269 for (
Decl *I : PreInitDecl->decls())
281 emitPreInitStmt(CGF, S);
286 emitPreInitStmt(CGF, S);
291 CodeGenFunction::OMPPrivateScope InlinedShareds;
293 static bool isCapturedVar(CodeGenFunction &CGF,
const VarDecl *VD) {
301 OMPSimdLexicalScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
303 InlinedShareds(CGF) {
304 for (
const auto *
C : S.clauses()) {
305 if (const auto *CPI = OMPClauseWithPreInit::get(C)) {
306 if (const auto *PreInit =
307 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
308 for (const auto *I : PreInit->decls()) {
309 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
310 CGF.EmitVarDecl(cast<VarDecl>(*I));
312 CodeGenFunction::AutoVarEmission Emission =
313 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
314 CGF.EmitAutoVarCleanups(Emission);
318 }
else if (
const auto *UDP = dyn_cast<OMPUseDevicePtrClause>(
C)) {
319 for (
const Expr *E : UDP->varlist()) {
321 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
324 }
else if (
const auto *UDP = dyn_cast<OMPUseDeviceAddrClause>(
C)) {
325 for (
const Expr *E : UDP->varlist()) {
327 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
334 if (
const auto *TG = dyn_cast<OMPTaskgroupDirective>(&S)) {
335 if (
const Expr *E = TG->getReductionRef())
340 llvm::DenseSet<CanonicalDeclPtr<const Decl>> CopyArrayTemps;
341 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
342 if (C->getModifier() != OMPC_REDUCTION_inscan)
344 for (const Expr *E : C->copy_array_temps())
345 CopyArrayTemps.insert(cast<DeclRefExpr>(E)->getDecl());
347 const auto *CS = cast_or_null<CapturedStmt>(S.getAssociatedStmt());
350 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
351 auto *VD =
C.getCapturedVar();
352 if (CopyArrayTemps.contains(VD))
355 "Canonical decl must be captured.");
356 DeclRefExpr DRE(CGF.
getContext(),
const_cast<VarDecl *
>(VD),
357 isCapturedVar(CGF, VD) ||
359 InlinedShareds.isGlobalVarCaptured(VD)),
367 (void)InlinedShareds.Privatize();
378 if (Kind != OMPD_loop)
383 BindKind =
C->getBindKind();
386 case OMPC_BIND_parallel:
388 case OMPC_BIND_teams:
389 return OMPD_distribute;
390 case OMPC_BIND_thread:
417 if (
const auto *OrigDRE = dyn_cast<DeclRefExpr>(E)) {
418 if (
const auto *OrigVD = dyn_cast<VarDecl>(OrigDRE->getDecl())) {
419 OrigVD = OrigVD->getCanonicalDecl();
425 OrigDRE->getType(),
VK_LValue, OrigDRE->getExprLoc());
428 if (
const auto *OrigBD = dyn_cast<BindingDecl>(OrigDRE->getDecl())) {
435 IsCaptured, OrigDRE->getType(),
VK_LValue,
436 OrigDRE->getExprLoc());
445 llvm::Value *Size =
nullptr;
446 auto SizeInChars =
C.getTypeSizeInChars(Ty);
447 if (SizeInChars.isZero()) {
455 SizeInChars =
C.getTypeSizeInChars(Ty);
456 if (SizeInChars.isZero())
457 return llvm::ConstantInt::get(
SizeTy, 0);
458 return Builder.CreateNUWMul(Size,
CGM.getSize(SizeInChars));
460 return CGM.getSize(SizeInChars);
470 I != E; ++I, ++CurField, ++CurCap) {
471 if (CurField->hasCapturedVLAType()) {
474 CapturedVars.push_back(Val);
475 }
else if (CurCap->capturesThis()) {
476 CapturedVars.push_back(CXXThisValue);
477 }
else if (CurCap->capturesVariableByCopy()) {
482 if (!CurField->getType()->isAnyPointerType()) {
486 Twine(CurCap->getCapturedVar()->getName(),
".casted"));
502 CapturedVars.push_back(CV);
504 assert(CurCap->capturesVariable() &&
"Expected capture by reference.");
507 llvm::Type *ArgTy =
ConvertType(CurField->getType());
508 if (
Addr->getType() != ArgTy)
510 CapturedVars.push_back(
Addr);
530 if (
T->isLValueReferenceType())
531 return C.getLValueReferenceType(
534 if (
T->isPointerType())
536 if (
const ArrayType *A =
T->getAsArrayTypeUnsafe()) {
537 if (
const auto *VLA = dyn_cast<VariableArrayType>(A))
539 if (!A->isVariablyModifiedType())
540 return C.getCanonicalType(
T);
542 return C.getCanonicalParamType(
T);
547struct FunctionOptions {
549 const CapturedStmt *S =
nullptr;
552 const bool UIntPtrCastRequired =
true;
555 const bool RegisterCastedArgsOnly =
false;
557 const StringRef FunctionName;
560 const bool IsDeviceKernel =
false;
561 explicit FunctionOptions(
const CapturedStmt *S,
bool UIntPtrCastRequired,
562 bool RegisterCastedArgsOnly, StringRef FunctionName,
563 SourceLocation Loc,
bool IsDeviceKernel)
564 : S(S), UIntPtrCastRequired(UIntPtrCastRequired),
565 RegisterCastedArgsOnly(UIntPtrCastRequired && RegisterCastedArgsOnly),
566 FunctionName(FunctionName), Loc(Loc), IsDeviceKernel(IsDeviceKernel) {}
572 llvm::MapVector<
const Decl *, std::pair<const VarDecl *, Address>>
574 llvm::DenseMap<
const Decl *, std::pair<const Expr *, llvm::Value *>>
576 llvm::Value *&CXXThisValue,
const FunctionOptions &FO) {
579 assert(CD->
hasBody() &&
"missing CapturedDecl body");
581 CXXThisValue =
nullptr;
593 if (!FO.UIntPtrCastRequired) {
613 if (FO.UIntPtrCastRequired &&
614 ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) ||
615 I->capturesVariableArrayType()))
618 if (I->capturesVariable() || I->capturesVariableByCopy()) {
619 CapVar = I->getCapturedVar();
621 }
else if (I->capturesThis()) {
624 assert(I->capturesVariableArrayType());
627 if (ArgType->isVariablyModifiedType())
634 }
else if (DebugFunctionDecl && (CapVar || I->capturesThis())) {
636 Ctx, DebugFunctionDecl,
637 CapVar ? CapVar->
getBeginLoc() : FD->getBeginLoc(),
638 CapVar ? CapVar->
getLocation() : FD->getLocation(), II, ArgType,
644 Args.emplace_back(Arg);
646 TargetArgs.emplace_back(
647 FO.UIntPtrCastRequired
668 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
674 if (CGM.
getTriple().isSPIRV() && !FO.IsDeviceKernel)
675 F->setCallingConv(llvm::CallingConv::SPIR_FUNC);
678 F->setDoesNotThrow();
682 F->removeFnAttr(llvm::Attribute::NoInline);
683 F->addFnAttr(llvm::Attribute::AlwaysInline);
686 F->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
690 FO.UIntPtrCastRequired ? FO.Loc : FO.S->
getBeginLoc(),
691 FO.UIntPtrCastRequired ? FO.Loc
698 if (!FO.UIntPtrCastRequired && Args[Cnt] != TargetArgs[Cnt]) {
706 if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
707 const VarDecl *CurVD = I->getCapturedVar();
708 if (!FO.RegisterCastedArgsOnly)
709 LocalAddrs.insert({Args[Cnt], {CurVD, LocalAddr}});
717 if (FD->hasCapturedVLAType()) {
718 if (FO.UIntPtrCastRequired) {
721 Args[Cnt]->getName(), ArgLVal),
726 VLASizes.try_emplace(Args[Cnt], VAT->
getSizeExpr(), ExprArg);
727 }
else if (I->capturesVariable()) {
728 const VarDecl *Var = I->getCapturedVar();
730 Address ArgAddr = ArgLVal.getAddress();
731 if (ArgLVal.getType()->isLValueReferenceType()) {
734 assert(ArgLVal.getType()->isPointerType());
736 ArgAddr, ArgLVal.getType()->castAs<
PointerType>());
738 if (!FO.RegisterCastedArgsOnly) {
742 }
else if (I->capturesVariableByCopy()) {
743 assert(!FD->getType()->isAnyPointerType() &&
744 "Not expecting a captured pointer.");
745 const VarDecl *Var = I->getCapturedVar();
746 LocalAddrs.insert({Args[Cnt],
747 {Var, FO.UIntPtrCastRequired
749 CGF, I->getLocation(), FD->getType(),
750 Args[Cnt]->getName(), ArgLVal)
751 : ArgLVal.getAddress()}});
754 assert(I->capturesThis());
756 LocalAddrs.insert({Args[Cnt], {
nullptr, ArgLVal.getAddress()}});
767 llvm::MapVector<
const Decl *, std::pair<const VarDecl *, Address>>
769 llvm::DenseMap<
const Decl *, std::pair<const Expr *, llvm::Value *>>
771 llvm::Value *&CXXThisValue, llvm::Value *&ContextV,
const CapturedStmt &CS,
776 CXXThisValue =
nullptr;
786 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
790 F->setDoesNotThrow();
797 llvm::Type *PtrTy = CGF.
Builder.getPtrTy();
798 llvm::Align PtrAlign = CGM.
getDataLayout().getPointerABIAlignment(0);
801 for (
auto [FD,
C, FieldIdx] :
804 llvm::Value *SlotPtr =
805 CGF.
Builder.CreateConstInBoundsGEP1_32(PtrTy, ContextV, FieldIdx);
811 if (
C.capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
812 const VarDecl *CurVD =
C.getCapturedVar();
813 Slot->setName(CurVD->
getName());
814 Address SlotAddr(Slot, PtrTy, SlotAlign);
815 LocalAddrs.insert({FD, {CurVD, SlotAddr}});
816 }
else if (FD->hasCapturedVLAType()) {
823 VLASizes.try_emplace(FD, VAT->
getSizeExpr(), ExprArg);
824 }
else if (
C.capturesVariable()) {
825 const VarDecl *Var =
C.getCapturedVar();
829 Slot->setName(Var->
getName() +
".addr");
830 Address SlotAddr(Slot, PtrTy, SlotAlign);
831 LocalAddrs.insert({FD, {Var, SlotAddr}});
834 PtrTy, Slot, PtrAlign, Var->
getName());
835 LocalAddrs.insert({FD,
839 }
else if (
C.capturesVariableByCopy()) {
840 assert(!FD->getType()->isAnyPointerType() &&
841 "Not expecting a captured pointer.");
842 const VarDecl *Var =
C.getCapturedVar();
857 LocalAddrs.insert({FD, {Var, CopyAddr}});
859 assert(
C.capturesThis() &&
"Default case expected to be CXX 'this'");
862 Address SlotAddr(Slot, PtrTy, SlotAlign);
863 LocalAddrs.insert({FD, {
nullptr, SlotAddr}});
875 "CapturedStmtInfo should be set when generating the captured function");
878 bool NeedWrapperFunction =
881 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs,
883 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes,
886 llvm::raw_svector_ostream Out(Buffer);
889 bool IsDeviceKernel =
CGM.getOpenMPRuntime().isGPU() &&
891 D.getCapturedStmt(OMPD_target) == &S;
892 CodeGenFunction WrapperCGF(
CGM,
true);
893 llvm::Function *WrapperF =
nullptr;
894 if (NeedWrapperFunction) {
897 FunctionOptions WrapperFO(&S,
true,
904 WrapperCGF.CXXThisValue, WrapperFO);
907 FunctionOptions FO(&S, !NeedWrapperFunction,
false,
908 Out.str(), Loc, !NeedWrapperFunction && IsDeviceKernel);
910 *
this, WrapperArgs, WrapperLocalAddrs, WrapperVLASizes, CXXThisValue, FO);
912 for (
const auto &LocalAddrPair : WrapperLocalAddrs) {
913 if (LocalAddrPair.second.first) {
914 LocalScope.addPrivate(LocalAddrPair.second.first,
915 LocalAddrPair.second.second);
918 (void)LocalScope.Privatize();
919 for (
const auto &VLASizePair : WrapperVLASizes)
920 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
923 LocalScope.ForceCleanup();
925 if (!NeedWrapperFunction)
929 WrapperF->removeFromParent();
930 F->getParent()->getFunctionList().insertAfter(F->getIterator(), WrapperF);
933 auto *PI = F->arg_begin();
934 for (
const auto *Arg : Args) {
936 auto I = LocalAddrs.find(Arg);
937 if (I != LocalAddrs.end()) {
940 I->second.first ? I->second.first->getType() : Arg->getType(),
946 auto EI = VLASizes.find(Arg);
947 if (EI != VLASizes.end()) {
959 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
969 "CapturedStmtInfo should be set when generating the captured function");
973 bool NeedWrapperFunction =
976 CodeGenFunction WrapperCGF(
CGM,
true);
977 llvm::Function *WrapperF =
nullptr;
978 llvm::Value *WrapperContextV =
nullptr;
979 if (NeedWrapperFunction) {
982 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>>
984 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>>
987 WrapperCGF, WrapperArgs, WrapperLocalAddrs, WrapperVLASizes,
988 WrapperCGF.CXXThisValue, WrapperContextV, S, Loc, FunctionName);
992 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs;
993 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes;
996 if (NeedWrapperFunction) {
998 llvm::raw_svector_ostream Out(Buffer);
999 Out << FunctionName <<
"_debug__";
1001 FunctionOptions FO(&S,
false,
1002 false, Out.str(), Loc,
1007 llvm::Value *ContextV =
nullptr;
1009 CXXThisValue, ContextV, S, Loc,
1018 llvm::Align PtrAlign =
CGM.getDataLayout().getPointerABIAlignment(0);
1019 llvm::Value *SlotPtr =
Builder.CreateConstInBoundsGEP1_32(
1020 Builder.getPtrTy(), ContextV, FieldIdx,
1021 Twine(Param->getName()) +
".addr");
1022 llvm::Value *ParamAddr =
1023 Builder.CreateAlignedLoad(
Builder.getPtrTy(), SlotPtr, PtrAlign);
1024 llvm::Value *ParamVal =
Builder.CreateAlignedLoad(
1025 Builder.getPtrTy(), ParamAddr, PtrAlign, Param->getName());
1028 Builder.CreateStore(ParamVal, ParamLocalAddr);
1029 LocalAddrs.insert({Param, {Param, ParamLocalAddr}});
1035 for (
const auto &LocalAddrPair : LocalAddrs) {
1036 if (LocalAddrPair.second.first)
1037 LocalScope.addPrivate(LocalAddrPair.second.first,
1038 LocalAddrPair.second.second);
1040 (void)LocalScope.Privatize();
1041 for (
const auto &VLASizePair : VLASizes)
1042 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
1043 PGO->assignRegionCounters(
GlobalDecl(CD), F);
1045 (void)LocalScope.ForceCleanup();
1048 if (!NeedWrapperFunction)
1052 WrapperF->removeFromParent();
1053 F->getParent()->getFunctionList().insertAfter(F->getIterator(), WrapperF);
1055 llvm::Align PtrAlign =
CGM.getDataLayout().getPointerABIAlignment(0);
1058 "Expected context param at position 0 for target regions");
1059 assert(RD->
getNumFields() + 1 == F->getNumOperands() &&
1060 "Argument count mismatch");
1062 for (
auto [FD, InnerParam, SlotIdx] : llvm::zip(
1064 llvm::Value *SlotPtr = WrapperCGF.
Builder.CreateConstInBoundsGEP1_32(
1065 WrapperCGF.
Builder.getPtrTy(), WrapperContextV, SlotIdx);
1067 WrapperCGF.
Builder.getPtrTy(), SlotPtr, PtrAlign);
1069 InnerParam.getType(), Slot, PtrAlign, InnerParam.getName());
1070 CallArgs.push_back(Val);
1075 auto InnerParam = F->arg_begin() + SlotIdx;
1076 llvm::Value *SlotPtr = WrapperCGF.
Builder.CreateConstInBoundsGEP1_32(
1077 WrapperCGF.
Builder.getPtrTy(), WrapperContextV, SlotIdx);
1079 WrapperCGF.
Builder.getPtrTy(), SlotPtr, PtrAlign);
1081 InnerParam->getType(), Slot, PtrAlign, InnerParam->getName());
1082 CallArgs.push_back(Val);
1084 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
1100 llvm::Value *NumElements =
emitArrayLength(ArrayTy, ElementTy, DestAddr);
1107 DestBegin, NumElements);
1112 llvm::Value *IsEmpty =
1113 Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arraycpy.isempty");
1114 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
1117 llvm::BasicBlock *EntryBB =
Builder.GetInsertBlock();
1122 llvm::PHINode *SrcElementPHI =
1123 Builder.CreatePHI(SrcBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
1124 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
1129 llvm::PHINode *DestElementPHI =
Builder.CreatePHI(
1130 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
1131 DestElementPHI->addIncoming(DestBegin, EntryBB);
1137 CopyGen(DestElementCurrent, SrcElementCurrent);
1140 llvm::Value *DestElementNext =
1142 1,
"omp.arraycpy.dest.element");
1143 llvm::Value *SrcElementNext =
1145 1,
"omp.arraycpy.src.element");
1148 Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
1149 Builder.CreateCondBr(Done, DoneBB, BodyBB);
1150 DestElementPHI->addIncoming(DestElementNext,
Builder.GetInsertBlock());
1151 SrcElementPHI->addIncoming(SrcElementNext,
Builder.GetInsertBlock());
1161 const auto *BO = dyn_cast<BinaryOperator>(
Copy);
1162 if (BO && BO->getOpcode() == BO_Assign) {
1171 DestAddr, SrcAddr, OriginalType,
1199 bool DeviceConstTarget =
getLangOpts().OpenMPIsTargetDevice &&
1201 bool FirstprivateIsLastprivate =
false;
1202 llvm::SmallDenseMap<const Decl *, OpenMPLastprivateModifier> Lastprivates;
1203 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1204 for (
const auto *D :
C->varlist()) {
1209 llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
1214 bool MustEmitFirstprivateCopy =
1215 CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown;
1216 for (
const auto *
C : D.getClausesOfKind<OMPFirstprivateClause>()) {
1217 const auto *IRef =
C->varlist_begin();
1218 const auto *InitsRef =
C->inits().begin();
1219 for (
const Expr *IInit :
C->private_copies()) {
1223 if (
const auto *BD = dyn_cast<BindingDecl>(OrigDecl)) {
1225 bool ThisFirstprivateIsLastprivate =
1226 Lastprivates.count(BD->getCanonicalDecl()) > 0;
1230 if (!MustEmitFirstprivateCopy && !ThisFirstprivateIsLastprivate) {
1232 if (!FD->getType()->isReferenceType()) {
1235 assert(IsRegistered &&
1236 "firstprivate var already registered as firstprivate");
1244 const auto *VDInit =
1251 if (
Type->isArrayType()) {
1266 RunCleanupsScope InitScope(*this);
1268 setAddrOfLocalVar(VDInit, SrcElement);
1269 EmitAnyExprToMem(Init, DestElement,
1270 Init->getType().getQualifiers(),
1272 LocalDeclMap.erase(VDInit);
1281 setAddrOfLocalVar(VDInit, OriginalAddr);
1283 LocalDeclMap.erase(VDInit);
1286 IsRegistered = PrivateScope.
addPrivate(BD, VDAddr);
1289 assert(IsRegistered &&
1290 "firstprivate var already registered as firstprivate");
1292 FirstprivateIsLastprivate =
1293 FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate;
1300 const VarDecl *OrigVD = dyn_cast<VarDecl>(OrigDecl);
1301 assert(OrigVD &&
"Expected VarDecl for non-BindingDecl firstprivate");
1302 bool ThisFirstprivateIsLastprivate =
1305 if (!MustEmitFirstprivateCopy && !ThisFirstprivateIsLastprivate && FD &&
1307 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
1317 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
1323 FirstprivateIsLastprivate =
1324 FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate;
1326 const auto *VDInit =
1345 assert(!CE &&
"Expected non-constant firstprivate.");
1352 if (
Type->isArrayType()) {
1368 RunCleanupsScope InitScope(*this);
1370 setAddrOfLocalVar(VDInit, SrcElement);
1371 EmitAnyExprToMem(Init, DestElement,
1372 Init->getType().getQualifiers(),
1374 LocalDeclMap.erase(VDInit);
1385 setAddrOfLocalVar(VDInit, OriginalAddr);
1387 LocalDeclMap.erase(VDInit);
1389 if (ThisFirstprivateIsLastprivate &&
1391 OMPC_LASTPRIVATE_conditional) {
1396 (*IRef)->getExprLoc());
1397 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1401 LocalDeclMap.erase(VD);
1402 setAddrOfLocalVar(VD, VDAddr);
1404 IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1406 assert(IsRegistered &&
1407 "firstprivate var already registered as private");
1415 return FirstprivateIsLastprivate && !EmittedAsFirstprivate.empty();
1423 llvm::SmallDenseSet<const ValueDecl *> EmittedAsPrivate;
1424 for (
const auto *
C : D.getClausesOfKind<OMPPrivateClause>()) {
1425 auto IRef =
C->varlist_begin();
1426 for (
const Expr *IInit :
C->private_copies()) {
1429 if (EmittedAsPrivate.insert(
cast<ValueDecl>(OrigDecl->getCanonicalDecl()))
1434 assert(IsRegistered &&
"private var already registered as private");
1449 llvm::DenseSet<const VarDecl *> CopiedVars;
1450 llvm::BasicBlock *CopyBegin =
nullptr, *CopyEnd =
nullptr;
1452 auto IRef =
C->varlist_begin();
1453 auto ISrcRef =
C->source_exprs().begin();
1454 auto IDestRef =
C->destination_exprs().begin();
1455 for (
const Expr *AssignOp :
C->assignment_ops()) {
1464 getContext().getTargetInfo().isTLSSupported()) {
1466 "Copyin threadprivates should have been captured!");
1470 LocalDeclMap.erase(VD);
1474 :
CGM.GetAddrOfGlobal(VD),
1475 CGM.getTypes().ConvertTypeForMem(VD->
getType()),
1480 if (CopiedVars.size() == 1) {
1486 auto *MasterAddrInt =
Builder.CreatePtrToInt(
1488 auto *PrivateAddrInt =
Builder.CreatePtrToInt(
1491 Builder.CreateICmpNE(MasterAddrInt, PrivateAddrInt), CopyBegin,
1497 const auto *DestVD =
1518 bool HasAtLeastOneLastprivate =
false;
1520 llvm::DenseSet<const VarDecl *> SIMDLCVs;
1523 for (
const Expr *
C : LoopDirective->counters()) {
1528 llvm::SmallDenseSet<const ValueDecl *> AlreadyEmittedVars;
1529 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1530 HasAtLeastOneLastprivate =
true;
1533 const auto *IRef =
C->varlist_begin();
1534 const auto *IDestRef =
C->destination_exprs().begin();
1535 for (
const Expr *IInit :
C->private_copies()) {
1540 if (
const auto *BD = dyn_cast<BindingDecl>(OrigDecl)) {
1541 if (AlreadyEmittedVars.insert(
cast<ValueDecl>(BD->getCanonicalDecl()))
1543 const auto *DestVD =
1555 bool IsRegistered = PrivateScope.
addPrivate(BD, VDAddr);
1556 assert(IsRegistered &&
1557 "lastprivate binding already registered as private");
1568 if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) {
1569 const auto *DestVD =
1574 (*IRef)->getType(),
VK_LValue, (*IRef)->getExprLoc());
1579 if (IInit && !SIMDLCVs.count(OrigVD->getCanonicalDecl())) {
1582 if (
C->getKind() == OMPC_LASTPRIVATE_conditional) {
1583 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1585 setAddrOfLocalVar(VD, VDAddr);
1591 bool IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1592 assert(IsRegistered &&
1593 "lastprivate var already registered as private");
1601 return HasAtLeastOneLastprivate;
1606 llvm::Value *IsLastIterCond) {
1615 llvm::BasicBlock *ThenBB =
nullptr;
1616 llvm::BasicBlock *DoneBB =
nullptr;
1617 if (IsLastIterCond) {
1621 llvm::any_of(D.getClausesOfKind<OMPLastprivateClause>(),
1622 [](
const OMPLastprivateClause *
C) {
1623 return C->getKind() == OMPC_LASTPRIVATE_conditional;
1625 CGM.getOpenMPRuntime().emitBarrierCall(*
this, D.getBeginLoc(),
1632 Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB);
1635 llvm::DenseSet<const ValueDecl *> AlreadyEmittedVars;
1636 llvm::SmallDenseMap<const VarDecl *, const Expr *> LoopCountersAndUpdates;
1637 if (
const auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) {
1638 auto IC = LoopDirective->counters().begin();
1639 for (
const Expr *F : LoopDirective->finals()) {
1643 AlreadyEmittedVars.insert(D);
1645 LoopCountersAndUpdates[D] = F;
1649 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1650 auto IRef =
C->varlist_begin();
1651 auto ISrcRef =
C->source_exprs().begin();
1652 auto IDestRef =
C->destination_exprs().begin();
1653 for (
const Expr *AssignOp :
C->assignment_ops()) {
1658 const VarDecl *PrivateVD =
nullptr;
1660 if ((BD = dyn_cast<BindingDecl>(PrivateDecl))) {
1665 if (LocalDeclMap.count(SrcVD)) {
1668 }
else if (OMPPrivatizedBindings.count(BD)) {
1677 const auto *CanonicalVD =
1683 .insert(PrivateVD ?
static_cast<const ValueDecl *
>(CanonicalVD)
1691 if (
const Expr *FinalExpr =
1692 LoopCountersAndUpdates.lookup(CanonicalVD))
1697 const auto *DestVD =
1705 auto It = OMPPrivatizedBindings.find(BD);
1706 assert(It != OMPPrivatizedBindings.end() &&
1707 "BindingDecl should be privatized");
1708 PrivateAddr = It->second;
1713 Builder.CreateLoad(PrivateAddr),
1714 CGM.getTypes().ConvertTypeForMem(RefTy->getPointeeType()),
1715 CGM.getNaturalTypeAlignment(RefTy->getPointeeType()));
1718 if (
C->getKind() == OMPC_LASTPRIVATE_conditional)
1719 CGM.getOpenMPRuntime().emitLastprivateConditionalFinalUpdate(
1721 (*IRef)->getExprLoc());
1724 EmitOMPCopy(
Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp);
1730 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
1750 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1751 if (ForInscan != (
C->getModifier() == OMPC_REDUCTION_inscan))
1753 Shareds.append(
C->varlist_begin(),
C->varlist_end());
1754 Privates.append(
C->privates().begin(),
C->privates().end());
1755 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1756 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1757 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1758 if (
C->getModifier() == OMPC_REDUCTION_task) {
1759 Data.ReductionVars.append(
C->privates().begin(),
C->privates().end());
1760 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
1761 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
1762 Data.ReductionOps.append(
C->reduction_ops().begin(),
1763 C->reduction_ops().end());
1764 TaskLHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1765 TaskRHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1770 auto *ILHS = LHSs.begin();
1771 auto *IRHS = RHSs.begin();
1773 for (
const Expr *IRef : Shareds) {
1780 [&Emission](CodeGenFunction &CGF) {
1781 CGF.EmitAutoVarInit(Emission);
1789 assert(IsRegistered &&
"private var already registered as private");
1797 if (isaOMPArraySectionExpr &&
Type->isVariablyModifiedType()) {
1802 }
else if ((isaOMPArraySectionExpr &&
Type->isScalarType()) ||
1820 PrivateScope.
addPrivate(LHSVD, OriginalAddr);
1831 if (!
Data.ReductionVars.empty()) {
1833 Data.IsReductionWithTaskMod =
true;
1835 llvm::Value *ReductionDesc =
CGM.getOpenMPRuntime().emitTaskReductionInit(
1836 *
this, D.getBeginLoc(), TaskLHSs, TaskRHSs,
Data);
1837 const Expr *TaskRedRef =
nullptr;
1848 case OMPD_parallel_for:
1851 case OMPD_parallel_master:
1855 case OMPD_parallel_sections:
1859 case OMPD_target_parallel:
1863 case OMPD_target_parallel_for:
1867 case OMPD_distribute_parallel_for:
1871 case OMPD_teams_distribute_parallel_for:
1873 .getTaskReductionRefExpr();
1875 case OMPD_target_teams_distribute_parallel_for:
1877 .getTaskReductionRefExpr();
1885 case OMPD_parallel_for_simd:
1887 case OMPD_taskyield:
1891 case OMPD_taskgroup:
1895 case OMPD_ordered_standalone:
1896 case OMPD_ordered_blockassoc:
1900 case OMPD_cancellation_point:
1902 case OMPD_target_data:
1903 case OMPD_target_enter_data:
1904 case OMPD_target_exit_data:
1906 case OMPD_taskloop_simd:
1907 case OMPD_master_taskloop:
1908 case OMPD_master_taskloop_simd:
1909 case OMPD_parallel_master_taskloop:
1910 case OMPD_parallel_master_taskloop_simd:
1911 case OMPD_distribute:
1912 case OMPD_target_update:
1913 case OMPD_distribute_parallel_for_simd:
1914 case OMPD_distribute_simd:
1915 case OMPD_target_parallel_for_simd:
1916 case OMPD_target_simd:
1917 case OMPD_teams_distribute:
1918 case OMPD_teams_distribute_simd:
1919 case OMPD_teams_distribute_parallel_for_simd:
1920 case OMPD_target_teams:
1921 case OMPD_target_teams_distribute:
1922 case OMPD_target_teams_distribute_parallel_for_simd:
1923 case OMPD_target_teams_distribute_simd:
1924 case OMPD_declare_target:
1925 case OMPD_end_declare_target:
1926 case OMPD_threadprivate:
1928 case OMPD_declare_reduction:
1929 case OMPD_declare_mapper:
1930 case OMPD_declare_simd:
1932 case OMPD_declare_variant:
1933 case OMPD_begin_declare_variant:
1934 case OMPD_end_declare_variant:
1937 llvm_unreachable(
"Unexpected directive with task reductions.");
1943 false, TaskRedRef->
getType());
1956 bool HasAtLeastOneReduction =
false;
1957 bool IsReductionWithTaskMod =
false;
1958 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1960 if (
C->getModifier() == OMPC_REDUCTION_inscan)
1962 HasAtLeastOneReduction =
true;
1963 Privates.append(
C->privates().begin(),
C->privates().end());
1964 LHSExprs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1965 RHSExprs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1966 IsPrivateVarReduction.append(
C->private_var_reduction_flags().begin(),
1967 C->private_var_reduction_flags().end());
1968 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1969 IsReductionWithTaskMod =
1970 IsReductionWithTaskMod ||
C->getModifier() == OMPC_REDUCTION_task;
1972 if (HasAtLeastOneReduction) {
1974 if (IsReductionWithTaskMod) {
1975 CGM.getOpenMPRuntime().emitTaskReductionFini(
1978 bool TeamsLoopCanBeParallel =
false;
1979 if (
auto *TTLD = dyn_cast<OMPTargetTeamsGenericLoopDirective>(&D))
1980 TeamsLoopCanBeParallel = TTLD->canBeParallelFor();
1981 bool WithNowait = D.getSingleClause<OMPNowaitClause>() ||
1983 TeamsLoopCanBeParallel || ReductionKind == OMPD_simd;
1984 bool SimpleReduction = ReductionKind == OMPD_simd;
1987 CGM.getOpenMPRuntime().emitReduction(
1988 *
this, D.getEndLoc(),
Privates, LHSExprs, RHSExprs, ReductionOps,
1989 {WithNowait, SimpleReduction, IsPrivateVarReduction, ReductionKind});
1998 llvm::BasicBlock *DoneBB =
nullptr;
1999 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
2000 if (
const Expr *PostUpdate =
C->getPostUpdateExpr()) {
2002 if (llvm::Value *Cond = CondGen(CGF)) {
2007 CGF.
Builder.CreateCondBr(Cond, ThenBB, DoneBB);
2023 const OMPExecutableDirective &,
2024 llvm::SmallVectorImpl<llvm::Value *> &)>
2025 CodeGenBoundParametersTy;
2033 llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> PrivateDecls;
2034 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
2035 for (
const Expr *Ref :
C->varlist()) {
2036 if (!Ref->getType()->isScalarType())
2038 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
2042 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
2045 PrivateDecls.insert(VD);
2049 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
2050 for (
const Expr *Ref :
C->varlist()) {
2051 if (!Ref->getType()->isScalarType())
2053 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
2058 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
2059 PrivateDecls.insert(VD);
2064 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
2065 for (
const Expr *Ref :
C->varlist()) {
2066 if (!Ref->getType()->isScalarType())
2068 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
2071 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
2072 PrivateDecls.insert(VD);
2081 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
2082 for (
const Expr *Ref :
C->varlist()) {
2083 if (!Ref->getType()->isScalarType())
2085 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
2089 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
2090 PrivateDecls.insert(VD);
2094 CGF, S, PrivateDecls);
2100 const CodeGenBoundParametersTy &CodeGenBoundParameters) {
2101 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
2102 llvm::Value *NumThreads =
nullptr;
2111 llvm::Function *OutlinedFn =
2118 NumThreads = CGF.
EmitScalarExpr(NumThreadsClause->getNumThreads().front(),
2120 Modifier = NumThreadsClause->getPrescriptivenessModifier();
2121 if (
const auto *MessageClause = S.getSingleClause<OMPMessageClause>()) {
2122 Message = MessageClause->getMessageString();
2123 MessageLoc = MessageClause->getBeginLoc();
2125 if (
const auto *SeverityClause = S.getSingleClause<OMPSeverityClause>()) {
2126 Severity = SeverityClause->getSeverityKind();
2127 SeverityLoc = SeverityClause->getBeginLoc();
2130 CGF, NumThreads, NumThreadsClause->getBeginLoc(), Modifier, Severity,
2131 SeverityLoc, Message, MessageLoc);
2133 if (
const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>()) {
2136 CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getBeginLoc());
2138 const Expr *IfCond =
nullptr;
2139 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
2140 if (
C->getNameModifier() == OMPD_unknown ||
2141 C->getNameModifier() == OMPD_parallel) {
2142 IfCond =
C->getCondition();
2147 OMPParallelScope
Scope(CGF, S);
2153 CodeGenBoundParameters(CGF, S, CapturedVars);
2156 CapturedVars, IfCond, NumThreads,
2157 Modifier, Severity, Message);
2162 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
2164 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
2166 return !((AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc ||
2167 AA->getAllocatorType() == OMPAllocateDeclAttr::OMPNullMemAlloc) &&
2168 !AA->getAllocator());
2183 CGF, S.getBeginLoc(), OMPD_unknown,
false,
2189 CodeGenFunction &CGF,
const VarDecl *VD) {
2191 auto &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2203 Size = CGF.
Builder.CreateNUWAdd(
2205 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
2206 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
2212 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
2213 assert(AA->getAllocator() &&
2214 "Expected allocator expression for non-default allocator.");
2218 if (Allocator->getType()->isIntegerTy())
2219 Allocator = CGF.
Builder.CreateIntToPtr(Allocator,
CGM.VoidPtrTy);
2220 else if (Allocator->getType()->isPointerTy())
2224 llvm::Value *
Addr = OMPBuilder.createOMPAlloc(
2227 llvm::CallInst *FreeCI =
2228 OMPBuilder.createOMPFree(CGF.
Builder,
Addr, Allocator);
2242 if (
CGM.getLangOpts().OpenMPUseTLS &&
2243 CGM.getContext().getTargetInfo().isTLSSupported())
2246 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2251 llvm::ConstantInt *Size =
CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy));
2253 llvm::Twine CacheName = Twine(
CGM.getMangledName(VD)).concat(Suffix);
2255 llvm::CallInst *ThreadPrivateCacheCall =
2256 OMPBuilder.createCachedThreadPrivate(CGF.
Builder,
Data, Size, CacheName);
2264 llvm::raw_svector_ostream OS(Buffer);
2265 StringRef Sep = FirstSeparator;
2266 for (StringRef Part : Parts) {
2270 return OS.str().str();
2278 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
2279 "." + RegionName +
".after");
2286 if (
Builder.saveIP().isValid())
2295 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
2296 "." + RegionName +
".after");
2303 if (
Builder.saveIP().isValid())
2308 if (
CGM.getLangOpts().OpenMPIRBuilder) {
2309 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2311 llvm::Value *IfCond =
nullptr;
2316 llvm::Value *NumThreads =
nullptr;
2318 NumThreads =
EmitScalarExpr(NumThreadsClause->getNumThreads().front(),
2321 ProcBindKind ProcBind = OMP_PROC_BIND_default;
2322 if (
const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>())
2323 ProcBind = ProcBindClause->getProcBindKind();
2325 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2329 auto FiniCB = [
this](InsertPointTy IP) {
2331 return llvm::Error::success();
2338 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
2339 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
2350 auto BodyGenCB = [&,
this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
2353 *
this, ParallelRegionBodyStmt, AllocIP, CodeGenIP,
"parallel");
2354 return llvm::Error::success();
2359 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
2361 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2362 cantFail(OMPBuilder.createParallel(
2363 Builder, AllocaIP, {}, BodyGenCB, PrivCB, FiniCB,
2364 IfCond, NumThreads, ProcBind, S.hasCancel()));
2378 CGF.
EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt());
2387 [](CodeGenFunction &) {
return nullptr; });
2399class OMPTransformDirectiveScopeRAII {
2400 OMPLoopScope *
Scope =
nullptr;
2404 OMPTransformDirectiveScopeRAII(
const OMPTransformDirectiveScopeRAII &) =
2406 OMPTransformDirectiveScopeRAII &
2407 operator=(
const OMPTransformDirectiveScopeRAII &) =
delete;
2411 if (
const auto *Dir = dyn_cast<OMPLoopBasedDirective>(S)) {
2412 Scope =
new OMPLoopScope(CGF, *Dir);
2415 }
else if (
const auto *Dir =
2416 dyn_cast<OMPCanonicalLoopSequenceTransformationDirective>(
2421 Scope =
new OMPLoopScope(CGF, *Dir);
2426 ~OMPTransformDirectiveScopeRAII() {
2437 int MaxLevel,
int Level = 0) {
2438 assert(Level < MaxLevel &&
"Too deep lookup during loop body codegen.");
2440 if (
const auto *CS = dyn_cast<CompoundStmt>(SimplifiedS)) {
2443 "LLVM IR generation of compound statement ('{}')");
2447 for (
const Stmt *CurStmt : CS->body())
2448 emitBody(CGF, CurStmt, NextLoop, MaxLevel, Level);
2455 if (SimplifiedS == OMPLoopBasedDirective::ignoreIntraTileHint(NextLoop)) {
2456 if (
auto *Dir = dyn_cast<OMPLoopTransformationDirective>(SimplifiedS))
2457 SimplifiedS = Dir->getTransformedStmt();
2458 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(SimplifiedS))
2459 SimplifiedS = CanonLoop->getLoopStmt();
2460 if (
const auto *For = dyn_cast<ForStmt>(SimplifiedS)) {
2464 "Expected canonical for loop or range-based for loop.");
2466 CGF.
EmitStmt(CXXFor->getLoopVarStmt());
2467 S = CXXFor->getBody();
2469 if (Level + 1 < MaxLevel) {
2470 NextLoop = OMPLoopDirective::tryToFindNextInnerLoop(
2472 emitBody(CGF, S, NextLoop, MaxLevel, Level + 1);
2490 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2491 for (
const Expr *UE :
C->updates())
2498 BreakContinueStack.push_back(BreakContinue(D,
LoopExit, Continue));
2512 bool IsInscanRegion = InscanScope.
Privatize();
2513 if (IsInscanRegion) {
2523 if (EKind != OMPD_simd && !
getLangOpts().OpenMPSimd)
2532 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
2535 OMPLoopBasedDirective::tryToFindNextInnerLoop(
2537 D.getLoopsNumber());
2545 BreakContinueStack.pop_back();
2556 std::unique_ptr<CodeGenFunction::CGCapturedStmtInfo> CSI =
2557 std::make_unique<CodeGenFunction::CGCapturedStmtInfo>(*S);
2561 return {F, CapStruct.getPointer(
ParentCGF)};
2565static llvm::CallInst *
2570 EffectiveArgs.reserve(Args.size() + 1);
2571 llvm::append_range(EffectiveArgs, Args);
2572 EffectiveArgs.push_back(Cap.second);
2577llvm::CanonicalLoopInfo *
2579 assert(Depth == 1 &&
"Nested loops with OpenMPIRBuilder not yet implemented");
2605 const Stmt *SyntacticalLoop = S->getLoopStmt();
2616 const Stmt *BodyStmt;
2617 if (
const auto *For = dyn_cast<ForStmt>(SyntacticalLoop)) {
2618 if (
const Stmt *InitStmt = For->getInit())
2620 BodyStmt = For->getBody();
2621 }
else if (
const auto *RangeFor =
2622 dyn_cast<CXXForRangeStmt>(SyntacticalLoop)) {
2623 if (
const DeclStmt *RangeStmt = RangeFor->getRangeStmt())
2625 if (
const DeclStmt *BeginStmt = RangeFor->getBeginStmt())
2627 if (
const DeclStmt *EndStmt = RangeFor->getEndStmt())
2629 if (
const DeclStmt *LoopVarStmt = RangeFor->getLoopVarStmt())
2631 BodyStmt = RangeFor->getBody();
2633 llvm_unreachable(
"Expected for-stmt or range-based for-stmt");
2636 const CapturedStmt *DistanceFunc = S->getDistanceFunc();
2649 llvm::Value *DistVal =
Builder.CreateLoad(CountAddr,
".count");
2652 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2653 auto BodyGen = [&,
this](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP,
2654 llvm::Value *IndVar) {
2659 const DeclRefExpr *LoopVarRef = S->getLoopVarRef();
2667 return llvm::Error::success();
2670 llvm::CanonicalLoopInfo *
CL =
2671 cantFail(OMPBuilder.createCanonicalLoop(
Builder, BodyGen, DistVal));
2683 const Expr *IncExpr,
2684 const llvm::function_ref<
void(CodeGenFunction &)> BodyGen,
2685 const llvm::function_ref<
void(CodeGenFunction &)> PostIncGen) {
2695 const CapturedStmt *ICS = OMPED.getInnermostCapturedStmt();
2709 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
2710 if (RequiresCleanup)
2717 if (ExitBlock !=
LoopExit.getBlock()) {
2727 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
2735 BreakContinueStack.pop_back();
2746 bool HasLinears =
false;
2747 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2751 if (
const auto *Ref =
2774 if (
const auto *CS = cast_or_null<BinaryOperator>(
C->getCalcStep()))
2786 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2789 llvm::BasicBlock *DoneBB =
nullptr;
2791 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2792 auto IC =
C->varlist_begin();
2793 for (
const Expr *F :
C->finals()) {
2795 if (llvm::Value *Cond = CondGen(*
this)) {
2800 Builder.CreateCondBr(Cond, ThenBB, DoneBB);
2806 if (
const auto *BD = dyn_cast<BindingDecl>(OrigDecl)) {
2812 (*IC)->getType(),
VK_LValue, (*IC)->getExprLoc());
2821 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
2833 llvm::APInt ClauseAlignment(64, 0);
2834 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
2837 ClauseAlignment = AlignmentCI->getValue();
2839 for (
const Expr *E : Clause->varlist()) {
2840 llvm::APInt Alignment(ClauseAlignment);
2841 if (Alignment == 0) {
2848 E->getType()->getPointeeType()))
2851 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2852 "alignment is not power of 2");
2853 if (Alignment != 0) {
2874 LocalDeclMap.erase(PrivateVD);
2880 E->getType(),
VK_LValue, E->getExprLoc());
2888 for (
const auto *
C : S.getClausesOfKind<OMPOrderedClause>()) {
2889 if (!
C->getNumForLoops())
2891 for (
unsigned I = S.getLoopsNumber(), E =
C->getLoopNumIterations().size();
2897 if (DRE->refersToEnclosingVariableOrCapture()) {
2906 const Expr *Cond, llvm::BasicBlock *TrueBlock,
2907 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
2925 assert(!E->getType().getNonReferenceType()->isRecordType() &&
2926 "dependent counter must not be an iterator.");
2930 (void)PreCondVars.
setVarAddr(CGF, VD, CounterAddr);
2932 (void)PreCondVars.
apply(CGF);
2947 llvm::DenseSet<const VarDecl *> SIMDLCVs;
2951 for (
const Expr *
C : LoopDirective->counters()) {
2956 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2957 auto CurPrivate =
C->privates().begin();
2958 for (
const Expr *E :
C->varlist()) {
2960 const auto *PrivateVD =
2962 bool IsSIMDLCV =
false;
2963 if (
const auto *VarD = dyn_cast<VarDecl>(VD))
2964 IsSIMDLCV = SIMDLCVs.count(VarD->getCanonicalDecl());
2969 bool IsRegistered = PrivateScope.
addPrivate(VD, PrivateAddr);
2970 assert(IsRegistered &&
"linear var already registered as private");
3058 if (
const auto *CS = dyn_cast<CapturedStmt>(S))
3076 if (HasOrderedDirective)
3084 const Stmt *AssociatedStmt = D.getAssociatedStmt();
3088 if (
C->getKind() == OMPC_ORDER_concurrent)
3091 if ((EKind == OMPD_simd ||
3093 llvm::any_of(D.getClausesOfKind<OMPReductionClause>(),
3094 [](
const OMPReductionClause *
C) {
3095 return C->getModifier() == OMPC_REDUCTION_inscan;
3103 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
3106 llvm::BasicBlock *DoneBB =
nullptr;
3112 const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
3114 OrigVD->hasGlobalStorage() || CED) {
3116 if (llvm::Value *Cond = CondGen(*
this)) {
3121 Builder.CreateCondBr(Cond, ThenBB, DoneBB);
3164 auto &&ThenGen = [&S, &SimdInitGen, &BodyCodeGen](
CodeGenFunction &CGF,
3178 const Expr *IfCond =
nullptr;
3181 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
3183 (
C->getNameModifier() == OMPD_unknown ||
3184 C->getNameModifier() == OMPD_simd)) {
3185 IfCond =
C->getCondition();
3201 OMPLoopScope PreInitScope(CGF, S);
3223 llvm::BasicBlock *ContBlock =
nullptr;
3275 emitOMPLoopBodyWithStopPoint(CGF, S,
3276 CodeGenFunction::JumpDest());
3282 if (HasLastprivateClause)
3311 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(S.getRawStmt())) {
3312 if (
const Stmt *SyntacticalLoop = CanonLoop->getLoopStmt()) {
3313 for (
const Stmt *SubStmt : SyntacticalLoop->
children()) {
3316 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(SubStmt)) {
3331static llvm::MapVector<llvm::Value *, llvm::Value *>
3333 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars;
3335 llvm::APInt ClauseAlignment(64, 0);
3336 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
3339 ClauseAlignment = AlignmentCI->getValue();
3341 for (
const Expr *E : Clause->varlist()) {
3342 llvm::APInt Alignment(ClauseAlignment);
3343 if (Alignment == 0) {
3350 E->getType()->getPointeeType()))
3353 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
3354 "alignment is not power of 2");
3356 AlignedVars[PtrValue] = CGF.
Builder.getInt64(Alignment.getSExtValue());
3366 bool UseOMPIRBuilder =
3368 if (UseOMPIRBuilder) {
3372 if (UseOMPIRBuilder) {
3373 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars =
3376 const Stmt *Inner = S.getRawStmt();
3377 llvm::CanonicalLoopInfo *CLI =
3378 CGF.EmitOMPCollapsedCanonicalLoopNest(Inner, 1);
3380 llvm::OpenMPIRBuilder &OMPBuilder =
3383 llvm::ConstantInt *Simdlen =
nullptr;
3390 llvm::ConstantInt *Safelen =
nullptr;
3397 llvm::omp::OrderKind Order = llvm::omp::OrderKind::OMP_ORDER_unknown;
3399 if (
C->getKind() == OpenMPOrderClauseKind::OMPC_ORDER_concurrent) {
3400 Order = llvm::omp::OrderKind::OMP_ORDER_concurrent;
3405 OMPBuilder.applySimd(CLI, AlignedVars,
3406 nullptr, Order, Simdlen, Safelen);
3413 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
3428 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
3441 OMPTransformDirectiveScopeRAII TileScope(*
this, &S);
3447 OMPTransformDirectiveScopeRAII StripeScope(*
this, &S);
3453 OMPTransformDirectiveScopeRAII ReverseScope(*
this, &S);
3459 OMPTransformDirectiveScopeRAII SplitScope(*
this, &S);
3466 OMPTransformDirectiveScopeRAII InterchangeScope(*
this, &S);
3472 OMPTransformDirectiveScopeRAII FlattenScope(*
this, &S);
3479 OMPTransformDirectiveScopeRAII FuseScope(*
this, &S);
3484 bool UseOMPIRBuilder =
CGM.getLangOpts().OpenMPIRBuilder;
3486 if (UseOMPIRBuilder) {
3488 const Stmt *Inner = S.getRawStmt();
3496 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
3499 llvm::CanonicalLoopInfo *UnrolledCLI =
nullptr;
3503 OMPBuilder.unrollLoopFull(DL, CLI);
3505 uint64_t Factor = 0;
3506 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3508 FactorExpr->EvaluateKnownConstInt(
getContext()).getLimitedValue();
3509 assert(Factor >= 1 &&
"Only positive factors are valid");
3511 OMPBuilder.unrollLoopPartial(DL, CLI, Factor,
3512 NeedsUnrolledCLI ? &UnrolledCLI :
nullptr);
3514 OMPBuilder.unrollLoopHeuristic(DL, CLI);
3517 assert((!NeedsUnrolledCLI || UnrolledCLI) &&
3518 "NeedsUnrolledCLI implies UnrolledCLI to be set");
3535 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3537 FactorExpr->EvaluateKnownConstInt(
getContext()).getLimitedValue();
3538 assert(Factor >= 1 &&
"Only positive factors are valid");
3546void CodeGenFunction::EmitOMPOuterLoop(
3549 const CodeGenFunction::OMPLoopArguments &LoopArgs,
3568 llvm::Value *BoolCondVal =
nullptr;
3569 if (!DynamicOrOrdered) {
3580 RT.
emitForNext(*
this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL,
3581 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST);
3586 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
3591 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
3592 if (ExitBlock !=
LoopExit.getBlock()) {
3600 if (DynamicOrOrdered)
3605 BreakContinueStack.push_back(BreakContinue(S, LoopExit, Continue));
3610 [&S, IsMonotonic, EKind](CodeGenFunction &CGF, PrePostActionTy &) {
3615 if (
const auto *
C = S.getSingleClause<OMPOrderClause>())
3616 if (
C->getKind() == OMPC_ORDER_concurrent)
3622 [&S, &LoopArgs, LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered,
3623 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
3624 SourceLocation Loc = S.getBeginLoc();
3630 CGF.EmitOMPInnerLoop(
3632 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
3633 CodeGenLoop(CGF, S, LoopExit);
3635 [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) {
3636 CodeGenOrdered(CGF, Loc, IVSize, IVSigned);
3641 BreakContinueStack.pop_back();
3642 if (!DynamicOrOrdered) {
3655 auto &&CodeGen = [DynamicOrOrdered, &S, &LoopArgs](CodeGenFunction &CGF) {
3656 if (!DynamicOrOrdered)
3657 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
3660 OMPCancelStack.emitExit(*
this, EKind, CodeGen);
3663void CodeGenFunction::EmitOMPForOuterLoop(
3664 const OpenMPScheduleTy &ScheduleKind,
bool IsMonotonic,
3666 const OMPLoopArguments &LoopArgs,
3668 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3674 LoopArgs.Chunk !=
nullptr)) &&
3675 "static non-chunked schedule does not need outer loop");
3733 if (DynamicOrOrdered) {
3734 const std::pair<llvm::Value *, llvm::Value *> DispatchBounds =
3735 CGDispatchBounds(*
this, S, LoopArgs.LB, LoopArgs.UB);
3736 llvm::Value *LBVal = DispatchBounds.first;
3737 llvm::Value *UBVal = DispatchBounds.second;
3738 CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal,
3741 IVSigned, Ordered, DipatchRTInputValues);
3743 CGOpenMPRuntime::StaticRTInput StaticInit(
3744 IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
3745 LoopArgs.ST, LoopArgs.Chunk);
3751 auto &&CodeGenOrdered = [Ordered](CodeGenFunction &CGF, SourceLocation Loc,
3752 const unsigned IVSize,
3753 const bool IVSigned) {
3760 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST,
3761 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB);
3762 OuterLoopArgs.IncExpr = S.
getInc();
3763 OuterLoopArgs.Init = S.
getInit();
3764 OuterLoopArgs.Cond = S.
getCond();
3767 OuterLoopArgs.DKind = LoopArgs.DKind;
3768 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
3770 if (DynamicOrOrdered) {
3776 const unsigned IVSize,
const bool IVSigned) {}
3778void CodeGenFunction::EmitOMPDistributeOuterLoop(
3783 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3795 CGOpenMPRuntime::StaticRTInput StaticInit(
3796 IVSize, IVSigned,
false, LoopArgs.IL, LoopArgs.LB,
3797 LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
3811 OMPLoopArguments OuterLoopArgs;
3812 OuterLoopArgs.LB = LoopArgs.LB;
3813 OuterLoopArgs.UB = LoopArgs.UB;
3814 OuterLoopArgs.ST = LoopArgs.ST;
3815 OuterLoopArgs.IL = LoopArgs.IL;
3816 OuterLoopArgs.Chunk = LoopArgs.Chunk;
3820 OuterLoopArgs.IncExpr = IncExpr;
3833 OuterLoopArgs.DKind = OMPD_distribute;
3835 EmitOMPOuterLoop(
false,
false, S,
3836 LoopScope, OuterLoopArgs, CodeGenLoopContent,
3840static std::pair<LValue, LValue>
3883static std::pair<llvm::Value *, llvm::Value *>
3894 llvm::Value *LBVal =
3896 llvm::Value *UBVal =
3898 return {LBVal, UBVal};
3907 llvm::Value *LBCast = CGF.
Builder.CreateIntCast(
3909 CapturedVars.push_back(LBCast);
3913 llvm::Value *UBCast = CGF.
Builder.CreateIntCast(
3915 CapturedVars.push_back(UBCast);
3926 bool HasCancel =
false;
3928 if (
const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
3929 HasCancel = D->hasCancel();
3930 else if (
const auto *D = dyn_cast<OMPDistributeParallelForDirective>(&S))
3931 HasCancel = D->hasCancel();
3932 else if (
const auto *D =
3933 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S))
3934 HasCancel = D->hasCancel();
3944 CGInlinedWorksharingLoop,
3954 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3955 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3964 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3965 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3973 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
3974 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
3984 llvm::Constant *
Addr;
3986 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
3988 assert(Fn &&
Addr &&
"Target device function emission failed.");
4000struct ScheduleKindModifiersTy {
4007 : Kind(Kind), M1(M1), M2(M2) {}
4031 bool HasLastprivateClause;
4034 OMPLoopScope PreInitScope(*
this, S);
4039 llvm::BasicBlock *ContBlock =
nullptr;
4053 bool Ordered =
false;
4054 if (
const auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) {
4055 if (OrderedClause->getNumForLoops())
4065 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*
this, S);
4066 LValue LB = Bounds.first;
4067 LValue UB = Bounds.second;
4081 CGM.getOpenMPRuntime().emitBarrierCall(
4082 *
this, S.getBeginLoc(), OMPD_unknown,
false,
4094 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
4097 const Expr *ChunkExpr =
nullptr;
4099 if (
const auto *
C = S.getSingleClause<OMPScheduleClause>()) {
4100 ScheduleKind.
Schedule =
C->getScheduleKind();
4101 ScheduleKind.
M1 =
C->getFirstScheduleModifier();
4102 ScheduleKind.
M2 =
C->getSecondScheduleModifier();
4103 ChunkExpr =
C->getChunkSize();
4106 CGM.getOpenMPRuntime().getDefaultScheduleAndChunk(
4107 *
this, S, ScheduleKind.
Schedule, ChunkExpr);
4109 bool HasChunkSizeOne =
false;
4110 llvm::Value *Chunk =
nullptr;
4118 llvm::APSInt EvaluatedChunk =
Result.Val.getInt();
4119 HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
4128 bool StaticChunkedOne =
4130 Chunk !=
nullptr) &&
4142 "fused distribute schedule requires a static chunk-one schedule");
4145 (ScheduleKind.
Schedule == OMPC_SCHEDULE_static &&
4146 !(ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4147 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)) ||
4148 ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
4149 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
4151 Chunk !=
nullptr) ||
4152 StaticChunkedOne) &&
4162 if (
C->getKind() == OMPC_ORDER_concurrent)
4166 [IVSize, IVSigned, Ordered, IL, LB, UB, ST, StaticChunkedOne, Chunk,
4175 IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(),
4176 UB.getAddress(), ST.getAddress(),
4177 StaticChunkedOne ? Chunk :
nullptr);
4179 CGF, S.getBeginLoc(), EKind, ScheduleKind, StaticInit);
4181 if (!StaticChunkedOne)
4200 StaticChunkedOne ? S.getCombinedParForInDistCond()
4202 StaticChunkedOne ? S.getDistInc() : S.getInc(),
4203 [&S,
LoopExit](CodeGenFunction &CGF) {
4204 emitOMPLoopBodyWithStopPoint(CGF, S, LoopExit);
4206 [](CodeGenFunction &) {});
4210 auto &&
CodeGen = [&S](CodeGenFunction &CGF) {
4214 OMPCancelStack.emitExit(*
this, EKind,
CodeGen);
4221 LoopArguments.DKind = OMPD_for;
4222 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
4223 LoopArguments, CGDispatchBounds);
4227 return CGF.
Builder.CreateIsNotNull(
4233 ? OMPD_parallel_for_simd
4237 *
this, S, [IL, &S](CodeGenFunction &CGF) {
4238 return CGF.
Builder.CreateIsNotNull(
4242 if (HasLastprivateClause)
4248 return CGF.
Builder.CreateIsNotNull(
4259 return HasLastprivateClause;
4265static std::pair<LValue, LValue>
4279static std::pair<llvm::Value *, llvm::Value *>
4283 const Expr *IVExpr = LS.getIterationVariable();
4285 llvm::Value *LBVal = CGF.
Builder.getIntN(IVSize, 0);
4287 return {LBVal, UBVal};
4299 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
4300 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4301 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4306 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4307 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4308 "Only inscan reductions are expected.");
4309 Shareds.append(
C->varlist_begin(),
C->varlist_end());
4310 Privates.append(
C->privates().begin(),
C->privates().end());
4311 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
4312 CopyArrayTemps.append(
C->copy_array_temps().begin(),
4313 C->copy_array_temps().end());
4321 auto *ITA = CopyArrayTemps.begin();
4326 if (PrivateVD->getType()->isVariablyModifiedType()) {
4351 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
4352 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4353 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4360 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4361 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4362 "Only inscan reductions are expected.");
4363 Shareds.append(
C->varlist_begin(),
C->varlist_end());
4364 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
4365 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
4366 Privates.append(
C->privates().begin(),
C->privates().end());
4367 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
4368 CopyArrayElems.append(
C->copy_array_elems().begin(),
4369 C->copy_array_elems().end());
4373 llvm::Value *OMPLast = CGF.
Builder.CreateNSWSub(
4374 OMPScanNumIterations,
4375 llvm::ConstantInt::get(CGF.
SizeTy, 1,
false));
4376 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
4378 const Expr *OrigExpr = Shareds[I];
4379 const Expr *CopyArrayElem = CopyArrayElems[I];
4386 LValue SrcLVal = CGF.
EmitLValue(CopyArrayElem);
4388 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
4418 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4419 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4425 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4426 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4427 "Only inscan reductions are expected.");
4428 Privates.append(
C->privates().begin(),
C->privates().end());
4429 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
4430 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
4431 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
4432 CopyArrayElems.append(
C->copy_array_elems().begin(),
4433 C->copy_array_elems().end());
4448 auto &&
CodeGen = [&S, OMPScanNumIterations, &LHSs, &RHSs, &CopyArrayElems,
4455 llvm::BasicBlock *InputBB = CGF.Builder.GetInsertBlock();
4456 llvm::BasicBlock *LoopBB = CGF.createBasicBlock(
"omp.outer.log.scan.body");
4457 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
"omp.outer.log.scan.exit");
4459 CGF.CGM.getIntrinsic(llvm::Intrinsic::log2, CGF.DoubleTy);
4461 CGF.Builder.CreateUIToFP(OMPScanNumIterations, CGF.DoubleTy);
4462 llvm::Value *LogVal = CGF.EmitNounwindRuntimeCall(F, Arg);
4463 F = CGF.CGM.getIntrinsic(llvm::Intrinsic::ceil, CGF.DoubleTy);
4464 LogVal = CGF.EmitNounwindRuntimeCall(F, LogVal);
4465 LogVal = CGF.Builder.CreateFPToUI(LogVal, CGF.IntTy);
4466 llvm::Value *NMin1 = CGF.Builder.CreateNUWSub(
4467 OMPScanNumIterations, llvm::ConstantInt::get(CGF.SizeTy, 1));
4469 CGF.EmitBlock(LoopBB);
4470 auto *Counter = CGF.Builder.CreatePHI(CGF.IntTy, 2);
4472 auto *Pow2K = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
4473 Counter->addIncoming(llvm::ConstantInt::get(CGF.IntTy, 0), InputBB);
4474 Pow2K->addIncoming(llvm::ConstantInt::get(CGF.SizeTy, 1), InputBB);
4477 llvm::BasicBlock *InnerLoopBB =
4478 CGF.createBasicBlock(
"omp.inner.log.scan.body");
4479 llvm::BasicBlock *InnerExitBB =
4480 CGF.createBasicBlock(
"omp.inner.log.scan.exit");
4481 llvm::Value *CmpI = CGF.Builder.CreateICmpUGE(NMin1, Pow2K);
4482 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4483 CGF.EmitBlock(InnerLoopBB);
4484 auto *IVal = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
4485 IVal->addIncoming(NMin1, LoopBB);
4488 auto *ILHS = LHSs.begin();
4489 auto *IRHS = RHSs.begin();
4490 for (
const Expr *CopyArrayElem : CopyArrayElems) {
4500 LHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4505 llvm::Value *OffsetIVal = CGF.Builder.CreateNUWSub(IVal, Pow2K);
4511 RHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4518 CGF.CGM.getOpenMPRuntime().emitReduction(
4519 CGF, S.getEndLoc(),
Privates, LHSs, RHSs, ReductionOps,
4523 llvm::Value *NextIVal =
4524 CGF.Builder.CreateNUWSub(IVal, llvm::ConstantInt::get(CGF.SizeTy, 1));
4525 IVal->addIncoming(NextIVal, CGF.Builder.GetInsertBlock());
4526 CmpI = CGF.Builder.CreateICmpUGE(NextIVal, Pow2K);
4527 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4528 CGF.EmitBlock(InnerExitBB);
4530 CGF.Builder.CreateNUWAdd(Counter, llvm::ConstantInt::get(CGF.IntTy, 1));
4531 Counter->addIncoming(
Next, CGF.Builder.GetInsertBlock());
4533 llvm::Value *NextPow2K =
4534 CGF.Builder.CreateShl(Pow2K, 1,
"",
true);
4535 Pow2K->addIncoming(NextPow2K, CGF.Builder.GetInsertBlock());
4536 llvm::Value *
Cmp = CGF.Builder.CreateICmpNE(
Next, LogVal);
4537 CGF.Builder.CreateCondBr(
Cmp, LoopBB, ExitBB);
4539 CGF.EmitBlock(ExitBB);
4545 CGF, S.getBeginLoc(), OMPD_unknown,
false,
4548 RegionCodeGenTy RCG(CodeGen);
4559 bool HasLastprivates;
4561 if (llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4562 [](
const OMPReductionClause *
C) {
4563 return C->getModifier() == OMPC_REDUCTION_inscan;
4567 OMPLoopScope LoopScope(CGF, S);
4570 const auto &&FirstGen = [&S, HasCancel, EKind](
CodeGenFunction &CGF) {
4579 const auto &&SecondGen = [&S, HasCancel, EKind,
4597 return HasLastprivates;
4610 if (
auto *SC = dyn_cast<OMPScheduleClause>(
C)) {
4615 switch (SC->getScheduleKind()) {
4616 case OMPC_SCHEDULE_auto:
4617 case OMPC_SCHEDULE_dynamic:
4618 case OMPC_SCHEDULE_runtime:
4619 case OMPC_SCHEDULE_guided:
4620 case OMPC_SCHEDULE_static:
4633static llvm::omp::ScheduleKind
4635 switch (ScheduleClauseKind) {
4637 return llvm::omp::OMP_SCHEDULE_Default;
4638 case OMPC_SCHEDULE_auto:
4639 return llvm::omp::OMP_SCHEDULE_Auto;
4640 case OMPC_SCHEDULE_dynamic:
4641 return llvm::omp::OMP_SCHEDULE_Dynamic;
4642 case OMPC_SCHEDULE_guided:
4643 return llvm::omp::OMP_SCHEDULE_Guided;
4644 case OMPC_SCHEDULE_runtime:
4645 return llvm::omp::OMP_SCHEDULE_Runtime;
4646 case OMPC_SCHEDULE_static:
4647 return llvm::omp::OMP_SCHEDULE_Static;
4649 llvm_unreachable(
"Unhandled schedule kind");
4656 bool HasLastprivates =
false;
4659 auto &&
CodeGen = [&S, &
CGM, HasCancel, &HasLastprivates,
4662 if (UseOMPIRBuilder) {
4663 bool NeedsBarrier = !S.getSingleClause<OMPNowaitClause>();
4665 llvm::omp::ScheduleKind SchedKind = llvm::omp::OMP_SCHEDULE_Default;
4666 llvm::Value *ChunkSize =
nullptr;
4667 if (
auto *SchedClause = S.getSingleClause<OMPScheduleClause>()) {
4670 if (
const Expr *ChunkSizeExpr = SchedClause->getChunkSize())
4675 const Stmt *Inner = S.getRawStmt();
4676 llvm::CanonicalLoopInfo *CLI =
4679 llvm::OpenMPIRBuilder &OMPBuilder =
4681 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4683 cantFail(OMPBuilder.applyWorkshareLoop(
4684 CGF.
Builder.getCurrentDebugLocation(), CLI, AllocaIP, NeedsBarrier,
4685 SchedKind, ChunkSize,
false,
4696 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
4701 if (!UseOMPIRBuilder) {
4703 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4715 bool HasLastprivates =
false;
4716 auto &&
CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
4723 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4724 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
4728 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4729 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_for);
4736 llvm::Value *
Init =
nullptr) {
4743void CodeGenFunction::EmitSections(
const OMPExecutableDirective &S) {
4744 const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4745 const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt);
4746 bool HasLastprivates =
false;
4748 auto &&CodeGen = [&S, CapturedStmt, CS, EKind,
4749 &HasLastprivates](CodeGenFunction &CGF, PrePostActionTy &) {
4750 const ASTContext &
C = CGF.getContext();
4751 QualType KmpInt32Ty =
4752 C.getIntTypeForBitwidth(32, 1);
4755 CGF.Builder.getInt32(0));
4756 llvm::ConstantInt *GlobalUBVal = CS !=
nullptr
4757 ? CGF.Builder.getInt32(CS->size() - 1)
4758 : CGF.Builder.getInt32(0);
4762 CGF.Builder.getInt32(1));
4764 CGF.Builder.getInt32(0));
4767 OpaqueValueExpr IVRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4768 CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
4769 OpaqueValueExpr UBRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4770 CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
4774 S.getBeginLoc(), FPOptionsOverride());
4778 S.getBeginLoc(),
true, FPOptionsOverride());
4779 auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
4791 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".omp.sections.exit");
4792 llvm::SwitchInst *SwitchStmt =
4793 CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.
getBeginLoc()),
4794 ExitBB, CS ==
nullptr ? 1 : CS->size());
4796 unsigned CaseNumber = 0;
4797 for (
const Stmt *SubStmt : CS->
children()) {
4798 auto CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4799 CGF.EmitBlock(CaseBB);
4800 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
4801 CGF.EmitStmt(SubStmt);
4802 CGF.EmitBranch(ExitBB);
4806 llvm::BasicBlock *CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4807 CGF.EmitBlock(CaseBB);
4808 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
4809 CGF.EmitStmt(CapturedStmt);
4810 CGF.EmitBranch(ExitBB);
4812 CGF.EmitBlock(ExitBB,
true);
4815 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
4816 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
4820 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
4824 CGF.EmitOMPPrivateClause(S, LoopScope);
4825 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(CGF, S, IV);
4826 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
4827 CGF.EmitOMPReductionClauseInit(S, LoopScope);
4828 (void)LoopScope.Privatize();
4830 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
4833 OpenMPScheduleTy ScheduleKind;
4834 ScheduleKind.
Schedule = OMPC_SCHEDULE_static;
4835 CGOpenMPRuntime::StaticRTInput StaticInit(
4836 32,
true,
false, IL.getAddress(),
4837 LB.getAddress(), UB.getAddress(), ST.getAddress());
4838 CGF.CGM.getOpenMPRuntime().emitForStaticInit(CGF, S.
getBeginLoc(), EKind,
4839 ScheduleKind, StaticInit);
4841 llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.
getBeginLoc());
4842 llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
4843 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
4844 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
4846 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.
getBeginLoc()), IV);
4848 CGF.EmitOMPInnerLoop(S,
false, Cond, Inc, BodyGen,
4849 [](CodeGenFunction &) {});
4851 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
4852 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.
getEndLoc(),
4855 CGF.OMPCancelStack.emitExit(CGF, EKind, CodeGen);
4856 CGF.EmitOMPReductionClauseFinal(S, OMPD_parallel);
4859 return CGF.
Builder.CreateIsNotNull(
4864 if (HasLastprivates)
4871 bool HasCancel =
false;
4872 if (
auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
4873 HasCancel = OSD->hasCancel();
4874 else if (
auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
4875 HasCancel = OPSD->hasCancel();
4877 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_sections, CodeGen,
4882 if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) {
4900 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4905 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4906 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_scope,
CodeGen);
4909 if (!S.getSingleClause<OMPNowaitClause>()) {
4910 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_scope);
4917 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4918 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4919 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4920 using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
4922 auto FiniCB = [](InsertPointTy IP) {
4925 return llvm::Error::success();
4928 const CapturedStmt *ICS = S.getInnermostCapturedStmt();
4929 const Stmt *
CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4934 auto SectionCB = [
this, SubStmt](
4935 InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4938 CodeGenIP,
"section");
4939 return llvm::Error::success();
4941 SectionCBVector.push_back(SectionCB);
4945 [
this,
CapturedStmt](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4949 return llvm::Error::success();
4951 SectionCBVector.push_back(SectionCB);
4958 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
4959 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
4969 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4971 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4972 cantFail(OMPBuilder.createSections(
4974 S.getSingleClause<OMPNowaitClause>()));
4981 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4985 if (!S.getSingleClause<OMPNowaitClause>()) {
4986 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(),
4994 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4995 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4996 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4998 const Stmt *SectionRegionBodyStmt = S.getAssociatedStmt();
4999 auto FiniCB = [
this](InsertPointTy IP) {
5001 return llvm::Error::success();
5004 auto BodyGenCB = [SectionRegionBodyStmt,
5005 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
5008 *
this, SectionRegionBodyStmt, AllocIP, CodeGenIP,
"section");
5009 return llvm::Error::success();
5014 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5015 cantFail(OMPBuilder.createSection(
Builder, BodyGenCB, FiniCB));
5035 CopyprivateVars.append(
C->varlist_begin(),
C->varlist_end());
5036 DestExprs.append(
C->destination_exprs().begin(),
5037 C->destination_exprs().end());
5038 SrcExprs.append(
C->source_exprs().begin(),
C->source_exprs().end());
5039 AssignmentOps.append(
C->assignment_ops().begin(),
5040 C->assignment_ops().end());
5049 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5054 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
5055 CGM.getOpenMPRuntime().emitSingleRegion(*
this,
CodeGen, S.getBeginLoc(),
5056 CopyprivateVars, DestExprs,
5057 SrcExprs, AssignmentOps);
5061 if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) {
5062 CGM.getOpenMPRuntime().emitBarrierCall(
5063 *
this, S.getBeginLoc(),
5064 S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);
5079 if (
CGM.getLangOpts().OpenMPIRBuilder) {
5080 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
5081 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5083 const Stmt *MasterRegionBodyStmt = S.getAssociatedStmt();
5085 auto FiniCB = [
this](InsertPointTy IP) {
5087 return llvm::Error::success();
5090 auto BodyGenCB = [MasterRegionBodyStmt,
5091 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
5094 *
this, MasterRegionBodyStmt, AllocIP, CodeGenIP,
"master");
5095 return llvm::Error::success();
5100 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5101 cantFail(OMPBuilder.createMaster(
Builder, BodyGenCB, FiniCB));
5116 Expr *Filter =
nullptr;
5118 Filter = FilterClause->getThreadID();
5124 if (
CGM.getLangOpts().OpenMPIRBuilder) {
5125 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
5126 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5128 const Stmt *MaskedRegionBodyStmt = S.getAssociatedStmt();
5129 const Expr *Filter =
nullptr;
5131 Filter = FilterClause->getThreadID();
5132 llvm::Value *FilterVal = Filter
5134 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
5136 auto FiniCB = [
this](InsertPointTy IP) {
5138 return llvm::Error::success();
5141 auto BodyGenCB = [MaskedRegionBodyStmt,
5142 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
5145 *
this, MaskedRegionBodyStmt, AllocIP, CodeGenIP,
"masked");
5146 return llvm::Error::success();
5151 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
5152 OMPBuilder.createMasked(
Builder, BodyGenCB, FiniCB, FilterVal));
5163 if (
CGM.getLangOpts().OpenMPIRBuilder) {
5164 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
5165 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5167 const Stmt *CriticalRegionBodyStmt = S.getAssociatedStmt();
5168 const Expr *Hint =
nullptr;
5169 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
5170 Hint = HintClause->getHint();
5175 llvm::Value *HintInst =
nullptr;
5180 auto FiniCB = [
this](InsertPointTy IP) {
5182 return llvm::Error::success();
5185 auto BodyGenCB = [CriticalRegionBodyStmt,
5186 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
5189 *
this, CriticalRegionBodyStmt, AllocIP, CodeGenIP,
"critical");
5190 return llvm::Error::success();
5195 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5196 cantFail(OMPBuilder.createCritical(
Builder, BodyGenCB, FiniCB,
5206 CGF.
EmitStmt(S.getAssociatedStmt());
5208 const Expr *Hint =
nullptr;
5209 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
5210 Hint = HintClause->getHint();
5213 CGM.getOpenMPRuntime().emitCriticalRegion(*
this,
5215 CodeGen, S.getBeginLoc(), Hint);
5228 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
5232 OMPLoopScope LoopScope(CGF, S);
5235 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
5236 [](
const OMPReductionClause *
C) {
5237 return C->getModifier() == OMPC_REDUCTION_inscan;
5262 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
5266 OMPLoopScope LoopScope(CGF, S);
5269 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
5270 [](
const OMPReductionClause *
C) {
5271 return C->getModifier() == OMPC_REDUCTION_inscan;
5307 [](CodeGenFunction &) {
return nullptr; });
5334 [](CodeGenFunction &) {
return nullptr; });
5347 CGF.EmitSections(S);
5361class CheckVarsEscapingUntiedTaskDeclContext final
5366 explicit CheckVarsEscapingUntiedTaskDeclContext() =
default;
5367 ~CheckVarsEscapingUntiedTaskDeclContext() =
default;
5368 void VisitDeclStmt(
const DeclStmt *S) {
5373 if (
const auto *VD = dyn_cast_or_null<VarDecl>(D))
5375 PrivateDecls.push_back(VD);
5379 void VisitCapturedStmt(
const CapturedStmt *) {}
5381 void VisitBlockExpr(
const BlockExpr *) {}
5382 void VisitStmt(
const Stmt *S) {
5385 for (
const Stmt *Child : S->
children())
5391 ArrayRef<const VarDecl *> getPrivateDecls()
const {
return PrivateDecls; }
5399 bool OmpAllMemory =
false;
5402 return C->getDependencyKind() == OMPC_DEPEND_outallmemory ||
5403 C->getDependencyKind() == OMPC_DEPEND_inoutallmemory;
5405 OmpAllMemory =
true;
5410 Data.Dependences.emplace_back(OMPC_DEPEND_outallmemory,
5419 if (Kind == OMPC_DEPEND_outallmemory || Kind == OMPC_DEPEND_inoutallmemory)
5421 if (OmpAllMemory && (Kind == OMPC_DEPEND_out || Kind == OMPC_DEPEND_inout))
5424 Data.Dependences.emplace_back(
C->getDependencyKind(),
C->getModifier());
5425 DD.
DepExprs.append(
C->varlist_begin(),
C->varlist_end());
5434 const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion);
5436 auto PartId = std::next(I);
5437 auto TaskT = std::next(I, 4);
5442 const Expr *Cond = Clause->getCondition();
5445 Data.Final.setInt(CondConstant);
5450 Data.Final.setInt(
false);
5454 const Expr *Prio = Clause->getPriority();
5455 Data.Priority.setInt(
true);
5463 llvm::DenseSet<const ValueDecl *> EmittedAsPrivate;
5465 for (
const auto *
C : S.getClausesOfKind<OMPPrivateClause>()) {
5466 auto IRef =
C->varlist_begin();
5467 for (
const Expr *IInit :
C->private_copies()) {
5469 if (EmittedAsPrivate.insert(
cast<ValueDecl>(OrigDecl->getCanonicalDecl()))
5471 Data.PrivateVars.push_back(*IRef);
5472 Data.PrivateCopies.push_back(IInit);
5477 EmittedAsPrivate.clear();
5479 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5480 auto IRef =
C->varlist_begin();
5481 auto IElemInitRef =
C->inits().begin();
5482 for (
const Expr *IInit :
C->private_copies()) {
5484 if (EmittedAsPrivate.insert(
cast<ValueDecl>(OrigDecl->getCanonicalDecl()))
5486 Data.FirstprivateVars.push_back(*IRef);
5487 Data.FirstprivateCopies.push_back(IInit);
5488 Data.FirstprivateInits.push_back(*IElemInitRef);
5495 llvm::MapVector<const ValueDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
5496 llvm::MapVector<const ValueDecl *, const DeclRefExpr *> LastprivateSrcsOrigs;
5497 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
5498 auto IRef =
C->varlist_begin();
5499 auto ID =
C->destination_exprs().begin();
5500 auto IS =
C->source_exprs().begin();
5501 for (
const Expr *IInit :
C->private_copies()) {
5503 if (EmittedAsPrivate.insert(
cast<ValueDecl>(OrigDecl->getCanonicalDecl()))
5505 Data.LastprivateVars.push_back(*IRef);
5506 Data.LastprivateCopies.push_back(IInit);
5508 LastprivateDstsOrigs.insert(std::make_pair(
5510 LastprivateSrcsOrigs.insert(std::make_pair(
5519 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
5520 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5521 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5522 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5523 Data.ReductionOps.append(
C->reduction_ops().begin(),
5524 C->reduction_ops().end());
5525 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5526 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5528 Data.Reductions =
CGM.getOpenMPRuntime().emitTaskReductionInit(
5529 *
this, S.getBeginLoc(), LHSs, RHSs,
Data);
5534 CheckVarsEscapingUntiedTaskDeclContext Checker;
5535 Checker.Visit(S.getInnermostCapturedStmt()->getCapturedStmt());
5536 Data.PrivateLocals.append(Checker.getPrivateDecls().begin(),
5537 Checker.getPrivateDecls().end());
5539 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
5540 &LastprivateSrcsOrigs, CapturedRegion](
5542 llvm::MapVector<CanonicalDeclPtr<const VarDecl>,
5543 std::pair<Address, Address>>
5548 if (
auto *DI = CGF.getDebugInfo()) {
5549 llvm::SmallDenseMap<const VarDecl *, FieldDecl *> CaptureFields =
5550 CGF.CapturedStmtInfo->getCaptureFields();
5551 llvm::Value *ContextValue = CGF.CapturedStmtInfo->getContextValue();
5552 if (CaptureFields.size() && ContextValue) {
5553 unsigned CharWidth = CGF.getContext().getCharWidth();
5567 for (
auto It = CaptureFields.begin(); It != CaptureFields.end(); ++It) {
5568 const VarDecl *SharedVar = It->first;
5571 CGF.getContext().getASTRecordLayout(CaptureRecord);
5574 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5575 (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue,
5576 CGF.Builder,
false);
5579 auto UpdateExpr = [](llvm::LLVMContext &Ctx,
auto *
Declare,
5584 Ops.push_back(llvm::dwarf::DW_OP_plus_uconst);
5585 Ops.push_back(Offset);
5587 Ops.push_back(llvm::dwarf::DW_OP_deref);
5588 Declare->setExpression(llvm::DIExpression::get(Ctx, Ops));
5590 llvm::Instruction &
Last = CGF.Builder.GetInsertBlock()->back();
5591 if (
auto DDI = dyn_cast<llvm::DbgVariableIntrinsic>(&
Last))
5592 UpdateExpr(DDI->getContext(), DDI, Offset);
5595 assert(!
Last.isTerminator() &&
"unexpected terminator");
5597 CGF.Builder.GetInsertBlock()->getTrailingDbgRecords()) {
5598 for (llvm::DbgVariableRecord &DVR : llvm::reverse(
5599 llvm::filterDbgVars(Marker->getDbgRecordRange()))) {
5600 UpdateExpr(
Last.getContext(), &DVR, Offset);
5609 if (!
Data.PrivateVars.empty() || !
Data.FirstprivateVars.empty() ||
5610 !
Data.LastprivateVars.empty() || !
Data.PrivateLocals.empty()) {
5611 enum { PrivatesParam = 2, CopyFnParam = 3 };
5612 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5614 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5620 CallArgs.push_back(PrivatesPtr);
5621 ParamTypes.push_back(PrivatesPtr->getType());
5622 for (
const Expr *E :
Data.PrivateVars) {
5624 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5625 CGF.getContext().getPointerType(E->
getType()),
".priv.ptr.addr");
5626 PrivatePtrs.emplace_back(VD, PrivatePtr);
5628 ParamTypes.push_back(PrivatePtr.
getType());
5630 for (
const Expr *E :
Data.FirstprivateVars) {
5632 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5633 CGF.getContext().getPointerType(E->
getType()),
5634 ".firstpriv.ptr.addr");
5635 PrivatePtrs.emplace_back(VD, PrivatePtr);
5636 FirstprivatePtrs.emplace_back(VD, PrivatePtr);
5638 ParamTypes.push_back(PrivatePtr.
getType());
5640 for (
const Expr *E :
Data.LastprivateVars) {
5642 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5643 CGF.getContext().getPointerType(E->
getType()),
5644 ".lastpriv.ptr.addr");
5645 PrivatePtrs.emplace_back(VD, PrivatePtr);
5647 ParamTypes.push_back(PrivatePtr.
getType());
5652 Ty = CGF.getContext().getPointerType(Ty);
5654 Ty = CGF.getContext().getPointerType(Ty);
5655 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5656 CGF.getContext().getPointerType(Ty),
".local.ptr.addr");
5657 auto Result = UntiedLocalVars.insert(
5660 if (
Result.second ==
false)
5661 *
Result.first = std::make_pair(
5664 ParamTypes.push_back(PrivatePtr.
getType());
5666 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5668 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5669 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5670 for (
const auto &Pair : LastprivateDstsOrigs) {
5671 const auto *OrigDecl = Pair.second->getDecl();
5672 if (
const auto *BD = dyn_cast<BindingDecl>(OrigDecl)) {
5675 CGF.EmitOMPBindingOriginalAddr(BD, Pair.second->getExprLoc());
5676 Scope.addPrivate(Pair.first, OrigAddr);
5681 CGF.CapturedStmtInfo->lookup(OrigVD) !=
nullptr,
5683 Pair.second->getExprLoc());
5684 Scope.addPrivate(Pair.first, CGF.EmitLValue(&DRE).getAddress());
5687 for (
const auto &Pair : PrivatePtrs) {
5689 CGF.Builder.CreateLoad(Pair.second),
5690 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5691 CGF.getContext().getDeclAlign(Pair.first));
5692 Scope.addPrivate(Pair.first, Replacement);
5697 for (
const auto &SrcPair : LastprivateSrcsOrigs) {
5698 if (SrcPair.second->getDecl() == Pair.first) {
5699 Scope.addPrivate(SrcPair.first, Replacement);
5705 if (
auto *DI = CGF.getDebugInfo())
5706 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5708 if (
const auto *VD = dyn_cast<VarDecl>(Pair.first))
5709 (void)DI->EmitDeclareOfAutoVariable(
5710 VD, Pair.second.getBasePointer(), CGF.Builder,
5715 for (
auto &Pair : UntiedLocalVars) {
5716 QualType VDType = Pair.first->getType().getNonReferenceType();
5717 if (Pair.first->getType()->isLValueReferenceType())
5718 VDType = CGF.getContext().getPointerType(VDType);
5720 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5723 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(VDType)),
5724 CGF.getPointerAlign());
5725 Pair.second.first = Replacement;
5726 Ptr = CGF.Builder.CreateLoad(Replacement);
5727 Replacement =
Address(Ptr, CGF.ConvertTypeForMem(VDType),
5728 CGF.getContext().getDeclAlign(Pair.first));
5729 Pair.second.second = Replacement;
5731 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5732 Address Replacement(Ptr, CGF.ConvertTypeForMem(VDType),
5733 CGF.getContext().getDeclAlign(Pair.first));
5734 Pair.second.first = Replacement;
5738 if (
Data.Reductions) {
5740 for (
const auto &Pair : FirstprivatePtrs) {
5742 CGF.Builder.CreateLoad(Pair.second),
5743 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5744 CGF.getContext().getDeclAlign(Pair.first));
5745 FirstprivateScope.
addPrivate(Pair.first, Replacement);
5748 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5750 Data.ReductionCopies,
Data.ReductionOps);
5751 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
5753 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5759 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5761 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5764 CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF),
5765 CGF.getContext().VoidPtrTy,
5766 CGF.getContext().getPointerType(
5767 Data.ReductionCopies[Cnt]->getType()),
5768 Data.ReductionCopies[Cnt]->getExprLoc()),
5769 CGF.ConvertTypeForMem(
Data.ReductionCopies[Cnt]->getType()),
5770 Replacement.getAlignment());
5776 (void)
Scope.Privatize();
5781 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5782 auto IPriv =
C->privates().begin();
5783 auto IRed =
C->reduction_ops().begin();
5784 auto ITD =
C->taskgroup_descriptors().begin();
5785 for (
const Expr *Ref :
C->varlist()) {
5786 InRedVars.emplace_back(Ref);
5787 InRedPrivs.emplace_back(*IPriv);
5788 InRedOps.emplace_back(*IRed);
5789 TaskgroupDescriptors.emplace_back(*ITD);
5790 std::advance(IPriv, 1);
5791 std::advance(IRed, 1);
5792 std::advance(ITD, 1);
5798 if (!InRedVars.empty()) {
5800 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5808 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5810 llvm::Value *ReductionsPtr;
5811 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5812 ReductionsPtr = CGF.EmitLoadOfScalar(CGF.EmitLValue(TRExpr),
5813 TRExpr->getExprLoc());
5815 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5817 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5820 CGF.EmitScalarConversion(
5821 Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy,
5822 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
5823 InRedPrivs[Cnt]->getExprLoc()),
5824 CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()),
5825 Replacement.getAlignment());
5838 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5839 S, *I, *PartId, *TaskT, EKind,
CodeGen,
Data.Tied,
Data.NumberOfParts);
5840 OMPLexicalScope
Scope(*
this, S, std::nullopt,
5843 TaskGen(*
this, OutlinedFn,
Data);
5860 QualType ElemType =
C.getBaseElementType(Ty);
5870 Data.FirstprivateVars.emplace_back(OrigRef);
5871 Data.FirstprivateCopies.emplace_back(PrivateRef);
5872 Data.FirstprivateInits.emplace_back(InitRef);
5885 auto PartId = std::next(I);
5886 auto TaskT = std::next(I, 4);
5889 Data.Final.setInt(
false);
5891 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5892 auto IRef =
C->varlist_begin();
5893 auto IElemInitRef =
C->inits().begin();
5894 for (
auto *IInit :
C->private_copies()) {
5895 Data.FirstprivateVars.push_back(*IRef);
5896 Data.FirstprivateCopies.push_back(IInit);
5897 Data.FirstprivateInits.push_back(*IElemInitRef);
5904 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5905 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5906 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5907 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5908 Data.ReductionOps.append(
C->reduction_ops().begin(),
5909 C->reduction_ops().end());
5910 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5911 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5926 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5928 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5940 if (!isa_and_nonnull<llvm::ConstantPointerNull>(
5943 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5950 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, BPVD, PVD, SVD, MVD, EKind,
5954 if (!
Data.FirstprivateVars.empty()) {
5955 enum { PrivatesParam = 2, CopyFnParam = 3 };
5956 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5958 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5964 CallArgs.push_back(PrivatesPtr);
5965 ParamTypes.push_back(PrivatesPtr->getType());
5966 for (
const Expr *E :
Data.FirstprivateVars) {
5968 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5969 CGF.getContext().getPointerType(E->
getType()),
5970 ".firstpriv.ptr.addr");
5971 PrivatePtrs.emplace_back(VD, PrivatePtr);
5973 ParamTypes.push_back(PrivatePtr.
getType());
5975 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5977 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5978 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5979 for (
const auto &Pair : PrivatePtrs) {
5981 CGF.Builder.CreateLoad(Pair.second),
5982 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5983 CGF.getContext().getDeclAlign(Pair.first));
5984 Scope.addPrivate(Pair.first, Replacement);
5987 CGF.processInReduction(S,
Data, CGF, CS,
Scope);
5990 CGF.GetAddrOfLocalVar(BPVD), 0);
5992 CGF.GetAddrOfLocalVar(PVD), 0);
5993 InputInfo.
SizesArray = CGF.Builder.CreateConstArrayGEP(
5994 CGF.GetAddrOfLocalVar(SVD), 0);
5997 InputInfo.
MappersArray = CGF.Builder.CreateConstArrayGEP(
5998 CGF.GetAddrOfLocalVar(MVD), 0);
6002 OMPLexicalScope LexScope(CGF, S, OMPD_task,
false);
6004 if (CGF.CGM.getLangOpts().OpenMP >= 51 &&
6009 CGF.CGM.getOpenMPRuntime().emitThreadLimitClause(
6010 CGF, TL->getThreadLimit().front(), S.getBeginLoc());
6014 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
6015 S, *I, *PartId, *TaskT, EKind,
CodeGen,
true,
6016 Data.NumberOfParts);
6017 llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<OMPNowaitClause>() ? 1 : 0);
6021 CGM.getOpenMPRuntime().emitTaskCall(*
this, S.getBeginLoc(), S, OutlinedFn,
6022 SharedsTy, CapturedStruct, &IfCond,
Data);
6027 CodeGenFunction &CGF,
6031 if (
Data.Reductions) {
6033 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
6035 Data.ReductionCopies,
Data.ReductionOps);
6038 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
6052 Data.ReductionCopies[Cnt]->getType()),
6053 Data.ReductionCopies[Cnt]->getExprLoc()),
6055 Replacement.getAlignment());
6060 (void)
Scope.Privatize();
6065 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
6066 auto IPriv =
C->privates().begin();
6067 auto IRed =
C->reduction_ops().begin();
6068 auto ITD =
C->taskgroup_descriptors().begin();
6069 for (
const Expr *Ref :
C->varlist()) {
6070 InRedVars.emplace_back(Ref);
6071 InRedPrivs.emplace_back(*IPriv);
6072 InRedOps.emplace_back(*IRed);
6073 TaskgroupDescriptors.emplace_back(*ITD);
6074 std::advance(IPriv, 1);
6075 std::advance(IRed, 1);
6076 std::advance(ITD, 1);
6080 if (!InRedVars.empty()) {
6082 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
6090 llvm::Value *ReductionsPtr;
6091 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
6095 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6103 InRedPrivs[Cnt]->getExprLoc()),
6105 Replacement.getAlignment());
6119 const Expr *IfCond =
nullptr;
6120 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
6121 if (
C->getNameModifier() == OMPD_unknown ||
6122 C->getNameModifier() == OMPD_task) {
6123 IfCond =
C->getCondition();
6130 Data.Tied = !S.getSingleClause<OMPUntiedClause>();
6134 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
6135 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
6138 SharedsTy, CapturedStruct, IfCond,
6148 CGM.getOpenMPRuntime().emitTaskyieldCall(*
this, S.getBeginLoc());
6152 const OMPMessageClause *MC = S.getSingleClause<OMPMessageClause>();
6153 Expr *ME = MC ? MC->getMessageString() :
nullptr;
6154 const OMPSeverityClause *SC = S.getSingleClause<OMPSeverityClause>();
6155 bool IsFatal =
false;
6156 if (!SC || SC->getSeverityKind() == OMPC_SEVERITY_fatal)
6158 CGM.getOpenMPRuntime().emitErrorCall(*
this, S.getBeginLoc(), ME, IsFatal);
6162 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_barrier);
6169 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
6170 CGM.getOpenMPRuntime().emitTaskwaitCall(*
this, S.getBeginLoc(),
Data);
6174 return T.clauses().empty();
6179 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6181 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
6182 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6185 auto BodyGenCB = [&,
this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
6188 EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
6189 return llvm::Error::success();
6194 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
6195 cantFail(OMPBuilder.createTaskgroup(
Builder, AllocaIP,
6206 for (
const auto *
C : S.getClausesOfKind<OMPTaskReductionClause>()) {
6207 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
6208 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
6209 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
6210 Data.ReductionOps.append(
C->reduction_ops().begin(),
6211 C->reduction_ops().end());
6212 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
6213 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
6215 llvm::Value *ReductionDesc =
6223 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
6225 CGM.getOpenMPRuntime().emitTaskgroupRegion(*
this,
CodeGen, S.getBeginLoc());
6230 ? llvm::AtomicOrdering::NotAtomic
6231 : llvm::AtomicOrdering::AcquireRelease;
6232 CGM.getOpenMPRuntime().emitFlush(
6235 if (
const auto *FlushClause = S.getSingleClause<
OMPFlushClause>())
6237 FlushClause->varlist_end());
6240 S.getBeginLoc(), AO);
6250 for (
auto &Dep :
Data.Dependences) {
6251 Address DepAddr =
CGM.getOpenMPRuntime().emitDepobjDependClause(
6252 *
this, Dep, DC->getBeginLoc());
6258 CGM.getOpenMPRuntime().emitDestroyClause(*
this, DOLVal, DC->getBeginLoc());
6261 if (
const auto *UC = S.getSingleClause<OMPUpdateDependObjectsClause>()) {
6262 CGM.getOpenMPRuntime().emitUpdateDependObjectsClause(
6263 *
this, DOLVal, UC->getDependencyKind(), UC->getBeginLoc());
6281 for (
const auto *
C : ParentDir.getClausesOfKind<OMPReductionClause>()) {
6282 if (
C->getModifier() != OMPC_REDUCTION_inscan)
6284 Shareds.append(
C->varlist_begin(),
C->varlist_end());
6285 Privates.append(
C->privates().begin(),
C->privates().end());
6286 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
6287 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
6288 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
6289 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
6290 CopyArrayTemps.append(
C->copy_array_temps().begin(),
6291 C->copy_array_temps().end());
6292 CopyArrayElems.append(
C->copy_array_elems().begin(),
6293 C->copy_array_elems().end());
6295 if (ParentDir.getDirectiveKind() == OMPD_simd ||
6337 : BreakContinueStack.back().ContinueBlock.getBlock());
6348 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6350 const Expr *TempExpr = CopyArrayTemps[I];
6362 CGM.getOpenMPRuntime().emitReduction(
6363 *
this, ParentDir.getEndLoc(),
Privates, LHSs, RHSs, ReductionOps,
6366 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6374 const Expr *TempExpr = CopyArrayTemps[I];
6386 ? BreakContinueStack.back().ContinueBlock.getBlock()
6392 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6398 .getIterationVariable()
6399 ->IgnoreParenImpCasts();
6402 IdxVal = Builder.CreateIntCast(IdxVal,
SizeTy,
false);
6403 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6405 const Expr *OrigExpr = Shareds[I];
6406 const Expr *CopyArrayElem = CopyArrayElems[I];
6407 OpaqueValueMapping IdxMapping(
6420 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6423 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6429 .getIterationVariable()
6430 ->IgnoreParenImpCasts();
6434 llvm::BasicBlock *ExclusiveExitBB =
nullptr;
6438 llvm::Value *
Cmp =
Builder.CreateIsNull(IdxVal);
6439 Builder.CreateCondBr(
Cmp, ExclusiveExitBB, ContBB);
6442 IdxVal =
Builder.CreateNUWSub(IdxVal, llvm::ConstantInt::get(
SizeTy, 1));
6444 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6445 const Expr *PrivateExpr =
Privates[I];
6446 const Expr *OrigExpr = Shareds[I];
6447 const Expr *CopyArrayElem = CopyArrayElems[I];
6456 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
6488 bool HasLastprivateClause =
false;
6491 OMPLoopScope PreInitScope(*
this, S);
6496 llvm::BasicBlock *ContBlock =
nullptr;
6534 CGM.getOpenMPRuntime().emitBarrierCall(
6535 *
this, S.getBeginLoc(), OMPD_unknown,
false,
6547 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
6550 llvm::Value *Chunk =
nullptr;
6553 ScheduleKind =
C->getDistScheduleKind();
6554 if (
const Expr *Ch =
C->getChunkSize()) {
6562 CGM.getOpenMPRuntime().getDefaultDistScheduleAndChunk(
6563 *
this, S, ScheduleKind, Chunk);
6584 bool StaticChunked =
6588 Chunk !=
nullptr) ||
6593 StaticChunked ? Chunk :
nullptr);
6647 [&S, &LoopScope, Cond, IncExpr,
LoopExit, &CodeGenLoop,
6650 S, LoopScope.requiresCleanups(), Cond, IncExpr,
6651 [&S,
LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
6652 CodeGenLoop(CGF, S, LoopExit);
6654 [&S, StaticChunked](CodeGenFunction &CGF) {
6655 if (StaticChunked) {
6656 CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound());
6657 CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound());
6658 CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound());
6659 CGF.EmitIgnoredExpr(S.getCombinedInit());
6669 const OMPLoopArguments LoopArguments = {
6672 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments,
6678 return CGF.
Builder.CreateIsNotNull(
6688 *
this, S, [IL, &S](CodeGenFunction &CGF) {
6689 return CGF.
Builder.CreateIsNotNull(
6694 if (HasLastprivateClause) {
6717 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
6726static llvm::Function *
6733 Fn->setDoesNotRecurse();
6737template <
typename T>
6739 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP,
6740 llvm::OpenMPIRBuilder &OMPBuilder) {
6742 unsigned NumLoops =
C->getNumLoops();
6746 for (
unsigned I = 0; I < NumLoops; I++) {
6747 const Expr *CounterVal =
C->getLoopData(I);
6752 StoreValues.emplace_back(StoreValue);
6754 OMPDoacrossKind<T> ODK;
6755 bool IsDependSource = ODK.isSource(
C);
6757 OMPBuilder.createOrderedDepend(CGF.
Builder, AllocaIP, NumLoops,
6758 StoreValues,
".cnt.addr", IsDependSource));
6765 "Standalone ordered directive should have either depend or doacross "
6768 assert(!S.hasAssociatedStmt() &&
"No associated statement must be in "
6769 "ordered depend|doacross construct.");
6771 if (
CGM.getLangOpts().OpenMPIRBuilder) {
6772 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
6773 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6785 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6788 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6794 if (
CGM.getLangOpts().OpenMPIRBuilder) {
6795 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
6796 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6802 auto FiniCB = [
this](InsertPointTy IP) {
6804 return llvm::Error::success();
6807 auto BodyGenCB = [&S,
C,
this](InsertPointTy AllocIP,
6808 InsertPointTy CodeGenIP,
6814 llvm::BasicBlock *CodeGenBB = CodeGenIP.getNodeParent();
6815 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
6816 Builder,
false,
".ordered.after");
6820 assert(S.getBeginLoc().isValid() &&
6821 "Outlined function call location must be valid.");
6824 OutlinedFn, CapturedVars);
6829 return llvm::Error::success();
6832 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6833 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
6834 OMPBuilder.createOrderedThreadsSimd(
Builder, BodyGenCB, FiniCB, !
C));
6840 auto &&
CodeGen = [&S,
C,
this](CodeGenFunction &CGF,
6845 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
6847 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
6848 OutlinedFn, CapturedVars);
6854 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6855 CGM.getOpenMPRuntime().emitOrderedRegion(*
this,
CodeGen, S.getBeginLoc(), !
C);
6862 "DestType must have scalar evaluation kind.");
6863 assert(!Val.
isAggregate() &&
"Must be a scalar or complex.");
6874 "DestType must have complex evaluation kind.");
6883 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
6885 assert(Val.
isComplex() &&
"Must be a scalar or complex.");
6890 Val.
getComplexVal().first, SrcElementType, DestElementType, Loc);
6892 Val.
getComplexVal().second, SrcElementType, DestElementType, Loc);
6898 LValue LVal,
RValue RVal) {
6899 if (LVal.isGlobalReg())
6906 llvm::AtomicOrdering AO, LValue LVal,
6908 if (LVal.isGlobalReg())
6911 LVal, Loc, llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO),
6920 *
this, RVal, RValTy, LVal.
getType(), Loc)),
6929 llvm_unreachable(
"Must be a scalar or complex.");
6937 assert(
V->isLValue() &&
"V of 'omp atomic read' is not lvalue");
6938 assert(
X->isLValue() &&
"X of 'omp atomic read' is not lvalue");
6947 case llvm::AtomicOrdering::Acquire:
6948 case llvm::AtomicOrdering::AcquireRelease:
6949 case llvm::AtomicOrdering::SequentiallyConsistent:
6951 llvm::AtomicOrdering::Acquire);
6953 case llvm::AtomicOrdering::Monotonic:
6954 case llvm::AtomicOrdering::Release:
6956 case llvm::AtomicOrdering::NotAtomic:
6957 case llvm::AtomicOrdering::Unordered:
6958 llvm_unreachable(
"Unexpected ordering.");
6965 llvm::AtomicOrdering AO,
const Expr *
X,
6968 assert(
X->isLValue() &&
"X of 'omp atomic write' is not lvalue");
6976 case llvm::AtomicOrdering::Release:
6977 case llvm::AtomicOrdering::AcquireRelease:
6978 case llvm::AtomicOrdering::SequentiallyConsistent:
6980 llvm::AtomicOrdering::Release);
6982 case llvm::AtomicOrdering::Acquire:
6983 case llvm::AtomicOrdering::Monotonic:
6985 case llvm::AtomicOrdering::NotAtomic:
6986 case llvm::AtomicOrdering::Unordered:
6987 llvm_unreachable(
"Unexpected ordering.");
6994 llvm::AtomicOrdering AO,
6995 bool IsXLHSInRHSPart) {
7000 if (BO == BO_Comma || !
Update.isScalar() || !
X.isSimple() ||
7002 (
Update.getScalarVal()->getType() !=
X.getAddress().getElementType())) ||
7003 !Context.getTargetInfo().hasBuiltinAtomic(
7004 Context.getTypeSize(
X.getType()), Context.toBits(
X.getAlignment())))
7005 return std::make_pair(
false,
RValue::get(
nullptr));
7008 if (
T->isIntegerTy())
7011 if (
T->isFloatingPointTy() && (BO == BO_Add || BO == BO_Sub))
7017 if (!CheckAtomicSupport(
Update.getScalarVal()->getType(), BO) ||
7018 !CheckAtomicSupport(
X.getAddress().getElementType(), BO))
7019 return std::make_pair(
false,
RValue::get(
nullptr));
7021 bool IsInteger =
X.getAddress().getElementType()->isIntegerTy();
7022 llvm::AtomicRMWInst::BinOp RMWOp;
7025 RMWOp = IsInteger ? llvm::AtomicRMWInst::Add : llvm::AtomicRMWInst::FAdd;
7028 if (!IsXLHSInRHSPart)
7029 return std::make_pair(
false,
RValue::get(
nullptr));
7030 RMWOp = IsInteger ? llvm::AtomicRMWInst::Sub : llvm::AtomicRMWInst::FSub;
7033 RMWOp = llvm::AtomicRMWInst::And;
7036 RMWOp = llvm::AtomicRMWInst::Or;
7039 RMWOp = llvm::AtomicRMWInst::Xor;
7043 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
7044 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Min
7045 : llvm::AtomicRMWInst::Max)
7046 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMin
7047 : llvm::AtomicRMWInst::UMax);
7049 RMWOp = IsXLHSInRHSPart ? llvm::AtomicRMWInst::FMin
7050 : llvm::AtomicRMWInst::FMax;
7054 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
7055 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Max
7056 : llvm::AtomicRMWInst::Min)
7057 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMax
7058 : llvm::AtomicRMWInst::UMin);
7060 RMWOp = IsXLHSInRHSPart ? llvm::AtomicRMWInst::FMax
7061 : llvm::AtomicRMWInst::FMin;
7064 RMWOp = llvm::AtomicRMWInst::Xchg;
7073 return std::make_pair(
false,
RValue::get(
nullptr));
7092 llvm_unreachable(
"Unsupported atomic update operation");
7094 llvm::Value *UpdateVal =
Update.getScalarVal();
7095 if (
auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
7097 UpdateVal = CGF.
Builder.CreateIntCast(
7098 IC,
X.getAddress().getElementType(),
7099 X.getType()->hasSignedIntegerRepresentation());
7101 UpdateVal = CGF.
Builder.CreateCast(llvm::Instruction::CastOps::UIToFP, IC,
7102 X.getAddress().getElementType());
7104 llvm::AtomicRMWInst *Res =
7121 if (
X.isGlobalReg()) {
7134 llvm::AtomicOrdering AO,
const Expr *
X,
7138 "Update expr in 'atomic update' must be a binary operator.");
7146 assert(
X->isLValue() &&
"X of 'omp atomic update' is not lvalue");
7153 auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](
RValue XRValue) {
7159 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
7166 case llvm::AtomicOrdering::Release:
7167 case llvm::AtomicOrdering::AcquireRelease:
7168 case llvm::AtomicOrdering::SequentiallyConsistent:
7170 llvm::AtomicOrdering::Release);
7172 case llvm::AtomicOrdering::Acquire:
7173 case llvm::AtomicOrdering::Monotonic:
7175 case llvm::AtomicOrdering::NotAtomic:
7176 case llvm::AtomicOrdering::Unordered:
7177 llvm_unreachable(
"Unexpected ordering.");
7195 llvm_unreachable(
"Must be a scalar or complex.");
7199 llvm::AtomicOrdering AO,
7200 bool IsPostfixUpdate,
const Expr *
V,
7202 const Expr *UE,
bool IsXLHSInRHSPart,
7204 assert(
X->isLValue() &&
"X of 'omp atomic capture' is not lvalue");
7205 assert(
V->isLValue() &&
"V of 'omp atomic capture' is not lvalue");
7214 "Update expr in 'atomic capture' must be a binary operator.");
7225 NewVValType = XRValExpr->
getType();
7227 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
7228 IsPostfixUpdate](
RValue XRValue) {
7232 NewVVal = IsPostfixUpdate ? XRValue : Res;
7236 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
7240 if (IsPostfixUpdate) {
7242 NewVVal = Res.second;
7253 NewVValType =
X->getType().getNonReferenceType();
7255 X->getType().getNonReferenceType(), Loc);
7256 auto &&Gen = [&NewVVal, ExprRValue](
RValue XRValue) {
7262 XLValue, ExprRValue, BO_Assign,
false, AO,
7267 NewVVal = IsPostfixUpdate ? Res.second : ExprRValue;
7283 case llvm::AtomicOrdering::Release:
7285 llvm::AtomicOrdering::Release);
7287 case llvm::AtomicOrdering::Acquire:
7289 llvm::AtomicOrdering::Acquire);
7291 case llvm::AtomicOrdering::AcquireRelease:
7292 case llvm::AtomicOrdering::SequentiallyConsistent:
7294 CGF, {}, Loc, llvm::AtomicOrdering::AcquireRelease);
7296 case llvm::AtomicOrdering::Monotonic:
7298 case llvm::AtomicOrdering::NotAtomic:
7299 case llvm::AtomicOrdering::Unordered:
7300 llvm_unreachable(
"Unexpected ordering.");
7306 CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO,
7308 const Expr *CE,
bool IsXBinopExpr,
bool IsPostfixUpdate,
bool IsFailOnly,
7310 llvm::OpenMPIRBuilder &OMPBuilder =
7313 OMPAtomicCompareOp Op;
7317 Op = OMPAtomicCompareOp::EQ;
7320 Op = OMPAtomicCompareOp::MIN;
7323 Op = OMPAtomicCompareOp::MAX;
7326 llvm_unreachable(
"unsupported atomic compare binary operator");
7330 Address XAddr = XLVal.getAddress();
7332 auto EmitRValueWithCastIfNeeded = [&CGF, Loc](
const Expr *
X,
const Expr *E) {
7337 if (NewE->
getType() ==
X->getType())
7342 llvm::Value *EVal = EmitRValueWithCastIfNeeded(
X, E);
7343 llvm::Value *DVal = D ? EmitRValueWithCastIfNeeded(
X, D) :
nullptr;
7344 if (
auto *CI = dyn_cast<llvm::ConstantInt>(EVal))
7345 EVal = CGF.
Builder.CreateIntCast(
7346 CI, XLVal.getAddress().getElementType(),
7349 if (
auto *CI = dyn_cast<llvm::ConstantInt>(DVal))
7350 DVal = CGF.
Builder.CreateIntCast(
7351 CI, XLVal.getAddress().getElementType(),
7354 llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{
7356 X->getType()->hasSignedIntegerRepresentation(),
7357 X->getType().isVolatileQualified()};
7358 llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal;
7362 VOpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
7363 V->getType()->hasSignedIntegerRepresentation(),
7364 V->getType().isVolatileQualified()};
7369 ROpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
7370 R->getType()->hasSignedIntegerRepresentation(),
7371 R->getType().isVolatileQualified()};
7374 if (FailAO == llvm::AtomicOrdering::NotAtomic) {
7377 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
7378 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
7379 IsPostfixUpdate, IsFailOnly));
7381 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
7382 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
7383 IsPostfixUpdate, IsFailOnly, FailAO));
7387 llvm::AtomicOrdering AO,
7388 llvm::AtomicOrdering FailAO,
bool IsPostfixUpdate,
7391 const Expr *CE,
bool IsXLHSInRHSPart,
7406 IsXLHSInRHSPart, Loc);
7408 case OMPC_compare: {
7410 IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly, Loc);
7414 llvm_unreachable(
"Clause is not allowed in 'omp atomic'.");
7419 llvm::AtomicOrdering AO =
CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
7421 llvm::AtomicOrdering FailAO = llvm::AtomicOrdering::NotAtomic;
7422 bool MemOrderingSpecified =
false;
7423 if (S.getSingleClause<OMPSeqCstClause>()) {
7424 AO = llvm::AtomicOrdering::SequentiallyConsistent;
7425 MemOrderingSpecified =
true;
7426 }
else if (S.getSingleClause<OMPAcqRelClause>()) {
7427 AO = llvm::AtomicOrdering::AcquireRelease;
7428 MemOrderingSpecified =
true;
7429 }
else if (S.getSingleClause<OMPAcquireClause>()) {
7430 AO = llvm::AtomicOrdering::Acquire;
7431 MemOrderingSpecified =
true;
7432 }
else if (S.getSingleClause<OMPReleaseClause>()) {
7433 AO = llvm::AtomicOrdering::Release;
7434 MemOrderingSpecified =
true;
7435 }
else if (S.getSingleClause<OMPRelaxedClause>()) {
7436 AO = llvm::AtomicOrdering::Monotonic;
7437 MemOrderingSpecified =
true;
7439 llvm::SmallSet<OpenMPClauseKind, 2> KindsEncountered;
7448 if (K == OMPC_seq_cst || K == OMPC_acq_rel || K == OMPC_acquire ||
7449 K == OMPC_release || K == OMPC_relaxed || K == OMPC_hint)
7452 KindsEncountered.insert(K);
7457 if (KindsEncountered.contains(OMPC_compare) &&
7458 KindsEncountered.contains(OMPC_capture))
7459 Kind = OMPC_compare;
7460 if (!MemOrderingSpecified) {
7461 llvm::AtomicOrdering DefaultOrder =
7462 CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
7463 if (DefaultOrder == llvm::AtomicOrdering::Monotonic ||
7464 DefaultOrder == llvm::AtomicOrdering::SequentiallyConsistent ||
7465 (DefaultOrder == llvm::AtomicOrdering::AcquireRelease &&
7466 Kind == OMPC_capture)) {
7468 }
else if (DefaultOrder == llvm::AtomicOrdering::AcquireRelease) {
7469 if (Kind == OMPC_unknown || Kind == OMPC_update || Kind == OMPC_write) {
7470 AO = llvm::AtomicOrdering::Release;
7471 }
else if (Kind == OMPC_read) {
7472 assert(Kind == OMPC_read &&
"Unexpected atomic kind.");
7473 AO = llvm::AtomicOrdering::Acquire;
7478 if (KindsEncountered.contains(OMPC_compare) &&
7479 KindsEncountered.contains(OMPC_fail)) {
7480 Kind = OMPC_compare;
7481 const auto *FailClause = S.getSingleClause<OMPFailClause>();
7484 if (FailParameter == llvm::omp::OMPC_relaxed)
7485 FailAO = llvm::AtomicOrdering::Monotonic;
7486 else if (FailParameter == llvm::omp::OMPC_acquire)
7487 FailAO = llvm::AtomicOrdering::Acquire;
7488 else if (FailParameter == llvm::omp::OMPC_seq_cst)
7489 FailAO = llvm::AtomicOrdering::SequentiallyConsistent;
7509 OMPLexicalScope
Scope(CGF, S, OMPD_target);
7512 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
7518 llvm::Function *Fn =
nullptr;
7519 llvm::Constant *FnID =
nullptr;
7521 const Expr *IfCond =
nullptr;
7523 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7524 if (
C->getNameModifier() == OMPD_unknown ||
7525 C->getNameModifier() == OMPD_target) {
7526 IfCond =
C->getCondition();
7532 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device(
7535 Device.setPointerAndInt(
C->getDevice(),
C->getModifier());
7540 bool IsOffloadEntry =
true;
7544 IsOffloadEntry =
false;
7547 IsOffloadEntry =
false;
7549 if (
CGM.
getLangOpts().OpenMPOffloadMandatory && !IsOffloadEntry) {
7553 StringRef ParentName;
7558 ParentName = CGF.
CurFn->getName();
7559 else if (
const auto *D = dyn_cast<CXXConstructorDecl>(CGF.
CurFuncDecl))
7561 else if (
const auto *D = dyn_cast<CXXDestructorDecl>(CGF.
CurFuncDecl))
7570 OMPLexicalScope
Scope(CGF, S, OMPD_task);
7571 auto &&SizeEmitter =
7574 if (IsOffloadEntry) {
7575 OMPLoopScope PreInitScope(CGF, D);
7578 NumIterations = CGF.
Builder.CreateIntCast(NumIterations, CGF.
Int64Ty,
7580 return NumIterations;
7598 CGF.
EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
7603 StringRef ParentName,
7609 llvm::Constant *
Addr;
7611 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7613 assert(Fn &&
Addr &&
"Target device function emission failed.");
7627 const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams);
7628 llvm::Function *OutlinedFn =
7633 OMPTeamsScope
Scope(CGF, S);
7638 const Expr *NumTeams = NT ? NT->getNumTeams().front() :
nullptr;
7639 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() :
nullptr;
7646 const Expr *IfCond =
nullptr;
7647 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7648 if (
C->getNameModifier() == OMPD_unknown ||
7649 C->getNameModifier() == OMPD_teams) {
7650 IfCond =
C->getCondition();
7659 const llvm::APInt One(32, 1);
7666 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() :
nullptr;
7692 CGF.
EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt());
7697 [](CodeGenFunction &) {
return nullptr; });
7702 auto *CS = S.getCapturedStmt(OMPD_teams);
7729 llvm::Constant *
Addr;
7731 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7733 assert(Fn &&
Addr &&
"Target device function emission failed.");
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.");
7839 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7844 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7856 [](CodeGenFunction &) {
return nullptr; });
7861 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7866 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7878 [](CodeGenFunction &) {
return nullptr; });
7883 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7889 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7901 [](CodeGenFunction &) {
return nullptr; });
7906 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7912 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7919 CGF, OMPD_distribute, CodeGenDistribute,
false);
7925 [](CodeGenFunction &) {
return nullptr; });
7929 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7930 llvm::Value *
Device =
nullptr;
7931 llvm::Value *NumDependences =
nullptr;
7932 llvm::Value *DependenceList =
nullptr;
7940 if (!
Data.Dependences.empty()) {
7942 std::tie(NumDependences, DependenciesArray) =
7943 CGM.getOpenMPRuntime().emitDependClause(*
this,
Data.Dependences,
7947 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
7952 "OMPNowaitClause clause is used separately in OMPInteropDirective.");
7955 if (!ItOMPInitClause.empty()) {
7958 llvm::Value *InteropvarPtr =
7960 llvm::omp::OMPInteropType InteropType =
7961 llvm::omp::OMPInteropType::Unknown;
7962 if (
C->getIsTarget()) {
7963 InteropType = llvm::omp::OMPInteropType::Target;
7965 assert(
C->getIsTargetSync() &&
7966 "Expected interop-type target/targetsync");
7967 InteropType = llvm::omp::OMPInteropType::TargetSync;
7969 OMPBuilder.createOMPInteropInit(
Builder, InteropvarPtr, InteropType,
7970 Device, NumDependences, DependenceList,
7971 Data.HasNowaitClause);
7975 if (!ItOMPDestroyClause.empty()) {
7978 llvm::Value *InteropvarPtr =
7980 OMPBuilder.createOMPInteropDestroy(
Builder, InteropvarPtr,
Device,
7981 NumDependences, DependenceList,
7982 Data.HasNowaitClause);
7985 auto ItOMPUseClause = S.getClausesOfKind<
OMPUseClause>();
7986 if (!ItOMPUseClause.empty()) {
7989 llvm::Value *InteropvarPtr =
7991 OMPBuilder.createOMPInteropUse(
Builder, InteropvarPtr,
Device,
7992 NumDependences, DependenceList,
7993 Data.HasNowaitClause);
8015 CGF, OMPD_distribute, CodeGenDistribute,
false);
8034 llvm::Constant *
Addr;
8036 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8038 assert(Fn &&
Addr &&
"Target device function emission failed.");
8067 CGF, OMPD_distribute, CodeGenDistribute,
false);
8086 llvm::Constant *
Addr;
8088 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8090 assert(Fn &&
Addr &&
"Target device function emission failed.");
8103 CGM.getOpenMPRuntime().emitCancellationPointCall(*
this, S.getBeginLoc(),
8108 const Expr *IfCond =
nullptr;
8109 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
8110 if (
C->getNameModifier() == OMPD_unknown ||
8111 C->getNameModifier() == OMPD_cancel) {
8112 IfCond =
C->getCondition();
8116 if (
CGM.getLangOpts().OpenMPIRBuilder) {
8117 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
8123 llvm::Value *IfCondition =
nullptr;
8127 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
8129 return Builder.restoreIP(AfterIP);
8133 CGM.getOpenMPRuntime().emitCancelCall(*
this, S.getBeginLoc(), IfCond,
8139 if (Kind == OMPD_parallel || Kind == OMPD_task ||
8140 Kind == OMPD_target_parallel || Kind == OMPD_taskloop ||
8141 Kind == OMPD_master_taskloop || Kind == OMPD_parallel_master_taskloop)
8143 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
8144 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
8145 Kind == OMPD_distribute_parallel_for ||
8146 Kind == OMPD_target_parallel_for ||
8147 Kind == OMPD_teams_distribute_parallel_for ||
8148 Kind == OMPD_target_teams_distribute_parallel_for);
8149 return OMPCancelStack.getExitBlock();
8154 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
8155 CaptureDeviceAddrMap) {
8156 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
8157 for (
const Expr *OrigVarIt :
C.varlist()) {
8159 if (!Processed.insert(OrigVD).second)
8166 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
8171 "Base should be the current struct!");
8172 MatchingVD = ME->getMemberDecl();
8177 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
8178 if (InitAddrIt == CaptureDeviceAddrMap.end())
8186 Address(InitAddrIt->second, Ty,
8188 assert(IsRegistered &&
"firstprivate var already registered as private");
8196 while (
const auto *OASE = dyn_cast<ArraySectionExpr>(
Base))
8197 Base = OASE->getBase()->IgnoreParenImpCasts();
8198 while (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(
Base))
8199 Base = ASE->getBase()->IgnoreParenImpCasts();
8205 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
8206 CaptureDeviceAddrMap) {
8207 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
8208 for (
const Expr *Ref :
C.varlist()) {
8210 if (!Processed.insert(OrigVD).second)
8216 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
8221 "Base should be the current struct!");
8222 MatchingVD = ME->getMemberDecl();
8227 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
8228 if (InitAddrIt == CaptureDeviceAddrMap.end())
8234 Address(InitAddrIt->second, Ty,
8247 (void)PrivateScope.
addPrivate(OrigVD, PrivAddr);
8255 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
8256 CGM.getOpenMPRuntime().registerVTable(S);
8264 bool PrivatizeDevicePointers =
false;
8266 bool &PrivatizeDevicePointers;
8269 explicit DevicePointerPrivActionTy(
bool &PrivatizeDevicePointers)
8270 : PrivatizeDevicePointers(PrivatizeDevicePointers) {}
8271 void Enter(CodeGenFunction &CGF)
override {
8272 PrivatizeDevicePointers =
true;
8275 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
8278 auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
8279 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
8283 auto &&PrivCodeGen = [&](CodeGenFunction &CGF,
PrePostActionTy &Action) {
8285 PrivatizeDevicePointers =
false;
8291 if (PrivatizeDevicePointers) {
8305 std::optional<OpenMPDirectiveKind> CaptureRegion;
8306 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
8309 for (
const Expr *E :
C->varlist()) {
8311 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
8315 for (
const Expr *E :
C->varlist()) {
8317 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
8321 CaptureRegion = OMPD_unknown;
8324 OMPLexicalScope
Scope(CGF, S, CaptureRegion);
8336 OMPLexicalScope
Scope(CGF, S);
8345 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
8351 const Expr *IfCond =
nullptr;
8353 IfCond =
C->getCondition();
8364 CGM.getOpenMPRuntime().emitTargetDataCalls(*
this, S, IfCond,
Device, RCG,
8372 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8376 const Expr *IfCond =
nullptr;
8378 IfCond =
C->getCondition();
8385 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8386 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8393 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8397 const Expr *IfCond =
nullptr;
8399 IfCond =
C->getCondition();
8406 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8407 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8414 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
8442 llvm::Constant *
Addr;
8444 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8446 assert(Fn &&
Addr &&
"Target device function emission failed.");
8466 CGF, OMPD_target_parallel_for, S.
hasCancel());
8482 llvm::Constant *
Addr;
8484 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8486 assert(Fn &&
Addr &&
"Target device function emission failed.");
8521 llvm::Constant *
Addr;
8523 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8525 assert(Fn &&
Addr &&
"Target device function emission failed.");
8547 const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop);
8550 OMPLexicalScope
Scope(*
this, S, OMPD_taskloop,
false);
8555 const Expr *IfCond =
nullptr;
8556 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
8557 if (
C->getNameModifier() == OMPD_unknown ||
8558 C->getNameModifier() == OMPD_taskloop) {
8559 IfCond =
C->getCondition();
8572 Data.Schedule.setInt(
false);
8575 (Clause->getModifier() == OMPC_GRAINSIZE_strict) ?
true :
false;
8578 Data.Schedule.setInt(
true);
8581 (Clause->getModifier() == OMPC_NUMTASKS_strict) ?
true :
false;
8595 llvm::BasicBlock *ContBlock =
nullptr;
8596 OMPLoopScope PreInitScope(CGF, S);
8597 if (CGF.ConstantFoldsToSimpleInteger(S.
getPreCond(), CondConstant)) {
8601 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock(
"taskloop.if.then");
8602 ContBlock = CGF.createBasicBlock(
"taskloop.if.end");
8604 CGF.getProfileCount(&S));
8605 CGF.EmitBlock(ThenBlock);
8606 CGF.incrementProfileCounter(&S);
8609 (void)CGF.EmitOMPLinearClauseInit(S);
8613 enum { LowerBound = 5, UpperBound, Stride, LastIter };
8615 auto *LBP = std::next(I, LowerBound);
8616 auto *UBP = std::next(I, UpperBound);
8617 auto *STP = std::next(I, Stride);
8618 auto *LIP = std::next(I, LastIter);
8626 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
8627 CGF.EmitOMPLinearClause(S, LoopScope);
8628 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
8633 CGF.EmitVarDecl(*IVDecl);
8634 CGF.EmitIgnoredExpr(S.
getInit());
8646 OMPLexicalScope
Scope(CGF, S, OMPD_taskloop,
false);
8656 [&S](CodeGenFunction &CGF) {
8657 emitOMPLoopBodyWithStopPoint(CGF, S,
8658 CodeGenFunction::JumpDest());
8660 [](CodeGenFunction &) {});
8665 CGF.EmitBranch(ContBlock);
8666 CGF.EmitBlock(ContBlock,
true);
8669 if (HasLastprivateClause) {
8670 CGF.EmitOMPLastprivateClauseFinal(
8672 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
8673 CGF.GetAddrOfLocalVar(*LIP),
false,
8674 (*LIP)->getType(), S.getBeginLoc())));
8677 CGF.EmitOMPLinearClauseFinal(S, [LIP, &S](CodeGenFunction &CGF) {
8678 return CGF.
Builder.CreateIsNotNull(
8680 (*LIP)->
getType(), S.getBeginLoc()));
8683 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
8684 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
8686 auto &&
CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
8688 OMPLoopScope PreInitScope(CGF, S);
8689 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S,
8690 OutlinedFn, SharedsTy,
8691 CapturedStruct, IfCond,
Data);
8693 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
8699 CGM.getOpenMPRuntime().emitTaskgroupRegion(
8701 [&S, &BodyGen, &TaskGen, &
Data](CodeGenFunction &CGF,
8721 OMPLexicalScope
Scope(*
this, S);
8733 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8734 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8745 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8746 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8757 OMPLexicalScope
Scope(*
this, S);
8758 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8769 OMPLexicalScope
Scope(*
this, S);
8770 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8776 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8781 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8782 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8794 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8799 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8800 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8812 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8817 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8818 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8830 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8835 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8836 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8850 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8854 const Expr *IfCond =
nullptr;
8856 IfCond =
C->getCondition();
8863 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8864 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8874 BindKind =
C->getBindKind();
8877 case OMPC_BIND_parallel:
8879 case OMPC_BIND_teams:
8881 case OMPC_BIND_thread:
8892 const auto *ForS = dyn_cast<ForStmt>(CS);
8903 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
8904 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_loop,
CodeGen);
8930 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
8935 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
8947 [](CodeGenFunction &) {
return nullptr; });
8952 std::string StatusMsg,
8956 StatusMsg +=
": DEVICE";
8958 StatusMsg +=
": HOST";
8965 llvm::dbgs() << StatusMsg <<
": " <<
FileName <<
": " << LineNo <<
"\n";
8988 CGF, OMPD_distribute, CodeGenDistribute,
false);
9017 CGF, OMPD_distribute, CodeGenDistribute,
false);
9050 llvm::Constant *
Addr;
9052 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
9054 assert(Fn &&
Addr &&
9055 "Target device function emission failed for 'target teams loop'.");
9066 CGF, OMPD_target_parallel_loop,
false);
9082 llvm::Constant *
Addr;
9084 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
9086 assert(Fn &&
Addr &&
"Target device function emission failed.");
9101 if (
const auto *SD = dyn_cast<OMPScanDirective>(&D)) {
9105 if (!D.hasAssociatedStmt() || !D.getAssociatedStmt())
9111 for (
const auto *
C : D.getClausesOfKind<OMPFirstprivateClause>()) {
9112 for (
const Expr *Ref :
C->varlist()) {
9116 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
9119 if (!CGF.LocalDeclMap.count(VD)) {
9131 if (
const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
9132 for (
const Expr *E : LD->counters()) {
9140 if (!CGF.LocalDeclMap.count(VD))
9144 for (
const auto *
C : D.getClausesOfKind<OMPOrderedClause>()) {
9145 if (!
C->getNumForLoops())
9147 for (
unsigned I = LD->getLoopsNumber(),
9148 E =
C->getLoopNumIterations().size();
9150 if (
const auto *VD = dyn_cast<OMPCapturedExprDecl>(
9153 if (!CGF.LocalDeclMap.count(VD))
9160 CGF.
EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
9163 if (D.getDirectiveKind() == OMPD_atomic ||
9164 D.getDirectiveKind() == OMPD_critical ||
9165 D.getDirectiveKind() == OMPD_section ||
9166 D.getDirectiveKind() == OMPD_master ||
9167 D.getDirectiveKind() == OMPD_masked ||
9168 D.getDirectiveKind() == OMPD_unroll ||
9169 D.getDirectiveKind() == OMPD_assume) {
9174 OMPSimdLexicalScope
Scope(*
this, D);
9175 CGM.getOpenMPRuntime().emitInlinedDirective(
9178 : D.getDirectiveKind(),
9186 for (
const auto *
C : S.getClausesOfKind<OMPHoldsClause>()) {
9187 const Expr *E =
C->getExpr();
9188 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 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 * getTransformedStmt() const
Gets the associated loops after the transformation.
This represents 'pragma omp loop' directive.
This represents 'grainsize' clause in the 'pragma omp ...' directive.
This represents 'hint' clause in the 'pragma omp ...' directive.
This represents clause 'inclusive' in the 'pragma omp scan' directive.
This represents the 'init' clause in 'pragma omp ...' directives.
Represents the 'pragma omp interchange' loop transformation directive.
Stmt * getTransformedStmt() const
Gets the associated loops after the transformation.
This represents 'pragma omp interop' directive.
This 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.
Stmt * getTransformedStmt() const
Gets/sets the associated loops after the transformation, i.e.
This represents 'simd' clause in the 'pragma omp ...' directive.
This represents 'pragma omp scan' directive.
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.
Stmt * getTransformedStmt() const
Gets/sets the associated loops after the transformation, i.e.
This represents the 'pragma omp stripe' loop transformation directive.
Stmt * getTransformedStmt() const
Gets/sets the associated loops after striping.
This represents 'pragma omp target data' directive.
This represents 'pragma omp target' directive.
This represents 'pragma omp target enter data' directive.
This represents 'pragma omp target exit data' directive.
This represents 'pragma omp target parallel' directive.
This represents 'pragma omp target parallel for' directive.
bool hasCancel() const
Return true if current directive has inner cancel directive.
This represents 'pragma omp target parallel for simd' directive.
This represents 'pragma omp target parallel loop' directive.
This represents 'pragma omp target simd' directive.
This represents 'pragma omp target teams' directive.
This represents 'pragma omp target teams distribute' combined directive.
This represents 'pragma omp target teams distribute parallel for' combined directive.
This represents 'pragma omp target teams distribute parallel for simd' combined directive.
This represents 'pragma omp target teams distribute simd' combined directive.
This represents 'pragma omp target teams loop' directive.
bool canBeParallelFor() const
Return true if current loop directive's associated loop can be a parallel for.
This represents 'pragma omp target update' directive.
This represents 'pragma omp 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.
Stmt * getTransformedStmt() const
Gets/sets the associated loops after tiling.
This represents the 'pragma omp unroll' loop transformation directive.
This represents the 'use' clause in 'pragma omp ...' directives.
This represents clause 'use_device_addr' in the 'pragma omp ...' directives.
This represents clause 'use_device_ptr' in the 'pragma omp ...' directives.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
TranslationUnitDecl * getTranslationUnitDecl() const
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
QualType getUIntPtrType() const
Return a type compatible with "uintptr_t" (C99 7.18.1.4), as defined by the target.
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
unsigned getOpenMPDefaultSimdAlign(QualType T) const
Get default simd alignment of the specified complete type in bits.
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
CanQualType getCanonicalTagType(const TagDecl *TD) const
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Represents an attribute applied to a statement.
ArrayRef< const Attr * > getAttrs() const
static BinaryOperator * Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, FPOptionsOverride FPFeatures)
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 EmitOMPDistributeSimdDirective(const OMPDistributeSimdDirective &S)
void EmitAutoVarDecl(const VarDecl &D)
EmitAutoVarDecl - Emit an auto variable declaration.
static void EmitOMPTargetTeamsDistributeDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeDirective &S)
Emit device code for the target teams distribute directive.
llvm::Function * GenerateOpenMPCapturedStmtFunctionAggregate(const CapturedStmt &S, const OMPExecutableDirective &D)
void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
void EmitOMPTargetParallelForDirective(const OMPTargetParallelForDirective &S)
const LangOptions & getLangOpts() const
LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
EmitAutoVarAlloca - Emit the alloca and debug information for a local variable.
void EmitAtomicUpdate(LValue LVal, llvm::AtomicOrdering AO, const llvm::function_ref< RValue(RValue)> &UpdateOp, bool IsVolatile)
Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr)
Load a pointer with type PtrTy stored at address Ptr.
void EmitOMPSplitDirective(const OMPSplitDirective &S)
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
void EmitOMPReductionClauseFinal(const OMPExecutableDirective &D, const OpenMPDirectiveKind ReductionKind)
Emit final update of reduction values to original variables at the end of the directive.
void EmitOMPLoopBody(const OMPLoopDirective &D, JumpDest LoopExit)
Helper for the OpenMP loop directives.
void EmitOMPScopeDirective(const OMPScopeDirective &S)
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
llvm::AssertingVH< llvm::Instruction > AllocaInsertPt
AllocaInsertPoint - This is an instruction in the entry block before which we prefer to insert alloca...
void EmitAggregateAssign(LValue Dest, LValue Src, QualType EltTy)
Emit an aggregate assignment.
CodeGenFunction * ParentCGF
JumpDest ReturnBlock
ReturnBlock - Unified return block.
void EmitOMPTargetTeamsDistributeSimdDirective(const OMPTargetTeamsDistributeSimdDirective &S)
const llvm::function_ref< void(CodeGenFunction &, llvm::Function *, const OMPTaskDataTy &)> TaskGenTy
llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Location)
Converts Location to a DebugLoc, if debug information is enabled.
bool EmitOMPCopyinClause(const OMPExecutableDirective &D)
Emit code for copyin clause in D directive.
void EmitOMPLinearClause(const OMPLoopDirective &D, CodeGenFunction::OMPPrivateScope &PrivateScope)
Emit initial code for linear clauses.
llvm::BasicBlock * OMPBeforeScanBlock
void EmitOMPInterchangeDirective(const OMPInterchangeDirective &S)
void EmitOMPPrivateLoopCounters(const OMPLoopDirective &S, OMPPrivateScope &LoopScope)
Emit initial code for loop counters of loop-based directives.
void GenerateOpenMPCapturedVars(const CapturedStmt &S, SmallVectorImpl< llvm::Value * > &CapturedVars)
void EmitOMPDepobjDirective(const OMPDepobjDirective &S)
void EmitOMPMetaDirective(const OMPMetaDirective &S)
void EmitOMPCriticalDirective(const OMPCriticalDirective &S)
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
void EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S)
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
void EmitOMPCancelDirective(const OMPCancelDirective &S)
void EmitOMPBarrierDirective(const OMPBarrierDirective &S)
llvm::Value * EmitComplexToScalarConversion(ComplexPairTy Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified complex type to the specified destination type,...
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 EmitOMPTargetSimdDirective(const OMPTargetSimdDirective &S)
void EmitOMPTeamsGenericLoopDirective(const OMPTeamsGenericLoopDirective &S)
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.
static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S)
Emit device code for the target simd directive.
llvm::Function * GenerateCapturedStmtFunction(const CapturedStmt &S)
Creates the outlined function for a CapturedStmt.
static void EmitOMPTargetParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForDirective &S)
Emit device code for the target parallel for directive.
uint64_t getProfileCount(const Stmt *S)
Get the profiler's count for the given statement.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)
ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant,...
static void EmitOMPTargetTeamsGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsGenericLoopDirective &S)
Emit device code for the target teams loop directive.
void EmitOMPTileDirective(const OMPTileDirective &S)
void EmitDecl(const Decl &D, bool EvaluateConditionDecl=false)
EmitDecl - Emit a declaration.
void EmitOMPAtomicDirective(const OMPAtomicDirective &S)
llvm::BasicBlock * OMPAfterScanBlock
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
ConstantEmission tryEmitAsConstant(const DeclRefExpr *RefExpr)
Try to emit a reference to the given value without producing it as an l-value.
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
void EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst)
Store of global named registers are always calls to intrinsics.
void EmitOMPParallelMasterTaskLoopDirective(const OMPParallelMasterTaskLoopDirective &S)
void EmitOMPDistributeParallelForSimdDirective(const OMPDistributeParallelForSimdDirective &S)
void EmitOMPSectionDirective(const OMPSectionDirective &S)
void EnsureInsertPoint()
EnsureInsertPoint - Ensure that an insertion point is defined so that emitted IR has a place to go.
void EmitOMPForSimdDirective(const OMPForSimdDirective &S)
llvm::LLVMContext & getLLVMContext()
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
void emitAlignmentAssumption(llvm::Value *PtrValue, QualType Ty, SourceLocation Loc, SourceLocation AssumptionLoc, llvm::Value *Alignment, llvm::Value *OffsetValue=nullptr)
static void EmitOMPTargetTeamsDistributeSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeSimdDirective &S)
Emit device code for the target teams distribute simd directive.
llvm::function_ref< void(CodeGenFunction &, const OMPLoopDirective &, JumpDest)> CodeGenLoopTy
llvm::Value * EmitScalarConversion(llvm::Value *Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified type to the specified destination type, both of which are LLVM s...
bool isTrivialInitializer(const Expr *Init)
Determine whether the given initializer is trivial in the sense that it requires no code to be genera...
void EmitOMPParallelMasterDirective(const OMPParallelMasterDirective &S)
void EmitOMPTaskBasedDirective(const OMPExecutableDirective &S, const OpenMPDirectiveKind CapturedRegion, const RegionCodeGenTy &BodyGen, const TaskGenTy &TaskGen, OMPTaskDataTy &Data)
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
void EmitOMPForDirective(const OMPForDirective &S)
void EmitOMPLinearClauseFinal(const OMPLoopDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
Emit final code for linear clauses.
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
void EmitExprAsInit(const Expr *init, const ValueDecl *D, LValue lvalue, bool capturedByInit)
EmitExprAsInit - Emits the code necessary to initialize a location in memory with the given initializ...
void EmitOMPSimdFinal(const OMPLoopDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
This class organizes the cross-function state that is used while generating LLVM code.
void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)
Set the attributes on the LLVM function for the given decl and function info.
llvm::Module & getModule() const
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
CodeGenTypes & getTypes()
const llvm::DataLayout & getDataLayout() const
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
const llvm::Triple & getTriple() const
ASTContext & getContext() const
const CodeGenOptions & getCodeGenOpts() const
StringRef getMangledName(GlobalDecl GD)
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
const CGFunctionInfo & arrangeDeviceKernelCallerDeclaration(QualType resultType, const FunctionArgList &args)
A device kernel caller function is an offload device entry point function with a target device depend...
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
llvm::Value * getPointer(CodeGenFunction &CGF) const
Address getAddress() const
void setAddress(Address address)
A stack of loop information corresponding to loop nesting levels.
void setVectorizeWidth(unsigned W)
Set the vectorize width for the next loop pushed.
void setParallel(bool Enable=true)
Set the next pushed loop as parallel.
void push(llvm::BasicBlock *Header, const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc)
Begin a new structured loop.
void setVectorizeEnable(bool Enable=true)
Set the next pushed loop 'vectorize.enable'.
A basic class for pre|post-action for advanced codegen sequence for OpenMP region.
virtual void Enter(CodeGenFunction &CGF)
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
static RValue getComplex(llvm::Value *V1, llvm::Value *V2)
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
std::pair< llvm::Value *, llvm::Value * > getComplexVal() const
getComplexVal - Return the real/imag components of this complex value.
An abstract representation of an aligned address.
llvm::PointerType * getType() const
Return the type of the pointer value.
llvm::Value * getPointer() const
Class intended to support codegen of all kind of the reduction clauses.
LValue getSharedLValue(unsigned N) const
Returns LValue for the reduction item.
void emitAggregateType(CodeGenFunction &CGF, unsigned N)
Emits the code for the variable-modified type, if required.
const VarDecl * getBaseDecl(unsigned N) const
Returns the base declaration of the reduction item.
void emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N)
Emits lvalue for the shared and original reduction item.
void emitInitialization(CodeGenFunction &CGF, unsigned N, Address PrivateAddr, Address SharedAddr, llvm::function_ref< bool(CodeGenFunction &)> DefaultInit)
Performs initialization of the private copy for the reduction item.
Address adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Adjusts PrivatedAddr for using instead of the original variable address in normal operations.
Class provides a way to call simple version of codegen for OpenMP region, or an advanced with possibl...
void setAction(PrePostActionTy &Action) const
Complex values, per C99 6.2.5p11.
CompoundStmt - This represents a group of statements like { stmt stmt }.
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
A reference to a declared variable, function, enum, etc.
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Decl - This represents one declaration (or definition), e.g.
SourceLocation getBodyRBrace() const
getBodyRBrace - Gets the right brace of the body, if a body exists.
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
SourceLocation getLocation() const
The name of a declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreImplicitAsWritten() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
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())))
@ OK_Ordinary
An ordinary object is located at an address in memory.
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ Tile
'tile' clause, allowed on 'loop' and Combined constructs.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_unknown
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
@ OMPC_DIST_SCHEDULE_unknown
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
bool isOpenMPGenericLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive constitutes a 'loop' directive in the outermost nest.
OpenMPBindClauseKind
OpenMP bindings for the 'bind' clause.
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.
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