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)) {
154 (void)OMPLoopBasedDirective::doForAllLoops(
155 LD->getInnermostCapturedStmt()->getCapturedStmt(),
156 true, LD->getLoopsNumber(),
157 [&CGF](
unsigned Cnt,
const Stmt *CurStmt) {
158 if (const auto *CXXFor = dyn_cast<CXXForRangeStmt>(CurStmt)) {
159 if (const Stmt *Init = CXXFor->getInit())
161 CGF.EmitStmt(CXXFor->getRangeStmt());
162 CGF.EmitStmt(CXXFor->getBeginStmt());
163 CGF.EmitStmt(CXXFor->getEndStmt());
167 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
168 for (
const auto *E : LD->counters()) {
175 for (
const auto *
C : LD->getClausesOfKind<OMPPrivateClause>()) {
176 for (
const Expr *IRef :
C->varlist()) {
179 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
180 QualType OrigVDTy = OrigVD->getType().getNonReferenceType();
190 (void)PreCondVars.
apply(CGF);
191 PreInits = LD->getPreInits();
192 }
else if (
const auto *
Tile = dyn_cast<OMPTileDirective>(&S)) {
193 PreInits =
Tile->getPreInits();
194 }
else if (
const auto *Stripe = dyn_cast<OMPStripeDirective>(&S)) {
195 PreInits = Stripe->getPreInits();
196 }
else if (
const auto *Unroll = dyn_cast<OMPUnrollDirective>(&S)) {
197 PreInits = Unroll->getPreInits();
198 }
else if (
const auto *Reverse = dyn_cast<OMPReverseDirective>(&S)) {
199 PreInits = Reverse->getPreInits();
200 }
else if (
const auto *Interchange =
201 dyn_cast<OMPInterchangeDirective>(&S)) {
202 PreInits = Interchange->getPreInits();
204 llvm_unreachable(
"Unknown loop-based directive kind.");
206 doEmitPreinits(PreInits);
213 const Stmt *PreInits;
214 if (
const auto *Fuse = dyn_cast<OMPFuseDirective>(&S)) {
215 PreInits = Fuse->getPreInits();
218 "Unknown canonical loop sequence transform directive kind.");
220 doEmitPreinits(PreInits);
223 void doEmitPreinits(
const Stmt *PreInits) {
229 if (
auto *PreInitCompound = dyn_cast<CompoundStmt>(PreInits))
230 llvm::append_range(PreInitStmts, PreInitCompound->body());
232 PreInitStmts.push_back(PreInits);
234 for (
const Stmt *S : PreInitStmts) {
237 if (
auto *PreInitDecl = dyn_cast<DeclStmt>(S)) {
238 for (
Decl *I : PreInitDecl->decls())
250 emitPreInitStmt(CGF, S);
255 emitPreInitStmt(CGF, S);
260 CodeGenFunction::OMPPrivateScope InlinedShareds;
262 static bool isCapturedVar(CodeGenFunction &CGF,
const VarDecl *VD) {
270 OMPSimdLexicalScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
272 InlinedShareds(CGF) {
273 for (
const auto *
C : S.clauses()) {
274 if (const auto *CPI = OMPClauseWithPreInit::get(C)) {
275 if (const auto *PreInit =
276 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
277 for (const auto *I : PreInit->decls()) {
278 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
279 CGF.EmitVarDecl(cast<VarDecl>(*I));
281 CodeGenFunction::AutoVarEmission Emission =
282 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
283 CGF.EmitAutoVarCleanups(Emission);
287 }
else if (
const auto *UDP = dyn_cast<OMPUseDevicePtrClause>(
C)) {
288 for (
const Expr *E : UDP->varlist()) {
290 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
293 }
else if (
const auto *UDP = dyn_cast<OMPUseDeviceAddrClause>(
C)) {
294 for (
const Expr *E : UDP->varlist()) {
296 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
303 if (
const auto *TG = dyn_cast<OMPTaskgroupDirective>(&S)) {
304 if (
const Expr *E = TG->getReductionRef())
309 llvm::DenseSet<CanonicalDeclPtr<const Decl>> CopyArrayTemps;
310 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
311 if (C->getModifier() != OMPC_REDUCTION_inscan)
313 for (const Expr *E : C->copy_array_temps())
314 CopyArrayTemps.insert(cast<DeclRefExpr>(E)->getDecl());
316 const auto *CS = cast_or_null<CapturedStmt>(S.getAssociatedStmt());
319 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
320 auto *VD =
C.getCapturedVar();
321 if (CopyArrayTemps.contains(VD))
324 "Canonical decl must be captured.");
325 DeclRefExpr DRE(CGF.
getContext(),
const_cast<VarDecl *
>(VD),
326 isCapturedVar(CGF, VD) ||
328 InlinedShareds.isGlobalVarCaptured(VD)),
336 (void)InlinedShareds.Privatize();
347 if (Kind != OMPD_loop)
352 BindKind =
C->getBindKind();
355 case OMPC_BIND_parallel:
357 case OMPC_BIND_teams:
358 return OMPD_distribute;
359 case OMPC_BIND_thread:
371 if (
const auto *OrigDRE = dyn_cast<DeclRefExpr>(E)) {
372 if (
const auto *OrigVD = dyn_cast<VarDecl>(OrigDRE->getDecl())) {
373 OrigVD = OrigVD->getCanonicalDecl();
379 OrigDRE->getType(),
VK_LValue, OrigDRE->getExprLoc());
388 llvm::Value *Size =
nullptr;
389 auto SizeInChars =
C.getTypeSizeInChars(Ty);
390 if (SizeInChars.isZero()) {
398 SizeInChars =
C.getTypeSizeInChars(Ty);
399 if (SizeInChars.isZero())
400 return llvm::ConstantInt::get(
SizeTy, 0);
401 return Builder.CreateNUWMul(Size,
CGM.getSize(SizeInChars));
403 return CGM.getSize(SizeInChars);
413 I != E; ++I, ++CurField, ++CurCap) {
414 if (CurField->hasCapturedVLAType()) {
417 CapturedVars.push_back(Val);
418 }
else if (CurCap->capturesThis()) {
419 CapturedVars.push_back(CXXThisValue);
420 }
else if (CurCap->capturesVariableByCopy()) {
425 if (!CurField->getType()->isAnyPointerType()) {
429 Twine(CurCap->getCapturedVar()->getName(),
".casted"));
445 CapturedVars.push_back(CV);
447 assert(CurCap->capturesVariable() &&
"Expected capture by reference.");
468 if (T->isLValueReferenceType())
469 return C.getLValueReferenceType(
472 if (T->isPointerType())
475 if (
const auto *VLA = dyn_cast<VariableArrayType>(A))
477 if (!A->isVariablyModifiedType())
478 return C.getCanonicalType(T);
480 return C.getCanonicalParamType(T);
485struct FunctionOptions {
487 const CapturedStmt *S =
nullptr;
490 const bool UIntPtrCastRequired =
true;
493 const bool RegisterCastedArgsOnly =
false;
495 const StringRef FunctionName;
498 const bool IsDeviceKernel =
false;
499 explicit FunctionOptions(
const CapturedStmt *S,
bool UIntPtrCastRequired,
500 bool RegisterCastedArgsOnly, StringRef FunctionName,
501 SourceLocation Loc,
bool IsDeviceKernel)
502 : S(S), UIntPtrCastRequired(UIntPtrCastRequired),
503 RegisterCastedArgsOnly(UIntPtrCastRequired && RegisterCastedArgsOnly),
504 FunctionName(FunctionName), Loc(Loc), IsDeviceKernel(IsDeviceKernel) {}
510 llvm::MapVector<
const Decl *, std::pair<const VarDecl *, Address>>
512 llvm::DenseMap<
const Decl *, std::pair<const Expr *, llvm::Value *>>
514 llvm::Value *&CXXThisValue,
const FunctionOptions &FO) {
517 assert(CD->
hasBody() &&
"missing CapturedDecl body");
519 CXXThisValue =
nullptr;
531 if (!FO.UIntPtrCastRequired) {
551 if (FO.UIntPtrCastRequired &&
552 ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) ||
553 I->capturesVariableArrayType()))
556 if (I->capturesVariable() || I->capturesVariableByCopy()) {
557 CapVar = I->getCapturedVar();
559 }
else if (I->capturesThis()) {
562 assert(I->capturesVariableArrayType());
565 if (ArgType->isVariablyModifiedType())
572 }
else if (DebugFunctionDecl && (CapVar || I->capturesThis())) {
574 Ctx, DebugFunctionDecl,
575 CapVar ? CapVar->
getBeginLoc() : FD->getBeginLoc(),
576 CapVar ? CapVar->
getLocation() : FD->getLocation(), II, ArgType,
582 Args.emplace_back(Arg);
584 TargetArgs.emplace_back(
585 FO.UIntPtrCastRequired
606 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
610 F->setDoesNotThrow();
611 F->setDoesNotRecurse();
615 F->removeFnAttr(llvm::Attribute::NoInline);
616 F->addFnAttr(llvm::Attribute::AlwaysInline);
619 F->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
623 FO.UIntPtrCastRequired ? FO.Loc : FO.S->
getBeginLoc(),
624 FO.UIntPtrCastRequired ? FO.Loc
631 if (!FO.UIntPtrCastRequired && Args[Cnt] != TargetArgs[Cnt]) {
639 if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
640 const VarDecl *CurVD = I->getCapturedVar();
641 if (!FO.RegisterCastedArgsOnly)
642 LocalAddrs.insert({Args[Cnt], {CurVD, LocalAddr}});
650 if (FD->hasCapturedVLAType()) {
651 if (FO.UIntPtrCastRequired) {
654 Args[Cnt]->getName(), ArgLVal),
659 VLASizes.try_emplace(Args[Cnt], VAT->
getSizeExpr(), ExprArg);
660 }
else if (I->capturesVariable()) {
661 const VarDecl *Var = I->getCapturedVar();
663 Address ArgAddr = ArgLVal.getAddress();
664 if (ArgLVal.getType()->isLValueReferenceType()) {
667 assert(ArgLVal.getType()->isPointerType());
669 ArgAddr, ArgLVal.getType()->castAs<
PointerType>());
671 if (!FO.RegisterCastedArgsOnly) {
675 }
else if (I->capturesVariableByCopy()) {
676 assert(!FD->getType()->isAnyPointerType() &&
677 "Not expecting a captured pointer.");
678 const VarDecl *Var = I->getCapturedVar();
679 LocalAddrs.insert({Args[Cnt],
680 {Var, FO.UIntPtrCastRequired
682 CGF, I->getLocation(), FD->getType(),
683 Args[Cnt]->getName(), ArgLVal)
684 : ArgLVal.getAddress()}});
687 assert(I->capturesThis());
689 LocalAddrs.insert({Args[Cnt], {
nullptr, ArgLVal.getAddress()}});
703 "CapturedStmtInfo should be set when generating the captured function");
706 bool NeedWrapperFunction =
709 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs,
711 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes,
714 llvm::raw_svector_ostream Out(Buffer);
717 bool IsDeviceKernel =
CGM.getOpenMPRuntime().isGPU() &&
719 D.getCapturedStmt(OMPD_target) == &S;
720 CodeGenFunction WrapperCGF(
CGM,
true);
721 llvm::Function *WrapperF =
nullptr;
722 if (NeedWrapperFunction) {
725 FunctionOptions WrapperFO(&S,
true,
732 WrapperCGF.CXXThisValue, WrapperFO);
735 FunctionOptions FO(&S, !NeedWrapperFunction,
false,
736 Out.str(), Loc, !NeedWrapperFunction && IsDeviceKernel);
738 *
this, WrapperArgs, WrapperLocalAddrs, WrapperVLASizes, CXXThisValue, FO);
740 for (
const auto &LocalAddrPair : WrapperLocalAddrs) {
741 if (LocalAddrPair.second.first) {
742 LocalScope.addPrivate(LocalAddrPair.second.first,
743 LocalAddrPair.second.second);
746 (void)LocalScope.Privatize();
747 for (
const auto &VLASizePair : WrapperVLASizes)
748 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
751 LocalScope.ForceCleanup();
753 if (!NeedWrapperFunction)
757 WrapperF->removeFromParent();
758 F->getParent()->getFunctionList().insertAfter(F->getIterator(), WrapperF);
761 auto *PI = F->arg_begin();
762 for (
const auto *Arg : Args) {
764 auto I = LocalAddrs.find(Arg);
765 if (I != LocalAddrs.end()) {
768 I->second.first ? I->second.first->getType() : Arg->getType(),
774 auto EI = VLASizes.find(Arg);
775 if (EI != VLASizes.end()) {
787 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
803 llvm::Value *NumElements =
emitArrayLength(ArrayTy, ElementTy, DestAddr);
810 DestBegin, NumElements);
815 llvm::Value *IsEmpty =
816 Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arraycpy.isempty");
817 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
820 llvm::BasicBlock *EntryBB =
Builder.GetInsertBlock();
825 llvm::PHINode *SrcElementPHI =
826 Builder.CreatePHI(SrcBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
827 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
832 llvm::PHINode *DestElementPHI =
Builder.CreatePHI(
833 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
834 DestElementPHI->addIncoming(DestBegin, EntryBB);
840 CopyGen(DestElementCurrent, SrcElementCurrent);
843 llvm::Value *DestElementNext =
845 1,
"omp.arraycpy.dest.element");
846 llvm::Value *SrcElementNext =
848 1,
"omp.arraycpy.src.element");
851 Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
852 Builder.CreateCondBr(Done, DoneBB, BodyBB);
853 DestElementPHI->addIncoming(DestElementNext,
Builder.GetInsertBlock());
854 SrcElementPHI->addIncoming(SrcElementNext,
Builder.GetInsertBlock());
864 const auto *BO = dyn_cast<BinaryOperator>(
Copy);
865 if (BO && BO->getOpcode() == BO_Assign) {
874 DestAddr, SrcAddr, OriginalType,
902 bool DeviceConstTarget =
getLangOpts().OpenMPIsTargetDevice &&
904 bool FirstprivateIsLastprivate =
false;
905 llvm::DenseMap<const VarDecl *, OpenMPLastprivateModifier> Lastprivates;
906 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
907 for (
const auto *D :
C->varlist())
908 Lastprivates.try_emplace(
912 llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
917 bool MustEmitFirstprivateCopy =
918 CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown;
919 for (
const auto *
C : D.getClausesOfKind<OMPFirstprivateClause>()) {
920 const auto *IRef =
C->varlist_begin();
921 const auto *InitsRef =
C->inits().begin();
922 for (
const Expr *IInit :
C->private_copies()) {
924 bool ThisFirstprivateIsLastprivate =
925 Lastprivates.count(OrigVD->getCanonicalDecl()) > 0;
928 if (!MustEmitFirstprivateCopy && !ThisFirstprivateIsLastprivate && FD &&
930 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
931 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
938 if (DeviceConstTarget && OrigVD->getType().isConstant(
getContext()) &&
940 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
941 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
946 FirstprivateIsLastprivate =
947 FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate;
948 if (EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()).second) {
968 assert(!CE &&
"Expected non-constant firstprivate.");
975 if (
Type->isArrayType()) {
991 RunCleanupsScope InitScope(*this);
993 setAddrOfLocalVar(VDInit, SrcElement);
994 EmitAnyExprToMem(Init, DestElement,
995 Init->getType().getQualifiers(),
997 LocalDeclMap.erase(VDInit);
1008 setAddrOfLocalVar(VDInit, OriginalAddr);
1010 LocalDeclMap.erase(VDInit);
1012 if (ThisFirstprivateIsLastprivate &&
1013 Lastprivates[OrigVD->getCanonicalDecl()] ==
1014 OMPC_LASTPRIVATE_conditional) {
1019 (*IRef)->getExprLoc());
1020 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1024 LocalDeclMap.erase(VD);
1025 setAddrOfLocalVar(VD, VDAddr);
1027 IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1029 assert(IsRegistered &&
1030 "firstprivate var already registered as private");
1038 return FirstprivateIsLastprivate && !EmittedAsFirstprivate.empty();
1046 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
1047 for (
const auto *
C : D.getClausesOfKind<OMPPrivateClause>()) {
1048 auto IRef =
C->varlist_begin();
1049 for (
const Expr *IInit :
C->private_copies()) {
1051 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
1057 assert(IsRegistered &&
"private var already registered as private");
1073 llvm::DenseSet<const VarDecl *> CopiedVars;
1074 llvm::BasicBlock *CopyBegin =
nullptr, *CopyEnd =
nullptr;
1076 auto IRef =
C->varlist_begin();
1077 auto ISrcRef =
C->source_exprs().begin();
1078 auto IDestRef =
C->destination_exprs().begin();
1079 for (
const Expr *AssignOp :
C->assignment_ops()) {
1088 getContext().getTargetInfo().isTLSSupported()) {
1090 "Copyin threadprivates should have been captured!");
1094 LocalDeclMap.erase(VD);
1098 :
CGM.GetAddrOfGlobal(VD),
1099 CGM.getTypes().ConvertTypeForMem(VD->
getType()),
1104 if (CopiedVars.size() == 1) {
1110 auto *MasterAddrInt =
Builder.CreatePtrToInt(
1112 auto *PrivateAddrInt =
Builder.CreatePtrToInt(
1115 Builder.CreateICmpNE(MasterAddrInt, PrivateAddrInt), CopyBegin,
1121 const auto *DestVD =
1142 bool HasAtLeastOneLastprivate =
false;
1144 llvm::DenseSet<const VarDecl *> SIMDLCVs;
1147 for (
const Expr *
C : LoopDirective->counters()) {
1152 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1153 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1154 HasAtLeastOneLastprivate =
true;
1157 const auto *IRef =
C->varlist_begin();
1158 const auto *IDestRef =
C->destination_exprs().begin();
1159 for (
const Expr *IInit :
C->private_copies()) {
1165 if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) {
1166 const auto *DestVD =
1171 (*IRef)->getType(),
VK_LValue, (*IRef)->getExprLoc());
1176 if (IInit && !SIMDLCVs.count(OrigVD->getCanonicalDecl())) {
1179 if (
C->getKind() == OMPC_LASTPRIVATE_conditional) {
1180 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1182 setAddrOfLocalVar(VD, VDAddr);
1188 bool IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1189 assert(IsRegistered &&
1190 "lastprivate var already registered as private");
1198 return HasAtLeastOneLastprivate;
1203 llvm::Value *IsLastIterCond) {
1212 llvm::BasicBlock *ThenBB =
nullptr;
1213 llvm::BasicBlock *DoneBB =
nullptr;
1214 if (IsLastIterCond) {
1218 llvm::any_of(D.getClausesOfKind<OMPLastprivateClause>(),
1219 [](
const OMPLastprivateClause *
C) {
1220 return C->getKind() == OMPC_LASTPRIVATE_conditional;
1222 CGM.getOpenMPRuntime().emitBarrierCall(*
this, D.getBeginLoc(),
1229 Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB);
1232 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1233 llvm::DenseMap<const VarDecl *, const Expr *> LoopCountersAndUpdates;
1234 if (
const auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) {
1235 auto IC = LoopDirective->counters().begin();
1236 for (
const Expr *F : LoopDirective->finals()) {
1240 AlreadyEmittedVars.insert(D);
1242 LoopCountersAndUpdates[D] = F;
1246 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1247 auto IRef =
C->varlist_begin();
1248 auto ISrcRef =
C->source_exprs().begin();
1249 auto IDestRef =
C->destination_exprs().begin();
1250 for (
const Expr *AssignOp :
C->assignment_ops()) {
1251 const auto *PrivateVD =
1254 const auto *CanonicalVD = PrivateVD->getCanonicalDecl();
1255 if (AlreadyEmittedVars.insert(CanonicalVD).second) {
1259 if (
const Expr *FinalExpr = LoopCountersAndUpdates.lookup(CanonicalVD))
1263 const auto *DestVD =
1267 if (
const auto *RefTy = PrivateVD->getType()->getAs<
ReferenceType>())
1269 Builder.CreateLoad(PrivateAddr),
1270 CGM.getTypes().ConvertTypeForMem(RefTy->getPointeeType()),
1271 CGM.getNaturalTypeAlignment(RefTy->getPointeeType()));
1273 if (
C->getKind() == OMPC_LASTPRIVATE_conditional)
1274 CGM.getOpenMPRuntime().emitLastprivateConditionalFinalUpdate(
1276 (*IRef)->getExprLoc());
1279 EmitOMPCopy(
Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp);
1285 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
1305 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1306 if (ForInscan != (
C->getModifier() == OMPC_REDUCTION_inscan))
1308 Shareds.append(
C->varlist_begin(),
C->varlist_end());
1309 Privates.append(
C->privates().begin(),
C->privates().end());
1310 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1311 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1312 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1313 if (
C->getModifier() == OMPC_REDUCTION_task) {
1314 Data.ReductionVars.append(
C->privates().begin(),
C->privates().end());
1315 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
1316 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
1317 Data.ReductionOps.append(
C->reduction_ops().begin(),
1318 C->reduction_ops().end());
1319 TaskLHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1320 TaskRHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1325 auto *ILHS = LHSs.begin();
1326 auto *IRHS = RHSs.begin();
1328 for (
const Expr *IRef : Shareds) {
1336 [&Emission](CodeGenFunction &CGF) {
1337 CGF.EmitAutoVarInit(Emission);
1345 assert(IsRegistered &&
"private var already registered as private");
1353 if (isaOMPArraySectionExpr &&
Type->isVariablyModifiedType()) {
1358 }
else if ((isaOMPArraySectionExpr &&
Type->isScalarType()) ||
1376 PrivateScope.
addPrivate(LHSVD, OriginalAddr);
1387 if (!
Data.ReductionVars.empty()) {
1389 Data.IsReductionWithTaskMod =
true;
1391 llvm::Value *ReductionDesc =
CGM.getOpenMPRuntime().emitTaskReductionInit(
1392 *
this, D.getBeginLoc(), TaskLHSs, TaskRHSs,
Data);
1393 const Expr *TaskRedRef =
nullptr;
1404 case OMPD_parallel_for:
1407 case OMPD_parallel_master:
1411 case OMPD_parallel_sections:
1415 case OMPD_target_parallel:
1419 case OMPD_target_parallel_for:
1423 case OMPD_distribute_parallel_for:
1427 case OMPD_teams_distribute_parallel_for:
1429 .getTaskReductionRefExpr();
1431 case OMPD_target_teams_distribute_parallel_for:
1433 .getTaskReductionRefExpr();
1441 case OMPD_parallel_for_simd:
1443 case OMPD_taskyield:
1447 case OMPD_taskgroup:
1455 case OMPD_cancellation_point:
1457 case OMPD_target_data:
1458 case OMPD_target_enter_data:
1459 case OMPD_target_exit_data:
1461 case OMPD_taskloop_simd:
1462 case OMPD_master_taskloop:
1463 case OMPD_master_taskloop_simd:
1464 case OMPD_parallel_master_taskloop:
1465 case OMPD_parallel_master_taskloop_simd:
1466 case OMPD_distribute:
1467 case OMPD_target_update:
1468 case OMPD_distribute_parallel_for_simd:
1469 case OMPD_distribute_simd:
1470 case OMPD_target_parallel_for_simd:
1471 case OMPD_target_simd:
1472 case OMPD_teams_distribute:
1473 case OMPD_teams_distribute_simd:
1474 case OMPD_teams_distribute_parallel_for_simd:
1475 case OMPD_target_teams:
1476 case OMPD_target_teams_distribute:
1477 case OMPD_target_teams_distribute_parallel_for_simd:
1478 case OMPD_target_teams_distribute_simd:
1479 case OMPD_declare_target:
1480 case OMPD_end_declare_target:
1481 case OMPD_threadprivate:
1483 case OMPD_declare_reduction:
1484 case OMPD_declare_mapper:
1485 case OMPD_declare_simd:
1487 case OMPD_declare_variant:
1488 case OMPD_begin_declare_variant:
1489 case OMPD_end_declare_variant:
1492 llvm_unreachable(
"Unexpected directive with task reductions.");
1498 false, TaskRedRef->
getType());
1511 bool HasAtLeastOneReduction =
false;
1512 bool IsReductionWithTaskMod =
false;
1513 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1515 if (
C->getModifier() == OMPC_REDUCTION_inscan)
1517 HasAtLeastOneReduction =
true;
1518 Privates.append(
C->privates().begin(),
C->privates().end());
1519 LHSExprs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1520 RHSExprs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1521 IsPrivateVarReduction.append(
C->private_var_reduction_flags().begin(),
1522 C->private_var_reduction_flags().end());
1523 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1524 IsReductionWithTaskMod =
1525 IsReductionWithTaskMod ||
C->getModifier() == OMPC_REDUCTION_task;
1527 if (HasAtLeastOneReduction) {
1529 if (IsReductionWithTaskMod) {
1530 CGM.getOpenMPRuntime().emitTaskReductionFini(
1533 bool TeamsLoopCanBeParallel =
false;
1534 if (
auto *TTLD = dyn_cast<OMPTargetTeamsGenericLoopDirective>(&D))
1535 TeamsLoopCanBeParallel = TTLD->canBeParallelFor();
1536 bool WithNowait = D.getSingleClause<OMPNowaitClause>() ||
1538 TeamsLoopCanBeParallel || ReductionKind == OMPD_simd;
1539 bool SimpleReduction = ReductionKind == OMPD_simd;
1542 CGM.getOpenMPRuntime().emitReduction(
1543 *
this, D.getEndLoc(),
Privates, LHSExprs, RHSExprs, ReductionOps,
1544 {WithNowait, SimpleReduction, IsPrivateVarReduction, ReductionKind});
1553 llvm::BasicBlock *DoneBB =
nullptr;
1554 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1555 if (
const Expr *PostUpdate =
C->getPostUpdateExpr()) {
1557 if (llvm::Value *
Cond = CondGen(CGF)) {
1578 const OMPExecutableDirective &,
1579 llvm::SmallVectorImpl<llvm::Value *> &)>
1580 CodeGenBoundParametersTy;
1588 llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> PrivateDecls;
1589 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
1590 for (
const Expr *Ref :
C->varlist()) {
1591 if (!Ref->getType()->isScalarType())
1593 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1600 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
1601 for (
const Expr *Ref :
C->varlist()) {
1602 if (!Ref->getType()->isScalarType())
1604 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1611 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
1612 for (
const Expr *Ref :
C->varlist()) {
1613 if (!Ref->getType()->isScalarType())
1615 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1626 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
1627 for (
const Expr *Ref :
C->varlist()) {
1628 if (!Ref->getType()->isScalarType())
1630 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1637 CGF, S, PrivateDecls);
1643 const CodeGenBoundParametersTy &CodeGenBoundParameters) {
1644 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
1645 llvm::Value *NumThreads =
nullptr;
1654 llvm::Function *OutlinedFn =
1661 NumThreads = CGF.
EmitScalarExpr(NumThreadsClause->getNumThreads(),
1663 Modifier = NumThreadsClause->getModifier();
1664 if (
const auto *MessageClause = S.getSingleClause<OMPMessageClause>()) {
1665 Message = MessageClause->getMessageString();
1666 MessageLoc = MessageClause->getBeginLoc();
1668 if (
const auto *SeverityClause = S.getSingleClause<OMPSeverityClause>()) {
1669 Severity = SeverityClause->getSeverityKind();
1670 SeverityLoc = SeverityClause->getBeginLoc();
1673 CGF, NumThreads, NumThreadsClause->getBeginLoc(), Modifier, Severity,
1674 SeverityLoc, Message, MessageLoc);
1676 if (
const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>()) {
1679 CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getBeginLoc());
1681 const Expr *IfCond =
nullptr;
1682 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
1683 if (
C->getNameModifier() == OMPD_unknown ||
1684 C->getNameModifier() == OMPD_parallel) {
1685 IfCond =
C->getCondition();
1690 OMPParallelScope
Scope(CGF, S);
1696 CodeGenBoundParameters(CGF, S, CapturedVars);
1699 CapturedVars, IfCond, NumThreads,
1700 Modifier, Severity, Message);
1705 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
1707 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
1709 return !((AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc ||
1710 AA->getAllocatorType() == OMPAllocateDeclAttr::OMPNullMemAlloc) &&
1711 !AA->getAllocator());
1726 CGF, S.getBeginLoc(), OMPD_unknown,
false,
1732 CodeGenFunction &CGF,
const VarDecl *VD) {
1734 auto &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1746 Size = CGF.
Builder.CreateNUWAdd(
1748 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
1749 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
1755 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
1756 assert(AA->getAllocator() &&
1757 "Expected allocator expression for non-default allocator.");
1761 if (Allocator->getType()->isIntegerTy())
1762 Allocator = CGF.
Builder.CreateIntToPtr(Allocator,
CGM.VoidPtrTy);
1763 else if (Allocator->getType()->isPointerTy())
1767 llvm::Value *
Addr = OMPBuilder.createOMPAlloc(
1770 llvm::CallInst *FreeCI =
1771 OMPBuilder.createOMPFree(CGF.
Builder,
Addr, Allocator);
1785 if (
CGM.getLangOpts().OpenMPUseTLS &&
1786 CGM.getContext().getTargetInfo().isTLSSupported())
1789 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1794 llvm::ConstantInt *Size =
CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy));
1796 llvm::Twine CacheName = Twine(
CGM.getMangledName(VD)).concat(Suffix);
1798 llvm::CallInst *ThreadPrivateCacheCall =
1799 OMPBuilder.createCachedThreadPrivate(CGF.
Builder,
Data, Size, CacheName);
1807 llvm::raw_svector_ostream OS(Buffer);
1808 StringRef Sep = FirstSeparator;
1809 for (StringRef Part : Parts) {
1813 return OS.str().str();
1821 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
1822 "." + RegionName +
".after");
1838 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
1839 "." + RegionName +
".after");
1851 if (
CGM.getLangOpts().OpenMPIRBuilder) {
1852 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1854 llvm::Value *IfCond =
nullptr;
1859 llvm::Value *NumThreads =
nullptr;
1864 ProcBindKind ProcBind = OMP_PROC_BIND_default;
1865 if (
const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>())
1866 ProcBind = ProcBindClause->getProcBindKind();
1868 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1872 auto FiniCB = [
this](InsertPointTy IP) {
1874 return llvm::Error::success();
1881 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
1882 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
1893 auto BodyGenCB = [&,
this](InsertPointTy AllocaIP,
1894 InsertPointTy CodeGenIP) {
1896 *
this, ParallelRegionBodyStmt, AllocaIP, CodeGenIP,
"parallel");
1897 return llvm::Error::success();
1902 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
1904 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
1905 OMPBuilder.createParallel(
Builder, AllocaIP, BodyGenCB, PrivCB, FiniCB,
1906 IfCond, NumThreads, ProcBind, S.hasCancel()));
1920 CGF.
EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt());
1929 [](CodeGenFunction &) {
return nullptr; });
1941class OMPTransformDirectiveScopeRAII {
1942 OMPLoopScope *
Scope =
nullptr;
1946 OMPTransformDirectiveScopeRAII(
const OMPTransformDirectiveScopeRAII &) =
1948 OMPTransformDirectiveScopeRAII &
1949 operator=(
const OMPTransformDirectiveScopeRAII &) =
delete;
1953 if (
const auto *Dir = dyn_cast<OMPLoopBasedDirective>(S)) {
1954 Scope =
new OMPLoopScope(CGF, *Dir);
1957 }
else if (
const auto *Dir =
1958 dyn_cast<OMPCanonicalLoopSequenceTransformationDirective>(
1963 Scope =
new OMPLoopScope(CGF, *Dir);
1968 ~OMPTransformDirectiveScopeRAII() {
1979 int MaxLevel,
int Level = 0) {
1980 assert(Level < MaxLevel &&
"Too deep lookup during loop body codegen.");
1982 if (
const auto *CS = dyn_cast<CompoundStmt>(SimplifiedS)) {
1985 "LLVM IR generation of compound statement ('{}')");
1989 for (
const Stmt *CurStmt : CS->body())
1990 emitBody(CGF, CurStmt, NextLoop, MaxLevel, Level);
1993 if (SimplifiedS == NextLoop) {
1994 if (
auto *Dir = dyn_cast<OMPLoopTransformationDirective>(SimplifiedS))
1995 SimplifiedS = Dir->getTransformedStmt();
1996 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(SimplifiedS))
1997 SimplifiedS = CanonLoop->getLoopStmt();
1998 if (
const auto *For = dyn_cast<ForStmt>(SimplifiedS)) {
2002 "Expected canonical for loop or range-based for loop.");
2004 CGF.
EmitStmt(CXXFor->getLoopVarStmt());
2005 S = CXXFor->getBody();
2007 if (Level + 1 < MaxLevel) {
2008 NextLoop = OMPLoopDirective::tryToFindNextInnerLoop(
2010 emitBody(CGF, S, NextLoop, MaxLevel, Level + 1);
2021 for (
const Expr *UE : D.updates())
2028 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2029 for (
const Expr *UE :
C->updates())
2036 BreakContinueStack.push_back(BreakContinue(D,
LoopExit, Continue));
2037 for (
const Expr *E : D.finals_conditions()) {
2050 bool IsInscanRegion = InscanScope.
Privatize();
2051 if (IsInscanRegion) {
2061 if (EKind != OMPD_simd && !
getLangOpts().OpenMPSimd)
2070 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
2073 OMPLoopBasedDirective::tryToFindNextInnerLoop(
2075 D.getLoopsNumber());
2083 BreakContinueStack.pop_back();
2094 std::unique_ptr<CodeGenFunction::CGCapturedStmtInfo> CSI =
2095 std::make_unique<CodeGenFunction::CGCapturedStmtInfo>(*S);
2099 return {F, CapStruct.getPointer(
ParentCGF)};
2103static llvm::CallInst *
2108 EffectiveArgs.reserve(Args.size() + 1);
2109 llvm::append_range(EffectiveArgs, Args);
2110 EffectiveArgs.push_back(Cap.second);
2115llvm::CanonicalLoopInfo *
2117 assert(Depth == 1 &&
"Nested loops with OpenMPIRBuilder not yet implemented");
2143 const Stmt *SyntacticalLoop = S->getLoopStmt();
2154 const Stmt *BodyStmt;
2155 if (
const auto *For = dyn_cast<ForStmt>(SyntacticalLoop)) {
2156 if (
const Stmt *InitStmt = For->getInit())
2158 BodyStmt = For->getBody();
2159 }
else if (
const auto *RangeFor =
2160 dyn_cast<CXXForRangeStmt>(SyntacticalLoop)) {
2161 if (
const DeclStmt *RangeStmt = RangeFor->getRangeStmt())
2163 if (
const DeclStmt *BeginStmt = RangeFor->getBeginStmt())
2165 if (
const DeclStmt *EndStmt = RangeFor->getEndStmt())
2167 if (
const DeclStmt *LoopVarStmt = RangeFor->getLoopVarStmt())
2169 BodyStmt = RangeFor->getBody();
2171 llvm_unreachable(
"Expected for-stmt or range-based for-stmt");
2174 const CapturedStmt *DistanceFunc = S->getDistanceFunc();
2187 llvm::Value *DistVal =
Builder.CreateLoad(CountAddr,
".count");
2190 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2191 auto BodyGen = [&,
this](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP,
2192 llvm::Value *IndVar) {
2197 const DeclRefExpr *LoopVarRef = S->getLoopVarRef();
2205 return llvm::Error::success();
2208 llvm::CanonicalLoopInfo *
CL =
2209 cantFail(OMPBuilder.createCanonicalLoop(
Builder, BodyGen, DistVal));
2221 const Expr *IncExpr,
2222 const llvm::function_ref<
void(CodeGenFunction &)> BodyGen,
2223 const llvm::function_ref<
void(CodeGenFunction &)> PostIncGen) {
2233 const CapturedStmt *ICS = OMPED.getInnermostCapturedStmt();
2247 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
2248 if (RequiresCleanup)
2255 if (ExitBlock !=
LoopExit.getBlock()) {
2265 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
2273 BreakContinueStack.pop_back();
2284 bool HasLinears =
false;
2285 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2289 if (
const auto *Ref =
2308 if (
const auto *CS = cast_or_null<BinaryOperator>(
C->getCalcStep()))
2320 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2323 llvm::BasicBlock *DoneBB =
nullptr;
2325 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2326 auto IC =
C->varlist_begin();
2327 for (
const Expr *F :
C->finals()) {
2329 if (llvm::Value *
Cond = CondGen(*
this)) {
2341 (*IC)->getType(),
VK_LValue, (*IC)->getExprLoc());
2349 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
2361 llvm::APInt ClauseAlignment(64, 0);
2362 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
2365 ClauseAlignment = AlignmentCI->getValue();
2367 for (
const Expr *E : Clause->varlist()) {
2368 llvm::APInt Alignment(ClauseAlignment);
2369 if (Alignment == 0) {
2376 E->getType()->getPointeeType()))
2379 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2380 "alignment is not power of 2");
2381 if (Alignment != 0) {
2395 auto I = S.private_counters().begin();
2396 for (
const Expr *E : S.counters()) {
2402 LocalDeclMap.erase(PrivateVD);
2408 E->getType(),
VK_LValue, E->getExprLoc());
2416 for (
const auto *
C : S.getClausesOfKind<OMPOrderedClause>()) {
2417 if (!
C->getNumForLoops())
2419 for (
unsigned I = S.getLoopsNumber(), E =
C->getLoopNumIterations().size();
2425 if (DRE->refersToEnclosingVariableOrCapture()) {
2434 const Expr *
Cond, llvm::BasicBlock *TrueBlock,
2435 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
2443 for (
const Expr *I : S.inits()) {
2450 for (
const Expr *E : S.dependent_counters()) {
2453 assert(!E->getType().getNonReferenceType()->isRecordType() &&
2454 "dependent counter must not be an iterator.");
2458 (void)PreCondVars.
setVarAddr(CGF, VD, CounterAddr);
2460 (void)PreCondVars.
apply(CGF);
2461 for (
const Expr *E : S.dependent_inits()) {
2475 llvm::DenseSet<const VarDecl *> SIMDLCVs;
2479 for (
const Expr *
C : LoopDirective->counters()) {
2484 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2485 auto CurPrivate =
C->privates().begin();
2486 for (
const Expr *E :
C->varlist()) {
2488 const auto *PrivateVD =
2495 assert(IsRegistered &&
"linear var already registered as private");
2583 if (
const auto *CS = dyn_cast<CapturedStmt>(S))
2601 if (HasOrderedDirective)
2609 const Stmt *AssociatedStmt = D.getAssociatedStmt();
2613 if (
C->getKind() == OMPC_ORDER_concurrent)
2616 if ((EKind == OMPD_simd ||
2618 llvm::any_of(D.getClausesOfKind<OMPReductionClause>(),
2619 [](
const OMPReductionClause *
C) {
2620 return C->getModifier() == OMPC_REDUCTION_inscan;
2628 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2631 llvm::BasicBlock *DoneBB =
nullptr;
2632 auto IC = D.counters().begin();
2633 auto IPC = D.private_counters().begin();
2634 for (
const Expr *F : D.finals()) {
2637 const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
2639 OrigVD->hasGlobalStorage() || CED) {
2641 if (llvm::Value *
Cond = CondGen(*
this)) {
2689 auto &&ThenGen = [&S, &SimdInitGen, &BodyCodeGen](
CodeGenFunction &CGF,
2703 const Expr *IfCond =
nullptr;
2706 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
2708 (
C->getNameModifier() == OMPD_unknown ||
2709 C->getNameModifier() == OMPD_simd)) {
2710 IfCond =
C->getCondition();
2726 OMPLoopScope PreInitScope(CGF, S);
2748 llvm::BasicBlock *ContBlock =
nullptr;
2755 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
2762 const Expr *IVExpr = S.getIterationVariable();
2770 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
2785 CGF, S, CGF.
EmitLValue(S.getIterationVariable()));
2800 emitOMPLoopBodyWithStopPoint(CGF, S,
2801 CodeGenFunction::JumpDest());
2807 if (HasLastprivateClause)
2836 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(S.getRawStmt())) {
2837 if (
const Stmt *SyntacticalLoop = CanonLoop->getLoopStmt()) {
2838 for (
const Stmt *SubStmt : SyntacticalLoop->
children()) {
2841 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(SubStmt)) {
2856static llvm::MapVector<llvm::Value *, llvm::Value *>
2858 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars;
2860 llvm::APInt ClauseAlignment(64, 0);
2861 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
2864 ClauseAlignment = AlignmentCI->getValue();
2866 for (
const Expr *E : Clause->varlist()) {
2867 llvm::APInt Alignment(ClauseAlignment);
2868 if (Alignment == 0) {
2875 E->getType()->getPointeeType()))
2878 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2879 "alignment is not power of 2");
2881 AlignedVars[PtrValue] = CGF.
Builder.getInt64(Alignment.getSExtValue());
2891 bool UseOMPIRBuilder =
2893 if (UseOMPIRBuilder) {
2897 if (UseOMPIRBuilder) {
2898 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars =
2901 const Stmt *Inner = S.getRawStmt();
2902 llvm::CanonicalLoopInfo *CLI =
2903 CGF.EmitOMPCollapsedCanonicalLoopNest(Inner, 1);
2905 llvm::OpenMPIRBuilder &OMPBuilder =
2908 llvm::ConstantInt *Simdlen =
nullptr;
2915 llvm::ConstantInt *Safelen =
nullptr;
2922 llvm::omp::OrderKind Order = llvm::omp::OrderKind::OMP_ORDER_unknown;
2924 if (
C->getKind() == OpenMPOrderClauseKind::OMPC_ORDER_concurrent) {
2925 Order = llvm::omp::OrderKind::OMP_ORDER_concurrent;
2930 OMPBuilder.applySimd(CLI, AlignedVars,
2931 nullptr, Order, Simdlen, Safelen);
2938 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
2953 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
2966 OMPTransformDirectiveScopeRAII TileScope(*
this, &S);
2972 OMPTransformDirectiveScopeRAII StripeScope(*
this, &S);
2978 OMPTransformDirectiveScopeRAII ReverseScope(*
this, &S);
2985 OMPTransformDirectiveScopeRAII InterchangeScope(*
this, &S);
2991 OMPTransformDirectiveScopeRAII FuseScope(*
this, &S);
2996 bool UseOMPIRBuilder =
CGM.getLangOpts().OpenMPIRBuilder;
2998 if (UseOMPIRBuilder) {
3000 const Stmt *Inner = S.getRawStmt();
3008 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
3011 llvm::CanonicalLoopInfo *UnrolledCLI =
nullptr;
3015 OMPBuilder.unrollLoopFull(DL, CLI);
3017 uint64_t Factor = 0;
3018 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3019 Factor = FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
3020 assert(Factor >= 1 &&
"Only positive factors are valid");
3022 OMPBuilder.unrollLoopPartial(DL, CLI, Factor,
3023 NeedsUnrolledCLI ? &UnrolledCLI :
nullptr);
3025 OMPBuilder.unrollLoopHeuristic(DL, CLI);
3028 assert((!NeedsUnrolledCLI || UnrolledCLI) &&
3029 "NeedsUnrolledCLI implies UnrolledCLI to be set");
3046 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3048 FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
3049 assert(Factor >= 1 &&
"Only positive factors are valid");
3057void CodeGenFunction::EmitOMPOuterLoop(
3060 const CodeGenFunction::OMPLoopArguments &LoopArgs,
3065 const Expr *IVExpr = S.getIterationVariable();
3079 llvm::Value *BoolCondVal =
nullptr;
3080 if (!DynamicOrOrdered) {
3091 RT.
emitForNext(*
this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL,
3092 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST);
3097 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
3102 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
3103 if (ExitBlock !=
LoopExit.getBlock()) {
3111 if (DynamicOrOrdered)
3116 BreakContinueStack.push_back(BreakContinue(S, LoopExit, Continue));
3121 [&S, IsMonotonic, EKind](CodeGenFunction &CGF, PrePostActionTy &) {
3126 if (
const auto *
C = S.getSingleClause<OMPOrderClause>())
3127 if (
C->getKind() == OMPC_ORDER_concurrent)
3133 [&S, &LoopArgs, LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered,
3134 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
3135 SourceLocation Loc = S.getBeginLoc();
3141 CGF.EmitOMPInnerLoop(
3143 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
3144 CodeGenLoop(CGF, S, LoopExit);
3146 [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) {
3147 CodeGenOrdered(CGF, Loc, IVSize, IVSigned);
3152 BreakContinueStack.pop_back();
3153 if (!DynamicOrOrdered) {
3166 auto &&CodeGen = [DynamicOrOrdered, &S, &LoopArgs](CodeGenFunction &CGF) {
3167 if (!DynamicOrOrdered)
3168 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
3171 OMPCancelStack.emitExit(*
this, EKind, CodeGen);
3174void CodeGenFunction::EmitOMPForOuterLoop(
3175 const OpenMPScheduleTy &ScheduleKind,
bool IsMonotonic,
3177 const OMPLoopArguments &LoopArgs,
3179 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3185 LoopArgs.Chunk !=
nullptr)) &&
3186 "static non-chunked schedule does not need outer loop");
3240 const Expr *IVExpr = S.getIterationVariable();
3244 if (DynamicOrOrdered) {
3245 const std::pair<llvm::Value *, llvm::Value *> DispatchBounds =
3246 CGDispatchBounds(*
this, S, LoopArgs.LB, LoopArgs.UB);
3247 llvm::Value *LBVal = DispatchBounds.first;
3248 llvm::Value *UBVal = DispatchBounds.second;
3249 CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal,
3252 IVSigned, Ordered, DipatchRTInputValues);
3254 CGOpenMPRuntime::StaticRTInput StaticInit(
3255 IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
3256 LoopArgs.ST, LoopArgs.Chunk);
3262 auto &&CodeGenOrdered = [Ordered](CodeGenFunction &CGF, SourceLocation Loc,
3263 const unsigned IVSize,
3264 const bool IVSigned) {
3271 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST,
3272 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB);
3273 OuterLoopArgs.IncExpr = S.getInc();
3274 OuterLoopArgs.Init = S.getInit();
3275 OuterLoopArgs.Cond = S.getCond();
3276 OuterLoopArgs.NextLB = S.getNextLowerBound();
3277 OuterLoopArgs.NextUB = S.getNextUpperBound();
3278 OuterLoopArgs.DKind = LoopArgs.DKind;
3279 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
3281 if (DynamicOrOrdered) {
3287 const unsigned IVSize,
const bool IVSigned) {}
3289void CodeGenFunction::EmitOMPDistributeOuterLoop(
3294 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3301 const Expr *IVExpr = S.getIterationVariable();
3306 CGOpenMPRuntime::StaticRTInput StaticInit(
3307 IVSize, IVSigned,
false, LoopArgs.IL, LoopArgs.LB,
3308 LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
3315 IncExpr = S.getDistInc();
3317 IncExpr = S.getInc();
3322 OMPLoopArguments OuterLoopArgs;
3323 OuterLoopArgs.LB = LoopArgs.LB;
3324 OuterLoopArgs.UB = LoopArgs.UB;
3325 OuterLoopArgs.ST = LoopArgs.ST;
3326 OuterLoopArgs.IL = LoopArgs.IL;
3327 OuterLoopArgs.Chunk = LoopArgs.Chunk;
3329 ? S.getCombinedEnsureUpperBound()
3330 : S.getEnsureUpperBound();
3331 OuterLoopArgs.IncExpr = IncExpr;
3333 ? S.getCombinedInit()
3336 ? S.getCombinedCond()
3339 ? S.getCombinedNextLowerBound()
3340 : S.getNextLowerBound();
3342 ? S.getCombinedNextUpperBound()
3343 : S.getNextUpperBound();
3344 OuterLoopArgs.DKind = OMPD_distribute;
3346 EmitOMPOuterLoop(
false,
false, S,
3347 LoopScope, OuterLoopArgs, CodeGenLoopContent,
3351static std::pair<LValue, LValue>
3366 LValue PrevLB = CGF.
EmitLValue(LS.getPrevLowerBoundVariable());
3367 LValue PrevUB = CGF.
EmitLValue(LS.getPrevUpperBoundVariable());
3369 PrevLB, LS.getPrevLowerBoundVariable()->getExprLoc());
3371 PrevLBVal, LS.getPrevLowerBoundVariable()->getType(),
3372 LS.getIterationVariable()->getType(),
3373 LS.getPrevLowerBoundVariable()->getExprLoc());
3375 PrevUB, LS.getPrevUpperBoundVariable()->getExprLoc());
3377 PrevUBVal, LS.getPrevUpperBoundVariable()->getType(),
3378 LS.getIterationVariable()->getType(),
3379 LS.getPrevUpperBoundVariable()->getExprLoc());
3394static std::pair<llvm::Value *, llvm::Value *>
3399 const Expr *IVExpr = LS.getIterationVariable();
3405 llvm::Value *LBVal =
3407 llvm::Value *UBVal =
3409 return {LBVal, UBVal};
3418 llvm::Value *LBCast = CGF.
Builder.CreateIntCast(
3420 CapturedVars.push_back(LBCast);
3424 llvm::Value *UBCast = CGF.
Builder.CreateIntCast(
3426 CapturedVars.push_back(UBCast);
3437 bool HasCancel =
false;
3439 if (
const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
3440 HasCancel = D->hasCancel();
3441 else if (
const auto *D = dyn_cast<OMPDistributeParallelForDirective>(&S))
3442 HasCancel = D->hasCancel();
3443 else if (
const auto *D =
3444 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S))
3445 HasCancel = D->hasCancel();
3455 CGInlinedWorksharingLoop,
3465 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3466 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3475 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3476 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3484 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
3485 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
3495 llvm::Constant *
Addr;
3497 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
3499 assert(Fn &&
Addr &&
"Target device function emission failed.");
3511struct ScheduleKindModifiersTy {
3518 : Kind(Kind), M1(M1), M2(M2) {}
3534 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
3542 bool HasLastprivateClause;
3545 OMPLoopScope PreInitScope(*
this, S);
3550 llvm::BasicBlock *ContBlock =
nullptr;
3557 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
3564 bool Ordered =
false;
3565 if (
const auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) {
3566 if (OrderedClause->getNumForLoops())
3576 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*
this, S);
3577 LValue LB = Bounds.first;
3578 LValue UB = Bounds.second;
3592 CGM.getOpenMPRuntime().emitBarrierCall(
3593 *
this, S.getBeginLoc(), OMPD_unknown,
false,
3598 *
this, S,
EmitLValue(S.getIterationVariable()));
3605 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
3608 const Expr *ChunkExpr =
nullptr;
3610 if (
const auto *
C = S.getSingleClause<OMPScheduleClause>()) {
3611 ScheduleKind.
Schedule =
C->getScheduleKind();
3612 ScheduleKind.
M1 =
C->getFirstScheduleModifier();
3613 ScheduleKind.
M2 =
C->getSecondScheduleModifier();
3614 ChunkExpr =
C->getChunkSize();
3617 CGM.getOpenMPRuntime().getDefaultScheduleAndChunk(
3618 *
this, S, ScheduleKind.
Schedule, ChunkExpr);
3620 bool HasChunkSizeOne =
false;
3621 llvm::Value *Chunk =
nullptr;
3625 S.getIterationVariable()->getType(),
3629 llvm::APSInt EvaluatedChunk =
Result.Val.getInt();
3630 HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
3639 bool StaticChunkedOne =
3641 Chunk !=
nullptr) &&
3645 (ScheduleKind.
Schedule == OMPC_SCHEDULE_static &&
3646 !(ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
3647 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)) ||
3648 ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
3649 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
3651 Chunk !=
nullptr) ||
3652 StaticChunkedOne) &&
3662 if (
C->getKind() == OMPC_ORDER_concurrent)
3666 [IVSize, IVSigned, Ordered, IL, LB, UB, ST, StaticChunkedOne, Chunk,
3675 IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(),
3676 UB.getAddress(), ST.getAddress(),
3677 StaticChunkedOne ? Chunk :
nullptr);
3679 CGF, S.getBeginLoc(), EKind, ScheduleKind, StaticInit);
3681 if (!StaticChunkedOne)
3700 StaticChunkedOne ? S.getCombinedParForInDistCond()
3702 StaticChunkedOne ? S.getDistInc() : S.getInc(),
3703 [&S,
LoopExit](CodeGenFunction &CGF) {
3704 emitOMPLoopBodyWithStopPoint(CGF, S, LoopExit);
3706 [](CodeGenFunction &) {});
3710 auto &&
CodeGen = [&S](CodeGenFunction &CGF) {
3714 OMPCancelStack.emitExit(*
this, EKind,
CodeGen);
3721 LoopArguments.DKind = OMPD_for;
3722 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
3723 LoopArguments, CGDispatchBounds);
3727 return CGF.
Builder.CreateIsNotNull(
3733 ? OMPD_parallel_for_simd
3737 *
this, S, [IL, &S](CodeGenFunction &CGF) {
3738 return CGF.
Builder.CreateIsNotNull(
3742 if (HasLastprivateClause)
3748 return CGF.
Builder.CreateIsNotNull(
3759 return HasLastprivateClause;
3765static std::pair<LValue, LValue>
3779static std::pair<llvm::Value *, llvm::Value *>
3783 const Expr *IVExpr = LS.getIterationVariable();
3785 llvm::Value *LBVal = CGF.
Builder.getIntN(IVSize, 0);
3787 return {LBVal, UBVal};
3799 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
3800 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
3801 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
3806 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
3807 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
3808 "Only inscan reductions are expected.");
3809 Shareds.append(
C->varlist_begin(),
C->varlist_end());
3810 Privates.append(
C->privates().begin(),
C->privates().end());
3811 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
3812 CopyArrayTemps.append(
C->copy_array_temps().begin(),
3813 C->copy_array_temps().end());
3821 auto *ITA = CopyArrayTemps.begin();
3826 if (PrivateVD->getType()->isVariablyModifiedType()) {
3851 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
3852 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
3853 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
3860 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
3861 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
3862 "Only inscan reductions are expected.");
3863 Shareds.append(
C->varlist_begin(),
C->varlist_end());
3864 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
3865 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
3866 Privates.append(
C->privates().begin(),
C->privates().end());
3867 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
3868 CopyArrayElems.append(
C->copy_array_elems().begin(),
3869 C->copy_array_elems().end());
3873 llvm::Value *OMPLast = CGF.
Builder.CreateNSWSub(
3874 OMPScanNumIterations,
3875 llvm::ConstantInt::get(CGF.
SizeTy, 1,
false));
3876 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
3878 const Expr *OrigExpr = Shareds[I];
3879 const Expr *CopyArrayElem = CopyArrayElems[I];
3886 LValue SrcLVal = CGF.
EmitLValue(CopyArrayElem);
3888 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
3918 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
3919 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
3925 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
3926 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
3927 "Only inscan reductions are expected.");
3928 Privates.append(
C->privates().begin(),
C->privates().end());
3929 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
3930 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
3931 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
3932 CopyArrayElems.append(
C->copy_array_elems().begin(),
3933 C->copy_array_elems().end());
3948 auto &&
CodeGen = [&S, OMPScanNumIterations, &LHSs, &RHSs, &CopyArrayElems,
3955 llvm::BasicBlock *InputBB = CGF.Builder.GetInsertBlock();
3956 llvm::BasicBlock *LoopBB = CGF.createBasicBlock(
"omp.outer.log.scan.body");
3957 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
"omp.outer.log.scan.exit");
3959 CGF.CGM.getIntrinsic(llvm::Intrinsic::log2, CGF.DoubleTy);
3961 CGF.Builder.CreateUIToFP(OMPScanNumIterations, CGF.DoubleTy);
3962 llvm::Value *LogVal = CGF.EmitNounwindRuntimeCall(F, Arg);
3963 F = CGF.CGM.getIntrinsic(llvm::Intrinsic::ceil, CGF.DoubleTy);
3964 LogVal = CGF.EmitNounwindRuntimeCall(F, LogVal);
3965 LogVal = CGF.Builder.CreateFPToUI(LogVal, CGF.IntTy);
3966 llvm::Value *NMin1 = CGF.Builder.CreateNUWSub(
3967 OMPScanNumIterations, llvm::ConstantInt::get(CGF.SizeTy, 1));
3969 CGF.EmitBlock(LoopBB);
3970 auto *Counter = CGF.Builder.CreatePHI(CGF.IntTy, 2);
3972 auto *Pow2K = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
3973 Counter->addIncoming(llvm::ConstantInt::get(CGF.IntTy, 0), InputBB);
3974 Pow2K->addIncoming(llvm::ConstantInt::get(CGF.SizeTy, 1), InputBB);
3977 llvm::BasicBlock *InnerLoopBB =
3978 CGF.createBasicBlock(
"omp.inner.log.scan.body");
3979 llvm::BasicBlock *InnerExitBB =
3980 CGF.createBasicBlock(
"omp.inner.log.scan.exit");
3981 llvm::Value *CmpI = CGF.Builder.CreateICmpUGE(NMin1, Pow2K);
3982 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
3983 CGF.EmitBlock(InnerLoopBB);
3984 auto *IVal = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
3985 IVal->addIncoming(NMin1, LoopBB);
3988 auto *ILHS = LHSs.begin();
3989 auto *IRHS = RHSs.begin();
3990 for (
const Expr *CopyArrayElem : CopyArrayElems) {
4000 LHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4005 llvm::Value *OffsetIVal = CGF.Builder.CreateNUWSub(IVal, Pow2K);
4011 RHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4018 CGF.CGM.getOpenMPRuntime().emitReduction(
4019 CGF, S.getEndLoc(),
Privates, LHSs, RHSs, ReductionOps,
4023 llvm::Value *NextIVal =
4024 CGF.Builder.CreateNUWSub(IVal, llvm::ConstantInt::get(CGF.SizeTy, 1));
4025 IVal->addIncoming(NextIVal, CGF.Builder.GetInsertBlock());
4026 CmpI = CGF.Builder.CreateICmpUGE(NextIVal, Pow2K);
4027 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4028 CGF.EmitBlock(InnerExitBB);
4030 CGF.Builder.CreateNUWAdd(Counter, llvm::ConstantInt::get(CGF.IntTy, 1));
4031 Counter->addIncoming(
Next, CGF.Builder.GetInsertBlock());
4033 llvm::Value *NextPow2K =
4034 CGF.Builder.CreateShl(Pow2K, 1,
"",
true);
4035 Pow2K->addIncoming(NextPow2K, CGF.Builder.GetInsertBlock());
4036 llvm::Value *
Cmp = CGF.Builder.CreateICmpNE(
Next, LogVal);
4037 CGF.Builder.CreateCondBr(
Cmp, LoopBB, ExitBB);
4039 CGF.EmitBlock(ExitBB);
4045 CGF, S.getBeginLoc(), OMPD_unknown,
false,
4048 RegionCodeGenTy RCG(CodeGen);
4059 bool HasLastprivates;
4061 if (llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4062 [](
const OMPReductionClause *
C) {
4063 return C->getModifier() == OMPC_REDUCTION_inscan;
4067 OMPLoopScope LoopScope(CGF, S);
4070 const auto &&FirstGen = [&S, HasCancel, EKind](
CodeGenFunction &CGF) {
4079 const auto &&SecondGen = [&S, HasCancel, EKind,
4097 return HasLastprivates;
4110 if (
auto *SC = dyn_cast<OMPScheduleClause>(
C)) {
4115 switch (SC->getScheduleKind()) {
4116 case OMPC_SCHEDULE_auto:
4117 case OMPC_SCHEDULE_dynamic:
4118 case OMPC_SCHEDULE_runtime:
4119 case OMPC_SCHEDULE_guided:
4120 case OMPC_SCHEDULE_static:
4133static llvm::omp::ScheduleKind
4135 switch (ScheduleClauseKind) {
4137 return llvm::omp::OMP_SCHEDULE_Default;
4138 case OMPC_SCHEDULE_auto:
4139 return llvm::omp::OMP_SCHEDULE_Auto;
4140 case OMPC_SCHEDULE_dynamic:
4141 return llvm::omp::OMP_SCHEDULE_Dynamic;
4142 case OMPC_SCHEDULE_guided:
4143 return llvm::omp::OMP_SCHEDULE_Guided;
4144 case OMPC_SCHEDULE_runtime:
4145 return llvm::omp::OMP_SCHEDULE_Runtime;
4146 case OMPC_SCHEDULE_static:
4147 return llvm::omp::OMP_SCHEDULE_Static;
4149 llvm_unreachable(
"Unhandled schedule kind");
4156 bool HasLastprivates =
false;
4159 auto &&
CodeGen = [&S, &
CGM, HasCancel, &HasLastprivates,
4162 if (UseOMPIRBuilder) {
4163 bool NeedsBarrier = !S.getSingleClause<OMPNowaitClause>();
4165 llvm::omp::ScheduleKind SchedKind = llvm::omp::OMP_SCHEDULE_Default;
4166 llvm::Value *ChunkSize =
nullptr;
4167 if (
auto *SchedClause = S.getSingleClause<OMPScheduleClause>()) {
4170 if (
const Expr *ChunkSizeExpr = SchedClause->getChunkSize())
4175 const Stmt *Inner = S.getRawStmt();
4176 llvm::CanonicalLoopInfo *CLI =
4179 llvm::OpenMPIRBuilder &OMPBuilder =
4181 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4183 cantFail(OMPBuilder.applyWorkshareLoop(
4184 CGF.
Builder.getCurrentDebugLocation(), CLI, AllocaIP, NeedsBarrier,
4185 SchedKind, ChunkSize,
false,
4196 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
4201 if (!UseOMPIRBuilder) {
4203 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4215 bool HasLastprivates =
false;
4216 auto &&
CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
4223 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4224 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
4228 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4229 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_for);
4236 llvm::Value *
Init =
nullptr) {
4243void CodeGenFunction::EmitSections(
const OMPExecutableDirective &S) {
4244 const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4245 const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt);
4246 bool HasLastprivates =
false;
4248 auto &&CodeGen = [&S, CapturedStmt, CS, EKind,
4249 &HasLastprivates](CodeGenFunction &CGF, PrePostActionTy &) {
4250 const ASTContext &
C = CGF.getContext();
4251 QualType KmpInt32Ty =
4252 C.getIntTypeForBitwidth(32, 1);
4255 CGF.Builder.getInt32(0));
4256 llvm::ConstantInt *GlobalUBVal = CS !=
nullptr
4257 ? CGF.Builder.getInt32(CS->size() - 1)
4258 : CGF.Builder.getInt32(0);
4262 CGF.Builder.getInt32(1));
4264 CGF.Builder.getInt32(0));
4267 OpaqueValueExpr IVRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4268 CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
4269 OpaqueValueExpr UBRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4270 CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
4274 S.getBeginLoc(), FPOptionsOverride());
4278 S.getBeginLoc(),
true, FPOptionsOverride());
4279 auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
4291 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".omp.sections.exit");
4292 llvm::SwitchInst *SwitchStmt =
4293 CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.
getBeginLoc()),
4294 ExitBB, CS ==
nullptr ? 1 : CS->size());
4296 unsigned CaseNumber = 0;
4297 for (
const Stmt *SubStmt : CS->
children()) {
4298 auto CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4299 CGF.EmitBlock(CaseBB);
4300 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
4301 CGF.EmitStmt(SubStmt);
4302 CGF.EmitBranch(ExitBB);
4306 llvm::BasicBlock *CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4307 CGF.EmitBlock(CaseBB);
4308 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
4309 CGF.EmitStmt(CapturedStmt);
4310 CGF.EmitBranch(ExitBB);
4312 CGF.EmitBlock(ExitBB,
true);
4315 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
4316 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
4320 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
4324 CGF.EmitOMPPrivateClause(S, LoopScope);
4325 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(CGF, S, IV);
4326 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
4327 CGF.EmitOMPReductionClauseInit(S, LoopScope);
4328 (void)LoopScope.Privatize();
4330 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
4333 OpenMPScheduleTy ScheduleKind;
4334 ScheduleKind.
Schedule = OMPC_SCHEDULE_static;
4335 CGOpenMPRuntime::StaticRTInput StaticInit(
4336 32,
true,
false, IL.getAddress(),
4337 LB.getAddress(), UB.getAddress(), ST.getAddress());
4338 CGF.CGM.getOpenMPRuntime().emitForStaticInit(CGF, S.
getBeginLoc(), EKind,
4339 ScheduleKind, StaticInit);
4341 llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.
getBeginLoc());
4342 llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
4343 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
4344 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
4346 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.
getBeginLoc()), IV);
4348 CGF.EmitOMPInnerLoop(S,
false,
Cond, Inc, BodyGen,
4349 [](CodeGenFunction &) {});
4351 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
4352 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.
getEndLoc(),
4355 CGF.OMPCancelStack.emitExit(CGF, EKind, CodeGen);
4356 CGF.EmitOMPReductionClauseFinal(S, OMPD_parallel);
4359 return CGF.
Builder.CreateIsNotNull(
4364 if (HasLastprivates)
4371 bool HasCancel =
false;
4372 if (
auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
4373 HasCancel = OSD->hasCancel();
4374 else if (
auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
4375 HasCancel = OPSD->hasCancel();
4377 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_sections, CodeGen,
4382 if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) {
4400 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4405 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4406 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_scope,
CodeGen);
4409 if (!S.getSingleClause<OMPNowaitClause>()) {
4410 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_scope);
4417 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4418 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4419 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4420 using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
4422 auto FiniCB = [](InsertPointTy IP) {
4425 return llvm::Error::success();
4428 const CapturedStmt *ICS = S.getInnermostCapturedStmt();
4434 auto SectionCB = [
this, SubStmt](InsertPointTy AllocaIP,
4435 InsertPointTy CodeGenIP) {
4437 *
this, SubStmt, AllocaIP, CodeGenIP,
"section");
4438 return llvm::Error::success();
4440 SectionCBVector.push_back(SectionCB);
4443 auto SectionCB = [
this,
CapturedStmt](InsertPointTy AllocaIP,
4444 InsertPointTy CodeGenIP) {
4447 return llvm::Error::success();
4449 SectionCBVector.push_back(SectionCB);
4456 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
4457 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
4467 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4469 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4470 cantFail(OMPBuilder.createSections(
4471 Builder, AllocaIP, SectionCBVector, PrivCB, FiniCB, S.hasCancel(),
4472 S.getSingleClause<OMPNowaitClause>()));
4479 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4483 if (!S.getSingleClause<OMPNowaitClause>()) {
4484 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(),
4492 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4493 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4494 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4496 const Stmt *SectionRegionBodyStmt = S.getAssociatedStmt();
4497 auto FiniCB = [
this](InsertPointTy IP) {
4499 return llvm::Error::success();
4502 auto BodyGenCB = [SectionRegionBodyStmt,
this](InsertPointTy AllocaIP,
4503 InsertPointTy CodeGenIP) {
4505 *
this, SectionRegionBodyStmt, AllocaIP, CodeGenIP,
"section");
4506 return llvm::Error::success();
4511 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4512 cantFail(OMPBuilder.createSection(
Builder, BodyGenCB, FiniCB));
4532 CopyprivateVars.append(
C->varlist_begin(),
C->varlist_end());
4533 DestExprs.append(
C->destination_exprs().begin(),
4534 C->destination_exprs().end());
4535 SrcExprs.append(
C->source_exprs().begin(),
C->source_exprs().end());
4536 AssignmentOps.append(
C->assignment_ops().begin(),
4537 C->assignment_ops().end());
4546 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4551 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4552 CGM.getOpenMPRuntime().emitSingleRegion(*
this,
CodeGen, S.getBeginLoc(),
4553 CopyprivateVars, DestExprs,
4554 SrcExprs, AssignmentOps);
4558 if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) {
4559 CGM.getOpenMPRuntime().emitBarrierCall(
4560 *
this, S.getBeginLoc(),
4561 S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);
4576 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4577 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4578 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4580 const Stmt *MasterRegionBodyStmt = S.getAssociatedStmt();
4582 auto FiniCB = [
this](InsertPointTy IP) {
4584 return llvm::Error::success();
4587 auto BodyGenCB = [MasterRegionBodyStmt,
this](InsertPointTy AllocaIP,
4588 InsertPointTy CodeGenIP) {
4590 *
this, MasterRegionBodyStmt, AllocaIP, CodeGenIP,
"master");
4591 return llvm::Error::success();
4596 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4597 cantFail(OMPBuilder.createMaster(
Builder, BodyGenCB, FiniCB));
4612 Expr *Filter =
nullptr;
4614 Filter = FilterClause->getThreadID();
4620 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4621 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4622 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4624 const Stmt *MaskedRegionBodyStmt = S.getAssociatedStmt();
4625 const Expr *Filter =
nullptr;
4627 Filter = FilterClause->getThreadID();
4628 llvm::Value *FilterVal = Filter
4630 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
4632 auto FiniCB = [
this](InsertPointTy IP) {
4634 return llvm::Error::success();
4637 auto BodyGenCB = [MaskedRegionBodyStmt,
this](InsertPointTy AllocaIP,
4638 InsertPointTy CodeGenIP) {
4640 *
this, MaskedRegionBodyStmt, AllocaIP, CodeGenIP,
"masked");
4641 return llvm::Error::success();
4646 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
4647 OMPBuilder.createMasked(
Builder, BodyGenCB, FiniCB, FilterVal));
4658 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4659 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4660 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4662 const Stmt *CriticalRegionBodyStmt = S.getAssociatedStmt();
4663 const Expr *Hint =
nullptr;
4664 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4665 Hint = HintClause->getHint();
4670 llvm::Value *HintInst =
nullptr;
4675 auto FiniCB = [
this](InsertPointTy IP) {
4677 return llvm::Error::success();
4680 auto BodyGenCB = [CriticalRegionBodyStmt,
this](InsertPointTy AllocaIP,
4681 InsertPointTy CodeGenIP) {
4683 *
this, CriticalRegionBodyStmt, AllocaIP, CodeGenIP,
"critical");
4684 return llvm::Error::success();
4689 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4690 cantFail(OMPBuilder.createCritical(
Builder, BodyGenCB, FiniCB,
4691 S.getDirectiveName().getAsString(),
4700 CGF.
EmitStmt(S.getAssociatedStmt());
4702 const Expr *Hint =
nullptr;
4703 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4704 Hint = HintClause->getHint();
4707 CGM.getOpenMPRuntime().emitCriticalRegion(*
this,
4708 S.getDirectiveName().getAsString(),
4709 CodeGen, S.getBeginLoc(), Hint);
4713 const OMPParallelForDirective &S) {
4722 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
4726 OMPLoopScope LoopScope(CGF, S);
4729 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4730 [](
const OMPReductionClause *
C) {
4731 return C->getModifier() == OMPC_REDUCTION_inscan;
4747 const OMPParallelForSimdDirective &S) {
4756 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
4760 OMPLoopScope LoopScope(CGF, S);
4763 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4764 [](
const OMPReductionClause *
C) {
4765 return C->getModifier() == OMPC_REDUCTION_inscan;
4781 const OMPParallelMasterDirective &S) {
4801 [](CodeGenFunction &) {
return nullptr; });
4808 const OMPParallelMaskedDirective &S) {
4828 [](CodeGenFunction &) {
return nullptr; });
4835 const OMPParallelSectionsDirective &S) {
4841 CGF.EmitSections(S);
4855class CheckVarsEscapingUntiedTaskDeclContext final
4860 explicit CheckVarsEscapingUntiedTaskDeclContext() =
default;
4861 ~CheckVarsEscapingUntiedTaskDeclContext() =
default;
4862 void VisitDeclStmt(
const DeclStmt *S) {
4867 if (
const auto *VD = dyn_cast_or_null<VarDecl>(D))
4869 PrivateDecls.push_back(VD);
4873 void VisitCapturedStmt(
const CapturedStmt *) {}
4875 void VisitBlockExpr(
const BlockExpr *) {}
4876 void VisitStmt(
const Stmt *S) {
4879 for (
const Stmt *Child : S->
children())
4885 ArrayRef<const VarDecl *> getPrivateDecls()
const {
return PrivateDecls; }
4893 bool OmpAllMemory =
false;
4896 return C->getDependencyKind() == OMPC_DEPEND_outallmemory ||
4897 C->getDependencyKind() == OMPC_DEPEND_inoutallmemory;
4899 OmpAllMemory =
true;
4904 Data.Dependences.emplace_back(OMPC_DEPEND_outallmemory,
4913 if (Kind == OMPC_DEPEND_outallmemory || Kind == OMPC_DEPEND_inoutallmemory)
4915 if (OmpAllMemory && (Kind == OMPC_DEPEND_out || Kind == OMPC_DEPEND_inout))
4918 Data.Dependences.emplace_back(
C->getDependencyKind(),
C->getModifier());
4919 DD.
DepExprs.append(
C->varlist_begin(),
C->varlist_end());
4928 const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion);
4930 auto PartId = std::next(I);
4931 auto TaskT = std::next(I, 4);
4936 const Expr *
Cond = Clause->getCondition();
4939 Data.Final.setInt(CondConstant);
4944 Data.Final.setInt(
false);
4948 const Expr *Prio = Clause->getPriority();
4949 Data.Priority.setInt(
true);
4957 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
4959 for (
const auto *
C : S.getClausesOfKind<OMPPrivateClause>()) {
4960 auto IRef =
C->varlist_begin();
4961 for (
const Expr *IInit :
C->private_copies()) {
4963 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
4964 Data.PrivateVars.push_back(*IRef);
4965 Data.PrivateCopies.push_back(IInit);
4970 EmittedAsPrivate.clear();
4972 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
4973 auto IRef =
C->varlist_begin();
4974 auto IElemInitRef =
C->inits().begin();
4975 for (
const Expr *IInit :
C->private_copies()) {
4977 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
4978 Data.FirstprivateVars.push_back(*IRef);
4979 Data.FirstprivateCopies.push_back(IInit);
4980 Data.FirstprivateInits.push_back(*IElemInitRef);
4987 llvm::MapVector<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
4988 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
4989 auto IRef =
C->varlist_begin();
4990 auto ID =
C->destination_exprs().begin();
4991 for (
const Expr *IInit :
C->private_copies()) {
4993 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
4994 Data.LastprivateVars.push_back(*IRef);
4995 Data.LastprivateCopies.push_back(IInit);
4997 LastprivateDstsOrigs.insert(
5006 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
5007 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5008 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5009 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5010 Data.ReductionOps.append(
C->reduction_ops().begin(),
5011 C->reduction_ops().end());
5012 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5013 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5015 Data.Reductions =
CGM.getOpenMPRuntime().emitTaskReductionInit(
5016 *
this, S.getBeginLoc(), LHSs, RHSs,
Data);
5021 CheckVarsEscapingUntiedTaskDeclContext Checker;
5022 Checker.Visit(S.getInnermostCapturedStmt()->getCapturedStmt());
5023 Data.PrivateLocals.append(Checker.getPrivateDecls().begin(),
5024 Checker.getPrivateDecls().end());
5026 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
5027 CapturedRegion](CodeGenFunction &CGF,
5029 llvm::MapVector<CanonicalDeclPtr<const VarDecl>,
5030 std::pair<Address, Address>>
5035 if (
auto *DI = CGF.getDebugInfo()) {
5036 llvm::SmallDenseMap<const VarDecl *, FieldDecl *> CaptureFields =
5037 CGF.CapturedStmtInfo->getCaptureFields();
5038 llvm::Value *ContextValue = CGF.CapturedStmtInfo->getContextValue();
5039 if (CaptureFields.size() && ContextValue) {
5040 unsigned CharWidth = CGF.getContext().getCharWidth();
5054 for (
auto It = CaptureFields.begin(); It != CaptureFields.end(); ++It) {
5055 const VarDecl *SharedVar = It->first;
5058 CGF.getContext().getASTRecordLayout(CaptureRecord);
5061 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5062 (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue,
5063 CGF.Builder,
false);
5066 auto UpdateExpr = [](llvm::LLVMContext &Ctx,
auto *
Declare,
5071 Ops.push_back(llvm::dwarf::DW_OP_plus_uconst);
5072 Ops.push_back(Offset);
5074 Ops.push_back(llvm::dwarf::DW_OP_deref);
5075 Declare->setExpression(llvm::DIExpression::get(Ctx, Ops));
5077 llvm::Instruction &
Last = CGF.Builder.GetInsertBlock()->back();
5078 if (
auto DDI = dyn_cast<llvm::DbgVariableIntrinsic>(&
Last))
5079 UpdateExpr(DDI->getContext(), DDI, Offset);
5082 assert(!
Last.isTerminator() &&
"unexpected terminator");
5084 CGF.Builder.GetInsertBlock()->getTrailingDbgRecords()) {
5085 for (llvm::DbgVariableRecord &DVR : llvm::reverse(
5086 llvm::filterDbgVars(Marker->getDbgRecordRange()))) {
5087 UpdateExpr(
Last.getContext(), &DVR, Offset);
5095 if (!
Data.PrivateVars.empty() || !
Data.FirstprivateVars.empty() ||
5096 !
Data.LastprivateVars.empty() || !
Data.PrivateLocals.empty()) {
5097 enum { PrivatesParam = 2, CopyFnParam = 3 };
5098 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5100 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5106 CallArgs.push_back(PrivatesPtr);
5107 ParamTypes.push_back(PrivatesPtr->getType());
5108 for (
const Expr *E :
Data.PrivateVars) {
5111 CGF.getContext().getPointerType(E->
getType()),
".priv.ptr.addr");
5112 PrivatePtrs.emplace_back(VD, PrivatePtr);
5114 ParamTypes.push_back(PrivatePtr.
getType());
5116 for (
const Expr *E :
Data.FirstprivateVars) {
5119 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
5120 ".firstpriv.ptr.addr");
5121 PrivatePtrs.emplace_back(VD, PrivatePtr);
5122 FirstprivatePtrs.emplace_back(VD, PrivatePtr);
5124 ParamTypes.push_back(PrivatePtr.
getType());
5126 for (
const Expr *E :
Data.LastprivateVars) {
5129 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
5130 ".lastpriv.ptr.addr");
5131 PrivatePtrs.emplace_back(VD, PrivatePtr);
5133 ParamTypes.push_back(PrivatePtr.
getType());
5138 Ty = CGF.getContext().getPointerType(Ty);
5140 Ty = CGF.getContext().getPointerType(Ty);
5142 CGF.getContext().getPointerType(Ty),
".local.ptr.addr");
5143 auto Result = UntiedLocalVars.insert(
5146 if (
Result.second ==
false)
5147 *
Result.first = std::make_pair(
5150 ParamTypes.push_back(PrivatePtr.
getType());
5152 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5154 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5155 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5156 for (
const auto &Pair : LastprivateDstsOrigs) {
5160 CGF.CapturedStmtInfo->lookup(OrigVD) !=
nullptr,
5162 Pair.second->getExprLoc());
5163 Scope.addPrivate(Pair.first, CGF.EmitLValue(&DRE).getAddress());
5165 for (
const auto &Pair : PrivatePtrs) {
5167 CGF.Builder.CreateLoad(Pair.second),
5168 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5169 CGF.getContext().getDeclAlign(Pair.first));
5170 Scope.addPrivate(Pair.first, Replacement);
5171 if (
auto *DI = CGF.getDebugInfo())
5172 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5173 (void)DI->EmitDeclareOfAutoVariable(
5174 Pair.first, Pair.second.getBasePointer(), CGF.Builder,
5179 for (
auto &Pair : UntiedLocalVars) {
5180 QualType VDType = Pair.first->getType().getNonReferenceType();
5181 if (Pair.first->getType()->isLValueReferenceType())
5182 VDType = CGF.getContext().getPointerType(VDType);
5184 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5187 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(VDType)),
5188 CGF.getPointerAlign());
5189 Pair.second.first = Replacement;
5190 Ptr = CGF.Builder.CreateLoad(Replacement);
5191 Replacement =
Address(Ptr, CGF.ConvertTypeForMem(VDType),
5192 CGF.getContext().getDeclAlign(Pair.first));
5193 Pair.second.second = Replacement;
5195 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5196 Address Replacement(Ptr, CGF.ConvertTypeForMem(VDType),
5197 CGF.getContext().getDeclAlign(Pair.first));
5198 Pair.second.first = Replacement;
5202 if (
Data.Reductions) {
5204 for (
const auto &Pair : FirstprivatePtrs) {
5206 CGF.Builder.CreateLoad(Pair.second),
5207 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5208 CGF.getContext().getDeclAlign(Pair.first));
5209 FirstprivateScope.
addPrivate(Pair.first, Replacement);
5212 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5214 Data.ReductionCopies,
Data.ReductionOps);
5215 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
5217 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5223 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5225 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5228 CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF),
5229 CGF.getContext().VoidPtrTy,
5230 CGF.getContext().getPointerType(
5231 Data.ReductionCopies[Cnt]->getType()),
5232 Data.ReductionCopies[Cnt]->getExprLoc()),
5233 CGF.ConvertTypeForMem(
Data.ReductionCopies[Cnt]->getType()),
5234 Replacement.getAlignment());
5240 (void)
Scope.Privatize();
5245 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5246 auto IPriv =
C->privates().begin();
5247 auto IRed =
C->reduction_ops().begin();
5248 auto ITD =
C->taskgroup_descriptors().begin();
5249 for (
const Expr *Ref :
C->varlist()) {
5250 InRedVars.emplace_back(Ref);
5251 InRedPrivs.emplace_back(*IPriv);
5252 InRedOps.emplace_back(*IRed);
5253 TaskgroupDescriptors.emplace_back(*ITD);
5254 std::advance(IPriv, 1);
5255 std::advance(IRed, 1);
5256 std::advance(ITD, 1);
5262 if (!InRedVars.empty()) {
5264 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5272 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5274 llvm::Value *ReductionsPtr;
5275 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5276 ReductionsPtr = CGF.EmitLoadOfScalar(CGF.EmitLValue(TRExpr),
5277 TRExpr->getExprLoc());
5279 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5281 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5284 CGF.EmitScalarConversion(
5285 Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy,
5286 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
5287 InRedPrivs[Cnt]->getExprLoc()),
5288 CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()),
5289 Replacement.getAlignment());
5302 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5303 S, *I, *PartId, *TaskT, EKind,
CodeGen,
Data.Tied,
Data.NumberOfParts);
5304 OMPLexicalScope
Scope(*
this, S, std::nullopt,
5307 TaskGen(*
this, OutlinedFn,
Data);
5324 QualType ElemType =
C.getBaseElementType(Ty);
5334 Data.FirstprivateVars.emplace_back(OrigRef);
5335 Data.FirstprivateCopies.emplace_back(PrivateRef);
5336 Data.FirstprivateInits.emplace_back(InitRef);
5349 auto PartId = std::next(I);
5350 auto TaskT = std::next(I, 4);
5353 Data.Final.setInt(
false);
5355 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5356 auto IRef =
C->varlist_begin();
5357 auto IElemInitRef =
C->inits().begin();
5358 for (
auto *IInit :
C->private_copies()) {
5359 Data.FirstprivateVars.push_back(*IRef);
5360 Data.FirstprivateCopies.push_back(IInit);
5361 Data.FirstprivateInits.push_back(*IElemInitRef);
5368 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5369 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5370 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5371 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5372 Data.ReductionOps.append(
C->reduction_ops().begin(),
5373 C->reduction_ops().end());
5374 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5375 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5390 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5392 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5404 if (!isa_and_nonnull<llvm::ConstantPointerNull>(
5407 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5414 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, BPVD, PVD, SVD, MVD, EKind,
5418 if (!
Data.FirstprivateVars.empty()) {
5419 enum { PrivatesParam = 2, CopyFnParam = 3 };
5420 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5422 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5428 CallArgs.push_back(PrivatesPtr);
5429 ParamTypes.push_back(PrivatesPtr->getType());
5430 for (
const Expr *E :
Data.FirstprivateVars) {
5433 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
5434 ".firstpriv.ptr.addr");
5435 PrivatePtrs.emplace_back(VD, PrivatePtr);
5437 ParamTypes.push_back(PrivatePtr.
getType());
5439 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5441 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5442 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5443 for (
const auto &Pair : PrivatePtrs) {
5445 CGF.Builder.CreateLoad(Pair.second),
5446 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5447 CGF.getContext().getDeclAlign(Pair.first));
5448 Scope.addPrivate(Pair.first, Replacement);
5451 CGF.processInReduction(S,
Data, CGF, CS,
Scope);
5454 CGF.GetAddrOfLocalVar(BPVD), 0);
5456 CGF.GetAddrOfLocalVar(PVD), 0);
5457 InputInfo.
SizesArray = CGF.Builder.CreateConstArrayGEP(
5458 CGF.GetAddrOfLocalVar(SVD), 0);
5461 InputInfo.
MappersArray = CGF.Builder.CreateConstArrayGEP(
5462 CGF.GetAddrOfLocalVar(MVD), 0);
5466 OMPLexicalScope LexScope(CGF, S, OMPD_task,
false);
5468 if (CGF.CGM.getLangOpts().OpenMP >= 51 &&
5473 CGF.CGM.getOpenMPRuntime().emitThreadLimitClause(
5474 CGF, TL->getThreadLimit().front(), S.getBeginLoc());
5478 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5479 S, *I, *PartId, *TaskT, EKind,
CodeGen,
true,
5480 Data.NumberOfParts);
5481 llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<OMPNowaitClause>() ? 1 : 0);
5485 CGM.getOpenMPRuntime().emitTaskCall(*
this, S.getBeginLoc(), S, OutlinedFn,
5486 SharedsTy, CapturedStruct, &IfCond,
Data);
5491 CodeGenFunction &CGF,
5495 if (
Data.Reductions) {
5497 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5499 Data.ReductionCopies,
Data.ReductionOps);
5502 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5516 Data.ReductionCopies[Cnt]->getType()),
5517 Data.ReductionCopies[Cnt]->getExprLoc()),
5519 Replacement.getAlignment());
5524 (void)
Scope.Privatize();
5529 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5530 auto IPriv =
C->privates().begin();
5531 auto IRed =
C->reduction_ops().begin();
5532 auto ITD =
C->taskgroup_descriptors().begin();
5533 for (
const Expr *Ref :
C->varlist()) {
5534 InRedVars.emplace_back(Ref);
5535 InRedPrivs.emplace_back(*IPriv);
5536 InRedOps.emplace_back(*IRed);
5537 TaskgroupDescriptors.emplace_back(*ITD);
5538 std::advance(IPriv, 1);
5539 std::advance(IRed, 1);
5540 std::advance(ITD, 1);
5544 if (!InRedVars.empty()) {
5546 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5554 llvm::Value *ReductionsPtr;
5555 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5559 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
5567 InRedPrivs[Cnt]->getExprLoc()),
5569 Replacement.getAlignment());
5583 const Expr *IfCond =
nullptr;
5584 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
5585 if (
C->getNameModifier() == OMPD_unknown ||
5586 C->getNameModifier() == OMPD_task) {
5587 IfCond =
C->getCondition();
5594 Data.Tied = !S.getSingleClause<OMPUntiedClause>();
5598 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
5599 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
5602 SharedsTy, CapturedStruct, IfCond,
5611 const OMPTaskyieldDirective &S) {
5612 CGM.getOpenMPRuntime().emitTaskyieldCall(*
this, S.getBeginLoc());
5616 const OMPMessageClause *MC = S.getSingleClause<OMPMessageClause>();
5617 Expr *ME = MC ? MC->getMessageString() :
nullptr;
5618 const OMPSeverityClause *SC = S.getSingleClause<OMPSeverityClause>();
5619 bool IsFatal =
false;
5620 if (!SC || SC->getSeverityKind() == OMPC_SEVERITY_fatal)
5622 CGM.getOpenMPRuntime().emitErrorCall(*
this, S.getBeginLoc(), ME, IsFatal);
5626 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_barrier);
5633 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
5634 CGM.getOpenMPRuntime().emitTaskwaitCall(*
this, S.getBeginLoc(),
Data);
5638 return T.clauses().empty();
5642 const OMPTaskgroupDirective &S) {
5643 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
5645 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
5646 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5650 auto BodyGenCB = [&,
this](InsertPointTy AllocaIP,
5651 InsertPointTy CodeGenIP) {
5653 EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5654 return llvm::Error::success();
5659 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5660 cantFail(OMPBuilder.createTaskgroup(
Builder, AllocaIP, BodyGenCB));
5666 if (
const Expr *E = S.getReductionRef()) {
5670 for (
const auto *
C : S.getClausesOfKind<OMPTaskReductionClause>()) {
5671 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5672 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5673 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5674 Data.ReductionOps.append(
C->reduction_ops().begin(),
5675 C->reduction_ops().end());
5676 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5677 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5679 llvm::Value *ReductionDesc =
5687 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5689 CGM.getOpenMPRuntime().emitTaskgroupRegion(*
this,
CodeGen, S.getBeginLoc());
5694 ? llvm::AtomicOrdering::NotAtomic
5695 : llvm::AtomicOrdering::AcquireRelease;
5696 CGM.getOpenMPRuntime().emitFlush(
5699 if (
const auto *FlushClause = S.getSingleClause<
OMPFlushClause>())
5701 FlushClause->varlist_end());
5704 S.getBeginLoc(), AO);
5714 for (
auto &Dep :
Data.Dependences) {
5715 Address DepAddr =
CGM.getOpenMPRuntime().emitDepobjDependClause(
5716 *
this, Dep, DC->getBeginLoc());
5722 CGM.getOpenMPRuntime().emitDestroyClause(*
this, DOLVal, DC->getBeginLoc());
5725 if (
const auto *UC = S.getSingleClause<OMPUpdateClause>()) {
5726 CGM.getOpenMPRuntime().emitUpdateClause(
5727 *
this, DOLVal, UC->getDependencyKind(), UC->getBeginLoc());
5745 for (
const auto *
C : ParentDir.getClausesOfKind<OMPReductionClause>()) {
5746 if (
C->getModifier() != OMPC_REDUCTION_inscan)
5748 Shareds.append(
C->varlist_begin(),
C->varlist_end());
5749 Privates.append(
C->privates().begin(),
C->privates().end());
5750 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5751 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5752 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
5753 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
5754 CopyArrayTemps.append(
C->copy_array_temps().begin(),
5755 C->copy_array_temps().end());
5756 CopyArrayElems.append(
C->copy_array_elems().begin(),
5757 C->copy_array_elems().end());
5759 if (ParentDir.getDirectiveKind() == OMPD_simd ||
5801 : BreakContinueStack.back().ContinueBlock.getBlock());
5812 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
5814 const Expr *TempExpr = CopyArrayTemps[I];
5826 CGM.getOpenMPRuntime().emitReduction(
5827 *
this, ParentDir.getEndLoc(),
Privates, LHSs, RHSs, ReductionOps,
5830 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
5838 const Expr *TempExpr = CopyArrayTemps[I];
5850 ? BreakContinueStack.back().ContinueBlock.getBlock()
5856 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
5862 .getIterationVariable()
5863 ->IgnoreParenImpCasts();
5866 IdxVal = Builder.CreateIntCast(IdxVal,
SizeTy,
false);
5867 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
5869 const Expr *OrigExpr = Shareds[I];
5870 const Expr *CopyArrayElem = CopyArrayElems[I];
5871 OpaqueValueMapping IdxMapping(
5884 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
5887 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
5893 .getIterationVariable()
5894 ->IgnoreParenImpCasts();
5898 llvm::BasicBlock *ExclusiveExitBB =
nullptr;
5902 llvm::Value *
Cmp =
Builder.CreateIsNull(IdxVal);
5903 Builder.CreateCondBr(
Cmp, ExclusiveExitBB, ContBB);
5906 IdxVal =
Builder.CreateNUWSub(IdxVal, llvm::ConstantInt::get(
SizeTy, 1));
5908 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
5909 const Expr *PrivateExpr =
Privates[I];
5910 const Expr *OrigExpr = Shareds[I];
5911 const Expr *CopyArrayElem = CopyArrayElems[I];
5920 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
5944 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
5952 bool HasLastprivateClause =
false;
5955 OMPLoopScope PreInitScope(*
this, S);
5960 llvm::BasicBlock *ContBlock =
nullptr;
5967 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
5981 ? S.getCombinedLowerBoundVariable()
5982 : S.getLowerBoundVariable())));
5986 ? S.getCombinedUpperBoundVariable()
5987 : S.getUpperBoundVariable())));
5998 CGM.getOpenMPRuntime().emitBarrierCall(
5999 *
this, S.getBeginLoc(), OMPD_unknown,
false,
6011 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
6014 llvm::Value *Chunk =
nullptr;
6017 ScheduleKind =
C->getDistScheduleKind();
6018 if (
const Expr *Ch =
C->getChunkSize()) {
6021 S.getIterationVariable()->getType(),
6026 CGM.getOpenMPRuntime().getDefaultDistScheduleAndChunk(
6027 *
this, S, ScheduleKind, Chunk);
6040 bool StaticChunked =
6044 Chunk !=
nullptr) ||
6049 StaticChunked ? Chunk :
nullptr);
6056 ? S.getCombinedEnsureUpperBound()
6057 : S.getEnsureUpperBound());
6060 ? S.getCombinedInit()
6065 ? S.getCombinedCond()
6069 Cond = S.getCombinedDistCond();
6101 [&S, &LoopScope,
Cond, IncExpr,
LoopExit, &CodeGenLoop,
6104 S, LoopScope.requiresCleanups(),
Cond, IncExpr,
6105 [&S,
LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
6106 CodeGenLoop(CGF, S, LoopExit);
6108 [&S, StaticChunked](CodeGenFunction &CGF) {
6109 if (StaticChunked) {
6110 CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound());
6111 CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound());
6112 CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound());
6113 CGF.EmitIgnoredExpr(S.getCombinedInit());
6123 const OMPLoopArguments LoopArguments = {
6124 LB.getAddress(), UB.getAddress(), ST.getAddress(), IL.getAddress(),
6126 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments,
6131 return CGF.
Builder.CreateIsNotNull(
6141 *
this, S, [IL, &S](CodeGenFunction &CGF) {
6142 return CGF.
Builder.CreateIsNotNull(
6147 if (HasLastprivateClause) {
6170 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
6179static llvm::Function *
6186 Fn->setDoesNotRecurse();
6190template <
typename T>
6192 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP,
6193 llvm::OpenMPIRBuilder &OMPBuilder) {
6195 unsigned NumLoops =
C->getNumLoops();
6199 for (
unsigned I = 0; I < NumLoops; I++) {
6200 const Expr *CounterVal =
C->getLoopData(I);
6205 StoreValues.emplace_back(StoreValue);
6207 OMPDoacrossKind<T> ODK;
6208 bool IsDependSource = ODK.isSource(
C);
6210 OMPBuilder.createOrderedDepend(CGF.
Builder, AllocaIP, NumLoops,
6211 StoreValues,
".cnt.addr", IsDependSource));
6215 if (
CGM.getLangOpts().OpenMPIRBuilder) {
6216 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
6217 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6222 assert(!S.hasAssociatedStmt() &&
"No associated statement must be in "
6223 "ordered depend|doacross construct.");
6235 auto FiniCB = [
this](InsertPointTy IP) {
6237 return llvm::Error::success();
6240 auto BodyGenCB = [&S,
C,
this](InsertPointTy AllocaIP,
6241 InsertPointTy CodeGenIP) {
6246 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
6247 Builder,
false,
".ordered.after");
6251 assert(S.getBeginLoc().isValid() &&
6252 "Outlined function call location must be valid.");
6255 OutlinedFn, CapturedVars);
6260 return llvm::Error::success();
6263 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6264 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
6265 OMPBuilder.createOrderedThreadsSimd(
Builder, BodyGenCB, FiniCB, !
C));
6272 assert(!S.hasAssociatedStmt() &&
6273 "No associated statement must be in ordered depend construct.");
6275 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6279 assert(!S.hasAssociatedStmt() &&
6280 "No associated statement must be in ordered doacross construct.");
6282 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6286 auto &&
CodeGen = [&S,
C,
this](CodeGenFunction &CGF,
6291 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
6293 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
6294 OutlinedFn, CapturedVars);
6300 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6301 CGM.getOpenMPRuntime().emitOrderedRegion(*
this,
CodeGen, S.getBeginLoc(), !
C);
6308 "DestType must have scalar evaluation kind.");
6309 assert(!Val.
isAggregate() &&
"Must be a scalar or complex.");
6320 "DestType must have complex evaluation kind.");
6329 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
6331 assert(Val.
isComplex() &&
"Must be a scalar or complex.");
6336 Val.
getComplexVal().first, SrcElementType, DestElementType, Loc);
6338 Val.
getComplexVal().second, SrcElementType, DestElementType, Loc);
6344 LValue LVal,
RValue RVal) {
6345 if (LVal.isGlobalReg())
6352 llvm::AtomicOrdering AO, LValue LVal,
6354 if (LVal.isGlobalReg())
6357 LVal, Loc, llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO),
6366 *
this, RVal, RValTy, LVal.
getType(), Loc)),
6375 llvm_unreachable(
"Must be a scalar or complex.");
6383 assert(
V->isLValue() &&
"V of 'omp atomic read' is not lvalue");
6384 assert(
X->isLValue() &&
"X of 'omp atomic read' is not lvalue");
6393 case llvm::AtomicOrdering::Acquire:
6394 case llvm::AtomicOrdering::AcquireRelease:
6395 case llvm::AtomicOrdering::SequentiallyConsistent:
6397 llvm::AtomicOrdering::Acquire);
6399 case llvm::AtomicOrdering::Monotonic:
6400 case llvm::AtomicOrdering::Release:
6402 case llvm::AtomicOrdering::NotAtomic:
6403 case llvm::AtomicOrdering::Unordered:
6404 llvm_unreachable(
"Unexpected ordering.");
6411 llvm::AtomicOrdering AO,
const Expr *
X,
6414 assert(
X->isLValue() &&
"X of 'omp atomic write' is not lvalue");
6422 case llvm::AtomicOrdering::Release:
6423 case llvm::AtomicOrdering::AcquireRelease:
6424 case llvm::AtomicOrdering::SequentiallyConsistent:
6426 llvm::AtomicOrdering::Release);
6428 case llvm::AtomicOrdering::Acquire:
6429 case llvm::AtomicOrdering::Monotonic:
6431 case llvm::AtomicOrdering::NotAtomic:
6432 case llvm::AtomicOrdering::Unordered:
6433 llvm_unreachable(
"Unexpected ordering.");
6440 llvm::AtomicOrdering AO,
6446 if (BO == BO_Comma || !
Update.isScalar() || !
X.isSimple() ||
6448 (
Update.getScalarVal()->getType() !=
X.getAddress().getElementType())) ||
6449 !Context.getTargetInfo().hasBuiltinAtomic(
6450 Context.getTypeSize(
X.getType()), Context.toBits(
X.getAlignment())))
6451 return std::make_pair(
false,
RValue::get(
nullptr));
6454 if (T->isIntegerTy())
6457 if (T->isFloatingPointTy() && (BO == BO_Add || BO == BO_Sub))
6463 if (!CheckAtomicSupport(
Update.getScalarVal()->getType(), BO) ||
6464 !CheckAtomicSupport(
X.getAddress().getElementType(), BO))
6465 return std::make_pair(
false,
RValue::get(
nullptr));
6467 bool IsInteger =
X.getAddress().getElementType()->isIntegerTy();
6468 llvm::AtomicRMWInst::BinOp RMWOp;
6471 RMWOp = IsInteger ? llvm::AtomicRMWInst::Add : llvm::AtomicRMWInst::FAdd;
6475 return std::make_pair(
false,
RValue::get(
nullptr));
6476 RMWOp = IsInteger ? llvm::AtomicRMWInst::Sub : llvm::AtomicRMWInst::FSub;
6479 RMWOp = llvm::AtomicRMWInst::And;
6482 RMWOp = llvm::AtomicRMWInst::Or;
6485 RMWOp = llvm::AtomicRMWInst::Xor;
6489 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6491 : llvm::AtomicRMWInst::Max)
6493 : llvm::AtomicRMWInst::UMax);
6496 : llvm::AtomicRMWInst::FMax;
6500 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6502 : llvm::AtomicRMWInst::Min)
6504 : llvm::AtomicRMWInst::UMin);
6507 : llvm::AtomicRMWInst::FMin;
6510 RMWOp = llvm::AtomicRMWInst::Xchg;
6519 return std::make_pair(
false,
RValue::get(
nullptr));
6538 llvm_unreachable(
"Unsupported atomic update operation");
6540 llvm::Value *UpdateVal =
Update.getScalarVal();
6541 if (
auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
6543 UpdateVal = CGF.
Builder.CreateIntCast(
6544 IC,
X.getAddress().getElementType(),
6545 X.getType()->hasSignedIntegerRepresentation());
6547 UpdateVal = CGF.
Builder.CreateCast(llvm::Instruction::CastOps::UIToFP, IC,
6548 X.getAddress().getElementType());
6550 llvm::AtomicRMWInst *Res =
6567 if (
X.isGlobalReg()) {
6580 llvm::AtomicOrdering AO,
const Expr *
X,
6584 "Update expr in 'atomic update' must be a binary operator.");
6592 assert(
X->isLValue() &&
"X of 'omp atomic update' is not lvalue");
6599 auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](
RValue XRValue) {
6605 XLValue, ExprRValue, BOUE->getOpcode(),
IsXLHSInRHSPart, AO, Loc, Gen);
6612 case llvm::AtomicOrdering::Release:
6613 case llvm::AtomicOrdering::AcquireRelease:
6614 case llvm::AtomicOrdering::SequentiallyConsistent:
6616 llvm::AtomicOrdering::Release);
6618 case llvm::AtomicOrdering::Acquire:
6619 case llvm::AtomicOrdering::Monotonic:
6621 case llvm::AtomicOrdering::NotAtomic:
6622 case llvm::AtomicOrdering::Unordered:
6623 llvm_unreachable(
"Unexpected ordering.");
6641 llvm_unreachable(
"Must be a scalar or complex.");
6645 llvm::AtomicOrdering AO,
6650 assert(
X->isLValue() &&
"X of 'omp atomic capture' is not lvalue");
6651 assert(
V->isLValue() &&
"V of 'omp atomic capture' is not lvalue");
6660 "Update expr in 'atomic capture' must be a binary operator.");
6671 NewVValType = XRValExpr->
getType();
6673 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
6682 XLValue, ExprRValue, BOUE->getOpcode(),
IsXLHSInRHSPart, AO, Loc, Gen);
6688 NewVVal = Res.second;
6699 NewVValType =
X->getType().getNonReferenceType();
6701 X->getType().getNonReferenceType(), Loc);
6702 auto &&Gen = [&NewVVal, ExprRValue](
RValue XRValue) {
6708 XLValue, ExprRValue, BO_Assign,
false, AO,
6729 case llvm::AtomicOrdering::Release:
6731 llvm::AtomicOrdering::Release);
6733 case llvm::AtomicOrdering::Acquire:
6735 llvm::AtomicOrdering::Acquire);
6737 case llvm::AtomicOrdering::AcquireRelease:
6738 case llvm::AtomicOrdering::SequentiallyConsistent:
6740 CGF, {}, Loc, llvm::AtomicOrdering::AcquireRelease);
6742 case llvm::AtomicOrdering::Monotonic:
6744 case llvm::AtomicOrdering::NotAtomic:
6745 case llvm::AtomicOrdering::Unordered:
6746 llvm_unreachable(
"Unexpected ordering.");
6752 CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO,
6756 llvm::OpenMPIRBuilder &OMPBuilder =
6759 OMPAtomicCompareOp Op;
6763 Op = OMPAtomicCompareOp::EQ;
6766 Op = OMPAtomicCompareOp::MIN;
6769 Op = OMPAtomicCompareOp::MAX;
6772 llvm_unreachable(
"unsupported atomic compare binary operator");
6776 Address XAddr = XLVal.getAddress();
6778 auto EmitRValueWithCastIfNeeded = [&CGF, Loc](
const Expr *
X,
const Expr *E) {
6783 if (NewE->
getType() ==
X->getType())
6788 llvm::Value *EVal = EmitRValueWithCastIfNeeded(
X, E);
6789 llvm::Value *DVal = D ? EmitRValueWithCastIfNeeded(
X, D) :
nullptr;
6790 if (
auto *CI = dyn_cast<llvm::ConstantInt>(EVal))
6791 EVal = CGF.
Builder.CreateIntCast(
6792 CI, XLVal.getAddress().getElementType(),
6795 if (
auto *CI = dyn_cast<llvm::ConstantInt>(DVal))
6796 DVal = CGF.
Builder.CreateIntCast(
6797 CI, XLVal.getAddress().getElementType(),
6800 llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{
6802 X->getType()->hasSignedIntegerRepresentation(),
6803 X->getType().isVolatileQualified()};
6804 llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal;
6808 VOpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
6809 V->getType()->hasSignedIntegerRepresentation(),
6810 V->getType().isVolatileQualified()};
6815 ROpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
6820 if (FailAO == llvm::AtomicOrdering::NotAtomic) {
6823 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
6824 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
6827 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
6828 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
6833 llvm::AtomicOrdering AO,
6854 case OMPC_compare: {
6860 llvm_unreachable(
"Clause is not allowed in 'omp atomic'.");
6865 llvm::AtomicOrdering AO =
CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
6867 llvm::AtomicOrdering FailAO = llvm::AtomicOrdering::NotAtomic;
6868 bool MemOrderingSpecified =
false;
6869 if (S.getSingleClause<OMPSeqCstClause>()) {
6870 AO = llvm::AtomicOrdering::SequentiallyConsistent;
6871 MemOrderingSpecified =
true;
6872 }
else if (S.getSingleClause<OMPAcqRelClause>()) {
6873 AO = llvm::AtomicOrdering::AcquireRelease;
6874 MemOrderingSpecified =
true;
6875 }
else if (S.getSingleClause<OMPAcquireClause>()) {
6876 AO = llvm::AtomicOrdering::Acquire;
6877 MemOrderingSpecified =
true;
6878 }
else if (S.getSingleClause<OMPReleaseClause>()) {
6879 AO = llvm::AtomicOrdering::Release;
6880 MemOrderingSpecified =
true;
6881 }
else if (S.getSingleClause<OMPRelaxedClause>()) {
6882 AO = llvm::AtomicOrdering::Monotonic;
6883 MemOrderingSpecified =
true;
6885 llvm::SmallSet<OpenMPClauseKind, 2> KindsEncountered;
6894 if (K == OMPC_seq_cst || K == OMPC_acq_rel || K == OMPC_acquire ||
6895 K == OMPC_release || K == OMPC_relaxed || K == OMPC_hint)
6898 KindsEncountered.insert(K);
6903 if (KindsEncountered.contains(OMPC_compare) &&
6904 KindsEncountered.contains(OMPC_capture))
6905 Kind = OMPC_compare;
6906 if (!MemOrderingSpecified) {
6907 llvm::AtomicOrdering DefaultOrder =
6908 CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
6909 if (DefaultOrder == llvm::AtomicOrdering::Monotonic ||
6910 DefaultOrder == llvm::AtomicOrdering::SequentiallyConsistent ||
6911 (DefaultOrder == llvm::AtomicOrdering::AcquireRelease &&
6912 Kind == OMPC_capture)) {
6914 }
else if (DefaultOrder == llvm::AtomicOrdering::AcquireRelease) {
6915 if (Kind == OMPC_unknown || Kind == OMPC_update || Kind == OMPC_write) {
6916 AO = llvm::AtomicOrdering::Release;
6917 }
else if (Kind == OMPC_read) {
6918 assert(Kind == OMPC_read &&
"Unexpected atomic kind.");
6919 AO = llvm::AtomicOrdering::Acquire;
6924 if (KindsEncountered.contains(OMPC_compare) &&
6925 KindsEncountered.contains(OMPC_fail)) {
6926 Kind = OMPC_compare;
6927 const auto *FailClause = S.getSingleClause<OMPFailClause>();
6930 if (FailParameter == llvm::omp::OMPC_relaxed)
6931 FailAO = llvm::AtomicOrdering::Monotonic;
6932 else if (FailParameter == llvm::omp::OMPC_acquire)
6933 FailAO = llvm::AtomicOrdering::Acquire;
6934 else if (FailParameter == llvm::omp::OMPC_seq_cst)
6935 FailAO = llvm::AtomicOrdering::SequentiallyConsistent;
6942 S.getV(), S.getR(), S.getExpr(), S.getUpdateExpr(),
6943 S.getD(), S.getCondExpr(), S.isXLHSInRHSPart(),
6944 S.isFailOnly(), S.getBeginLoc());
6955 OMPLexicalScope
Scope(CGF, S, OMPD_target);
6958 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
6964 llvm::Function *Fn =
nullptr;
6965 llvm::Constant *FnID =
nullptr;
6967 const Expr *IfCond =
nullptr;
6969 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
6970 if (
C->getNameModifier() == OMPD_unknown ||
6971 C->getNameModifier() == OMPD_target) {
6972 IfCond =
C->getCondition();
6978 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device(
6981 Device.setPointerAndInt(
C->getDevice(),
C->getModifier());
6986 bool IsOffloadEntry =
true;
6990 IsOffloadEntry =
false;
6993 IsOffloadEntry =
false;
6995 if (
CGM.
getLangOpts().OpenMPOffloadMandatory && !IsOffloadEntry) {
6999 assert(CGF.
CurFuncDecl &&
"No parent declaration for target region!");
7000 StringRef ParentName;
7003 if (
const auto *D = dyn_cast<CXXConstructorDecl>(CGF.
CurFuncDecl))
7005 else if (
const auto *D = dyn_cast<CXXDestructorDecl>(CGF.
CurFuncDecl))
7014 OMPLexicalScope
Scope(CGF, S, OMPD_task);
7015 auto &&SizeEmitter =
7018 if (IsOffloadEntry) {
7019 OMPLoopScope(CGF, D);
7021 llvm::Value *NumIterations = CGF.
EmitScalarExpr(D.getNumIterations());
7022 NumIterations = CGF.
Builder.CreateIntCast(NumIterations, CGF.
Int64Ty,
7024 return NumIterations;
7042 CGF.
EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
7047 StringRef ParentName,
7053 llvm::Constant *
Addr;
7055 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7057 assert(Fn &&
Addr &&
"Target device function emission failed.");
7071 const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams);
7072 llvm::Function *OutlinedFn =
7080 const Expr *NumTeams = NT ? NT->getNumTeams().front() :
nullptr;
7081 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() :
nullptr;
7087 OMPTeamsScope
Scope(CGF, S);
7103 CGF.
EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt());
7108 [](CodeGenFunction &) {
return nullptr; });
7113 auto *CS = S.getCapturedStmt(OMPD_teams);
7140 llvm::Constant *
Addr;
7142 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7144 assert(Fn &&
Addr &&
"Target device function emission failed.");
7186 llvm::Constant *
Addr;
7188 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7190 assert(Fn &&
Addr &&
"Target device function emission failed.");
7232 llvm::Constant *
Addr;
7234 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7236 assert(Fn &&
Addr &&
"Target device function emission failed.");
7250 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7255 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7267 [](CodeGenFunction &) {
return nullptr; });
7272 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7277 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7289 [](CodeGenFunction &) {
return nullptr; });
7294 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7300 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7312 [](CodeGenFunction &) {
return nullptr; });
7317 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7323 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7330 CGF, OMPD_distribute, CodeGenDistribute,
false);
7336 [](CodeGenFunction &) {
return nullptr; });
7340 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7341 llvm::Value *
Device =
nullptr;
7342 llvm::Value *NumDependences =
nullptr;
7343 llvm::Value *DependenceList =
nullptr;
7351 if (!
Data.Dependences.empty()) {
7353 std::tie(NumDependences, DependenciesArray) =
7354 CGM.getOpenMPRuntime().emitDependClause(*
this,
Data.Dependences,
7358 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
7363 "OMPNowaitClause clause is used separately in OMPInteropDirective.");
7366 if (!ItOMPInitClause.empty()) {
7369 llvm::Value *InteropvarPtr =
7371 llvm::omp::OMPInteropType InteropType =
7372 llvm::omp::OMPInteropType::Unknown;
7373 if (
C->getIsTarget()) {
7374 InteropType = llvm::omp::OMPInteropType::Target;
7376 assert(
C->getIsTargetSync() &&
7377 "Expected interop-type target/targetsync");
7378 InteropType = llvm::omp::OMPInteropType::TargetSync;
7380 OMPBuilder.createOMPInteropInit(
Builder, InteropvarPtr, InteropType,
7381 Device, NumDependences, DependenceList,
7382 Data.HasNowaitClause);
7386 if (!ItOMPDestroyClause.empty()) {
7389 llvm::Value *InteropvarPtr =
7391 OMPBuilder.createOMPInteropDestroy(
Builder, InteropvarPtr,
Device,
7392 NumDependences, DependenceList,
7393 Data.HasNowaitClause);
7396 auto ItOMPUseClause = S.getClausesOfKind<
OMPUseClause>();
7397 if (!ItOMPUseClause.empty()) {
7400 llvm::Value *InteropvarPtr =
7402 OMPBuilder.createOMPInteropUse(
Builder, InteropvarPtr,
Device,
7403 NumDependences, DependenceList,
7404 Data.HasNowaitClause);
7426 CGF, OMPD_distribute, CodeGenDistribute,
false);
7445 llvm::Constant *
Addr;
7447 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7449 assert(Fn &&
Addr &&
"Target device function emission failed.");
7478 CGF, OMPD_distribute, CodeGenDistribute,
false);
7497 llvm::Constant *
Addr;
7499 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7501 assert(Fn &&
Addr &&
"Target device function emission failed.");
7514 CGM.getOpenMPRuntime().emitCancellationPointCall(*
this, S.getBeginLoc(),
7519 const Expr *IfCond =
nullptr;
7520 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7521 if (
C->getNameModifier() == OMPD_unknown ||
7522 C->getNameModifier() == OMPD_cancel) {
7523 IfCond =
C->getCondition();
7527 if (
CGM.getLangOpts().OpenMPIRBuilder) {
7528 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7534 llvm::Value *IfCondition =
nullptr;
7538 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
7540 return Builder.restoreIP(AfterIP);
7544 CGM.getOpenMPRuntime().emitCancelCall(*
this, S.getBeginLoc(), IfCond,
7550 if (Kind == OMPD_parallel || Kind == OMPD_task ||
7551 Kind == OMPD_target_parallel || Kind == OMPD_taskloop ||
7552 Kind == OMPD_master_taskloop || Kind == OMPD_parallel_master_taskloop)
7554 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
7555 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
7556 Kind == OMPD_distribute_parallel_for ||
7557 Kind == OMPD_target_parallel_for ||
7558 Kind == OMPD_teams_distribute_parallel_for ||
7559 Kind == OMPD_target_teams_distribute_parallel_for);
7560 return OMPCancelStack.getExitBlock();
7565 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7566 CaptureDeviceAddrMap) {
7567 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7568 for (
const Expr *OrigVarIt :
C.varlist()) {
7570 if (!Processed.insert(OrigVD).second)
7577 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7582 "Base should be the current struct!");
7583 MatchingVD = ME->getMemberDecl();
7588 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7589 if (InitAddrIt == CaptureDeviceAddrMap.end())
7597 Address(InitAddrIt->second, Ty,
7599 assert(IsRegistered &&
"firstprivate var already registered as private");
7607 while (
const auto *OASE = dyn_cast<ArraySectionExpr>(
Base))
7608 Base = OASE->getBase()->IgnoreParenImpCasts();
7609 while (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(
Base))
7610 Base = ASE->getBase()->IgnoreParenImpCasts();
7616 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7617 CaptureDeviceAddrMap) {
7618 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7619 for (
const Expr *Ref :
C.varlist()) {
7621 if (!Processed.insert(OrigVD).second)
7627 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7632 "Base should be the current struct!");
7633 MatchingVD = ME->getMemberDecl();
7638 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7639 if (InitAddrIt == CaptureDeviceAddrMap.end())
7645 Address(InitAddrIt->second, Ty,
7658 (void)PrivateScope.
addPrivate(OrigVD, PrivAddr);
7666 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
7667 CGM.getOpenMPRuntime().registerVTable(S);
7675 bool PrivatizeDevicePointers =
false;
7677 bool &PrivatizeDevicePointers;
7680 explicit DevicePointerPrivActionTy(
bool &PrivatizeDevicePointers)
7681 : PrivatizeDevicePointers(PrivatizeDevicePointers) {}
7682 void Enter(CodeGenFunction &CGF)
override {
7683 PrivatizeDevicePointers =
true;
7686 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
7689 auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7690 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
7694 auto &&PrivCodeGen = [&](CodeGenFunction &CGF,
PrePostActionTy &Action) {
7696 PrivatizeDevicePointers =
false;
7702 if (PrivatizeDevicePointers) {
7716 std::optional<OpenMPDirectiveKind> CaptureRegion;
7717 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
7720 for (
const Expr *E :
C->varlist()) {
7722 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
7726 for (
const Expr *E :
C->varlist()) {
7728 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
7732 CaptureRegion = OMPD_unknown;
7735 OMPLexicalScope
Scope(CGF, S, CaptureRegion);
7747 OMPLexicalScope
Scope(CGF, S);
7756 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
7762 const Expr *IfCond =
nullptr;
7764 IfCond =
C->getCondition();
7775 CGM.getOpenMPRuntime().emitTargetDataCalls(*
this, S, IfCond,
Device, RCG,
7783 if (
CGM.getLangOpts().OMPTargetTriples.empty())
7787 const Expr *IfCond =
nullptr;
7789 IfCond =
C->getCondition();
7796 OMPLexicalScope
Scope(*
this, S, OMPD_task);
7797 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
7804 if (
CGM.getLangOpts().OMPTargetTriples.empty())
7808 const Expr *IfCond =
nullptr;
7810 IfCond =
C->getCondition();
7817 OMPLexicalScope
Scope(*
this, S, OMPD_task);
7818 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
7825 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
7853 llvm::Constant *
Addr;
7855 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7857 assert(Fn &&
Addr &&
"Target device function emission failed.");
7877 CGF, OMPD_target_parallel_for, S.
hasCancel());
7893 llvm::Constant *
Addr;
7895 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7897 assert(Fn &&
Addr &&
"Target device function emission failed.");
7932 llvm::Constant *
Addr;
7934 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7936 assert(Fn &&
Addr &&
"Target device function emission failed.");
7958 const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop);
7961 OMPLexicalScope
Scope(*
this, S, OMPD_taskloop,
false);
7966 const Expr *IfCond =
nullptr;
7967 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7968 if (
C->getNameModifier() == OMPD_unknown ||
7969 C->getNameModifier() == OMPD_taskloop) {
7970 IfCond =
C->getCondition();
7983 Data.Schedule.setInt(
false);
7986 (Clause->getModifier() == OMPC_GRAINSIZE_strict) ?
true :
false;
7989 Data.Schedule.setInt(
true);
7992 (Clause->getModifier() == OMPC_NUMTASKS_strict) ?
true :
false;
8006 llvm::BasicBlock *ContBlock =
nullptr;
8007 OMPLoopScope PreInitScope(CGF, S);
8008 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
8012 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock(
"taskloop.if.then");
8013 ContBlock = CGF.createBasicBlock(
"taskloop.if.end");
8014 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
8015 CGF.getProfileCount(&S));
8016 CGF.EmitBlock(ThenBlock);
8017 CGF.incrementProfileCounter(&S);
8020 (void)CGF.EmitOMPLinearClauseInit(S);
8024 enum { LowerBound = 5, UpperBound, Stride, LastIter };
8026 auto *LBP = std::next(I, LowerBound);
8027 auto *UBP = std::next(I, UpperBound);
8028 auto *STP = std::next(I, Stride);
8029 auto *LIP = std::next(I, LastIter);
8037 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
8038 CGF.EmitOMPLinearClause(S, LoopScope);
8039 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
8042 const Expr *IVExpr = S.getIterationVariable();
8044 CGF.EmitVarDecl(*IVDecl);
8045 CGF.EmitIgnoredExpr(S.getInit());
8050 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
8053 CGF.EmitIgnoredExpr(S.getCalcLastIteration());
8057 OMPLexicalScope
Scope(CGF, S, OMPD_taskloop,
false);
8067 [&S](CodeGenFunction &CGF) {
8068 emitOMPLoopBodyWithStopPoint(CGF, S,
8069 CodeGenFunction::JumpDest());
8071 [](CodeGenFunction &) {});
8076 CGF.EmitBranch(ContBlock);
8077 CGF.EmitBlock(ContBlock,
true);
8080 if (HasLastprivateClause) {
8081 CGF.EmitOMPLastprivateClauseFinal(
8083 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
8084 CGF.GetAddrOfLocalVar(*LIP),
false,
8085 (*LIP)->getType(), S.getBeginLoc())));
8088 CGF.EmitOMPLinearClauseFinal(S, [LIP, &S](CodeGenFunction &CGF) {
8089 return CGF.
Builder.CreateIsNotNull(
8091 (*LIP)->
getType(), S.getBeginLoc()));
8094 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
8095 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
8097 auto &&
CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
8099 OMPLoopScope PreInitScope(CGF, S);
8100 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S,
8101 OutlinedFn, SharedsTy,
8102 CapturedStruct, IfCond,
Data);
8104 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
8110 CGM.getOpenMPRuntime().emitTaskgroupRegion(
8112 [&S, &BodyGen, &TaskGen, &
Data](CodeGenFunction &CGF,
8132 OMPLexicalScope
Scope(*
this, S);
8144 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8145 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8156 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8157 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8168 OMPLexicalScope
Scope(*
this, S);
8169 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8180 OMPLexicalScope
Scope(*
this, S);
8181 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8187 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8192 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8193 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8205 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8210 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8211 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8223 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8228 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8229 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8241 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8246 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8247 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8261 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8265 const Expr *IfCond =
nullptr;
8267 IfCond =
C->getCondition();
8274 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8275 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8285 BindKind =
C->getBindKind();
8288 case OMPC_BIND_parallel:
8290 case OMPC_BIND_teams:
8292 case OMPC_BIND_thread:
8303 const auto *ForS = dyn_cast<ForStmt>(CS);
8314 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
8315 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_loop,
CodeGen);
8341 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
8346 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
8358 [](CodeGenFunction &) {
return nullptr; });
8363 std::string StatusMsg,
8367 StatusMsg +=
": DEVICE";
8369 StatusMsg +=
": HOST";
8376 llvm::dbgs() << StatusMsg <<
": " <<
FileName <<
": " << LineNo <<
"\n";
8399 CGF, OMPD_distribute, CodeGenDistribute,
false);
8428 CGF, OMPD_distribute, CodeGenDistribute,
false);
8461 llvm::Constant *
Addr;
8463 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8465 assert(Fn &&
Addr &&
8466 "Target device function emission failed for 'target teams loop'.");
8477 CGF, OMPD_target_parallel_loop,
false);
8493 llvm::Constant *
Addr;
8495 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8497 assert(Fn &&
Addr &&
"Target device function emission failed.");
8512 if (
const auto *SD = dyn_cast<OMPScanDirective>(&D)) {
8516 if (!D.hasAssociatedStmt() || !D.getAssociatedStmt())
8522 for (
const auto *
C : D.getClausesOfKind<OMPFirstprivateClause>()) {
8523 for (
const Expr *Ref :
C->varlist()) {
8527 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
8530 if (!CGF.LocalDeclMap.count(VD)) {
8542 if (
const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
8543 for (
const Expr *E : LD->counters()) {
8551 if (!CGF.LocalDeclMap.count(VD))
8555 for (
const auto *
C : D.getClausesOfKind<OMPOrderedClause>()) {
8556 if (!
C->getNumForLoops())
8558 for (
unsigned I = LD->getLoopsNumber(),
8559 E =
C->getLoopNumIterations().size();
8561 if (
const auto *VD = dyn_cast<OMPCapturedExprDecl>(
8564 if (!CGF.LocalDeclMap.count(VD))
8571 CGF.
EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
8574 if (D.getDirectiveKind() == OMPD_atomic ||
8575 D.getDirectiveKind() == OMPD_critical ||
8576 D.getDirectiveKind() == OMPD_section ||
8577 D.getDirectiveKind() == OMPD_master ||
8578 D.getDirectiveKind() == OMPD_masked ||
8579 D.getDirectiveKind() == OMPD_unroll ||
8580 D.getDirectiveKind() == OMPD_assume) {
8585 OMPSimdLexicalScope
Scope(*
this, D);
8586 CGM.getOpenMPRuntime().emitInlinedDirective(
8589 : 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 clause 'aligned' in the 'pragma omp ...' directives.
This represents 'bind' clause in the 'pragma omp ...' directives.
This represents 'pragma omp cancel' directive.
OpenMPDirectiveKind getCancelRegion() const
Get cancellation region for the current cancellation point.
This represents 'pragma omp cancellation point' directive.
OpenMPDirectiveKind getCancelRegion() const
Get cancellation region for the current cancellation point.
This represents clause 'copyin' in the 'pragma omp ...' directives.
This represents clause 'copyprivate' in the 'pragma omp ...' directives.
This represents implicit clause 'depend' for the 'pragma omp task' directive.
This represents implicit clause 'depobj' for the 'pragma omp depobj' directive. This clause does not ...
This represents 'destroy' clause in the 'pragma omp depobj' directive or the 'pragma omp interop' dir...
This represents 'device' clause in the 'pragma omp ...' directive.
This represents 'dist_schedule' clause in the 'pragma omp ...' directive.
This represents 'pragma omp distribute' directive.
This represents 'pragma omp distribute parallel for' composite directive.
This represents 'pragma omp distribute parallel for simd' composite directive.
This represents 'pragma omp distribute simd' composite directive.
This represents the 'doacross' clause for the 'pragma omp ordered' directive.
This represents 'pragma omp error' directive.
This represents 'filter' clause in the 'pragma omp ...' directive.
This represents implicit clause 'flush' for the 'pragma omp flush' directive. This clause does not ex...
Represents the 'pragma omp fuse' loop transformation directive.
Stmt * getTransformedStmt() const
Gets the associated loops after the transformation.
This represents 'pragma omp loop' directive.
This represents 'grainsize' clause in the 'pragma omp ...' directive.
This represents 'hint' clause in the 'pragma omp ...' directive.
This represents clause 'inclusive' in the 'pragma omp scan' directive.
This represents the 'init' clause in 'pragma omp ...' directives.
Represents the 'pragma omp interchange' loop transformation directive.
Stmt * getTransformedStmt() const
Gets the associated loops after the transformation.
This represents 'pragma omp interop' directive.
This represents 'pragma omp masked' directive.
This represents 'pragma omp masked taskloop' directive.
This represents 'pragma omp masked taskloop simd' directive.
This represents 'pragma omp master taskloop' directive.
This represents 'pragma omp master taskloop simd' directive.
This represents 'nogroup' clause in the 'pragma omp ...' directive.
This represents 'num_tasks' clause in the 'pragma omp ...' directive.
This represents 'num_teams' clause in the 'pragma omp ...' directive.
This represents 'order' clause in the 'pragma omp ...' directive.
This represents 'pragma omp parallel masked taskloop' directive.
This represents 'pragma omp parallel masked taskloop simd' directive.
This represents 'pragma omp parallel master taskloop' directive.
This represents 'pragma omp parallel master taskloop simd' directive.
This represents 'priority' clause in the 'pragma omp ...' directive.
Represents the 'pragma omp reverse' loop transformation directive.
Stmt * getTransformedStmt() const
Gets/sets the associated loops after the transformation, i.e.
This represents 'simd' clause in the 'pragma omp ...' directive.
This represents 'pragma omp scan' directive.
This represents the 'pragma omp stripe' loop transformation directive.
Stmt * getTransformedStmt() const
Gets/sets the associated loops after striping.
This represents 'pragma omp target data' directive.
This represents 'pragma omp target' directive.
This represents 'pragma omp target enter data' directive.
This represents 'pragma omp target exit data' directive.
This represents 'pragma omp target parallel' directive.
This represents 'pragma omp target parallel for' directive.
bool hasCancel() const
Return true if current directive has inner cancel directive.
This represents 'pragma omp target parallel for simd' directive.
This represents 'pragma omp target parallel loop' directive.
This represents 'pragma omp target simd' directive.
This represents 'pragma omp target teams' directive.
This represents 'pragma omp target teams distribute' combined directive.
This represents 'pragma omp target teams distribute parallel for' combined directive.
This represents 'pragma omp target teams distribute parallel for simd' combined directive.
This represents 'pragma omp target teams distribute simd' combined directive.
This represents 'pragma omp target teams loop' directive.
bool canBeParallelFor() const
Return true if current loop directive's associated loop can be a parallel for.
This represents 'pragma omp target update' directive.
This represents 'pragma omp taskloop' directive.
This represents 'pragma omp taskloop simd' directive.
This represents 'pragma omp teams' directive.
This represents 'pragma omp teams distribute' directive.
This represents 'pragma omp teams distribute parallel for' composite directive.
This represents 'pragma omp teams distribute parallel for simd' composite directive.
This represents 'pragma omp teams distribute simd' combined directive.
This represents 'pragma omp teams loop' directive.
This represents 'thread_limit' clause in the 'pragma omp ...' directive.
This represents the 'pragma omp tile' loop transformation directive.
Stmt * getTransformedStmt() const
Gets/sets the associated loops after tiling.
This represents the 'pragma omp unroll' loop transformation directive.
This represents the 'use' clause in 'pragma omp ...' directives.
This represents clause 'use_device_addr' in the 'pragma omp ...' directives.
This represents clause 'use_device_ptr' in the 'pragma omp ...' directives.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
TranslationUnitDecl * getTranslationUnitDecl() const
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
QualType getUIntPtrType() const
Return a type compatible with "uintptr_t" (C99 7.18.1.4), as defined by the target.
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
unsigned getOpenMPDefaultSimdAlign(QualType T) const
Get default simd alignment of the specified complete type in bits.
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
CanQualType getCanonicalTagType(const TagDecl *TD) const
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Represents an attribute applied to a statement.
ArrayRef< const Attr * > getAttrs() const
static BinaryOperator * Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, FPOptionsOverride FPFeatures)
Represents the body of a CapturedStmt, and serves as its DeclContext.
unsigned getContextParamPosition() const
static CapturedDecl * Create(ASTContext &C, DeclContext *DC, unsigned NumParams)
param_iterator param_end() const
Retrieve an iterator one past the last parameter decl.
param_iterator param_begin() const
Retrieve an iterator pointing to the first parameter decl.
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
ImplicitParamDecl * getParam(unsigned i) const
This captures a statement into a function.
SourceLocation getEndLoc() const LLVM_READONLY
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
const RecordDecl * getCapturedRecordDecl() const
Retrieve the record declaration for captured variables.
Stmt * getCapturedStmt()
Retrieve the statement being captured.
capture_init_iterator capture_init_begin()
Retrieve the first initialization argument.
SourceLocation getBeginLoc() const LLVM_READONLY
capture_init_iterator capture_init_end()
Retrieve the iterator pointing one past the last initialization argument.
Expr *const * const_capture_init_iterator
Const iterator that walks over the capture initialization arguments.
CharUnits - This is an opaque type for sizes expressed in character units.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
std::string SampleProfileFile
Name of the profile file to use with -fprofile-sample-use.
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
CharUnits getAlignment() const
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
Address withAlignment(CharUnits NewAlignment) const
Return address with different alignment, but same pointer and element type.
llvm::PointerType * getType() const
Return the type of the pointer value.
static AggValueSlot ignored()
ignored - Returns an aggregate value slot indicating that the aggregate value is being ignored.
static ApplyDebugLocation CreateDefaultArtificial(CodeGenFunction &CGF, SourceLocation TemporaryLocation)
Apply TemporaryLocation if it is valid.
Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
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 EmitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &S)
void EmitOMPMaskedTaskLoopSimdDirective(const OMPMaskedTaskLoopSimdDirective &S)
std::pair< bool, RValue > EmitOMPAtomicSimpleUpdateExpr(LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart, llvm::AtomicOrdering AO, SourceLocation Loc, const llvm::function_ref< RValue(RValue)> CommonGen)
Emit atomic update code for constructs: X = X BO E or X = E BO E.
VlaSizePair getVLASize(const VariableArrayType *vla)
Returns an LLVM value that corresponds to the size, in non-variably-sized elements,...
void EmitOMPParallelDirective(const OMPParallelDirective &S)
void EmitOMPTaskDirective(const OMPTaskDirective &S)
void EmitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective &S)
void EmitOMPDistributeParallelForDirective(const OMPDistributeParallelForDirective &S)
void EmitOMPAssumeDirective(const OMPAssumeDirective &S)
int ExpectedOMPLoopDepth
Number of nested loop to be consumed by the last surrounding loop-associated directive.
void EmitOMPPrivateClause(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
void EmitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &S)
ASTContext & getContext() const
void EmitStopPoint(const Stmt *S)
EmitStopPoint - Emit a debug stoppoint if we are emitting debug info.
void EmitOMPTargetUpdateDirective(const OMPTargetUpdateDirective &S)
llvm::Value * EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, AlignmentSource Source=AlignmentSource::Type, bool isNontemporal=false)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
void EmitOMPTargetTeamsGenericLoopDirective(const OMPTargetTeamsGenericLoopDirective &S)
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
void EmitAutoVarCleanups(const AutoVarEmission &emission)
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
SmallVector< llvm::CanonicalLoopInfo *, 4 > OMPLoopNestStack
List of recently emitted OMPCanonicalLoops.
void EmitOMPTeamsDistributeParallelForDirective(const OMPTeamsDistributeParallelForDirective &S)
llvm::AtomicRMWInst * emitAtomicRMWInst(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val, llvm::AtomicOrdering Order=llvm::AtomicOrdering::SequentiallyConsistent, llvm::SyncScope::ID SSID=llvm::SyncScope::System, const AtomicExpr *AE=nullptr)
Emit an atomicrmw instruction, and applying relevant metadata when applicable.
void EmitOMPFuseDirective(const OMPFuseDirective &S)
void EmitOMPTargetTeamsDistributeDirective(const OMPTargetTeamsDistributeDirective &S)
void EmitOMPUseDevicePtrClause(const OMPUseDevicePtrClause &C, OMPPrivateScope &PrivateScope, const llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap)
RValue EmitAnyExpr(const Expr *E, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
EmitAnyExpr - Emit code to compute the specified expression which can have any type.
void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs={})
EmitStmt - Emit the code for the statement.
llvm::DenseMap< const ValueDecl *, FieldDecl * > LambdaCaptureFields
void EmitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &S)
llvm::Type * ConvertTypeForMem(QualType T)
void EmitOMPInnerLoop(const OMPExecutableDirective &S, bool RequiresCleanup, const Expr *LoopCond, const Expr *IncExpr, const llvm::function_ref< void(CodeGenFunction &)> BodyGen, const llvm::function_ref< void(CodeGenFunction &)> PostIncGen)
Emit inner loop of the worksharing/simd construct.
void EmitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective &S)
static void EmitOMPTargetTeamsDistributeParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForDirective &S)
void EmitOMPTargetDirective(const OMPTargetDirective &S)
static void EmitOMPTargetParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForSimdDirective &S)
Emit device code for the target parallel for simd directive.
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
llvm::BasicBlock * OMPScanExitBlock
void EmitOMPTeamsDirective(const OMPTeamsDirective &S)
void EmitSimpleOMPExecutableDirective(const OMPExecutableDirective &D)
Emit simple code for OpenMP directives in Simd-only mode.
void EmitOMPErrorDirective(const OMPErrorDirective &S)
void EmitOMPTargetTaskBasedDirective(const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen, OMPTargetDataInfo &InputInfo)
void EmitOMPParallelMaskedTaskLoopSimdDirective(const OMPParallelMaskedTaskLoopSimdDirective &S)
void EmitOMPTargetTeamsDirective(const OMPTargetTeamsDirective &S)
void EmitOMPTargetDataDirective(const OMPTargetDataDirective &S)
Address GenerateCapturedStmtArgument(const CapturedStmt &S)
bool EmitOMPLastprivateClauseInit(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
Emit initial code for lastprivate variables.
static void EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForSimdDirective &S)
Emit device code for the target teams distribute parallel for simd directive.
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
llvm::Function * GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S, const OMPExecutableDirective &D)
void EmitOMPSimdDirective(const OMPSimdDirective &S)
RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
Address EmitLoadOfReference(LValue RefLVal, LValueBaseInfo *PointeeBaseInfo=nullptr, TBAAAccessInfo *PointeeTBAAInfo=nullptr)
void EmitOMPParallelGenericLoopDirective(const OMPLoopDirective &S)
void EmitOMPTargetSimdDirective(const OMPTargetSimdDirective &S)
void EmitOMPTeamsGenericLoopDirective(const OMPTeamsGenericLoopDirective &S)
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
bool EmitOMPLinearClauseInit(const OMPLoopDirective &D)
Emit initial code for linear variables.
static void EmitOMPTargetParallelGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelGenericLoopDirective &S)
Emit device code for the target parallel loop directive.
void EmitOMPUnrollDirective(const OMPUnrollDirective &S)
void EmitOMPStripeDirective(const OMPStripeDirective &S)
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitOMPSingleDirective(const OMPSingleDirective &S)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
llvm::function_ref< void(CodeGenFunction &, SourceLocation, const unsigned, const bool)> CodeGenOrderedTy
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
llvm::Value * EmitFromMemory(llvm::Value *Value, QualType Ty)
EmitFromMemory - Change a scalar value from its memory representation to its value representation.
static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S)
Emit device code for the target simd directive.
llvm::Function * GenerateCapturedStmtFunction(const CapturedStmt &S)
Creates the outlined function for a CapturedStmt.
static void EmitOMPTargetParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForDirective &S)
Emit device code for the target parallel for directive.
uint64_t getProfileCount(const Stmt *S)
Get the profiler's count for the given statement.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)
ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant,...
static void EmitOMPTargetTeamsGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsGenericLoopDirective &S)
Emit device code for the target teams loop directive.
void EmitOMPTileDirective(const OMPTileDirective &S)
void EmitDecl(const Decl &D, bool EvaluateConditionDecl=false)
EmitDecl - Emit a declaration.
void EmitOMPAtomicDirective(const OMPAtomicDirective &S)
llvm::BasicBlock * OMPAfterScanBlock
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
ConstantEmission tryEmitAsConstant(const DeclRefExpr *RefExpr)
Try to emit a reference to the given value without producing it as an l-value.
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
void EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst)
Store of global named registers are always calls to intrinsics.
void EmitOMPParallelMasterTaskLoopDirective(const OMPParallelMasterTaskLoopDirective &S)
void EmitOMPDistributeParallelForSimdDirective(const OMPDistributeParallelForSimdDirective &S)
void EmitOMPSectionDirective(const OMPSectionDirective &S)
void EnsureInsertPoint()
EnsureInsertPoint - Ensure that an insertion point is defined so that emitted IR has a place to go.
void EmitOMPForSimdDirective(const OMPForSimdDirective &S)
llvm::LLVMContext & getLLVMContext()
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
void emitAlignmentAssumption(llvm::Value *PtrValue, QualType Ty, SourceLocation Loc, SourceLocation AssumptionLoc, llvm::Value *Alignment, llvm::Value *OffsetValue=nullptr)
static void EmitOMPTargetTeamsDistributeSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeSimdDirective &S)
Emit device code for the target teams distribute simd directive.
llvm::function_ref< void(CodeGenFunction &, const OMPLoopDirective &, JumpDest)> CodeGenLoopTy
llvm::Value * EmitScalarConversion(llvm::Value *Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified type to the specified destination type, both of which are LLVM s...
bool isTrivialInitializer(const Expr *Init)
Determine whether the given initializer is trivial in the sense that it requires no code to be genera...
void EmitOMPParallelMasterDirective(const OMPParallelMasterDirective &S)
void EmitOMPTaskBasedDirective(const OMPExecutableDirective &S, const OpenMPDirectiveKind CapturedRegion, const RegionCodeGenTy &BodyGen, const TaskGenTy &TaskGen, OMPTaskDataTy &Data)
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
void EmitOMPForDirective(const OMPForDirective &S)
void EmitOMPLinearClauseFinal(const OMPLoopDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
Emit final code for linear clauses.
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
void EmitExprAsInit(const Expr *init, const ValueDecl *D, LValue lvalue, bool capturedByInit)
EmitExprAsInit - Emits the code necessary to initialize a location in memory with the given initializ...
void EmitOMPSimdFinal(const OMPLoopDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
This class organizes the cross-function state that is used while generating LLVM code.
void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)
Set the attributes on the LLVM function for the given decl and function info.
llvm::Module & getModule() const
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
CodeGenTypes & getTypes()
const llvm::DataLayout & getDataLayout() const
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
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.
static OMPClauseWithPreInit * get(OMPClause *C)
This is a basic class for representing single OpenMP clause.
This represents 'final' clause in the 'pragma omp ...' directive.
Representation of the 'full' clause of the 'pragma omp unroll' directive.
This represents 'if' clause in the 'pragma omp ...' directive.
This represents 'num_threads' clause in the 'pragma omp ...' directive.
Representation of the 'partial' clause of the 'pragma omp unroll' directive.
This represents 'safelen' clause in the 'pragma omp ...' directive.
This represents 'simdlen' clause in the 'pragma omp ...' directive.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
PointerType - C99 6.7.5.1 - Pointer Declarators.
Represents an unpacked "presumed" location which can be presented to the user.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
If a crash happens while one of these objects are live, the message is printed out along with the spe...
A (possibly-)qualified type.
bool 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.
Privates[]
This class represents the 'transparent' clause in the 'pragma omp task' directive.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
@ OK_Ordinary
An ordinary object is located at an address in memory.
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ Tile
'tile' clause, allowed on 'loop' and Combined constructs.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_unknown
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
@ OMPC_DIST_SCHEDULE_unknown
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
bool isOpenMPGenericLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive constitutes a 'loop' directive in the outermost nest.
OpenMPBindClauseKind
OpenMP bindings for the 'bind' clause.
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
bool IsXLHSInRHSPart
True if UE has the first form and false if the second.
bool IsPostfixUpdate
True if original value of 'x' must be stored in 'v', not an updated one.
@ Dtor_Complete
Complete object dtor.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of the composite or combined directives that need loop ...
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPNumThreadsClauseModifier
@ OMPC_NUMTHREADS_unknown
bool IsFailOnly
True if 'v' is updated only when the condition is false (compare capture only).
U cast(CodeGen::Address addr)
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
@ ThreadPrivateVar
Parameter for Thread private variable.
@ Other
Other implicit parameter.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
A jump destination is an abstract label, branching to which may require a jump out through normal cle...
llvm::BasicBlock * getBlock() const
static Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc)
Returns address of the threadprivate variable for the current thread.
llvm::OpenMPIRBuilder::InsertPointTy InsertPointTy
static void EmitOMPOutlinedRegionBody(CodeGenFunction &CGF, const Stmt *RegionBodyStmt, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Twine RegionName)
Emit the body of an OMP region that will be outlined in OpenMPIRBuilder::finalize().
static Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD)
Gets the OpenMP-specific address of the local variable /p VD.
static void EmitCaptureStmt(CodeGenFunction &CGF, InsertPointTy CodeGenIP, llvm::BasicBlock &FiniBB, llvm::Function *Fn, ArrayRef< llvm::Value * > Args)
static std::string getNameWithSeparators(ArrayRef< StringRef > Parts, StringRef FirstSeparator=".", StringRef Separator=".")
Get the platform-specific name separator.
static void FinalizeOMPRegion(CodeGenFunction &CGF, InsertPointTy IP)
Emit the Finalization for an OMP region.
static void EmitOMPInlinedRegionBody(CodeGenFunction &CGF, const Stmt *RegionBodyStmt, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Twine RegionName)
Emit the body of an OMP region.
unsigned NumberOfTargetItems
Address BasePointersArray
llvm::PointerType * VoidPtrTy
llvm::IntegerType * Int64Ty
llvm::IntegerType * SizeTy
SmallVector< const Expr *, 4 > DepExprs
EvalResult is a struct with detailed info about an evaluated expression.
Extra information about a function prototype.
Scheduling data for loop-based OpenMP directives.
OpenMPScheduleClauseModifier M2
OpenMPScheduleClauseModifier M1
OpenMPScheduleClauseKind Schedule