31#include "llvm/ADT/SmallSet.h"
32#include "llvm/BinaryFormat/Dwarf.h"
33#include "llvm/Frontend/OpenMP/OMPConstants.h"
34#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
35#include "llvm/IR/Constants.h"
36#include "llvm/IR/DebugInfoMetadata.h"
37#include "llvm/IR/Instructions.h"
38#include "llvm/IR/IntrinsicInst.h"
39#include "llvm/IR/Metadata.h"
40#include "llvm/Support/AtomicOrdering.h"
41#include "llvm/Support/Debug.h"
45using namespace llvm::omp;
47#define TTL_CODEGEN_TYPE "target-teams-loop-codegen"
58 for (
const auto *
C : S.clauses()) {
60 if (
const auto *PreInit =
61 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
62 for (
const auto *I : PreInit->decls()) {
63 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
66 CodeGenFunction::AutoVarEmission Emission =
75 CodeGenFunction::OMPPrivateScope InlinedShareds;
77 static bool isCapturedVar(CodeGenFunction &CGF,
const VarDecl *VD) {
86 CodeGenFunction &CGF,
const OMPExecutableDirective &S,
87 const std::optional<OpenMPDirectiveKind> CapturedRegion = std::nullopt,
88 const bool EmitPreInitStmt =
true)
92 emitPreInitStmt(CGF, S);
95 assert(S.hasAssociatedStmt() &&
96 "Expected associated statement for inlined directive.");
97 const CapturedStmt *CS = S.getCapturedStmt(*CapturedRegion);
99 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
100 auto *VD =
C.getCapturedVar();
102 "Canonical decl must be captured.");
106 InlinedShareds.isGlobalVarCaptured(VD)),
111 (void)InlinedShareds.Privatize();
117class OMPParallelScope final :
public OMPLexicalScope {
118 bool EmitPreInitStmt(
const OMPExecutableDirective &S) {
126 OMPParallelScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
127 : OMPLexicalScope(CGF, S, std::nullopt,
128 EmitPreInitStmt(S)) {}
133class OMPTeamsScope final :
public OMPLexicalScope {
134 bool EmitPreInitStmt(
const OMPExecutableDirective &S) {
141 OMPTeamsScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
142 : OMPLexicalScope(CGF, S, std::nullopt,
143 EmitPreInitStmt(S)) {}
149 void emitPreInitStmt(CodeGenFunction &CGF,
const OMPLoopBasedDirective &S) {
150 const Stmt *PreInits;
151 CodeGenFunction::OMPMapVars PreCondVars;
152 if (
auto *LD = dyn_cast<OMPLoopDirective>(&S)) {
153 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
154 for (
const auto *E : LD->counters()) {
161 for (
const auto *
C : LD->getClausesOfKind<OMPPrivateClause>()) {
162 for (
const Expr *IRef :
C->varlist()) {
165 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
166 QualType OrigVDTy = OrigVD->getType().getNonReferenceType();
176 (void)PreCondVars.
apply(CGF);
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->getEndStmt());
190 PreInits = LD->getPreInits();
191 }
else if (
const auto *
Tile = dyn_cast<OMPTileDirective>(&S)) {
192 PreInits =
Tile->getPreInits();
193 }
else if (
const auto *Stripe = dyn_cast<OMPStripeDirective>(&S)) {
194 PreInits = Stripe->getPreInits();
195 }
else if (
const auto *Unroll = dyn_cast<OMPUnrollDirective>(&S)) {
196 PreInits = Unroll->getPreInits();
197 }
else if (
const auto *Reverse = dyn_cast<OMPReverseDirective>(&S)) {
198 PreInits = Reverse->getPreInits();
199 }
else if (
const auto *Interchange =
200 dyn_cast<OMPInterchangeDirective>(&S)) {
201 PreInits = Interchange->getPreInits();
203 llvm_unreachable(
"Unknown loop-based directive kind.");
205 doEmitPreinits(PreInits);
212 const Stmt *PreInits;
213 if (
const auto *Fuse = dyn_cast<OMPFuseDirective>(&S)) {
214 PreInits = Fuse->getPreInits();
217 "Unknown canonical loop sequence transform directive kind.");
219 doEmitPreinits(PreInits);
222 void doEmitPreinits(
const Stmt *PreInits) {
228 if (
auto *PreInitCompound = dyn_cast<CompoundStmt>(PreInits))
229 llvm::append_range(PreInitStmts, PreInitCompound->body());
231 PreInitStmts.push_back(PreInits);
233 for (
const Stmt *S : PreInitStmts) {
236 if (
auto *PreInitDecl = dyn_cast<DeclStmt>(S)) {
237 for (
Decl *I : PreInitDecl->decls())
249 emitPreInitStmt(CGF, S);
254 emitPreInitStmt(CGF, S);
259 CodeGenFunction::OMPPrivateScope InlinedShareds;
261 static bool isCapturedVar(CodeGenFunction &CGF,
const VarDecl *VD) {
269 OMPSimdLexicalScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
271 InlinedShareds(CGF) {
272 for (
const auto *
C : S.clauses()) {
273 if (const auto *CPI = OMPClauseWithPreInit::get(C)) {
274 if (const auto *PreInit =
275 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
276 for (const auto *I : PreInit->decls()) {
277 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
278 CGF.EmitVarDecl(cast<VarDecl>(*I));
280 CodeGenFunction::AutoVarEmission Emission =
281 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
282 CGF.EmitAutoVarCleanups(Emission);
286 }
else if (
const auto *UDP = dyn_cast<OMPUseDevicePtrClause>(
C)) {
287 for (
const Expr *E : UDP->varlist()) {
289 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
292 }
else if (
const auto *UDP = dyn_cast<OMPUseDeviceAddrClause>(
C)) {
293 for (
const Expr *E : UDP->varlist()) {
295 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
302 if (
const auto *TG = dyn_cast<OMPTaskgroupDirective>(&S)) {
303 if (
const Expr *E = TG->getReductionRef())
308 llvm::DenseSet<CanonicalDeclPtr<const Decl>> CopyArrayTemps;
309 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
310 if (C->getModifier() != OMPC_REDUCTION_inscan)
312 for (const Expr *E : C->copy_array_temps())
313 CopyArrayTemps.insert(cast<DeclRefExpr>(E)->getDecl());
315 const auto *CS = cast_or_null<CapturedStmt>(S.getAssociatedStmt());
318 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
319 auto *VD =
C.getCapturedVar();
320 if (CopyArrayTemps.contains(VD))
323 "Canonical decl must be captured.");
324 DeclRefExpr DRE(CGF.
getContext(),
const_cast<VarDecl *
>(VD),
325 isCapturedVar(CGF, VD) ||
327 InlinedShareds.isGlobalVarCaptured(VD)),
335 (void)InlinedShareds.Privatize();
346 if (Kind != OMPD_loop)
351 BindKind =
C->getBindKind();
354 case OMPC_BIND_parallel:
356 case OMPC_BIND_teams:
357 return OMPD_distribute;
358 case OMPC_BIND_thread:
370 if (
const auto *OrigDRE = dyn_cast<DeclRefExpr>(E)) {
371 if (
const auto *OrigVD = dyn_cast<VarDecl>(OrigDRE->getDecl())) {
372 OrigVD = OrigVD->getCanonicalDecl();
378 OrigDRE->getType(),
VK_LValue, OrigDRE->getExprLoc());
387 llvm::Value *Size =
nullptr;
388 auto SizeInChars =
C.getTypeSizeInChars(Ty);
389 if (SizeInChars.isZero()) {
397 SizeInChars =
C.getTypeSizeInChars(Ty);
398 if (SizeInChars.isZero())
399 return llvm::ConstantInt::get(
SizeTy, 0);
400 return Builder.CreateNUWMul(Size,
CGM.getSize(SizeInChars));
402 return CGM.getSize(SizeInChars);
412 I != E; ++I, ++CurField, ++CurCap) {
413 if (CurField->hasCapturedVLAType()) {
416 CapturedVars.push_back(Val);
417 }
else if (CurCap->capturesThis()) {
418 CapturedVars.push_back(CXXThisValue);
419 }
else if (CurCap->capturesVariableByCopy()) {
424 if (!CurField->getType()->isAnyPointerType()) {
428 Twine(CurCap->getCapturedVar()->getName(),
".casted"));
444 CapturedVars.push_back(CV);
446 assert(CurCap->capturesVariable() &&
"Expected capture by reference.");
467 if (
T->isLValueReferenceType())
468 return C.getLValueReferenceType(
471 if (
T->isPointerType())
473 if (
const ArrayType *A =
T->getAsArrayTypeUnsafe()) {
474 if (
const auto *VLA = dyn_cast<VariableArrayType>(A))
476 if (!A->isVariablyModifiedType())
477 return C.getCanonicalType(
T);
479 return C.getCanonicalParamType(
T);
484struct FunctionOptions {
486 const CapturedStmt *S =
nullptr;
489 const bool UIntPtrCastRequired =
true;
492 const bool RegisterCastedArgsOnly =
false;
494 const StringRef FunctionName;
497 const bool IsDeviceKernel =
false;
498 explicit FunctionOptions(
const CapturedStmt *S,
bool UIntPtrCastRequired,
499 bool RegisterCastedArgsOnly, StringRef FunctionName,
500 SourceLocation Loc,
bool IsDeviceKernel)
501 : S(S), UIntPtrCastRequired(UIntPtrCastRequired),
502 RegisterCastedArgsOnly(UIntPtrCastRequired && RegisterCastedArgsOnly),
503 FunctionName(FunctionName), Loc(Loc), IsDeviceKernel(IsDeviceKernel) {}
509 llvm::MapVector<
const Decl *, std::pair<const VarDecl *, Address>>
511 llvm::DenseMap<
const Decl *, std::pair<const Expr *, llvm::Value *>>
513 llvm::Value *&CXXThisValue,
const FunctionOptions &FO) {
516 assert(CD->
hasBody() &&
"missing CapturedDecl body");
518 CXXThisValue =
nullptr;
530 if (!FO.UIntPtrCastRequired) {
550 if (FO.UIntPtrCastRequired &&
551 ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) ||
552 I->capturesVariableArrayType()))
555 if (I->capturesVariable() || I->capturesVariableByCopy()) {
556 CapVar = I->getCapturedVar();
558 }
else if (I->capturesThis()) {
561 assert(I->capturesVariableArrayType());
564 if (ArgType->isVariablyModifiedType())
571 }
else if (DebugFunctionDecl && (CapVar || I->capturesThis())) {
573 Ctx, DebugFunctionDecl,
574 CapVar ? CapVar->
getBeginLoc() : FD->getBeginLoc(),
575 CapVar ? CapVar->
getLocation() : FD->getLocation(), II, ArgType,
581 Args.emplace_back(Arg);
583 TargetArgs.emplace_back(
584 FO.UIntPtrCastRequired
605 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
609 F->setDoesNotThrow();
610 F->setDoesNotRecurse();
614 F->removeFnAttr(llvm::Attribute::NoInline);
615 F->addFnAttr(llvm::Attribute::AlwaysInline);
620 FO.UIntPtrCastRequired ? FO.Loc : FO.S->
getBeginLoc(),
621 FO.UIntPtrCastRequired ? FO.Loc
628 if (!FO.UIntPtrCastRequired && Args[Cnt] != TargetArgs[Cnt]) {
636 if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
637 const VarDecl *CurVD = I->getCapturedVar();
638 if (!FO.RegisterCastedArgsOnly)
639 LocalAddrs.insert({Args[Cnt], {CurVD, LocalAddr}});
647 if (FD->hasCapturedVLAType()) {
648 if (FO.UIntPtrCastRequired) {
651 Args[Cnt]->getName(), ArgLVal),
656 VLASizes.try_emplace(Args[Cnt], VAT->
getSizeExpr(), ExprArg);
657 }
else if (I->capturesVariable()) {
658 const VarDecl *Var = I->getCapturedVar();
660 Address ArgAddr = ArgLVal.getAddress();
661 if (ArgLVal.getType()->isLValueReferenceType()) {
664 assert(ArgLVal.getType()->isPointerType());
666 ArgAddr, ArgLVal.getType()->castAs<
PointerType>());
668 if (!FO.RegisterCastedArgsOnly) {
672 }
else if (I->capturesVariableByCopy()) {
673 assert(!FD->getType()->isAnyPointerType() &&
674 "Not expecting a captured pointer.");
675 const VarDecl *Var = I->getCapturedVar();
676 LocalAddrs.insert({Args[Cnt],
677 {Var, FO.UIntPtrCastRequired
679 CGF, I->getLocation(), FD->getType(),
680 Args[Cnt]->getName(), ArgLVal)
681 : ArgLVal.getAddress()}});
684 assert(I->capturesThis());
686 LocalAddrs.insert({Args[Cnt], {
nullptr, ArgLVal.getAddress()}});
700 "CapturedStmtInfo should be set when generating the captured function");
703 bool NeedWrapperFunction =
706 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs,
708 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes,
711 llvm::raw_svector_ostream Out(Buffer);
714 bool IsDeviceKernel =
CGM.getOpenMPRuntime().isGPU() &&
716 D.getCapturedStmt(OMPD_target) == &S;
717 CodeGenFunction WrapperCGF(
CGM,
true);
718 llvm::Function *WrapperF =
nullptr;
719 if (NeedWrapperFunction) {
722 FunctionOptions WrapperFO(&S,
true,
729 WrapperCGF.CXXThisValue, WrapperFO);
732 FunctionOptions FO(&S, !NeedWrapperFunction,
false,
733 Out.str(), Loc, !NeedWrapperFunction && IsDeviceKernel);
735 *
this, WrapperArgs, WrapperLocalAddrs, WrapperVLASizes, CXXThisValue, FO);
737 for (
const auto &LocalAddrPair : WrapperLocalAddrs) {
738 if (LocalAddrPair.second.first) {
739 LocalScope.addPrivate(LocalAddrPair.second.first,
740 LocalAddrPair.second.second);
743 (void)LocalScope.Privatize();
744 for (
const auto &VLASizePair : WrapperVLASizes)
745 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
748 LocalScope.ForceCleanup();
750 if (!NeedWrapperFunction)
754 WrapperF->removeFromParent();
755 F->getParent()->getFunctionList().insertAfter(F->getIterator(), WrapperF);
758 auto *PI = F->arg_begin();
759 for (
const auto *Arg : Args) {
761 auto I = LocalAddrs.find(Arg);
762 if (I != LocalAddrs.end()) {
765 I->second.first ? I->second.first->getType() : Arg->getType(),
771 auto EI = VLASizes.find(Arg);
772 if (EI != VLASizes.end()) {
784 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
800 llvm::Value *NumElements =
emitArrayLength(ArrayTy, ElementTy, DestAddr);
807 DestBegin, NumElements);
812 llvm::Value *IsEmpty =
813 Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arraycpy.isempty");
814 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
817 llvm::BasicBlock *EntryBB =
Builder.GetInsertBlock();
822 llvm::PHINode *SrcElementPHI =
823 Builder.CreatePHI(SrcBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
824 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
829 llvm::PHINode *DestElementPHI =
Builder.CreatePHI(
830 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
831 DestElementPHI->addIncoming(DestBegin, EntryBB);
837 CopyGen(DestElementCurrent, SrcElementCurrent);
840 llvm::Value *DestElementNext =
842 1,
"omp.arraycpy.dest.element");
843 llvm::Value *SrcElementNext =
845 1,
"omp.arraycpy.src.element");
848 Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
849 Builder.CreateCondBr(Done, DoneBB, BodyBB);
850 DestElementPHI->addIncoming(DestElementNext,
Builder.GetInsertBlock());
851 SrcElementPHI->addIncoming(SrcElementNext,
Builder.GetInsertBlock());
861 const auto *BO = dyn_cast<BinaryOperator>(
Copy);
862 if (BO && BO->getOpcode() == BO_Assign) {
871 DestAddr, SrcAddr, OriginalType,
899 bool DeviceConstTarget =
getLangOpts().OpenMPIsTargetDevice &&
901 bool FirstprivateIsLastprivate =
false;
902 llvm::DenseMap<const VarDecl *, OpenMPLastprivateModifier> Lastprivates;
904 for (
const auto *D :
C->varlist())
905 Lastprivates.try_emplace(
909 llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
914 bool MustEmitFirstprivateCopy =
915 CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown;
917 const auto *IRef =
C->varlist_begin();
918 const auto *InitsRef =
C->inits().begin();
919 for (
const Expr *IInit :
C->private_copies()) {
921 bool ThisFirstprivateIsLastprivate =
922 Lastprivates.count(OrigVD->getCanonicalDecl()) > 0;
925 if (!MustEmitFirstprivateCopy && !ThisFirstprivateIsLastprivate && FD &&
927 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
928 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
935 if (DeviceConstTarget && OrigVD->getType().isConstant(
getContext()) &&
937 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
938 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
943 FirstprivateIsLastprivate =
944 FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate;
945 if (EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()).second) {
965 assert(!CE &&
"Expected non-constant firstprivate.");
972 if (
Type->isArrayType()) {
988 RunCleanupsScope InitScope(*this);
990 setAddrOfLocalVar(VDInit, SrcElement);
991 EmitAnyExprToMem(Init, DestElement,
992 Init->getType().getQualifiers(),
994 LocalDeclMap.erase(VDInit);
1005 setAddrOfLocalVar(VDInit, OriginalAddr);
1007 LocalDeclMap.erase(VDInit);
1009 if (ThisFirstprivateIsLastprivate &&
1010 Lastprivates[OrigVD->getCanonicalDecl()] ==
1011 OMPC_LASTPRIVATE_conditional) {
1016 (*IRef)->getExprLoc());
1017 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1021 LocalDeclMap.erase(VD);
1022 setAddrOfLocalVar(VD, VDAddr);
1024 IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1026 assert(IsRegistered &&
1027 "firstprivate var already registered as private");
1035 return FirstprivateIsLastprivate && !EmittedAsFirstprivate.empty();
1043 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
1045 auto IRef =
C->varlist_begin();
1046 for (
const Expr *IInit :
C->private_copies()) {
1048 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
1054 assert(IsRegistered &&
"private var already registered as private");
1070 llvm::DenseSet<const VarDecl *> CopiedVars;
1071 llvm::BasicBlock *CopyBegin =
nullptr, *CopyEnd =
nullptr;
1073 auto IRef =
C->varlist_begin();
1074 auto ISrcRef =
C->source_exprs().begin();
1075 auto IDestRef =
C->destination_exprs().begin();
1076 for (
const Expr *AssignOp :
C->assignment_ops()) {
1085 getContext().getTargetInfo().isTLSSupported()) {
1087 "Copyin threadprivates should have been captured!");
1091 LocalDeclMap.erase(VD);
1095 :
CGM.GetAddrOfGlobal(VD),
1096 CGM.getTypes().ConvertTypeForMem(VD->
getType()),
1101 if (CopiedVars.size() == 1) {
1107 auto *MasterAddrInt =
Builder.CreatePtrToInt(
1109 auto *PrivateAddrInt =
Builder.CreatePtrToInt(
1112 Builder.CreateICmpNE(MasterAddrInt, PrivateAddrInt), CopyBegin,
1118 const auto *DestVD =
1139 bool HasAtLeastOneLastprivate =
false;
1141 llvm::DenseSet<const VarDecl *> SIMDLCVs;
1144 for (
const Expr *
C : LoopDirective->counters()) {
1149 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1151 HasAtLeastOneLastprivate =
true;
1154 const auto *IRef =
C->varlist_begin();
1155 const auto *IDestRef =
C->destination_exprs().begin();
1156 for (
const Expr *IInit :
C->private_copies()) {
1162 if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) {
1163 const auto *DestVD =
1168 (*IRef)->getType(),
VK_LValue, (*IRef)->getExprLoc());
1173 if (IInit && !SIMDLCVs.count(OrigVD->getCanonicalDecl())) {
1176 if (
C->getKind() == OMPC_LASTPRIVATE_conditional) {
1177 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1179 setAddrOfLocalVar(VD, VDAddr);
1185 bool IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1186 assert(IsRegistered &&
1187 "lastprivate var already registered as private");
1195 return HasAtLeastOneLastprivate;
1200 llvm::Value *IsLastIterCond) {
1209 llvm::BasicBlock *ThenBB =
nullptr;
1210 llvm::BasicBlock *DoneBB =
nullptr;
1211 if (IsLastIterCond) {
1217 return C->getKind() == OMPC_LASTPRIVATE_conditional;
1219 CGM.getOpenMPRuntime().emitBarrierCall(*
this, D.getBeginLoc(),
1226 Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB);
1229 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1230 llvm::DenseMap<const VarDecl *, const Expr *> LoopCountersAndUpdates;
1231 if (
const auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) {
1232 auto IC = LoopDirective->counters().begin();
1233 for (
const Expr *F : LoopDirective->finals()) {
1237 AlreadyEmittedVars.insert(D);
1239 LoopCountersAndUpdates[D] = F;
1244 auto IRef =
C->varlist_begin();
1245 auto ISrcRef =
C->source_exprs().begin();
1246 auto IDestRef =
C->destination_exprs().begin();
1247 for (
const Expr *AssignOp :
C->assignment_ops()) {
1248 const auto *PrivateVD =
1251 const auto *CanonicalVD = PrivateVD->getCanonicalDecl();
1252 if (AlreadyEmittedVars.insert(CanonicalVD).second) {
1256 if (
const Expr *FinalExpr = LoopCountersAndUpdates.lookup(CanonicalVD))
1260 const auto *DestVD =
1264 if (
const auto *RefTy = PrivateVD->getType()->getAs<
ReferenceType>())
1266 Builder.CreateLoad(PrivateAddr),
1267 CGM.getTypes().ConvertTypeForMem(RefTy->getPointeeType()),
1268 CGM.getNaturalTypeAlignment(RefTy->getPointeeType()));
1270 if (
C->getKind() == OMPC_LASTPRIVATE_conditional)
1271 CGM.getOpenMPRuntime().emitLastprivateConditionalFinalUpdate(
1273 (*IRef)->getExprLoc());
1276 EmitOMPCopy(
Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp);
1282 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
1303 if (ForInscan != (
C->getModifier() == OMPC_REDUCTION_inscan))
1305 Shareds.append(
C->varlist_begin(),
C->varlist_end());
1306 Privates.append(
C->privates().begin(),
C->privates().end());
1307 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1308 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1309 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1310 if (
C->getModifier() == OMPC_REDUCTION_task) {
1311 Data.ReductionVars.append(
C->privates().begin(),
C->privates().end());
1312 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
1313 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
1314 Data.ReductionOps.append(
C->reduction_ops().begin(),
1315 C->reduction_ops().end());
1316 TaskLHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1317 TaskRHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1322 auto *ILHS = LHSs.begin();
1323 auto *IRHS = RHSs.begin();
1324 auto *IPriv = Privates.begin();
1325 for (
const Expr *IRef : Shareds) {
1333 [&Emission](CodeGenFunction &CGF) {
1334 CGF.EmitAutoVarInit(Emission);
1342 assert(IsRegistered &&
"private var already registered as private");
1350 if (isaOMPArraySectionExpr &&
Type->isVariablyModifiedType()) {
1355 }
else if ((isaOMPArraySectionExpr &&
Type->isScalarType()) ||
1373 PrivateScope.
addPrivate(LHSVD, OriginalAddr);
1384 if (!
Data.ReductionVars.empty()) {
1386 Data.IsReductionWithTaskMod =
true;
1388 llvm::Value *ReductionDesc =
CGM.getOpenMPRuntime().emitTaskReductionInit(
1389 *
this, D.getBeginLoc(), TaskLHSs, TaskRHSs,
Data);
1390 const Expr *TaskRedRef =
nullptr;
1401 case OMPD_parallel_for:
1404 case OMPD_parallel_master:
1408 case OMPD_parallel_sections:
1412 case OMPD_target_parallel:
1416 case OMPD_target_parallel_for:
1420 case OMPD_distribute_parallel_for:
1424 case OMPD_teams_distribute_parallel_for:
1426 .getTaskReductionRefExpr();
1428 case OMPD_target_teams_distribute_parallel_for:
1430 .getTaskReductionRefExpr();
1438 case OMPD_parallel_for_simd:
1440 case OMPD_taskyield:
1444 case OMPD_taskgroup:
1452 case OMPD_cancellation_point:
1454 case OMPD_target_data:
1455 case OMPD_target_enter_data:
1456 case OMPD_target_exit_data:
1458 case OMPD_taskloop_simd:
1459 case OMPD_master_taskloop:
1460 case OMPD_master_taskloop_simd:
1461 case OMPD_parallel_master_taskloop:
1462 case OMPD_parallel_master_taskloop_simd:
1463 case OMPD_distribute:
1464 case OMPD_target_update:
1465 case OMPD_distribute_parallel_for_simd:
1466 case OMPD_distribute_simd:
1467 case OMPD_target_parallel_for_simd:
1468 case OMPD_target_simd:
1469 case OMPD_teams_distribute:
1470 case OMPD_teams_distribute_simd:
1471 case OMPD_teams_distribute_parallel_for_simd:
1472 case OMPD_target_teams:
1473 case OMPD_target_teams_distribute:
1474 case OMPD_target_teams_distribute_parallel_for_simd:
1475 case OMPD_target_teams_distribute_simd:
1476 case OMPD_declare_target:
1477 case OMPD_end_declare_target:
1478 case OMPD_threadprivate:
1480 case OMPD_declare_reduction:
1481 case OMPD_declare_mapper:
1482 case OMPD_declare_simd:
1484 case OMPD_declare_variant:
1485 case OMPD_begin_declare_variant:
1486 case OMPD_end_declare_variant:
1489 llvm_unreachable(
"Unexpected directive with task reductions.");
1495 false, TaskRedRef->
getType());
1508 bool HasAtLeastOneReduction =
false;
1509 bool IsReductionWithTaskMod =
false;
1512 if (
C->getModifier() == OMPC_REDUCTION_inscan)
1514 HasAtLeastOneReduction =
true;
1515 Privates.append(
C->privates().begin(),
C->privates().end());
1516 LHSExprs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1517 RHSExprs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1518 IsPrivateVarReduction.append(
C->private_var_reduction_flags().begin(),
1519 C->private_var_reduction_flags().end());
1520 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1521 IsReductionWithTaskMod =
1522 IsReductionWithTaskMod ||
C->getModifier() == OMPC_REDUCTION_task;
1524 if (HasAtLeastOneReduction) {
1526 if (IsReductionWithTaskMod) {
1527 CGM.getOpenMPRuntime().emitTaskReductionFini(
1530 bool TeamsLoopCanBeParallel =
false;
1531 if (
auto *TTLD = dyn_cast<OMPTargetTeamsGenericLoopDirective>(&D))
1532 TeamsLoopCanBeParallel = TTLD->canBeParallelFor();
1535 TeamsLoopCanBeParallel || ReductionKind == OMPD_simd;
1536 bool SimpleReduction = ReductionKind == OMPD_simd;
1539 CGM.getOpenMPRuntime().emitReduction(
1540 *
this, D.getEndLoc(), Privates, LHSExprs, RHSExprs, ReductionOps,
1541 {WithNowait, SimpleReduction, IsPrivateVarReduction, ReductionKind});
1550 llvm::BasicBlock *DoneBB =
nullptr;
1552 if (
const Expr *PostUpdate =
C->getPostUpdateExpr()) {
1554 if (llvm::Value *
Cond = CondGen(CGF)) {
1575 const OMPExecutableDirective &,
1576 llvm::SmallVectorImpl<llvm::Value *> &)>
1577 CodeGenBoundParametersTy;
1585 llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> PrivateDecls;
1587 for (
const Expr *Ref :
C->varlist()) {
1588 if (!Ref->getType()->isScalarType())
1590 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1598 for (
const Expr *Ref :
C->varlist()) {
1599 if (!Ref->getType()->isScalarType())
1601 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1609 for (
const Expr *Ref :
C->varlist()) {
1610 if (!Ref->getType()->isScalarType())
1612 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1624 for (
const Expr *Ref :
C->varlist()) {
1625 if (!Ref->getType()->isScalarType())
1627 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1634 CGF, S, PrivateDecls);
1640 const CodeGenBoundParametersTy &CodeGenBoundParameters) {
1641 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
1642 llvm::Value *NumThreads =
nullptr;
1651 llvm::Function *OutlinedFn =
1658 NumThreads = CGF.
EmitScalarExpr(NumThreadsClause->getNumThreads(),
1660 Modifier = NumThreadsClause->getModifier();
1662 Message = MessageClause->getMessageString();
1663 MessageLoc = MessageClause->getBeginLoc();
1666 Severity = SeverityClause->getSeverityKind();
1667 SeverityLoc = SeverityClause->getBeginLoc();
1670 CGF, NumThreads, NumThreadsClause->getBeginLoc(), Modifier, Severity,
1671 SeverityLoc, Message, MessageLoc);
1676 CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getBeginLoc());
1678 const Expr *IfCond =
nullptr;
1679 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
1680 if (
C->getNameModifier() == OMPD_unknown ||
1681 C->getNameModifier() == OMPD_parallel) {
1682 IfCond =
C->getCondition();
1687 OMPParallelScope
Scope(CGF, S);
1693 CodeGenBoundParameters(CGF, S, CapturedVars);
1696 CapturedVars, IfCond, NumThreads,
1697 Modifier, Severity, Message);
1702 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
1704 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
1706 return !((AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc ||
1707 AA->getAllocatorType() == OMPAllocateDeclAttr::OMPNullMemAlloc) &&
1708 !AA->getAllocator());
1723 CGF, S.getBeginLoc(), OMPD_unknown,
false,
1729 CodeGenFunction &CGF,
const VarDecl *VD) {
1731 auto &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1743 Size = CGF.
Builder.CreateNUWAdd(
1745 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
1746 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
1752 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
1753 assert(AA->getAllocator() &&
1754 "Expected allocator expression for non-default allocator.");
1758 if (Allocator->getType()->isIntegerTy())
1759 Allocator = CGF.
Builder.CreateIntToPtr(Allocator,
CGM.VoidPtrTy);
1760 else if (Allocator->getType()->isPointerTy())
1764 llvm::Value *
Addr = OMPBuilder.createOMPAlloc(
1767 llvm::CallInst *FreeCI =
1768 OMPBuilder.createOMPFree(CGF.
Builder,
Addr, Allocator);
1782 if (
CGM.getLangOpts().OpenMPUseTLS &&
1783 CGM.getContext().getTargetInfo().isTLSSupported())
1786 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1791 llvm::ConstantInt *Size =
CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy));
1793 llvm::Twine CacheName = Twine(
CGM.getMangledName(VD)).concat(Suffix);
1795 llvm::CallInst *ThreadPrivateCacheCall =
1796 OMPBuilder.createCachedThreadPrivate(CGF.
Builder,
Data, Size, CacheName);
1804 llvm::raw_svector_ostream OS(Buffer);
1805 StringRef Sep = FirstSeparator;
1806 for (StringRef Part : Parts) {
1810 return OS.str().str();
1818 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
1819 "." + RegionName +
".after");
1835 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
1836 "." + RegionName +
".after");
1848 if (
CGM.getLangOpts().OpenMPIRBuilder) {
1849 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1851 llvm::Value *IfCond =
nullptr;
1856 llvm::Value *NumThreads =
nullptr;
1861 ProcBindKind ProcBind = OMP_PROC_BIND_default;
1863 ProcBind = ProcBindClause->getProcBindKind();
1865 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1869 auto FiniCB = [
this](InsertPointTy IP) {
1871 return llvm::Error::success();
1878 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
1879 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
1890 auto BodyGenCB = [&,
this](InsertPointTy AllocaIP,
1891 InsertPointTy CodeGenIP) {
1893 *
this, ParallelRegionBodyStmt, AllocaIP, CodeGenIP,
"parallel");
1894 return llvm::Error::success();
1899 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
1901 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
1902 OMPBuilder.createParallel(
Builder, AllocaIP, BodyGenCB, PrivCB, FiniCB,
1903 IfCond, NumThreads, ProcBind, S.hasCancel()));
1917 CGF.
EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt());
1926 [](CodeGenFunction &) {
return nullptr; });
1938class OMPTransformDirectiveScopeRAII {
1939 OMPLoopScope *
Scope =
nullptr;
1943 OMPTransformDirectiveScopeRAII(
const OMPTransformDirectiveScopeRAII &) =
1945 OMPTransformDirectiveScopeRAII &
1946 operator=(
const OMPTransformDirectiveScopeRAII &) =
delete;
1950 if (
const auto *Dir = dyn_cast<OMPLoopBasedDirective>(S)) {
1951 Scope =
new OMPLoopScope(CGF, *Dir);
1954 }
else if (
const auto *Dir =
1955 dyn_cast<OMPCanonicalLoopSequenceTransformationDirective>(
1960 Scope =
new OMPLoopScope(CGF, *Dir);
1965 ~OMPTransformDirectiveScopeRAII() {
1976 int MaxLevel,
int Level = 0) {
1977 assert(Level < MaxLevel &&
"Too deep lookup during loop body codegen.");
1979 if (
const auto *CS = dyn_cast<CompoundStmt>(SimplifiedS)) {
1982 "LLVM IR generation of compound statement ('{}')");
1986 for (
const Stmt *CurStmt : CS->body())
1987 emitBody(CGF, CurStmt, NextLoop, MaxLevel, Level);
1990 if (SimplifiedS == NextLoop) {
1991 if (
auto *Dir = dyn_cast<OMPLoopTransformationDirective>(SimplifiedS))
1992 SimplifiedS = Dir->getTransformedStmt();
1993 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(SimplifiedS))
1994 SimplifiedS = CanonLoop->getLoopStmt();
1995 if (
const auto *For = dyn_cast<ForStmt>(SimplifiedS)) {
1999 "Expected canonical for loop or range-based for loop.");
2001 CGF.
EmitStmt(CXXFor->getLoopVarStmt());
2002 S = CXXFor->getBody();
2004 if (Level + 1 < MaxLevel) {
2005 NextLoop = OMPLoopDirective::tryToFindNextInnerLoop(
2007 emitBody(CGF, S, NextLoop, MaxLevel, Level + 1);
2018 for (
const Expr *UE : D.updates())
2026 for (
const Expr *UE :
C->updates())
2033 BreakContinueStack.push_back(BreakContinue(D,
LoopExit, Continue));
2034 for (
const Expr *E : D.finals_conditions()) {
2047 bool IsInscanRegion = InscanScope.
Privatize();
2048 if (IsInscanRegion) {
2058 if (EKind != OMPD_simd && !
getLangOpts().OpenMPSimd)
2067 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
2070 OMPLoopBasedDirective::tryToFindNextInnerLoop(
2072 D.getLoopsNumber());
2080 BreakContinueStack.pop_back();
2091 std::unique_ptr<CodeGenFunction::CGCapturedStmtInfo> CSI =
2092 std::make_unique<CodeGenFunction::CGCapturedStmtInfo>(*S);
2096 return {F, CapStruct.getPointer(
ParentCGF)};
2100static llvm::CallInst *
2105 EffectiveArgs.reserve(Args.size() + 1);
2106 llvm::append_range(EffectiveArgs, Args);
2107 EffectiveArgs.push_back(Cap.second);
2112llvm::CanonicalLoopInfo *
2114 assert(Depth == 1 &&
"Nested loops with OpenMPIRBuilder not yet implemented");
2140 const Stmt *SyntacticalLoop = S->getLoopStmt();
2151 const Stmt *BodyStmt;
2152 if (
const auto *For = dyn_cast<ForStmt>(SyntacticalLoop)) {
2153 if (
const Stmt *InitStmt = For->getInit())
2155 BodyStmt = For->getBody();
2156 }
else if (
const auto *RangeFor =
2157 dyn_cast<CXXForRangeStmt>(SyntacticalLoop)) {
2158 if (
const DeclStmt *RangeStmt = RangeFor->getRangeStmt())
2160 if (
const DeclStmt *BeginStmt = RangeFor->getBeginStmt())
2162 if (
const DeclStmt *EndStmt = RangeFor->getEndStmt())
2164 if (
const DeclStmt *LoopVarStmt = RangeFor->getLoopVarStmt())
2166 BodyStmt = RangeFor->getBody();
2168 llvm_unreachable(
"Expected for-stmt or range-based for-stmt");
2171 const CapturedStmt *DistanceFunc = S->getDistanceFunc();
2184 llvm::Value *DistVal =
Builder.CreateLoad(CountAddr,
".count");
2187 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2188 auto BodyGen = [&,
this](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP,
2189 llvm::Value *IndVar) {
2194 const DeclRefExpr *LoopVarRef = S->getLoopVarRef();
2202 return llvm::Error::success();
2205 llvm::CanonicalLoopInfo *
CL =
2206 cantFail(OMPBuilder.createCanonicalLoop(
Builder, BodyGen, DistVal));
2218 const Expr *IncExpr,
2219 const llvm::function_ref<
void(CodeGenFunction &)> BodyGen,
2220 const llvm::function_ref<
void(CodeGenFunction &)> PostIncGen) {
2230 const CapturedStmt *ICS = OMPED.getInnermostCapturedStmt();
2244 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
2245 if (RequiresCleanup)
2252 if (ExitBlock !=
LoopExit.getBlock()) {
2262 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
2270 BreakContinueStack.pop_back();
2281 bool HasLinears =
false;
2286 if (
const auto *Ref =
2305 if (
const auto *CS = cast_or_null<BinaryOperator>(
C->getCalcStep()))
2317 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2320 llvm::BasicBlock *DoneBB =
nullptr;
2323 auto IC =
C->varlist_begin();
2324 for (
const Expr *F :
C->finals()) {
2326 if (llvm::Value *
Cond = CondGen(*
this)) {
2338 (*IC)->getType(),
VK_LValue, (*IC)->getExprLoc());
2346 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
2358 llvm::APInt ClauseAlignment(64, 0);
2359 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
2362 ClauseAlignment = AlignmentCI->getValue();
2364 for (
const Expr *E : Clause->varlist()) {
2365 llvm::APInt Alignment(ClauseAlignment);
2366 if (Alignment == 0) {
2373 E->getType()->getPointeeType()))
2376 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2377 "alignment is not power of 2");
2378 if (Alignment != 0) {
2392 auto I = S.private_counters().begin();
2393 for (
const Expr *E : S.counters()) {
2399 LocalDeclMap.erase(PrivateVD);
2405 E->getType(),
VK_LValue, E->getExprLoc());
2414 if (!
C->getNumForLoops())
2416 for (
unsigned I = S.getLoopsNumber(), E =
C->getLoopNumIterations().size();
2422 if (DRE->refersToEnclosingVariableOrCapture()) {
2431 const Expr *
Cond, llvm::BasicBlock *TrueBlock,
2432 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
2440 for (
const Expr *I : S.inits()) {
2447 for (
const Expr *E : S.dependent_counters()) {
2450 assert(!E->getType().getNonReferenceType()->isRecordType() &&
2451 "dependent counter must not be an iterator.");
2455 (void)PreCondVars.
setVarAddr(CGF, VD, CounterAddr);
2457 (void)PreCondVars.
apply(CGF);
2458 for (
const Expr *E : S.dependent_inits()) {
2472 llvm::DenseSet<const VarDecl *> SIMDLCVs;
2476 for (
const Expr *
C : LoopDirective->counters()) {
2482 auto CurPrivate =
C->privates().begin();
2483 for (
const Expr *E :
C->varlist()) {
2485 const auto *PrivateVD =
2492 assert(IsRegistered &&
"linear var already registered as private");
2580 if (
const auto *CS = dyn_cast<CapturedStmt>(S))
2598 if (HasOrderedDirective)
2606 const Stmt *AssociatedStmt = D.getAssociatedStmt();
2610 if (
C->getKind() == OMPC_ORDER_concurrent)
2613 if ((EKind == OMPD_simd ||
2617 return C->getModifier() == OMPC_REDUCTION_inscan;
2625 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2628 llvm::BasicBlock *DoneBB =
nullptr;
2629 auto IC = D.counters().begin();
2630 auto IPC = D.private_counters().begin();
2631 for (
const Expr *F : D.finals()) {
2634 const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
2636 OrigVD->hasGlobalStorage() || CED) {
2638 if (llvm::Value *
Cond = CondGen(*
this)) {
2686 auto &&ThenGen = [&S, &SimdInitGen, &BodyCodeGen](
CodeGenFunction &CGF,
2700 const Expr *IfCond =
nullptr;
2703 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
2705 (
C->getNameModifier() == OMPD_unknown ||
2706 C->getNameModifier() == OMPD_simd)) {
2707 IfCond =
C->getCondition();
2723 OMPLoopScope PreInitScope(CGF, S);
2745 llvm::BasicBlock *ContBlock =
nullptr;
2752 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
2759 const Expr *IVExpr = S.getIterationVariable();
2767 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
2782 CGF, S, CGF.
EmitLValue(S.getIterationVariable()));
2797 emitOMPLoopBodyWithStopPoint(CGF, S,
2798 CodeGenFunction::JumpDest());
2804 if (HasLastprivateClause)
2833 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(S.getRawStmt())) {
2834 if (
const Stmt *SyntacticalLoop = CanonLoop->getLoopStmt()) {
2835 for (
const Stmt *SubStmt : SyntacticalLoop->
children()) {
2838 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(SubStmt)) {
2853static llvm::MapVector<llvm::Value *, llvm::Value *>
2855 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars;
2857 llvm::APInt ClauseAlignment(64, 0);
2858 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
2861 ClauseAlignment = AlignmentCI->getValue();
2863 for (
const Expr *E : Clause->varlist()) {
2864 llvm::APInt Alignment(ClauseAlignment);
2865 if (Alignment == 0) {
2872 E->getType()->getPointeeType()))
2875 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2876 "alignment is not power of 2");
2878 AlignedVars[PtrValue] = CGF.
Builder.getInt64(Alignment.getSExtValue());
2888 bool UseOMPIRBuilder =
2890 if (UseOMPIRBuilder) {
2894 if (UseOMPIRBuilder) {
2895 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars =
2898 const Stmt *Inner = S.getRawStmt();
2899 llvm::CanonicalLoopInfo *CLI =
2900 CGF.EmitOMPCollapsedCanonicalLoopNest(Inner, 1);
2902 llvm::OpenMPIRBuilder &OMPBuilder =
2905 llvm::ConstantInt *Simdlen =
nullptr;
2912 llvm::ConstantInt *Safelen =
nullptr;
2919 llvm::omp::OrderKind Order = llvm::omp::OrderKind::OMP_ORDER_unknown;
2921 if (
C->getKind() == OpenMPOrderClauseKind::OMPC_ORDER_concurrent) {
2922 Order = llvm::omp::OrderKind::OMP_ORDER_concurrent;
2927 OMPBuilder.applySimd(CLI, AlignedVars,
2928 nullptr, Order, Simdlen, Safelen);
2935 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
2950 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
2963 OMPTransformDirectiveScopeRAII TileScope(*
this, &S);
2969 OMPTransformDirectiveScopeRAII StripeScope(*
this, &S);
2975 OMPTransformDirectiveScopeRAII ReverseScope(*
this, &S);
2982 OMPTransformDirectiveScopeRAII InterchangeScope(*
this, &S);
2988 OMPTransformDirectiveScopeRAII FuseScope(*
this, &S);
2993 bool UseOMPIRBuilder =
CGM.getLangOpts().OpenMPIRBuilder;
2995 if (UseOMPIRBuilder) {
2997 const Stmt *Inner = S.getRawStmt();
3005 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
3008 llvm::CanonicalLoopInfo *UnrolledCLI =
nullptr;
3012 OMPBuilder.unrollLoopFull(DL, CLI);
3014 uint64_t Factor = 0;
3015 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3016 Factor = FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
3017 assert(Factor >= 1 &&
"Only positive factors are valid");
3019 OMPBuilder.unrollLoopPartial(DL, CLI, Factor,
3020 NeedsUnrolledCLI ? &UnrolledCLI :
nullptr);
3022 OMPBuilder.unrollLoopHeuristic(DL, CLI);
3025 assert((!NeedsUnrolledCLI || UnrolledCLI) &&
3026 "NeedsUnrolledCLI implies UnrolledCLI to be set");
3043 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3045 FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
3046 assert(Factor >= 1 &&
"Only positive factors are valid");
3054void CodeGenFunction::EmitOMPOuterLoop(
3057 const CodeGenFunction::OMPLoopArguments &LoopArgs,
3062 const Expr *IVExpr = S.getIterationVariable();
3076 llvm::Value *BoolCondVal =
nullptr;
3077 if (!DynamicOrOrdered) {
3088 RT.
emitForNext(*
this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL,
3089 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST);
3094 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
3099 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
3100 if (ExitBlock !=
LoopExit.getBlock()) {
3108 if (DynamicOrOrdered)
3113 BreakContinueStack.push_back(BreakContinue(S, LoopExit, Continue));
3118 [&S, IsMonotonic, EKind](CodeGenFunction &CGF, PrePostActionTy &) {
3123 if (
const auto *
C = S.getSingleClause<OMPOrderClause>())
3124 if (
C->getKind() == OMPC_ORDER_concurrent)
3130 [&S, &LoopArgs, LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered,
3131 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
3132 SourceLocation Loc = S.getBeginLoc();
3138 CGF.EmitOMPInnerLoop(
3140 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
3141 CodeGenLoop(CGF, S, LoopExit);
3143 [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) {
3144 CodeGenOrdered(CGF, Loc, IVSize, IVSigned);
3149 BreakContinueStack.pop_back();
3150 if (!DynamicOrOrdered) {
3163 auto &&CodeGen = [DynamicOrOrdered, &S, &LoopArgs](CodeGenFunction &CGF) {
3164 if (!DynamicOrOrdered)
3165 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
3168 OMPCancelStack.emitExit(*
this, EKind, CodeGen);
3171void CodeGenFunction::EmitOMPForOuterLoop(
3172 const OpenMPScheduleTy &ScheduleKind,
bool IsMonotonic,
3174 const OMPLoopArguments &LoopArgs,
3176 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3182 LoopArgs.Chunk !=
nullptr)) &&
3183 "static non-chunked schedule does not need outer loop");
3237 const Expr *IVExpr = S.getIterationVariable();
3241 if (DynamicOrOrdered) {
3242 const std::pair<llvm::Value *, llvm::Value *> DispatchBounds =
3243 CGDispatchBounds(*
this, S, LoopArgs.LB, LoopArgs.UB);
3244 llvm::Value *LBVal = DispatchBounds.first;
3245 llvm::Value *UBVal = DispatchBounds.second;
3246 CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal,
3249 IVSigned, Ordered, DipatchRTInputValues);
3251 CGOpenMPRuntime::StaticRTInput StaticInit(
3252 IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
3253 LoopArgs.ST, LoopArgs.Chunk);
3259 auto &&CodeGenOrdered = [Ordered](CodeGenFunction &CGF, SourceLocation Loc,
3260 const unsigned IVSize,
3261 const bool IVSigned) {
3268 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST,
3269 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB);
3270 OuterLoopArgs.IncExpr = S.getInc();
3271 OuterLoopArgs.Init = S.getInit();
3272 OuterLoopArgs.Cond = S.getCond();
3273 OuterLoopArgs.NextLB = S.getNextLowerBound();
3274 OuterLoopArgs.NextUB = S.getNextUpperBound();
3275 OuterLoopArgs.DKind = LoopArgs.DKind;
3276 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
3278 if (DynamicOrOrdered) {
3284 const unsigned IVSize,
const bool IVSigned) {}
3286void CodeGenFunction::EmitOMPDistributeOuterLoop(
3291 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3298 const Expr *IVExpr = S.getIterationVariable();
3303 CGOpenMPRuntime::StaticRTInput StaticInit(
3304 IVSize, IVSigned,
false, LoopArgs.IL, LoopArgs.LB,
3305 LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
3312 IncExpr = S.getDistInc();
3314 IncExpr = S.getInc();
3319 OMPLoopArguments OuterLoopArgs;
3320 OuterLoopArgs.LB = LoopArgs.LB;
3321 OuterLoopArgs.UB = LoopArgs.UB;
3322 OuterLoopArgs.ST = LoopArgs.ST;
3323 OuterLoopArgs.IL = LoopArgs.IL;
3324 OuterLoopArgs.Chunk = LoopArgs.Chunk;
3326 ? S.getCombinedEnsureUpperBound()
3327 : S.getEnsureUpperBound();
3328 OuterLoopArgs.IncExpr = IncExpr;
3330 ? S.getCombinedInit()
3333 ? S.getCombinedCond()
3336 ? S.getCombinedNextLowerBound()
3337 : S.getNextLowerBound();
3339 ? S.getCombinedNextUpperBound()
3340 : S.getNextUpperBound();
3341 OuterLoopArgs.DKind = OMPD_distribute;
3343 EmitOMPOuterLoop(
false,
false, S,
3344 LoopScope, OuterLoopArgs, CodeGenLoopContent,
3348static std::pair<LValue, LValue>
3363 LValue PrevLB = CGF.
EmitLValue(LS.getPrevLowerBoundVariable());
3364 LValue PrevUB = CGF.
EmitLValue(LS.getPrevUpperBoundVariable());
3366 PrevLB, LS.getPrevLowerBoundVariable()->getExprLoc());
3368 PrevLBVal, LS.getPrevLowerBoundVariable()->getType(),
3369 LS.getIterationVariable()->getType(),
3370 LS.getPrevLowerBoundVariable()->getExprLoc());
3372 PrevUB, LS.getPrevUpperBoundVariable()->getExprLoc());
3374 PrevUBVal, LS.getPrevUpperBoundVariable()->getType(),
3375 LS.getIterationVariable()->getType(),
3376 LS.getPrevUpperBoundVariable()->getExprLoc());
3391static std::pair<llvm::Value *, llvm::Value *>
3396 const Expr *IVExpr = LS.getIterationVariable();
3402 llvm::Value *LBVal =
3404 llvm::Value *UBVal =
3406 return {LBVal, UBVal};
3415 llvm::Value *LBCast = CGF.
Builder.CreateIntCast(
3417 CapturedVars.push_back(LBCast);
3421 llvm::Value *UBCast = CGF.
Builder.CreateIntCast(
3423 CapturedVars.push_back(UBCast);
3434 bool HasCancel =
false;
3436 if (
const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
3437 HasCancel = D->hasCancel();
3438 else if (
const auto *D = dyn_cast<OMPDistributeParallelForDirective>(&S))
3439 HasCancel = D->hasCancel();
3440 else if (
const auto *D =
3441 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S))
3442 HasCancel = D->hasCancel();
3452 CGInlinedWorksharingLoop,
3462 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3463 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3472 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3473 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3481 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
3482 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
3492 llvm::Constant *
Addr;
3494 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
3496 assert(Fn &&
Addr &&
"Target device function emission failed.");
3508struct ScheduleKindModifiersTy {
3515 : Kind(Kind), M1(M1), M2(M2) {}
3531 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
3539 bool HasLastprivateClause;
3542 OMPLoopScope PreInitScope(*
this, S);
3547 llvm::BasicBlock *ContBlock =
nullptr;
3554 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
3561 bool Ordered =
false;
3563 if (OrderedClause->getNumForLoops())
3573 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*
this, S);
3574 LValue LB = Bounds.first;
3575 LValue UB = Bounds.second;
3589 CGM.getOpenMPRuntime().emitBarrierCall(
3590 *
this, S.getBeginLoc(), OMPD_unknown,
false,
3595 *
this, S,
EmitLValue(S.getIterationVariable()));
3602 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
3605 const Expr *ChunkExpr =
nullptr;
3608 ScheduleKind.
Schedule =
C->getScheduleKind();
3609 ScheduleKind.
M1 =
C->getFirstScheduleModifier();
3610 ScheduleKind.
M2 =
C->getSecondScheduleModifier();
3611 ChunkExpr =
C->getChunkSize();
3614 CGM.getOpenMPRuntime().getDefaultScheduleAndChunk(
3615 *
this, S, ScheduleKind.
Schedule, ChunkExpr);
3617 bool HasChunkSizeOne =
false;
3618 llvm::Value *Chunk =
nullptr;
3622 S.getIterationVariable()->getType(),
3626 llvm::APSInt EvaluatedChunk =
Result.Val.getInt();
3627 HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
3636 bool StaticChunkedOne =
3638 Chunk !=
nullptr) &&
3642 (ScheduleKind.
Schedule == OMPC_SCHEDULE_static &&
3643 !(ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
3644 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)) ||
3645 ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
3646 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
3648 Chunk !=
nullptr) ||
3649 StaticChunkedOne) &&
3659 if (
C->getKind() == OMPC_ORDER_concurrent)
3663 [IVSize, IVSigned, Ordered, IL, LB, UB, ST, StaticChunkedOne, Chunk,
3672 IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(),
3673 UB.getAddress(), ST.getAddress(),
3674 StaticChunkedOne ? Chunk :
nullptr);
3676 CGF, S.getBeginLoc(), EKind, ScheduleKind, StaticInit);
3678 if (!StaticChunkedOne)
3697 StaticChunkedOne ? S.getCombinedParForInDistCond()
3699 StaticChunkedOne ? S.getDistInc() : S.getInc(),
3700 [&S,
LoopExit](CodeGenFunction &CGF) {
3701 emitOMPLoopBodyWithStopPoint(CGF, S, LoopExit);
3703 [](CodeGenFunction &) {});
3707 auto &&
CodeGen = [&S](CodeGenFunction &CGF) {
3711 OMPCancelStack.emitExit(*
this, EKind,
CodeGen);
3718 LoopArguments.DKind = OMPD_for;
3719 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
3720 LoopArguments, CGDispatchBounds);
3724 return CGF.
Builder.CreateIsNotNull(
3730 ? OMPD_parallel_for_simd
3734 *
this, S, [IL, &S](CodeGenFunction &CGF) {
3735 return CGF.
Builder.CreateIsNotNull(
3739 if (HasLastprivateClause)
3745 return CGF.
Builder.CreateIsNotNull(
3756 return HasLastprivateClause;
3762static std::pair<LValue, LValue>
3776static std::pair<llvm::Value *, llvm::Value *>
3780 const Expr *IVExpr = LS.getIterationVariable();
3782 llvm::Value *LBVal = CGF.
Builder.getIntN(IVSize, 0);
3784 return {LBVal, UBVal};
3796 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
3797 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
3798 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
3804 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
3805 "Only inscan reductions are expected.");
3806 Shareds.append(
C->varlist_begin(),
C->varlist_end());
3807 Privates.append(
C->privates().begin(),
C->privates().end());
3808 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
3809 CopyArrayTemps.append(
C->copy_array_temps().begin(),
3810 C->copy_array_temps().end());
3818 auto *ITA = CopyArrayTemps.begin();
3819 for (
const Expr *IRef : Privates) {
3823 if (PrivateVD->getType()->isVariablyModifiedType()) {
3848 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
3849 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
3850 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
3858 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
3859 "Only inscan reductions are expected.");
3860 Shareds.append(
C->varlist_begin(),
C->varlist_end());
3861 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
3862 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
3863 Privates.append(
C->privates().begin(),
C->privates().end());
3864 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
3865 CopyArrayElems.append(
C->copy_array_elems().begin(),
3866 C->copy_array_elems().end());
3870 llvm::Value *OMPLast = CGF.
Builder.CreateNSWSub(
3871 OMPScanNumIterations,
3872 llvm::ConstantInt::get(CGF.
SizeTy, 1,
false));
3873 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
3874 const Expr *PrivateExpr = Privates[I];
3875 const Expr *OrigExpr = Shareds[I];
3876 const Expr *CopyArrayElem = CopyArrayElems[I];
3883 LValue SrcLVal = CGF.
EmitLValue(CopyArrayElem);
3885 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
3915 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
3916 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
3923 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
3924 "Only inscan reductions are expected.");
3925 Privates.append(
C->privates().begin(),
C->privates().end());
3926 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
3927 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
3928 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
3929 CopyArrayElems.append(
C->copy_array_elems().begin(),
3930 C->copy_array_elems().end());
3945 auto &&
CodeGen = [&S, OMPScanNumIterations, &LHSs, &RHSs, &CopyArrayElems,
3952 llvm::BasicBlock *InputBB = CGF.Builder.GetInsertBlock();
3953 llvm::BasicBlock *LoopBB = CGF.createBasicBlock(
"omp.outer.log.scan.body");
3954 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
"omp.outer.log.scan.exit");
3956 CGF.CGM.getIntrinsic(llvm::Intrinsic::log2, CGF.DoubleTy);
3958 CGF.Builder.CreateUIToFP(OMPScanNumIterations, CGF.DoubleTy);
3959 llvm::Value *LogVal = CGF.EmitNounwindRuntimeCall(F, Arg);
3960 F = CGF.CGM.getIntrinsic(llvm::Intrinsic::ceil, CGF.DoubleTy);
3961 LogVal = CGF.EmitNounwindRuntimeCall(F, LogVal);
3962 LogVal = CGF.Builder.CreateFPToUI(LogVal, CGF.IntTy);
3963 llvm::Value *NMin1 = CGF.Builder.CreateNUWSub(
3964 OMPScanNumIterations, llvm::ConstantInt::get(CGF.SizeTy, 1));
3966 CGF.EmitBlock(LoopBB);
3967 auto *Counter = CGF.Builder.CreatePHI(CGF.IntTy, 2);
3969 auto *Pow2K = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
3970 Counter->addIncoming(llvm::ConstantInt::get(CGF.IntTy, 0), InputBB);
3971 Pow2K->addIncoming(llvm::ConstantInt::get(CGF.SizeTy, 1), InputBB);
3974 llvm::BasicBlock *InnerLoopBB =
3975 CGF.createBasicBlock(
"omp.inner.log.scan.body");
3976 llvm::BasicBlock *InnerExitBB =
3977 CGF.createBasicBlock(
"omp.inner.log.scan.exit");
3978 llvm::Value *CmpI = CGF.Builder.CreateICmpUGE(NMin1, Pow2K);
3979 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
3980 CGF.EmitBlock(InnerLoopBB);
3981 auto *IVal = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
3982 IVal->addIncoming(NMin1, LoopBB);
3985 auto *ILHS = LHSs.begin();
3986 auto *IRHS = RHSs.begin();
3987 for (
const Expr *CopyArrayElem : CopyArrayElems) {
3997 LHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4002 llvm::Value *OffsetIVal = CGF.Builder.CreateNUWSub(IVal, Pow2K);
4008 RHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4015 CGF.CGM.getOpenMPRuntime().emitReduction(
4016 CGF, S.getEndLoc(), Privates, LHSs, RHSs, ReductionOps,
4020 llvm::Value *NextIVal =
4021 CGF.Builder.CreateNUWSub(IVal, llvm::ConstantInt::get(CGF.SizeTy, 1));
4022 IVal->addIncoming(NextIVal, CGF.Builder.GetInsertBlock());
4023 CmpI = CGF.Builder.CreateICmpUGE(NextIVal, Pow2K);
4024 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4025 CGF.EmitBlock(InnerExitBB);
4027 CGF.Builder.CreateNUWAdd(Counter, llvm::ConstantInt::get(CGF.IntTy, 1));
4028 Counter->addIncoming(
Next, CGF.Builder.GetInsertBlock());
4030 llvm::Value *NextPow2K =
4031 CGF.Builder.CreateShl(Pow2K, 1,
"",
true);
4032 Pow2K->addIncoming(NextPow2K, CGF.Builder.GetInsertBlock());
4033 llvm::Value *Cmp = CGF.Builder.CreateICmpNE(
Next, LogVal);
4034 CGF.Builder.CreateCondBr(Cmp, LoopBB, ExitBB);
4036 CGF.EmitBlock(ExitBB);
4042 CGF, S.getBeginLoc(), OMPD_unknown,
false,
4045 RegionCodeGenTy RCG(CodeGen);
4056 bool HasLastprivates;
4060 return C->getModifier() == OMPC_REDUCTION_inscan;
4064 OMPLoopScope LoopScope(CGF, S);
4067 const auto &&FirstGen = [&S, HasCancel, EKind](
CodeGenFunction &CGF) {
4076 const auto &&SecondGen = [&S, HasCancel, EKind,
4094 return HasLastprivates;
4107 if (
auto *SC = dyn_cast<OMPScheduleClause>(
C)) {
4112 switch (SC->getScheduleKind()) {
4113 case OMPC_SCHEDULE_auto:
4114 case OMPC_SCHEDULE_dynamic:
4115 case OMPC_SCHEDULE_runtime:
4116 case OMPC_SCHEDULE_guided:
4117 case OMPC_SCHEDULE_static:
4130static llvm::omp::ScheduleKind
4132 switch (ScheduleClauseKind) {
4134 return llvm::omp::OMP_SCHEDULE_Default;
4135 case OMPC_SCHEDULE_auto:
4136 return llvm::omp::OMP_SCHEDULE_Auto;
4137 case OMPC_SCHEDULE_dynamic:
4138 return llvm::omp::OMP_SCHEDULE_Dynamic;
4139 case OMPC_SCHEDULE_guided:
4140 return llvm::omp::OMP_SCHEDULE_Guided;
4141 case OMPC_SCHEDULE_runtime:
4142 return llvm::omp::OMP_SCHEDULE_Runtime;
4143 case OMPC_SCHEDULE_static:
4144 return llvm::omp::OMP_SCHEDULE_Static;
4146 llvm_unreachable(
"Unhandled schedule kind");
4153 bool HasLastprivates =
false;
4156 auto &&
CodeGen = [&S, &
CGM, HasCancel, &HasLastprivates,
4159 if (UseOMPIRBuilder) {
4162 llvm::omp::ScheduleKind SchedKind = llvm::omp::OMP_SCHEDULE_Default;
4163 llvm::Value *ChunkSize =
nullptr;
4167 if (
const Expr *ChunkSizeExpr = SchedClause->getChunkSize())
4172 const Stmt *Inner = S.getRawStmt();
4173 llvm::CanonicalLoopInfo *CLI =
4176 llvm::OpenMPIRBuilder &OMPBuilder =
4178 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4180 cantFail(OMPBuilder.applyWorkshareLoop(
4181 CGF.
Builder.getCurrentDebugLocation(), CLI, AllocaIP, NeedsBarrier,
4182 SchedKind, ChunkSize,
false,
4193 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
4198 if (!UseOMPIRBuilder) {
4212 bool HasLastprivates =
false;
4213 auto &&
CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
4220 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4221 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
4226 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_for);
4233 llvm::Value *
Init =
nullptr) {
4240void CodeGenFunction::EmitSections(
const OMPExecutableDirective &S) {
4241 const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4242 const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt);
4243 bool HasLastprivates =
false;
4245 auto &&CodeGen = [&S, CapturedStmt, CS, EKind,
4246 &HasLastprivates](CodeGenFunction &CGF, PrePostActionTy &) {
4247 const ASTContext &
C = CGF.getContext();
4248 QualType KmpInt32Ty =
4249 C.getIntTypeForBitwidth(32, 1);
4252 CGF.Builder.getInt32(0));
4253 llvm::ConstantInt *GlobalUBVal = CS !=
nullptr
4254 ? CGF.Builder.getInt32(CS->size() - 1)
4255 : CGF.Builder.getInt32(0);
4259 CGF.Builder.getInt32(1));
4261 CGF.Builder.getInt32(0));
4264 OpaqueValueExpr IVRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4265 CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
4266 OpaqueValueExpr UBRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4267 CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
4271 S.getBeginLoc(), FPOptionsOverride());
4275 S.getBeginLoc(),
true, FPOptionsOverride());
4276 auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
4288 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".omp.sections.exit");
4289 llvm::SwitchInst *SwitchStmt =
4290 CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.
getBeginLoc()),
4291 ExitBB, CS ==
nullptr ? 1 : CS->size());
4293 unsigned CaseNumber = 0;
4294 for (
const Stmt *SubStmt : CS->
children()) {
4295 auto CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4296 CGF.EmitBlock(CaseBB);
4297 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
4298 CGF.EmitStmt(SubStmt);
4299 CGF.EmitBranch(ExitBB);
4303 llvm::BasicBlock *CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4304 CGF.EmitBlock(CaseBB);
4305 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
4306 CGF.EmitStmt(CapturedStmt);
4307 CGF.EmitBranch(ExitBB);
4309 CGF.EmitBlock(ExitBB,
true);
4312 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
4313 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
4317 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
4321 CGF.EmitOMPPrivateClause(S, LoopScope);
4322 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(CGF, S, IV);
4323 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
4324 CGF.EmitOMPReductionClauseInit(S, LoopScope);
4325 (void)LoopScope.Privatize();
4327 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
4330 OpenMPScheduleTy ScheduleKind;
4331 ScheduleKind.
Schedule = OMPC_SCHEDULE_static;
4332 CGOpenMPRuntime::StaticRTInput StaticInit(
4333 32,
true,
false, IL.getAddress(),
4334 LB.getAddress(), UB.getAddress(), ST.getAddress());
4335 CGF.CGM.getOpenMPRuntime().emitForStaticInit(CGF, S.
getBeginLoc(), EKind,
4336 ScheduleKind, StaticInit);
4338 llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.
getBeginLoc());
4339 llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
4340 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
4341 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
4343 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.
getBeginLoc()), IV);
4345 CGF.EmitOMPInnerLoop(S,
false,
Cond, Inc, BodyGen,
4346 [](CodeGenFunction &) {});
4348 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
4349 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.
getEndLoc(),
4352 CGF.OMPCancelStack.emitExit(CGF, EKind, CodeGen);
4353 CGF.EmitOMPReductionClauseFinal(S, OMPD_parallel);
4356 return CGF.
Builder.CreateIsNotNull(
4361 if (HasLastprivates)
4368 bool HasCancel =
false;
4369 if (
auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
4370 HasCancel = OSD->hasCancel();
4371 else if (
auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
4372 HasCancel = OPSD->hasCancel();
4374 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_sections, CodeGen,
4379 if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) {
4397 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4402 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4403 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_scope,
CodeGen);
4407 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_scope);
4414 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4415 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4416 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4417 using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
4419 auto FiniCB = [](InsertPointTy IP) {
4422 return llvm::Error::success();
4425 const CapturedStmt *ICS = S.getInnermostCapturedStmt();
4431 auto SectionCB = [
this, SubStmt](InsertPointTy AllocaIP,
4432 InsertPointTy CodeGenIP) {
4434 *
this, SubStmt, AllocaIP, CodeGenIP,
"section");
4435 return llvm::Error::success();
4437 SectionCBVector.push_back(SectionCB);
4440 auto SectionCB = [
this,
CapturedStmt](InsertPointTy AllocaIP,
4441 InsertPointTy CodeGenIP) {
4444 return llvm::Error::success();
4446 SectionCBVector.push_back(SectionCB);
4453 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
4454 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
4464 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4466 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4467 cantFail(OMPBuilder.createSections(
4468 Builder, AllocaIP, SectionCBVector, PrivCB, FiniCB, S.hasCancel(),
4476 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4481 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(),
4489 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4490 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4491 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4493 const Stmt *SectionRegionBodyStmt = S.getAssociatedStmt();
4494 auto FiniCB = [
this](InsertPointTy IP) {
4496 return llvm::Error::success();
4499 auto BodyGenCB = [SectionRegionBodyStmt,
this](InsertPointTy AllocaIP,
4500 InsertPointTy CodeGenIP) {
4502 *
this, SectionRegionBodyStmt, AllocaIP, CodeGenIP,
"section");
4503 return llvm::Error::success();
4508 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4509 cantFail(OMPBuilder.createSection(
Builder, BodyGenCB, FiniCB));
4529 CopyprivateVars.append(
C->varlist_begin(),
C->varlist_end());
4530 DestExprs.append(
C->destination_exprs().begin(),
4531 C->destination_exprs().end());
4532 SrcExprs.append(
C->source_exprs().begin(),
C->source_exprs().end());
4533 AssignmentOps.append(
C->assignment_ops().begin(),
4534 C->assignment_ops().end());
4543 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4548 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4549 CGM.getOpenMPRuntime().emitSingleRegion(*
this,
CodeGen, S.getBeginLoc(),
4550 CopyprivateVars, DestExprs,
4551 SrcExprs, AssignmentOps);
4555 if (!S.getSingleClause<
OMPNowaitClause>() && CopyprivateVars.empty()) {
4556 CGM.getOpenMPRuntime().emitBarrierCall(
4557 *
this, S.getBeginLoc(),
4573 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4574 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4575 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4577 const Stmt *MasterRegionBodyStmt = S.getAssociatedStmt();
4579 auto FiniCB = [
this](InsertPointTy IP) {
4581 return llvm::Error::success();
4584 auto BodyGenCB = [MasterRegionBodyStmt,
this](InsertPointTy AllocaIP,
4585 InsertPointTy CodeGenIP) {
4587 *
this, MasterRegionBodyStmt, AllocaIP, CodeGenIP,
"master");
4588 return llvm::Error::success();
4593 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4594 cantFail(OMPBuilder.createMaster(
Builder, BodyGenCB, FiniCB));
4609 Expr *Filter =
nullptr;
4611 Filter = FilterClause->getThreadID();
4617 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4618 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4619 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4621 const Stmt *MaskedRegionBodyStmt = S.getAssociatedStmt();
4622 const Expr *Filter =
nullptr;
4624 Filter = FilterClause->getThreadID();
4625 llvm::Value *FilterVal = Filter
4627 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
4629 auto FiniCB = [
this](InsertPointTy IP) {
4631 return llvm::Error::success();
4634 auto BodyGenCB = [MaskedRegionBodyStmt,
this](InsertPointTy AllocaIP,
4635 InsertPointTy CodeGenIP) {
4637 *
this, MaskedRegionBodyStmt, AllocaIP, CodeGenIP,
"masked");
4638 return llvm::Error::success();
4643 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
4644 OMPBuilder.createMasked(
Builder, BodyGenCB, FiniCB, FilterVal));
4655 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4656 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4657 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4659 const Stmt *CriticalRegionBodyStmt = S.getAssociatedStmt();
4660 const Expr *Hint =
nullptr;
4661 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4662 Hint = HintClause->getHint();
4667 llvm::Value *HintInst =
nullptr;
4672 auto FiniCB = [
this](InsertPointTy IP) {
4674 return llvm::Error::success();
4677 auto BodyGenCB = [CriticalRegionBodyStmt,
this](InsertPointTy AllocaIP,
4678 InsertPointTy CodeGenIP) {
4680 *
this, CriticalRegionBodyStmt, AllocaIP, CodeGenIP,
"critical");
4681 return llvm::Error::success();
4686 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4687 cantFail(OMPBuilder.createCritical(
Builder, BodyGenCB, FiniCB,
4688 S.getDirectiveName().getAsString(),
4697 CGF.
EmitStmt(S.getAssociatedStmt());
4699 const Expr *Hint =
nullptr;
4700 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4701 Hint = HintClause->getHint();
4704 CGM.getOpenMPRuntime().emitCriticalRegion(*
this,
4705 S.getDirectiveName().getAsString(),
4706 CodeGen, S.getBeginLoc(), Hint);
4710 const OMPParallelForDirective &S) {
4719 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
4723 OMPLoopScope LoopScope(CGF, S);
4728 return C->getModifier() == OMPC_REDUCTION_inscan;
4744 const OMPParallelForSimdDirective &S) {
4753 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
4757 OMPLoopScope LoopScope(CGF, S);
4762 return C->getModifier() == OMPC_REDUCTION_inscan;
4778 const OMPParallelMasterDirective &S) {
4798 [](CodeGenFunction &) {
return nullptr; });
4805 const OMPParallelMaskedDirective &S) {
4825 [](CodeGenFunction &) {
return nullptr; });
4832 const OMPParallelSectionsDirective &S) {
4838 CGF.EmitSections(S);
4852class CheckVarsEscapingUntiedTaskDeclContext final
4857 explicit CheckVarsEscapingUntiedTaskDeclContext() =
default;
4858 ~CheckVarsEscapingUntiedTaskDeclContext() =
default;
4859 void VisitDeclStmt(
const DeclStmt *S) {
4864 if (
const auto *VD = dyn_cast_or_null<VarDecl>(D))
4866 PrivateDecls.push_back(VD);
4870 void VisitCapturedStmt(
const CapturedStmt *) {}
4872 void VisitBlockExpr(
const BlockExpr *) {}
4873 void VisitStmt(
const Stmt *S) {
4876 for (
const Stmt *Child : S->
children())
4882 ArrayRef<const VarDecl *> getPrivateDecls()
const {
return PrivateDecls; }
4890 bool OmpAllMemory =
false;
4893 return C->getDependencyKind() == OMPC_DEPEND_outallmemory ||
4894 C->getDependencyKind() == OMPC_DEPEND_inoutallmemory;
4896 OmpAllMemory =
true;
4901 Data.Dependences.emplace_back(OMPC_DEPEND_outallmemory,
4910 if (Kind == OMPC_DEPEND_outallmemory || Kind == OMPC_DEPEND_inoutallmemory)
4912 if (OmpAllMemory && (Kind == OMPC_DEPEND_out || Kind == OMPC_DEPEND_inout))
4915 Data.Dependences.emplace_back(
C->getDependencyKind(),
C->getModifier());
4916 DD.
DepExprs.append(
C->varlist_begin(),
C->varlist_end());
4925 const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion);
4927 auto PartId = std::next(I);
4928 auto TaskT = std::next(I, 4);
4933 const Expr *
Cond = Clause->getCondition();
4936 Data.Final.setInt(CondConstant);
4941 Data.Final.setInt(
false);
4945 const Expr *Prio = Clause->getPriority();
4946 Data.Priority.setInt(
true);
4954 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
4957 auto IRef =
C->varlist_begin();
4958 for (
const Expr *IInit :
C->private_copies()) {
4960 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
4961 Data.PrivateVars.push_back(*IRef);
4962 Data.PrivateCopies.push_back(IInit);
4967 EmittedAsPrivate.clear();
4970 auto IRef =
C->varlist_begin();
4971 auto IElemInitRef =
C->inits().begin();
4972 for (
const Expr *IInit :
C->private_copies()) {
4974 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
4975 Data.FirstprivateVars.push_back(*IRef);
4976 Data.FirstprivateCopies.push_back(IInit);
4977 Data.FirstprivateInits.push_back(*IElemInitRef);
4984 llvm::MapVector<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
4986 auto IRef =
C->varlist_begin();
4987 auto ID =
C->destination_exprs().begin();
4988 for (
const Expr *IInit :
C->private_copies()) {
4990 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
4991 Data.LastprivateVars.push_back(*IRef);
4992 Data.LastprivateCopies.push_back(IInit);
4994 LastprivateDstsOrigs.insert(
5004 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5005 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5006 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5007 Data.ReductionOps.append(
C->reduction_ops().begin(),
5008 C->reduction_ops().end());
5009 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5010 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5012 Data.Reductions =
CGM.getOpenMPRuntime().emitTaskReductionInit(
5013 *
this, S.getBeginLoc(), LHSs, RHSs,
Data);
5018 CheckVarsEscapingUntiedTaskDeclContext Checker;
5019 Checker.Visit(S.getInnermostCapturedStmt()->getCapturedStmt());
5020 Data.PrivateLocals.append(Checker.getPrivateDecls().begin(),
5021 Checker.getPrivateDecls().end());
5023 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
5024 CapturedRegion](CodeGenFunction &CGF,
5026 llvm::MapVector<CanonicalDeclPtr<const VarDecl>,
5027 std::pair<Address, Address>>
5032 if (
auto *DI = CGF.getDebugInfo()) {
5033 llvm::SmallDenseMap<const VarDecl *, FieldDecl *> CaptureFields =
5034 CGF.CapturedStmtInfo->getCaptureFields();
5035 llvm::Value *ContextValue = CGF.CapturedStmtInfo->getContextValue();
5036 if (CaptureFields.size() && ContextValue) {
5037 unsigned CharWidth = CGF.getContext().getCharWidth();
5051 for (
auto It = CaptureFields.begin(); It != CaptureFields.end(); ++It) {
5052 const VarDecl *SharedVar = It->first;
5055 CGF.getContext().getASTRecordLayout(CaptureRecord);
5058 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5059 (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue,
5060 CGF.Builder,
false);
5063 auto UpdateExpr = [](llvm::LLVMContext &Ctx,
auto *
Declare,
5068 Ops.push_back(llvm::dwarf::DW_OP_plus_uconst);
5069 Ops.push_back(Offset);
5071 Ops.push_back(llvm::dwarf::DW_OP_deref);
5072 Declare->setExpression(llvm::DIExpression::get(Ctx, Ops));
5074 llvm::Instruction &
Last = CGF.Builder.GetInsertBlock()->back();
5075 if (
auto DDI = dyn_cast<llvm::DbgVariableIntrinsic>(&
Last))
5076 UpdateExpr(DDI->getContext(), DDI, Offset);
5079 assert(!
Last.isTerminator() &&
"unexpected terminator");
5081 CGF.Builder.GetInsertBlock()->getTrailingDbgRecords()) {
5082 for (llvm::DbgVariableRecord &DVR : llvm::reverse(
5083 llvm::filterDbgVars(Marker->getDbgRecordRange()))) {
5084 UpdateExpr(
Last.getContext(), &DVR, Offset);
5092 if (!
Data.PrivateVars.empty() || !
Data.FirstprivateVars.empty() ||
5093 !
Data.LastprivateVars.empty() || !
Data.PrivateLocals.empty()) {
5094 enum { PrivatesParam = 2, CopyFnParam = 3 };
5095 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5097 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5103 CallArgs.push_back(PrivatesPtr);
5104 ParamTypes.push_back(PrivatesPtr->getType());
5105 for (
const Expr *E :
Data.PrivateVars) {
5108 CGF.getContext().getPointerType(E->
getType()),
".priv.ptr.addr");
5109 PrivatePtrs.emplace_back(VD, PrivatePtr);
5111 ParamTypes.push_back(PrivatePtr.
getType());
5113 for (
const Expr *E :
Data.FirstprivateVars) {
5116 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
5117 ".firstpriv.ptr.addr");
5118 PrivatePtrs.emplace_back(VD, PrivatePtr);
5119 FirstprivatePtrs.emplace_back(VD, PrivatePtr);
5121 ParamTypes.push_back(PrivatePtr.
getType());
5123 for (
const Expr *E :
Data.LastprivateVars) {
5126 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
5127 ".lastpriv.ptr.addr");
5128 PrivatePtrs.emplace_back(VD, PrivatePtr);
5130 ParamTypes.push_back(PrivatePtr.
getType());
5135 Ty = CGF.getContext().getPointerType(Ty);
5137 Ty = CGF.getContext().getPointerType(Ty);
5139 CGF.getContext().getPointerType(Ty),
".local.ptr.addr");
5140 auto Result = UntiedLocalVars.insert(
5143 if (
Result.second ==
false)
5144 *
Result.first = std::make_pair(
5147 ParamTypes.push_back(PrivatePtr.
getType());
5149 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5151 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5152 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5153 for (
const auto &Pair : LastprivateDstsOrigs) {
5157 CGF.CapturedStmtInfo->lookup(OrigVD) !=
nullptr,
5159 Pair.second->getExprLoc());
5160 Scope.addPrivate(Pair.first, CGF.EmitLValue(&DRE).getAddress());
5162 for (
const auto &Pair : PrivatePtrs) {
5164 CGF.Builder.CreateLoad(Pair.second),
5165 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5166 CGF.getContext().getDeclAlign(Pair.first));
5167 Scope.addPrivate(Pair.first, Replacement);
5168 if (
auto *DI = CGF.getDebugInfo())
5169 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5170 (void)DI->EmitDeclareOfAutoVariable(
5171 Pair.first, Pair.second.getBasePointer(), CGF.Builder,
5176 for (
auto &Pair : UntiedLocalVars) {
5177 QualType VDType = Pair.first->getType().getNonReferenceType();
5178 if (Pair.first->getType()->isLValueReferenceType())
5179 VDType = CGF.getContext().getPointerType(VDType);
5181 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5184 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(VDType)),
5185 CGF.getPointerAlign());
5186 Pair.second.first = Replacement;
5187 Ptr = CGF.Builder.CreateLoad(Replacement);
5188 Replacement =
Address(Ptr, CGF.ConvertTypeForMem(VDType),
5189 CGF.getContext().getDeclAlign(Pair.first));
5190 Pair.second.second = Replacement;
5192 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5193 Address Replacement(Ptr, CGF.ConvertTypeForMem(VDType),
5194 CGF.getContext().getDeclAlign(Pair.first));
5195 Pair.second.first = Replacement;
5199 if (
Data.Reductions) {
5201 for (
const auto &Pair : FirstprivatePtrs) {
5203 CGF.Builder.CreateLoad(Pair.second),
5204 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5205 CGF.getContext().getDeclAlign(Pair.first));
5206 FirstprivateScope.
addPrivate(Pair.first, Replacement);
5209 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5211 Data.ReductionCopies,
Data.ReductionOps);
5212 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
5214 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5220 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5222 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5225 CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF),
5226 CGF.getContext().VoidPtrTy,
5227 CGF.getContext().getPointerType(
5228 Data.ReductionCopies[Cnt]->getType()),
5229 Data.ReductionCopies[Cnt]->getExprLoc()),
5230 CGF.ConvertTypeForMem(
Data.ReductionCopies[Cnt]->getType()),
5231 Replacement.getAlignment());
5237 (void)
Scope.Privatize();
5243 auto IPriv =
C->privates().begin();
5244 auto IRed =
C->reduction_ops().begin();
5245 auto ITD =
C->taskgroup_descriptors().begin();
5246 for (
const Expr *Ref :
C->varlist()) {
5247 InRedVars.emplace_back(Ref);
5248 InRedPrivs.emplace_back(*IPriv);
5249 InRedOps.emplace_back(*IRed);
5250 TaskgroupDescriptors.emplace_back(*ITD);
5251 std::advance(IPriv, 1);
5252 std::advance(IRed, 1);
5253 std::advance(ITD, 1);
5259 if (!InRedVars.empty()) {
5261 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5269 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5271 llvm::Value *ReductionsPtr;
5272 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5273 ReductionsPtr = CGF.EmitLoadOfScalar(CGF.EmitLValue(TRExpr),
5274 TRExpr->getExprLoc());
5276 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5278 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5281 CGF.EmitScalarConversion(
5282 Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy,
5283 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
5284 InRedPrivs[Cnt]->getExprLoc()),
5285 CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()),
5286 Replacement.getAlignment());
5299 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5300 S, *I, *PartId, *TaskT, EKind,
CodeGen,
Data.Tied,
Data.NumberOfParts);
5301 OMPLexicalScope
Scope(*
this, S, std::nullopt,
5304 TaskGen(*
this, OutlinedFn,
Data);
5321 QualType ElemType =
C.getBaseElementType(Ty);
5331 Data.FirstprivateVars.emplace_back(OrigRef);
5332 Data.FirstprivateCopies.emplace_back(PrivateRef);
5333 Data.FirstprivateInits.emplace_back(InitRef);
5346 auto PartId = std::next(I);
5347 auto TaskT = std::next(I, 4);
5350 Data.Final.setInt(
false);
5353 auto IRef =
C->varlist_begin();
5354 auto IElemInitRef =
C->inits().begin();
5355 for (
auto *IInit :
C->private_copies()) {
5356 Data.FirstprivateVars.push_back(*IRef);
5357 Data.FirstprivateCopies.push_back(IInit);
5358 Data.FirstprivateInits.push_back(*IElemInitRef);
5366 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5367 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5368 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5369 Data.ReductionOps.append(
C->reduction_ops().begin(),
5370 C->reduction_ops().end());
5371 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5372 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5387 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5389 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5401 if (!isa_and_nonnull<llvm::ConstantPointerNull>(
5404 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5411 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, BPVD, PVD, SVD, MVD, EKind,
5415 if (!
Data.FirstprivateVars.empty()) {
5416 enum { PrivatesParam = 2, CopyFnParam = 3 };
5417 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5419 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5425 CallArgs.push_back(PrivatesPtr);
5426 ParamTypes.push_back(PrivatesPtr->getType());
5427 for (
const Expr *E :
Data.FirstprivateVars) {
5430 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
5431 ".firstpriv.ptr.addr");
5432 PrivatePtrs.emplace_back(VD, PrivatePtr);
5434 ParamTypes.push_back(PrivatePtr.
getType());
5436 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5438 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5439 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5440 for (
const auto &Pair : PrivatePtrs) {
5442 CGF.Builder.CreateLoad(Pair.second),
5443 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5444 CGF.getContext().getDeclAlign(Pair.first));
5445 Scope.addPrivate(Pair.first, Replacement);
5448 CGF.processInReduction(S,
Data, CGF, CS,
Scope);
5451 CGF.GetAddrOfLocalVar(BPVD), 0);
5453 CGF.GetAddrOfLocalVar(PVD), 0);
5454 InputInfo.
SizesArray = CGF.Builder.CreateConstArrayGEP(
5455 CGF.GetAddrOfLocalVar(SVD), 0);
5458 InputInfo.
MappersArray = CGF.Builder.CreateConstArrayGEP(
5459 CGF.GetAddrOfLocalVar(MVD), 0);
5463 OMPLexicalScope LexScope(CGF, S, OMPD_task,
false);
5465 if (CGF.CGM.getLangOpts().OpenMP >= 51 &&
5470 CGF.CGM.getOpenMPRuntime().emitThreadLimitClause(
5471 CGF, TL->getThreadLimit().front(), S.getBeginLoc());
5475 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5476 S, *I, *PartId, *TaskT, EKind,
CodeGen,
true,
5477 Data.NumberOfParts);
5478 llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<
OMPNowaitClause>() ? 1 : 0);
5482 CGM.getOpenMPRuntime().emitTaskCall(*
this, S.getBeginLoc(), S, OutlinedFn,
5483 SharedsTy, CapturedStruct, &IfCond,
Data);
5488 CodeGenFunction &CGF,
5492 if (
Data.Reductions) {
5494 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5496 Data.ReductionCopies,
Data.ReductionOps);
5499 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5513 Data.ReductionCopies[Cnt]->getType()),
5514 Data.ReductionCopies[Cnt]->getExprLoc()),
5516 Replacement.getAlignment());
5521 (void)
Scope.Privatize();
5527 auto IPriv =
C->privates().begin();
5528 auto IRed =
C->reduction_ops().begin();
5529 auto ITD =
C->taskgroup_descriptors().begin();
5530 for (
const Expr *Ref :
C->varlist()) {
5531 InRedVars.emplace_back(Ref);
5532 InRedPrivs.emplace_back(*IPriv);
5533 InRedOps.emplace_back(*IRed);
5534 TaskgroupDescriptors.emplace_back(*ITD);
5535 std::advance(IPriv, 1);
5536 std::advance(IRed, 1);
5537 std::advance(ITD, 1);
5541 if (!InRedVars.empty()) {
5543 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5551 llvm::Value *ReductionsPtr;
5552 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5556 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
5564 InRedPrivs[Cnt]->getExprLoc()),
5566 Replacement.getAlignment());
5580 const Expr *IfCond =
nullptr;
5581 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
5582 if (
C->getNameModifier() == OMPD_unknown ||
5583 C->getNameModifier() == OMPD_task) {
5584 IfCond =
C->getCondition();
5595 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
5596 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
5599 SharedsTy, CapturedStruct, IfCond,
5608 const OMPTaskyieldDirective &S) {
5609 CGM.getOpenMPRuntime().emitTaskyieldCall(*
this, S.getBeginLoc());
5616 bool IsFatal =
false;
5619 CGM.getOpenMPRuntime().emitErrorCall(*
this, S.getBeginLoc(), ME, IsFatal);
5623 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_barrier);
5631 CGM.getOpenMPRuntime().emitTaskwaitCall(*
this, S.getBeginLoc(),
Data);
5635 return T.clauses().empty();
5639 const OMPTaskgroupDirective &S) {
5640 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
5642 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
5643 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5647 auto BodyGenCB = [&,
this](InsertPointTy AllocaIP,
5648 InsertPointTy CodeGenIP) {
5650 EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5651 return llvm::Error::success();
5656 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5657 cantFail(OMPBuilder.createTaskgroup(
Builder, AllocaIP, BodyGenCB));
5663 if (
const Expr *E = S.getReductionRef()) {
5668 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5669 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5670 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5671 Data.ReductionOps.append(
C->reduction_ops().begin(),
5672 C->reduction_ops().end());
5673 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5674 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5676 llvm::Value *ReductionDesc =
5684 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5686 CGM.getOpenMPRuntime().emitTaskgroupRegion(*
this,
CodeGen, S.getBeginLoc());
5691 ? llvm::AtomicOrdering::NotAtomic
5692 : llvm::AtomicOrdering::AcquireRelease;
5693 CGM.getOpenMPRuntime().emitFlush(
5696 if (
const auto *FlushClause = S.getSingleClause<
OMPFlushClause>())
5698 FlushClause->varlist_end());
5701 S.getBeginLoc(), AO);
5711 for (
auto &Dep :
Data.Dependences) {
5712 Address DepAddr =
CGM.getOpenMPRuntime().emitDepobjDependClause(
5713 *
this, Dep, DC->getBeginLoc());
5719 CGM.getOpenMPRuntime().emitDestroyClause(*
this, DOLVal, DC->getBeginLoc());
5723 CGM.getOpenMPRuntime().emitUpdateClause(
5724 *
this, DOLVal, UC->getDependencyKind(), UC->getBeginLoc());
5743 if (
C->getModifier() != OMPC_REDUCTION_inscan)
5745 Shareds.append(
C->varlist_begin(),
C->varlist_end());
5746 Privates.append(
C->privates().begin(),
C->privates().end());
5747 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5748 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5749 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
5750 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
5751 CopyArrayTemps.append(
C->copy_array_temps().begin(),
5752 C->copy_array_temps().end());
5753 CopyArrayElems.append(
C->copy_array_elems().begin(),
5754 C->copy_array_elems().end());
5756 if (ParentDir.getDirectiveKind() == OMPD_simd ||
5798 : BreakContinueStack.back().ContinueBlock.getBlock());
5809 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
5810 const Expr *PrivateExpr = Privates[I];
5811 const Expr *TempExpr = CopyArrayTemps[I];
5823 CGM.getOpenMPRuntime().emitReduction(
5824 *
this, ParentDir.getEndLoc(), Privates, LHSs, RHSs, ReductionOps,
5827 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
5828 const Expr *PrivateExpr = Privates[I];
5835 const Expr *TempExpr = CopyArrayTemps[I];
5847 ? BreakContinueStack.back().ContinueBlock.getBlock()
5853 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
5859 .getIterationVariable()
5860 ->IgnoreParenImpCasts();
5863 IdxVal = Builder.CreateIntCast(IdxVal,
SizeTy,
false);
5864 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
5865 const Expr *PrivateExpr = Privates[I];
5866 const Expr *OrigExpr = Shareds[I];
5867 const Expr *CopyArrayElem = CopyArrayElems[I];
5868 OpaqueValueMapping IdxMapping(
5881 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
5884 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
5890 .getIterationVariable()
5891 ->IgnoreParenImpCasts();
5895 llvm::BasicBlock *ExclusiveExitBB =
nullptr;
5899 llvm::Value *Cmp =
Builder.CreateIsNull(IdxVal);
5900 Builder.CreateCondBr(Cmp, ExclusiveExitBB, ContBB);
5903 IdxVal =
Builder.CreateNUWSub(IdxVal, llvm::ConstantInt::get(
SizeTy, 1));
5905 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
5906 const Expr *PrivateExpr = Privates[I];
5907 const Expr *OrigExpr = Shareds[I];
5908 const Expr *CopyArrayElem = CopyArrayElems[I];
5917 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
5941 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
5949 bool HasLastprivateClause =
false;
5952 OMPLoopScope PreInitScope(*
this, S);
5957 llvm::BasicBlock *ContBlock =
nullptr;
5964 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
5978 ? S.getCombinedLowerBoundVariable()
5979 : S.getLowerBoundVariable())));
5983 ? S.getCombinedUpperBoundVariable()
5984 : S.getUpperBoundVariable())));
5995 CGM.getOpenMPRuntime().emitBarrierCall(
5996 *
this, S.getBeginLoc(), OMPD_unknown,
false,
6008 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
6011 llvm::Value *Chunk =
nullptr;
6014 ScheduleKind =
C->getDistScheduleKind();
6015 if (
const Expr *Ch =
C->getChunkSize()) {
6018 S.getIterationVariable()->getType(),
6023 CGM.getOpenMPRuntime().getDefaultDistScheduleAndChunk(
6024 *
this, S, ScheduleKind, Chunk);
6037 bool StaticChunked =
6041 Chunk !=
nullptr) ||
6046 StaticChunked ? Chunk :
nullptr);
6053 ? S.getCombinedEnsureUpperBound()
6054 : S.getEnsureUpperBound());
6057 ? S.getCombinedInit()
6062 ? S.getCombinedCond()
6066 Cond = S.getCombinedDistCond();
6098 [&S, &LoopScope,
Cond, IncExpr,
LoopExit, &CodeGenLoop,
6101 S, LoopScope.requiresCleanups(),
Cond, IncExpr,
6102 [&S,
LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
6103 CodeGenLoop(CGF, S, LoopExit);
6105 [&S, StaticChunked](CodeGenFunction &CGF) {
6106 if (StaticChunked) {
6107 CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound());
6108 CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound());
6109 CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound());
6110 CGF.EmitIgnoredExpr(S.getCombinedInit());
6120 const OMPLoopArguments LoopArguments = {
6121 LB.getAddress(), UB.getAddress(), ST.getAddress(), IL.getAddress(),
6123 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments,
6128 return CGF.
Builder.CreateIsNotNull(
6138 *
this, S, [IL, &S](CodeGenFunction &CGF) {
6139 return CGF.
Builder.CreateIsNotNull(
6144 if (HasLastprivateClause) {
6167 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
6176static llvm::Function *
6183 Fn->setDoesNotRecurse();
6187template <
typename T>
6189 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP,
6190 llvm::OpenMPIRBuilder &OMPBuilder) {
6192 unsigned NumLoops =
C->getNumLoops();
6196 for (
unsigned I = 0; I < NumLoops; I++) {
6197 const Expr *CounterVal =
C->getLoopData(I);
6202 StoreValues.emplace_back(StoreValue);
6204 OMPDoacrossKind<T> ODK;
6205 bool IsDependSource = ODK.isSource(
C);
6207 OMPBuilder.createOrderedDepend(CGF.
Builder, AllocaIP, NumLoops,
6208 StoreValues,
".cnt.addr", IsDependSource));
6212 if (
CGM.getLangOpts().OpenMPIRBuilder) {
6213 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
6214 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6219 assert(!S.hasAssociatedStmt() &&
"No associated statement must be in "
6220 "ordered depend|doacross construct.");
6232 auto FiniCB = [
this](InsertPointTy IP) {
6234 return llvm::Error::success();
6237 auto BodyGenCB = [&S,
C,
this](InsertPointTy AllocaIP,
6238 InsertPointTy CodeGenIP) {
6243 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
6244 Builder,
false,
".ordered.after");
6248 assert(S.getBeginLoc().isValid() &&
6249 "Outlined function call location must be valid.");
6252 OutlinedFn, CapturedVars);
6257 return llvm::Error::success();
6260 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6261 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
6262 OMPBuilder.createOrderedThreadsSimd(
Builder, BodyGenCB, FiniCB, !
C));
6269 assert(!S.hasAssociatedStmt() &&
6270 "No associated statement must be in ordered depend construct.");
6272 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6276 assert(!S.hasAssociatedStmt() &&
6277 "No associated statement must be in ordered doacross construct.");
6279 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6283 auto &&
CodeGen = [&S,
C,
this](CodeGenFunction &CGF,
6288 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
6290 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
6291 OutlinedFn, CapturedVars);
6297 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6298 CGM.getOpenMPRuntime().emitOrderedRegion(*
this,
CodeGen, S.getBeginLoc(), !
C);
6305 "DestType must have scalar evaluation kind.");
6306 assert(!Val.
isAggregate() &&
"Must be a scalar or complex.");
6317 "DestType must have complex evaluation kind.");
6326 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
6328 assert(Val.
isComplex() &&
"Must be a scalar or complex.");
6333 Val.
getComplexVal().first, SrcElementType, DestElementType, Loc);
6335 Val.
getComplexVal().second, SrcElementType, DestElementType, Loc);
6341 LValue LVal,
RValue RVal) {
6342 if (LVal.isGlobalReg())
6349 llvm::AtomicOrdering AO, LValue LVal,
6351 if (LVal.isGlobalReg())
6354 LVal, Loc, llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO),
6363 *
this, RVal, RValTy, LVal.
getType(), Loc)),
6372 llvm_unreachable(
"Must be a scalar or complex.");
6380 assert(
V->isLValue() &&
"V of 'omp atomic read' is not lvalue");
6381 assert(
X->isLValue() &&
"X of 'omp atomic read' is not lvalue");
6390 case llvm::AtomicOrdering::Acquire:
6391 case llvm::AtomicOrdering::AcquireRelease:
6392 case llvm::AtomicOrdering::SequentiallyConsistent:
6394 llvm::AtomicOrdering::Acquire);
6396 case llvm::AtomicOrdering::Monotonic:
6397 case llvm::AtomicOrdering::Release:
6399 case llvm::AtomicOrdering::NotAtomic:
6400 case llvm::AtomicOrdering::Unordered:
6401 llvm_unreachable(
"Unexpected ordering.");
6408 llvm::AtomicOrdering AO,
const Expr *
X,
6411 assert(
X->isLValue() &&
"X of 'omp atomic write' is not lvalue");
6419 case llvm::AtomicOrdering::Release:
6420 case llvm::AtomicOrdering::AcquireRelease:
6421 case llvm::AtomicOrdering::SequentiallyConsistent:
6423 llvm::AtomicOrdering::Release);
6425 case llvm::AtomicOrdering::Acquire:
6426 case llvm::AtomicOrdering::Monotonic:
6428 case llvm::AtomicOrdering::NotAtomic:
6429 case llvm::AtomicOrdering::Unordered:
6430 llvm_unreachable(
"Unexpected ordering.");
6437 llvm::AtomicOrdering AO,
6443 if (BO == BO_Comma || !
Update.isScalar() || !
X.isSimple() ||
6445 (
Update.getScalarVal()->getType() !=
X.getAddress().getElementType())) ||
6446 !Context.getTargetInfo().hasBuiltinAtomic(
6447 Context.getTypeSize(
X.getType()), Context.toBits(
X.getAlignment())))
6448 return std::make_pair(
false,
RValue::get(
nullptr));
6451 if (
T->isIntegerTy())
6454 if (
T->isFloatingPointTy() && (BO == BO_Add || BO == BO_Sub))
6460 if (!CheckAtomicSupport(
Update.getScalarVal()->getType(), BO) ||
6461 !CheckAtomicSupport(
X.getAddress().getElementType(), BO))
6462 return std::make_pair(
false,
RValue::get(
nullptr));
6464 bool IsInteger =
X.getAddress().getElementType()->isIntegerTy();
6465 llvm::AtomicRMWInst::BinOp RMWOp;
6468 RMWOp = IsInteger ? llvm::AtomicRMWInst::Add : llvm::AtomicRMWInst::FAdd;
6472 return std::make_pair(
false,
RValue::get(
nullptr));
6473 RMWOp = IsInteger ? llvm::AtomicRMWInst::Sub : llvm::AtomicRMWInst::FSub;
6476 RMWOp = llvm::AtomicRMWInst::And;
6479 RMWOp = llvm::AtomicRMWInst::Or;
6482 RMWOp = llvm::AtomicRMWInst::Xor;
6486 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6488 : llvm::AtomicRMWInst::Max)
6490 : llvm::AtomicRMWInst::UMax);
6493 : llvm::AtomicRMWInst::FMax;
6497 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6499 : llvm::AtomicRMWInst::Min)
6501 : llvm::AtomicRMWInst::UMin);
6504 : llvm::AtomicRMWInst::FMin;
6507 RMWOp = llvm::AtomicRMWInst::Xchg;
6516 return std::make_pair(
false,
RValue::get(
nullptr));
6535 llvm_unreachable(
"Unsupported atomic update operation");
6537 llvm::Value *UpdateVal =
Update.getScalarVal();
6538 if (
auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
6540 UpdateVal = CGF.
Builder.CreateIntCast(
6541 IC,
X.getAddress().getElementType(),
6542 X.getType()->hasSignedIntegerRepresentation());
6544 UpdateVal = CGF.
Builder.CreateCast(llvm::Instruction::CastOps::UIToFP, IC,
6545 X.getAddress().getElementType());
6547 llvm::AtomicRMWInst *Res =
6564 if (
X.isGlobalReg()) {
6577 llvm::AtomicOrdering AO,
const Expr *
X,
6581 "Update expr in 'atomic update' must be a binary operator.");
6589 assert(
X->isLValue() &&
"X of 'omp atomic update' is not lvalue");
6596 auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](
RValue XRValue) {
6602 XLValue, ExprRValue, BOUE->getOpcode(),
IsXLHSInRHSPart, AO, Loc, Gen);
6609 case llvm::AtomicOrdering::Release:
6610 case llvm::AtomicOrdering::AcquireRelease:
6611 case llvm::AtomicOrdering::SequentiallyConsistent:
6613 llvm::AtomicOrdering::Release);
6615 case llvm::AtomicOrdering::Acquire:
6616 case llvm::AtomicOrdering::Monotonic:
6618 case llvm::AtomicOrdering::NotAtomic:
6619 case llvm::AtomicOrdering::Unordered:
6620 llvm_unreachable(
"Unexpected ordering.");
6638 llvm_unreachable(
"Must be a scalar or complex.");
6642 llvm::AtomicOrdering AO,
6647 assert(
X->isLValue() &&
"X of 'omp atomic capture' is not lvalue");
6648 assert(
V->isLValue() &&
"V of 'omp atomic capture' is not lvalue");
6657 "Update expr in 'atomic capture' must be a binary operator.");
6668 NewVValType = XRValExpr->
getType();
6670 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
6679 XLValue, ExprRValue, BOUE->getOpcode(),
IsXLHSInRHSPart, AO, Loc, Gen);
6685 NewVVal = Res.second;
6696 NewVValType =
X->getType().getNonReferenceType();
6698 X->getType().getNonReferenceType(), Loc);
6699 auto &&Gen = [&NewVVal, ExprRValue](
RValue XRValue) {
6705 XLValue, ExprRValue, BO_Assign,
false, AO,
6726 case llvm::AtomicOrdering::Release:
6728 llvm::AtomicOrdering::Release);
6730 case llvm::AtomicOrdering::Acquire:
6732 llvm::AtomicOrdering::Acquire);
6734 case llvm::AtomicOrdering::AcquireRelease:
6735 case llvm::AtomicOrdering::SequentiallyConsistent:
6737 CGF, {}, Loc, llvm::AtomicOrdering::AcquireRelease);
6739 case llvm::AtomicOrdering::Monotonic:
6741 case llvm::AtomicOrdering::NotAtomic:
6742 case llvm::AtomicOrdering::Unordered:
6743 llvm_unreachable(
"Unexpected ordering.");
6749 CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO,
6753 llvm::OpenMPIRBuilder &OMPBuilder =
6756 OMPAtomicCompareOp Op;
6760 Op = OMPAtomicCompareOp::EQ;
6763 Op = OMPAtomicCompareOp::MIN;
6766 Op = OMPAtomicCompareOp::MAX;
6769 llvm_unreachable(
"unsupported atomic compare binary operator");
6773 Address XAddr = XLVal.getAddress();
6775 auto EmitRValueWithCastIfNeeded = [&CGF, Loc](
const Expr *
X,
const Expr *E) {
6780 if (NewE->
getType() ==
X->getType())
6785 llvm::Value *EVal = EmitRValueWithCastIfNeeded(
X, E);
6786 llvm::Value *DVal = D ? EmitRValueWithCastIfNeeded(
X, D) :
nullptr;
6787 if (
auto *CI = dyn_cast<llvm::ConstantInt>(EVal))
6788 EVal = CGF.
Builder.CreateIntCast(
6789 CI, XLVal.getAddress().getElementType(),
6792 if (
auto *CI = dyn_cast<llvm::ConstantInt>(DVal))
6793 DVal = CGF.
Builder.CreateIntCast(
6794 CI, XLVal.getAddress().getElementType(),
6797 llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{
6799 X->getType()->hasSignedIntegerRepresentation(),
6800 X->getType().isVolatileQualified()};
6801 llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal;
6805 VOpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
6806 V->getType()->hasSignedIntegerRepresentation(),
6807 V->getType().isVolatileQualified()};
6812 ROpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
6817 if (FailAO == llvm::AtomicOrdering::NotAtomic) {
6820 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
6821 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
6824 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
6825 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
6830 llvm::AtomicOrdering AO,
6851 case OMPC_compare: {
6857 llvm_unreachable(
"Clause is not allowed in 'omp atomic'.");
6862 llvm::AtomicOrdering AO =
CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
6864 llvm::AtomicOrdering FailAO = llvm::AtomicOrdering::NotAtomic;
6865 bool MemOrderingSpecified =
false;
6867 AO = llvm::AtomicOrdering::SequentiallyConsistent;
6868 MemOrderingSpecified =
true;
6870 AO = llvm::AtomicOrdering::AcquireRelease;
6871 MemOrderingSpecified =
true;
6873 AO = llvm::AtomicOrdering::Acquire;
6874 MemOrderingSpecified =
true;
6876 AO = llvm::AtomicOrdering::Release;
6877 MemOrderingSpecified =
true;
6879 AO = llvm::AtomicOrdering::Monotonic;
6880 MemOrderingSpecified =
true;
6882 llvm::SmallSet<OpenMPClauseKind, 2> KindsEncountered;
6891 if (K == OMPC_seq_cst || K == OMPC_acq_rel || K == OMPC_acquire ||
6892 K == OMPC_release || K == OMPC_relaxed || K == OMPC_hint)
6895 KindsEncountered.insert(K);
6900 if (KindsEncountered.contains(OMPC_compare) &&
6901 KindsEncountered.contains(OMPC_capture))
6902 Kind = OMPC_compare;
6903 if (!MemOrderingSpecified) {
6904 llvm::AtomicOrdering DefaultOrder =
6905 CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
6906 if (DefaultOrder == llvm::AtomicOrdering::Monotonic ||
6907 DefaultOrder == llvm::AtomicOrdering::SequentiallyConsistent ||
6908 (DefaultOrder == llvm::AtomicOrdering::AcquireRelease &&
6909 Kind == OMPC_capture)) {
6911 }
else if (DefaultOrder == llvm::AtomicOrdering::AcquireRelease) {
6912 if (Kind == OMPC_unknown || Kind == OMPC_update || Kind == OMPC_write) {
6913 AO = llvm::AtomicOrdering::Release;
6914 }
else if (Kind == OMPC_read) {
6915 assert(Kind == OMPC_read &&
"Unexpected atomic kind.");
6916 AO = llvm::AtomicOrdering::Acquire;
6921 if (KindsEncountered.contains(OMPC_compare) &&
6922 KindsEncountered.contains(OMPC_fail)) {
6923 Kind = OMPC_compare;
6924 const auto *FailClause = S.getSingleClause<
OMPFailClause>();
6927 if (FailParameter == llvm::omp::OMPC_relaxed)
6928 FailAO = llvm::AtomicOrdering::Monotonic;
6929 else if (FailParameter == llvm::omp::OMPC_acquire)
6930 FailAO = llvm::AtomicOrdering::Acquire;
6931 else if (FailParameter == llvm::omp::OMPC_seq_cst)
6932 FailAO = llvm::AtomicOrdering::SequentiallyConsistent;
6939 S.getV(), S.getR(), S.getExpr(), S.getUpdateExpr(),
6940 S.getD(), S.getCondExpr(), S.isXLHSInRHSPart(),
6941 S.isFailOnly(), S.getBeginLoc());
6952 OMPLexicalScope
Scope(CGF, S, OMPD_target);
6955 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
6961 llvm::Function *Fn =
nullptr;
6962 llvm::Constant *FnID =
nullptr;
6964 const Expr *IfCond =
nullptr;
6966 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
6967 if (
C->getNameModifier() == OMPD_unknown ||
6968 C->getNameModifier() == OMPD_target) {
6969 IfCond =
C->getCondition();
6975 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device(
6978 Device.setPointerAndInt(
C->getDevice(),
C->getModifier());
6983 bool IsOffloadEntry =
true;
6987 IsOffloadEntry =
false;
6990 IsOffloadEntry =
false;
6992 if (
CGM.
getLangOpts().OpenMPOffloadMandatory && !IsOffloadEntry) {
6996 assert(CGF.
CurFuncDecl &&
"No parent declaration for target region!");
6997 StringRef ParentName;
7000 if (
const auto *D = dyn_cast<CXXConstructorDecl>(CGF.
CurFuncDecl))
7002 else if (
const auto *D = dyn_cast<CXXDestructorDecl>(CGF.
CurFuncDecl))
7011 OMPLexicalScope
Scope(CGF, S, OMPD_task);
7012 auto &&SizeEmitter =
7015 if (IsOffloadEntry) {
7016 OMPLoopScope(CGF, D);
7018 llvm::Value *NumIterations = CGF.
EmitScalarExpr(D.getNumIterations());
7019 NumIterations = CGF.
Builder.CreateIntCast(NumIterations, CGF.
Int64Ty,
7021 return NumIterations;
7039 CGF.
EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
7044 StringRef ParentName,
7050 llvm::Constant *
Addr;
7052 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7054 assert(Fn &&
Addr &&
"Target device function emission failed.");
7068 const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams);
7069 llvm::Function *OutlinedFn =
7077 const Expr *NumTeams = NT ? NT->getNumTeams().front() :
nullptr;
7078 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() :
nullptr;
7084 OMPTeamsScope
Scope(CGF, S);
7100 CGF.
EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt());
7105 [](CodeGenFunction &) {
return nullptr; });
7110 auto *CS = S.getCapturedStmt(OMPD_teams);
7137 llvm::Constant *
Addr;
7139 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7141 assert(Fn &&
Addr &&
"Target device function emission failed.");
7183 llvm::Constant *
Addr;
7185 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7187 assert(Fn &&
Addr &&
"Target device function emission failed.");
7229 llvm::Constant *
Addr;
7231 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7233 assert(Fn &&
Addr &&
"Target device function emission failed.");
7247 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7252 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7264 [](CodeGenFunction &) {
return nullptr; });
7269 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7274 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7286 [](CodeGenFunction &) {
return nullptr; });
7291 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7297 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7309 [](CodeGenFunction &) {
return nullptr; });
7314 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7320 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7327 CGF, OMPD_distribute, CodeGenDistribute,
false);
7333 [](CodeGenFunction &) {
return nullptr; });
7337 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7338 llvm::Value *
Device =
nullptr;
7339 llvm::Value *NumDependences =
nullptr;
7340 llvm::Value *DependenceList =
nullptr;
7348 if (!
Data.Dependences.empty()) {
7350 std::tie(NumDependences, DependenciesArray) =
7351 CGM.getOpenMPRuntime().emitDependClause(*
this,
Data.Dependences,
7360 "OMPNowaitClause clause is used separately in OMPInteropDirective.");
7363 if (!ItOMPInitClause.empty()) {
7366 llvm::Value *InteropvarPtr =
7368 llvm::omp::OMPInteropType InteropType =
7369 llvm::omp::OMPInteropType::Unknown;
7370 if (
C->getIsTarget()) {
7371 InteropType = llvm::omp::OMPInteropType::Target;
7373 assert(
C->getIsTargetSync() &&
7374 "Expected interop-type target/targetsync");
7375 InteropType = llvm::omp::OMPInteropType::TargetSync;
7377 OMPBuilder.createOMPInteropInit(
Builder, InteropvarPtr, InteropType,
7378 Device, NumDependences, DependenceList,
7379 Data.HasNowaitClause);
7383 if (!ItOMPDestroyClause.empty()) {
7386 llvm::Value *InteropvarPtr =
7388 OMPBuilder.createOMPInteropDestroy(
Builder, InteropvarPtr,
Device,
7389 NumDependences, DependenceList,
7390 Data.HasNowaitClause);
7393 auto ItOMPUseClause = S.getClausesOfKind<
OMPUseClause>();
7394 if (!ItOMPUseClause.empty()) {
7397 llvm::Value *InteropvarPtr =
7399 OMPBuilder.createOMPInteropUse(
Builder, InteropvarPtr,
Device,
7400 NumDependences, DependenceList,
7401 Data.HasNowaitClause);
7423 CGF, OMPD_distribute, CodeGenDistribute,
false);
7442 llvm::Constant *
Addr;
7444 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7446 assert(Fn &&
Addr &&
"Target device function emission failed.");
7475 CGF, OMPD_distribute, CodeGenDistribute,
false);
7494 llvm::Constant *
Addr;
7496 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7498 assert(Fn &&
Addr &&
"Target device function emission failed.");
7511 CGM.getOpenMPRuntime().emitCancellationPointCall(*
this, S.getBeginLoc(),
7516 const Expr *IfCond =
nullptr;
7517 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7518 if (
C->getNameModifier() == OMPD_unknown ||
7519 C->getNameModifier() == OMPD_cancel) {
7520 IfCond =
C->getCondition();
7524 if (
CGM.getLangOpts().OpenMPIRBuilder) {
7525 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7531 llvm::Value *IfCondition =
nullptr;
7535 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
7537 return Builder.restoreIP(AfterIP);
7541 CGM.getOpenMPRuntime().emitCancelCall(*
this, S.getBeginLoc(), IfCond,
7547 if (Kind == OMPD_parallel || Kind == OMPD_task ||
7548 Kind == OMPD_target_parallel || Kind == OMPD_taskloop ||
7549 Kind == OMPD_master_taskloop || Kind == OMPD_parallel_master_taskloop)
7551 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
7552 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
7553 Kind == OMPD_distribute_parallel_for ||
7554 Kind == OMPD_target_parallel_for ||
7555 Kind == OMPD_teams_distribute_parallel_for ||
7556 Kind == OMPD_target_teams_distribute_parallel_for);
7557 return OMPCancelStack.getExitBlock();
7562 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7563 CaptureDeviceAddrMap) {
7564 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7565 for (
const Expr *OrigVarIt :
C.varlist()) {
7567 if (!Processed.insert(OrigVD).second)
7574 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7579 "Base should be the current struct!");
7580 MatchingVD = ME->getMemberDecl();
7585 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7586 if (InitAddrIt == CaptureDeviceAddrMap.end())
7594 Address(InitAddrIt->second, Ty,
7596 assert(IsRegistered &&
"firstprivate var already registered as private");
7604 while (
const auto *OASE = dyn_cast<ArraySectionExpr>(
Base))
7605 Base = OASE->getBase()->IgnoreParenImpCasts();
7606 while (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(
Base))
7607 Base = ASE->getBase()->IgnoreParenImpCasts();
7613 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7614 CaptureDeviceAddrMap) {
7615 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7616 for (
const Expr *Ref :
C.varlist()) {
7618 if (!Processed.insert(OrigVD).second)
7624 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7629 "Base should be the current struct!");
7630 MatchingVD = ME->getMemberDecl();
7635 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7636 if (InitAddrIt == CaptureDeviceAddrMap.end())
7642 Address(InitAddrIt->second, Ty,
7655 (void)PrivateScope.
addPrivate(OrigVD, PrivAddr);
7663 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
7664 CGM.getOpenMPRuntime().registerVTable(S);
7672 bool PrivatizeDevicePointers =
false;
7674 bool &PrivatizeDevicePointers;
7677 explicit DevicePointerPrivActionTy(
bool &PrivatizeDevicePointers)
7678 : PrivatizeDevicePointers(PrivatizeDevicePointers) {}
7679 void Enter(CodeGenFunction &CGF)
override {
7680 PrivatizeDevicePointers =
true;
7683 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
7686 auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7687 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
7691 auto &&PrivCodeGen = [&](CodeGenFunction &CGF,
PrePostActionTy &Action) {
7693 PrivatizeDevicePointers =
false;
7699 if (PrivatizeDevicePointers) {
7713 std::optional<OpenMPDirectiveKind> CaptureRegion;
7714 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
7717 for (
const Expr *E :
C->varlist()) {
7719 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
7723 for (
const Expr *E :
C->varlist()) {
7725 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
7729 CaptureRegion = OMPD_unknown;
7732 OMPLexicalScope
Scope(CGF, S, CaptureRegion);
7744 OMPLexicalScope
Scope(CGF, S);
7753 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
7759 const Expr *IfCond =
nullptr;
7761 IfCond =
C->getCondition();
7772 CGM.getOpenMPRuntime().emitTargetDataCalls(*
this, S, IfCond,
Device, RCG,
7780 if (
CGM.getLangOpts().OMPTargetTriples.empty())
7784 const Expr *IfCond =
nullptr;
7786 IfCond =
C->getCondition();
7793 OMPLexicalScope
Scope(*
this, S, OMPD_task);
7794 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
7801 if (
CGM.getLangOpts().OMPTargetTriples.empty())
7805 const Expr *IfCond =
nullptr;
7807 IfCond =
C->getCondition();
7814 OMPLexicalScope
Scope(*
this, S, OMPD_task);
7815 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
7822 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
7850 llvm::Constant *
Addr;
7852 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7854 assert(Fn &&
Addr &&
"Target device function emission failed.");
7874 CGF, OMPD_target_parallel_for, S.
hasCancel());
7890 llvm::Constant *
Addr;
7892 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7894 assert(Fn &&
Addr &&
"Target device function emission failed.");
7929 llvm::Constant *
Addr;
7931 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7933 assert(Fn &&
Addr &&
"Target device function emission failed.");
7955 const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop);
7958 OMPLexicalScope
Scope(*
this, S, OMPD_taskloop,
false);
7963 const Expr *IfCond =
nullptr;
7964 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7965 if (
C->getNameModifier() == OMPD_unknown ||
7966 C->getNameModifier() == OMPD_taskloop) {
7967 IfCond =
C->getCondition();
7980 Data.Schedule.setInt(
false);
7983 (Clause->getModifier() == OMPC_GRAINSIZE_strict) ?
true :
false;
7986 Data.Schedule.setInt(
true);
7989 (Clause->getModifier() == OMPC_NUMTASKS_strict) ?
true :
false;
8003 llvm::BasicBlock *ContBlock =
nullptr;
8004 OMPLoopScope PreInitScope(CGF, S);
8005 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
8009 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock(
"taskloop.if.then");
8010 ContBlock = CGF.createBasicBlock(
"taskloop.if.end");
8011 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
8012 CGF.getProfileCount(&S));
8013 CGF.EmitBlock(ThenBlock);
8014 CGF.incrementProfileCounter(&S);
8017 (void)CGF.EmitOMPLinearClauseInit(S);
8021 enum { LowerBound = 5, UpperBound, Stride, LastIter };
8023 auto *LBP = std::next(I, LowerBound);
8024 auto *UBP = std::next(I, UpperBound);
8025 auto *STP = std::next(I, Stride);
8026 auto *LIP = std::next(I, LastIter);
8034 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
8035 CGF.EmitOMPLinearClause(S, LoopScope);
8036 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
8039 const Expr *IVExpr = S.getIterationVariable();
8041 CGF.EmitVarDecl(*IVDecl);
8042 CGF.EmitIgnoredExpr(S.getInit());
8047 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
8050 CGF.EmitIgnoredExpr(S.getCalcLastIteration());
8054 OMPLexicalScope
Scope(CGF, S, OMPD_taskloop,
false);
8064 [&S](CodeGenFunction &CGF) {
8065 emitOMPLoopBodyWithStopPoint(CGF, S,
8066 CodeGenFunction::JumpDest());
8068 [](CodeGenFunction &) {});
8073 CGF.EmitBranch(ContBlock);
8074 CGF.EmitBlock(ContBlock,
true);
8077 if (HasLastprivateClause) {
8078 CGF.EmitOMPLastprivateClauseFinal(
8080 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
8081 CGF.GetAddrOfLocalVar(*LIP),
false,
8082 (*LIP)->getType(), S.getBeginLoc())));
8085 CGF.EmitOMPLinearClauseFinal(S, [LIP, &S](CodeGenFunction &CGF) {
8086 return CGF.
Builder.CreateIsNotNull(
8088 (*LIP)->
getType(), S.getBeginLoc()));
8091 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
8092 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
8094 auto &&
CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
8096 OMPLoopScope PreInitScope(CGF, S);
8097 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S,
8098 OutlinedFn, SharedsTy,
8099 CapturedStruct, IfCond,
Data);
8101 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
8107 CGM.getOpenMPRuntime().emitTaskgroupRegion(
8109 [&S, &BodyGen, &TaskGen, &
Data](CodeGenFunction &CGF,
8129 OMPLexicalScope
Scope(*
this, S);
8141 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8142 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8153 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8154 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8165 OMPLexicalScope
Scope(*
this, S);
8166 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8177 OMPLexicalScope
Scope(*
this, S);
8178 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8184 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8189 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8190 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8202 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8207 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8208 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8220 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8225 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8226 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8238 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8243 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8244 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8258 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8262 const Expr *IfCond =
nullptr;
8264 IfCond =
C->getCondition();
8271 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8272 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8282 BindKind =
C->getBindKind();
8285 case OMPC_BIND_parallel:
8287 case OMPC_BIND_teams:
8289 case OMPC_BIND_thread:
8300 const auto *ForS = dyn_cast<ForStmt>(CS);
8311 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
8312 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_loop,
CodeGen);
8338 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
8343 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
8355 [](CodeGenFunction &) {
return nullptr; });
8360 std::string StatusMsg,
8364 StatusMsg +=
": DEVICE";
8366 StatusMsg +=
": HOST";
8373 llvm::dbgs() << StatusMsg <<
": " <<
FileName <<
": " << LineNo <<
"\n";
8396 CGF, OMPD_distribute, CodeGenDistribute,
false);
8425 CGF, OMPD_distribute, CodeGenDistribute,
false);
8458 llvm::Constant *
Addr;
8460 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8462 assert(Fn &&
Addr &&
8463 "Target device function emission failed for 'target teams loop'.");
8474 CGF, OMPD_target_parallel_loop,
false);
8490 llvm::Constant *
Addr;
8492 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8494 assert(Fn &&
Addr &&
"Target device function emission failed.");
8509 if (
const auto *SD = dyn_cast<OMPScanDirective>(&D)) {
8513 if (!D.hasAssociatedStmt() || !D.getAssociatedStmt())
8520 for (
const Expr *Ref :
C->varlist()) {
8524 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
8527 if (!CGF.LocalDeclMap.count(VD)) {
8539 if (
const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
8540 for (
const Expr *E : LD->counters()) {
8548 if (!CGF.LocalDeclMap.count(VD))
8553 if (!
C->getNumForLoops())
8555 for (
unsigned I = LD->getLoopsNumber(),
8556 E =
C->getLoopNumIterations().size();
8558 if (
const auto *VD = dyn_cast<OMPCapturedExprDecl>(
8561 if (!CGF.LocalDeclMap.count(VD))
8568 CGF.
EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
8571 if (D.getDirectiveKind() == OMPD_atomic ||
8572 D.getDirectiveKind() == OMPD_critical ||
8573 D.getDirectiveKind() == OMPD_section ||
8574 D.getDirectiveKind() == OMPD_master ||
8575 D.getDirectiveKind() == OMPD_masked ||
8576 D.getDirectiveKind() == OMPD_unroll ||
8577 D.getDirectiveKind() == OMPD_assume) {
8582 OMPSimdLexicalScope
Scope(*
this, D);
8583 CGM.getOpenMPRuntime().emitInlinedDirective(
8586 : D.getDirectiveKind(),
Defines the clang::ASTContext interface.
static bool isAllocatableDecl(const VarDecl *VD)
static const VarDecl * getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE)
static void emitTargetRegion(CodeGenFunction &CGF, const OMPTargetDirective &S, PrePostActionTy &Action)
static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S, PrePostActionTy &Action)
static const VarDecl * getBaseDecl(const Expr *Ref)
static void emitTargetTeamsGenericLoopRegionAsParallel(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsGenericLoopDirective &S)
static void emitOMPAtomicReadExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, const Expr *X, const Expr *V, SourceLocation Loc)
static void emitOMPAtomicCaptureExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, bool IsPostfixUpdate, const Expr *V, const Expr *X, const Expr *E, const Expr *UE, bool IsXLHSInRHSPart, SourceLocation Loc)
static void emitScanBasedDirective(CodeGenFunction &CGF, const OMPLoopDirective &S, llvm::function_ref< llvm::Value *(CodeGenFunction &)> NumIteratorsGen, llvm::function_ref< void(CodeGenFunction &)> FirstGen, llvm::function_ref< void(CodeGenFunction &)> SecondGen)
Emits the code for the directive with inscan reductions.
static void emitSimpleAtomicStore(CodeGenFunction &CGF, llvm::AtomicOrdering AO, LValue LVal, RValue RVal)
static bool isSupportedByOpenMPIRBuilder(const OMPTaskgroupDirective &T)
static Address castValueFromUintptr(CodeGenFunction &CGF, SourceLocation Loc, QualType DstType, StringRef Name, LValue AddrLV)
static 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 LValue EmitOMPHelperVar(CodeGenFunction &CGF, const DeclRefExpr *Helper)
Emit a helper variable and return corresponding lvalue.
static void emitOMPAtomicUpdateExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, const Expr *X, const Expr *E, const Expr *UE, bool IsXLHSInRHSPart, SourceLocation Loc)
static llvm::Value * convertToScalarValue(CodeGenFunction &CGF, RValue Val, QualType SrcType, QualType DestType, SourceLocation Loc)
static llvm::Function * emitOutlinedOrderedFunction(CodeGenModule &CGM, const CapturedStmt *S, const OMPExecutableDirective &D)
static void emitPreCond(CodeGenFunction &CGF, const OMPLoopDirective &S, const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount)
static std::pair< bool, RValue > emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X, RValue Update, BinaryOperatorKind BO, llvm::AtomicOrdering AO, bool IsXLHSInRHSPart)
static std::pair< LValue, LValue > emitDistributeParallelForInnerBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitTargetTeamsGenericLoopRegionAsDistribute(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsGenericLoopDirective &S)
static void emitTargetParallelRegion(CodeGenFunction &CGF, const OMPTargetParallelDirective &S, PrePostActionTy &Action)
static std::pair< llvm::Value *, llvm::Value * > emitDispatchForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S, Address LB, Address UB)
When dealing with dispatch schedules (e.g.
static void emitMaster(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitRestoreIP(CodeGenFunction &CGF, const T *C, llvm::OpenMPIRBuilder::InsertPointTy AllocaIP, llvm::OpenMPIRBuilder &OMPBuilder)
static void emitCommonOMPTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, const RegionCodeGenTy &CodeGen)
static void emitSimdlenSafelenClause(CodeGenFunction &CGF, const OMPExecutableDirective &D)
static void emitAlignedClause(CodeGenFunction &CGF, const OMPExecutableDirective &D)
static bool isSimdSupportedByOpenMPIRBuilder(const OMPLoopDirective &S)
static void emitCommonOMPParallelDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, const CodeGenBoundParametersTy &CodeGenBoundParameters)
static void applyConservativeSimdOrderedDirective(const Stmt &AssociatedStmt, LoopInfoStack &LoopStack)
static bool emitWorksharingDirective(CodeGenFunction &CGF, const OMPLoopDirective &S, bool HasCancel)
static void emitPostUpdateForReductionClause(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
static void emitEmptyOrdered(CodeGenFunction &, SourceLocation Loc, const unsigned IVSize, const bool IVSigned)
static void emitTargetTeamsLoopCodegenStatus(CodeGenFunction &CGF, std::string StatusMsg, const OMPExecutableDirective &D)
static bool isForSupportedByOpenMPIRBuilder(const OMPLoopDirective &S, bool HasCancel)
static RValue emitSimpleAtomicLoad(CodeGenFunction &CGF, llvm::AtomicOrdering AO, LValue LVal, SourceLocation Loc)
static std::pair< llvm::Value *, llvm::Value * > emitDistributeParallelForDispatchBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S, Address LB, Address UB)
if the 'for' loop has a dispatch schedule (e.g.
static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO, bool IsPostfixUpdate, const Expr *X, const Expr *V, const Expr *R, const Expr *E, const Expr *UE, const Expr *D, const Expr *CE, bool IsXLHSInRHSPart, bool IsFailOnly, SourceLocation Loc)
static CodeGenFunction::ComplexPairTy convertToComplexValue(CodeGenFunction &CGF, RValue Val, QualType SrcType, QualType DestType, SourceLocation Loc)
static ImplicitParamDecl * createImplicitFirstprivateForType(ASTContext &C, OMPTaskDataTy &Data, QualType Ty, CapturedDecl *CD, SourceLocation Loc)
static EmittedClosureTy emitCapturedStmtFunc(CodeGenFunction &ParentCGF, const CapturedStmt *S)
Emit a captured statement and return the function as well as its captured closure context.
static void emitOMPLoopBodyWithStopPoint(CodeGenFunction &CGF, const OMPLoopDirective &S, CodeGenFunction::JumpDest LoopExit)
static void emitOMPDistributeDirective(const OMPLoopDirective &S, CodeGenFunction &CGF, CodeGenModule &CGM)
static void emitOMPCopyinClause(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitTargetTeamsDistributeParallelForRegion(CodeGenFunction &CGF, const OMPTargetTeamsDistributeParallelForDirective &S, PrePostActionTy &Action)
static bool hasOrderedDirective(const Stmt *S)
static llvm::CallInst * emitCapturedStmtCall(CodeGenFunction &ParentCGF, EmittedClosureTy Cap, llvm::ArrayRef< llvm::Value * > Args)
Emit a call to a previously captured closure.
static void emitMasked(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitBody(CodeGenFunction &CGF, const Stmt *S, const Stmt *NextLoop, int MaxLevel, int Level=0)
static void emitOMPForDirective(const OMPLoopDirective &S, CodeGenFunction &CGF, CodeGenModule &CGM, bool HasCancel)
static void emitEmptyBoundParameters(CodeGenFunction &, const OMPExecutableDirective &, llvm::SmallVectorImpl< llvm::Value * > &)
static void emitTargetParallelForSimdRegion(CodeGenFunction &CGF, const OMPTargetParallelForSimdDirective &S, PrePostActionTy &Action)
static void emitOMPSimdDirective(const OMPLoopDirective &S, CodeGenFunction &CGF, CodeGenModule &CGM)
static void emitOMPAtomicCompareExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO, const Expr *X, const Expr *V, const Expr *R, const Expr *E, const Expr *D, const Expr *CE, bool IsXBinopExpr, bool IsPostfixUpdate, bool IsFailOnly, SourceLocation Loc)
std::pair< llvm::Function *, llvm::Value * > EmittedClosureTy
static OpenMPDirectiveKind getEffectiveDirectiveKind(const OMPExecutableDirective &S)
static void emitTargetTeamsRegion(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsDirective &S)
static void buildDependences(const OMPExecutableDirective &S, OMPTaskDataTy &Data)
static RValue convertToType(CodeGenFunction &CGF, RValue Value, QualType SourceType, QualType ResType, SourceLocation Loc)
static void emitScanBasedDirectiveDecls(CodeGenFunction &CGF, const OMPLoopDirective &S, llvm::function_ref< llvm::Value *(CodeGenFunction &)> NumIteratorsGen)
Emits internal temp array declarations for the directive with inscan reductions.
static void emitTargetTeamsDistributeParallelForSimdRegion(CodeGenFunction &CGF, const OMPTargetTeamsDistributeParallelForSimdDirective &S, PrePostActionTy &Action)
static void emitTargetTeamsDistributeSimdRegion(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsDistributeSimdDirective &S)
static llvm::MapVector< llvm::Value *, llvm::Value * > GetAlignedMapping(const OMPLoopDirective &S, CodeGenFunction &CGF)
static llvm::omp::ScheduleKind convertClauseKindToSchedKind(OpenMPScheduleClauseKind ScheduleClauseKind)
static void mapParam(CodeGenFunction &CGF, const DeclRefExpr *Helper, const ImplicitParamDecl *PVD, CodeGenFunction::OMPPrivateScope &Privates)
Emit a helper variable and return corresponding lvalue.
static void emitCommonOMPTeamsDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
static void emitTargetParallelGenericLoopRegion(CodeGenFunction &CGF, const OMPTargetParallelGenericLoopDirective &S, PrePostActionTy &Action)
static QualType getCanonicalParamType(ASTContext &C, QualType T)
static void emitCommonSimdLoop(CodeGenFunction &CGF, const OMPLoopDirective &S, const RegionCodeGenTy &SimdInitGen, const RegionCodeGenTy &BodyCodeGen)
static LValue createSectionLVal(CodeGenFunction &CGF, QualType Ty, const Twine &Name, llvm::Value *Init=nullptr)
static void emitOMPAtomicWriteExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, const Expr *X, const Expr *E, SourceLocation Loc)
static llvm::Function * emitOutlinedFunctionPrologue(CodeGenFunction &CGF, FunctionArgList &Args, llvm::MapVector< const Decl *, std::pair< const VarDecl *, Address > > &LocalAddrs, llvm::DenseMap< const Decl *, std::pair< const Expr *, llvm::Value * > > &VLASizes, llvm::Value *&CXXThisValue, const FunctionOptions &FO)
static void emitInnerParallelForWhenCombined(CodeGenFunction &CGF, const OMPLoopDirective &S, CodeGenFunction::JumpDest LoopExit)
static void emitTargetTeamsDistributeRegion(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsDistributeDirective &S)
This file defines OpenMP nodes for declarative directives.
static const Decl * getCanonicalDecl(const Decl *D)
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
Defines the PrettyStackTraceEntry class, which is used to make crashes give more contextual informati...
Defines the SourceManager interface.
This file defines OpenMP AST classes for executable directives and clauses.
This represents '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 '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 'pragma omp error' 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.
Represents the 'pragma omp interchange' loop transformation directive.
Stmt * getTransformedStmt() const
Gets the associated loops after the transformation.
This represents 'pragma omp interop' directive.
This represents 'pragma omp masked' directive.
This represents 'pragma omp masked taskloop' directive.
This represents 'pragma omp masked taskloop simd' directive.
This represents 'pragma omp master taskloop' directive.
This represents 'pragma omp master taskloop simd' directive.
This represents 'pragma omp parallel masked taskloop' directive.
This represents 'pragma omp parallel masked taskloop simd' directive.
This represents 'pragma omp parallel master taskloop' directive.
This represents 'pragma omp parallel master taskloop simd' directive.
Represents the 'pragma omp reverse' loop transformation directive.
Stmt * getTransformedStmt() const
Gets/sets the associated loops after the transformation, i.e.
This represents 'pragma omp scan' directive.
This represents the 'pragma omp stripe' loop transformation directive.
Stmt * getTransformedStmt() const
Gets/sets the associated loops after striping.
This represents 'pragma omp target data' directive.
This represents 'pragma omp target' directive.
This represents 'pragma omp target enter data' directive.
This represents 'pragma omp target exit data' directive.
This represents 'pragma omp target parallel' directive.
This represents 'pragma omp target parallel for' directive.
bool hasCancel() const
Return true if current directive has inner cancel directive.
This represents 'pragma omp target parallel for simd' directive.
This represents 'pragma omp target parallel loop' directive.
This represents 'pragma omp target simd' directive.
This represents 'pragma omp target teams' directive.
This represents 'pragma omp target teams distribute' combined directive.
This represents 'pragma omp target teams distribute parallel for' combined directive.
This represents 'pragma omp target teams distribute parallel for simd' combined directive.
This represents 'pragma omp target teams distribute simd' combined directive.
This represents 'pragma omp target teams loop' directive.
bool canBeParallelFor() const
Return true if current loop directive's associated loop can be a parallel for.
This represents 'pragma omp target update' directive.
This represents 'pragma omp taskloop' directive.
This represents 'pragma omp taskloop simd' directive.
This represents 'pragma omp teams' directive.
This represents 'pragma omp teams distribute' directive.
This represents 'pragma omp teams distribute parallel for' composite directive.
This represents 'pragma omp teams distribute parallel for simd' composite directive.
This represents 'pragma omp teams distribute simd' combined directive.
This represents 'pragma omp teams loop' directive.
This represents 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.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
TranslationUnitDecl * getTranslationUnitDecl() const
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
QualType getUIntPtrType() const
Return a type compatible with "uintptr_t" (C99 7.18.1.4), as defined by the target.
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
unsigned getOpenMPDefaultSimdAlign(QualType T) const
Get default simd alignment of the specified complete type in bits.
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
CanQualType getCanonicalTagType(const TagDecl *TD) const
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Represents an attribute applied to a statement.
ArrayRef< const Attr * > getAttrs() const
static BinaryOperator * Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, FPOptionsOverride FPFeatures)
Represents the body of a CapturedStmt, and serves as its DeclContext.
unsigned getContextParamPosition() const
static CapturedDecl * Create(ASTContext &C, DeclContext *DC, unsigned NumParams)
param_iterator param_end() const
Retrieve an iterator one past the last parameter decl.
param_iterator param_begin() const
Retrieve an iterator pointing to the first parameter decl.
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
ImplicitParamDecl * getParam(unsigned i) const
This captures a statement into a function.
SourceLocation getEndLoc() const LLVM_READONLY
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
const RecordDecl * getCapturedRecordDecl() const
Retrieve the record declaration for captured variables.
Stmt * getCapturedStmt()
Retrieve the statement being captured.
capture_init_iterator capture_init_begin()
Retrieve the first initialization argument.
SourceLocation getBeginLoc() const LLVM_READONLY
capture_init_iterator capture_init_end()
Retrieve the iterator pointing one past the last initialization argument.
Expr *const * const_capture_init_iterator
Const iterator that walks over the capture initialization arguments.
CharUnits - This is an opaque type for sizes expressed in character units.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
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="")
CGFunctionInfo - Class to encapsulate the information about a function definition.
Manages list of lastprivate conditional decls for the specified directive.
static LastprivateConditionalRAII disable(CodeGenFunction &CGF, const OMPExecutableDirective &S)
Manages list of nontemporal decls for the specified directive.
Struct that keeps all the relevant information that should be kept throughout a 'target data' region.
llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap
Map between the a declaration of a capture and the corresponding new llvm address where the runtime r...
Manages list of nontemporal decls for the specified directive.
virtual void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the task directive.
virtual llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST)
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
virtual void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr)
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
virtual void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, SourceLocation SeverityLoc=SourceLocation(), const Expr *Message=nullptr, SourceLocation MessageLoc=SourceLocation())
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_tid, kmp_int32 num_threads) ...
virtual Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal)
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
virtual void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc)
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
virtual void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars)
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
virtual const VarDecl * translateParameter(const FieldDecl *FD, const VarDecl *NativeParam) const
Translates the native parameter of outlined function if this is required for target.
virtual llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP teams directive D.
virtual void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef< Expr * > NumIterations)
Emit initialization for doacross loop nesting support.
virtual void adjustTargetSpecificDataForLambdas(CodeGenFunction &CGF, const OMPExecutableDirective &D) const
Adjust some parameters for the target-based directives, like addresses of the variables captured by r...
virtual Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const
Gets the address of the native argument basing on the address of the target-specific parameter.
virtual void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc)
Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32global_tid, kmp_int32 num_teams,...
virtual llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data)
Emit a code for initialization of task reduction clause.
virtual void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO)
Emit flush of the variables specified in 'omp flush' directive.
virtual void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc)
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32global_tid, int proc_bind) to generate...
virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false)
Emit an implicit/explicit barrier for OpenMP threads.
virtual void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values)
virtual void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind)
Call the appropriate runtime routine to notify that we finished all the work with current loop.
void emitIfClause(CodeGenFunction &CGF, const Expr *Cond, const RegionCodeGenTy &ThenGen, const RegionCodeGenTy &ElseGen)
Emits code for OpenMP 'if' clause using specified CodeGen function.
virtual llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP parallel directive D.
virtual void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values)
Call the appropriate runtime routine to initialize it before start of loop.
virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static non-chunked.
virtual void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc)
Emits a master region.
virtual void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Required to resolve existing problems in the runtime.
virtual void checkAndEmitLastprivateConditional(CodeGenFunction &CGF, const Expr *LHS)
Checks if the provided LVal is lastprivate conditional and emits the code to update the value of the ...
llvm::OpenMPIRBuilder & getOMPBuilder()
virtual void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Emit outilined function for 'target' directive.
virtual void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned)
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
virtual void checkAndEmitSharedLastprivateConditional(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::DenseSet< CanonicalDeclPtr< const VarDecl > > &IgnoredDecls)
Checks if the lastprivate conditional was updated in inner region and writes the value.
virtual void emitInlinedDirective(CodeGenFunction &CGF, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool HasCancel=false)
Emit code for the directive that does not require outlining.
virtual bool isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static chunked.
virtual void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Emit the target offloading code associated with D.
virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const
Check if the specified ScheduleKind is dynamic.
virtual void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr)
Emits a masked region.
virtual void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues)
Call the appropriate runtime routine to initialize it before start of loop.
Address getAllocatedAddress() const
Returns the raw, allocated address, which is not necessarily the address of the object itself.
API for captured statement code generation.
virtual const FieldDecl * lookup(const VarDecl *VD) const
Lookup the captured field decl for a variable.
RAII for correct setting/restoring of CapturedStmtInfo.
LValue getReferenceLValue(CodeGenFunction &CGF, const Expr *RefExpr) const
void ForceCleanup()
Force the emission of cleanups now, instead of waiting until this object is destroyed.
RAII for preserving necessary info during inlined region body codegen.
Cleanup action for allocate support.
RAII for preserving necessary info during Outlined region body codegen.
Controls insertion of cancellation exit blocks in worksharing constructs.
Save/restore original map of previously emitted local vars in case when we need to duplicate emission...
The class used to assign some variables some temporarily addresses.
bool apply(CodeGenFunction &CGF)
Applies new addresses to the list of the variables.
void restore(CodeGenFunction &CGF)
Restores original addresses of the variables.
bool setVarAddr(CodeGenFunction &CGF, const VarDecl *LocalVD, Address TempAddr)
Sets the address of the variable LocalVD to be TempAddr in function CGF.
The scope used to remap some variables as private in the OpenMP loop body (or other captured region e...
void restoreMap()
Restore all mapped variables w/o clean up.
bool Privatize()
Privatizes local variables previously registered as private.
bool addPrivate(const VarDecl *LocalVD, Address Addr)
Registers LocalVD variable as a private with Addr as the address of the corresponding private variabl...
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
Manages parent directive for scan directives.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
void ForceCleanup(std::initializer_list< llvm::Value ** > ValuesToReload={})
Force the emission of cleanups now, instead of waiting until this object is destroyed.
bool requiresCleanups() const
Determine whether this scope requires any cleanups.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void EmitOMPParallelMaskedTaskLoopDirective(const OMPParallelMaskedTaskLoopDirective &S)
void EmitOMPParallelMaskedDirective(const OMPParallelMaskedDirective &S)
void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S)
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr, const VarDecl *ConditionalDecl=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
void EmitOMPLastprivateClauseFinal(const OMPExecutableDirective &D, bool NoFinals, llvm::Value *IsLastIterCond=nullptr)
Emit final copying of lastprivate values to original variables at the end of the worksharing or simd ...
void processInReduction(const OMPExecutableDirective &S, OMPTaskDataTy &Data, CodeGenFunction &CGF, const CapturedStmt *CS, OMPPrivateScope &Scope)
JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target)
The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...
void EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S)
void emitOMPSimpleStore(LValue LVal, RValue RVal, QualType RValTy, SourceLocation Loc)
static void EmitOMPTargetParallelDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelDirective &S)
void EmitOMPCanonicalLoop(const OMPCanonicalLoop *S)
Emit an OMPCanonicalLoop using the OpenMPIRBuilder.
void EmitOMPGenericLoopDirective(const OMPGenericLoopDirective &S)
void EmitOMPScanDirective(const OMPScanDirective &S)
static bool hasScalarEvaluationKind(QualType T)
llvm::function_ref< std::pair< llvm::Value *, llvm::Value * >(CodeGenFunction &, const OMPExecutableDirective &S, Address LB, Address UB)> CodeGenDispatchBoundsTy
LValue InitCapturedStruct(const CapturedStmt &S)
CGCapturedStmtInfo * CapturedStmtInfo
void EmitOMPDistributeDirective(const OMPDistributeDirective &S)
void EmitOMPParallelForDirective(const OMPParallelForDirective &S)
void EmitOMPMasterDirective(const OMPMasterDirective &S)
void EmitOMPParallelMasterTaskLoopSimdDirective(const OMPParallelMasterTaskLoopSimdDirective &S)
void EmitOMPSimdInit(const OMPLoopDirective &D)
Helpers for the OpenMP loop directives.
const OMPExecutableDirective * OMPParentLoopDirectiveForScan
Parent loop-based directive for scan directive.
void EmitOMPFlushDirective(const OMPFlushDirective &S)
static void EmitOMPTargetDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetDirective &S)
Emit device code for the target directive.
bool EmitOMPFirstprivateClause(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
void EmitOMPTaskgroupDirective(const OMPTaskgroupDirective &S)
void EmitOMPTargetTeamsDistributeParallelForSimdDirective(const OMPTargetTeamsDistributeParallelForSimdDirective &S)
static void EmitOMPTargetTeamsDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDirective &S)
Emit device code for the target teams directive.
void EmitOMPReductionClauseInit(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope, bool ForInscan=false)
Emit initial code for reduction variables.
void EmitOMPDistributeSimdDirective(const OMPDistributeSimdDirective &S)
void EmitAutoVarDecl(const VarDecl &D)
EmitAutoVarDecl - Emit an auto variable declaration.
static void EmitOMPTargetTeamsDistributeDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeDirective &S)
Emit device code for the target teams distribute directive.
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 EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
void EmitOMPReductionClauseFinal(const OMPExecutableDirective &D, const OpenMPDirectiveKind ReductionKind)
Emit final update of reduction values to original variables at the end of the directive.
void EmitOMPLoopBody(const OMPLoopDirective &D, JumpDest LoopExit)
Helper for the OpenMP loop directives.
void EmitOMPScopeDirective(const OMPScopeDirective &S)
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
llvm::AssertingVH< llvm::Instruction > AllocaInsertPt
AllocaInsertPoint - This is an instruction in the entry block before which we prefer to insert alloca...
void EmitAggregateAssign(LValue Dest, LValue Src, QualType EltTy)
Emit an aggregate assignment.
CodeGenFunction * ParentCGF
JumpDest ReturnBlock
ReturnBlock - Unified return block.
void EmitOMPTargetTeamsDistributeSimdDirective(const OMPTargetTeamsDistributeSimdDirective &S)
const llvm::function_ref< void(CodeGenFunction &, llvm::Function *, const OMPTaskDataTy &)> TaskGenTy
llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Location)
Converts Location to a DebugLoc, if debug information is enabled.
bool EmitOMPCopyinClause(const OMPExecutableDirective &D)
Emit code for copyin clause in D directive.
void EmitOMPLinearClause(const OMPLoopDirective &D, CodeGenFunction::OMPPrivateScope &PrivateScope)
Emit initial code for linear clauses.
llvm::BasicBlock * OMPBeforeScanBlock
void EmitOMPInterchangeDirective(const OMPInterchangeDirective &S)
void EmitOMPPrivateLoopCounters(const OMPLoopDirective &S, OMPPrivateScope &LoopScope)
Emit initial code for loop counters of loop-based directives.
void GenerateOpenMPCapturedVars(const CapturedStmt &S, SmallVectorImpl< llvm::Value * > &CapturedVars)
void EmitOMPDepobjDirective(const OMPDepobjDirective &S)
void EmitOMPMetaDirective(const OMPMetaDirective &S)
void EmitOMPCriticalDirective(const OMPCriticalDirective &S)
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
void EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S)
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
void EmitOMPCancelDirective(const OMPCancelDirective &S)
void EmitOMPBarrierDirective(const OMPBarrierDirective &S)
llvm::Value * EmitComplexToScalarConversion(ComplexPairTy Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified complex type to the specified destination type,...
void EmitOMPOrderedDirective(const OMPOrderedDirective &S)
bool EmitOMPWorksharingLoop(const OMPLoopDirective &S, Expr *EUB, const CodeGenLoopBoundsTy &CodeGenLoopBounds, const CodeGenDispatchBoundsTy &CGDispatchBounds)
Emit code for the worksharing loop-based directive.
LValue EmitOMPSharedLValue(const Expr *E)
Emits the lvalue for the expression with possibly captured variable.
llvm::CanonicalLoopInfo * EmitOMPCollapsedCanonicalLoopNest(const Stmt *S, int Depth)
Emit the Stmt S and return its topmost canonical loop, if any.
void EmitOMPSectionsDirective(const OMPSectionsDirective &S)
void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())
Emit code for the start of a function.
void EmitOMPInteropDirective(const OMPInteropDirective &S)
void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S)
void EmitOMPTargetParallelDirective(const OMPTargetParallelDirective &S)
void EmitOMPCopy(QualType OriginalType, Address DestAddr, Address SrcAddr, const VarDecl *DestVD, const VarDecl *SrcVD, const Expr *Copy)
Emit proper copying of data from one variable to another.
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
JumpDest getOMPCancelDestination(OpenMPDirectiveKind Kind)
void EmitOMPTargetParallelForSimdDirective(const OMPTargetParallelForSimdDirective &S)
void EmitOMPTargetParallelGenericLoopDirective(const OMPTargetParallelGenericLoopDirective &S)
Emit combined directive 'target parallel loop' as if its constituent constructs are 'target',...
void EmitOMPUseDeviceAddrClause(const OMPUseDeviceAddrClause &C, OMPPrivateScope &PrivateScope, const llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap)
void EmitOMPTeamsDistributeParallelForSimdDirective(const OMPTeamsDistributeParallelForSimdDirective &S)
void EmitOMPMaskedDirective(const OMPMaskedDirective &S)
llvm::Value * emitArrayLength(const ArrayType *arrayType, QualType &baseType, Address &addr)
emitArrayLength - Compute the length of an array, even if it's a VLA, and drill down to the base elem...
void EmitOMPAggregateAssign(Address DestAddr, Address SrcAddr, QualType OriginalType, const llvm::function_ref< void(Address, Address)> CopyGen)
Perform element by element copying of arrays with type OriginalType from SrcAddr to DestAddr using co...
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
void EmitOMPTeamsDistributeSimdDirective(const OMPTeamsDistributeSimdDirective &S)
RValue EmitAtomicLoad(LValue LV, SourceLocation SL, AggValueSlot Slot=AggValueSlot::ignored())
CGDebugInfo * getDebugInfo()
void EmitOMPDistributeLoop(const OMPLoopDirective &S, const CodeGenLoopTy &CodeGenLoop, Expr *IncExpr)
Emit code for the distribute loop-based directive.
void EmitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective &S)
void EmitOMPReverseDirective(const OMPReverseDirective &S)
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
void EmitOMPCancellationPointDirective(const OMPCancellationPointDirective &S)
void EmitOMPTargetTeamsDistributeParallelForDirective(const OMPTargetTeamsDistributeParallelForDirective &S)
void EmitOMPMaskedTaskLoopDirective(const OMPMaskedTaskLoopDirective &S)
llvm::BasicBlock * OMPScanDispatch
llvm::function_ref< std::pair< LValue, LValue >(CodeGenFunction &, const OMPExecutableDirective &S)> CodeGenLoopBoundsTy
void EmitOMPTargetExitDataDirective(const OMPTargetExitDataDirective &S)
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
void EmitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &S)
void EmitOMPMaskedTaskLoopSimdDirective(const OMPMaskedTaskLoopSimdDirective &S)
std::pair< bool, RValue > EmitOMPAtomicSimpleUpdateExpr(LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart, llvm::AtomicOrdering AO, SourceLocation Loc, const llvm::function_ref< RValue(RValue)> CommonGen)
Emit atomic update code for constructs: X = X BO E or X = E BO E.
VlaSizePair getVLASize(const VariableArrayType *vla)
Returns an LLVM value that corresponds to the size, in non-variably-sized elements,...
void EmitOMPParallelDirective(const OMPParallelDirective &S)
void EmitOMPTaskDirective(const OMPTaskDirective &S)
void EmitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective &S)
void EmitOMPDistributeParallelForDirective(const OMPDistributeParallelForDirective &S)
void EmitOMPAssumeDirective(const OMPAssumeDirective &S)
int ExpectedOMPLoopDepth
Number of nested loop to be consumed by the last surrounding loop-associated directive.
void EmitOMPPrivateClause(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
void EmitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &S)
ASTContext & getContext() const
void EmitStopPoint(const Stmt *S)
EmitStopPoint - Emit a debug stoppoint if we are emitting debug info.
void EmitOMPTargetUpdateDirective(const OMPTargetUpdateDirective &S)
llvm::Value * EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, AlignmentSource Source=AlignmentSource::Type, bool isNontemporal=false)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
void EmitOMPTargetTeamsGenericLoopDirective(const OMPTargetTeamsGenericLoopDirective &S)
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
void EmitAutoVarCleanups(const AutoVarEmission &emission)
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
SmallVector< llvm::CanonicalLoopInfo *, 4 > OMPLoopNestStack
List of recently emitted OMPCanonicalLoops.
void EmitOMPTeamsDistributeParallelForDirective(const OMPTeamsDistributeParallelForDirective &S)
llvm::AtomicRMWInst * emitAtomicRMWInst(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val, llvm::AtomicOrdering Order=llvm::AtomicOrdering::SequentiallyConsistent, llvm::SyncScope::ID SSID=llvm::SyncScope::System, const AtomicExpr *AE=nullptr)
Emit an atomicrmw instruction, and applying relevant metadata when applicable.
void EmitOMPFuseDirective(const OMPFuseDirective &S)
void EmitOMPTargetTeamsDistributeDirective(const OMPTargetTeamsDistributeDirective &S)
void EmitOMPUseDevicePtrClause(const OMPUseDevicePtrClause &C, OMPPrivateScope &PrivateScope, const llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap)
RValue EmitAnyExpr(const Expr *E, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
EmitAnyExpr - Emit code to compute the specified expression which can have any type.
void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs={})
EmitStmt - Emit the code for the statement.
llvm::DenseMap< const ValueDecl *, FieldDecl * > LambdaCaptureFields
void EmitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &S)
llvm::Type * ConvertTypeForMem(QualType T)
void EmitOMPInnerLoop(const OMPExecutableDirective &S, bool RequiresCleanup, const Expr *LoopCond, const Expr *IncExpr, const llvm::function_ref< void(CodeGenFunction &)> BodyGen, const llvm::function_ref< void(CodeGenFunction &)> PostIncGen)
Emit inner loop of the worksharing/simd construct.
void EmitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective &S)
static void EmitOMPTargetTeamsDistributeParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForDirective &S)
void EmitOMPTargetDirective(const OMPTargetDirective &S)
static void EmitOMPTargetParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForSimdDirective &S)
Emit device code for the target parallel for simd directive.
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
llvm::BasicBlock * OMPScanExitBlock
void EmitOMPTeamsDirective(const OMPTeamsDirective &S)
void EmitSimpleOMPExecutableDirective(const OMPExecutableDirective &D)
Emit simple code for OpenMP directives in Simd-only mode.
void EmitOMPErrorDirective(const OMPErrorDirective &S)
void EmitOMPTargetTaskBasedDirective(const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen, OMPTargetDataInfo &InputInfo)
void EmitOMPParallelMaskedTaskLoopSimdDirective(const OMPParallelMaskedTaskLoopSimdDirective &S)
void EmitOMPTargetTeamsDirective(const OMPTargetTeamsDirective &S)
void EmitOMPTargetDataDirective(const OMPTargetDataDirective &S)
Address GenerateCapturedStmtArgument(const CapturedStmt &S)
bool EmitOMPLastprivateClauseInit(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
Emit initial code for lastprivate variables.
static void EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForSimdDirective &S)
Emit device code for the target teams distribute parallel for simd directive.
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
llvm::Function * GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S, const OMPExecutableDirective &D)
void EmitOMPSimdDirective(const OMPSimdDirective &S)
RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
Address EmitLoadOfReference(LValue RefLVal, LValueBaseInfo *PointeeBaseInfo=nullptr, TBAAAccessInfo *PointeeTBAAInfo=nullptr)
void EmitOMPParallelGenericLoopDirective(const OMPLoopDirective &S)
void EmitOMPTargetSimdDirective(const OMPTargetSimdDirective &S)
void EmitOMPTeamsGenericLoopDirective(const OMPTeamsGenericLoopDirective &S)
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
bool EmitOMPLinearClauseInit(const OMPLoopDirective &D)
Emit initial code for linear variables.
static void EmitOMPTargetParallelGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelGenericLoopDirective &S)
Emit device code for the target parallel loop directive.
void EmitOMPUnrollDirective(const OMPUnrollDirective &S)
void EmitOMPStripeDirective(const OMPStripeDirective &S)
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitOMPSingleDirective(const OMPSingleDirective &S)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
llvm::function_ref< void(CodeGenFunction &, SourceLocation, const unsigned, const bool)> CodeGenOrderedTy
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
llvm::Value * EmitFromMemory(llvm::Value *Value, QualType Ty)
EmitFromMemory - Change a scalar value from its memory representation to its value representation.
static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S)
Emit device code for the target simd directive.
llvm::Function * GenerateCapturedStmtFunction(const CapturedStmt &S)
Creates the outlined function for a CapturedStmt.
static void EmitOMPTargetParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForDirective &S)
Emit device code for the target parallel for directive.
uint64_t getProfileCount(const Stmt *S)
Get the profiler's count for the given statement.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)
ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant,...
static void EmitOMPTargetTeamsGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsGenericLoopDirective &S)
Emit device code for the target teams loop directive.
void EmitOMPTileDirective(const OMPTileDirective &S)
void EmitDecl(const Decl &D, bool EvaluateConditionDecl=false)
EmitDecl - Emit a declaration.
void EmitOMPAtomicDirective(const OMPAtomicDirective &S)
llvm::BasicBlock * OMPAfterScanBlock
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
ConstantEmission tryEmitAsConstant(const DeclRefExpr *RefExpr)
Try to emit a reference to the given value without producing it as an l-value.
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
void EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst)
Store of global named registers are always calls to intrinsics.
void EmitOMPParallelMasterTaskLoopDirective(const OMPParallelMasterTaskLoopDirective &S)
void EmitOMPDistributeParallelForSimdDirective(const OMPDistributeParallelForSimdDirective &S)
void EmitOMPSectionDirective(const OMPSectionDirective &S)
void EnsureInsertPoint()
EnsureInsertPoint - Ensure that an insertion point is defined so that emitted IR has a place to go.
void EmitOMPForSimdDirective(const OMPForSimdDirective &S)
llvm::LLVMContext & getLLVMContext()
void 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.
ASTContext & getContext() const
const CodeGenOptions & getCodeGenOpts() const
StringRef getMangledName(GlobalDecl GD)
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
const CGFunctionInfo & arrangeDeviceKernelCallerDeclaration(QualType resultType, const FunctionArgList &args)
A device kernel caller function is an offload device entry point function with a target device depend...
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
llvm::Value * getPointer(CodeGenFunction &CGF) const
Address getAddress() const
void setAddress(Address address)
A stack of loop information corresponding to loop nesting levels.
void setVectorizeWidth(unsigned W)
Set the vectorize width for the next loop pushed.
void setParallel(bool Enable=true)
Set the next pushed loop as parallel.
void push(llvm::BasicBlock *Header, const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc)
Begin a new structured loop.
void setVectorizeEnable(bool Enable=true)
Set the next pushed loop 'vectorize.enable'.
A basic class for pre|post-action for advanced codegen sequence for OpenMP region.
virtual void Enter(CodeGenFunction &CGF)
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
static RValue getComplex(llvm::Value *V1, llvm::Value *V2)
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
std::pair< llvm::Value *, llvm::Value * > getComplexVal() const
getComplexVal - Return the real/imag components of this complex value.
An abstract representation of an aligned address.
llvm::PointerType * getType() const
Return the type of the pointer value.
llvm::Value * getPointer() const
Class intended to support codegen of all kind of the reduction clauses.
LValue getSharedLValue(unsigned N) const
Returns LValue for the reduction item.
void emitAggregateType(CodeGenFunction &CGF, unsigned N)
Emits the code for the variable-modified type, if required.
const VarDecl * getBaseDecl(unsigned N) const
Returns the base declaration of the reduction item.
void emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N)
Emits lvalue for the shared and original reduction item.
void emitInitialization(CodeGenFunction &CGF, unsigned N, Address PrivateAddr, Address SharedAddr, llvm::function_ref< bool(CodeGenFunction &)> DefaultInit)
Performs initialization of the private copy for the reduction item.
Address adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Adjusts PrivatedAddr for using instead of the original variable address in normal operations.
Class provides a way to call simple version of codegen for OpenMP region, or an advanced with possibl...
void setAction(PrePostActionTy &Action) const
Complex values, per C99 6.2.5p11.
CompoundStmt - This represents a group of statements like { stmt stmt }.
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
A reference to a declared variable, function, enum, etc.
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Decl - This represents one declaration (or definition), e.g.
SourceLocation getBodyRBrace() const
getBodyRBrace - Gets the right brace of the body, if a body exists.
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
SourceLocation getLocation() const
The name of a declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreImplicitAsWritten() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
Represents a function declaration or definition.
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin=false, bool isInlineSpecified=false, bool hasWrittenPrototype=true, ConstexprSpecKind ConstexprKind=ConstexprSpecKind::Unspecified, const AssociatedConstraint &TrailingRequiresClause={})
GlobalDecl - represents a global declaration.
One of these records is kept for each identifier that is lexed.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, 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 represents 'acq_rel' clause in the 'pragma omp atomic|flush' directives.
This represents 'acquire' clause in the 'pragma omp atomic|flush' directives.
This represents clause 'aligned' in the 'pragma omp ...' directives.
This represents 'bind' clause in the 'pragma omp ...' directives.
static OMPClauseWithPreInit * get(OMPClause *C)
This is a basic class for representing single OpenMP clause.
This represents clause 'copyin' in the 'pragma omp ...' directives.
This represents clause 'copyprivate' in the 'pragma omp ...' directives.
This represents implicit clause 'depend' for the 'pragma omp task' directive.
This represents implicit clause 'depobj' for the 'pragma omp depobj' directive.
This 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 the 'doacross' clause for the 'pragma omp ordered' directive.
This represents 'fail' clause in the 'pragma omp atomic' directive.
This represents 'filter' clause in the 'pragma omp ...' directive.
This represents 'final' clause in the 'pragma omp ...' directive.
This represents clause 'firstprivate' in the 'pragma omp ...' directives.
This represents implicit clause 'flush' for the 'pragma omp flush' directive.
Representation of the 'full' clause of the 'pragma omp unroll' directive.
This represents 'grainsize' clause in the 'pragma omp ...' directive.
This represents 'hint' clause in the 'pragma omp ...' directive.
This represents 'if' clause in the 'pragma omp ...' directive.
This represents clause 'in_reduction' in the 'pragma omp task' directives.
This represents clause 'inclusive' in the 'pragma omp scan' directive.
This represents the 'init' clause in 'pragma omp ...' directives.
This represents clause 'lastprivate' in the 'pragma omp ...' directives.
This represents clause 'linear' in the 'pragma omp ...' directives.
This represents the 'message' clause in the 'pragma omp error' and the 'pragma omp parallel' directiv...
Expr * getMessageString() const
Returns message string of the clause.
This represents 'nogroup' clause in the 'pragma omp ...' directive.
This represents 'nowait' 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 'num_threads' clause in the 'pragma omp ...' directive.
This represents 'order' clause in the 'pragma omp ...' directive.
This represents 'ordered' clause in the 'pragma omp ...' directive.
Representation of the 'partial' clause of the 'pragma omp unroll' directive.
This represents 'priority' clause in the 'pragma omp ...' directive.
This represents clause 'private' in the 'pragma omp ...' directives.
This represents 'proc_bind' clause in the 'pragma omp ...' directive.
This represents clause 'reduction' in the 'pragma omp ...' directives.
This represents 'relaxed' clause in the 'pragma omp atomic' directives.
This represents 'release' clause in the 'pragma omp atomic|flush' directives.
This represents 'simd' clause in the 'pragma omp ...' directive.
This represents 'safelen' clause in the 'pragma omp ...' directive.
This represents 'schedule' clause in the 'pragma omp ...' directive.
This represents 'seq_cst' clause in the 'pragma omp atomic|flush' directives.
This represents the 'severity' clause in the 'pragma omp error' and the 'pragma omp parallel' directi...
OpenMPSeverityClauseKind getSeverityKind() const
Returns kind of the clause.
This represents 'simdlen' clause in the 'pragma omp ...' directive.
This represents clause 'task_reduction' in the 'pragma omp taskgroup' directives.
This represents 'thread_limit' clause in the 'pragma omp ...' directive.
This represents 'untied' clause in the 'pragma omp ...' directive.
This represents 'update' clause in the 'pragma omp atomic' 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.
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 isVolatileQualified() const
Determine whether this type is volatile-qualified.
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.
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.
SourceLocation getEnd() const
SourceLocation getBegin() const
Stmt - This represents one statement.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
SourceLocation getBeginLoc() const LLVM_READONLY
bool isPointerType() const
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isLValueReferenceType() const
bool isAnyComplexType() const
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
static UnaryOperator * Create(const ASTContext &C, Expr *input, Opcode opc, QualType type, ExprValueKind VK, ExprObjectKind OK, SourceLocation l, bool CanOverflow, FPOptionsOverride FPFeatures)
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
TLSKind getTLSKind() const
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
@ CInit
C-style initialization with assignment.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
const Expr * getInit() const
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
@ TLS_None
Not a TLS variable.
Represents a C array with a specified size that is not an integer-constant-expression.
Expr * getSizeExpr() const
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
bool Inc(InterpState &S, CodePtr OpPC, bool CanOverflow)
1) Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value increased by ...
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool needsTaskBasedThreadLimit(OpenMPDirectiveKind DKind)
Checks if the specified target directive, combined or not, needs task based thread_limit.
@ Ctor_Complete
Complete object ctor.
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.
bool IsXLHSInRHSPart
True if UE has the first form and false if the second.
bool IsPostfixUpdate
True if original value of 'x' must be stored in 'v', not an updated one.
@ Dtor_Complete
Complete object dtor.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of the composite or combined directives that need loop ...
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPNumThreadsClauseModifier
@ OMPC_NUMTHREADS_unknown
bool IsFailOnly
True if 'v' is updated only when the condition is false (compare capture only).
U cast(CodeGen::Address addr)
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
@ ThreadPrivateVar
Parameter for Thread private variable.
@ Other
Other implicit parameter.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
A jump destination is an abstract label, branching to which may require a jump out through normal cle...
llvm::BasicBlock * getBlock() const
static Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc)
Returns address of the threadprivate variable for the current thread.
llvm::OpenMPIRBuilder::InsertPointTy InsertPointTy
static void EmitOMPOutlinedRegionBody(CodeGenFunction &CGF, const Stmt *RegionBodyStmt, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Twine RegionName)
Emit the body of an OMP region that will be outlined in OpenMPIRBuilder::finalize().
static Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD)
Gets the OpenMP-specific address of the local variable /p VD.
static void EmitCaptureStmt(CodeGenFunction &CGF, InsertPointTy CodeGenIP, llvm::BasicBlock &FiniBB, llvm::Function *Fn, ArrayRef< llvm::Value * > Args)
static std::string getNameWithSeparators(ArrayRef< StringRef > Parts, StringRef FirstSeparator=".", StringRef Separator=".")
Get the platform-specific name separator.
static void FinalizeOMPRegion(CodeGenFunction &CGF, InsertPointTy IP)
Emit the Finalization for an OMP region.
static void EmitOMPInlinedRegionBody(CodeGenFunction &CGF, const Stmt *RegionBodyStmt, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Twine RegionName)
Emit the body of an OMP region.
unsigned NumberOfTargetItems
Address BasePointersArray
llvm::PointerType * VoidPtrTy
llvm::IntegerType * Int64Ty
llvm::IntegerType * SizeTy
SmallVector< const Expr *, 4 > DepExprs
EvalResult is a struct with detailed info about an evaluated expression.
Extra information about a function prototype.
Scheduling data for loop-based OpenMP directives.
OpenMPScheduleClauseModifier M2
OpenMPScheduleClauseModifier M1
OpenMPScheduleClauseKind Schedule