31#include "llvm/ADT/SmallSet.h"
32#include "llvm/BinaryFormat/Dwarf.h"
33#include "llvm/Frontend/OpenMP/OMPConstants.h"
34#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
35#include "llvm/IR/Constants.h"
36#include "llvm/IR/DebugInfoMetadata.h"
37#include "llvm/IR/Instructions.h"
38#include "llvm/IR/Metadata.h"
39#include "llvm/Support/AtomicOrdering.h"
40#include "llvm/Support/Debug.h"
44using namespace llvm::omp;
46#define TTL_CODEGEN_TYPE "target-teams-loop-codegen"
62 if (DKind == OMPD_teams_loop)
64 if (
const auto *TTLD = dyn_cast<OMPTargetTeamsGenericLoopDirective>(&S);
65 TTLD && !TTLD->canBeParallelFor())
71 S.hasClausesOfKind<OMPReductionClause>() &&
73 !S.getSingleClause<OMPScheduleClause>() &&
74 !S.getSingleClause<OMPOrderedClause>();
81 void emitPreInitStmt(CodeGenFunction &CGF,
const OMPExecutableDirective &S) {
82 for (
const auto *
C : S.clauses()) {
83 if (
const auto *CPI = OMPClauseWithPreInit::get(
C)) {
84 if (
const auto *PreInit =
85 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
86 for (
const auto *I : PreInit->decls()) {
87 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
90 CodeGenFunction::AutoVarEmission Emission =
99 CodeGenFunction::OMPPrivateScope InlinedShareds;
101 static bool isCapturedVar(CodeGenFunction &CGF,
const VarDecl *VD) {
110 CodeGenFunction &CGF,
const OMPExecutableDirective &S,
111 const std::optional<OpenMPDirectiveKind> CapturedRegion = std::nullopt,
112 const bool EmitPreInitStmt =
true)
114 InlinedShareds(CGF) {
116 emitPreInitStmt(CGF, S);
119 assert(S.hasAssociatedStmt() &&
120 "Expected associated statement for inlined directive.");
121 const CapturedStmt *CS = S.getCapturedStmt(*CapturedRegion);
123 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
124 auto *VD =
C.getCapturedVar();
126 "Canonical decl must be captured.");
130 InlinedShareds.isGlobalVarCaptured(VD)),
135 (void)InlinedShareds.Privatize();
141class OMPParallelScope final :
public OMPLexicalScope {
142 bool EmitPreInitStmt(
const OMPExecutableDirective &S) {
150 OMPParallelScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
151 : OMPLexicalScope(CGF, S, std::nullopt,
152 EmitPreInitStmt(S)) {}
157class OMPTeamsScope final :
public OMPLexicalScope {
158 bool EmitPreInitStmt(
const OMPExecutableDirective &S) {
165 OMPTeamsScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
166 : OMPLexicalScope(CGF, S, std::nullopt,
167 EmitPreInitStmt(S)) {}
173 void emitPreInitStmt(CodeGenFunction &CGF,
const OMPLoopBasedDirective &S) {
174 const Stmt *PreInits;
175 CodeGenFunction::OMPMapVars PreCondVars;
176 if (
auto *LD = dyn_cast<OMPLoopDirective>(&S)) {
178 (void)OMPLoopBasedDirective::doForAllLoops(
179 LD->getInnermostCapturedStmt()->getCapturedStmt(),
180 true, LD->getLoopsNumber(),
181 [&CGF](
unsigned Cnt,
const Stmt *CurStmt) {
182 if (const auto *CXXFor = dyn_cast<CXXForRangeStmt>(CurStmt)) {
183 if (const Stmt *Init = CXXFor->getInit())
185 CGF.EmitStmt(CXXFor->getRangeStmt());
186 CGF.EmitStmt(CXXFor->getBeginStmt());
187 CGF.EmitStmt(CXXFor->getEndStmt());
191 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
192 for (
const auto *E : LD->counters()) {
199 for (
const auto *
C : LD->getClausesOfKind<OMPPrivateClause>()) {
200 for (
const Expr *IRef :
C->varlist()) {
202 const auto *OrigVD = dyn_cast<VarDecl>(OrigDecl);
205 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
206 QualType OrigVDTy = OrigVD->getType().getNonReferenceType();
216 (void)PreCondVars.
apply(CGF);
217 PreInits = LD->getPreInits();
218 }
else if (
const auto *
Tile = dyn_cast<OMPTileDirective>(&S)) {
219 PreInits =
Tile->getPreInits();
220 }
else if (
const auto *Stripe = dyn_cast<OMPStripeDirective>(&S)) {
221 PreInits = Stripe->getPreInits();
222 }
else if (
const auto *Unroll = dyn_cast<OMPUnrollDirective>(&S)) {
223 PreInits = Unroll->getPreInits();
224 }
else if (
const auto *Reverse = dyn_cast<OMPReverseDirective>(&S)) {
225 PreInits = Reverse->getPreInits();
226 }
else if (
const auto *Split = dyn_cast<OMPSplitDirective>(&S)) {
227 PreInits =
Split->getPreInits();
228 }
else if (
const auto *Interchange =
229 dyn_cast<OMPInterchangeDirective>(&S)) {
230 PreInits = Interchange->getPreInits();
231 }
else if (
const auto *Flatten = dyn_cast<OMPFlattenDirective>(&S)) {
232 PreInits = Flatten->getPreInits();
234 llvm_unreachable(
"Unknown loop-based directive kind.");
236 doEmitPreinits(PreInits);
243 const Stmt *PreInits;
244 if (
const auto *Fuse = dyn_cast<OMPFuseDirective>(&S)) {
245 PreInits = Fuse->getPreInits();
248 "Unknown canonical loop sequence transform directive kind.");
250 doEmitPreinits(PreInits);
253 void doEmitPreinits(
const Stmt *PreInits) {
259 if (
auto *PreInitCompound = dyn_cast<CompoundStmt>(PreInits))
260 llvm::append_range(PreInitStmts, PreInitCompound->body());
262 PreInitStmts.push_back(PreInits);
264 for (
const Stmt *S : PreInitStmts) {
267 if (
auto *PreInitDecl = dyn_cast<DeclStmt>(S)) {
268 for (
Decl *I : PreInitDecl->decls())
280 emitPreInitStmt(CGF, S);
285 emitPreInitStmt(CGF, S);
290 CodeGenFunction::OMPPrivateScope InlinedShareds;
292 static bool isCapturedVar(CodeGenFunction &CGF,
const VarDecl *VD) {
300 OMPSimdLexicalScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
302 InlinedShareds(CGF) {
303 for (
const auto *
C : S.clauses()) {
304 if (const auto *CPI = OMPClauseWithPreInit::get(C)) {
305 if (const auto *PreInit =
306 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
307 for (const auto *I : PreInit->decls()) {
308 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
309 CGF.EmitVarDecl(cast<VarDecl>(*I));
311 CodeGenFunction::AutoVarEmission Emission =
312 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
313 CGF.EmitAutoVarCleanups(Emission);
317 }
else if (
const auto *UDP = dyn_cast<OMPUseDevicePtrClause>(
C)) {
318 for (
const Expr *E : UDP->varlist()) {
320 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
323 }
else if (
const auto *UDP = dyn_cast<OMPUseDeviceAddrClause>(
C)) {
324 for (
const Expr *E : UDP->varlist()) {
326 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
333 if (
const auto *TG = dyn_cast<OMPTaskgroupDirective>(&S)) {
334 if (
const Expr *E = TG->getReductionRef())
339 llvm::DenseSet<CanonicalDeclPtr<const Decl>> CopyArrayTemps;
340 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
341 if (C->getModifier() != OMPC_REDUCTION_inscan)
343 for (const Expr *E : C->copy_array_temps())
344 CopyArrayTemps.insert(cast<DeclRefExpr>(E)->getDecl());
346 const auto *CS = cast_or_null<CapturedStmt>(S.getAssociatedStmt());
349 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
350 auto *VD =
C.getCapturedVar();
351 if (CopyArrayTemps.contains(VD))
354 "Canonical decl must be captured.");
355 DeclRefExpr DRE(CGF.
getContext(),
const_cast<VarDecl *
>(VD),
356 isCapturedVar(CGF, VD) ||
358 InlinedShareds.isGlobalVarCaptured(VD)),
366 (void)InlinedShareds.Privatize();
378 if (Kind == OMPD_teams_loop)
379 return OMPD_teams_distribute;
380 if (Kind == OMPD_target_teams_loop)
382 ? OMPD_target_teams_distribute_parallel_for
383 : OMPD_target_teams_distribute;
385 if (Kind != OMPD_loop)
390 BindKind =
C->getBindKind();
393 case OMPC_BIND_parallel:
395 case OMPC_BIND_teams:
396 return OMPD_distribute;
397 case OMPC_BIND_thread:
424 if (
const auto *OrigDRE = dyn_cast<DeclRefExpr>(E)) {
425 if (
const auto *OrigVD = dyn_cast<VarDecl>(OrigDRE->getDecl())) {
426 OrigVD = OrigVD->getCanonicalDecl();
432 OrigDRE->getType(),
VK_LValue, OrigDRE->getExprLoc());
435 if (
const auto *OrigBD = dyn_cast<BindingDecl>(OrigDRE->getDecl())) {
442 IsCaptured, OrigDRE->getType(),
VK_LValue,
443 OrigDRE->getExprLoc());
452 llvm::Value *Size =
nullptr;
453 auto SizeInChars =
C.getTypeSizeInChars(Ty);
454 if (SizeInChars.isZero()) {
462 SizeInChars =
C.getTypeSizeInChars(Ty);
463 if (SizeInChars.isZero())
464 return llvm::ConstantInt::get(
SizeTy, 0);
465 return Builder.CreateNUWMul(Size,
CGM.getSize(SizeInChars));
467 return CGM.getSize(SizeInChars);
477 I != E; ++I, ++CurField, ++CurCap) {
478 if (CurField->hasCapturedVLAType()) {
481 CapturedVars.push_back(Val);
482 }
else if (CurCap->capturesThis()) {
483 CapturedVars.push_back(CXXThisValue);
484 }
else if (CurCap->capturesVariableByCopy()) {
489 if (!CurField->getType()->isAnyPointerType()) {
493 Twine(CurCap->getCapturedVar()->getName(),
".casted"));
509 CapturedVars.push_back(CV);
511 assert(CurCap->capturesVariable() &&
"Expected capture by reference.");
514 llvm::Type *ArgTy =
ConvertType(CurField->getType());
515 if (
Addr->getType() != ArgTy)
517 CapturedVars.push_back(
Addr);
537 if (
T->isLValueReferenceType())
538 return C.getLValueReferenceType(
541 if (
T->isPointerType())
543 if (
const ArrayType *A =
T->getAsArrayTypeUnsafe()) {
544 if (
const auto *VLA = dyn_cast<VariableArrayType>(A))
546 if (!A->isVariablyModifiedType())
547 return C.getCanonicalType(
T);
549 return C.getCanonicalParamType(
T);
554struct FunctionOptions {
556 const CapturedStmt *S =
nullptr;
559 const bool UIntPtrCastRequired =
true;
562 const bool RegisterCastedArgsOnly =
false;
564 const StringRef FunctionName;
567 const bool IsDeviceKernel =
false;
568 explicit FunctionOptions(
const CapturedStmt *S,
bool UIntPtrCastRequired,
569 bool RegisterCastedArgsOnly, StringRef FunctionName,
570 SourceLocation Loc,
bool IsDeviceKernel)
571 : S(S), UIntPtrCastRequired(UIntPtrCastRequired),
572 RegisterCastedArgsOnly(UIntPtrCastRequired && RegisterCastedArgsOnly),
573 FunctionName(FunctionName), Loc(Loc), IsDeviceKernel(IsDeviceKernel) {}
579 llvm::MapVector<
const Decl *, std::pair<const VarDecl *, Address>>
581 llvm::DenseMap<
const Decl *, std::pair<const Expr *, llvm::Value *>>
583 llvm::Value *&CXXThisValue,
const FunctionOptions &FO) {
586 assert(CD->
hasBody() &&
"missing CapturedDecl body");
588 CXXThisValue =
nullptr;
600 if (!FO.UIntPtrCastRequired) {
620 if (FO.UIntPtrCastRequired &&
621 ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) ||
622 I->capturesVariableArrayType()))
625 if (I->capturesVariable() || I->capturesVariableByCopy()) {
626 CapVar = I->getCapturedVar();
628 }
else if (I->capturesThis()) {
631 assert(I->capturesVariableArrayType());
634 if (ArgType->isVariablyModifiedType())
641 }
else if (DebugFunctionDecl && (CapVar || I->capturesThis())) {
643 Ctx, DebugFunctionDecl,
644 CapVar ? CapVar->
getBeginLoc() : FD->getBeginLoc(),
645 CapVar ? CapVar->
getLocation() : FD->getLocation(), II, ArgType,
651 Args.emplace_back(Arg);
653 TargetArgs.emplace_back(
654 FO.UIntPtrCastRequired
675 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
681 if (CGM.
getTriple().isSPIRV() && !FO.IsDeviceKernel)
682 F->setCallingConv(llvm::CallingConv::SPIR_FUNC);
685 F->setDoesNotThrow();
689 F->removeFnAttr(llvm::Attribute::NoInline);
690 F->addFnAttr(llvm::Attribute::AlwaysInline);
693 F->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
697 FO.UIntPtrCastRequired ? FO.Loc : FO.S->
getBeginLoc(),
698 FO.UIntPtrCastRequired ? FO.Loc
705 if (!FO.UIntPtrCastRequired && Args[Cnt] != TargetArgs[Cnt]) {
713 if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
714 const VarDecl *CurVD = I->getCapturedVar();
715 if (!FO.RegisterCastedArgsOnly)
716 LocalAddrs.insert({Args[Cnt], {CurVD, LocalAddr}});
724 if (FD->hasCapturedVLAType()) {
725 if (FO.UIntPtrCastRequired) {
728 Args[Cnt]->getName(), ArgLVal),
733 VLASizes.try_emplace(Args[Cnt], VAT->
getSizeExpr(), ExprArg);
734 }
else if (I->capturesVariable()) {
735 const VarDecl *Var = I->getCapturedVar();
737 Address ArgAddr = ArgLVal.getAddress();
738 if (ArgLVal.getType()->isLValueReferenceType()) {
741 assert(ArgLVal.getType()->isPointerType());
743 ArgAddr, ArgLVal.getType()->castAs<
PointerType>());
745 if (!FO.RegisterCastedArgsOnly) {
749 }
else if (I->capturesVariableByCopy()) {
750 assert(!FD->getType()->isAnyPointerType() &&
751 "Not expecting a captured pointer.");
752 const VarDecl *Var = I->getCapturedVar();
753 LocalAddrs.insert({Args[Cnt],
754 {Var, FO.UIntPtrCastRequired
756 CGF, I->getLocation(), FD->getType(),
757 Args[Cnt]->getName(), ArgLVal)
758 : ArgLVal.getAddress()}});
761 assert(I->capturesThis());
763 LocalAddrs.insert({Args[Cnt], {
nullptr, ArgLVal.getAddress()}});
774 llvm::MapVector<
const Decl *, std::pair<const VarDecl *, Address>>
776 llvm::DenseMap<
const Decl *, std::pair<const Expr *, llvm::Value *>>
778 llvm::Value *&CXXThisValue, llvm::Value *&ContextV,
const CapturedStmt &CS,
783 CXXThisValue =
nullptr;
793 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
797 F->setDoesNotThrow();
804 llvm::Type *PtrTy = CGF.
Builder.getPtrTy();
805 llvm::Align PtrAlign = CGM.
getDataLayout().getPointerABIAlignment(0);
808 for (
auto [FD,
C, FieldIdx] :
811 llvm::Value *SlotPtr =
812 CGF.
Builder.CreateConstInBoundsGEP1_32(PtrTy, ContextV, FieldIdx);
818 if (
C.capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
819 const VarDecl *CurVD =
C.getCapturedVar();
820 Slot->setName(CurVD->
getName());
821 Address SlotAddr(Slot, PtrTy, SlotAlign);
822 LocalAddrs.insert({FD, {CurVD, SlotAddr}});
823 }
else if (FD->hasCapturedVLAType()) {
830 VLASizes.try_emplace(FD, VAT->
getSizeExpr(), ExprArg);
831 }
else if (
C.capturesVariable()) {
832 const VarDecl *Var =
C.getCapturedVar();
836 Slot->setName(Var->
getName() +
".addr");
837 Address SlotAddr(Slot, PtrTy, SlotAlign);
838 LocalAddrs.insert({FD, {Var, SlotAddr}});
841 PtrTy, Slot, PtrAlign, Var->
getName());
842 LocalAddrs.insert({FD,
846 }
else if (
C.capturesVariableByCopy()) {
847 assert(!FD->getType()->isAnyPointerType() &&
848 "Not expecting a captured pointer.");
849 const VarDecl *Var =
C.getCapturedVar();
864 LocalAddrs.insert({FD, {Var, CopyAddr}});
866 assert(
C.capturesThis() &&
"Default case expected to be CXX 'this'");
869 Address SlotAddr(Slot, PtrTy, SlotAlign);
870 LocalAddrs.insert({FD, {
nullptr, SlotAddr}});
882 "CapturedStmtInfo should be set when generating the captured function");
885 bool NeedWrapperFunction =
888 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs,
890 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes,
893 llvm::raw_svector_ostream Out(Buffer);
896 bool IsDeviceKernel =
CGM.getOpenMPRuntime().isGPU() &&
898 D.getCapturedStmt(OMPD_target) == &S;
899 CodeGenFunction WrapperCGF(
CGM,
true);
900 llvm::Function *WrapperF =
nullptr;
901 if (NeedWrapperFunction) {
904 FunctionOptions WrapperFO(&S,
true,
911 WrapperCGF.CXXThisValue, WrapperFO);
914 FunctionOptions FO(&S, !NeedWrapperFunction,
false,
915 Out.str(), Loc, !NeedWrapperFunction && IsDeviceKernel);
917 *
this, WrapperArgs, WrapperLocalAddrs, WrapperVLASizes, CXXThisValue, FO);
919 for (
const auto &LocalAddrPair : WrapperLocalAddrs) {
920 if (LocalAddrPair.second.first) {
921 LocalScope.addPrivate(LocalAddrPair.second.first,
922 LocalAddrPair.second.second);
925 (void)LocalScope.Privatize();
926 for (
const auto &VLASizePair : WrapperVLASizes)
927 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
930 LocalScope.ForceCleanup();
932 if (!NeedWrapperFunction)
936 WrapperF->removeFromParent();
937 F->getParent()->getFunctionList().insertAfter(F->getIterator(), WrapperF);
940 auto *PI = F->arg_begin();
941 for (
const auto *Arg : Args) {
943 auto I = LocalAddrs.find(Arg);
944 if (I != LocalAddrs.end()) {
947 I->second.first ? I->second.first->getType() : Arg->getType(),
953 auto EI = VLASizes.find(Arg);
954 if (EI != VLASizes.end()) {
966 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
976 "CapturedStmtInfo should be set when generating the captured function");
980 bool NeedWrapperFunction =
983 CodeGenFunction WrapperCGF(
CGM,
true);
984 llvm::Function *WrapperF =
nullptr;
985 llvm::Value *WrapperContextV =
nullptr;
986 if (NeedWrapperFunction) {
989 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>>
991 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>>
994 WrapperCGF, WrapperArgs, WrapperLocalAddrs, WrapperVLASizes,
995 WrapperCGF.CXXThisValue, WrapperContextV, S, Loc, FunctionName);
999 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs;
1000 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes;
1003 if (NeedWrapperFunction) {
1005 llvm::raw_svector_ostream Out(Buffer);
1006 Out << FunctionName <<
"_debug__";
1008 FunctionOptions FO(&S,
false,
1009 false, Out.str(), Loc,
1014 llvm::Value *ContextV =
nullptr;
1016 CXXThisValue, ContextV, S, Loc,
1025 llvm::Align PtrAlign =
CGM.getDataLayout().getPointerABIAlignment(0);
1026 llvm::Value *SlotPtr =
Builder.CreateConstInBoundsGEP1_32(
1027 Builder.getPtrTy(), ContextV, FieldIdx,
1028 Twine(Param->getName()) +
".addr");
1029 llvm::Value *ParamAddr =
1030 Builder.CreateAlignedLoad(
Builder.getPtrTy(), SlotPtr, PtrAlign);
1031 llvm::Value *ParamVal =
Builder.CreateAlignedLoad(
1032 Builder.getPtrTy(), ParamAddr, PtrAlign, Param->getName());
1035 Builder.CreateStore(ParamVal, ParamLocalAddr);
1036 LocalAddrs.insert({Param, {Param, ParamLocalAddr}});
1042 for (
const auto &LocalAddrPair : LocalAddrs) {
1043 if (LocalAddrPair.second.first)
1044 LocalScope.addPrivate(LocalAddrPair.second.first,
1045 LocalAddrPair.second.second);
1047 (void)LocalScope.Privatize();
1048 for (
const auto &VLASizePair : VLASizes)
1049 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
1050 PGO->assignRegionCounters(
GlobalDecl(CD), F);
1052 (void)LocalScope.ForceCleanup();
1055 if (!NeedWrapperFunction)
1059 WrapperF->removeFromParent();
1060 F->getParent()->getFunctionList().insertAfter(F->getIterator(), WrapperF);
1062 llvm::Align PtrAlign =
CGM.getDataLayout().getPointerABIAlignment(0);
1065 "Expected context param at position 0 for target regions");
1066 assert(RD->
getNumFields() + 1 == F->getNumOperands() &&
1067 "Argument count mismatch");
1069 for (
auto [FD, InnerParam, SlotIdx] : llvm::zip(
1071 llvm::Value *SlotPtr = WrapperCGF.
Builder.CreateConstInBoundsGEP1_32(
1072 WrapperCGF.
Builder.getPtrTy(), WrapperContextV, SlotIdx);
1074 WrapperCGF.
Builder.getPtrTy(), SlotPtr, PtrAlign);
1076 InnerParam.getType(), Slot, PtrAlign, InnerParam.getName());
1077 CallArgs.push_back(Val);
1082 auto InnerParam = F->arg_begin() + SlotIdx;
1083 llvm::Value *SlotPtr = WrapperCGF.
Builder.CreateConstInBoundsGEP1_32(
1084 WrapperCGF.
Builder.getPtrTy(), WrapperContextV, SlotIdx);
1086 WrapperCGF.
Builder.getPtrTy(), SlotPtr, PtrAlign);
1088 InnerParam->getType(), Slot, PtrAlign, InnerParam->getName());
1089 CallArgs.push_back(Val);
1091 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
1107 llvm::Value *NumElements =
emitArrayLength(ArrayTy, ElementTy, DestAddr);
1114 DestBegin, NumElements);
1119 llvm::Value *IsEmpty =
1120 Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arraycpy.isempty");
1121 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
1124 llvm::BasicBlock *EntryBB =
Builder.GetInsertBlock();
1129 llvm::PHINode *SrcElementPHI =
1130 Builder.CreatePHI(SrcBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
1131 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
1136 llvm::PHINode *DestElementPHI =
Builder.CreatePHI(
1137 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
1138 DestElementPHI->addIncoming(DestBegin, EntryBB);
1144 CopyGen(DestElementCurrent, SrcElementCurrent);
1147 llvm::Value *DestElementNext =
1149 1,
"omp.arraycpy.dest.element");
1150 llvm::Value *SrcElementNext =
1152 1,
"omp.arraycpy.src.element");
1155 Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
1156 Builder.CreateCondBr(Done, DoneBB, BodyBB);
1157 DestElementPHI->addIncoming(DestElementNext,
Builder.GetInsertBlock());
1158 SrcElementPHI->addIncoming(SrcElementNext,
Builder.GetInsertBlock());
1168 const auto *BO = dyn_cast<BinaryOperator>(
Copy);
1169 if (BO && BO->getOpcode() == BO_Assign) {
1178 DestAddr, SrcAddr, OriginalType,
1206 bool DeviceConstTarget =
getLangOpts().OpenMPIsTargetDevice &&
1208 bool FirstprivateIsLastprivate =
false;
1209 llvm::SmallDenseMap<const Decl *, OpenMPLastprivateModifier> Lastprivates;
1210 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1211 for (
const auto *D :
C->varlist()) {
1216 llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
1221 bool MustEmitFirstprivateCopy =
1222 CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown;
1223 for (
const auto *
C : D.getClausesOfKind<OMPFirstprivateClause>()) {
1224 const auto *IRef =
C->varlist_begin();
1225 const auto *InitsRef =
C->inits().begin();
1226 for (
const Expr *IInit :
C->private_copies()) {
1230 if (
const auto *BD = dyn_cast<BindingDecl>(OrigDecl)) {
1232 bool ThisFirstprivateIsLastprivate =
1233 Lastprivates.count(BD->getCanonicalDecl()) > 0;
1237 if (!MustEmitFirstprivateCopy && !ThisFirstprivateIsLastprivate) {
1239 if (!FD->getType()->isReferenceType()) {
1242 assert(IsRegistered &&
1243 "firstprivate var already registered as firstprivate");
1251 const auto *VDInit =
1258 if (
Type->isArrayType()) {
1273 RunCleanupsScope InitScope(*this);
1275 setAddrOfLocalVar(VDInit, SrcElement);
1276 EmitAnyExprToMem(Init, DestElement,
1277 Init->getType().getQualifiers(),
1279 LocalDeclMap.erase(VDInit);
1288 setAddrOfLocalVar(VDInit, OriginalAddr);
1290 LocalDeclMap.erase(VDInit);
1293 IsRegistered = PrivateScope.
addPrivate(BD, VDAddr);
1296 assert(IsRegistered &&
1297 "firstprivate var already registered as firstprivate");
1299 FirstprivateIsLastprivate =
1300 FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate;
1307 const VarDecl *OrigVD = dyn_cast<VarDecl>(OrigDecl);
1308 assert(OrigVD &&
"Expected VarDecl for non-BindingDecl firstprivate");
1309 bool ThisFirstprivateIsLastprivate =
1312 if (!MustEmitFirstprivateCopy && !ThisFirstprivateIsLastprivate && FD &&
1314 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
1324 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
1330 FirstprivateIsLastprivate =
1331 FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate;
1333 const auto *VDInit =
1352 assert(!CE &&
"Expected non-constant firstprivate.");
1359 if (
Type->isArrayType()) {
1375 RunCleanupsScope InitScope(*this);
1377 setAddrOfLocalVar(VDInit, SrcElement);
1378 EmitAnyExprToMem(Init, DestElement,
1379 Init->getType().getQualifiers(),
1381 LocalDeclMap.erase(VDInit);
1392 setAddrOfLocalVar(VDInit, OriginalAddr);
1394 LocalDeclMap.erase(VDInit);
1396 if (ThisFirstprivateIsLastprivate &&
1398 OMPC_LASTPRIVATE_conditional) {
1403 (*IRef)->getExprLoc());
1404 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1408 LocalDeclMap.erase(VD);
1409 setAddrOfLocalVar(VD, VDAddr);
1411 IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1413 assert(IsRegistered &&
1414 "firstprivate var already registered as private");
1422 return FirstprivateIsLastprivate && !EmittedAsFirstprivate.empty();
1430 llvm::SmallDenseSet<const ValueDecl *> EmittedAsPrivate;
1431 for (
const auto *
C : D.getClausesOfKind<OMPPrivateClause>()) {
1432 auto IRef =
C->varlist_begin();
1433 for (
const Expr *IInit :
C->private_copies()) {
1436 if (EmittedAsPrivate.insert(
cast<ValueDecl>(OrigDecl->getCanonicalDecl()))
1441 assert(IsRegistered &&
"private var already registered as private");
1456 llvm::DenseSet<const VarDecl *> CopiedVars;
1457 llvm::BasicBlock *CopyBegin =
nullptr, *CopyEnd =
nullptr;
1459 auto IRef =
C->varlist_begin();
1460 auto ISrcRef =
C->source_exprs().begin();
1461 auto IDestRef =
C->destination_exprs().begin();
1462 for (
const Expr *AssignOp :
C->assignment_ops()) {
1471 getContext().getTargetInfo().isTLSSupported()) {
1473 "Copyin threadprivates should have been captured!");
1477 LocalDeclMap.erase(VD);
1481 :
CGM.GetAddrOfGlobal(VD),
1482 CGM.getTypes().ConvertTypeForMem(VD->
getType()),
1487 if (CopiedVars.size() == 1) {
1493 auto *MasterAddrInt =
Builder.CreatePtrToInt(
1495 auto *PrivateAddrInt =
Builder.CreatePtrToInt(
1498 Builder.CreateICmpNE(MasterAddrInt, PrivateAddrInt), CopyBegin,
1504 const auto *DestVD =
1525 bool HasAtLeastOneLastprivate =
false;
1527 llvm::DenseSet<const VarDecl *> SIMDLCVs;
1530 for (
const Expr *
C : LoopDirective->counters()) {
1535 llvm::SmallDenseSet<const ValueDecl *> AlreadyEmittedVars;
1536 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1537 HasAtLeastOneLastprivate =
true;
1540 const auto *IRef =
C->varlist_begin();
1541 const auto *IDestRef =
C->destination_exprs().begin();
1542 for (
const Expr *IInit :
C->private_copies()) {
1547 if (
const auto *BD = dyn_cast<BindingDecl>(OrigDecl)) {
1548 if (AlreadyEmittedVars.insert(
cast<ValueDecl>(BD->getCanonicalDecl()))
1550 const auto *DestVD =
1562 bool IsRegistered = PrivateScope.
addPrivate(BD, VDAddr);
1563 assert(IsRegistered &&
1564 "lastprivate binding already registered as private");
1575 if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) {
1576 const auto *DestVD =
1581 (*IRef)->getType(),
VK_LValue, (*IRef)->getExprLoc());
1586 if (IInit && !SIMDLCVs.count(OrigVD->getCanonicalDecl())) {
1589 if (
C->getKind() == OMPC_LASTPRIVATE_conditional) {
1590 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1592 setAddrOfLocalVar(VD, VDAddr);
1598 bool IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1599 assert(IsRegistered &&
1600 "lastprivate var already registered as private");
1608 return HasAtLeastOneLastprivate;
1613 llvm::Value *IsLastIterCond) {
1622 llvm::BasicBlock *ThenBB =
nullptr;
1623 llvm::BasicBlock *DoneBB =
nullptr;
1624 if (IsLastIterCond) {
1628 llvm::any_of(D.getClausesOfKind<OMPLastprivateClause>(),
1629 [](
const OMPLastprivateClause *
C) {
1630 return C->getKind() == OMPC_LASTPRIVATE_conditional;
1632 CGM.getOpenMPRuntime().emitBarrierCall(*
this, D.getBeginLoc(),
1639 Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB);
1642 llvm::DenseSet<const ValueDecl *> AlreadyEmittedVars;
1643 llvm::SmallDenseMap<const VarDecl *, const Expr *> LoopCountersAndUpdates;
1644 if (
const auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) {
1645 auto IC = LoopDirective->counters().begin();
1646 for (
const Expr *F : LoopDirective->finals()) {
1650 AlreadyEmittedVars.insert(D);
1652 LoopCountersAndUpdates[D] = F;
1656 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1657 auto IRef =
C->varlist_begin();
1658 auto ISrcRef =
C->source_exprs().begin();
1659 auto IDestRef =
C->destination_exprs().begin();
1660 for (
const Expr *AssignOp :
C->assignment_ops()) {
1665 const VarDecl *PrivateVD =
nullptr;
1667 if ((BD = dyn_cast<BindingDecl>(PrivateDecl))) {
1672 if (LocalDeclMap.count(SrcVD)) {
1675 }
else if (OMPPrivatizedBindings.count(BD)) {
1684 const auto *CanonicalVD =
1690 .insert(PrivateVD ?
static_cast<const ValueDecl *
>(CanonicalVD)
1698 if (
const Expr *FinalExpr =
1699 LoopCountersAndUpdates.lookup(CanonicalVD))
1704 const auto *DestVD =
1712 auto It = OMPPrivatizedBindings.find(BD);
1713 assert(It != OMPPrivatizedBindings.end() &&
1714 "BindingDecl should be privatized");
1715 PrivateAddr = It->second;
1720 Builder.CreateLoad(PrivateAddr),
1721 CGM.getTypes().ConvertTypeForMem(RefTy->getPointeeType()),
1722 CGM.getNaturalTypeAlignment(RefTy->getPointeeType()));
1725 if (
C->getKind() == OMPC_LASTPRIVATE_conditional)
1726 CGM.getOpenMPRuntime().emitLastprivateConditionalFinalUpdate(
1728 (*IRef)->getExprLoc());
1731 EmitOMPCopy(
Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp);
1737 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
1757 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1758 if (ForInscan != (
C->getModifier() == OMPC_REDUCTION_inscan))
1760 Shareds.append(
C->varlist_begin(),
C->varlist_end());
1761 Privates.append(
C->privates().begin(),
C->privates().end());
1762 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1763 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1764 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1765 if (
C->getModifier() == OMPC_REDUCTION_task) {
1766 Data.ReductionVars.append(
C->privates().begin(),
C->privates().end());
1767 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
1768 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
1769 Data.ReductionOps.append(
C->reduction_ops().begin(),
1770 C->reduction_ops().end());
1771 TaskLHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1772 TaskRHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1777 auto *ILHS = LHSs.begin();
1778 auto *IRHS = RHSs.begin();
1780 for (
const Expr *IRef : Shareds) {
1787 [&Emission](CodeGenFunction &CGF) {
1788 CGF.EmitAutoVarInit(Emission);
1796 assert(IsRegistered &&
"private var already registered as private");
1804 if (isaOMPArraySectionExpr &&
Type->isVariablyModifiedType()) {
1809 }
else if ((isaOMPArraySectionExpr &&
Type->isScalarType()) ||
1827 PrivateScope.
addPrivate(LHSVD, OriginalAddr);
1838 if (!
Data.ReductionVars.empty()) {
1840 Data.IsReductionWithTaskMod =
true;
1842 llvm::Value *ReductionDesc =
CGM.getOpenMPRuntime().emitTaskReductionInit(
1843 *
this, D.getBeginLoc(), TaskLHSs, TaskRHSs,
Data);
1844 const Expr *TaskRedRef =
nullptr;
1855 case OMPD_parallel_for:
1858 case OMPD_parallel_master:
1862 case OMPD_parallel_sections:
1866 case OMPD_target_parallel:
1870 case OMPD_target_parallel_for:
1874 case OMPD_distribute_parallel_for:
1878 case OMPD_teams_distribute_parallel_for:
1880 .getTaskReductionRefExpr();
1882 case OMPD_target_teams_distribute_parallel_for:
1884 .getTaskReductionRefExpr();
1892 case OMPD_parallel_for_simd:
1894 case OMPD_taskyield:
1898 case OMPD_taskgroup:
1902 case OMPD_ordered_standalone:
1903 case OMPD_ordered_blockassoc:
1907 case OMPD_cancellation_point:
1909 case OMPD_target_data:
1910 case OMPD_target_enter_data:
1911 case OMPD_target_exit_data:
1913 case OMPD_taskloop_simd:
1914 case OMPD_master_taskloop:
1915 case OMPD_master_taskloop_simd:
1916 case OMPD_parallel_master_taskloop:
1917 case OMPD_parallel_master_taskloop_simd:
1918 case OMPD_distribute:
1919 case OMPD_target_update:
1920 case OMPD_distribute_parallel_for_simd:
1921 case OMPD_distribute_simd:
1922 case OMPD_target_parallel_for_simd:
1923 case OMPD_target_simd:
1924 case OMPD_teams_distribute:
1925 case OMPD_teams_distribute_simd:
1926 case OMPD_teams_distribute_parallel_for_simd:
1927 case OMPD_target_teams:
1928 case OMPD_target_teams_distribute:
1929 case OMPD_target_teams_distribute_parallel_for_simd:
1930 case OMPD_target_teams_distribute_simd:
1931 case OMPD_declare_target:
1932 case OMPD_end_declare_target:
1933 case OMPD_threadprivate:
1935 case OMPD_declare_reduction:
1936 case OMPD_declare_mapper:
1937 case OMPD_declare_simd:
1939 case OMPD_declare_variant:
1940 case OMPD_begin_declare_variant:
1941 case OMPD_end_declare_variant:
1944 llvm_unreachable(
"Unexpected directive with task reductions.");
1950 false, TaskRedRef->
getType());
1963 bool HasAtLeastOneReduction =
false;
1964 bool IsReductionWithTaskMod =
false;
1965 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1967 if (
C->getModifier() == OMPC_REDUCTION_inscan)
1969 HasAtLeastOneReduction =
true;
1970 Privates.append(
C->privates().begin(),
C->privates().end());
1971 LHSExprs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1972 RHSExprs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1973 IsPrivateVarReduction.append(
C->private_var_reduction_flags().begin(),
1974 C->private_var_reduction_flags().end());
1975 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1976 IsReductionWithTaskMod =
1977 IsReductionWithTaskMod ||
C->getModifier() == OMPC_REDUCTION_task;
1979 if (HasAtLeastOneReduction) {
1981 if (IsReductionWithTaskMod) {
1982 CGM.getOpenMPRuntime().emitTaskReductionFini(
1985 bool TeamsLoopCanBeParallel =
false;
1986 if (
auto *TTLD = dyn_cast<OMPTargetTeamsGenericLoopDirective>(&D))
1987 TeamsLoopCanBeParallel = TTLD->canBeParallelFor();
1988 bool WithNowait = D.getSingleClause<OMPNowaitClause>() ||
1990 TeamsLoopCanBeParallel || ReductionKind == OMPD_simd;
1991 bool SimpleReduction = ReductionKind == OMPD_simd;
1994 CGM.getOpenMPRuntime().emitReduction(
1995 *
this, D.getEndLoc(),
Privates, LHSExprs, RHSExprs, ReductionOps,
1996 {WithNowait, SimpleReduction, IsPrivateVarReduction, ReductionKind});
2005 llvm::BasicBlock *DoneBB =
nullptr;
2006 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
2007 if (
const Expr *PostUpdate =
C->getPostUpdateExpr()) {
2009 if (llvm::Value *Cond = CondGen(CGF)) {
2014 CGF.
Builder.CreateCondBr(Cond, ThenBB, DoneBB);
2030 const OMPExecutableDirective &,
2031 llvm::SmallVectorImpl<llvm::Value *> &)>
2032 CodeGenBoundParametersTy;
2040 llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> PrivateDecls;
2041 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
2042 for (
const Expr *Ref :
C->varlist()) {
2043 if (!Ref->getType()->isScalarType())
2045 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
2049 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
2052 PrivateDecls.insert(VD);
2056 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
2057 for (
const Expr *Ref :
C->varlist()) {
2058 if (!Ref->getType()->isScalarType())
2060 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
2065 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
2066 PrivateDecls.insert(VD);
2071 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
2072 for (
const Expr *Ref :
C->varlist()) {
2073 if (!Ref->getType()->isScalarType())
2075 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
2078 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
2079 PrivateDecls.insert(VD);
2088 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
2089 for (
const Expr *Ref :
C->varlist()) {
2090 if (!Ref->getType()->isScalarType())
2092 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
2096 if (
const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
2097 PrivateDecls.insert(VD);
2101 CGF, S, PrivateDecls);
2107 const CodeGenBoundParametersTy &CodeGenBoundParameters) {
2108 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
2109 llvm::Value *NumThreads =
nullptr;
2118 llvm::Function *OutlinedFn =
2125 NumThreads = CGF.
EmitScalarExpr(NumThreadsClause->getNumThreads().front(),
2127 Modifier = NumThreadsClause->getPrescriptivenessModifier();
2128 if (
const auto *MessageClause = S.getSingleClause<OMPMessageClause>()) {
2129 Message = MessageClause->getMessageString();
2130 MessageLoc = MessageClause->getBeginLoc();
2132 if (
const auto *SeverityClause = S.getSingleClause<OMPSeverityClause>()) {
2133 Severity = SeverityClause->getSeverityKind();
2134 SeverityLoc = SeverityClause->getBeginLoc();
2137 CGF, NumThreads, NumThreadsClause->getBeginLoc(), Modifier, Severity,
2138 SeverityLoc, Message, MessageLoc);
2140 if (
const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>()) {
2143 CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getBeginLoc());
2145 const Expr *IfCond =
nullptr;
2146 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
2147 if (
C->getNameModifier() == OMPD_unknown ||
2148 C->getNameModifier() == OMPD_parallel) {
2149 IfCond =
C->getCondition();
2154 OMPParallelScope
Scope(CGF, S);
2160 CodeGenBoundParameters(CGF, S, CapturedVars);
2163 CapturedVars, IfCond, NumThreads,
2164 Modifier, Severity, Message);
2169 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
2171 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
2173 return !((AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc ||
2174 AA->getAllocatorType() == OMPAllocateDeclAttr::OMPNullMemAlloc) &&
2175 !AA->getAllocator());
2190 CGF, S.getBeginLoc(), OMPD_unknown,
false,
2196 CodeGenFunction &CGF,
const VarDecl *VD) {
2198 auto &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2210 Size = CGF.
Builder.CreateNUWAdd(
2212 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
2213 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
2219 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
2220 assert(AA->getAllocator() &&
2221 "Expected allocator expression for non-default allocator.");
2225 if (Allocator->getType()->isIntegerTy())
2226 Allocator = CGF.
Builder.CreateIntToPtr(Allocator,
CGM.VoidPtrTy);
2227 else if (Allocator->getType()->isPointerTy())
2231 llvm::Value *
Addr = OMPBuilder.createOMPAlloc(
2234 llvm::CallInst *FreeCI =
2235 OMPBuilder.createOMPFree(CGF.
Builder,
Addr, Allocator);
2249 if (
CGM.getLangOpts().OpenMPUseTLS &&
2250 CGM.getContext().getTargetInfo().isTLSSupported())
2253 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2258 llvm::ConstantInt *Size =
CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy));
2260 llvm::Twine CacheName = Twine(
CGM.getMangledName(VD)).concat(Suffix);
2262 llvm::CallInst *ThreadPrivateCacheCall =
2263 OMPBuilder.createCachedThreadPrivate(CGF.
Builder,
Data, Size, CacheName);
2271 llvm::raw_svector_ostream OS(Buffer);
2272 StringRef Sep = FirstSeparator;
2273 for (StringRef Part : Parts) {
2277 return OS.str().str();
2285 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
2286 "." + RegionName +
".after");
2293 if (
Builder.saveIP().isValid())
2302 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
2303 "." + RegionName +
".after");
2310 if (
Builder.saveIP().isValid())
2315 if (
CGM.getLangOpts().OpenMPIRBuilder) {
2316 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2318 llvm::Value *IfCond =
nullptr;
2323 llvm::Value *NumThreads =
nullptr;
2325 NumThreads =
EmitScalarExpr(NumThreadsClause->getNumThreads().front(),
2328 ProcBindKind ProcBind = OMP_PROC_BIND_default;
2329 if (
const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>())
2330 ProcBind = ProcBindClause->getProcBindKind();
2332 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2336 auto FiniCB = [
this](InsertPointTy IP) {
2338 return llvm::Error::success();
2345 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
2346 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
2357 auto BodyGenCB = [&,
this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
2360 *
this, ParallelRegionBodyStmt, AllocIP, CodeGenIP,
"parallel");
2361 return llvm::Error::success();
2366 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
2368 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
2369 cantFail(OMPBuilder.createParallel(
2370 Builder, AllocaIP, {}, BodyGenCB, PrivCB, FiniCB,
2371 IfCond, NumThreads, ProcBind, S.hasCancel()));
2385 CGF.
EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt());
2394 [](CodeGenFunction &) {
return nullptr; });
2406class OMPTransformDirectiveScopeRAII {
2407 OMPLoopScope *
Scope =
nullptr;
2411 OMPTransformDirectiveScopeRAII(
const OMPTransformDirectiveScopeRAII &) =
2413 OMPTransformDirectiveScopeRAII &
2414 operator=(
const OMPTransformDirectiveScopeRAII &) =
delete;
2418 if (
const auto *Dir = dyn_cast<OMPLoopBasedDirective>(S)) {
2419 Scope =
new OMPLoopScope(CGF, *Dir);
2422 }
else if (
const auto *Dir =
2423 dyn_cast<OMPCanonicalLoopSequenceTransformationDirective>(
2428 Scope =
new OMPLoopScope(CGF, *Dir);
2433 ~OMPTransformDirectiveScopeRAII() {
2444 int MaxLevel,
int Level = 0) {
2445 assert(Level < MaxLevel &&
"Too deep lookup during loop body codegen.");
2447 if (
const auto *CS = dyn_cast<CompoundStmt>(SimplifiedS)) {
2450 "LLVM IR generation of compound statement ('{}')");
2454 for (
const Stmt *CurStmt : CS->body())
2455 emitBody(CGF, CurStmt, NextLoop, MaxLevel, Level);
2462 if (SimplifiedS == OMPLoopBasedDirective::ignoreIntraTileHint(NextLoop)) {
2463 if (
auto *Dir = dyn_cast<OMPLoopTransformationDirective>(SimplifiedS))
2464 SimplifiedS = Dir->getTransformedStmt();
2465 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(SimplifiedS))
2466 SimplifiedS = CanonLoop->getLoopStmt();
2467 if (
const auto *For = dyn_cast<ForStmt>(SimplifiedS)) {
2471 "Expected canonical for loop or range-based for loop.");
2473 CGF.
EmitStmt(CXXFor->getLoopVarStmt());
2474 S = CXXFor->getBody();
2476 if (Level + 1 < MaxLevel) {
2477 NextLoop = OMPLoopDirective::tryToFindNextInnerLoop(
2479 emitBody(CGF, S, NextLoop, MaxLevel, Level + 1);
2497 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2498 for (
const Expr *UE :
C->updates())
2505 BreakContinueStack.push_back(BreakContinue(D,
LoopExit, Continue));
2519 bool IsInscanRegion = InscanScope.
Privatize();
2520 if (IsInscanRegion) {
2530 if (EKind != OMPD_simd && !
getLangOpts().OpenMPSimd)
2539 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
2542 OMPLoopBasedDirective::tryToFindNextInnerLoop(
2544 D.getLoopsNumber());
2552 BreakContinueStack.pop_back();
2563 std::unique_ptr<CodeGenFunction::CGCapturedStmtInfo> CSI =
2564 std::make_unique<CodeGenFunction::CGCapturedStmtInfo>(*S);
2568 return {F, CapStruct.getPointer(
ParentCGF)};
2572static llvm::CallInst *
2577 EffectiveArgs.reserve(Args.size() + 1);
2578 llvm::append_range(EffectiveArgs, Args);
2579 EffectiveArgs.push_back(Cap.second);
2584llvm::CanonicalLoopInfo *
2586 assert(Depth == 1 &&
"Nested loops with OpenMPIRBuilder not yet implemented");
2612 const Stmt *SyntacticalLoop = S->getLoopStmt();
2623 const Stmt *BodyStmt;
2624 if (
const auto *For = dyn_cast<ForStmt>(SyntacticalLoop)) {
2625 if (
const Stmt *InitStmt = For->getInit())
2627 BodyStmt = For->getBody();
2628 }
else if (
const auto *RangeFor =
2629 dyn_cast<CXXForRangeStmt>(SyntacticalLoop)) {
2630 if (
const DeclStmt *RangeStmt = RangeFor->getRangeStmt())
2632 if (
const DeclStmt *BeginStmt = RangeFor->getBeginStmt())
2634 if (
const DeclStmt *EndStmt = RangeFor->getEndStmt())
2636 if (
const DeclStmt *LoopVarStmt = RangeFor->getLoopVarStmt())
2638 BodyStmt = RangeFor->getBody();
2640 llvm_unreachable(
"Expected for-stmt or range-based for-stmt");
2643 const CapturedStmt *DistanceFunc = S->getDistanceFunc();
2656 llvm::Value *DistVal =
Builder.CreateLoad(CountAddr,
".count");
2659 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2660 auto BodyGen = [&,
this](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP,
2661 llvm::Value *IndVar) {
2666 const DeclRefExpr *LoopVarRef = S->getLoopVarRef();
2674 return llvm::Error::success();
2677 llvm::CanonicalLoopInfo *
CL =
2678 cantFail(OMPBuilder.createCanonicalLoop(
Builder, BodyGen, DistVal));
2690 const Expr *IncExpr,
2691 const llvm::function_ref<
void(CodeGenFunction &)> BodyGen,
2692 const llvm::function_ref<
void(CodeGenFunction &)> PostIncGen) {
2702 const CapturedStmt *ICS = OMPED.getInnermostCapturedStmt();
2716 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
2717 if (RequiresCleanup)
2724 if (ExitBlock !=
LoopExit.getBlock()) {
2734 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
2742 BreakContinueStack.pop_back();
2753 bool HasLinears =
false;
2754 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2758 if (
const auto *Ref =
2781 if (
const auto *CS = cast_or_null<BinaryOperator>(
C->getCalcStep()))
2793 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2796 llvm::BasicBlock *DoneBB =
nullptr;
2798 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2799 auto IC =
C->varlist_begin();
2800 for (
const Expr *F :
C->finals()) {
2802 if (llvm::Value *Cond = CondGen(*
this)) {
2807 Builder.CreateCondBr(Cond, ThenBB, DoneBB);
2813 if (
const auto *BD = dyn_cast<BindingDecl>(OrigDecl)) {
2819 (*IC)->getType(),
VK_LValue, (*IC)->getExprLoc());
2828 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
2840 llvm::APInt ClauseAlignment(64, 0);
2841 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
2844 ClauseAlignment = AlignmentCI->getValue();
2846 for (
const Expr *E : Clause->varlist()) {
2847 llvm::APInt Alignment(ClauseAlignment);
2848 if (Alignment == 0) {
2855 E->getType()->getPointeeType()))
2858 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2859 "alignment is not power of 2");
2860 if (Alignment != 0) {
2881 LocalDeclMap.erase(PrivateVD);
2887 E->getType(),
VK_LValue, E->getExprLoc());
2895 for (
const auto *
C : S.getClausesOfKind<OMPOrderedClause>()) {
2896 if (!
C->getNumForLoops())
2898 for (
unsigned I = S.getLoopsNumber(), E =
C->getLoopNumIterations().size();
2904 if (DRE->refersToEnclosingVariableOrCapture()) {
2913 const Expr *Cond, llvm::BasicBlock *TrueBlock,
2914 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
2932 assert(!E->getType().getNonReferenceType()->isRecordType() &&
2933 "dependent counter must not be an iterator.");
2937 (void)PreCondVars.
setVarAddr(CGF, VD, CounterAddr);
2939 (void)PreCondVars.
apply(CGF);
2954 llvm::DenseSet<const VarDecl *> SIMDLCVs;
2958 for (
const Expr *
C : LoopDirective->counters()) {
2963 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2964 auto CurPrivate =
C->privates().begin();
2965 for (
const Expr *E :
C->varlist()) {
2967 const auto *PrivateVD =
2969 bool IsSIMDLCV =
false;
2970 if (
const auto *VarD = dyn_cast<VarDecl>(VD))
2971 IsSIMDLCV = SIMDLCVs.count(VarD->getCanonicalDecl());
2976 bool IsRegistered = PrivateScope.
addPrivate(VD, PrivateAddr);
2977 assert(IsRegistered &&
"linear var already registered as private");
3065 if (
const auto *CS = dyn_cast<CapturedStmt>(S))
3083 if (HasOrderedDirective)
3091 const Stmt *AssociatedStmt = D.getAssociatedStmt();
3095 if (
C->getKind() == OMPC_ORDER_concurrent)
3098 if ((EKind == OMPD_simd ||
3100 llvm::any_of(D.getClausesOfKind<OMPReductionClause>(),
3101 [](
const OMPReductionClause *
C) {
3102 return C->getModifier() == OMPC_REDUCTION_inscan;
3110 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
3113 llvm::BasicBlock *DoneBB =
nullptr;
3119 const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
3121 OrigVD->hasGlobalStorage() || CED) {
3123 if (llvm::Value *Cond = CondGen(*
this)) {
3128 Builder.CreateCondBr(Cond, ThenBB, DoneBB);
3171 auto &&ThenGen = [&S, &SimdInitGen, &BodyCodeGen](
CodeGenFunction &CGF,
3185 const Expr *IfCond =
nullptr;
3188 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
3190 (
C->getNameModifier() == OMPD_unknown ||
3191 C->getNameModifier() == OMPD_simd)) {
3192 IfCond =
C->getCondition();
3208 OMPLoopScope PreInitScope(CGF, S);
3230 llvm::BasicBlock *ContBlock =
nullptr;
3282 emitOMPLoopBodyWithStopPoint(CGF, S,
3283 CodeGenFunction::JumpDest());
3289 if (HasLastprivateClause)
3318 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(S.getRawStmt())) {
3319 if (
const Stmt *SyntacticalLoop = CanonLoop->getLoopStmt()) {
3320 for (
const Stmt *SubStmt : SyntacticalLoop->
children()) {
3323 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(SubStmt)) {
3338static llvm::MapVector<llvm::Value *, llvm::Value *>
3340 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars;
3342 llvm::APInt ClauseAlignment(64, 0);
3343 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
3346 ClauseAlignment = AlignmentCI->getValue();
3348 for (
const Expr *E : Clause->varlist()) {
3349 llvm::APInt Alignment(ClauseAlignment);
3350 if (Alignment == 0) {
3357 E->getType()->getPointeeType()))
3360 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
3361 "alignment is not power of 2");
3363 AlignedVars[PtrValue] = CGF.
Builder.getInt64(Alignment.getSExtValue());
3373 bool UseOMPIRBuilder =
3375 if (UseOMPIRBuilder) {
3379 if (UseOMPIRBuilder) {
3380 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars =
3383 const Stmt *Inner = S.getRawStmt();
3384 llvm::CanonicalLoopInfo *CLI =
3385 CGF.EmitOMPCollapsedCanonicalLoopNest(Inner, 1);
3387 llvm::OpenMPIRBuilder &OMPBuilder =
3390 llvm::ConstantInt *Simdlen =
nullptr;
3397 llvm::ConstantInt *Safelen =
nullptr;
3404 llvm::omp::OrderKind Order = llvm::omp::OrderKind::OMP_ORDER_unknown;
3406 if (
C->getKind() == OpenMPOrderClauseKind::OMPC_ORDER_concurrent) {
3407 Order = llvm::omp::OrderKind::OMP_ORDER_concurrent;
3412 OMPBuilder.applySimd(CLI, AlignedVars,
3413 nullptr, Order, Simdlen, Safelen);
3420 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
3435 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
3448 OMPTransformDirectiveScopeRAII TileScope(*
this, &S);
3454 OMPTransformDirectiveScopeRAII StripeScope(*
this, &S);
3460 OMPTransformDirectiveScopeRAII ReverseScope(*
this, &S);
3466 OMPTransformDirectiveScopeRAII SplitScope(*
this, &S);
3473 OMPTransformDirectiveScopeRAII InterchangeScope(*
this, &S);
3479 OMPTransformDirectiveScopeRAII FlattenScope(*
this, &S);
3486 OMPTransformDirectiveScopeRAII FuseScope(*
this, &S);
3491 bool UseOMPIRBuilder =
CGM.getLangOpts().OpenMPIRBuilder;
3493 if (UseOMPIRBuilder) {
3495 const Stmt *Inner = S.getRawStmt();
3503 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
3506 llvm::CanonicalLoopInfo *UnrolledCLI =
nullptr;
3510 OMPBuilder.unrollLoopFull(DL, CLI);
3512 uint64_t Factor = 0;
3513 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3515 FactorExpr->EvaluateKnownConstInt(
getContext()).getLimitedValue();
3516 assert(Factor >= 1 &&
"Only positive factors are valid");
3518 OMPBuilder.unrollLoopPartial(DL, CLI, Factor,
3519 NeedsUnrolledCLI ? &UnrolledCLI :
nullptr);
3521 OMPBuilder.unrollLoopHeuristic(DL, CLI);
3524 assert((!NeedsUnrolledCLI || UnrolledCLI) &&
3525 "NeedsUnrolledCLI implies UnrolledCLI to be set");
3542 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3544 FactorExpr->EvaluateKnownConstInt(
getContext()).getLimitedValue();
3545 assert(Factor >= 1 &&
"Only positive factors are valid");
3553void CodeGenFunction::EmitOMPOuterLoop(
3556 const CodeGenFunction::OMPLoopArguments &LoopArgs,
3575 llvm::Value *BoolCondVal =
nullptr;
3576 if (!DynamicOrOrdered) {
3587 RT.
emitForNext(*
this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL,
3588 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST);
3593 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
3598 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
3599 if (ExitBlock !=
LoopExit.getBlock()) {
3607 if (DynamicOrOrdered)
3612 BreakContinueStack.push_back(BreakContinue(S, LoopExit, Continue));
3617 [&S, IsMonotonic, EKind](CodeGenFunction &CGF, PrePostActionTy &) {
3622 if (
const auto *
C = S.getSingleClause<OMPOrderClause>())
3623 if (
C->getKind() == OMPC_ORDER_concurrent)
3629 [&S, &LoopArgs, LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered,
3630 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
3631 SourceLocation Loc = S.getBeginLoc();
3637 CGF.EmitOMPInnerLoop(
3639 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
3640 CodeGenLoop(CGF, S, LoopExit);
3642 [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) {
3643 CodeGenOrdered(CGF, Loc, IVSize, IVSigned);
3648 BreakContinueStack.pop_back();
3649 if (!DynamicOrOrdered) {
3662 auto &&CodeGen = [DynamicOrOrdered, &S, &LoopArgs](CodeGenFunction &CGF) {
3663 if (!DynamicOrOrdered)
3664 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
3667 OMPCancelStack.emitExit(*
this, EKind, CodeGen);
3670void CodeGenFunction::EmitOMPForOuterLoop(
3671 const OpenMPScheduleTy &ScheduleKind,
bool IsMonotonic,
3673 const OMPLoopArguments &LoopArgs,
3675 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3681 LoopArgs.Chunk !=
nullptr)) &&
3682 "static non-chunked schedule does not need outer loop");
3740 if (DynamicOrOrdered) {
3741 const std::pair<llvm::Value *, llvm::Value *> DispatchBounds =
3742 CGDispatchBounds(*
this, S, LoopArgs.LB, LoopArgs.UB);
3743 llvm::Value *LBVal = DispatchBounds.first;
3744 llvm::Value *UBVal = DispatchBounds.second;
3745 CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal,
3748 IVSigned, Ordered, DipatchRTInputValues);
3750 CGOpenMPRuntime::StaticRTInput StaticInit(
3751 IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
3752 LoopArgs.ST, LoopArgs.Chunk);
3758 auto &&CodeGenOrdered = [Ordered](CodeGenFunction &CGF, SourceLocation Loc,
3759 const unsigned IVSize,
3760 const bool IVSigned) {
3767 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST,
3768 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB);
3769 OuterLoopArgs.IncExpr = S.
getInc();
3770 OuterLoopArgs.Init = S.
getInit();
3771 OuterLoopArgs.Cond = S.
getCond();
3774 OuterLoopArgs.DKind = LoopArgs.DKind;
3775 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
3777 if (DynamicOrOrdered) {
3783 const unsigned IVSize,
const bool IVSigned) {}
3785void CodeGenFunction::EmitOMPDistributeOuterLoop(
3790 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3802 CGOpenMPRuntime::StaticRTInput StaticInit(
3803 IVSize, IVSigned,
false, LoopArgs.IL, LoopArgs.LB,
3804 LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
3818 OMPLoopArguments OuterLoopArgs;
3819 OuterLoopArgs.LB = LoopArgs.LB;
3820 OuterLoopArgs.UB = LoopArgs.UB;
3821 OuterLoopArgs.ST = LoopArgs.ST;
3822 OuterLoopArgs.IL = LoopArgs.IL;
3823 OuterLoopArgs.Chunk = LoopArgs.Chunk;
3827 OuterLoopArgs.IncExpr = IncExpr;
3840 OuterLoopArgs.DKind = OMPD_distribute;
3842 EmitOMPOuterLoop(
false,
false, S,
3843 LoopScope, OuterLoopArgs, CodeGenLoopContent,
3847static std::pair<LValue, LValue>
3890static std::pair<llvm::Value *, llvm::Value *>
3901 llvm::Value *LBVal =
3903 llvm::Value *UBVal =
3905 return {LBVal, UBVal};
3914 llvm::Value *LBCast = CGF.
Builder.CreateIntCast(
3916 CapturedVars.push_back(LBCast);
3920 llvm::Value *UBCast = CGF.
Builder.CreateIntCast(
3922 CapturedVars.push_back(UBCast);
3933 bool HasCancel =
false;
3935 if (
const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
3936 HasCancel = D->hasCancel();
3937 else if (
const auto *D = dyn_cast<OMPDistributeParallelForDirective>(&S))
3938 HasCancel = D->hasCancel();
3939 else if (
const auto *D =
3940 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S))
3941 HasCancel = D->hasCancel();
3951 CGInlinedWorksharingLoop,
3961 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3962 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3971 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3972 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3980 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
3981 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
3991 llvm::Constant *
Addr;
3993 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
3995 assert(Fn &&
Addr &&
"Target device function emission failed.");
4007struct ScheduleKindModifiersTy {
4014 : Kind(Kind), M1(M1), M2(M2) {}
4038 bool HasLastprivateClause;
4041 OMPLoopScope PreInitScope(*
this, S);
4046 llvm::BasicBlock *ContBlock =
nullptr;
4060 bool Ordered =
false;
4061 if (
const auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) {
4062 if (OrderedClause->getNumForLoops())
4072 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*
this, S);
4073 LValue LB = Bounds.first;
4074 LValue UB = Bounds.second;
4088 CGM.getOpenMPRuntime().emitBarrierCall(
4089 *
this, S.getBeginLoc(), OMPD_unknown,
false,
4101 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
4104 const Expr *ChunkExpr =
nullptr;
4106 if (
const auto *
C = S.getSingleClause<OMPScheduleClause>()) {
4107 ScheduleKind.
Schedule =
C->getScheduleKind();
4108 ScheduleKind.
M1 =
C->getFirstScheduleModifier();
4109 ScheduleKind.
M2 =
C->getSecondScheduleModifier();
4110 ChunkExpr =
C->getChunkSize();
4113 CGM.getOpenMPRuntime().getDefaultScheduleAndChunk(
4114 *
this, S, ScheduleKind.
Schedule, ChunkExpr);
4116 bool HasChunkSizeOne =
false;
4117 llvm::Value *Chunk =
nullptr;
4125 llvm::APSInt EvaluatedChunk =
Result.Val.getInt();
4126 HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
4135 bool StaticChunkedOne =
4137 Chunk !=
nullptr) &&
4149 "fused distribute schedule requires a static chunk-one schedule");
4152 (ScheduleKind.
Schedule == OMPC_SCHEDULE_static &&
4153 !(ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4154 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)) ||
4155 ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
4156 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
4158 Chunk !=
nullptr) ||
4159 StaticChunkedOne) &&
4169 if (
C->getKind() == OMPC_ORDER_concurrent)
4173 [IVSize, IVSigned, Ordered, IL, LB, UB, ST, StaticChunkedOne, Chunk,
4182 IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(),
4183 UB.getAddress(), ST.getAddress(),
4184 StaticChunkedOne ? Chunk :
nullptr);
4186 CGF, S.getBeginLoc(), EKind, ScheduleKind, StaticInit);
4188 if (!StaticChunkedOne)
4207 StaticChunkedOne ? S.getCombinedParForInDistCond()
4209 StaticChunkedOne ? S.getDistInc() : S.getInc(),
4210 [&S,
LoopExit](CodeGenFunction &CGF) {
4211 emitOMPLoopBodyWithStopPoint(CGF, S, LoopExit);
4213 [](CodeGenFunction &) {});
4217 auto &&
CodeGen = [&S](CodeGenFunction &CGF) {
4221 OMPCancelStack.emitExit(*
this, EKind,
CodeGen);
4228 LoopArguments.DKind = OMPD_for;
4229 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
4230 LoopArguments, CGDispatchBounds);
4234 return CGF.
Builder.CreateIsNotNull(
4240 ? OMPD_parallel_for_simd
4244 *
this, S, [IL, &S](CodeGenFunction &CGF) {
4245 return CGF.
Builder.CreateIsNotNull(
4249 if (HasLastprivateClause)
4255 return CGF.
Builder.CreateIsNotNull(
4266 return HasLastprivateClause;
4272static std::pair<LValue, LValue>
4286static std::pair<llvm::Value *, llvm::Value *>
4290 const Expr *IVExpr = LS.getIterationVariable();
4292 llvm::Value *LBVal = CGF.
Builder.getIntN(IVSize, 0);
4294 return {LBVal, UBVal};
4306 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
4307 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4308 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4313 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4314 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4315 "Only inscan reductions are expected.");
4316 Shareds.append(
C->varlist_begin(),
C->varlist_end());
4317 Privates.append(
C->privates().begin(),
C->privates().end());
4318 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
4319 CopyArrayTemps.append(
C->copy_array_temps().begin(),
4320 C->copy_array_temps().end());
4328 auto *ITA = CopyArrayTemps.begin();
4333 if (PrivateVD->getType()->isVariablyModifiedType()) {
4358 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
4359 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4360 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4367 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4368 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4369 "Only inscan reductions are expected.");
4370 Shareds.append(
C->varlist_begin(),
C->varlist_end());
4371 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
4372 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
4373 Privates.append(
C->privates().begin(),
C->privates().end());
4374 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
4375 CopyArrayElems.append(
C->copy_array_elems().begin(),
4376 C->copy_array_elems().end());
4380 llvm::Value *OMPLast = CGF.
Builder.CreateNSWSub(
4381 OMPScanNumIterations,
4382 llvm::ConstantInt::get(CGF.
SizeTy, 1,
false));
4383 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
4385 const Expr *OrigExpr = Shareds[I];
4386 const Expr *CopyArrayElem = CopyArrayElems[I];
4393 LValue SrcLVal = CGF.
EmitLValue(CopyArrayElem);
4395 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
4425 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4426 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4432 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4433 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4434 "Only inscan reductions are expected.");
4435 Privates.append(
C->privates().begin(),
C->privates().end());
4436 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
4437 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
4438 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
4439 CopyArrayElems.append(
C->copy_array_elems().begin(),
4440 C->copy_array_elems().end());
4455 auto &&
CodeGen = [&S, OMPScanNumIterations, &LHSs, &RHSs, &CopyArrayElems,
4462 llvm::BasicBlock *InputBB = CGF.Builder.GetInsertBlock();
4463 llvm::BasicBlock *LoopBB = CGF.createBasicBlock(
"omp.outer.log.scan.body");
4464 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
"omp.outer.log.scan.exit");
4466 CGF.CGM.getIntrinsic(llvm::Intrinsic::log2, CGF.DoubleTy);
4468 CGF.Builder.CreateUIToFP(OMPScanNumIterations, CGF.DoubleTy);
4469 llvm::Value *LogVal = CGF.EmitNounwindRuntimeCall(F, Arg);
4470 F = CGF.CGM.getIntrinsic(llvm::Intrinsic::ceil, CGF.DoubleTy);
4471 LogVal = CGF.EmitNounwindRuntimeCall(F, LogVal);
4472 LogVal = CGF.Builder.CreateFPToUI(LogVal, CGF.IntTy);
4473 llvm::Value *NMin1 = CGF.Builder.CreateNUWSub(
4474 OMPScanNumIterations, llvm::ConstantInt::get(CGF.SizeTy, 1));
4476 CGF.EmitBlock(LoopBB);
4477 auto *Counter = CGF.Builder.CreatePHI(CGF.IntTy, 2);
4479 auto *Pow2K = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
4480 Counter->addIncoming(llvm::ConstantInt::get(CGF.IntTy, 0), InputBB);
4481 Pow2K->addIncoming(llvm::ConstantInt::get(CGF.SizeTy, 1), InputBB);
4484 llvm::BasicBlock *InnerLoopBB =
4485 CGF.createBasicBlock(
"omp.inner.log.scan.body");
4486 llvm::BasicBlock *InnerExitBB =
4487 CGF.createBasicBlock(
"omp.inner.log.scan.exit");
4488 llvm::Value *CmpI = CGF.Builder.CreateICmpUGE(NMin1, Pow2K);
4489 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4490 CGF.EmitBlock(InnerLoopBB);
4491 auto *IVal = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
4492 IVal->addIncoming(NMin1, LoopBB);
4495 auto *ILHS = LHSs.begin();
4496 auto *IRHS = RHSs.begin();
4497 for (
const Expr *CopyArrayElem : CopyArrayElems) {
4507 LHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4512 llvm::Value *OffsetIVal = CGF.Builder.CreateNUWSub(IVal, Pow2K);
4518 RHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4525 CGF.CGM.getOpenMPRuntime().emitReduction(
4526 CGF, S.getEndLoc(),
Privates, LHSs, RHSs, ReductionOps,
4530 llvm::Value *NextIVal =
4531 CGF.Builder.CreateNUWSub(IVal, llvm::ConstantInt::get(CGF.SizeTy, 1));
4532 IVal->addIncoming(NextIVal, CGF.Builder.GetInsertBlock());
4533 CmpI = CGF.Builder.CreateICmpUGE(NextIVal, Pow2K);
4534 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4535 CGF.EmitBlock(InnerExitBB);
4537 CGF.Builder.CreateNUWAdd(Counter, llvm::ConstantInt::get(CGF.IntTy, 1));
4538 Counter->addIncoming(
Next, CGF.Builder.GetInsertBlock());
4540 llvm::Value *NextPow2K =
4541 CGF.Builder.CreateShl(Pow2K, 1,
"",
true);
4542 Pow2K->addIncoming(NextPow2K, CGF.Builder.GetInsertBlock());
4543 llvm::Value *
Cmp = CGF.Builder.CreateICmpNE(
Next, LogVal);
4544 CGF.Builder.CreateCondBr(
Cmp, LoopBB, ExitBB);
4546 CGF.EmitBlock(ExitBB);
4552 CGF, S.getBeginLoc(), OMPD_unknown,
false,
4555 RegionCodeGenTy RCG(CodeGen);
4566 bool HasLastprivates;
4568 if (llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4569 [](
const OMPReductionClause *
C) {
4570 return C->getModifier() == OMPC_REDUCTION_inscan;
4574 OMPLoopScope LoopScope(CGF, S);
4577 const auto &&FirstGen = [&S, HasCancel, EKind](
CodeGenFunction &CGF) {
4586 const auto &&SecondGen = [&S, HasCancel, EKind,
4604 return HasLastprivates;
4617 if (
auto *SC = dyn_cast<OMPScheduleClause>(
C)) {
4622 switch (SC->getScheduleKind()) {
4623 case OMPC_SCHEDULE_auto:
4624 case OMPC_SCHEDULE_dynamic:
4625 case OMPC_SCHEDULE_runtime:
4626 case OMPC_SCHEDULE_guided:
4627 case OMPC_SCHEDULE_static:
4640static llvm::omp::ScheduleKind
4642 switch (ScheduleClauseKind) {
4644 return llvm::omp::OMP_SCHEDULE_Default;
4645 case OMPC_SCHEDULE_auto:
4646 return llvm::omp::OMP_SCHEDULE_Auto;
4647 case OMPC_SCHEDULE_dynamic:
4648 return llvm::omp::OMP_SCHEDULE_Dynamic;
4649 case OMPC_SCHEDULE_guided:
4650 return llvm::omp::OMP_SCHEDULE_Guided;
4651 case OMPC_SCHEDULE_runtime:
4652 return llvm::omp::OMP_SCHEDULE_Runtime;
4653 case OMPC_SCHEDULE_static:
4654 return llvm::omp::OMP_SCHEDULE_Static;
4656 llvm_unreachable(
"Unhandled schedule kind");
4663 bool HasLastprivates =
false;
4666 auto &&
CodeGen = [&S, &
CGM, HasCancel, &HasLastprivates,
4669 if (UseOMPIRBuilder) {
4670 bool NeedsBarrier = !S.getSingleClause<OMPNowaitClause>();
4672 llvm::omp::ScheduleKind SchedKind = llvm::omp::OMP_SCHEDULE_Default;
4673 llvm::Value *ChunkSize =
nullptr;
4674 if (
auto *SchedClause = S.getSingleClause<OMPScheduleClause>()) {
4677 if (
const Expr *ChunkSizeExpr = SchedClause->getChunkSize())
4682 const Stmt *Inner = S.getRawStmt();
4683 llvm::CanonicalLoopInfo *CLI =
4686 llvm::OpenMPIRBuilder &OMPBuilder =
4688 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4690 cantFail(OMPBuilder.applyWorkshareLoop(
4691 CGF.
Builder.getCurrentDebugLocation(), CLI, AllocaIP, NeedsBarrier,
4692 SchedKind, ChunkSize,
false,
4703 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
4708 if (!UseOMPIRBuilder) {
4710 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4722 bool HasLastprivates =
false;
4723 auto &&
CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
4730 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4731 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
4735 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4736 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_for);
4743 llvm::Value *
Init =
nullptr) {
4750void CodeGenFunction::EmitSections(
const OMPExecutableDirective &S) {
4751 const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4752 const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt);
4753 bool HasLastprivates =
false;
4755 auto &&CodeGen = [&S, CapturedStmt, CS, EKind,
4756 &HasLastprivates](CodeGenFunction &CGF, PrePostActionTy &) {
4757 const ASTContext &
C = CGF.getContext();
4758 QualType KmpInt32Ty =
4759 C.getIntTypeForBitwidth(32, 1);
4762 CGF.Builder.getInt32(0));
4763 llvm::ConstantInt *GlobalUBVal = CS !=
nullptr
4764 ? CGF.Builder.getInt32(CS->size() - 1)
4765 : CGF.Builder.getInt32(0);
4769 CGF.Builder.getInt32(1));
4771 CGF.Builder.getInt32(0));
4774 OpaqueValueExpr IVRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4775 CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
4776 OpaqueValueExpr UBRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4777 CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
4781 S.getBeginLoc(), FPOptionsOverride());
4785 S.getBeginLoc(),
true, FPOptionsOverride());
4786 auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
4798 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".omp.sections.exit");
4799 llvm::SwitchInst *SwitchStmt =
4800 CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.
getBeginLoc()),
4801 ExitBB, CS ==
nullptr ? 1 : CS->size());
4803 unsigned CaseNumber = 0;
4804 for (
const Stmt *SubStmt : CS->
children()) {
4805 auto CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4806 CGF.EmitBlock(CaseBB);
4807 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
4808 CGF.EmitStmt(SubStmt);
4809 CGF.EmitBranch(ExitBB);
4813 llvm::BasicBlock *CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4814 CGF.EmitBlock(CaseBB);
4815 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
4816 CGF.EmitStmt(CapturedStmt);
4817 CGF.EmitBranch(ExitBB);
4819 CGF.EmitBlock(ExitBB,
true);
4822 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
4823 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
4827 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
4831 CGF.EmitOMPPrivateClause(S, LoopScope);
4832 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(CGF, S, IV);
4833 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
4834 CGF.EmitOMPReductionClauseInit(S, LoopScope);
4835 (void)LoopScope.Privatize();
4837 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
4840 OpenMPScheduleTy ScheduleKind;
4841 ScheduleKind.
Schedule = OMPC_SCHEDULE_static;
4842 CGOpenMPRuntime::StaticRTInput StaticInit(
4843 32,
true,
false, IL.getAddress(),
4844 LB.getAddress(), UB.getAddress(), ST.getAddress());
4845 CGF.CGM.getOpenMPRuntime().emitForStaticInit(CGF, S.
getBeginLoc(), EKind,
4846 ScheduleKind, StaticInit);
4848 llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.
getBeginLoc());
4849 llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
4850 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
4851 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
4853 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.
getBeginLoc()), IV);
4855 CGF.EmitOMPInnerLoop(S,
false, Cond, Inc, BodyGen,
4856 [](CodeGenFunction &) {});
4858 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
4859 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.
getEndLoc(),
4862 CGF.OMPCancelStack.emitExit(CGF, EKind, CodeGen);
4863 CGF.EmitOMPReductionClauseFinal(S, OMPD_parallel);
4866 return CGF.
Builder.CreateIsNotNull(
4871 if (HasLastprivates)
4878 bool HasCancel =
false;
4879 if (
auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
4880 HasCancel = OSD->hasCancel();
4881 else if (
auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
4882 HasCancel = OPSD->hasCancel();
4884 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_sections, CodeGen,
4889 if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) {
4907 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4912 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4913 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_scope,
CodeGen);
4916 if (!S.getSingleClause<OMPNowaitClause>()) {
4917 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_scope);
4924 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4925 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4926 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4927 using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
4929 auto FiniCB = [](InsertPointTy IP) {
4932 return llvm::Error::success();
4935 const CapturedStmt *ICS = S.getInnermostCapturedStmt();
4936 const Stmt *
CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4941 auto SectionCB = [
this, SubStmt](
4942 InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4945 CodeGenIP,
"section");
4946 return llvm::Error::success();
4948 SectionCBVector.push_back(SectionCB);
4952 [
this,
CapturedStmt](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
4956 return llvm::Error::success();
4958 SectionCBVector.push_back(SectionCB);
4965 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
4966 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
4976 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4978 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4979 cantFail(OMPBuilder.createSections(
4981 S.getSingleClause<OMPNowaitClause>()));
4988 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4992 if (!S.getSingleClause<OMPNowaitClause>()) {
4993 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(),
5001 if (
CGM.getLangOpts().OpenMPIRBuilder) {
5002 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
5003 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5005 const Stmt *SectionRegionBodyStmt = S.getAssociatedStmt();
5006 auto FiniCB = [
this](InsertPointTy IP) {
5008 return llvm::Error::success();
5011 auto BodyGenCB = [SectionRegionBodyStmt,
5012 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
5015 *
this, SectionRegionBodyStmt, AllocIP, CodeGenIP,
"section");
5016 return llvm::Error::success();
5021 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5022 cantFail(OMPBuilder.createSection(
Builder, BodyGenCB, FiniCB));
5042 CopyprivateVars.append(
C->varlist_begin(),
C->varlist_end());
5043 DestExprs.append(
C->destination_exprs().begin(),
5044 C->destination_exprs().end());
5045 SrcExprs.append(
C->source_exprs().begin(),
C->source_exprs().end());
5046 AssignmentOps.append(
C->assignment_ops().begin(),
5047 C->assignment_ops().end());
5056 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5061 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
5062 CGM.getOpenMPRuntime().emitSingleRegion(*
this,
CodeGen, S.getBeginLoc(),
5063 CopyprivateVars, DestExprs,
5064 SrcExprs, AssignmentOps);
5068 if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) {
5069 CGM.getOpenMPRuntime().emitBarrierCall(
5070 *
this, S.getBeginLoc(),
5071 S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);
5086 if (
CGM.getLangOpts().OpenMPIRBuilder) {
5087 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
5088 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5090 const Stmt *MasterRegionBodyStmt = S.getAssociatedStmt();
5092 auto FiniCB = [
this](InsertPointTy IP) {
5094 return llvm::Error::success();
5097 auto BodyGenCB = [MasterRegionBodyStmt,
5098 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
5101 *
this, MasterRegionBodyStmt, AllocIP, CodeGenIP,
"master");
5102 return llvm::Error::success();
5107 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5108 cantFail(OMPBuilder.createMaster(
Builder, BodyGenCB, FiniCB));
5123 Expr *Filter =
nullptr;
5125 Filter = FilterClause->getThreadID();
5131 if (
CGM.getLangOpts().OpenMPIRBuilder) {
5132 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
5133 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5135 const Stmt *MaskedRegionBodyStmt = S.getAssociatedStmt();
5136 const Expr *Filter =
nullptr;
5138 Filter = FilterClause->getThreadID();
5139 llvm::Value *FilterVal = Filter
5141 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
5143 auto FiniCB = [
this](InsertPointTy IP) {
5145 return llvm::Error::success();
5148 auto BodyGenCB = [MaskedRegionBodyStmt,
5149 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
5152 *
this, MaskedRegionBodyStmt, AllocIP, CodeGenIP,
"masked");
5153 return llvm::Error::success();
5158 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
5159 OMPBuilder.createMasked(
Builder, BodyGenCB, FiniCB, FilterVal));
5170 if (
CGM.getLangOpts().OpenMPIRBuilder) {
5171 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
5172 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5174 const Stmt *CriticalRegionBodyStmt = S.getAssociatedStmt();
5175 const Expr *Hint =
nullptr;
5176 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
5177 Hint = HintClause->getHint();
5182 llvm::Value *HintInst =
nullptr;
5187 auto FiniCB = [
this](InsertPointTy IP) {
5189 return llvm::Error::success();
5192 auto BodyGenCB = [CriticalRegionBodyStmt,
5193 this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
5196 *
this, CriticalRegionBodyStmt, AllocIP, CodeGenIP,
"critical");
5197 return llvm::Error::success();
5202 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5203 cantFail(OMPBuilder.createCritical(
Builder, BodyGenCB, FiniCB,
5213 CGF.
EmitStmt(S.getAssociatedStmt());
5215 const Expr *Hint =
nullptr;
5216 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
5217 Hint = HintClause->getHint();
5220 CGM.getOpenMPRuntime().emitCriticalRegion(*
this,
5222 CodeGen, S.getBeginLoc(), Hint);
5235 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
5239 OMPLoopScope LoopScope(CGF, S);
5242 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
5243 [](
const OMPReductionClause *
C) {
5244 return C->getModifier() == OMPC_REDUCTION_inscan;
5269 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
5273 OMPLoopScope LoopScope(CGF, S);
5276 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
5277 [](
const OMPReductionClause *
C) {
5278 return C->getModifier() == OMPC_REDUCTION_inscan;
5314 [](CodeGenFunction &) {
return nullptr; });
5341 [](CodeGenFunction &) {
return nullptr; });
5354 CGF.EmitSections(S);
5368class CheckVarsEscapingUntiedTaskDeclContext final
5373 explicit CheckVarsEscapingUntiedTaskDeclContext() =
default;
5374 ~CheckVarsEscapingUntiedTaskDeclContext() =
default;
5375 void VisitDeclStmt(
const DeclStmt *S) {
5380 if (
const auto *VD = dyn_cast_or_null<VarDecl>(D))
5382 PrivateDecls.push_back(VD);
5386 void VisitCapturedStmt(
const CapturedStmt *) {}
5388 void VisitBlockExpr(
const BlockExpr *) {}
5389 void VisitStmt(
const Stmt *S) {
5392 for (
const Stmt *Child : S->
children())
5398 ArrayRef<const VarDecl *> getPrivateDecls()
const {
return PrivateDecls; }
5406 bool OmpAllMemory =
false;
5409 return C->getDependencyKind() == OMPC_DEPEND_outallmemory ||
5410 C->getDependencyKind() == OMPC_DEPEND_inoutallmemory;
5412 OmpAllMemory =
true;
5417 Data.Dependences.emplace_back(OMPC_DEPEND_outallmemory,
5426 if (Kind == OMPC_DEPEND_outallmemory || Kind == OMPC_DEPEND_inoutallmemory)
5428 if (OmpAllMemory && (Kind == OMPC_DEPEND_out || Kind == OMPC_DEPEND_inout))
5431 Data.Dependences.emplace_back(
C->getDependencyKind(),
C->getModifier());
5432 DD.
DepExprs.append(
C->varlist_begin(),
C->varlist_end());
5441 const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion);
5443 auto PartId = std::next(I);
5444 auto TaskT = std::next(I, 4);
5449 const Expr *Cond = Clause->getCondition();
5452 Data.Final.setInt(CondConstant);
5457 Data.Final.setInt(
false);
5461 const Expr *Prio = Clause->getPriority();
5462 Data.Priority.setInt(
true);
5470 llvm::DenseSet<const ValueDecl *> EmittedAsPrivate;
5472 for (
const auto *
C : S.getClausesOfKind<OMPPrivateClause>()) {
5473 auto IRef =
C->varlist_begin();
5474 for (
const Expr *IInit :
C->private_copies()) {
5476 if (EmittedAsPrivate.insert(
cast<ValueDecl>(OrigDecl->getCanonicalDecl()))
5478 Data.PrivateVars.push_back(*IRef);
5479 Data.PrivateCopies.push_back(IInit);
5484 EmittedAsPrivate.clear();
5486 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5487 auto IRef =
C->varlist_begin();
5488 auto IElemInitRef =
C->inits().begin();
5489 for (
const Expr *IInit :
C->private_copies()) {
5491 if (EmittedAsPrivate.insert(
cast<ValueDecl>(OrigDecl->getCanonicalDecl()))
5493 Data.FirstprivateVars.push_back(*IRef);
5494 Data.FirstprivateCopies.push_back(IInit);
5495 Data.FirstprivateInits.push_back(*IElemInitRef);
5502 llvm::MapVector<const ValueDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
5503 llvm::MapVector<const ValueDecl *, const DeclRefExpr *> LastprivateSrcsOrigs;
5504 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
5505 auto IRef =
C->varlist_begin();
5506 auto ID =
C->destination_exprs().begin();
5507 auto IS =
C->source_exprs().begin();
5508 for (
const Expr *IInit :
C->private_copies()) {
5510 if (EmittedAsPrivate.insert(
cast<ValueDecl>(OrigDecl->getCanonicalDecl()))
5512 Data.LastprivateVars.push_back(*IRef);
5513 Data.LastprivateCopies.push_back(IInit);
5515 LastprivateDstsOrigs.insert(std::make_pair(
5517 LastprivateSrcsOrigs.insert(std::make_pair(
5526 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
5527 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5528 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5529 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5530 Data.ReductionOps.append(
C->reduction_ops().begin(),
5531 C->reduction_ops().end());
5532 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5533 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5535 Data.Reductions =
CGM.getOpenMPRuntime().emitTaskReductionInit(
5536 *
this, S.getBeginLoc(), LHSs, RHSs,
Data);
5541 CheckVarsEscapingUntiedTaskDeclContext Checker;
5542 Checker.Visit(S.getInnermostCapturedStmt()->getCapturedStmt());
5543 Data.PrivateLocals.append(Checker.getPrivateDecls().begin(),
5544 Checker.getPrivateDecls().end());
5546 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
5547 &LastprivateSrcsOrigs, CapturedRegion](
5549 llvm::MapVector<CanonicalDeclPtr<const VarDecl>,
5550 std::pair<Address, Address>>
5555 if (
auto *DI = CGF.getDebugInfo()) {
5556 llvm::SmallDenseMap<const VarDecl *, FieldDecl *> CaptureFields =
5557 CGF.CapturedStmtInfo->getCaptureFields();
5558 llvm::Value *ContextValue = CGF.CapturedStmtInfo->getContextValue();
5559 if (CaptureFields.size() && ContextValue) {
5560 unsigned CharWidth = CGF.getContext().getCharWidth();
5574 for (
auto It = CaptureFields.begin(); It != CaptureFields.end(); ++It) {
5575 const VarDecl *SharedVar = It->first;
5578 CGF.getContext().getASTRecordLayout(CaptureRecord);
5581 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5582 (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue,
5583 CGF.Builder,
false);
5586 auto UpdateExpr = [](llvm::LLVMContext &Ctx,
auto *
Declare,
5591 Ops.push_back(llvm::dwarf::DW_OP_plus_uconst);
5592 Ops.push_back(Offset);
5594 Ops.push_back(llvm::dwarf::DW_OP_deref);
5595 Declare->setExpression(llvm::DIExpression::get(Ctx, Ops));
5597 llvm::Instruction &
Last = CGF.Builder.GetInsertBlock()->back();
5600 assert(!
Last.isTerminator() &&
"unexpected terminator");
5602 CGF.Builder.GetInsertBlock()->getTrailingDbgRecords()) {
5603 for (llvm::DbgVariableRecord &DVR : llvm::reverse(
5604 llvm::filterDbgVars(Marker->getDbgRecordRange()))) {
5605 UpdateExpr(
Last.getContext(), &DVR, Offset);
5614 if (!
Data.PrivateVars.empty() || !
Data.FirstprivateVars.empty() ||
5615 !
Data.LastprivateVars.empty() || !
Data.PrivateLocals.empty()) {
5616 enum { PrivatesParam = 2, CopyFnParam = 3 };
5617 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5619 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5625 CallArgs.push_back(PrivatesPtr);
5626 ParamTypes.push_back(PrivatesPtr->getType());
5627 for (
const Expr *E :
Data.PrivateVars) {
5629 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5630 CGF.getContext().getPointerType(E->
getType()),
".priv.ptr.addr");
5631 PrivatePtrs.emplace_back(VD, PrivatePtr);
5633 ParamTypes.push_back(PrivatePtr.
getType());
5635 for (
const Expr *E :
Data.FirstprivateVars) {
5637 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5638 CGF.getContext().getPointerType(E->
getType()),
5639 ".firstpriv.ptr.addr");
5640 PrivatePtrs.emplace_back(VD, PrivatePtr);
5641 FirstprivatePtrs.emplace_back(VD, PrivatePtr);
5643 ParamTypes.push_back(PrivatePtr.
getType());
5645 for (
const Expr *E :
Data.LastprivateVars) {
5647 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5648 CGF.getContext().getPointerType(E->
getType()),
5649 ".lastpriv.ptr.addr");
5650 PrivatePtrs.emplace_back(VD, PrivatePtr);
5652 ParamTypes.push_back(PrivatePtr.
getType());
5657 Ty = CGF.getContext().getPointerType(Ty);
5659 Ty = CGF.getContext().getPointerType(Ty);
5660 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5661 CGF.getContext().getPointerType(Ty),
".local.ptr.addr");
5662 auto Result = UntiedLocalVars.insert(
5665 if (
Result.second ==
false)
5666 *
Result.first = std::make_pair(
5669 ParamTypes.push_back(PrivatePtr.
getType());
5671 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5673 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5674 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5675 for (
const auto &Pair : LastprivateDstsOrigs) {
5676 const auto *OrigDecl = Pair.second->getDecl();
5677 if (
const auto *BD = dyn_cast<BindingDecl>(OrigDecl)) {
5680 CGF.EmitOMPBindingOriginalAddr(BD, Pair.second->getExprLoc());
5681 Scope.addPrivate(Pair.first, OrigAddr);
5686 CGF.CapturedStmtInfo->lookup(OrigVD) !=
nullptr,
5688 Pair.second->getExprLoc());
5689 Scope.addPrivate(Pair.first, CGF.EmitLValue(&DRE).getAddress());
5692 for (
const auto &Pair : PrivatePtrs) {
5694 CGF.Builder.CreateLoad(Pair.second),
5695 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5696 CGF.getContext().getDeclAlign(Pair.first));
5697 Scope.addPrivate(Pair.first, Replacement);
5702 for (
const auto &SrcPair : LastprivateSrcsOrigs) {
5703 if (SrcPair.second->getDecl() == Pair.first) {
5704 Scope.addPrivate(SrcPair.first, Replacement);
5710 if (
auto *DI = CGF.getDebugInfo())
5711 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5713 if (
const auto *VD = dyn_cast<VarDecl>(Pair.first))
5714 (void)DI->EmitDeclareOfAutoVariable(
5715 VD, Pair.second.getBasePointer(), CGF.Builder,
5720 for (
auto &Pair : UntiedLocalVars) {
5721 QualType VDType = Pair.first->getType().getNonReferenceType();
5722 if (Pair.first->getType()->isLValueReferenceType())
5723 VDType = CGF.getContext().getPointerType(VDType);
5725 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5728 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(VDType)),
5729 CGF.getPointerAlign());
5730 Pair.second.first = Replacement;
5731 Ptr = CGF.Builder.CreateLoad(Replacement);
5732 Replacement =
Address(Ptr, CGF.ConvertTypeForMem(VDType),
5733 CGF.getContext().getDeclAlign(Pair.first));
5734 Pair.second.second = Replacement;
5736 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5737 Address Replacement(Ptr, CGF.ConvertTypeForMem(VDType),
5738 CGF.getContext().getDeclAlign(Pair.first));
5739 Pair.second.first = Replacement;
5743 if (
Data.Reductions) {
5745 for (
const auto &Pair : FirstprivatePtrs) {
5747 CGF.Builder.CreateLoad(Pair.second),
5748 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5749 CGF.getContext().getDeclAlign(Pair.first));
5750 FirstprivateScope.
addPrivate(Pair.first, Replacement);
5753 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5755 Data.ReductionCopies,
Data.ReductionOps);
5756 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
5758 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5764 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5766 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5769 CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF),
5770 CGF.getContext().VoidPtrTy,
5771 CGF.getContext().getPointerType(
5772 Data.ReductionCopies[Cnt]->getType()),
5773 Data.ReductionCopies[Cnt]->getExprLoc()),
5774 CGF.ConvertTypeForMem(
Data.ReductionCopies[Cnt]->getType()),
5775 Replacement.getAlignment());
5781 (void)
Scope.Privatize();
5786 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5787 auto IPriv =
C->privates().begin();
5788 auto IRed =
C->reduction_ops().begin();
5789 auto ITD =
C->taskgroup_descriptors().begin();
5790 for (
const Expr *Ref :
C->varlist()) {
5791 InRedVars.emplace_back(Ref);
5792 InRedPrivs.emplace_back(*IPriv);
5793 InRedOps.emplace_back(*IRed);
5794 TaskgroupDescriptors.emplace_back(*ITD);
5795 std::advance(IPriv, 1);
5796 std::advance(IRed, 1);
5797 std::advance(ITD, 1);
5803 if (!InRedVars.empty()) {
5805 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5813 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5815 llvm::Value *ReductionsPtr;
5816 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5817 ReductionsPtr = CGF.EmitLoadOfScalar(CGF.EmitLValue(TRExpr),
5818 TRExpr->getExprLoc());
5820 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5822 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5825 CGF.EmitScalarConversion(
5826 Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy,
5827 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
5828 InRedPrivs[Cnt]->getExprLoc()),
5829 CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()),
5830 Replacement.getAlignment());
5843 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5844 S, *I, *PartId, *TaskT, EKind,
CodeGen,
Data.Tied,
Data.NumberOfParts);
5845 OMPLexicalScope
Scope(*
this, S, std::nullopt,
5848 TaskGen(*
this, OutlinedFn,
Data);
5865 QualType ElemType =
C.getBaseElementType(Ty);
5875 Data.FirstprivateVars.emplace_back(OrigRef);
5876 Data.FirstprivateCopies.emplace_back(PrivateRef);
5877 Data.FirstprivateInits.emplace_back(InitRef);
5890 auto PartId = std::next(I);
5891 auto TaskT = std::next(I, 4);
5894 Data.Final.setInt(
false);
5896 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5897 auto IRef =
C->varlist_begin();
5898 auto IElemInitRef =
C->inits().begin();
5899 for (
auto *IInit :
C->private_copies()) {
5900 Data.FirstprivateVars.push_back(*IRef);
5901 Data.FirstprivateCopies.push_back(IInit);
5902 Data.FirstprivateInits.push_back(*IElemInitRef);
5909 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5910 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5911 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5912 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5913 Data.ReductionOps.append(
C->reduction_ops().begin(),
5914 C->reduction_ops().end());
5915 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5916 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5931 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5933 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5945 if (!isa_and_nonnull<llvm::ConstantPointerNull>(
5948 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5955 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, BPVD, PVD, SVD, MVD, EKind,
5959 if (!
Data.FirstprivateVars.empty()) {
5960 enum { PrivatesParam = 2, CopyFnParam = 3 };
5961 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5963 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5969 CallArgs.push_back(PrivatesPtr);
5970 ParamTypes.push_back(PrivatesPtr->getType());
5971 for (
const Expr *E :
Data.FirstprivateVars) {
5973 RawAddress PrivatePtr = CGF.CreateMemTempWithoutCast(
5974 CGF.getContext().getPointerType(E->
getType()),
5975 ".firstpriv.ptr.addr");
5976 PrivatePtrs.emplace_back(VD, PrivatePtr);
5978 ParamTypes.push_back(PrivatePtr.
getType());
5980 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5982 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5983 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5984 for (
const auto &Pair : PrivatePtrs) {
5986 CGF.Builder.CreateLoad(Pair.second),
5987 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5988 CGF.getContext().getDeclAlign(Pair.first));
5989 Scope.addPrivate(Pair.first, Replacement);
5992 CGF.processInReduction(S,
Data, CGF, CS,
Scope);
5995 CGF.GetAddrOfLocalVar(BPVD), 0);
5997 CGF.GetAddrOfLocalVar(PVD), 0);
5998 InputInfo.
SizesArray = CGF.Builder.CreateConstArrayGEP(
5999 CGF.GetAddrOfLocalVar(SVD), 0);
6002 InputInfo.
MappersArray = CGF.Builder.CreateConstArrayGEP(
6003 CGF.GetAddrOfLocalVar(MVD), 0);
6007 OMPLexicalScope LexScope(CGF, S, OMPD_task,
false);
6009 if (CGF.CGM.getLangOpts().OpenMP >= 51 &&
6014 CGF.CGM.getOpenMPRuntime().emitThreadLimitClause(
6015 CGF, TL->getThreadLimit().front(), S.getBeginLoc());
6019 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
6020 S, *I, *PartId, *TaskT, EKind,
CodeGen,
true,
6021 Data.NumberOfParts);
6022 llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<OMPNowaitClause>() ? 1 : 0);
6026 CGM.getOpenMPRuntime().emitTaskCall(*
this, S.getBeginLoc(), S, OutlinedFn,
6027 SharedsTy, CapturedStruct, &IfCond,
Data);
6032 CodeGenFunction &CGF,
6036 if (
Data.Reductions) {
6038 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
6040 Data.ReductionCopies,
Data.ReductionOps);
6043 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
6057 Data.ReductionCopies[Cnt]->getType()),
6058 Data.ReductionCopies[Cnt]->getExprLoc()),
6060 Replacement.getAlignment());
6065 (void)
Scope.Privatize();
6070 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
6071 auto IPriv =
C->privates().begin();
6072 auto IRed =
C->reduction_ops().begin();
6073 auto ITD =
C->taskgroup_descriptors().begin();
6074 for (
const Expr *Ref :
C->varlist()) {
6075 InRedVars.emplace_back(Ref);
6076 InRedPrivs.emplace_back(*IPriv);
6077 InRedOps.emplace_back(*IRed);
6078 TaskgroupDescriptors.emplace_back(*ITD);
6079 std::advance(IPriv, 1);
6080 std::advance(IRed, 1);
6081 std::advance(ITD, 1);
6085 if (!InRedVars.empty()) {
6087 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
6095 llvm::Value *ReductionsPtr;
6096 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
6100 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
6108 InRedPrivs[Cnt]->getExprLoc()),
6110 Replacement.getAlignment());
6124 const Expr *IfCond =
nullptr;
6125 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
6126 if (
C->getNameModifier() == OMPD_unknown ||
6127 C->getNameModifier() == OMPD_task) {
6128 IfCond =
C->getCondition();
6135 Data.Tied = !S.getSingleClause<OMPUntiedClause>();
6139 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
6140 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
6143 SharedsTy, CapturedStruct, IfCond,
6153 CGM.getOpenMPRuntime().emitTaskyieldCall(*
this, S.getBeginLoc());
6157 const OMPMessageClause *MC = S.getSingleClause<OMPMessageClause>();
6158 Expr *ME = MC ? MC->getMessageString() :
nullptr;
6159 const OMPSeverityClause *SC = S.getSingleClause<OMPSeverityClause>();
6160 bool IsFatal =
false;
6161 if (!SC || SC->getSeverityKind() == OMPC_SEVERITY_fatal)
6163 CGM.getOpenMPRuntime().emitErrorCall(*
this, S.getBeginLoc(), ME, IsFatal);
6167 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_barrier);
6174 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
6175 CGM.getOpenMPRuntime().emitTaskwaitCall(*
this, S.getBeginLoc(),
Data);
6179 return T.clauses().empty();
6184 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6186 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
6187 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6190 auto BodyGenCB = [&,
this](InsertPointTy AllocIP, InsertPointTy CodeGenIP,
6193 EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
6194 return llvm::Error::success();
6199 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
6200 cantFail(OMPBuilder.createTaskgroup(
Builder, AllocaIP,
6211 for (
const auto *
C : S.getClausesOfKind<OMPTaskReductionClause>()) {
6212 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
6213 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
6214 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
6215 Data.ReductionOps.append(
C->reduction_ops().begin(),
6216 C->reduction_ops().end());
6217 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
6218 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
6220 llvm::Value *ReductionDesc =
6228 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
6230 CGM.getOpenMPRuntime().emitTaskgroupRegion(*
this,
CodeGen, S.getBeginLoc());
6235 ? llvm::AtomicOrdering::NotAtomic
6236 : llvm::AtomicOrdering::AcquireRelease;
6237 CGM.getOpenMPRuntime().emitFlush(
6240 if (
const auto *FlushClause = S.getSingleClause<
OMPFlushClause>())
6242 FlushClause->varlist_end());
6245 S.getBeginLoc(), AO);
6255 for (
auto &Dep :
Data.Dependences) {
6256 Address DepAddr =
CGM.getOpenMPRuntime().emitDepobjDependClause(
6257 *
this, Dep, DC->getBeginLoc());
6263 CGM.getOpenMPRuntime().emitDestroyClause(*
this, DOLVal, DC->getBeginLoc());
6266 if (
const auto *UC = S.getSingleClause<OMPUpdateDependObjectsClause>()) {
6267 CGM.getOpenMPRuntime().emitUpdateDependObjectsClause(
6268 *
this, DOLVal, UC->getDependencyKind(), UC->getBeginLoc());
6286 for (
const auto *
C : ParentDir.getClausesOfKind<OMPReductionClause>()) {
6287 if (
C->getModifier() != OMPC_REDUCTION_inscan)
6289 Shareds.append(
C->varlist_begin(),
C->varlist_end());
6290 Privates.append(
C->privates().begin(),
C->privates().end());
6291 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
6292 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
6293 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
6294 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
6295 CopyArrayTemps.append(
C->copy_array_temps().begin(),
6296 C->copy_array_temps().end());
6297 CopyArrayElems.append(
C->copy_array_elems().begin(),
6298 C->copy_array_elems().end());
6300 if (ParentDir.getDirectiveKind() == OMPD_simd ||
6342 : BreakContinueStack.back().ContinueBlock.getBlock());
6353 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6355 const Expr *TempExpr = CopyArrayTemps[I];
6367 CGM.getOpenMPRuntime().emitReduction(
6368 *
this, ParentDir.getEndLoc(),
Privates, LHSs, RHSs, ReductionOps,
6371 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6379 const Expr *TempExpr = CopyArrayTemps[I];
6391 ? BreakContinueStack.back().ContinueBlock.getBlock()
6397 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6403 .getIterationVariable()
6404 ->IgnoreParenImpCasts();
6407 IdxVal = Builder.CreateIntCast(IdxVal,
SizeTy,
false);
6408 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6410 const Expr *OrigExpr = Shareds[I];
6411 const Expr *CopyArrayElem = CopyArrayElems[I];
6412 OpaqueValueMapping IdxMapping(
6425 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6428 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6434 .getIterationVariable()
6435 ->IgnoreParenImpCasts();
6439 llvm::BasicBlock *ExclusiveExitBB =
nullptr;
6443 llvm::Value *
Cmp =
Builder.CreateIsNull(IdxVal);
6444 Builder.CreateCondBr(
Cmp, ExclusiveExitBB, ContBB);
6447 IdxVal =
Builder.CreateNUWSub(IdxVal, llvm::ConstantInt::get(
SizeTy, 1));
6449 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6450 const Expr *PrivateExpr =
Privates[I];
6451 const Expr *OrigExpr = Shareds[I];
6452 const Expr *CopyArrayElem = CopyArrayElems[I];
6461 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
6494 bool HasLastprivateClause =
false;
6497 OMPLoopScope PreInitScope(*
this, S);
6502 llvm::BasicBlock *ContBlock =
nullptr;
6538 CGM.getOpenMPRuntime().emitBarrierCall(
6539 *
this, S.getBeginLoc(), OMPD_unknown,
false,
6551 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
6554 llvm::Value *Chunk =
nullptr;
6557 ScheduleKind =
C->getDistScheduleKind();
6558 if (
const Expr *Ch =
C->getChunkSize()) {
6566 CGM.getOpenMPRuntime().getDefaultDistScheduleAndChunk(
6567 *
this, S, ScheduleKind, Chunk);
6588 bool StaticChunked =
6592 Chunk !=
nullptr) ||
6597 StaticChunked ? Chunk :
nullptr);
6648 [&S, &LoopScope, Cond, IncExpr,
LoopExit, &CodeGenLoop,
6651 S, LoopScope.requiresCleanups(), Cond, IncExpr,
6652 [&S,
LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
6653 CodeGenLoop(CGF, S, LoopExit);
6655 [&S, StaticChunked](CodeGenFunction &CGF) {
6656 if (StaticChunked) {
6657 CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound());
6658 CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound());
6659 CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound());
6660 CGF.EmitIgnoredExpr(S.getCombinedInit());
6670 const OMPLoopArguments LoopArguments = {
6673 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments,
6679 return CGF.
Builder.CreateIsNotNull(
6689 *
this, S, [IL, &S](CodeGenFunction &CGF) {
6690 return CGF.
Builder.CreateIsNotNull(
6695 if (HasLastprivateClause) {
6718 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
6727static llvm::Function *
6734 Fn->setDoesNotRecurse();
6738template <
typename T>
6740 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP,
6741 llvm::OpenMPIRBuilder &OMPBuilder) {
6743 unsigned NumLoops =
C->getNumLoops();
6747 for (
unsigned I = 0; I < NumLoops; I++) {
6748 const Expr *CounterVal =
C->getLoopData(I);
6753 StoreValues.emplace_back(StoreValue);
6755 OMPDoacrossKind<T> ODK;
6756 bool IsDependSource = ODK.isSource(
C);
6758 OMPBuilder.createOrderedDepend(CGF.
Builder, AllocaIP, NumLoops,
6759 StoreValues,
".cnt.addr", IsDependSource));
6766 "Standalone ordered directive should have either depend or doacross "
6769 assert(!S.hasAssociatedStmt() &&
"No associated statement must be in "
6770 "ordered depend|doacross construct.");
6772 if (
CGM.getLangOpts().OpenMPIRBuilder) {
6773 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
6774 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6786 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6789 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6795 if (
CGM.getLangOpts().OpenMPIRBuilder) {
6796 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
6797 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6803 auto FiniCB = [
this](InsertPointTy IP) {
6805 return llvm::Error::success();
6808 auto BodyGenCB = [&S,
C,
this](InsertPointTy AllocIP,
6809 InsertPointTy CodeGenIP,
6815 llvm::BasicBlock *CodeGenBB = CodeGenIP.getNodeParent();
6816 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
6817 Builder,
false,
".ordered.after");
6821 assert(S.getBeginLoc().isValid() &&
6822 "Outlined function call location must be valid.");
6825 OutlinedFn, CapturedVars);
6830 return llvm::Error::success();
6833 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6834 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
6835 OMPBuilder.createOrderedThreadsSimd(
Builder, BodyGenCB, FiniCB, !
C));
6841 auto &&
CodeGen = [&S,
C,
this](CodeGenFunction &CGF,
6846 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
6848 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
6849 OutlinedFn, CapturedVars);
6855 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6856 CGM.getOpenMPRuntime().emitOrderedRegion(*
this,
CodeGen, S.getBeginLoc(), !
C);
6863 "DestType must have scalar evaluation kind.");
6864 assert(!Val.
isAggregate() &&
"Must be a scalar or complex.");
6875 "DestType must have complex evaluation kind.");
6884 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
6886 assert(Val.
isComplex() &&
"Must be a scalar or complex.");
6891 Val.
getComplexVal().first, SrcElementType, DestElementType, Loc);
6893 Val.
getComplexVal().second, SrcElementType, DestElementType, Loc);
6899 LValue LVal,
RValue RVal) {
6900 if (LVal.isGlobalReg())
6907 llvm::AtomicOrdering AO, LValue LVal,
6909 if (LVal.isGlobalReg())
6912 LVal, Loc, llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO),
6921 *
this, RVal, RValTy, LVal.
getType(), Loc)),
6930 llvm_unreachable(
"Must be a scalar or complex.");
6938 assert(
V->isLValue() &&
"V of 'omp atomic read' is not lvalue");
6939 assert(
X->isLValue() &&
"X of 'omp atomic read' is not lvalue");
6948 case llvm::AtomicOrdering::Acquire:
6949 case llvm::AtomicOrdering::AcquireRelease:
6950 case llvm::AtomicOrdering::SequentiallyConsistent:
6952 llvm::AtomicOrdering::Acquire);
6954 case llvm::AtomicOrdering::Monotonic:
6955 case llvm::AtomicOrdering::Release:
6957 case llvm::AtomicOrdering::NotAtomic:
6958 case llvm::AtomicOrdering::Unordered:
6959 llvm_unreachable(
"Unexpected ordering.");
6966 llvm::AtomicOrdering AO,
const Expr *
X,
6969 assert(
X->isLValue() &&
"X of 'omp atomic write' is not lvalue");
6977 case llvm::AtomicOrdering::Release:
6978 case llvm::AtomicOrdering::AcquireRelease:
6979 case llvm::AtomicOrdering::SequentiallyConsistent:
6981 llvm::AtomicOrdering::Release);
6983 case llvm::AtomicOrdering::Acquire:
6984 case llvm::AtomicOrdering::Monotonic:
6986 case llvm::AtomicOrdering::NotAtomic:
6987 case llvm::AtomicOrdering::Unordered:
6988 llvm_unreachable(
"Unexpected ordering.");
6995 llvm::AtomicOrdering AO,
6996 bool IsXLHSInRHSPart) {
7001 if (BO == BO_Comma || !
Update.isScalar() || !
X.isSimple() ||
7003 (
Update.getScalarVal()->getType() !=
X.getAddress().getElementType())) ||
7004 !Context.getTargetInfo().hasBuiltinAtomic(
7005 Context.getTypeSize(
X.getType()), Context.toBits(
X.getAlignment())))
7006 return std::make_pair(
false,
RValue::get(
nullptr));
7009 if (
T->isIntegerTy())
7012 if (
T->isFloatingPointTy() && (BO == BO_Add || BO == BO_Sub))
7018 if (!CheckAtomicSupport(
Update.getScalarVal()->getType(), BO) ||
7019 !CheckAtomicSupport(
X.getAddress().getElementType(), BO))
7020 return std::make_pair(
false,
RValue::get(
nullptr));
7022 bool IsInteger =
X.getAddress().getElementType()->isIntegerTy();
7023 llvm::AtomicRMWInst::BinOp RMWOp;
7026 RMWOp = IsInteger ? llvm::AtomicRMWInst::Add : llvm::AtomicRMWInst::FAdd;
7029 if (!IsXLHSInRHSPart)
7030 return std::make_pair(
false,
RValue::get(
nullptr));
7031 RMWOp = IsInteger ? llvm::AtomicRMWInst::Sub : llvm::AtomicRMWInst::FSub;
7034 RMWOp = llvm::AtomicRMWInst::And;
7037 RMWOp = llvm::AtomicRMWInst::Or;
7040 RMWOp = llvm::AtomicRMWInst::Xor;
7044 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
7045 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Min
7046 : llvm::AtomicRMWInst::Max)
7047 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMin
7048 : llvm::AtomicRMWInst::UMax);
7050 RMWOp = IsXLHSInRHSPart ? llvm::AtomicRMWInst::FMin
7051 : llvm::AtomicRMWInst::FMax;
7055 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
7056 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Max
7057 : llvm::AtomicRMWInst::Min)
7058 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMax
7059 : llvm::AtomicRMWInst::UMin);
7061 RMWOp = IsXLHSInRHSPart ? llvm::AtomicRMWInst::FMax
7062 : llvm::AtomicRMWInst::FMin;
7065 RMWOp = llvm::AtomicRMWInst::Xchg;
7074 return std::make_pair(
false,
RValue::get(
nullptr));
7093 llvm_unreachable(
"Unsupported atomic update operation");
7095 llvm::Value *UpdateVal =
Update.getScalarVal();
7096 if (
auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
7098 UpdateVal = CGF.
Builder.CreateIntCast(
7099 IC,
X.getAddress().getElementType(),
7100 X.getType()->hasSignedIntegerRepresentation());
7102 UpdateVal = CGF.
Builder.CreateCast(llvm::Instruction::CastOps::UIToFP, IC,
7103 X.getAddress().getElementType());
7105 llvm::AtomicRMWInst *Res =
7122 if (
X.isGlobalReg()) {
7135 llvm::AtomicOrdering AO,
const Expr *
X,
7139 "Update expr in 'atomic update' must be a binary operator.");
7147 assert(
X->isLValue() &&
"X of 'omp atomic update' is not lvalue");
7154 auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](
RValue XRValue) {
7160 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
7167 case llvm::AtomicOrdering::Release:
7168 case llvm::AtomicOrdering::AcquireRelease:
7169 case llvm::AtomicOrdering::SequentiallyConsistent:
7171 llvm::AtomicOrdering::Release);
7173 case llvm::AtomicOrdering::Acquire:
7174 case llvm::AtomicOrdering::Monotonic:
7176 case llvm::AtomicOrdering::NotAtomic:
7177 case llvm::AtomicOrdering::Unordered:
7178 llvm_unreachable(
"Unexpected ordering.");
7196 llvm_unreachable(
"Must be a scalar or complex.");
7200 llvm::AtomicOrdering AO,
7201 bool IsPostfixUpdate,
const Expr *
V,
7203 const Expr *UE,
bool IsXLHSInRHSPart,
7205 assert(
X->isLValue() &&
"X of 'omp atomic capture' is not lvalue");
7206 assert(
V->isLValue() &&
"V of 'omp atomic capture' is not lvalue");
7215 "Update expr in 'atomic capture' must be a binary operator.");
7226 NewVValType = XRValExpr->
getType();
7228 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
7229 IsPostfixUpdate](
RValue XRValue) {
7233 NewVVal = IsPostfixUpdate ? XRValue : Res;
7237 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
7241 if (IsPostfixUpdate) {
7243 NewVVal = Res.second;
7254 NewVValType =
X->getType().getNonReferenceType();
7256 X->getType().getNonReferenceType(), Loc);
7257 auto &&Gen = [&NewVVal, ExprRValue](
RValue XRValue) {
7263 XLValue, ExprRValue, BO_Assign,
false, AO,
7268 NewVVal = IsPostfixUpdate ? Res.second : ExprRValue;
7284 case llvm::AtomicOrdering::Release:
7286 llvm::AtomicOrdering::Release);
7288 case llvm::AtomicOrdering::Acquire:
7290 llvm::AtomicOrdering::Acquire);
7292 case llvm::AtomicOrdering::AcquireRelease:
7293 case llvm::AtomicOrdering::SequentiallyConsistent:
7295 CGF, {}, Loc, llvm::AtomicOrdering::AcquireRelease);
7297 case llvm::AtomicOrdering::Monotonic:
7299 case llvm::AtomicOrdering::NotAtomic:
7300 case llvm::AtomicOrdering::Unordered:
7301 llvm_unreachable(
"Unexpected ordering.");
7307 CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO,
7309 const Expr *CE,
bool IsXBinopExpr,
bool IsPostfixUpdate,
bool IsFailOnly,
7311 llvm::OpenMPIRBuilder &OMPBuilder =
7314 OMPAtomicCompareOp Op;
7318 Op = OMPAtomicCompareOp::EQ;
7321 Op = OMPAtomicCompareOp::MIN;
7324 Op = OMPAtomicCompareOp::MAX;
7327 llvm_unreachable(
"unsupported atomic compare binary operator");
7331 Address XAddr = XLVal.getAddress();
7333 auto EmitRValueWithCastIfNeeded = [&CGF, Loc](
const Expr *
X,
const Expr *E) {
7338 if (NewE->
getType() ==
X->getType())
7343 llvm::Value *EVal = EmitRValueWithCastIfNeeded(
X, E);
7344 llvm::Value *DVal = D ? EmitRValueWithCastIfNeeded(
X, D) :
nullptr;
7345 if (
auto *CI = dyn_cast<llvm::ConstantInt>(EVal))
7346 EVal = CGF.
Builder.CreateIntCast(
7347 CI, XLVal.getAddress().getElementType(),
7350 if (
auto *CI = dyn_cast<llvm::ConstantInt>(DVal))
7351 DVal = CGF.
Builder.CreateIntCast(
7352 CI, XLVal.getAddress().getElementType(),
7355 llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{
7357 X->getType()->hasSignedIntegerRepresentation(),
7358 X->getType().isVolatileQualified()};
7359 llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal;
7363 VOpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
7364 V->getType()->hasSignedIntegerRepresentation(),
7365 V->getType().isVolatileQualified()};
7370 ROpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
7371 R->getType()->hasSignedIntegerRepresentation(),
7372 R->getType().isVolatileQualified()};
7375 if (FailAO == llvm::AtomicOrdering::NotAtomic) {
7378 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
7379 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
7380 IsPostfixUpdate, IsFailOnly));
7382 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
7383 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
7384 IsPostfixUpdate, IsFailOnly, FailAO));
7388 llvm::AtomicOrdering AO,
7389 llvm::AtomicOrdering FailAO,
bool IsPostfixUpdate,
7392 const Expr *CE,
bool IsXLHSInRHSPart,
7407 IsXLHSInRHSPart, Loc);
7409 case OMPC_compare: {
7411 IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly, Loc);
7415 llvm_unreachable(
"Clause is not allowed in 'omp atomic'.");
7420 llvm::AtomicOrdering AO =
CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
7422 llvm::AtomicOrdering FailAO = llvm::AtomicOrdering::NotAtomic;
7423 bool MemOrderingSpecified =
false;
7424 if (S.getSingleClause<OMPSeqCstClause>()) {
7425 AO = llvm::AtomicOrdering::SequentiallyConsistent;
7426 MemOrderingSpecified =
true;
7427 }
else if (S.getSingleClause<OMPAcqRelClause>()) {
7428 AO = llvm::AtomicOrdering::AcquireRelease;
7429 MemOrderingSpecified =
true;
7430 }
else if (S.getSingleClause<OMPAcquireClause>()) {
7431 AO = llvm::AtomicOrdering::Acquire;
7432 MemOrderingSpecified =
true;
7433 }
else if (S.getSingleClause<OMPReleaseClause>()) {
7434 AO = llvm::AtomicOrdering::Release;
7435 MemOrderingSpecified =
true;
7436 }
else if (S.getSingleClause<OMPRelaxedClause>()) {
7437 AO = llvm::AtomicOrdering::Monotonic;
7438 MemOrderingSpecified =
true;
7440 llvm::SmallSet<OpenMPClauseKind, 2> KindsEncountered;
7449 if (K == OMPC_seq_cst || K == OMPC_acq_rel || K == OMPC_acquire ||
7450 K == OMPC_release || K == OMPC_relaxed || K == OMPC_hint)
7453 KindsEncountered.insert(K);
7458 if (KindsEncountered.contains(OMPC_compare) &&
7459 KindsEncountered.contains(OMPC_capture))
7460 Kind = OMPC_compare;
7461 if (!MemOrderingSpecified) {
7462 llvm::AtomicOrdering DefaultOrder =
7463 CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
7464 if (DefaultOrder == llvm::AtomicOrdering::Monotonic ||
7465 DefaultOrder == llvm::AtomicOrdering::SequentiallyConsistent ||
7466 (DefaultOrder == llvm::AtomicOrdering::AcquireRelease &&
7467 Kind == OMPC_capture)) {
7469 }
else if (DefaultOrder == llvm::AtomicOrdering::AcquireRelease) {
7470 if (Kind == OMPC_unknown || Kind == OMPC_update || Kind == OMPC_write) {
7471 AO = llvm::AtomicOrdering::Release;
7472 }
else if (Kind == OMPC_read) {
7473 assert(Kind == OMPC_read &&
"Unexpected atomic kind.");
7474 AO = llvm::AtomicOrdering::Acquire;
7479 if (KindsEncountered.contains(OMPC_compare) &&
7480 KindsEncountered.contains(OMPC_fail)) {
7481 Kind = OMPC_compare;
7482 const auto *FailClause = S.getSingleClause<OMPFailClause>();
7485 if (FailParameter == llvm::omp::OMPC_relaxed)
7486 FailAO = llvm::AtomicOrdering::Monotonic;
7487 else if (FailParameter == llvm::omp::OMPC_acquire)
7488 FailAO = llvm::AtomicOrdering::Acquire;
7489 else if (FailParameter == llvm::omp::OMPC_seq_cst)
7490 FailAO = llvm::AtomicOrdering::SequentiallyConsistent;
7510 OMPLexicalScope
Scope(CGF, S, OMPD_target);
7513 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
7519 llvm::Function *Fn =
nullptr;
7520 llvm::Constant *FnID =
nullptr;
7522 const Expr *IfCond =
nullptr;
7524 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7525 if (
C->getNameModifier() == OMPD_unknown ||
7526 C->getNameModifier() == OMPD_target) {
7527 IfCond =
C->getCondition();
7533 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device(
7536 Device.setPointerAndInt(
C->getDevice(),
C->getModifier());
7541 bool IsOffloadEntry =
true;
7545 IsOffloadEntry =
false;
7548 IsOffloadEntry =
false;
7550 if (
CGM.
getLangOpts().OpenMPOffloadMandatory && !IsOffloadEntry) {
7554 StringRef ParentName;
7559 ParentName = CGF.
CurFn->getName();
7560 else if (
const auto *D = dyn_cast<CXXConstructorDecl>(CGF.
CurFuncDecl))
7562 else if (
const auto *D = dyn_cast<CXXDestructorDecl>(CGF.
CurFuncDecl))
7571 OMPLexicalScope
Scope(CGF, S, OMPD_task);
7572 auto &&SizeEmitter =
7575 if (IsOffloadEntry) {
7576 OMPLoopScope PreInitScope(CGF, D);
7579 NumIterations = CGF.
Builder.CreateIntCast(NumIterations, CGF.
Int64Ty,
7581 return NumIterations;
7599 CGF.
EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
7604 StringRef ParentName,
7610 llvm::Constant *
Addr;
7612 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7614 assert(Fn &&
Addr &&
"Target device function emission failed.");
7628 const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams);
7629 llvm::Function *OutlinedFn =
7634 OMPTeamsScope
Scope(CGF, S);
7639 const Expr *NumTeams = NT ? NT->getNumTeams().front() :
nullptr;
7640 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() :
nullptr;
7647 const Expr *IfCond =
nullptr;
7648 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7649 if (
C->getNameModifier() == OMPD_unknown ||
7650 C->getNameModifier() == OMPD_teams) {
7651 IfCond =
C->getCondition();
7660 const llvm::APInt One(32, 1);
7667 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() :
nullptr;
7693 CGF.
EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt());
7698 [](CodeGenFunction &) {
return nullptr; });
7703 auto *CS = S.getCapturedStmt(OMPD_teams);
7730 llvm::Constant *
Addr;
7732 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7734 assert(Fn &&
Addr &&
"Target device function emission failed.");
7776 llvm::Constant *
Addr;
7778 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7780 assert(Fn &&
Addr &&
"Target device function emission failed.");
7822 llvm::Constant *
Addr;
7824 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7826 assert(Fn &&
Addr &&
"Target device function emission failed.");
7840 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7845 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7857 [](CodeGenFunction &) {
return nullptr; });
7862 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7867 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7879 [](CodeGenFunction &) {
return nullptr; });
7884 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7890 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7902 [](CodeGenFunction &) {
return nullptr; });
7907 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7913 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7920 CGF, OMPD_distribute, CodeGenDistribute,
false);
7926 [](CodeGenFunction &) {
return nullptr; });
7930 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7931 llvm::Value *
Device =
nullptr;
7932 llvm::Value *NumDependences =
nullptr;
7933 llvm::Value *DependenceList =
nullptr;
7941 if (!
Data.Dependences.empty()) {
7943 std::tie(NumDependences, DependenciesArray) =
7944 CGM.getOpenMPRuntime().emitDependClause(*
this,
Data.Dependences,
7948 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
7953 "OMPNowaitClause clause is used separately in OMPInteropDirective.");
7956 if (!ItOMPInitClause.empty()) {
7959 llvm::Value *InteropvarPtr =
7961 llvm::omp::OMPInteropType InteropType =
7962 llvm::omp::OMPInteropType::Unknown;
7963 if (
C->getIsTarget()) {
7964 InteropType = llvm::omp::OMPInteropType::Target;
7966 assert(
C->getIsTargetSync() &&
7967 "Expected interop-type target/targetsync");
7968 InteropType = llvm::omp::OMPInteropType::TargetSync;
7970 OMPBuilder.createOMPInteropInit(
Builder, InteropvarPtr, InteropType,
7971 Device, NumDependences, DependenceList,
7972 Data.HasNowaitClause);
7976 if (!ItOMPDestroyClause.empty()) {
7979 llvm::Value *InteropvarPtr =
7981 OMPBuilder.createOMPInteropDestroy(
Builder, InteropvarPtr,
Device,
7982 NumDependences, DependenceList,
7983 Data.HasNowaitClause);
7986 auto ItOMPUseClause = S.getClausesOfKind<
OMPUseClause>();
7987 if (!ItOMPUseClause.empty()) {
7990 llvm::Value *InteropvarPtr =
7992 OMPBuilder.createOMPInteropUse(
Builder, InteropvarPtr,
Device,
7993 NumDependences, DependenceList,
7994 Data.HasNowaitClause);
8016 CGF, OMPD_distribute, CodeGenDistribute,
false);
8035 llvm::Constant *
Addr;
8037 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8039 assert(Fn &&
Addr &&
"Target device function emission failed.");
8068 CGF, OMPD_distribute, CodeGenDistribute,
false);
8087 llvm::Constant *
Addr;
8089 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8091 assert(Fn &&
Addr &&
"Target device function emission failed.");
8104 CGM.getOpenMPRuntime().emitCancellationPointCall(*
this, S.getBeginLoc(),
8109 const Expr *IfCond =
nullptr;
8110 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
8111 if (
C->getNameModifier() == OMPD_unknown ||
8112 C->getNameModifier() == OMPD_cancel) {
8113 IfCond =
C->getCondition();
8117 if (
CGM.getLangOpts().OpenMPIRBuilder) {
8118 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
8124 llvm::Value *IfCondition =
nullptr;
8128 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
8130 return Builder.restoreIP(AfterIP);
8134 CGM.getOpenMPRuntime().emitCancelCall(*
this, S.getBeginLoc(), IfCond,
8140 if (Kind == OMPD_parallel || Kind == OMPD_task ||
8141 Kind == OMPD_target_parallel || Kind == OMPD_taskloop ||
8142 Kind == OMPD_master_taskloop || Kind == OMPD_parallel_master_taskloop)
8144 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
8145 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
8146 Kind == OMPD_distribute_parallel_for ||
8147 Kind == OMPD_target_parallel_for ||
8148 Kind == OMPD_teams_distribute_parallel_for ||
8149 Kind == OMPD_target_teams_distribute_parallel_for);
8150 return OMPCancelStack.getExitBlock();
8155 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
8156 CaptureDeviceAddrMap) {
8157 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
8158 for (
const Expr *OrigVarIt :
C.varlist()) {
8160 if (!Processed.insert(OrigVD).second)
8167 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
8172 "Base should be the current struct!");
8173 MatchingVD = ME->getMemberDecl();
8178 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
8179 if (InitAddrIt == CaptureDeviceAddrMap.end())
8187 Address(InitAddrIt->second, Ty,
8189 assert(IsRegistered &&
"firstprivate var already registered as private");
8197 while (
const auto *OASE = dyn_cast<ArraySectionExpr>(
Base))
8198 Base = OASE->getBase()->IgnoreParenImpCasts();
8199 while (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(
Base))
8200 Base = ASE->getBase()->IgnoreParenImpCasts();
8206 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
8207 CaptureDeviceAddrMap) {
8208 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
8209 for (
const Expr *Ref :
C.varlist()) {
8211 if (!Processed.insert(OrigVD).second)
8217 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
8222 "Base should be the current struct!");
8223 MatchingVD = ME->getMemberDecl();
8228 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
8229 if (InitAddrIt == CaptureDeviceAddrMap.end())
8235 Address(InitAddrIt->second, Ty,
8248 (void)PrivateScope.
addPrivate(OrigVD, PrivAddr);
8256 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
8257 CGM.getOpenMPRuntime().registerVTable(S);
8265 bool PrivatizeDevicePointers =
false;
8267 bool &PrivatizeDevicePointers;
8270 explicit DevicePointerPrivActionTy(
bool &PrivatizeDevicePointers)
8271 : PrivatizeDevicePointers(PrivatizeDevicePointers) {}
8272 void Enter(CodeGenFunction &CGF)
override {
8273 PrivatizeDevicePointers =
true;
8276 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
8279 auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
8280 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
8284 auto &&PrivCodeGen = [&](CodeGenFunction &CGF,
PrePostActionTy &Action) {
8286 PrivatizeDevicePointers =
false;
8292 if (PrivatizeDevicePointers) {
8306 std::optional<OpenMPDirectiveKind> CaptureRegion;
8307 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
8310 for (
const Expr *E :
C->varlist()) {
8312 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
8316 for (
const Expr *E :
C->varlist()) {
8318 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
8322 CaptureRegion = OMPD_unknown;
8325 OMPLexicalScope
Scope(CGF, S, CaptureRegion);
8337 OMPLexicalScope
Scope(CGF, S);
8346 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
8352 const Expr *IfCond =
nullptr;
8354 IfCond =
C->getCondition();
8365 CGM.getOpenMPRuntime().emitTargetDataCalls(*
this, S, IfCond,
Device, RCG,
8373 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8377 const Expr *IfCond =
nullptr;
8379 IfCond =
C->getCondition();
8386 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8387 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8394 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8398 const Expr *IfCond =
nullptr;
8400 IfCond =
C->getCondition();
8407 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8408 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8415 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
8443 llvm::Constant *
Addr;
8445 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8447 assert(Fn &&
Addr &&
"Target device function emission failed.");
8467 CGF, OMPD_target_parallel_for, S.
hasCancel());
8483 llvm::Constant *
Addr;
8485 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8487 assert(Fn &&
Addr &&
"Target device function emission failed.");
8522 llvm::Constant *
Addr;
8524 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8526 assert(Fn &&
Addr &&
"Target device function emission failed.");
8548 const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop);
8551 OMPLexicalScope
Scope(*
this, S, OMPD_taskloop,
false);
8556 const Expr *IfCond =
nullptr;
8557 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
8558 if (
C->getNameModifier() == OMPD_unknown ||
8559 C->getNameModifier() == OMPD_taskloop) {
8560 IfCond =
C->getCondition();
8573 Data.Schedule.setInt(
false);
8576 (Clause->getModifier() == OMPC_GRAINSIZE_strict) ?
true :
false;
8579 Data.Schedule.setInt(
true);
8582 (Clause->getModifier() == OMPC_NUMTASKS_strict) ?
true :
false;
8596 llvm::BasicBlock *ContBlock =
nullptr;
8597 OMPLoopScope PreInitScope(CGF, S);
8598 if (CGF.ConstantFoldsToSimpleInteger(S.
getPreCond(), CondConstant)) {
8602 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock(
"taskloop.if.then");
8603 ContBlock = CGF.createBasicBlock(
"taskloop.if.end");
8605 CGF.getProfileCount(&S));
8606 CGF.EmitBlock(ThenBlock);
8607 CGF.incrementProfileCounter(&S);
8610 (void)CGF.EmitOMPLinearClauseInit(S);
8614 enum { LowerBound = 5, UpperBound, Stride, LastIter };
8616 auto *LBP = std::next(I, LowerBound);
8617 auto *UBP = std::next(I, UpperBound);
8618 auto *STP = std::next(I, Stride);
8619 auto *LIP = std::next(I, LastIter);
8627 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
8628 CGF.EmitOMPLinearClause(S, LoopScope);
8629 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
8634 CGF.EmitVarDecl(*IVDecl);
8635 CGF.EmitIgnoredExpr(S.
getInit());
8647 OMPLexicalScope
Scope(CGF, S, OMPD_taskloop,
false);
8657 [&S](CodeGenFunction &CGF) {
8658 emitOMPLoopBodyWithStopPoint(CGF, S,
8659 CodeGenFunction::JumpDest());
8661 [](CodeGenFunction &) {});
8666 CGF.EmitBranch(ContBlock);
8667 CGF.EmitBlock(ContBlock,
true);
8670 if (HasLastprivateClause) {
8671 CGF.EmitOMPLastprivateClauseFinal(
8673 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
8674 CGF.GetAddrOfLocalVar(*LIP),
false,
8675 (*LIP)->getType(), S.getBeginLoc())));
8678 CGF.EmitOMPLinearClauseFinal(S, [LIP, &S](CodeGenFunction &CGF) {
8679 return CGF.
Builder.CreateIsNotNull(
8681 (*LIP)->
getType(), S.getBeginLoc()));
8684 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
8685 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
8687 auto &&
CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
8689 OMPLoopScope PreInitScope(CGF, S);
8690 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S,
8691 OutlinedFn, SharedsTy,
8692 CapturedStruct, IfCond,
Data);
8694 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
8700 CGM.getOpenMPRuntime().emitTaskgroupRegion(
8702 [&S, &BodyGen, &TaskGen, &
Data](CodeGenFunction &CGF,
8722 OMPLexicalScope
Scope(*
this, S);
8734 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8735 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8746 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8747 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8758 OMPLexicalScope
Scope(*
this, S);
8759 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8770 OMPLexicalScope
Scope(*
this, S);
8771 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8777 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8782 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8783 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8795 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8800 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8801 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8813 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8818 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8819 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8831 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8836 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8837 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8851 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8855 const Expr *IfCond =
nullptr;
8857 IfCond =
C->getCondition();
8864 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8865 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8875 BindKind =
C->getBindKind();
8878 case OMPC_BIND_parallel:
8880 case OMPC_BIND_teams:
8882 case OMPC_BIND_thread:
8893 const auto *ForS = dyn_cast<ForStmt>(CS);
8904 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
8905 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_loop,
CodeGen);
8931 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
8936 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
8948 [](CodeGenFunction &) {
return nullptr; });
8953 std::string StatusMsg,
8957 StatusMsg +=
": DEVICE";
8959 StatusMsg +=
": HOST";
8966 llvm::dbgs() << StatusMsg <<
": " <<
FileName <<
": " << LineNo <<
"\n";
8989 CGF, OMPD_distribute, CodeGenDistribute,
false);
9018 CGF, OMPD_distribute, CodeGenDistribute,
false);
9051 llvm::Constant *
Addr;
9053 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
9055 assert(Fn &&
Addr &&
9056 "Target device function emission failed for 'target teams loop'.");
9067 CGF, OMPD_target_parallel_loop,
false);
9083 llvm::Constant *
Addr;
9085 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
9087 assert(Fn &&
Addr &&
"Target device function emission failed.");
9102 if (
const auto *SD = dyn_cast<OMPScanDirective>(&D)) {
9106 if (!D.hasAssociatedStmt() || !D.getAssociatedStmt())
9112 for (
const auto *
C : D.getClausesOfKind<OMPFirstprivateClause>()) {
9113 for (
const Expr *Ref :
C->varlist()) {
9117 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
9120 if (!CGF.LocalDeclMap.count(VD)) {
9132 if (
const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
9133 for (
const Expr *E : LD->counters()) {
9141 if (!CGF.LocalDeclMap.count(VD))
9145 for (
const auto *
C : D.getClausesOfKind<OMPOrderedClause>()) {
9146 if (!
C->getNumForLoops())
9148 for (
unsigned I = LD->getLoopsNumber(),
9149 E =
C->getLoopNumIterations().size();
9151 if (
const auto *VD = dyn_cast<OMPCapturedExprDecl>(
9154 if (!CGF.LocalDeclMap.count(VD))
9161 CGF.
EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
9164 if (D.getDirectiveKind() == OMPD_atomic ||
9165 D.getDirectiveKind() == OMPD_critical ||
9166 D.getDirectiveKind() == OMPD_section ||
9167 D.getDirectiveKind() == OMPD_master ||
9168 D.getDirectiveKind() == OMPD_masked ||
9169 D.getDirectiveKind() == OMPD_unroll ||
9170 D.getDirectiveKind() == OMPD_assume) {
9175 OMPSimdLexicalScope
Scope(*
this, D);
9176 CGM.getOpenMPRuntime().emitInlinedDirective(
9179 : D.getDirectiveKind(),
9187 for (
const auto *
C : S.getClausesOfKind<OMPHoldsClause>()) {
9188 const Expr *E =
C->getExpr();
9189 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