30#include "llvm/ADT/SmallSet.h"
31#include "llvm/BinaryFormat/Dwarf.h"
32#include "llvm/Frontend/OpenMP/OMPConstants.h"
33#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
34#include "llvm/IR/Constants.h"
35#include "llvm/IR/DebugInfoMetadata.h"
36#include "llvm/IR/Instructions.h"
37#include "llvm/IR/IntrinsicInst.h"
38#include "llvm/IR/Metadata.h"
39#include "llvm/Support/AtomicOrdering.h"
40#include "llvm/Support/Debug.h"
44using namespace llvm::omp;
46#define TTL_CODEGEN_TYPE "target-teams-loop-codegen"
57 for (
const auto *
C : S.clauses()) {
59 if (
const auto *PreInit =
60 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
61 for (
const auto *I : PreInit->decls()) {
62 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
65 CodeGenFunction::AutoVarEmission Emission =
74 CodeGenFunction::OMPPrivateScope InlinedShareds;
76 static bool isCapturedVar(CodeGenFunction &CGF,
const VarDecl *VD) {
85 CodeGenFunction &CGF,
const OMPExecutableDirective &S,
86 const std::optional<OpenMPDirectiveKind> CapturedRegion = std::nullopt,
87 const bool EmitPreInitStmt =
true)
91 emitPreInitStmt(CGF, S);
94 assert(S.hasAssociatedStmt() &&
95 "Expected associated statement for inlined directive.");
96 const CapturedStmt *CS = S.getCapturedStmt(*CapturedRegion);
98 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
99 auto *VD =
C.getCapturedVar();
101 "Canonical decl must be captured.");
105 InlinedShareds.isGlobalVarCaptured(VD)),
110 (void)InlinedShareds.Privatize();
116class OMPParallelScope final :
public OMPLexicalScope {
117 bool EmitPreInitStmt(
const OMPExecutableDirective &S) {
125 OMPParallelScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
126 : OMPLexicalScope(CGF, S, std::nullopt,
127 EmitPreInitStmt(S)) {}
132class OMPTeamsScope final :
public OMPLexicalScope {
133 bool EmitPreInitStmt(
const OMPExecutableDirective &S) {
140 OMPTeamsScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
141 : OMPLexicalScope(CGF, S, std::nullopt,
142 EmitPreInitStmt(S)) {}
148 void emitPreInitStmt(CodeGenFunction &CGF,
const OMPLoopBasedDirective &S) {
149 const Stmt *PreInits;
150 CodeGenFunction::OMPMapVars PreCondVars;
151 if (
auto *LD = dyn_cast<OMPLoopDirective>(&S)) {
152 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
153 for (
const auto *E : LD->counters()) {
160 for (
const auto *
C : LD->getClausesOfKind<OMPPrivateClause>()) {
161 for (
const Expr *IRef :
C->varlist()) {
164 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
165 QualType OrigVDTy = OrigVD->getType().getNonReferenceType();
175 (void)PreCondVars.
apply(CGF);
177 (void)OMPLoopBasedDirective::doForAllLoops(
178 LD->getInnermostCapturedStmt()->getCapturedStmt(),
179 true, LD->getLoopsNumber(),
180 [&CGF](
unsigned Cnt,
const Stmt *CurStmt) {
181 if (const auto *CXXFor = dyn_cast<CXXForRangeStmt>(CurStmt)) {
182 if (const Stmt *Init = CXXFor->getInit())
184 CGF.EmitStmt(CXXFor->getRangeStmt());
185 CGF.EmitStmt(CXXFor->getEndStmt());
189 PreInits = LD->getPreInits();
190 }
else if (
const auto *
Tile = dyn_cast<OMPTileDirective>(&S)) {
191 PreInits =
Tile->getPreInits();
192 }
else if (
const auto *Stripe = dyn_cast<OMPStripeDirective>(&S)) {
193 PreInits = Stripe->getPreInits();
194 }
else if (
const auto *Unroll = dyn_cast<OMPUnrollDirective>(&S)) {
195 PreInits = Unroll->getPreInits();
196 }
else if (
const auto *Reverse = dyn_cast<OMPReverseDirective>(&S)) {
197 PreInits = Reverse->getPreInits();
198 }
else if (
const auto *Interchange =
199 dyn_cast<OMPInterchangeDirective>(&S)) {
200 PreInits = Interchange->getPreInits();
202 llvm_unreachable(
"Unknown loop-based directive kind.");
208 SmallVector<const Stmt *> PreInitStmts;
209 if (
auto *PreInitCompound = dyn_cast<CompoundStmt>(PreInits))
210 llvm::append_range(PreInitStmts, PreInitCompound->body());
212 PreInitStmts.push_back(PreInits);
214 for (
const Stmt *S : PreInitStmts) {
217 if (
auto *PreInitDecl = dyn_cast<DeclStmt>(S)) {
218 for (
Decl *I : PreInitDecl->decls())
231 emitPreInitStmt(CGF, S);
236 CodeGenFunction::OMPPrivateScope InlinedShareds;
238 static bool isCapturedVar(CodeGenFunction &CGF,
const VarDecl *VD) {
246 OMPSimdLexicalScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
248 InlinedShareds(CGF) {
249 for (
const auto *
C : S.clauses()) {
250 if (const auto *CPI = OMPClauseWithPreInit::get(C)) {
251 if (const auto *PreInit =
252 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
253 for (const auto *I : PreInit->decls()) {
254 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
255 CGF.EmitVarDecl(cast<VarDecl>(*I));
257 CodeGenFunction::AutoVarEmission Emission =
258 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
259 CGF.EmitAutoVarCleanups(Emission);
263 }
else if (
const auto *UDP = dyn_cast<OMPUseDevicePtrClause>(
C)) {
264 for (
const Expr *E : UDP->varlist()) {
266 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
269 }
else if (
const auto *UDP = dyn_cast<OMPUseDeviceAddrClause>(
C)) {
270 for (
const Expr *E : UDP->varlist()) {
272 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
279 if (
const auto *TG = dyn_cast<OMPTaskgroupDirective>(&S)) {
280 if (
const Expr *E = TG->getReductionRef())
285 llvm::DenseSet<CanonicalDeclPtr<const Decl>> CopyArrayTemps;
286 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
287 if (C->getModifier() != OMPC_REDUCTION_inscan)
289 for (const Expr *E : C->copy_array_temps())
290 CopyArrayTemps.insert(cast<DeclRefExpr>(E)->getDecl());
292 const auto *CS = cast_or_null<CapturedStmt>(S.getAssociatedStmt());
295 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
296 auto *VD =
C.getCapturedVar();
297 if (CopyArrayTemps.contains(VD))
300 "Canonical decl must be captured.");
301 DeclRefExpr DRE(CGF.
getContext(),
const_cast<VarDecl *
>(VD),
302 isCapturedVar(CGF, VD) ||
304 InlinedShareds.isGlobalVarCaptured(VD)),
312 (void)InlinedShareds.Privatize();
323 if (Kind != OMPD_loop)
328 BindKind =
C->getBindKind();
331 case OMPC_BIND_parallel:
333 case OMPC_BIND_teams:
334 return OMPD_distribute;
335 case OMPC_BIND_thread:
347 if (
const auto *OrigDRE = dyn_cast<DeclRefExpr>(E)) {
348 if (
const auto *OrigVD = dyn_cast<VarDecl>(OrigDRE->getDecl())) {
349 OrigVD = OrigVD->getCanonicalDecl();
355 OrigDRE->getType(),
VK_LValue, OrigDRE->getExprLoc());
364 llvm::Value *Size =
nullptr;
365 auto SizeInChars =
C.getTypeSizeInChars(Ty);
366 if (SizeInChars.isZero()) {
374 SizeInChars =
C.getTypeSizeInChars(Ty);
375 if (SizeInChars.isZero())
376 return llvm::ConstantInt::get(
SizeTy, 0);
377 return Builder.CreateNUWMul(Size,
CGM.getSize(SizeInChars));
379 return CGM.getSize(SizeInChars);
389 I != E; ++I, ++CurField, ++CurCap) {
390 if (CurField->hasCapturedVLAType()) {
393 CapturedVars.push_back(Val);
394 }
else if (CurCap->capturesThis()) {
395 CapturedVars.push_back(CXXThisValue);
396 }
else if (CurCap->capturesVariableByCopy()) {
401 if (!CurField->getType()->isAnyPointerType()) {
405 Twine(CurCap->getCapturedVar()->getName(),
".casted"));
421 CapturedVars.push_back(CV);
423 assert(CurCap->capturesVariable() &&
"Expected capture by reference.");
444 if (
T->isLValueReferenceType())
445 return C.getLValueReferenceType(
448 if (
T->isPointerType())
450 if (
const ArrayType *A =
T->getAsArrayTypeUnsafe()) {
451 if (
const auto *VLA = dyn_cast<VariableArrayType>(A))
453 if (!A->isVariablyModifiedType())
454 return C.getCanonicalType(
T);
456 return C.getCanonicalParamType(
T);
461struct FunctionOptions {
463 const CapturedStmt *S =
nullptr;
466 const bool UIntPtrCastRequired =
true;
469 const bool RegisterCastedArgsOnly =
false;
471 const StringRef FunctionName;
474 const bool IsDeviceKernel =
false;
475 explicit FunctionOptions(
const CapturedStmt *S,
bool UIntPtrCastRequired,
476 bool RegisterCastedArgsOnly, StringRef FunctionName,
477 SourceLocation Loc,
bool IsDeviceKernel)
478 : S(S), UIntPtrCastRequired(UIntPtrCastRequired),
479 RegisterCastedArgsOnly(UIntPtrCastRequired && RegisterCastedArgsOnly),
480 FunctionName(FunctionName), Loc(Loc), IsDeviceKernel(IsDeviceKernel) {}
486 llvm::MapVector<
const Decl *, std::pair<const VarDecl *, Address>>
488 llvm::DenseMap<
const Decl *, std::pair<const Expr *, llvm::Value *>>
490 llvm::Value *&CXXThisValue,
const FunctionOptions &FO) {
493 assert(CD->
hasBody() &&
"missing CapturedDecl body");
495 CXXThisValue =
nullptr;
507 if (!FO.UIntPtrCastRequired) {
527 if (FO.UIntPtrCastRequired &&
528 ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) ||
529 I->capturesVariableArrayType()))
532 if (I->capturesVariable() || I->capturesVariableByCopy()) {
533 CapVar = I->getCapturedVar();
535 }
else if (I->capturesThis()) {
538 assert(I->capturesVariableArrayType());
541 if (ArgType->isVariablyModifiedType())
548 }
else if (DebugFunctionDecl && (CapVar || I->capturesThis())) {
550 Ctx, DebugFunctionDecl,
551 CapVar ? CapVar->
getBeginLoc() : FD->getBeginLoc(),
552 CapVar ? CapVar->
getLocation() : FD->getLocation(), II, ArgType,
558 Args.emplace_back(Arg);
560 TargetArgs.emplace_back(
561 FO.UIntPtrCastRequired
582 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
586 F->setDoesNotThrow();
587 F->setDoesNotRecurse();
591 F->removeFnAttr(llvm::Attribute::NoInline);
592 F->addFnAttr(llvm::Attribute::AlwaysInline);
597 FO.UIntPtrCastRequired ? FO.Loc : FO.S->
getBeginLoc(),
598 FO.UIntPtrCastRequired ? FO.Loc
605 if (!FO.UIntPtrCastRequired && Args[Cnt] != TargetArgs[Cnt]) {
613 if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
614 const VarDecl *CurVD = I->getCapturedVar();
615 if (!FO.RegisterCastedArgsOnly)
616 LocalAddrs.insert({Args[Cnt], {CurVD, LocalAddr}});
624 if (FD->hasCapturedVLAType()) {
625 if (FO.UIntPtrCastRequired) {
628 Args[Cnt]->getName(), ArgLVal),
633 VLASizes.try_emplace(Args[Cnt], VAT->
getSizeExpr(), ExprArg);
634 }
else if (I->capturesVariable()) {
635 const VarDecl *Var = I->getCapturedVar();
637 Address ArgAddr = ArgLVal.getAddress();
638 if (ArgLVal.getType()->isLValueReferenceType()) {
641 assert(ArgLVal.getType()->isPointerType());
643 ArgAddr, ArgLVal.getType()->castAs<
PointerType>());
645 if (!FO.RegisterCastedArgsOnly) {
649 }
else if (I->capturesVariableByCopy()) {
650 assert(!FD->getType()->isAnyPointerType() &&
651 "Not expecting a captured pointer.");
652 const VarDecl *Var = I->getCapturedVar();
653 LocalAddrs.insert({Args[Cnt],
654 {Var, FO.UIntPtrCastRequired
656 CGF, I->getLocation(), FD->getType(),
657 Args[Cnt]->getName(), ArgLVal)
658 : ArgLVal.getAddress()}});
661 assert(I->capturesThis());
663 LocalAddrs.insert({Args[Cnt], {
nullptr, ArgLVal.getAddress()}});
677 "CapturedStmtInfo should be set when generating the captured function");
680 bool NeedWrapperFunction =
683 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs,
685 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes,
688 llvm::raw_svector_ostream Out(Buffer);
691 bool IsDeviceKernel =
CGM.getOpenMPRuntime().isGPU() &&
693 D.getCapturedStmt(OMPD_target) == &S;
694 CodeGenFunction WrapperCGF(
CGM,
true);
695 llvm::Function *WrapperF =
nullptr;
696 if (NeedWrapperFunction) {
699 FunctionOptions WrapperFO(&S,
true,
706 WrapperCGF.CXXThisValue, WrapperFO);
709 FunctionOptions FO(&S, !NeedWrapperFunction,
false,
710 Out.str(), Loc, !NeedWrapperFunction && IsDeviceKernel);
712 *
this, WrapperArgs, WrapperLocalAddrs, WrapperVLASizes, CXXThisValue, FO);
714 for (
const auto &LocalAddrPair : WrapperLocalAddrs) {
715 if (LocalAddrPair.second.first) {
716 LocalScope.addPrivate(LocalAddrPair.second.first,
717 LocalAddrPair.second.second);
720 (void)LocalScope.Privatize();
721 for (
const auto &VLASizePair : WrapperVLASizes)
722 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
725 LocalScope.ForceCleanup();
727 if (!NeedWrapperFunction)
731 WrapperF->removeFromParent();
732 F->getParent()->getFunctionList().insertAfter(F->getIterator(), WrapperF);
735 auto *PI = F->arg_begin();
736 for (
const auto *Arg : Args) {
738 auto I = LocalAddrs.find(Arg);
739 if (I != LocalAddrs.end()) {
742 I->second.first ? I->second.first->getType() : Arg->getType(),
748 auto EI = VLASizes.find(Arg);
749 if (EI != VLASizes.end()) {
761 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
777 llvm::Value *NumElements =
emitArrayLength(ArrayTy, ElementTy, DestAddr);
784 DestBegin, NumElements);
789 llvm::Value *IsEmpty =
790 Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arraycpy.isempty");
791 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
794 llvm::BasicBlock *EntryBB =
Builder.GetInsertBlock();
799 llvm::PHINode *SrcElementPHI =
800 Builder.CreatePHI(SrcBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
801 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
806 llvm::PHINode *DestElementPHI =
Builder.CreatePHI(
807 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
808 DestElementPHI->addIncoming(DestBegin, EntryBB);
814 CopyGen(DestElementCurrent, SrcElementCurrent);
817 llvm::Value *DestElementNext =
819 1,
"omp.arraycpy.dest.element");
820 llvm::Value *SrcElementNext =
822 1,
"omp.arraycpy.src.element");
825 Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
826 Builder.CreateCondBr(Done, DoneBB, BodyBB);
827 DestElementPHI->addIncoming(DestElementNext,
Builder.GetInsertBlock());
828 SrcElementPHI->addIncoming(SrcElementNext,
Builder.GetInsertBlock());
838 const auto *BO = dyn_cast<BinaryOperator>(
Copy);
839 if (BO && BO->getOpcode() == BO_Assign) {
848 DestAddr, SrcAddr, OriginalType,
876 bool DeviceConstTarget =
getLangOpts().OpenMPIsTargetDevice &&
878 bool FirstprivateIsLastprivate =
false;
879 llvm::DenseMap<const VarDecl *, OpenMPLastprivateModifier> Lastprivates;
881 for (
const auto *D :
C->varlist())
882 Lastprivates.try_emplace(
886 llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
891 bool MustEmitFirstprivateCopy =
892 CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown;
894 const auto *IRef =
C->varlist_begin();
895 const auto *InitsRef =
C->inits().begin();
896 for (
const Expr *IInit :
C->private_copies()) {
898 bool ThisFirstprivateIsLastprivate =
899 Lastprivates.count(OrigVD->getCanonicalDecl()) > 0;
902 if (!MustEmitFirstprivateCopy && !ThisFirstprivateIsLastprivate && FD &&
904 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
905 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
912 if (DeviceConstTarget && OrigVD->getType().isConstant(
getContext()) &&
914 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
915 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
920 FirstprivateIsLastprivate =
921 FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate;
922 if (EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()).second) {
942 assert(!CE &&
"Expected non-constant firstprivate.");
949 if (
Type->isArrayType()) {
965 RunCleanupsScope InitScope(*this);
967 setAddrOfLocalVar(VDInit, SrcElement);
968 EmitAnyExprToMem(Init, DestElement,
969 Init->getType().getQualifiers(),
971 LocalDeclMap.erase(VDInit);
982 setAddrOfLocalVar(VDInit, OriginalAddr);
984 LocalDeclMap.erase(VDInit);
986 if (ThisFirstprivateIsLastprivate &&
987 Lastprivates[OrigVD->getCanonicalDecl()] ==
988 OMPC_LASTPRIVATE_conditional) {
993 (*IRef)->getExprLoc());
994 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
998 LocalDeclMap.erase(VD);
999 setAddrOfLocalVar(VD, VDAddr);
1001 IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1003 assert(IsRegistered &&
1004 "firstprivate var already registered as private");
1012 return FirstprivateIsLastprivate && !EmittedAsFirstprivate.empty();
1020 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
1022 auto IRef =
C->varlist_begin();
1023 for (
const Expr *IInit :
C->private_copies()) {
1025 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
1031 assert(IsRegistered &&
"private var already registered as private");
1047 llvm::DenseSet<const VarDecl *> CopiedVars;
1048 llvm::BasicBlock *CopyBegin =
nullptr, *CopyEnd =
nullptr;
1050 auto IRef =
C->varlist_begin();
1051 auto ISrcRef =
C->source_exprs().begin();
1052 auto IDestRef =
C->destination_exprs().begin();
1053 for (
const Expr *AssignOp :
C->assignment_ops()) {
1062 getContext().getTargetInfo().isTLSSupported()) {
1064 "Copyin threadprivates should have been captured!");
1068 LocalDeclMap.erase(VD);
1072 :
CGM.GetAddrOfGlobal(VD),
1073 CGM.getTypes().ConvertTypeForMem(VD->
getType()),
1078 if (CopiedVars.size() == 1) {
1084 auto *MasterAddrInt =
Builder.CreatePtrToInt(
1086 auto *PrivateAddrInt =
Builder.CreatePtrToInt(
1089 Builder.CreateICmpNE(MasterAddrInt, PrivateAddrInt), CopyBegin,
1095 const auto *DestVD =
1116 bool HasAtLeastOneLastprivate =
false;
1118 llvm::DenseSet<const VarDecl *> SIMDLCVs;
1121 for (
const Expr *
C : LoopDirective->counters()) {
1126 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1128 HasAtLeastOneLastprivate =
true;
1131 const auto *IRef =
C->varlist_begin();
1132 const auto *IDestRef =
C->destination_exprs().begin();
1133 for (
const Expr *IInit :
C->private_copies()) {
1139 if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) {
1140 const auto *DestVD =
1145 (*IRef)->getType(),
VK_LValue, (*IRef)->getExprLoc());
1150 if (IInit && !SIMDLCVs.count(OrigVD->getCanonicalDecl())) {
1153 if (
C->getKind() == OMPC_LASTPRIVATE_conditional) {
1154 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1156 setAddrOfLocalVar(VD, VDAddr);
1162 bool IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1163 assert(IsRegistered &&
1164 "lastprivate var already registered as private");
1172 return HasAtLeastOneLastprivate;
1177 llvm::Value *IsLastIterCond) {
1186 llvm::BasicBlock *ThenBB =
nullptr;
1187 llvm::BasicBlock *DoneBB =
nullptr;
1188 if (IsLastIterCond) {
1194 return C->getKind() == OMPC_LASTPRIVATE_conditional;
1196 CGM.getOpenMPRuntime().emitBarrierCall(*
this, D.getBeginLoc(),
1203 Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB);
1206 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1207 llvm::DenseMap<const VarDecl *, const Expr *> LoopCountersAndUpdates;
1208 if (
const auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) {
1209 auto IC = LoopDirective->counters().begin();
1210 for (
const Expr *F : LoopDirective->finals()) {
1214 AlreadyEmittedVars.insert(D);
1216 LoopCountersAndUpdates[D] = F;
1221 auto IRef =
C->varlist_begin();
1222 auto ISrcRef =
C->source_exprs().begin();
1223 auto IDestRef =
C->destination_exprs().begin();
1224 for (
const Expr *AssignOp :
C->assignment_ops()) {
1225 const auto *PrivateVD =
1228 const auto *CanonicalVD = PrivateVD->getCanonicalDecl();
1229 if (AlreadyEmittedVars.insert(CanonicalVD).second) {
1233 if (
const Expr *FinalExpr = LoopCountersAndUpdates.lookup(CanonicalVD))
1237 const auto *DestVD =
1241 if (
const auto *RefTy = PrivateVD->getType()->getAs<
ReferenceType>())
1243 Builder.CreateLoad(PrivateAddr),
1244 CGM.getTypes().ConvertTypeForMem(RefTy->getPointeeType()),
1245 CGM.getNaturalTypeAlignment(RefTy->getPointeeType()));
1247 if (
C->getKind() == OMPC_LASTPRIVATE_conditional)
1248 CGM.getOpenMPRuntime().emitLastprivateConditionalFinalUpdate(
1250 (*IRef)->getExprLoc());
1253 EmitOMPCopy(
Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp);
1259 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
1280 if (ForInscan != (
C->getModifier() == OMPC_REDUCTION_inscan))
1282 Shareds.append(
C->varlist_begin(),
C->varlist_end());
1283 Privates.append(
C->privates().begin(),
C->privates().end());
1284 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1285 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1286 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1287 if (
C->getModifier() == OMPC_REDUCTION_task) {
1288 Data.ReductionVars.append(
C->privates().begin(),
C->privates().end());
1289 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
1290 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
1291 Data.ReductionOps.append(
C->reduction_ops().begin(),
1292 C->reduction_ops().end());
1293 TaskLHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1294 TaskRHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1299 auto *ILHS = LHSs.begin();
1300 auto *IRHS = RHSs.begin();
1301 auto *IPriv = Privates.begin();
1302 for (
const Expr *IRef : Shareds) {
1310 [&Emission](CodeGenFunction &CGF) {
1311 CGF.EmitAutoVarInit(Emission);
1319 assert(IsRegistered &&
"private var already registered as private");
1327 if (isaOMPArraySectionExpr &&
Type->isVariablyModifiedType()) {
1332 }
else if ((isaOMPArraySectionExpr &&
Type->isScalarType()) ||
1350 PrivateScope.
addPrivate(LHSVD, OriginalAddr);
1361 if (!
Data.ReductionVars.empty()) {
1363 Data.IsReductionWithTaskMod =
true;
1365 llvm::Value *ReductionDesc =
CGM.getOpenMPRuntime().emitTaskReductionInit(
1366 *
this, D.getBeginLoc(), TaskLHSs, TaskRHSs,
Data);
1367 const Expr *TaskRedRef =
nullptr;
1378 case OMPD_parallel_for:
1381 case OMPD_parallel_master:
1385 case OMPD_parallel_sections:
1389 case OMPD_target_parallel:
1393 case OMPD_target_parallel_for:
1397 case OMPD_distribute_parallel_for:
1401 case OMPD_teams_distribute_parallel_for:
1403 .getTaskReductionRefExpr();
1405 case OMPD_target_teams_distribute_parallel_for:
1407 .getTaskReductionRefExpr();
1415 case OMPD_parallel_for_simd:
1417 case OMPD_taskyield:
1421 case OMPD_taskgroup:
1429 case OMPD_cancellation_point:
1431 case OMPD_target_data:
1432 case OMPD_target_enter_data:
1433 case OMPD_target_exit_data:
1435 case OMPD_taskloop_simd:
1436 case OMPD_master_taskloop:
1437 case OMPD_master_taskloop_simd:
1438 case OMPD_parallel_master_taskloop:
1439 case OMPD_parallel_master_taskloop_simd:
1440 case OMPD_distribute:
1441 case OMPD_target_update:
1442 case OMPD_distribute_parallel_for_simd:
1443 case OMPD_distribute_simd:
1444 case OMPD_target_parallel_for_simd:
1445 case OMPD_target_simd:
1446 case OMPD_teams_distribute:
1447 case OMPD_teams_distribute_simd:
1448 case OMPD_teams_distribute_parallel_for_simd:
1449 case OMPD_target_teams:
1450 case OMPD_target_teams_distribute:
1451 case OMPD_target_teams_distribute_parallel_for_simd:
1452 case OMPD_target_teams_distribute_simd:
1453 case OMPD_declare_target:
1454 case OMPD_end_declare_target:
1455 case OMPD_threadprivate:
1457 case OMPD_declare_reduction:
1458 case OMPD_declare_mapper:
1459 case OMPD_declare_simd:
1461 case OMPD_declare_variant:
1462 case OMPD_begin_declare_variant:
1463 case OMPD_end_declare_variant:
1466 llvm_unreachable(
"Unexpected directive with task reductions.");
1472 false, TaskRedRef->
getType());
1485 bool HasAtLeastOneReduction =
false;
1486 bool IsReductionWithTaskMod =
false;
1489 if (
C->getModifier() == OMPC_REDUCTION_inscan)
1491 HasAtLeastOneReduction =
true;
1492 Privates.append(
C->privates().begin(),
C->privates().end());
1493 LHSExprs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1494 RHSExprs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1495 IsPrivateVarReduction.append(
C->private_var_reduction_flags().begin(),
1496 C->private_var_reduction_flags().end());
1497 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1498 IsReductionWithTaskMod =
1499 IsReductionWithTaskMod ||
C->getModifier() == OMPC_REDUCTION_task;
1501 if (HasAtLeastOneReduction) {
1503 if (IsReductionWithTaskMod) {
1504 CGM.getOpenMPRuntime().emitTaskReductionFini(
1507 bool TeamsLoopCanBeParallel =
false;
1508 if (
auto *TTLD = dyn_cast<OMPTargetTeamsGenericLoopDirective>(&D))
1509 TeamsLoopCanBeParallel = TTLD->canBeParallelFor();
1512 TeamsLoopCanBeParallel || ReductionKind == OMPD_simd;
1513 bool SimpleReduction = ReductionKind == OMPD_simd;
1516 CGM.getOpenMPRuntime().emitReduction(
1517 *
this, D.getEndLoc(), Privates, LHSExprs, RHSExprs, ReductionOps,
1518 {WithNowait, SimpleReduction, IsPrivateVarReduction, ReductionKind});
1527 llvm::BasicBlock *DoneBB =
nullptr;
1529 if (
const Expr *PostUpdate =
C->getPostUpdateExpr()) {
1531 if (llvm::Value *
Cond = CondGen(CGF)) {
1552 const OMPExecutableDirective &,
1553 llvm::SmallVectorImpl<llvm::Value *> &)>
1554 CodeGenBoundParametersTy;
1562 llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> PrivateDecls;
1564 for (
const Expr *Ref :
C->varlist()) {
1565 if (!Ref->getType()->isScalarType())
1567 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1575 for (
const Expr *Ref :
C->varlist()) {
1576 if (!Ref->getType()->isScalarType())
1578 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1586 for (
const Expr *Ref :
C->varlist()) {
1587 if (!Ref->getType()->isScalarType())
1589 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1601 for (
const Expr *Ref :
C->varlist()) {
1602 if (!Ref->getType()->isScalarType())
1604 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1611 CGF, S, PrivateDecls);
1617 const CodeGenBoundParametersTy &CodeGenBoundParameters) {
1618 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
1619 llvm::Value *NumThreads =
nullptr;
1628 llvm::Function *OutlinedFn =
1635 NumThreads = CGF.
EmitScalarExpr(NumThreadsClause->getNumThreads(),
1637 Modifier = NumThreadsClause->getModifier();
1639 Message = MessageClause->getMessageString();
1640 MessageLoc = MessageClause->getBeginLoc();
1643 Severity = SeverityClause->getSeverityKind();
1644 SeverityLoc = SeverityClause->getBeginLoc();
1647 CGF, NumThreads, NumThreadsClause->getBeginLoc(), Modifier, Severity,
1648 SeverityLoc, Message, MessageLoc);
1653 CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getBeginLoc());
1655 const Expr *IfCond =
nullptr;
1656 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
1657 if (
C->getNameModifier() == OMPD_unknown ||
1658 C->getNameModifier() == OMPD_parallel) {
1659 IfCond =
C->getCondition();
1664 OMPParallelScope
Scope(CGF, S);
1670 CodeGenBoundParameters(CGF, S, CapturedVars);
1673 CapturedVars, IfCond, NumThreads,
1674 Modifier, Severity, Message);
1679 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
1681 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
1683 return !((AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc ||
1684 AA->getAllocatorType() == OMPAllocateDeclAttr::OMPNullMemAlloc) &&
1685 !AA->getAllocator());
1700 CGF, S.getBeginLoc(), OMPD_unknown,
false,
1706 CodeGenFunction &CGF,
const VarDecl *VD) {
1708 auto &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1720 Size = CGF.
Builder.CreateNUWAdd(
1722 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
1723 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
1729 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
1730 assert(AA->getAllocator() &&
1731 "Expected allocator expression for non-default allocator.");
1735 if (Allocator->getType()->isIntegerTy())
1736 Allocator = CGF.
Builder.CreateIntToPtr(Allocator,
CGM.VoidPtrTy);
1737 else if (Allocator->getType()->isPointerTy())
1741 llvm::Value *
Addr = OMPBuilder.createOMPAlloc(
1744 llvm::CallInst *FreeCI =
1745 OMPBuilder.createOMPFree(CGF.
Builder,
Addr, Allocator);
1759 if (
CGM.getLangOpts().OpenMPUseTLS &&
1760 CGM.getContext().getTargetInfo().isTLSSupported())
1763 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1768 llvm::ConstantInt *Size =
CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy));
1770 llvm::Twine CacheName = Twine(
CGM.getMangledName(VD)).concat(Suffix);
1772 llvm::CallInst *ThreadPrivateCacheCall =
1773 OMPBuilder.createCachedThreadPrivate(CGF.
Builder,
Data, Size, CacheName);
1781 llvm::raw_svector_ostream OS(Buffer);
1782 StringRef Sep = FirstSeparator;
1783 for (StringRef Part : Parts) {
1787 return OS.str().str();
1795 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
1796 "." + RegionName +
".after");
1812 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
1813 "." + RegionName +
".after");
1825 if (
CGM.getLangOpts().OpenMPIRBuilder) {
1826 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1828 llvm::Value *IfCond =
nullptr;
1833 llvm::Value *NumThreads =
nullptr;
1838 ProcBindKind ProcBind = OMP_PROC_BIND_default;
1840 ProcBind = ProcBindClause->getProcBindKind();
1842 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1846 auto FiniCB = [
this](InsertPointTy IP) {
1848 return llvm::Error::success();
1855 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
1856 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
1867 auto BodyGenCB = [&,
this](InsertPointTy AllocaIP,
1868 InsertPointTy CodeGenIP) {
1870 *
this, ParallelRegionBodyStmt, AllocaIP, CodeGenIP,
"parallel");
1871 return llvm::Error::success();
1876 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
1878 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
1879 OMPBuilder.createParallel(
Builder, AllocaIP, BodyGenCB, PrivCB, FiniCB,
1880 IfCond, NumThreads, ProcBind, S.hasCancel()));
1894 CGF.
EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt());
1903 [](CodeGenFunction &) {
return nullptr; });
1915class OMPTransformDirectiveScopeRAII {
1916 OMPLoopScope *
Scope =
nullptr;
1920 OMPTransformDirectiveScopeRAII(
const OMPTransformDirectiveScopeRAII &) =
1922 OMPTransformDirectiveScopeRAII &
1923 operator=(
const OMPTransformDirectiveScopeRAII &) =
delete;
1927 if (
const auto *Dir = dyn_cast<OMPLoopBasedDirective>(S)) {
1928 Scope =
new OMPLoopScope(CGF, *Dir);
1933 ~OMPTransformDirectiveScopeRAII() {
1944 int MaxLevel,
int Level = 0) {
1945 assert(Level < MaxLevel &&
"Too deep lookup during loop body codegen.");
1947 if (
const auto *CS = dyn_cast<CompoundStmt>(SimplifiedS)) {
1950 "LLVM IR generation of compound statement ('{}')");
1954 for (
const Stmt *CurStmt : CS->body())
1955 emitBody(CGF, CurStmt, NextLoop, MaxLevel, Level);
1958 if (SimplifiedS == NextLoop) {
1960 dyn_cast<OMPCanonicalLoopNestTransformationDirective>(SimplifiedS))
1961 SimplifiedS = Dir->getTransformedStmt();
1962 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(SimplifiedS))
1963 SimplifiedS = CanonLoop->getLoopStmt();
1964 if (
const auto *For = dyn_cast<ForStmt>(SimplifiedS)) {
1968 "Expected canonical for loop or range-based for loop.");
1970 CGF.
EmitStmt(CXXFor->getLoopVarStmt());
1971 S = CXXFor->getBody();
1973 if (Level + 1 < MaxLevel) {
1974 NextLoop = OMPLoopDirective::tryToFindNextInnerLoop(
1976 emitBody(CGF, S, NextLoop, MaxLevel, Level + 1);
1987 for (
const Expr *UE : D.updates())
1995 for (
const Expr *UE :
C->updates())
2002 BreakContinueStack.push_back(BreakContinue(D,
LoopExit, Continue));
2003 for (
const Expr *E : D.finals_conditions()) {
2016 bool IsInscanRegion = InscanScope.
Privatize();
2017 if (IsInscanRegion) {
2027 if (EKind != OMPD_simd && !
getLangOpts().OpenMPSimd)
2036 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
2039 OMPLoopBasedDirective::tryToFindNextInnerLoop(
2041 D.getLoopsNumber());
2049 BreakContinueStack.pop_back();
2060 std::unique_ptr<CodeGenFunction::CGCapturedStmtInfo> CSI =
2061 std::make_unique<CodeGenFunction::CGCapturedStmtInfo>(*S);
2065 return {F, CapStruct.getPointer(
ParentCGF)};
2069static llvm::CallInst *
2074 EffectiveArgs.reserve(Args.size() + 1);
2075 llvm::append_range(EffectiveArgs, Args);
2076 EffectiveArgs.push_back(Cap.second);
2081llvm::CanonicalLoopInfo *
2083 assert(Depth == 1 &&
"Nested loops with OpenMPIRBuilder not yet implemented");
2109 const Stmt *SyntacticalLoop = S->getLoopStmt();
2120 const Stmt *BodyStmt;
2121 if (
const auto *For = dyn_cast<ForStmt>(SyntacticalLoop)) {
2122 if (
const Stmt *InitStmt = For->getInit())
2124 BodyStmt = For->getBody();
2125 }
else if (
const auto *RangeFor =
2126 dyn_cast<CXXForRangeStmt>(SyntacticalLoop)) {
2127 if (
const DeclStmt *RangeStmt = RangeFor->getRangeStmt())
2129 if (
const DeclStmt *BeginStmt = RangeFor->getBeginStmt())
2131 if (
const DeclStmt *EndStmt = RangeFor->getEndStmt())
2133 if (
const DeclStmt *LoopVarStmt = RangeFor->getLoopVarStmt())
2135 BodyStmt = RangeFor->getBody();
2137 llvm_unreachable(
"Expected for-stmt or range-based for-stmt");
2140 const CapturedStmt *DistanceFunc = S->getDistanceFunc();
2153 llvm::Value *DistVal =
Builder.CreateLoad(CountAddr,
".count");
2156 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2157 auto BodyGen = [&,
this](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP,
2158 llvm::Value *IndVar) {
2163 const DeclRefExpr *LoopVarRef = S->getLoopVarRef();
2171 return llvm::Error::success();
2174 llvm::CanonicalLoopInfo *
CL =
2175 cantFail(OMPBuilder.createCanonicalLoop(
Builder, BodyGen, DistVal));
2187 const Expr *IncExpr,
2188 const llvm::function_ref<
void(CodeGenFunction &)> BodyGen,
2189 const llvm::function_ref<
void(CodeGenFunction &)> PostIncGen) {
2199 const CapturedStmt *ICS = OMPED.getInnermostCapturedStmt();
2213 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
2214 if (RequiresCleanup)
2221 if (ExitBlock !=
LoopExit.getBlock()) {
2231 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
2239 BreakContinueStack.pop_back();
2250 bool HasLinears =
false;
2255 if (
const auto *Ref =
2274 if (
const auto *CS = cast_or_null<BinaryOperator>(
C->getCalcStep()))
2286 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2289 llvm::BasicBlock *DoneBB =
nullptr;
2292 auto IC =
C->varlist_begin();
2293 for (
const Expr *F :
C->finals()) {
2295 if (llvm::Value *
Cond = CondGen(*
this)) {
2307 (*IC)->getType(),
VK_LValue, (*IC)->getExprLoc());
2315 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
2327 llvm::APInt ClauseAlignment(64, 0);
2328 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
2331 ClauseAlignment = AlignmentCI->getValue();
2333 for (
const Expr *E : Clause->varlist()) {
2334 llvm::APInt Alignment(ClauseAlignment);
2335 if (Alignment == 0) {
2342 E->getType()->getPointeeType()))
2345 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2346 "alignment is not power of 2");
2347 if (Alignment != 0) {
2361 auto I = S.private_counters().begin();
2362 for (
const Expr *E : S.counters()) {
2368 LocalDeclMap.erase(PrivateVD);
2374 E->getType(),
VK_LValue, E->getExprLoc());
2383 if (!
C->getNumForLoops())
2385 for (
unsigned I = S.getLoopsNumber(), E =
C->getLoopNumIterations().size();
2391 if (DRE->refersToEnclosingVariableOrCapture()) {
2400 const Expr *
Cond, llvm::BasicBlock *TrueBlock,
2401 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
2409 for (
const Expr *I : S.inits()) {
2416 for (
const Expr *E : S.dependent_counters()) {
2419 assert(!E->getType().getNonReferenceType()->isRecordType() &&
2420 "dependent counter must not be an iterator.");
2424 (void)PreCondVars.
setVarAddr(CGF, VD, CounterAddr);
2426 (void)PreCondVars.
apply(CGF);
2427 for (
const Expr *E : S.dependent_inits()) {
2441 llvm::DenseSet<const VarDecl *> SIMDLCVs;
2445 for (
const Expr *
C : LoopDirective->counters()) {
2451 auto CurPrivate =
C->privates().begin();
2452 for (
const Expr *E :
C->varlist()) {
2454 const auto *PrivateVD =
2461 assert(IsRegistered &&
"linear var already registered as private");
2549 if (
const auto *CS = dyn_cast<CapturedStmt>(S))
2567 if (HasOrderedDirective)
2575 const Stmt *AssociatedStmt = D.getAssociatedStmt();
2579 if (
C->getKind() == OMPC_ORDER_concurrent)
2582 if ((EKind == OMPD_simd ||
2586 return C->getModifier() == OMPC_REDUCTION_inscan;
2594 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2597 llvm::BasicBlock *DoneBB =
nullptr;
2598 auto IC = D.counters().begin();
2599 auto IPC = D.private_counters().begin();
2600 for (
const Expr *F : D.finals()) {
2603 const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
2605 OrigVD->hasGlobalStorage() || CED) {
2607 if (llvm::Value *
Cond = CondGen(*
this)) {
2655 auto &&ThenGen = [&S, &SimdInitGen, &BodyCodeGen](
CodeGenFunction &CGF,
2669 const Expr *IfCond =
nullptr;
2672 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
2674 (
C->getNameModifier() == OMPD_unknown ||
2675 C->getNameModifier() == OMPD_simd)) {
2676 IfCond =
C->getCondition();
2692 OMPLoopScope PreInitScope(CGF, S);
2714 llvm::BasicBlock *ContBlock =
nullptr;
2721 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
2728 const Expr *IVExpr = S.getIterationVariable();
2736 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
2751 CGF, S, CGF.
EmitLValue(S.getIterationVariable()));
2766 emitOMPLoopBodyWithStopPoint(CGF, S,
2767 CodeGenFunction::JumpDest());
2773 if (HasLastprivateClause)
2802 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(S.getRawStmt())) {
2803 if (
const Stmt *SyntacticalLoop = CanonLoop->getLoopStmt()) {
2804 for (
const Stmt *SubStmt : SyntacticalLoop->
children()) {
2807 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(SubStmt)) {
2822static llvm::MapVector<llvm::Value *, llvm::Value *>
2824 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars;
2826 llvm::APInt ClauseAlignment(64, 0);
2827 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
2830 ClauseAlignment = AlignmentCI->getValue();
2832 for (
const Expr *E : Clause->varlist()) {
2833 llvm::APInt Alignment(ClauseAlignment);
2834 if (Alignment == 0) {
2841 E->getType()->getPointeeType()))
2844 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2845 "alignment is not power of 2");
2847 AlignedVars[PtrValue] = CGF.
Builder.getInt64(Alignment.getSExtValue());
2857 bool UseOMPIRBuilder =
2859 if (UseOMPIRBuilder) {
2863 if (UseOMPIRBuilder) {
2864 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars =
2867 const Stmt *Inner = S.getRawStmt();
2868 llvm::CanonicalLoopInfo *CLI =
2869 CGF.EmitOMPCollapsedCanonicalLoopNest(Inner, 1);
2871 llvm::OpenMPIRBuilder &OMPBuilder =
2874 llvm::ConstantInt *Simdlen =
nullptr;
2881 llvm::ConstantInt *Safelen =
nullptr;
2888 llvm::omp::OrderKind Order = llvm::omp::OrderKind::OMP_ORDER_unknown;
2890 if (
C->getKind() == OpenMPOrderClauseKind::OMPC_ORDER_concurrent) {
2891 Order = llvm::omp::OrderKind::OMP_ORDER_concurrent;
2896 OMPBuilder.applySimd(CLI, AlignedVars,
2897 nullptr, Order, Simdlen, Safelen);
2904 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
2919 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
2932 OMPTransformDirectiveScopeRAII TileScope(*
this, &S);
2938 OMPTransformDirectiveScopeRAII StripeScope(*
this, &S);
2944 OMPTransformDirectiveScopeRAII ReverseScope(*
this, &S);
2951 OMPTransformDirectiveScopeRAII InterchangeScope(*
this, &S);
2956 bool UseOMPIRBuilder =
CGM.getLangOpts().OpenMPIRBuilder;
2958 if (UseOMPIRBuilder) {
2960 const Stmt *Inner = S.getRawStmt();
2968 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2971 llvm::CanonicalLoopInfo *UnrolledCLI =
nullptr;
2975 OMPBuilder.unrollLoopFull(DL, CLI);
2977 uint64_t Factor = 0;
2978 if (
Expr *FactorExpr = PartialClause->getFactor()) {
2979 Factor = FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
2980 assert(Factor >= 1 &&
"Only positive factors are valid");
2982 OMPBuilder.unrollLoopPartial(DL, CLI, Factor,
2983 NeedsUnrolledCLI ? &UnrolledCLI :
nullptr);
2985 OMPBuilder.unrollLoopHeuristic(DL, CLI);
2988 assert((!NeedsUnrolledCLI || UnrolledCLI) &&
2989 "NeedsUnrolledCLI implies UnrolledCLI to be set");
3006 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3008 FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
3009 assert(Factor >= 1 &&
"Only positive factors are valid");
3017void CodeGenFunction::EmitOMPOuterLoop(
3020 const CodeGenFunction::OMPLoopArguments &LoopArgs,
3025 const Expr *IVExpr = S.getIterationVariable();
3039 llvm::Value *BoolCondVal =
nullptr;
3040 if (!DynamicOrOrdered) {
3051 RT.
emitForNext(*
this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL,
3052 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST);
3057 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
3062 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
3063 if (ExitBlock !=
LoopExit.getBlock()) {
3071 if (DynamicOrOrdered)
3076 BreakContinueStack.push_back(BreakContinue(S, LoopExit, Continue));
3081 [&S, IsMonotonic, EKind](CodeGenFunction &CGF, PrePostActionTy &) {
3086 if (
const auto *
C = S.getSingleClause<OMPOrderClause>())
3087 if (
C->getKind() == OMPC_ORDER_concurrent)
3093 [&S, &LoopArgs, LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered,
3094 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
3095 SourceLocation Loc = S.getBeginLoc();
3101 CGF.EmitOMPInnerLoop(
3103 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
3104 CodeGenLoop(CGF, S, LoopExit);
3106 [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) {
3107 CodeGenOrdered(CGF, Loc, IVSize, IVSigned);
3112 BreakContinueStack.pop_back();
3113 if (!DynamicOrOrdered) {
3126 auto &&CodeGen = [DynamicOrOrdered, &S, &LoopArgs](CodeGenFunction &CGF) {
3127 if (!DynamicOrOrdered)
3128 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
3131 OMPCancelStack.emitExit(*
this, EKind, CodeGen);
3134void CodeGenFunction::EmitOMPForOuterLoop(
3135 const OpenMPScheduleTy &ScheduleKind,
bool IsMonotonic,
3137 const OMPLoopArguments &LoopArgs,
3139 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3145 LoopArgs.Chunk !=
nullptr)) &&
3146 "static non-chunked schedule does not need outer loop");
3200 const Expr *IVExpr = S.getIterationVariable();
3204 if (DynamicOrOrdered) {
3205 const std::pair<llvm::Value *, llvm::Value *> DispatchBounds =
3206 CGDispatchBounds(*
this, S, LoopArgs.LB, LoopArgs.UB);
3207 llvm::Value *LBVal = DispatchBounds.first;
3208 llvm::Value *UBVal = DispatchBounds.second;
3209 CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal,
3212 IVSigned, Ordered, DipatchRTInputValues);
3214 CGOpenMPRuntime::StaticRTInput StaticInit(
3215 IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
3216 LoopArgs.ST, LoopArgs.Chunk);
3222 auto &&CodeGenOrdered = [Ordered](CodeGenFunction &CGF, SourceLocation Loc,
3223 const unsigned IVSize,
3224 const bool IVSigned) {
3231 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST,
3232 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB);
3233 OuterLoopArgs.IncExpr = S.getInc();
3234 OuterLoopArgs.Init = S.getInit();
3235 OuterLoopArgs.Cond = S.getCond();
3236 OuterLoopArgs.NextLB = S.getNextLowerBound();
3237 OuterLoopArgs.NextUB = S.getNextUpperBound();
3238 OuterLoopArgs.DKind = LoopArgs.DKind;
3239 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
3241 if (DynamicOrOrdered) {
3247 const unsigned IVSize,
const bool IVSigned) {}
3249void CodeGenFunction::EmitOMPDistributeOuterLoop(
3254 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3261 const Expr *IVExpr = S.getIterationVariable();
3266 CGOpenMPRuntime::StaticRTInput StaticInit(
3267 IVSize, IVSigned,
false, LoopArgs.IL, LoopArgs.LB,
3268 LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
3275 IncExpr = S.getDistInc();
3277 IncExpr = S.getInc();
3282 OMPLoopArguments OuterLoopArgs;
3283 OuterLoopArgs.LB = LoopArgs.LB;
3284 OuterLoopArgs.UB = LoopArgs.UB;
3285 OuterLoopArgs.ST = LoopArgs.ST;
3286 OuterLoopArgs.IL = LoopArgs.IL;
3287 OuterLoopArgs.Chunk = LoopArgs.Chunk;
3289 ? S.getCombinedEnsureUpperBound()
3290 : S.getEnsureUpperBound();
3291 OuterLoopArgs.IncExpr = IncExpr;
3293 ? S.getCombinedInit()
3296 ? S.getCombinedCond()
3299 ? S.getCombinedNextLowerBound()
3300 : S.getNextLowerBound();
3302 ? S.getCombinedNextUpperBound()
3303 : S.getNextUpperBound();
3304 OuterLoopArgs.DKind = OMPD_distribute;
3306 EmitOMPOuterLoop(
false,
false, S,
3307 LoopScope, OuterLoopArgs, CodeGenLoopContent,
3311static std::pair<LValue, LValue>
3326 LValue PrevLB = CGF.
EmitLValue(LS.getPrevLowerBoundVariable());
3327 LValue PrevUB = CGF.
EmitLValue(LS.getPrevUpperBoundVariable());
3329 PrevLB, LS.getPrevLowerBoundVariable()->getExprLoc());
3331 PrevLBVal, LS.getPrevLowerBoundVariable()->getType(),
3332 LS.getIterationVariable()->getType(),
3333 LS.getPrevLowerBoundVariable()->getExprLoc());
3335 PrevUB, LS.getPrevUpperBoundVariable()->getExprLoc());
3337 PrevUBVal, LS.getPrevUpperBoundVariable()->getType(),
3338 LS.getIterationVariable()->getType(),
3339 LS.getPrevUpperBoundVariable()->getExprLoc());
3354static std::pair<llvm::Value *, llvm::Value *>
3359 const Expr *IVExpr = LS.getIterationVariable();
3365 llvm::Value *LBVal =
3367 llvm::Value *UBVal =
3369 return {LBVal, UBVal};
3378 llvm::Value *LBCast = CGF.
Builder.CreateIntCast(
3380 CapturedVars.push_back(LBCast);
3384 llvm::Value *UBCast = CGF.
Builder.CreateIntCast(
3386 CapturedVars.push_back(UBCast);
3397 bool HasCancel =
false;
3399 if (
const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
3400 HasCancel = D->hasCancel();
3401 else if (
const auto *D = dyn_cast<OMPDistributeParallelForDirective>(&S))
3402 HasCancel = D->hasCancel();
3403 else if (
const auto *D =
3404 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S))
3405 HasCancel = D->hasCancel();
3415 CGInlinedWorksharingLoop,
3425 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3426 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3435 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3436 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3444 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
3445 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
3455 llvm::Constant *
Addr;
3457 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
3459 assert(Fn &&
Addr &&
"Target device function emission failed.");
3471struct ScheduleKindModifiersTy {
3478 : Kind(Kind), M1(M1), M2(M2) {}
3494 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
3502 bool HasLastprivateClause;
3505 OMPLoopScope PreInitScope(*
this, S);
3510 llvm::BasicBlock *ContBlock =
nullptr;
3517 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
3524 bool Ordered =
false;
3526 if (OrderedClause->getNumForLoops())
3536 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*
this, S);
3537 LValue LB = Bounds.first;
3538 LValue UB = Bounds.second;
3552 CGM.getOpenMPRuntime().emitBarrierCall(
3553 *
this, S.getBeginLoc(), OMPD_unknown,
false,
3558 *
this, S,
EmitLValue(S.getIterationVariable()));
3565 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
3568 const Expr *ChunkExpr =
nullptr;
3571 ScheduleKind.
Schedule =
C->getScheduleKind();
3572 ScheduleKind.
M1 =
C->getFirstScheduleModifier();
3573 ScheduleKind.
M2 =
C->getSecondScheduleModifier();
3574 ChunkExpr =
C->getChunkSize();
3577 CGM.getOpenMPRuntime().getDefaultScheduleAndChunk(
3578 *
this, S, ScheduleKind.
Schedule, ChunkExpr);
3580 bool HasChunkSizeOne =
false;
3581 llvm::Value *Chunk =
nullptr;
3585 S.getIterationVariable()->getType(),
3589 llvm::APSInt EvaluatedChunk =
Result.Val.getInt();
3590 HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
3599 bool StaticChunkedOne =
3601 Chunk !=
nullptr) &&
3605 (ScheduleKind.
Schedule == OMPC_SCHEDULE_static &&
3606 !(ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
3607 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)) ||
3608 ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
3609 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
3611 Chunk !=
nullptr) ||
3612 StaticChunkedOne) &&
3622 if (
C->getKind() == OMPC_ORDER_concurrent)
3626 [IVSize, IVSigned, Ordered, IL, LB, UB, ST, StaticChunkedOne, Chunk,
3635 IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(),
3636 UB.getAddress(), ST.getAddress(),
3637 StaticChunkedOne ? Chunk :
nullptr);
3639 CGF, S.getBeginLoc(), EKind, ScheduleKind, StaticInit);
3641 if (!StaticChunkedOne)
3660 StaticChunkedOne ? S.getCombinedParForInDistCond()
3662 StaticChunkedOne ? S.getDistInc() : S.getInc(),
3663 [&S,
LoopExit](CodeGenFunction &CGF) {
3664 emitOMPLoopBodyWithStopPoint(CGF, S, LoopExit);
3666 [](CodeGenFunction &) {});
3670 auto &&
CodeGen = [&S](CodeGenFunction &CGF) {
3674 OMPCancelStack.emitExit(*
this, EKind,
CodeGen);
3681 LoopArguments.DKind = OMPD_for;
3682 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
3683 LoopArguments, CGDispatchBounds);
3687 return CGF.
Builder.CreateIsNotNull(
3693 ? OMPD_parallel_for_simd
3697 *
this, S, [IL, &S](CodeGenFunction &CGF) {
3698 return CGF.
Builder.CreateIsNotNull(
3702 if (HasLastprivateClause)
3708 return CGF.
Builder.CreateIsNotNull(
3719 return HasLastprivateClause;
3725static std::pair<LValue, LValue>
3739static std::pair<llvm::Value *, llvm::Value *>
3743 const Expr *IVExpr = LS.getIterationVariable();
3745 llvm::Value *LBVal = CGF.
Builder.getIntN(IVSize, 0);
3747 return {LBVal, UBVal};
3759 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
3760 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
3761 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
3767 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
3768 "Only inscan reductions are expected.");
3769 Shareds.append(
C->varlist_begin(),
C->varlist_end());
3770 Privates.append(
C->privates().begin(),
C->privates().end());
3771 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
3772 CopyArrayTemps.append(
C->copy_array_temps().begin(),
3773 C->copy_array_temps().end());
3781 auto *ITA = CopyArrayTemps.begin();
3782 for (
const Expr *IRef : Privates) {
3786 if (PrivateVD->getType()->isVariablyModifiedType()) {
3811 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
3812 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
3813 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
3821 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
3822 "Only inscan reductions are expected.");
3823 Shareds.append(
C->varlist_begin(),
C->varlist_end());
3824 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
3825 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
3826 Privates.append(
C->privates().begin(),
C->privates().end());
3827 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
3828 CopyArrayElems.append(
C->copy_array_elems().begin(),
3829 C->copy_array_elems().end());
3833 llvm::Value *OMPLast = CGF.
Builder.CreateNSWSub(
3834 OMPScanNumIterations,
3835 llvm::ConstantInt::get(CGF.
SizeTy, 1,
false));
3836 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
3837 const Expr *PrivateExpr = Privates[I];
3838 const Expr *OrigExpr = Shareds[I];
3839 const Expr *CopyArrayElem = CopyArrayElems[I];
3846 LValue SrcLVal = CGF.
EmitLValue(CopyArrayElem);
3848 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
3878 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
3879 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
3886 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
3887 "Only inscan reductions are expected.");
3888 Privates.append(
C->privates().begin(),
C->privates().end());
3889 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
3890 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
3891 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
3892 CopyArrayElems.append(
C->copy_array_elems().begin(),
3893 C->copy_array_elems().end());
3908 auto &&
CodeGen = [&S, OMPScanNumIterations, &LHSs, &RHSs, &CopyArrayElems,
3915 llvm::BasicBlock *InputBB = CGF.Builder.GetInsertBlock();
3916 llvm::BasicBlock *LoopBB = CGF.createBasicBlock(
"omp.outer.log.scan.body");
3917 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
"omp.outer.log.scan.exit");
3919 CGF.CGM.getIntrinsic(llvm::Intrinsic::log2, CGF.DoubleTy);
3921 CGF.Builder.CreateUIToFP(OMPScanNumIterations, CGF.DoubleTy);
3922 llvm::Value *LogVal = CGF.EmitNounwindRuntimeCall(F, Arg);
3923 F = CGF.CGM.getIntrinsic(llvm::Intrinsic::ceil, CGF.DoubleTy);
3924 LogVal = CGF.EmitNounwindRuntimeCall(F, LogVal);
3925 LogVal = CGF.Builder.CreateFPToUI(LogVal, CGF.IntTy);
3926 llvm::Value *NMin1 = CGF.Builder.CreateNUWSub(
3927 OMPScanNumIterations, llvm::ConstantInt::get(CGF.SizeTy, 1));
3929 CGF.EmitBlock(LoopBB);
3930 auto *Counter = CGF.Builder.CreatePHI(CGF.IntTy, 2);
3932 auto *Pow2K = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
3933 Counter->addIncoming(llvm::ConstantInt::get(CGF.IntTy, 0), InputBB);
3934 Pow2K->addIncoming(llvm::ConstantInt::get(CGF.SizeTy, 1), InputBB);
3937 llvm::BasicBlock *InnerLoopBB =
3938 CGF.createBasicBlock(
"omp.inner.log.scan.body");
3939 llvm::BasicBlock *InnerExitBB =
3940 CGF.createBasicBlock(
"omp.inner.log.scan.exit");
3941 llvm::Value *CmpI = CGF.Builder.CreateICmpUGE(NMin1, Pow2K);
3942 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
3943 CGF.EmitBlock(InnerLoopBB);
3944 auto *IVal = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
3945 IVal->addIncoming(NMin1, LoopBB);
3948 auto *ILHS = LHSs.begin();
3949 auto *IRHS = RHSs.begin();
3950 for (
const Expr *CopyArrayElem : CopyArrayElems) {
3960 LHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
3965 llvm::Value *OffsetIVal = CGF.Builder.CreateNUWSub(IVal, Pow2K);
3971 RHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
3978 CGF.CGM.getOpenMPRuntime().emitReduction(
3979 CGF, S.getEndLoc(), Privates, LHSs, RHSs, ReductionOps,
3983 llvm::Value *NextIVal =
3984 CGF.Builder.CreateNUWSub(IVal, llvm::ConstantInt::get(CGF.SizeTy, 1));
3985 IVal->addIncoming(NextIVal, CGF.Builder.GetInsertBlock());
3986 CmpI = CGF.Builder.CreateICmpUGE(NextIVal, Pow2K);
3987 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
3988 CGF.EmitBlock(InnerExitBB);
3990 CGF.Builder.CreateNUWAdd(Counter, llvm::ConstantInt::get(CGF.IntTy, 1));
3991 Counter->addIncoming(
Next, CGF.Builder.GetInsertBlock());
3993 llvm::Value *NextPow2K =
3994 CGF.Builder.CreateShl(Pow2K, 1,
"",
true);
3995 Pow2K->addIncoming(NextPow2K, CGF.Builder.GetInsertBlock());
3996 llvm::Value *Cmp = CGF.Builder.CreateICmpNE(
Next, LogVal);
3997 CGF.Builder.CreateCondBr(Cmp, LoopBB, ExitBB);
3999 CGF.EmitBlock(ExitBB);
4005 CGF, S.getBeginLoc(), OMPD_unknown,
false,
4008 RegionCodeGenTy RCG(CodeGen);
4019 bool HasLastprivates;
4023 return C->getModifier() == OMPC_REDUCTION_inscan;
4027 OMPLoopScope LoopScope(CGF, S);
4030 const auto &&FirstGen = [&S, HasCancel, EKind](
CodeGenFunction &CGF) {
4039 const auto &&SecondGen = [&S, HasCancel, EKind,
4057 return HasLastprivates;
4070 if (
auto *SC = dyn_cast<OMPScheduleClause>(
C)) {
4075 switch (SC->getScheduleKind()) {
4076 case OMPC_SCHEDULE_auto:
4077 case OMPC_SCHEDULE_dynamic:
4078 case OMPC_SCHEDULE_runtime:
4079 case OMPC_SCHEDULE_guided:
4080 case OMPC_SCHEDULE_static:
4093static llvm::omp::ScheduleKind
4095 switch (ScheduleClauseKind) {
4097 return llvm::omp::OMP_SCHEDULE_Default;
4098 case OMPC_SCHEDULE_auto:
4099 return llvm::omp::OMP_SCHEDULE_Auto;
4100 case OMPC_SCHEDULE_dynamic:
4101 return llvm::omp::OMP_SCHEDULE_Dynamic;
4102 case OMPC_SCHEDULE_guided:
4103 return llvm::omp::OMP_SCHEDULE_Guided;
4104 case OMPC_SCHEDULE_runtime:
4105 return llvm::omp::OMP_SCHEDULE_Runtime;
4106 case OMPC_SCHEDULE_static:
4107 return llvm::omp::OMP_SCHEDULE_Static;
4109 llvm_unreachable(
"Unhandled schedule kind");
4116 bool HasLastprivates =
false;
4119 auto &&
CodeGen = [&S, &
CGM, HasCancel, &HasLastprivates,
4122 if (UseOMPIRBuilder) {
4125 llvm::omp::ScheduleKind SchedKind = llvm::omp::OMP_SCHEDULE_Default;
4126 llvm::Value *ChunkSize =
nullptr;
4130 if (
const Expr *ChunkSizeExpr = SchedClause->getChunkSize())
4135 const Stmt *Inner = S.getRawStmt();
4136 llvm::CanonicalLoopInfo *CLI =
4139 llvm::OpenMPIRBuilder &OMPBuilder =
4141 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4143 cantFail(OMPBuilder.applyWorkshareLoop(
4144 CGF.
Builder.getCurrentDebugLocation(), CLI, AllocaIP, NeedsBarrier,
4145 SchedKind, ChunkSize,
false,
4156 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
4161 if (!UseOMPIRBuilder) {
4175 bool HasLastprivates =
false;
4176 auto &&
CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
4183 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4184 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
4189 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_for);
4196 llvm::Value *
Init =
nullptr) {
4203void CodeGenFunction::EmitSections(
const OMPExecutableDirective &S) {
4204 const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4205 const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt);
4206 bool HasLastprivates =
false;
4208 auto &&CodeGen = [&S, CapturedStmt, CS, EKind,
4209 &HasLastprivates](CodeGenFunction &CGF, PrePostActionTy &) {
4210 const ASTContext &
C = CGF.getContext();
4211 QualType KmpInt32Ty =
4212 C.getIntTypeForBitwidth(32, 1);
4215 CGF.Builder.getInt32(0));
4216 llvm::ConstantInt *GlobalUBVal = CS !=
nullptr
4217 ? CGF.Builder.getInt32(CS->size() - 1)
4218 : CGF.Builder.getInt32(0);
4222 CGF.Builder.getInt32(1));
4224 CGF.Builder.getInt32(0));
4227 OpaqueValueExpr IVRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4228 CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
4229 OpaqueValueExpr UBRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4230 CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
4234 S.getBeginLoc(), FPOptionsOverride());
4238 S.getBeginLoc(),
true, FPOptionsOverride());
4239 auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
4251 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".omp.sections.exit");
4252 llvm::SwitchInst *SwitchStmt =
4253 CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.
getBeginLoc()),
4254 ExitBB, CS ==
nullptr ? 1 : CS->size());
4256 unsigned CaseNumber = 0;
4257 for (
const Stmt *SubStmt : CS->
children()) {
4258 auto CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4259 CGF.EmitBlock(CaseBB);
4260 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
4261 CGF.EmitStmt(SubStmt);
4262 CGF.EmitBranch(ExitBB);
4266 llvm::BasicBlock *CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4267 CGF.EmitBlock(CaseBB);
4268 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
4269 CGF.EmitStmt(CapturedStmt);
4270 CGF.EmitBranch(ExitBB);
4272 CGF.EmitBlock(ExitBB,
true);
4275 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
4276 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
4280 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
4284 CGF.EmitOMPPrivateClause(S, LoopScope);
4285 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(CGF, S, IV);
4286 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
4287 CGF.EmitOMPReductionClauseInit(S, LoopScope);
4288 (void)LoopScope.Privatize();
4290 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
4293 OpenMPScheduleTy ScheduleKind;
4294 ScheduleKind.
Schedule = OMPC_SCHEDULE_static;
4295 CGOpenMPRuntime::StaticRTInput StaticInit(
4296 32,
true,
false, IL.getAddress(),
4297 LB.getAddress(), UB.getAddress(), ST.getAddress());
4298 CGF.CGM.getOpenMPRuntime().emitForStaticInit(CGF, S.
getBeginLoc(), EKind,
4299 ScheduleKind, StaticInit);
4301 llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.
getBeginLoc());
4302 llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
4303 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
4304 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
4306 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.
getBeginLoc()), IV);
4308 CGF.EmitOMPInnerLoop(S,
false,
Cond, Inc, BodyGen,
4309 [](CodeGenFunction &) {});
4311 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
4312 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.
getEndLoc(),
4315 CGF.OMPCancelStack.emitExit(CGF, EKind, CodeGen);
4316 CGF.EmitOMPReductionClauseFinal(S, OMPD_parallel);
4319 return CGF.
Builder.CreateIsNotNull(
4324 if (HasLastprivates)
4331 bool HasCancel =
false;
4332 if (
auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
4333 HasCancel = OSD->hasCancel();
4334 else if (
auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
4335 HasCancel = OPSD->hasCancel();
4337 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_sections, CodeGen,
4342 if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) {
4360 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4365 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4366 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_scope,
CodeGen);
4370 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_scope);
4377 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4378 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4379 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4380 using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
4382 auto FiniCB = [](InsertPointTy IP) {
4385 return llvm::Error::success();
4388 const CapturedStmt *ICS = S.getInnermostCapturedStmt();
4394 auto SectionCB = [
this, SubStmt](InsertPointTy AllocaIP,
4395 InsertPointTy CodeGenIP) {
4397 *
this, SubStmt, AllocaIP, CodeGenIP,
"section");
4398 return llvm::Error::success();
4400 SectionCBVector.push_back(SectionCB);
4403 auto SectionCB = [
this,
CapturedStmt](InsertPointTy AllocaIP,
4404 InsertPointTy CodeGenIP) {
4407 return llvm::Error::success();
4409 SectionCBVector.push_back(SectionCB);
4416 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
4417 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
4427 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4429 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4430 cantFail(OMPBuilder.createSections(
4431 Builder, AllocaIP, SectionCBVector, PrivCB, FiniCB, S.hasCancel(),
4439 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4444 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(),
4452 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4453 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4454 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4456 const Stmt *SectionRegionBodyStmt = S.getAssociatedStmt();
4457 auto FiniCB = [
this](InsertPointTy IP) {
4459 return llvm::Error::success();
4462 auto BodyGenCB = [SectionRegionBodyStmt,
this](InsertPointTy AllocaIP,
4463 InsertPointTy CodeGenIP) {
4465 *
this, SectionRegionBodyStmt, AllocaIP, CodeGenIP,
"section");
4466 return llvm::Error::success();
4471 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4472 cantFail(OMPBuilder.createSection(
Builder, BodyGenCB, FiniCB));
4492 CopyprivateVars.append(
C->varlist_begin(),
C->varlist_end());
4493 DestExprs.append(
C->destination_exprs().begin(),
4494 C->destination_exprs().end());
4495 SrcExprs.append(
C->source_exprs().begin(),
C->source_exprs().end());
4496 AssignmentOps.append(
C->assignment_ops().begin(),
4497 C->assignment_ops().end());
4506 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4511 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4512 CGM.getOpenMPRuntime().emitSingleRegion(*
this,
CodeGen, S.getBeginLoc(),
4513 CopyprivateVars, DestExprs,
4514 SrcExprs, AssignmentOps);
4518 if (!S.getSingleClause<
OMPNowaitClause>() && CopyprivateVars.empty()) {
4519 CGM.getOpenMPRuntime().emitBarrierCall(
4520 *
this, S.getBeginLoc(),
4536 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4537 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4538 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4540 const Stmt *MasterRegionBodyStmt = S.getAssociatedStmt();
4542 auto FiniCB = [
this](InsertPointTy IP) {
4544 return llvm::Error::success();
4547 auto BodyGenCB = [MasterRegionBodyStmt,
this](InsertPointTy AllocaIP,
4548 InsertPointTy CodeGenIP) {
4550 *
this, MasterRegionBodyStmt, AllocaIP, CodeGenIP,
"master");
4551 return llvm::Error::success();
4556 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4557 cantFail(OMPBuilder.createMaster(
Builder, BodyGenCB, FiniCB));
4572 Expr *Filter =
nullptr;
4574 Filter = FilterClause->getThreadID();
4580 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4581 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4582 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4584 const Stmt *MaskedRegionBodyStmt = S.getAssociatedStmt();
4585 const Expr *Filter =
nullptr;
4587 Filter = FilterClause->getThreadID();
4588 llvm::Value *FilterVal = Filter
4590 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
4592 auto FiniCB = [
this](InsertPointTy IP) {
4594 return llvm::Error::success();
4597 auto BodyGenCB = [MaskedRegionBodyStmt,
this](InsertPointTy AllocaIP,
4598 InsertPointTy CodeGenIP) {
4600 *
this, MaskedRegionBodyStmt, AllocaIP, CodeGenIP,
"masked");
4601 return llvm::Error::success();
4606 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
4607 OMPBuilder.createMasked(
Builder, BodyGenCB, FiniCB, FilterVal));
4618 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4619 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4620 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4622 const Stmt *CriticalRegionBodyStmt = S.getAssociatedStmt();
4623 const Expr *Hint =
nullptr;
4624 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4625 Hint = HintClause->getHint();
4630 llvm::Value *HintInst =
nullptr;
4635 auto FiniCB = [
this](InsertPointTy IP) {
4637 return llvm::Error::success();
4640 auto BodyGenCB = [CriticalRegionBodyStmt,
this](InsertPointTy AllocaIP,
4641 InsertPointTy CodeGenIP) {
4643 *
this, CriticalRegionBodyStmt, AllocaIP, CodeGenIP,
"critical");
4644 return llvm::Error::success();
4649 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4650 cantFail(OMPBuilder.createCritical(
Builder, BodyGenCB, FiniCB,
4651 S.getDirectiveName().getAsString(),
4660 CGF.
EmitStmt(S.getAssociatedStmt());
4662 const Expr *Hint =
nullptr;
4663 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4664 Hint = HintClause->getHint();
4667 CGM.getOpenMPRuntime().emitCriticalRegion(*
this,
4668 S.getDirectiveName().getAsString(),
4669 CodeGen, S.getBeginLoc(), Hint);
4673 const OMPParallelForDirective &S) {
4682 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
4686 OMPLoopScope LoopScope(CGF, S);
4691 return C->getModifier() == OMPC_REDUCTION_inscan;
4707 const OMPParallelForSimdDirective &S) {
4716 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
4720 OMPLoopScope LoopScope(CGF, S);
4725 return C->getModifier() == OMPC_REDUCTION_inscan;
4741 const OMPParallelMasterDirective &S) {
4761 [](CodeGenFunction &) {
return nullptr; });
4768 const OMPParallelMaskedDirective &S) {
4788 [](CodeGenFunction &) {
return nullptr; });
4795 const OMPParallelSectionsDirective &S) {
4801 CGF.EmitSections(S);
4815class CheckVarsEscapingUntiedTaskDeclContext final
4820 explicit CheckVarsEscapingUntiedTaskDeclContext() =
default;
4821 ~CheckVarsEscapingUntiedTaskDeclContext() =
default;
4822 void VisitDeclStmt(
const DeclStmt *S) {
4827 if (
const auto *VD = dyn_cast_or_null<VarDecl>(D))
4829 PrivateDecls.push_back(VD);
4833 void VisitCapturedStmt(
const CapturedStmt *) {}
4835 void VisitBlockExpr(
const BlockExpr *) {}
4836 void VisitStmt(
const Stmt *S) {
4839 for (
const Stmt *Child : S->
children())
4845 ArrayRef<const VarDecl *> getPrivateDecls()
const {
return PrivateDecls; }
4853 bool OmpAllMemory =
false;
4856 return C->getDependencyKind() == OMPC_DEPEND_outallmemory ||
4857 C->getDependencyKind() == OMPC_DEPEND_inoutallmemory;
4859 OmpAllMemory =
true;
4864 Data.Dependences.emplace_back(OMPC_DEPEND_outallmemory,
4873 if (Kind == OMPC_DEPEND_outallmemory || Kind == OMPC_DEPEND_inoutallmemory)
4875 if (OmpAllMemory && (Kind == OMPC_DEPEND_out || Kind == OMPC_DEPEND_inout))
4878 Data.Dependences.emplace_back(
C->getDependencyKind(),
C->getModifier());
4879 DD.
DepExprs.append(
C->varlist_begin(),
C->varlist_end());
4888 const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion);
4890 auto PartId = std::next(I);
4891 auto TaskT = std::next(I, 4);
4896 const Expr *
Cond = Clause->getCondition();
4899 Data.Final.setInt(CondConstant);
4904 Data.Final.setInt(
false);
4908 const Expr *Prio = Clause->getPriority();
4909 Data.Priority.setInt(
true);
4917 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
4920 auto IRef =
C->varlist_begin();
4921 for (
const Expr *IInit :
C->private_copies()) {
4923 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
4924 Data.PrivateVars.push_back(*IRef);
4925 Data.PrivateCopies.push_back(IInit);
4930 EmittedAsPrivate.clear();
4933 auto IRef =
C->varlist_begin();
4934 auto IElemInitRef =
C->inits().begin();
4935 for (
const Expr *IInit :
C->private_copies()) {
4937 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
4938 Data.FirstprivateVars.push_back(*IRef);
4939 Data.FirstprivateCopies.push_back(IInit);
4940 Data.FirstprivateInits.push_back(*IElemInitRef);
4947 llvm::MapVector<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
4949 auto IRef =
C->varlist_begin();
4950 auto ID =
C->destination_exprs().begin();
4951 for (
const Expr *IInit :
C->private_copies()) {
4953 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
4954 Data.LastprivateVars.push_back(*IRef);
4955 Data.LastprivateCopies.push_back(IInit);
4957 LastprivateDstsOrigs.insert(
4967 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
4968 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
4969 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
4970 Data.ReductionOps.append(
C->reduction_ops().begin(),
4971 C->reduction_ops().end());
4972 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
4973 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
4975 Data.Reductions =
CGM.getOpenMPRuntime().emitTaskReductionInit(
4976 *
this, S.getBeginLoc(), LHSs, RHSs,
Data);
4981 CheckVarsEscapingUntiedTaskDeclContext Checker;
4982 Checker.Visit(S.getInnermostCapturedStmt()->getCapturedStmt());
4983 Data.PrivateLocals.append(Checker.getPrivateDecls().begin(),
4984 Checker.getPrivateDecls().end());
4986 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
4987 CapturedRegion](CodeGenFunction &CGF,
4989 llvm::MapVector<CanonicalDeclPtr<const VarDecl>,
4990 std::pair<Address, Address>>
4995 if (
auto *DI = CGF.getDebugInfo()) {
4996 llvm::SmallDenseMap<const VarDecl *, FieldDecl *> CaptureFields =
4997 CGF.CapturedStmtInfo->getCaptureFields();
4998 llvm::Value *ContextValue = CGF.CapturedStmtInfo->getContextValue();
4999 if (CaptureFields.size() && ContextValue) {
5000 unsigned CharWidth = CGF.getContext().getCharWidth();
5014 for (
auto It = CaptureFields.begin(); It != CaptureFields.end(); ++It) {
5015 const VarDecl *SharedVar = It->first;
5018 CGF.getContext().getASTRecordLayout(CaptureRecord);
5021 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5022 (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue,
5023 CGF.Builder,
false);
5026 auto UpdateExpr = [](llvm::LLVMContext &Ctx,
auto *
Declare,
5031 Ops.push_back(llvm::dwarf::DW_OP_plus_uconst);
5032 Ops.push_back(Offset);
5034 Ops.push_back(llvm::dwarf::DW_OP_deref);
5035 Declare->setExpression(llvm::DIExpression::get(Ctx, Ops));
5037 llvm::Instruction &
Last = CGF.Builder.GetInsertBlock()->back();
5038 if (
auto DDI = dyn_cast<llvm::DbgVariableIntrinsic>(&
Last))
5039 UpdateExpr(DDI->getContext(), DDI, Offset);
5042 assert(!
Last.isTerminator() &&
"unexpected terminator");
5044 CGF.Builder.GetInsertBlock()->getTrailingDbgRecords()) {
5045 for (llvm::DbgVariableRecord &DVR : llvm::reverse(
5046 llvm::filterDbgVars(Marker->getDbgRecordRange()))) {
5047 UpdateExpr(
Last.getContext(), &DVR, Offset);
5055 if (!
Data.PrivateVars.empty() || !
Data.FirstprivateVars.empty() ||
5056 !
Data.LastprivateVars.empty() || !
Data.PrivateLocals.empty()) {
5057 enum { PrivatesParam = 2, CopyFnParam = 3 };
5058 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5060 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5066 CallArgs.push_back(PrivatesPtr);
5067 ParamTypes.push_back(PrivatesPtr->getType());
5068 for (
const Expr *E :
Data.PrivateVars) {
5071 CGF.getContext().getPointerType(E->
getType()),
".priv.ptr.addr");
5072 PrivatePtrs.emplace_back(VD, PrivatePtr);
5074 ParamTypes.push_back(PrivatePtr.
getType());
5076 for (
const Expr *E :
Data.FirstprivateVars) {
5079 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
5080 ".firstpriv.ptr.addr");
5081 PrivatePtrs.emplace_back(VD, PrivatePtr);
5082 FirstprivatePtrs.emplace_back(VD, PrivatePtr);
5084 ParamTypes.push_back(PrivatePtr.
getType());
5086 for (
const Expr *E :
Data.LastprivateVars) {
5089 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
5090 ".lastpriv.ptr.addr");
5091 PrivatePtrs.emplace_back(VD, PrivatePtr);
5093 ParamTypes.push_back(PrivatePtr.
getType());
5098 Ty = CGF.getContext().getPointerType(Ty);
5100 Ty = CGF.getContext().getPointerType(Ty);
5102 CGF.getContext().getPointerType(Ty),
".local.ptr.addr");
5103 auto Result = UntiedLocalVars.insert(
5106 if (
Result.second ==
false)
5107 *
Result.first = std::make_pair(
5110 ParamTypes.push_back(PrivatePtr.
getType());
5112 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5114 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5115 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5116 for (
const auto &Pair : LastprivateDstsOrigs) {
5120 CGF.CapturedStmtInfo->lookup(OrigVD) !=
nullptr,
5122 Pair.second->getExprLoc());
5123 Scope.addPrivate(Pair.first, CGF.EmitLValue(&DRE).getAddress());
5125 for (
const auto &Pair : PrivatePtrs) {
5127 CGF.Builder.CreateLoad(Pair.second),
5128 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5129 CGF.getContext().getDeclAlign(Pair.first));
5130 Scope.addPrivate(Pair.first, Replacement);
5131 if (
auto *DI = CGF.getDebugInfo())
5132 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5133 (void)DI->EmitDeclareOfAutoVariable(
5134 Pair.first, Pair.second.getBasePointer(), CGF.Builder,
5139 for (
auto &Pair : UntiedLocalVars) {
5140 QualType VDType = Pair.first->getType().getNonReferenceType();
5141 if (Pair.first->getType()->isLValueReferenceType())
5142 VDType = CGF.getContext().getPointerType(VDType);
5144 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5147 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(VDType)),
5148 CGF.getPointerAlign());
5149 Pair.second.first = Replacement;
5150 Ptr = CGF.Builder.CreateLoad(Replacement);
5151 Replacement =
Address(Ptr, CGF.ConvertTypeForMem(VDType),
5152 CGF.getContext().getDeclAlign(Pair.first));
5153 Pair.second.second = Replacement;
5155 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5156 Address Replacement(Ptr, CGF.ConvertTypeForMem(VDType),
5157 CGF.getContext().getDeclAlign(Pair.first));
5158 Pair.second.first = Replacement;
5162 if (
Data.Reductions) {
5164 for (
const auto &Pair : FirstprivatePtrs) {
5166 CGF.Builder.CreateLoad(Pair.second),
5167 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5168 CGF.getContext().getDeclAlign(Pair.first));
5169 FirstprivateScope.
addPrivate(Pair.first, Replacement);
5172 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5174 Data.ReductionCopies,
Data.ReductionOps);
5175 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
5177 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5183 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5185 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5188 CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF),
5189 CGF.getContext().VoidPtrTy,
5190 CGF.getContext().getPointerType(
5191 Data.ReductionCopies[Cnt]->getType()),
5192 Data.ReductionCopies[Cnt]->getExprLoc()),
5193 CGF.ConvertTypeForMem(
Data.ReductionCopies[Cnt]->getType()),
5194 Replacement.getAlignment());
5200 (void)
Scope.Privatize();
5206 auto IPriv =
C->privates().begin();
5207 auto IRed =
C->reduction_ops().begin();
5208 auto ITD =
C->taskgroup_descriptors().begin();
5209 for (
const Expr *Ref :
C->varlist()) {
5210 InRedVars.emplace_back(Ref);
5211 InRedPrivs.emplace_back(*IPriv);
5212 InRedOps.emplace_back(*IRed);
5213 TaskgroupDescriptors.emplace_back(*ITD);
5214 std::advance(IPriv, 1);
5215 std::advance(IRed, 1);
5216 std::advance(ITD, 1);
5222 if (!InRedVars.empty()) {
5224 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5232 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5234 llvm::Value *ReductionsPtr;
5235 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5236 ReductionsPtr = CGF.EmitLoadOfScalar(CGF.EmitLValue(TRExpr),
5237 TRExpr->getExprLoc());
5239 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5241 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5244 CGF.EmitScalarConversion(
5245 Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy,
5246 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
5247 InRedPrivs[Cnt]->getExprLoc()),
5248 CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()),
5249 Replacement.getAlignment());
5262 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5263 S, *I, *PartId, *TaskT, EKind,
CodeGen,
Data.Tied,
Data.NumberOfParts);
5264 OMPLexicalScope
Scope(*
this, S, std::nullopt,
5267 TaskGen(*
this, OutlinedFn,
Data);
5284 QualType ElemType =
C.getBaseElementType(Ty);
5294 Data.FirstprivateVars.emplace_back(OrigRef);
5295 Data.FirstprivateCopies.emplace_back(PrivateRef);
5296 Data.FirstprivateInits.emplace_back(InitRef);
5309 auto PartId = std::next(I);
5310 auto TaskT = std::next(I, 4);
5313 Data.Final.setInt(
false);
5316 auto IRef =
C->varlist_begin();
5317 auto IElemInitRef =
C->inits().begin();
5318 for (
auto *IInit :
C->private_copies()) {
5319 Data.FirstprivateVars.push_back(*IRef);
5320 Data.FirstprivateCopies.push_back(IInit);
5321 Data.FirstprivateInits.push_back(*IElemInitRef);
5329 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5330 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5331 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5332 Data.ReductionOps.append(
C->reduction_ops().begin(),
5333 C->reduction_ops().end());
5334 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5335 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5350 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5352 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5364 if (!isa_and_nonnull<llvm::ConstantPointerNull>(
5367 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5374 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, BPVD, PVD, SVD, MVD, EKind,
5378 if (!
Data.FirstprivateVars.empty()) {
5379 enum { PrivatesParam = 2, CopyFnParam = 3 };
5380 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5382 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5388 CallArgs.push_back(PrivatesPtr);
5389 ParamTypes.push_back(PrivatesPtr->getType());
5390 for (
const Expr *E :
Data.FirstprivateVars) {
5393 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
5394 ".firstpriv.ptr.addr");
5395 PrivatePtrs.emplace_back(VD, PrivatePtr);
5397 ParamTypes.push_back(PrivatePtr.
getType());
5399 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5401 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5402 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5403 for (
const auto &Pair : PrivatePtrs) {
5405 CGF.Builder.CreateLoad(Pair.second),
5406 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5407 CGF.getContext().getDeclAlign(Pair.first));
5408 Scope.addPrivate(Pair.first, Replacement);
5411 CGF.processInReduction(S,
Data, CGF, CS,
Scope);
5414 CGF.GetAddrOfLocalVar(BPVD), 0);
5416 CGF.GetAddrOfLocalVar(PVD), 0);
5417 InputInfo.
SizesArray = CGF.Builder.CreateConstArrayGEP(
5418 CGF.GetAddrOfLocalVar(SVD), 0);
5421 InputInfo.
MappersArray = CGF.Builder.CreateConstArrayGEP(
5422 CGF.GetAddrOfLocalVar(MVD), 0);
5426 OMPLexicalScope LexScope(CGF, S, OMPD_task,
false);
5428 if (CGF.CGM.getLangOpts().OpenMP >= 51 &&
5433 CGF.CGM.getOpenMPRuntime().emitThreadLimitClause(
5434 CGF, TL->getThreadLimit().front(), S.getBeginLoc());
5438 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5439 S, *I, *PartId, *TaskT, EKind,
CodeGen,
true,
5440 Data.NumberOfParts);
5441 llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<
OMPNowaitClause>() ? 1 : 0);
5445 CGM.getOpenMPRuntime().emitTaskCall(*
this, S.getBeginLoc(), S, OutlinedFn,
5446 SharedsTy, CapturedStruct, &IfCond,
Data);
5451 CodeGenFunction &CGF,
5455 if (
Data.Reductions) {
5457 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5459 Data.ReductionCopies,
Data.ReductionOps);
5462 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5476 Data.ReductionCopies[Cnt]->getType()),
5477 Data.ReductionCopies[Cnt]->getExprLoc()),
5479 Replacement.getAlignment());
5484 (void)
Scope.Privatize();
5490 auto IPriv =
C->privates().begin();
5491 auto IRed =
C->reduction_ops().begin();
5492 auto ITD =
C->taskgroup_descriptors().begin();
5493 for (
const Expr *Ref :
C->varlist()) {
5494 InRedVars.emplace_back(Ref);
5495 InRedPrivs.emplace_back(*IPriv);
5496 InRedOps.emplace_back(*IRed);
5497 TaskgroupDescriptors.emplace_back(*ITD);
5498 std::advance(IPriv, 1);
5499 std::advance(IRed, 1);
5500 std::advance(ITD, 1);
5504 if (!InRedVars.empty()) {
5506 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5514 llvm::Value *ReductionsPtr;
5515 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5519 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
5527 InRedPrivs[Cnt]->getExprLoc()),
5529 Replacement.getAlignment());
5543 const Expr *IfCond =
nullptr;
5544 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
5545 if (
C->getNameModifier() == OMPD_unknown ||
5546 C->getNameModifier() == OMPD_task) {
5547 IfCond =
C->getCondition();
5558 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
5559 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
5562 SharedsTy, CapturedStruct, IfCond,
5571 const OMPTaskyieldDirective &S) {
5572 CGM.getOpenMPRuntime().emitTaskyieldCall(*
this, S.getBeginLoc());
5579 bool IsFatal =
false;
5582 CGM.getOpenMPRuntime().emitErrorCall(*
this, S.getBeginLoc(), ME, IsFatal);
5586 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_barrier);
5594 CGM.getOpenMPRuntime().emitTaskwaitCall(*
this, S.getBeginLoc(),
Data);
5598 return T.clauses().empty();
5602 const OMPTaskgroupDirective &S) {
5603 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
5605 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
5606 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5610 auto BodyGenCB = [&,
this](InsertPointTy AllocaIP,
5611 InsertPointTy CodeGenIP) {
5613 EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5614 return llvm::Error::success();
5619 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5620 cantFail(OMPBuilder.createTaskgroup(
Builder, AllocaIP, BodyGenCB));
5626 if (
const Expr *E = S.getReductionRef()) {
5631 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5632 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5633 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5634 Data.ReductionOps.append(
C->reduction_ops().begin(),
5635 C->reduction_ops().end());
5636 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5637 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5639 llvm::Value *ReductionDesc =
5647 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5649 CGM.getOpenMPRuntime().emitTaskgroupRegion(*
this,
CodeGen, S.getBeginLoc());
5654 ? llvm::AtomicOrdering::NotAtomic
5655 : llvm::AtomicOrdering::AcquireRelease;
5656 CGM.getOpenMPRuntime().emitFlush(
5659 if (
const auto *FlushClause = S.getSingleClause<
OMPFlushClause>())
5661 FlushClause->varlist_end());
5664 S.getBeginLoc(), AO);
5674 for (
auto &Dep :
Data.Dependences) {
5675 Address DepAddr =
CGM.getOpenMPRuntime().emitDepobjDependClause(
5676 *
this, Dep, DC->getBeginLoc());
5682 CGM.getOpenMPRuntime().emitDestroyClause(*
this, DOLVal, DC->getBeginLoc());
5686 CGM.getOpenMPRuntime().emitUpdateClause(
5687 *
this, DOLVal, UC->getDependencyKind(), UC->getBeginLoc());
5706 if (
C->getModifier() != OMPC_REDUCTION_inscan)
5708 Shareds.append(
C->varlist_begin(),
C->varlist_end());
5709 Privates.append(
C->privates().begin(),
C->privates().end());
5710 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5711 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5712 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
5713 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
5714 CopyArrayTemps.append(
C->copy_array_temps().begin(),
5715 C->copy_array_temps().end());
5716 CopyArrayElems.append(
C->copy_array_elems().begin(),
5717 C->copy_array_elems().end());
5719 if (ParentDir.getDirectiveKind() == OMPD_simd ||
5761 : BreakContinueStack.back().ContinueBlock.getBlock());
5772 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
5773 const Expr *PrivateExpr = Privates[I];
5774 const Expr *TempExpr = CopyArrayTemps[I];
5786 CGM.getOpenMPRuntime().emitReduction(
5787 *
this, ParentDir.getEndLoc(), Privates, LHSs, RHSs, ReductionOps,
5790 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
5791 const Expr *PrivateExpr = Privates[I];
5798 const Expr *TempExpr = CopyArrayTemps[I];
5810 ? BreakContinueStack.back().ContinueBlock.getBlock()
5816 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
5822 .getIterationVariable()
5823 ->IgnoreParenImpCasts();
5826 IdxVal = Builder.CreateIntCast(IdxVal,
SizeTy,
false);
5827 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
5828 const Expr *PrivateExpr = Privates[I];
5829 const Expr *OrigExpr = Shareds[I];
5830 const Expr *CopyArrayElem = CopyArrayElems[I];
5831 OpaqueValueMapping IdxMapping(
5844 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
5847 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
5853 .getIterationVariable()
5854 ->IgnoreParenImpCasts();
5858 llvm::BasicBlock *ExclusiveExitBB =
nullptr;
5862 llvm::Value *Cmp =
Builder.CreateIsNull(IdxVal);
5863 Builder.CreateCondBr(Cmp, ExclusiveExitBB, ContBB);
5866 IdxVal =
Builder.CreateNUWSub(IdxVal, llvm::ConstantInt::get(
SizeTy, 1));
5868 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
5869 const Expr *PrivateExpr = Privates[I];
5870 const Expr *OrigExpr = Shareds[I];
5871 const Expr *CopyArrayElem = CopyArrayElems[I];
5880 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
5904 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
5912 bool HasLastprivateClause =
false;
5915 OMPLoopScope PreInitScope(*
this, S);
5920 llvm::BasicBlock *ContBlock =
nullptr;
5927 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
5941 ? S.getCombinedLowerBoundVariable()
5942 : S.getLowerBoundVariable())));
5946 ? S.getCombinedUpperBoundVariable()
5947 : S.getUpperBoundVariable())));
5958 CGM.getOpenMPRuntime().emitBarrierCall(
5959 *
this, S.getBeginLoc(), OMPD_unknown,
false,
5971 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
5974 llvm::Value *Chunk =
nullptr;
5977 ScheduleKind =
C->getDistScheduleKind();
5978 if (
const Expr *Ch =
C->getChunkSize()) {
5981 S.getIterationVariable()->getType(),
5986 CGM.getOpenMPRuntime().getDefaultDistScheduleAndChunk(
5987 *
this, S, ScheduleKind, Chunk);
6000 bool StaticChunked =
6004 Chunk !=
nullptr) ||
6009 StaticChunked ? Chunk :
nullptr);
6016 ? S.getCombinedEnsureUpperBound()
6017 : S.getEnsureUpperBound());
6020 ? S.getCombinedInit()
6025 ? S.getCombinedCond()
6029 Cond = S.getCombinedDistCond();
6061 [&S, &LoopScope,
Cond, IncExpr,
LoopExit, &CodeGenLoop,
6064 S, LoopScope.requiresCleanups(),
Cond, IncExpr,
6065 [&S,
LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
6066 CodeGenLoop(CGF, S, LoopExit);
6068 [&S, StaticChunked](CodeGenFunction &CGF) {
6069 if (StaticChunked) {
6070 CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound());
6071 CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound());
6072 CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound());
6073 CGF.EmitIgnoredExpr(S.getCombinedInit());
6083 const OMPLoopArguments LoopArguments = {
6084 LB.getAddress(), UB.getAddress(), ST.getAddress(), IL.getAddress(),
6086 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments,
6091 return CGF.
Builder.CreateIsNotNull(
6101 *
this, S, [IL, &S](CodeGenFunction &CGF) {
6102 return CGF.
Builder.CreateIsNotNull(
6107 if (HasLastprivateClause) {
6130 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
6139static llvm::Function *
6146 Fn->setDoesNotRecurse();
6150template <
typename T>
6152 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP,
6153 llvm::OpenMPIRBuilder &OMPBuilder) {
6155 unsigned NumLoops =
C->getNumLoops();
6159 for (
unsigned I = 0; I < NumLoops; I++) {
6160 const Expr *CounterVal =
C->getLoopData(I);
6165 StoreValues.emplace_back(StoreValue);
6167 OMPDoacrossKind<T> ODK;
6168 bool IsDependSource = ODK.isSource(
C);
6170 OMPBuilder.createOrderedDepend(CGF.
Builder, AllocaIP, NumLoops,
6171 StoreValues,
".cnt.addr", IsDependSource));
6175 if (
CGM.getLangOpts().OpenMPIRBuilder) {
6176 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
6177 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6182 assert(!S.hasAssociatedStmt() &&
"No associated statement must be in "
6183 "ordered depend|doacross construct.");
6195 auto FiniCB = [
this](InsertPointTy IP) {
6197 return llvm::Error::success();
6200 auto BodyGenCB = [&S,
C,
this](InsertPointTy AllocaIP,
6201 InsertPointTy CodeGenIP) {
6206 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
6207 Builder,
false,
".ordered.after");
6211 assert(S.getBeginLoc().isValid() &&
6212 "Outlined function call location must be valid.");
6215 OutlinedFn, CapturedVars);
6220 return llvm::Error::success();
6223 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6224 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
6225 OMPBuilder.createOrderedThreadsSimd(
Builder, BodyGenCB, FiniCB, !
C));
6232 assert(!S.hasAssociatedStmt() &&
6233 "No associated statement must be in ordered depend construct.");
6235 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6239 assert(!S.hasAssociatedStmt() &&
6240 "No associated statement must be in ordered doacross construct.");
6242 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6246 auto &&
CodeGen = [&S,
C,
this](CodeGenFunction &CGF,
6251 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
6253 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
6254 OutlinedFn, CapturedVars);
6260 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6261 CGM.getOpenMPRuntime().emitOrderedRegion(*
this,
CodeGen, S.getBeginLoc(), !
C);
6268 "DestType must have scalar evaluation kind.");
6269 assert(!Val.
isAggregate() &&
"Must be a scalar or complex.");
6280 "DestType must have complex evaluation kind.");
6289 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
6291 assert(Val.
isComplex() &&
"Must be a scalar or complex.");
6296 Val.
getComplexVal().first, SrcElementType, DestElementType, Loc);
6298 Val.
getComplexVal().second, SrcElementType, DestElementType, Loc);
6304 LValue LVal,
RValue RVal) {
6305 if (LVal.isGlobalReg())
6312 llvm::AtomicOrdering AO, LValue LVal,
6314 if (LVal.isGlobalReg())
6317 LVal, Loc, llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO),
6326 *
this, RVal, RValTy, LVal.
getType(), Loc)),
6335 llvm_unreachable(
"Must be a scalar or complex.");
6343 assert(
V->isLValue() &&
"V of 'omp atomic read' is not lvalue");
6344 assert(
X->isLValue() &&
"X of 'omp atomic read' is not lvalue");
6353 case llvm::AtomicOrdering::Acquire:
6354 case llvm::AtomicOrdering::AcquireRelease:
6355 case llvm::AtomicOrdering::SequentiallyConsistent:
6357 llvm::AtomicOrdering::Acquire);
6359 case llvm::AtomicOrdering::Monotonic:
6360 case llvm::AtomicOrdering::Release:
6362 case llvm::AtomicOrdering::NotAtomic:
6363 case llvm::AtomicOrdering::Unordered:
6364 llvm_unreachable(
"Unexpected ordering.");
6371 llvm::AtomicOrdering AO,
const Expr *
X,
6374 assert(
X->isLValue() &&
"X of 'omp atomic write' is not lvalue");
6382 case llvm::AtomicOrdering::Release:
6383 case llvm::AtomicOrdering::AcquireRelease:
6384 case llvm::AtomicOrdering::SequentiallyConsistent:
6386 llvm::AtomicOrdering::Release);
6388 case llvm::AtomicOrdering::Acquire:
6389 case llvm::AtomicOrdering::Monotonic:
6391 case llvm::AtomicOrdering::NotAtomic:
6392 case llvm::AtomicOrdering::Unordered:
6393 llvm_unreachable(
"Unexpected ordering.");
6400 llvm::AtomicOrdering AO,
6406 if (BO == BO_Comma || !
Update.isScalar() || !
X.isSimple() ||
6408 (
Update.getScalarVal()->getType() !=
X.getAddress().getElementType())) ||
6409 !Context.getTargetInfo().hasBuiltinAtomic(
6410 Context.getTypeSize(
X.getType()), Context.toBits(
X.getAlignment())))
6411 return std::make_pair(
false,
RValue::get(
nullptr));
6414 if (
T->isIntegerTy())
6417 if (
T->isFloatingPointTy() && (BO == BO_Add || BO == BO_Sub))
6423 if (!CheckAtomicSupport(
Update.getScalarVal()->getType(), BO) ||
6424 !CheckAtomicSupport(
X.getAddress().getElementType(), BO))
6425 return std::make_pair(
false,
RValue::get(
nullptr));
6427 bool IsInteger =
X.getAddress().getElementType()->isIntegerTy();
6428 llvm::AtomicRMWInst::BinOp RMWOp;
6431 RMWOp = IsInteger ? llvm::AtomicRMWInst::Add : llvm::AtomicRMWInst::FAdd;
6435 return std::make_pair(
false,
RValue::get(
nullptr));
6436 RMWOp = IsInteger ? llvm::AtomicRMWInst::Sub : llvm::AtomicRMWInst::FSub;
6439 RMWOp = llvm::AtomicRMWInst::And;
6442 RMWOp = llvm::AtomicRMWInst::Or;
6445 RMWOp = llvm::AtomicRMWInst::Xor;
6449 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6451 : llvm::AtomicRMWInst::Max)
6453 : llvm::AtomicRMWInst::UMax);
6456 : llvm::AtomicRMWInst::FMax;
6460 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6462 : llvm::AtomicRMWInst::Min)
6464 : llvm::AtomicRMWInst::UMin);
6467 : llvm::AtomicRMWInst::FMin;
6470 RMWOp = llvm::AtomicRMWInst::Xchg;
6479 return std::make_pair(
false,
RValue::get(
nullptr));
6498 llvm_unreachable(
"Unsupported atomic update operation");
6500 llvm::Value *UpdateVal =
Update.getScalarVal();
6501 if (
auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
6503 UpdateVal = CGF.
Builder.CreateIntCast(
6504 IC,
X.getAddress().getElementType(),
6505 X.getType()->hasSignedIntegerRepresentation());
6507 UpdateVal = CGF.
Builder.CreateCast(llvm::Instruction::CastOps::UIToFP, IC,
6508 X.getAddress().getElementType());
6510 llvm::AtomicRMWInst *Res =
6527 if (
X.isGlobalReg()) {
6540 llvm::AtomicOrdering AO,
const Expr *
X,
6544 "Update expr in 'atomic update' must be a binary operator.");
6552 assert(
X->isLValue() &&
"X of 'omp atomic update' is not lvalue");
6559 auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](
RValue XRValue) {
6565 XLValue, ExprRValue, BOUE->getOpcode(),
IsXLHSInRHSPart, AO, Loc, Gen);
6572 case llvm::AtomicOrdering::Release:
6573 case llvm::AtomicOrdering::AcquireRelease:
6574 case llvm::AtomicOrdering::SequentiallyConsistent:
6576 llvm::AtomicOrdering::Release);
6578 case llvm::AtomicOrdering::Acquire:
6579 case llvm::AtomicOrdering::Monotonic:
6581 case llvm::AtomicOrdering::NotAtomic:
6582 case llvm::AtomicOrdering::Unordered:
6583 llvm_unreachable(
"Unexpected ordering.");
6601 llvm_unreachable(
"Must be a scalar or complex.");
6605 llvm::AtomicOrdering AO,
6610 assert(
X->isLValue() &&
"X of 'omp atomic capture' is not lvalue");
6611 assert(
V->isLValue() &&
"V of 'omp atomic capture' is not lvalue");
6620 "Update expr in 'atomic capture' must be a binary operator.");
6631 NewVValType = XRValExpr->
getType();
6633 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
6642 XLValue, ExprRValue, BOUE->getOpcode(),
IsXLHSInRHSPart, AO, Loc, Gen);
6648 NewVVal = Res.second;
6659 NewVValType =
X->getType().getNonReferenceType();
6661 X->getType().getNonReferenceType(), Loc);
6662 auto &&Gen = [&NewVVal, ExprRValue](
RValue XRValue) {
6668 XLValue, ExprRValue, BO_Assign,
false, AO,
6689 case llvm::AtomicOrdering::Release:
6691 llvm::AtomicOrdering::Release);
6693 case llvm::AtomicOrdering::Acquire:
6695 llvm::AtomicOrdering::Acquire);
6697 case llvm::AtomicOrdering::AcquireRelease:
6698 case llvm::AtomicOrdering::SequentiallyConsistent:
6700 CGF, {}, Loc, llvm::AtomicOrdering::AcquireRelease);
6702 case llvm::AtomicOrdering::Monotonic:
6704 case llvm::AtomicOrdering::NotAtomic:
6705 case llvm::AtomicOrdering::Unordered:
6706 llvm_unreachable(
"Unexpected ordering.");
6712 CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO,
6716 llvm::OpenMPIRBuilder &OMPBuilder =
6719 OMPAtomicCompareOp Op;
6723 Op = OMPAtomicCompareOp::EQ;
6726 Op = OMPAtomicCompareOp::MIN;
6729 Op = OMPAtomicCompareOp::MAX;
6732 llvm_unreachable(
"unsupported atomic compare binary operator");
6736 Address XAddr = XLVal.getAddress();
6738 auto EmitRValueWithCastIfNeeded = [&CGF, Loc](
const Expr *
X,
const Expr *E) {
6743 if (NewE->
getType() ==
X->getType())
6748 llvm::Value *EVal = EmitRValueWithCastIfNeeded(
X, E);
6749 llvm::Value *DVal = D ? EmitRValueWithCastIfNeeded(
X, D) :
nullptr;
6750 if (
auto *CI = dyn_cast<llvm::ConstantInt>(EVal))
6751 EVal = CGF.
Builder.CreateIntCast(
6752 CI, XLVal.getAddress().getElementType(),
6755 if (
auto *CI = dyn_cast<llvm::ConstantInt>(DVal))
6756 DVal = CGF.
Builder.CreateIntCast(
6757 CI, XLVal.getAddress().getElementType(),
6760 llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{
6762 X->getType()->hasSignedIntegerRepresentation(),
6763 X->getType().isVolatileQualified()};
6764 llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal;
6768 VOpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
6769 V->getType()->hasSignedIntegerRepresentation(),
6770 V->getType().isVolatileQualified()};
6775 ROpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
6780 if (FailAO == llvm::AtomicOrdering::NotAtomic) {
6783 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
6784 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
6787 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
6788 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
6793 llvm::AtomicOrdering AO,
6814 case OMPC_compare: {
6820 llvm_unreachable(
"Clause is not allowed in 'omp atomic'.");
6825 llvm::AtomicOrdering AO =
CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
6827 llvm::AtomicOrdering FailAO = llvm::AtomicOrdering::NotAtomic;
6828 bool MemOrderingSpecified =
false;
6830 AO = llvm::AtomicOrdering::SequentiallyConsistent;
6831 MemOrderingSpecified =
true;
6833 AO = llvm::AtomicOrdering::AcquireRelease;
6834 MemOrderingSpecified =
true;
6836 AO = llvm::AtomicOrdering::Acquire;
6837 MemOrderingSpecified =
true;
6839 AO = llvm::AtomicOrdering::Release;
6840 MemOrderingSpecified =
true;
6842 AO = llvm::AtomicOrdering::Monotonic;
6843 MemOrderingSpecified =
true;
6845 llvm::SmallSet<OpenMPClauseKind, 2> KindsEncountered;
6854 if (K == OMPC_seq_cst || K == OMPC_acq_rel || K == OMPC_acquire ||
6855 K == OMPC_release || K == OMPC_relaxed || K == OMPC_hint)
6858 KindsEncountered.insert(K);
6863 if (KindsEncountered.contains(OMPC_compare) &&
6864 KindsEncountered.contains(OMPC_capture))
6865 Kind = OMPC_compare;
6866 if (!MemOrderingSpecified) {
6867 llvm::AtomicOrdering DefaultOrder =
6868 CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
6869 if (DefaultOrder == llvm::AtomicOrdering::Monotonic ||
6870 DefaultOrder == llvm::AtomicOrdering::SequentiallyConsistent ||
6871 (DefaultOrder == llvm::AtomicOrdering::AcquireRelease &&
6872 Kind == OMPC_capture)) {
6874 }
else if (DefaultOrder == llvm::AtomicOrdering::AcquireRelease) {
6875 if (Kind == OMPC_unknown || Kind == OMPC_update || Kind == OMPC_write) {
6876 AO = llvm::AtomicOrdering::Release;
6877 }
else if (Kind == OMPC_read) {
6878 assert(Kind == OMPC_read &&
"Unexpected atomic kind.");
6879 AO = llvm::AtomicOrdering::Acquire;
6884 if (KindsEncountered.contains(OMPC_compare) &&
6885 KindsEncountered.contains(OMPC_fail)) {
6886 Kind = OMPC_compare;
6887 const auto *FailClause = S.getSingleClause<
OMPFailClause>();
6890 if (FailParameter == llvm::omp::OMPC_relaxed)
6891 FailAO = llvm::AtomicOrdering::Monotonic;
6892 else if (FailParameter == llvm::omp::OMPC_acquire)
6893 FailAO = llvm::AtomicOrdering::Acquire;
6894 else if (FailParameter == llvm::omp::OMPC_seq_cst)
6895 FailAO = llvm::AtomicOrdering::SequentiallyConsistent;
6902 S.getV(), S.getR(), S.getExpr(), S.getUpdateExpr(),
6903 S.getD(), S.getCondExpr(), S.isXLHSInRHSPart(),
6904 S.isFailOnly(), S.getBeginLoc());
6915 OMPLexicalScope
Scope(CGF, S, OMPD_target);
6918 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
6924 llvm::Function *Fn =
nullptr;
6925 llvm::Constant *FnID =
nullptr;
6927 const Expr *IfCond =
nullptr;
6929 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
6930 if (
C->getNameModifier() == OMPD_unknown ||
6931 C->getNameModifier() == OMPD_target) {
6932 IfCond =
C->getCondition();
6938 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device(
6941 Device.setPointerAndInt(
C->getDevice(),
C->getModifier());
6946 bool IsOffloadEntry =
true;
6950 IsOffloadEntry =
false;
6953 IsOffloadEntry =
false;
6955 if (
CGM.
getLangOpts().OpenMPOffloadMandatory && !IsOffloadEntry) {
6958 "No offloading entry generated while offloading is mandatory.");
6962 assert(CGF.
CurFuncDecl &&
"No parent declaration for target region!");
6963 StringRef ParentName;
6966 if (
const auto *D = dyn_cast<CXXConstructorDecl>(CGF.
CurFuncDecl))
6968 else if (
const auto *D = dyn_cast<CXXDestructorDecl>(CGF.
CurFuncDecl))
6977 OMPLexicalScope
Scope(CGF, S, OMPD_task);
6978 auto &&SizeEmitter =
6981 if (IsOffloadEntry) {
6982 OMPLoopScope(CGF, D);
6984 llvm::Value *NumIterations = CGF.
EmitScalarExpr(D.getNumIterations());
6985 NumIterations = CGF.
Builder.CreateIntCast(NumIterations, CGF.
Int64Ty,
6987 return NumIterations;
7005 CGF.
EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
7010 StringRef ParentName,
7016 llvm::Constant *
Addr;
7018 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7020 assert(Fn &&
Addr &&
"Target device function emission failed.");
7034 const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams);
7035 llvm::Function *OutlinedFn =
7043 const Expr *NumTeams = NT ? NT->getNumTeams().front() :
nullptr;
7044 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() :
nullptr;
7050 OMPTeamsScope
Scope(CGF, S);
7066 CGF.
EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt());
7071 [](CodeGenFunction &) {
return nullptr; });
7076 auto *CS = S.getCapturedStmt(OMPD_teams);
7103 llvm::Constant *
Addr;
7105 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7107 assert(Fn &&
Addr &&
"Target device function emission failed.");
7149 llvm::Constant *
Addr;
7151 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7153 assert(Fn &&
Addr &&
"Target device function emission failed.");
7195 llvm::Constant *
Addr;
7197 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7199 assert(Fn &&
Addr &&
"Target device function emission failed.");
7213 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7218 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7230 [](CodeGenFunction &) {
return nullptr; });
7235 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7240 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7252 [](CodeGenFunction &) {
return nullptr; });
7257 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7263 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7275 [](CodeGenFunction &) {
return nullptr; });
7280 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7286 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7293 CGF, OMPD_distribute, CodeGenDistribute,
false);
7299 [](CodeGenFunction &) {
return nullptr; });
7303 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7304 llvm::Value *
Device =
nullptr;
7305 llvm::Value *NumDependences =
nullptr;
7306 llvm::Value *DependenceList =
nullptr;
7314 if (!
Data.Dependences.empty()) {
7316 std::tie(NumDependences, DependenciesArray) =
7317 CGM.getOpenMPRuntime().emitDependClause(*
this,
Data.Dependences,
7326 "OMPNowaitClause clause is used separately in OMPInteropDirective.");
7329 if (!ItOMPInitClause.empty()) {
7332 llvm::Value *InteropvarPtr =
7334 llvm::omp::OMPInteropType InteropType =
7335 llvm::omp::OMPInteropType::Unknown;
7336 if (
C->getIsTarget()) {
7337 InteropType = llvm::omp::OMPInteropType::Target;
7339 assert(
C->getIsTargetSync() &&
7340 "Expected interop-type target/targetsync");
7341 InteropType = llvm::omp::OMPInteropType::TargetSync;
7343 OMPBuilder.createOMPInteropInit(
Builder, InteropvarPtr, InteropType,
7344 Device, NumDependences, DependenceList,
7345 Data.HasNowaitClause);
7349 if (!ItOMPDestroyClause.empty()) {
7352 llvm::Value *InteropvarPtr =
7354 OMPBuilder.createOMPInteropDestroy(
Builder, InteropvarPtr,
Device,
7355 NumDependences, DependenceList,
7356 Data.HasNowaitClause);
7359 auto ItOMPUseClause = S.getClausesOfKind<
OMPUseClause>();
7360 if (!ItOMPUseClause.empty()) {
7363 llvm::Value *InteropvarPtr =
7365 OMPBuilder.createOMPInteropUse(
Builder, InteropvarPtr,
Device,
7366 NumDependences, DependenceList,
7367 Data.HasNowaitClause);
7389 CGF, OMPD_distribute, CodeGenDistribute,
false);
7408 llvm::Constant *
Addr;
7410 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7412 assert(Fn &&
Addr &&
"Target device function emission failed.");
7441 CGF, OMPD_distribute, CodeGenDistribute,
false);
7460 llvm::Constant *
Addr;
7462 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7464 assert(Fn &&
Addr &&
"Target device function emission failed.");
7477 CGM.getOpenMPRuntime().emitCancellationPointCall(*
this, S.getBeginLoc(),
7482 const Expr *IfCond =
nullptr;
7483 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7484 if (
C->getNameModifier() == OMPD_unknown ||
7485 C->getNameModifier() == OMPD_cancel) {
7486 IfCond =
C->getCondition();
7490 if (
CGM.getLangOpts().OpenMPIRBuilder) {
7491 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7497 llvm::Value *IfCondition =
nullptr;
7501 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
7503 return Builder.restoreIP(AfterIP);
7507 CGM.getOpenMPRuntime().emitCancelCall(*
this, S.getBeginLoc(), IfCond,
7513 if (Kind == OMPD_parallel || Kind == OMPD_task ||
7514 Kind == OMPD_target_parallel || Kind == OMPD_taskloop ||
7515 Kind == OMPD_master_taskloop || Kind == OMPD_parallel_master_taskloop)
7517 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
7518 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
7519 Kind == OMPD_distribute_parallel_for ||
7520 Kind == OMPD_target_parallel_for ||
7521 Kind == OMPD_teams_distribute_parallel_for ||
7522 Kind == OMPD_target_teams_distribute_parallel_for);
7523 return OMPCancelStack.getExitBlock();
7528 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7529 CaptureDeviceAddrMap) {
7530 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7531 for (
const Expr *OrigVarIt :
C.varlist()) {
7533 if (!Processed.insert(OrigVD).second)
7540 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7545 "Base should be the current struct!");
7546 MatchingVD = ME->getMemberDecl();
7551 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7552 if (InitAddrIt == CaptureDeviceAddrMap.end())
7560 Address(InitAddrIt->second, Ty,
7562 assert(IsRegistered &&
"firstprivate var already registered as private");
7570 while (
const auto *OASE = dyn_cast<ArraySectionExpr>(
Base))
7571 Base = OASE->getBase()->IgnoreParenImpCasts();
7572 while (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(
Base))
7573 Base = ASE->getBase()->IgnoreParenImpCasts();
7579 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7580 CaptureDeviceAddrMap) {
7581 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7582 for (
const Expr *Ref :
C.varlist()) {
7584 if (!Processed.insert(OrigVD).second)
7590 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7595 "Base should be the current struct!");
7596 MatchingVD = ME->getMemberDecl();
7601 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7602 if (InitAddrIt == CaptureDeviceAddrMap.end())
7608 Address(InitAddrIt->second, Ty,
7621 (void)PrivateScope.
addPrivate(OrigVD, PrivAddr);
7634 bool PrivatizeDevicePointers =
false;
7636 bool &PrivatizeDevicePointers;
7639 explicit DevicePointerPrivActionTy(
bool &PrivatizeDevicePointers)
7640 : PrivatizeDevicePointers(PrivatizeDevicePointers) {}
7641 void Enter(CodeGenFunction &CGF)
override {
7642 PrivatizeDevicePointers =
true;
7645 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
7648 auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7649 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
7653 auto &&PrivCodeGen = [&](CodeGenFunction &CGF,
PrePostActionTy &Action) {
7655 PrivatizeDevicePointers =
false;
7661 if (PrivatizeDevicePointers) {
7675 std::optional<OpenMPDirectiveKind> CaptureRegion;
7676 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
7679 for (
const Expr *E :
C->varlist()) {
7681 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
7685 for (
const Expr *E :
C->varlist()) {
7687 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
7691 CaptureRegion = OMPD_unknown;
7694 OMPLexicalScope
Scope(CGF, S, CaptureRegion);
7706 OMPLexicalScope
Scope(CGF, S);
7715 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
7721 const Expr *IfCond =
nullptr;
7723 IfCond =
C->getCondition();
7734 CGM.getOpenMPRuntime().emitTargetDataCalls(*
this, S, IfCond,
Device, RCG,
7742 if (
CGM.getLangOpts().OMPTargetTriples.empty())
7746 const Expr *IfCond =
nullptr;
7748 IfCond =
C->getCondition();
7755 OMPLexicalScope
Scope(*
this, S, OMPD_task);
7756 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
7763 if (
CGM.getLangOpts().OMPTargetTriples.empty())
7767 const Expr *IfCond =
nullptr;
7769 IfCond =
C->getCondition();
7776 OMPLexicalScope
Scope(*
this, S, OMPD_task);
7777 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
7784 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
7812 llvm::Constant *
Addr;
7814 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7816 assert(Fn &&
Addr &&
"Target device function emission failed.");
7836 CGF, OMPD_target_parallel_for, S.
hasCancel());
7852 llvm::Constant *
Addr;
7854 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7856 assert(Fn &&
Addr &&
"Target device function emission failed.");
7891 llvm::Constant *
Addr;
7893 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7895 assert(Fn &&
Addr &&
"Target device function emission failed.");
7917 const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop);
7920 OMPLexicalScope
Scope(*
this, S, OMPD_taskloop,
false);
7925 const Expr *IfCond =
nullptr;
7926 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7927 if (
C->getNameModifier() == OMPD_unknown ||
7928 C->getNameModifier() == OMPD_taskloop) {
7929 IfCond =
C->getCondition();
7942 Data.Schedule.setInt(
false);
7945 (Clause->getModifier() == OMPC_GRAINSIZE_strict) ?
true :
false;
7948 Data.Schedule.setInt(
true);
7951 (Clause->getModifier() == OMPC_NUMTASKS_strict) ?
true :
false;
7965 llvm::BasicBlock *ContBlock =
nullptr;
7966 OMPLoopScope PreInitScope(CGF, S);
7967 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
7971 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock(
"taskloop.if.then");
7972 ContBlock = CGF.createBasicBlock(
"taskloop.if.end");
7973 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
7974 CGF.getProfileCount(&S));
7975 CGF.EmitBlock(ThenBlock);
7976 CGF.incrementProfileCounter(&S);
7979 (void)CGF.EmitOMPLinearClauseInit(S);
7983 enum { LowerBound = 5, UpperBound, Stride, LastIter };
7985 auto *LBP = std::next(I, LowerBound);
7986 auto *UBP = std::next(I, UpperBound);
7987 auto *STP = std::next(I, Stride);
7988 auto *LIP = std::next(I, LastIter);
7996 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
7997 CGF.EmitOMPLinearClause(S, LoopScope);
7998 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
8001 const Expr *IVExpr = S.getIterationVariable();
8003 CGF.EmitVarDecl(*IVDecl);
8004 CGF.EmitIgnoredExpr(S.getInit());
8009 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
8012 CGF.EmitIgnoredExpr(S.getCalcLastIteration());
8016 OMPLexicalScope
Scope(CGF, S, OMPD_taskloop,
false);
8026 [&S](CodeGenFunction &CGF) {
8027 emitOMPLoopBodyWithStopPoint(CGF, S,
8028 CodeGenFunction::JumpDest());
8030 [](CodeGenFunction &) {});
8035 CGF.EmitBranch(ContBlock);
8036 CGF.EmitBlock(ContBlock,
true);
8039 if (HasLastprivateClause) {
8040 CGF.EmitOMPLastprivateClauseFinal(
8042 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
8043 CGF.GetAddrOfLocalVar(*LIP),
false,
8044 (*LIP)->getType(), S.getBeginLoc())));
8047 CGF.EmitOMPLinearClauseFinal(S, [LIP, &S](CodeGenFunction &CGF) {
8048 return CGF.
Builder.CreateIsNotNull(
8050 (*LIP)->
getType(), S.getBeginLoc()));
8053 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
8054 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
8056 auto &&
CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
8058 OMPLoopScope PreInitScope(CGF, S);
8059 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S,
8060 OutlinedFn, SharedsTy,
8061 CapturedStruct, IfCond,
Data);
8063 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
8069 CGM.getOpenMPRuntime().emitTaskgroupRegion(
8071 [&S, &BodyGen, &TaskGen, &
Data](CodeGenFunction &CGF,
8091 OMPLexicalScope
Scope(*
this, S);
8103 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8104 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8115 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8116 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8127 OMPLexicalScope
Scope(*
this, S);
8128 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8139 OMPLexicalScope
Scope(*
this, S);
8140 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8146 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8151 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8152 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8164 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8169 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8170 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8182 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8187 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8188 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8200 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8205 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8206 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8220 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8224 const Expr *IfCond =
nullptr;
8226 IfCond =
C->getCondition();
8233 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8234 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8244 BindKind =
C->getBindKind();
8247 case OMPC_BIND_parallel:
8249 case OMPC_BIND_teams:
8251 case OMPC_BIND_thread:
8262 const auto *ForS = dyn_cast<ForStmt>(CS);
8273 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
8274 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_loop,
CodeGen);
8300 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
8305 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
8317 [](CodeGenFunction &) {
return nullptr; });
8322 std::string StatusMsg,
8326 StatusMsg +=
": DEVICE";
8328 StatusMsg +=
": HOST";
8335 llvm::dbgs() << StatusMsg <<
": " <<
FileName <<
": " << LineNo <<
"\n";
8358 CGF, OMPD_distribute, CodeGenDistribute,
false);
8387 CGF, OMPD_distribute, CodeGenDistribute,
false);
8420 llvm::Constant *
Addr;
8422 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8424 assert(Fn &&
Addr &&
8425 "Target device function emission failed for 'target teams loop'.");
8436 CGF, OMPD_target_parallel_loop,
false);
8452 llvm::Constant *
Addr;
8454 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8456 assert(Fn &&
Addr &&
"Target device function emission failed.");
8471 if (
const auto *SD = dyn_cast<OMPScanDirective>(&D)) {
8475 if (!D.hasAssociatedStmt() || !D.getAssociatedStmt())
8482 for (
const Expr *Ref :
C->varlist()) {
8486 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
8489 if (!CGF.LocalDeclMap.count(VD)) {
8501 if (
const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
8502 for (
const Expr *E : LD->counters()) {
8510 if (!CGF.LocalDeclMap.count(VD))
8515 if (!
C->getNumForLoops())
8517 for (
unsigned I = LD->getLoopsNumber(),
8518 E =
C->getLoopNumIterations().size();
8520 if (
const auto *VD = dyn_cast<OMPCapturedExprDecl>(
8523 if (!CGF.LocalDeclMap.count(VD))
8530 CGF.
EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
8533 if (D.getDirectiveKind() == OMPD_atomic ||
8534 D.getDirectiveKind() == OMPD_critical ||
8535 D.getDirectiveKind() == OMPD_section ||
8536 D.getDirectiveKind() == OMPD_master ||
8537 D.getDirectiveKind() == OMPD_masked ||
8538 D.getDirectiveKind() == OMPD_unroll ||
8539 D.getDirectiveKind() == OMPD_assume) {
8544 OMPSimdLexicalScope
Scope(*
this, D);
8545 CGM.getOpenMPRuntime().emitInlinedDirective(
8548 : D.getDirectiveKind(),
Defines the clang::ASTContext interface.
static bool isAllocatableDecl(const VarDecl *VD)
static const VarDecl * getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE)
static void emitTargetRegion(CodeGenFunction &CGF, const OMPTargetDirective &S, PrePostActionTy &Action)
static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S, PrePostActionTy &Action)
static const VarDecl * getBaseDecl(const Expr *Ref)
static void emitTargetTeamsGenericLoopRegionAsParallel(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsGenericLoopDirective &S)
static void emitOMPAtomicReadExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, const Expr *X, const Expr *V, SourceLocation Loc)
static void emitOMPAtomicCaptureExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, bool IsPostfixUpdate, const Expr *V, const Expr *X, const Expr *E, const Expr *UE, bool IsXLHSInRHSPart, SourceLocation Loc)
static void emitScanBasedDirective(CodeGenFunction &CGF, const OMPLoopDirective &S, llvm::function_ref< llvm::Value *(CodeGenFunction &)> NumIteratorsGen, llvm::function_ref< void(CodeGenFunction &)> FirstGen, llvm::function_ref< void(CodeGenFunction &)> SecondGen)
Emits the code for the directive with inscan reductions.
static void emitSimpleAtomicStore(CodeGenFunction &CGF, llvm::AtomicOrdering AO, LValue LVal, RValue RVal)
static bool isSupportedByOpenMPIRBuilder(const OMPTaskgroupDirective &T)
static Address castValueFromUintptr(CodeGenFunction &CGF, SourceLocation Loc, QualType DstType, StringRef Name, LValue AddrLV)
static void emitDistributeParallelForDistributeInnerBoundParams(CodeGenFunction &CGF, const OMPExecutableDirective &S, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars)
static void emitScanBasedDirectiveFinals(CodeGenFunction &CGF, const OMPLoopDirective &S, llvm::function_ref< llvm::Value *(CodeGenFunction &)> NumIteratorsGen)
Copies final inscan reductions values to the original variables.
static void checkForLastprivateConditionalUpdate(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static std::pair< LValue, LValue > emitForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S)
The following two functions generate expressions for the loop lower and upper bounds in case of stati...
static void emitTargetParallelForRegion(CodeGenFunction &CGF, const OMPTargetParallelForDirective &S, PrePostActionTy &Action)
static LValue EmitOMPHelperVar(CodeGenFunction &CGF, const DeclRefExpr *Helper)
Emit a helper variable and return corresponding lvalue.
static void emitOMPAtomicUpdateExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, const Expr *X, const Expr *E, const Expr *UE, bool IsXLHSInRHSPart, SourceLocation Loc)
static llvm::Value * convertToScalarValue(CodeGenFunction &CGF, RValue Val, QualType SrcType, QualType DestType, SourceLocation Loc)
static llvm::Function * emitOutlinedOrderedFunction(CodeGenModule &CGM, const CapturedStmt *S, const OMPExecutableDirective &D)
static void emitPreCond(CodeGenFunction &CGF, const OMPLoopDirective &S, const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount)
static std::pair< bool, RValue > emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X, RValue Update, BinaryOperatorKind BO, llvm::AtomicOrdering AO, bool IsXLHSInRHSPart)
static std::pair< LValue, LValue > emitDistributeParallelForInnerBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitTargetTeamsGenericLoopRegionAsDistribute(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsGenericLoopDirective &S)
static void emitTargetParallelRegion(CodeGenFunction &CGF, const OMPTargetParallelDirective &S, PrePostActionTy &Action)
static std::pair< llvm::Value *, llvm::Value * > emitDispatchForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S, Address LB, Address UB)
When dealing with dispatch schedules (e.g.
static void emitMaster(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitRestoreIP(CodeGenFunction &CGF, const T *C, llvm::OpenMPIRBuilder::InsertPointTy AllocaIP, llvm::OpenMPIRBuilder &OMPBuilder)
static void emitCommonOMPTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, const RegionCodeGenTy &CodeGen)
static void emitSimdlenSafelenClause(CodeGenFunction &CGF, const OMPExecutableDirective &D)
static void emitAlignedClause(CodeGenFunction &CGF, const OMPExecutableDirective &D)
static bool isSimdSupportedByOpenMPIRBuilder(const OMPLoopDirective &S)
static void emitCommonOMPParallelDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, const CodeGenBoundParametersTy &CodeGenBoundParameters)
static void applyConservativeSimdOrderedDirective(const Stmt &AssociatedStmt, LoopInfoStack &LoopStack)
static bool emitWorksharingDirective(CodeGenFunction &CGF, const OMPLoopDirective &S, bool HasCancel)
static void emitPostUpdateForReductionClause(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
static void emitEmptyOrdered(CodeGenFunction &, SourceLocation Loc, const unsigned IVSize, const bool IVSigned)
static void emitTargetTeamsLoopCodegenStatus(CodeGenFunction &CGF, std::string StatusMsg, const OMPExecutableDirective &D)
static bool isForSupportedByOpenMPIRBuilder(const OMPLoopDirective &S, bool HasCancel)
static RValue emitSimpleAtomicLoad(CodeGenFunction &CGF, llvm::AtomicOrdering AO, LValue LVal, SourceLocation Loc)
static std::pair< llvm::Value *, llvm::Value * > emitDistributeParallelForDispatchBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S, Address LB, Address UB)
if the 'for' loop has a dispatch schedule (e.g.
static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO, bool IsPostfixUpdate, const Expr *X, const Expr *V, const Expr *R, const Expr *E, const Expr *UE, const Expr *D, const Expr *CE, bool IsXLHSInRHSPart, bool IsFailOnly, SourceLocation Loc)
static CodeGenFunction::ComplexPairTy convertToComplexValue(CodeGenFunction &CGF, RValue Val, QualType SrcType, QualType DestType, SourceLocation Loc)
static ImplicitParamDecl * createImplicitFirstprivateForType(ASTContext &C, OMPTaskDataTy &Data, QualType Ty, CapturedDecl *CD, SourceLocation Loc)
static EmittedClosureTy emitCapturedStmtFunc(CodeGenFunction &ParentCGF, const CapturedStmt *S)
Emit a captured statement and return the function as well as its captured closure context.
static void emitOMPLoopBodyWithStopPoint(CodeGenFunction &CGF, const OMPLoopDirective &S, CodeGenFunction::JumpDest LoopExit)
static void emitOMPDistributeDirective(const OMPLoopDirective &S, CodeGenFunction &CGF, CodeGenModule &CGM)
static void emitOMPCopyinClause(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitTargetTeamsDistributeParallelForRegion(CodeGenFunction &CGF, const OMPTargetTeamsDistributeParallelForDirective &S, PrePostActionTy &Action)
static bool hasOrderedDirective(const Stmt *S)
static llvm::CallInst * emitCapturedStmtCall(CodeGenFunction &ParentCGF, EmittedClosureTy Cap, llvm::ArrayRef< llvm::Value * > Args)
Emit a call to a previously captured closure.
static void emitMasked(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitBody(CodeGenFunction &CGF, const Stmt *S, const Stmt *NextLoop, int MaxLevel, int Level=0)
static void emitOMPForDirective(const OMPLoopDirective &S, CodeGenFunction &CGF, CodeGenModule &CGM, bool HasCancel)
static void emitEmptyBoundParameters(CodeGenFunction &, const OMPExecutableDirective &, llvm::SmallVectorImpl< llvm::Value * > &)
static void emitTargetParallelForSimdRegion(CodeGenFunction &CGF, const OMPTargetParallelForSimdDirective &S, PrePostActionTy &Action)
static void emitOMPSimdDirective(const OMPLoopDirective &S, CodeGenFunction &CGF, CodeGenModule &CGM)
static void emitOMPAtomicCompareExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO, const Expr *X, const Expr *V, const Expr *R, const Expr *E, const Expr *D, const Expr *CE, bool IsXBinopExpr, bool IsPostfixUpdate, bool IsFailOnly, SourceLocation Loc)
std::pair< llvm::Function *, llvm::Value * > EmittedClosureTy
static OpenMPDirectiveKind getEffectiveDirectiveKind(const OMPExecutableDirective &S)
static void emitTargetTeamsRegion(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsDirective &S)
static void buildDependences(const OMPExecutableDirective &S, OMPTaskDataTy &Data)
static RValue convertToType(CodeGenFunction &CGF, RValue Value, QualType SourceType, QualType ResType, SourceLocation Loc)
static void emitScanBasedDirectiveDecls(CodeGenFunction &CGF, const OMPLoopDirective &S, llvm::function_ref< llvm::Value *(CodeGenFunction &)> NumIteratorsGen)
Emits internal temp array declarations for the directive with inscan reductions.
static void emitTargetTeamsDistributeParallelForSimdRegion(CodeGenFunction &CGF, const OMPTargetTeamsDistributeParallelForSimdDirective &S, PrePostActionTy &Action)
static void emitTargetTeamsDistributeSimdRegion(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsDistributeSimdDirective &S)
static llvm::MapVector< llvm::Value *, llvm::Value * > GetAlignedMapping(const OMPLoopDirective &S, CodeGenFunction &CGF)
static llvm::omp::ScheduleKind convertClauseKindToSchedKind(OpenMPScheduleClauseKind ScheduleClauseKind)
static void mapParam(CodeGenFunction &CGF, const DeclRefExpr *Helper, const ImplicitParamDecl *PVD, CodeGenFunction::OMPPrivateScope &Privates)
Emit a helper variable and return corresponding lvalue.
static void emitCommonOMPTeamsDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
static void emitTargetParallelGenericLoopRegion(CodeGenFunction &CGF, const OMPTargetParallelGenericLoopDirective &S, PrePostActionTy &Action)
static QualType getCanonicalParamType(ASTContext &C, QualType T)
static void emitCommonSimdLoop(CodeGenFunction &CGF, const OMPLoopDirective &S, const RegionCodeGenTy &SimdInitGen, const RegionCodeGenTy &BodyCodeGen)
static LValue createSectionLVal(CodeGenFunction &CGF, QualType Ty, const Twine &Name, llvm::Value *Init=nullptr)
static void emitOMPAtomicWriteExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, const Expr *X, const Expr *E, SourceLocation Loc)
static llvm::Function * emitOutlinedFunctionPrologue(CodeGenFunction &CGF, FunctionArgList &Args, llvm::MapVector< const Decl *, std::pair< const VarDecl *, Address > > &LocalAddrs, llvm::DenseMap< const Decl *, std::pair< const Expr *, llvm::Value * > > &VLASizes, llvm::Value *&CXXThisValue, const FunctionOptions &FO)
static void emitInnerParallelForWhenCombined(CodeGenFunction &CGF, const OMPLoopDirective &S, CodeGenFunction::JumpDest LoopExit)
static void emitTargetTeamsDistributeRegion(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsDistributeDirective &S)
This file defines OpenMP nodes for declarative directives.
static const Decl * getCanonicalDecl(const Decl *D)
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
Defines the PrettyStackTraceEntry class, which is used to make crashes give more contextual informati...
Defines the SourceManager interface.
This file defines OpenMP AST classes for executable directives and clauses.
This represents 'pragma omp cancel' directive.
OpenMPDirectiveKind getCancelRegion() const
Get cancellation region for the current cancellation point.
This represents 'pragma omp cancellation point' directive.
OpenMPDirectiveKind getCancelRegion() const
Get cancellation region for the current cancellation point.
This represents 'pragma omp distribute' directive.
This represents 'pragma omp distribute parallel for' composite directive.
This represents 'pragma omp distribute parallel for simd' composite directive.
This represents 'pragma omp distribute simd' composite directive.
This represents 'pragma omp error' directive.
This represents 'pragma omp loop' directive.
Represents the 'pragma omp interchange' loop transformation directive.
Stmt * getTransformedStmt() const
Gets the associated loops after the transformation.
This represents 'pragma omp interop' directive.
This represents 'pragma omp masked' directive.
This represents 'pragma omp masked taskloop' directive.
This represents 'pragma omp masked taskloop simd' directive.
This represents 'pragma omp master taskloop' directive.
This represents 'pragma omp master taskloop simd' directive.
This represents 'pragma omp parallel masked taskloop' directive.
This represents 'pragma omp parallel masked taskloop simd' directive.
This represents 'pragma omp parallel master taskloop' directive.
This represents 'pragma omp parallel master taskloop simd' directive.
Represents the 'pragma omp reverse' loop transformation directive.
Stmt * getTransformedStmt() const
Gets/sets the associated loops after the transformation, i.e.
This represents 'pragma omp scan' directive.
This represents the 'pragma omp stripe' loop transformation directive.
Stmt * getTransformedStmt() const
Gets/sets the associated loops after striping.
This represents 'pragma omp target data' directive.
This represents 'pragma omp target' directive.
This represents 'pragma omp target enter data' directive.
This represents 'pragma omp target exit data' directive.
This represents 'pragma omp target parallel' directive.
This represents 'pragma omp target parallel for' directive.
bool hasCancel() const
Return true if current directive has inner cancel directive.
This represents 'pragma omp target parallel for simd' directive.
This represents 'pragma omp target parallel loop' directive.
This represents 'pragma omp target simd' directive.
This represents 'pragma omp target teams' directive.
This represents 'pragma omp target teams distribute' combined directive.
This represents 'pragma omp target teams distribute parallel for' combined directive.
This represents 'pragma omp target teams distribute parallel for simd' combined directive.
This represents 'pragma omp target teams distribute simd' combined directive.
This represents 'pragma omp target teams loop' directive.
bool canBeParallelFor() const
Return true if current loop directive's associated loop can be a parallel for.
This represents 'pragma omp target update' directive.
This represents 'pragma omp taskloop' directive.
This represents 'pragma omp taskloop simd' directive.
This represents 'pragma omp teams' directive.
This represents 'pragma omp teams distribute' directive.
This represents 'pragma omp teams distribute parallel for' composite directive.
This represents 'pragma omp teams distribute parallel for simd' composite directive.
This represents 'pragma omp teams distribute simd' combined directive.
This represents 'pragma omp teams loop' directive.
This represents the 'pragma omp tile' loop transformation directive.
Stmt * getTransformedStmt() const
Gets/sets the associated loops after tiling.
This represents the 'pragma omp unroll' loop transformation directive.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
TranslationUnitDecl * getTranslationUnitDecl() const
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
QualType getUIntPtrType() const
Return a type compatible with "uintptr_t" (C99 7.18.1.4), as defined by the target.
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
unsigned getOpenMPDefaultSimdAlign(QualType T) const
Get default simd alignment of the specified complete type in bits.
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
CanQualType getCanonicalTagType(const TagDecl *TD) const
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Represents an attribute applied to a statement.
ArrayRef< const Attr * > getAttrs() const
static BinaryOperator * Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, FPOptionsOverride FPFeatures)
Represents the body of a CapturedStmt, and serves as its DeclContext.
unsigned getContextParamPosition() const
static CapturedDecl * Create(ASTContext &C, DeclContext *DC, unsigned NumParams)
param_iterator param_end() const
Retrieve an iterator one past the last parameter decl.
param_iterator param_begin() const
Retrieve an iterator pointing to the first parameter decl.
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
ImplicitParamDecl * getParam(unsigned i) const
This captures a statement into a function.
SourceLocation getEndLoc() const LLVM_READONLY
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
const RecordDecl * getCapturedRecordDecl() const
Retrieve the record declaration for captured variables.
Stmt * getCapturedStmt()
Retrieve the statement being captured.
capture_init_iterator capture_init_begin()
Retrieve the first initialization argument.
SourceLocation getBeginLoc() const LLVM_READONLY
capture_init_iterator capture_init_end()
Retrieve the iterator pointing one past the last initialization argument.
Expr *const * const_capture_init_iterator
Const iterator that walks over the capture initialization arguments.
CharUnits - This is an opaque type for sizes expressed in character units.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
CharUnits getAlignment() const
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
Address withAlignment(CharUnits NewAlignment) const
Return address with different alignment, but same pointer and element type.
llvm::PointerType * getType() const
Return the type of the pointer value.
static AggValueSlot ignored()
ignored - Returns an aggregate value slot indicating that the aggregate value is being ignored.
static ApplyDebugLocation CreateDefaultArtificial(CodeGenFunction &CGF, SourceLocation TemporaryLocation)
Apply TemporaryLocation if it is valid.
Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
CGFunctionInfo - Class to encapsulate the information about a function definition.
Manages list of lastprivate conditional decls for the specified directive.
static LastprivateConditionalRAII disable(CodeGenFunction &CGF, const OMPExecutableDirective &S)
Manages list of nontemporal decls for the specified directive.
Struct that keeps all the relevant information that should be kept throughout a 'target data' region.
llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap
Map between the a declaration of a capture and the corresponding new llvm address where the runtime r...
Manages list of nontemporal decls for the specified directive.
virtual void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the task directive.
virtual llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST)
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
virtual void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr)
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
virtual void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, SourceLocation SeverityLoc=SourceLocation(), const Expr *Message=nullptr, SourceLocation MessageLoc=SourceLocation())
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_tid, kmp_int32 num_threads) ...
virtual Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal)
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
virtual void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc)
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
virtual void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars)
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
virtual const VarDecl * translateParameter(const FieldDecl *FD, const VarDecl *NativeParam) const
Translates the native parameter of outlined function if this is required for target.
virtual llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP teams directive D.
virtual void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef< Expr * > NumIterations)
Emit initialization for doacross loop nesting support.
virtual void adjustTargetSpecificDataForLambdas(CodeGenFunction &CGF, const OMPExecutableDirective &D) const
Adjust some parameters for the target-based directives, like addresses of the variables captured by r...
virtual Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const
Gets the address of the native argument basing on the address of the target-specific parameter.
virtual void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc)
Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32global_tid, kmp_int32 num_teams,...
virtual llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data)
Emit a code for initialization of task reduction clause.
virtual void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO)
Emit flush of the variables specified in 'omp flush' directive.
virtual void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc)
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32global_tid, int proc_bind) to generate...
virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false)
Emit an implicit/explicit barrier for OpenMP threads.
virtual void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values)
virtual void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind)
Call the appropriate runtime routine to notify that we finished all the work with current loop.
void emitIfClause(CodeGenFunction &CGF, const Expr *Cond, const RegionCodeGenTy &ThenGen, const RegionCodeGenTy &ElseGen)
Emits code for OpenMP 'if' clause using specified CodeGen function.
virtual llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP parallel directive D.
virtual void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values)
Call the appropriate runtime routine to initialize it before start of loop.
virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static non-chunked.
virtual void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc)
Emits a master region.
virtual void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Required to resolve existing problems in the runtime.
virtual void checkAndEmitLastprivateConditional(CodeGenFunction &CGF, const Expr *LHS)
Checks if the provided LVal is lastprivate conditional and emits the code to update the value of the ...
llvm::OpenMPIRBuilder & getOMPBuilder()
virtual void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Emit outilined function for 'target' directive.
virtual void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned)
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
virtual void checkAndEmitSharedLastprivateConditional(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::DenseSet< CanonicalDeclPtr< const VarDecl > > &IgnoredDecls)
Checks if the lastprivate conditional was updated in inner region and writes the value.
virtual void emitInlinedDirective(CodeGenFunction &CGF, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool HasCancel=false)
Emit code for the directive that does not require outlining.
virtual bool isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static chunked.
virtual void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Emit the target offloading code associated with D.
virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const
Check if the specified ScheduleKind is dynamic.
virtual void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr)
Emits a masked region.
virtual void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues)
Call the appropriate runtime routine to initialize it before start of loop.
Address getAllocatedAddress() const
Returns the raw, allocated address, which is not necessarily the address of the object itself.
API for captured statement code generation.
virtual const FieldDecl * lookup(const VarDecl *VD) const
Lookup the captured field decl for a variable.
RAII for correct setting/restoring of CapturedStmtInfo.
LValue getReferenceLValue(CodeGenFunction &CGF, const Expr *RefExpr) const
void ForceCleanup()
Force the emission of cleanups now, instead of waiting until this object is destroyed.
RAII for preserving necessary info during inlined region body codegen.
Cleanup action for allocate support.
RAII for preserving necessary info during Outlined region body codegen.
Controls insertion of cancellation exit blocks in worksharing constructs.
Save/restore original map of previously emitted local vars in case when we need to duplicate emission...
The class used to assign some variables some temporarily addresses.
bool apply(CodeGenFunction &CGF)
Applies new addresses to the list of the variables.
void restore(CodeGenFunction &CGF)
Restores original addresses of the variables.
bool setVarAddr(CodeGenFunction &CGF, const VarDecl *LocalVD, Address TempAddr)
Sets the address of the variable LocalVD to be TempAddr in function CGF.
The scope used to remap some variables as private in the OpenMP loop body (or other captured region e...
void restoreMap()
Restore all mapped variables w/o clean up.
bool Privatize()
Privatizes local variables previously registered as private.
bool addPrivate(const VarDecl *LocalVD, Address Addr)
Registers LocalVD variable as a private with Addr as the address of the corresponding private variabl...
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
Manages parent directive for scan directives.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
void ForceCleanup(std::initializer_list< llvm::Value ** > ValuesToReload={})
Force the emission of cleanups now, instead of waiting until this object is destroyed.
bool requiresCleanups() const
Determine whether this scope requires any cleanups.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void EmitOMPParallelMaskedTaskLoopDirective(const OMPParallelMaskedTaskLoopDirective &S)
void EmitOMPParallelMaskedDirective(const OMPParallelMaskedDirective &S)
void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S)
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr, const VarDecl *ConditionalDecl=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
void EmitOMPLastprivateClauseFinal(const OMPExecutableDirective &D, bool NoFinals, llvm::Value *IsLastIterCond=nullptr)
Emit final copying of lastprivate values to original variables at the end of the worksharing or simd ...
void processInReduction(const OMPExecutableDirective &S, OMPTaskDataTy &Data, CodeGenFunction &CGF, const CapturedStmt *CS, OMPPrivateScope &Scope)
JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target)
The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...
void EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S)
void emitOMPSimpleStore(LValue LVal, RValue RVal, QualType RValTy, SourceLocation Loc)
static void EmitOMPTargetParallelDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelDirective &S)
void EmitOMPCanonicalLoop(const OMPCanonicalLoop *S)
Emit an OMPCanonicalLoop using the OpenMPIRBuilder.
void EmitOMPGenericLoopDirective(const OMPGenericLoopDirective &S)
void EmitOMPScanDirective(const OMPScanDirective &S)
static bool hasScalarEvaluationKind(QualType T)
llvm::function_ref< std::pair< llvm::Value *, llvm::Value * >(CodeGenFunction &, const OMPExecutableDirective &S, Address LB, Address UB)> CodeGenDispatchBoundsTy
LValue InitCapturedStruct(const CapturedStmt &S)
CGCapturedStmtInfo * CapturedStmtInfo
void EmitOMPDistributeDirective(const OMPDistributeDirective &S)
void EmitOMPParallelForDirective(const OMPParallelForDirective &S)
void EmitOMPMasterDirective(const OMPMasterDirective &S)
void EmitOMPParallelMasterTaskLoopSimdDirective(const OMPParallelMasterTaskLoopSimdDirective &S)
void EmitOMPSimdInit(const OMPLoopDirective &D)
Helpers for the OpenMP loop directives.
const OMPExecutableDirective * OMPParentLoopDirectiveForScan
Parent loop-based directive for scan directive.
void EmitOMPFlushDirective(const OMPFlushDirective &S)
static void EmitOMPTargetDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetDirective &S)
Emit device code for the target directive.
bool EmitOMPFirstprivateClause(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
void EmitOMPTaskgroupDirective(const OMPTaskgroupDirective &S)
void EmitOMPTargetTeamsDistributeParallelForSimdDirective(const OMPTargetTeamsDistributeParallelForSimdDirective &S)
static void EmitOMPTargetTeamsDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDirective &S)
Emit device code for the target teams directive.
void EmitOMPReductionClauseInit(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope, bool ForInscan=false)
Emit initial code for reduction variables.
void EmitOMPDistributeSimdDirective(const OMPDistributeSimdDirective &S)
void EmitAutoVarDecl(const VarDecl &D)
EmitAutoVarDecl - Emit an auto variable declaration.
static void EmitOMPTargetTeamsDistributeDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeDirective &S)
Emit device code for the target teams distribute directive.
void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
void EmitOMPTargetParallelForDirective(const OMPTargetParallelForDirective &S)
const LangOptions & getLangOpts() const
LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
EmitAutoVarAlloca - Emit the alloca and debug information for a local variable.
void EmitAtomicUpdate(LValue LVal, llvm::AtomicOrdering AO, const llvm::function_ref< RValue(RValue)> &UpdateOp, bool IsVolatile)
Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr)
Load a pointer with type PtrTy stored at address Ptr.
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
void EmitOMPReductionClauseFinal(const OMPExecutableDirective &D, const OpenMPDirectiveKind ReductionKind)
Emit final update of reduction values to original variables at the end of the directive.
void EmitOMPLoopBody(const OMPLoopDirective &D, JumpDest LoopExit)
Helper for the OpenMP loop directives.
void EmitOMPScopeDirective(const OMPScopeDirective &S)
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
llvm::AssertingVH< llvm::Instruction > AllocaInsertPt
AllocaInsertPoint - This is an instruction in the entry block before which we prefer to insert alloca...
void EmitAggregateAssign(LValue Dest, LValue Src, QualType EltTy)
Emit an aggregate assignment.
CodeGenFunction * ParentCGF
JumpDest ReturnBlock
ReturnBlock - Unified return block.
void EmitOMPTargetTeamsDistributeSimdDirective(const OMPTargetTeamsDistributeSimdDirective &S)
const llvm::function_ref< void(CodeGenFunction &, llvm::Function *, const OMPTaskDataTy &)> TaskGenTy
llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Location)
Converts Location to a DebugLoc, if debug information is enabled.
bool EmitOMPCopyinClause(const OMPExecutableDirective &D)
Emit code for copyin clause in D directive.
void EmitOMPLinearClause(const OMPLoopDirective &D, CodeGenFunction::OMPPrivateScope &PrivateScope)
Emit initial code for linear clauses.
llvm::BasicBlock * OMPBeforeScanBlock
void EmitOMPInterchangeDirective(const OMPInterchangeDirective &S)
void EmitOMPPrivateLoopCounters(const OMPLoopDirective &S, OMPPrivateScope &LoopScope)
Emit initial code for loop counters of loop-based directives.
void GenerateOpenMPCapturedVars(const CapturedStmt &S, SmallVectorImpl< llvm::Value * > &CapturedVars)
void EmitOMPDepobjDirective(const OMPDepobjDirective &S)
void EmitOMPMetaDirective(const OMPMetaDirective &S)
void EmitOMPCriticalDirective(const OMPCriticalDirective &S)
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
void EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S)
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
void EmitOMPCancelDirective(const OMPCancelDirective &S)
void EmitOMPBarrierDirective(const OMPBarrierDirective &S)
llvm::Value * EmitComplexToScalarConversion(ComplexPairTy Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified complex type to the specified destination type,...
void EmitOMPOrderedDirective(const OMPOrderedDirective &S)
bool EmitOMPWorksharingLoop(const OMPLoopDirective &S, Expr *EUB, const CodeGenLoopBoundsTy &CodeGenLoopBounds, const CodeGenDispatchBoundsTy &CGDispatchBounds)
Emit code for the worksharing loop-based directive.
LValue EmitOMPSharedLValue(const Expr *E)
Emits the lvalue for the expression with possibly captured variable.
llvm::CanonicalLoopInfo * EmitOMPCollapsedCanonicalLoopNest(const Stmt *S, int Depth)
Emit the Stmt S and return its topmost canonical loop, if any.
void EmitOMPSectionsDirective(const OMPSectionsDirective &S)
void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())
Emit code for the start of a function.
void EmitOMPInteropDirective(const OMPInteropDirective &S)
void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S)
void EmitOMPTargetParallelDirective(const OMPTargetParallelDirective &S)
void EmitOMPCopy(QualType OriginalType, Address DestAddr, Address SrcAddr, const VarDecl *DestVD, const VarDecl *SrcVD, const Expr *Copy)
Emit proper copying of data from one variable to another.
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
JumpDest getOMPCancelDestination(OpenMPDirectiveKind Kind)
void EmitOMPTargetParallelForSimdDirective(const OMPTargetParallelForSimdDirective &S)
void EmitOMPTargetParallelGenericLoopDirective(const OMPTargetParallelGenericLoopDirective &S)
Emit combined directive 'target parallel loop' as if its constituent constructs are 'target',...
void EmitOMPUseDeviceAddrClause(const OMPUseDeviceAddrClause &C, OMPPrivateScope &PrivateScope, const llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap)
void EmitOMPTeamsDistributeParallelForSimdDirective(const OMPTeamsDistributeParallelForSimdDirective &S)
void EmitOMPMaskedDirective(const OMPMaskedDirective &S)
llvm::Value * emitArrayLength(const ArrayType *arrayType, QualType &baseType, Address &addr)
emitArrayLength - Compute the length of an array, even if it's a VLA, and drill down to the base elem...
void EmitOMPAggregateAssign(Address DestAddr, Address SrcAddr, QualType OriginalType, const llvm::function_ref< void(Address, Address)> CopyGen)
Perform element by element copying of arrays with type OriginalType from SrcAddr to DestAddr using co...
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
void EmitOMPTeamsDistributeSimdDirective(const OMPTeamsDistributeSimdDirective &S)
RValue EmitAtomicLoad(LValue LV, SourceLocation SL, AggValueSlot Slot=AggValueSlot::ignored())
CGDebugInfo * getDebugInfo()
void EmitOMPDistributeLoop(const OMPLoopDirective &S, const CodeGenLoopTy &CodeGenLoop, Expr *IncExpr)
Emit code for the distribute loop-based directive.
void EmitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective &S)
void EmitOMPReverseDirective(const OMPReverseDirective &S)
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
void EmitOMPCancellationPointDirective(const OMPCancellationPointDirective &S)
void EmitOMPTargetTeamsDistributeParallelForDirective(const OMPTargetTeamsDistributeParallelForDirective &S)
void EmitOMPMaskedTaskLoopDirective(const OMPMaskedTaskLoopDirective &S)
llvm::BasicBlock * OMPScanDispatch
llvm::function_ref< std::pair< LValue, LValue >(CodeGenFunction &, const OMPExecutableDirective &S)> CodeGenLoopBoundsTy
void EmitOMPTargetExitDataDirective(const OMPTargetExitDataDirective &S)
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
void EmitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &S)
void EmitOMPMaskedTaskLoopSimdDirective(const OMPMaskedTaskLoopSimdDirective &S)
std::pair< bool, RValue > EmitOMPAtomicSimpleUpdateExpr(LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart, llvm::AtomicOrdering AO, SourceLocation Loc, const llvm::function_ref< RValue(RValue)> CommonGen)
Emit atomic update code for constructs: X = X BO E or X = E BO E.
VlaSizePair getVLASize(const VariableArrayType *vla)
Returns an LLVM value that corresponds to the size, in non-variably-sized elements,...
void EmitOMPParallelDirective(const OMPParallelDirective &S)
void EmitOMPTaskDirective(const OMPTaskDirective &S)
void EmitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective &S)
void EmitOMPDistributeParallelForDirective(const OMPDistributeParallelForDirective &S)
void EmitOMPAssumeDirective(const OMPAssumeDirective &S)
int ExpectedOMPLoopDepth
Number of nested loop to be consumed by the last surrounding loop-associated directive.
void EmitOMPPrivateClause(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
void EmitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &S)
ASTContext & getContext() const
void EmitStopPoint(const Stmt *S)
EmitStopPoint - Emit a debug stoppoint if we are emitting debug info.
void EmitOMPTargetUpdateDirective(const OMPTargetUpdateDirective &S)
llvm::Value * EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, AlignmentSource Source=AlignmentSource::Type, bool isNontemporal=false)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
void EmitOMPTargetTeamsGenericLoopDirective(const OMPTargetTeamsGenericLoopDirective &S)
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
void EmitAutoVarCleanups(const AutoVarEmission &emission)
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
SmallVector< llvm::CanonicalLoopInfo *, 4 > OMPLoopNestStack
List of recently emitted OMPCanonicalLoops.
void EmitOMPTeamsDistributeParallelForDirective(const OMPTeamsDistributeParallelForDirective &S)
llvm::AtomicRMWInst * emitAtomicRMWInst(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val, llvm::AtomicOrdering Order=llvm::AtomicOrdering::SequentiallyConsistent, llvm::SyncScope::ID SSID=llvm::SyncScope::System, const AtomicExpr *AE=nullptr)
Emit an atomicrmw instruction, and applying relevant metadata when applicable.
void EmitOMPTargetTeamsDistributeDirective(const OMPTargetTeamsDistributeDirective &S)
void EmitOMPUseDevicePtrClause(const OMPUseDevicePtrClause &C, OMPPrivateScope &PrivateScope, const llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap)
RValue EmitAnyExpr(const Expr *E, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
EmitAnyExpr - Emit code to compute the specified expression which can have any type.
void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs={})
EmitStmt - Emit the code for the statement.
llvm::DenseMap< const ValueDecl *, FieldDecl * > LambdaCaptureFields
void EmitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &S)
llvm::Type * ConvertTypeForMem(QualType T)
void EmitOMPInnerLoop(const OMPExecutableDirective &S, bool RequiresCleanup, const Expr *LoopCond, const Expr *IncExpr, const llvm::function_ref< void(CodeGenFunction &)> BodyGen, const llvm::function_ref< void(CodeGenFunction &)> PostIncGen)
Emit inner loop of the worksharing/simd construct.
void EmitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective &S)
static void EmitOMPTargetTeamsDistributeParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForDirective &S)
void EmitOMPTargetDirective(const OMPTargetDirective &S)
static void EmitOMPTargetParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForSimdDirective &S)
Emit device code for the target parallel for simd directive.
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
llvm::BasicBlock * OMPScanExitBlock
void EmitOMPTeamsDirective(const OMPTeamsDirective &S)
void EmitSimpleOMPExecutableDirective(const OMPExecutableDirective &D)
Emit simple code for OpenMP directives in Simd-only mode.
void EmitOMPErrorDirective(const OMPErrorDirective &S)
void EmitOMPTargetTaskBasedDirective(const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen, OMPTargetDataInfo &InputInfo)
void EmitOMPParallelMaskedTaskLoopSimdDirective(const OMPParallelMaskedTaskLoopSimdDirective &S)
void EmitOMPTargetTeamsDirective(const OMPTargetTeamsDirective &S)
void EmitOMPTargetDataDirective(const OMPTargetDataDirective &S)
Address GenerateCapturedStmtArgument(const CapturedStmt &S)
bool EmitOMPLastprivateClauseInit(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
Emit initial code for lastprivate variables.
static void EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForSimdDirective &S)
Emit device code for the target teams distribute parallel for simd directive.
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
llvm::Function * GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S, const OMPExecutableDirective &D)
void EmitOMPSimdDirective(const OMPSimdDirective &S)
RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
Address EmitLoadOfReference(LValue RefLVal, LValueBaseInfo *PointeeBaseInfo=nullptr, TBAAAccessInfo *PointeeTBAAInfo=nullptr)
void EmitOMPParallelGenericLoopDirective(const OMPLoopDirective &S)
void EmitOMPTargetSimdDirective(const OMPTargetSimdDirective &S)
void EmitOMPTeamsGenericLoopDirective(const OMPTeamsGenericLoopDirective &S)
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
bool EmitOMPLinearClauseInit(const OMPLoopDirective &D)
Emit initial code for linear variables.
static void EmitOMPTargetParallelGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelGenericLoopDirective &S)
Emit device code for the target parallel loop directive.
void EmitOMPUnrollDirective(const OMPUnrollDirective &S)
void EmitOMPStripeDirective(const OMPStripeDirective &S)
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitOMPSingleDirective(const OMPSingleDirective &S)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
llvm::function_ref< void(CodeGenFunction &, SourceLocation, const unsigned, const bool)> CodeGenOrderedTy
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
llvm::Value * EmitFromMemory(llvm::Value *Value, QualType Ty)
EmitFromMemory - Change a scalar value from its memory representation to its value representation.
static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S)
Emit device code for the target simd directive.
llvm::Function * GenerateCapturedStmtFunction(const CapturedStmt &S)
Creates the outlined function for a CapturedStmt.
static void EmitOMPTargetParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForDirective &S)
Emit device code for the target parallel for directive.
uint64_t getProfileCount(const Stmt *S)
Get the profiler's count for the given statement.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)
ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant,...
static void EmitOMPTargetTeamsGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsGenericLoopDirective &S)
Emit device code for the target teams loop directive.
void EmitOMPTileDirective(const OMPTileDirective &S)
void EmitDecl(const Decl &D, bool EvaluateConditionDecl=false)
EmitDecl - Emit a declaration.
void EmitOMPAtomicDirective(const OMPAtomicDirective &S)
llvm::BasicBlock * OMPAfterScanBlock
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
ConstantEmission tryEmitAsConstant(const DeclRefExpr *RefExpr)
Try to emit a reference to the given value without producing it as an l-value.
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
void EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst)
Store of global named registers are always calls to intrinsics.
void EmitOMPParallelMasterTaskLoopDirective(const OMPParallelMasterTaskLoopDirective &S)
void EmitOMPDistributeParallelForSimdDirective(const OMPDistributeParallelForSimdDirective &S)
void EmitOMPSectionDirective(const OMPSectionDirective &S)
void EnsureInsertPoint()
EnsureInsertPoint - Ensure that an insertion point is defined so that emitted IR has a place to go.
void EmitOMPForSimdDirective(const OMPForSimdDirective &S)
llvm::LLVMContext & getLLVMContext()
void emitAlignmentAssumption(llvm::Value *PtrValue, QualType Ty, SourceLocation Loc, SourceLocation AssumptionLoc, llvm::Value *Alignment, llvm::Value *OffsetValue=nullptr)
static void EmitOMPTargetTeamsDistributeSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeSimdDirective &S)
Emit device code for the target teams distribute simd directive.
llvm::function_ref< void(CodeGenFunction &, const OMPLoopDirective &, JumpDest)> CodeGenLoopTy
llvm::Value * EmitScalarConversion(llvm::Value *Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified type to the specified destination type, both of which are LLVM s...
bool isTrivialInitializer(const Expr *Init)
Determine whether the given initializer is trivial in the sense that it requires no code to be genera...
void EmitOMPParallelMasterDirective(const OMPParallelMasterDirective &S)
void EmitOMPTaskBasedDirective(const OMPExecutableDirective &S, const OpenMPDirectiveKind CapturedRegion, const RegionCodeGenTy &BodyGen, const TaskGenTy &TaskGen, OMPTaskDataTy &Data)
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
void EmitOMPForDirective(const OMPForDirective &S)
void EmitOMPLinearClauseFinal(const OMPLoopDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
Emit final code for linear clauses.
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
void EmitExprAsInit(const Expr *init, const ValueDecl *D, LValue lvalue, bool capturedByInit)
EmitExprAsInit - Emits the code necessary to initialize a location in memory with the given initializ...
void EmitOMPSimdFinal(const OMPLoopDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
This class organizes the cross-function state that is used while generating LLVM code.
void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)
Set the attributes on the LLVM function for the given decl and function info.
llvm::Module & getModule() const
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
CodeGenTypes & getTypes()
const llvm::DataLayout & getDataLayout() const
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
ASTContext & getContext() const
const CodeGenOptions & getCodeGenOpts() const
StringRef getMangledName(GlobalDecl GD)
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
const CGFunctionInfo & arrangeDeviceKernelCallerDeclaration(QualType resultType, const FunctionArgList &args)
A device kernel caller function is an offload device entry point function with a target device depend...
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
llvm::Value * getPointer(CodeGenFunction &CGF) const
Address getAddress() const
void setAddress(Address address)
A stack of loop information corresponding to loop nesting levels.
void setVectorizeWidth(unsigned W)
Set the vectorize width for the next loop pushed.
void setParallel(bool Enable=true)
Set the next pushed loop as parallel.
void push(llvm::BasicBlock *Header, const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc)
Begin a new structured loop.
void setVectorizeEnable(bool Enable=true)
Set the next pushed loop 'vectorize.enable'.
A basic class for pre|post-action for advanced codegen sequence for OpenMP region.
virtual void Enter(CodeGenFunction &CGF)
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
static RValue getComplex(llvm::Value *V1, llvm::Value *V2)
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
std::pair< llvm::Value *, llvm::Value * > getComplexVal() const
getComplexVal - Return the real/imag components of this complex value.
An abstract representation of an aligned address.
llvm::PointerType * getType() const
Return the type of the pointer value.
llvm::Value * getPointer() const
Class intended to support codegen of all kind of the reduction clauses.
LValue getSharedLValue(unsigned N) const
Returns LValue for the reduction item.
void emitAggregateType(CodeGenFunction &CGF, unsigned N)
Emits the code for the variable-modified type, if required.
const VarDecl * getBaseDecl(unsigned N) const
Returns the base declaration of the reduction item.
void emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N)
Emits lvalue for the shared and original reduction item.
void emitInitialization(CodeGenFunction &CGF, unsigned N, Address PrivateAddr, Address SharedAddr, llvm::function_ref< bool(CodeGenFunction &)> DefaultInit)
Performs initialization of the private copy for the reduction item.
Address adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Adjusts PrivatedAddr for using instead of the original variable address in normal operations.
Class provides a way to call simple version of codegen for OpenMP region, or an advanced with possibl...
void setAction(PrePostActionTy &Action) const
Complex values, per C99 6.2.5p11.
CompoundStmt - This represents a group of statements like { stmt stmt }.
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
A reference to a declared variable, function, enum, etc.
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Decl - This represents one declaration (or definition), e.g.
SourceLocation getBodyRBrace() const
getBodyRBrace - Gets the right brace of the body, if a body exists.
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
SourceLocation getLocation() const
The name of a declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreImplicitAsWritten() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
Represents a function declaration or definition.
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin=false, bool isInlineSpecified=false, bool hasWrittenPrototype=true, ConstexprSpecKind ConstexprKind=ConstexprSpecKind::Unspecified, const AssociatedConstraint &TrailingRequiresClause={})
GlobalDecl - represents a global declaration.
One of these records is kept for each identifier that is lexed.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
std::vector< llvm::Triple > OMPTargetTriples
Triples of the OpenMP targets that the host code codegen should take into account in order to generat...
Represents a point when we exit a loop.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
A C++ nested-name-specifier augmented with source location information.
This represents 'acq_rel' clause in the 'pragma omp atomic|flush' directives.
This represents 'acquire' clause in the 'pragma omp atomic|flush' directives.
This represents clause 'aligned' in the 'pragma omp ...' directives.
This represents 'bind' clause in the 'pragma omp ...' directives.
static OMPClauseWithPreInit * get(OMPClause *C)
This is a basic class for representing single OpenMP clause.
This represents clause 'copyin' in the 'pragma omp ...' directives.
This represents clause 'copyprivate' in the 'pragma omp ...' directives.
This represents implicit clause 'depend' for the 'pragma omp task' directive.
This represents implicit clause 'depobj' for the 'pragma omp depobj' directive.
This represents 'destroy' clause in the 'pragma omp depobj' directive or the 'pragma omp interop' dir...
This represents 'device' clause in the 'pragma omp ...' directive.
This represents 'dist_schedule' clause in the 'pragma omp ...' directive.
This represents the 'doacross' clause for the 'pragma omp ordered' directive.
This represents 'fail' clause in the 'pragma omp atomic' directive.
This represents 'filter' clause in the 'pragma omp ...' directive.
This represents 'final' clause in the 'pragma omp ...' directive.
This represents clause 'firstprivate' in the 'pragma omp ...' directives.
This represents implicit clause 'flush' for the 'pragma omp flush' directive.
Representation of the 'full' clause of the 'pragma omp unroll' directive.
This represents 'grainsize' clause in the 'pragma omp ...' directive.
This represents 'hint' clause in the 'pragma omp ...' directive.
This represents 'if' clause in the 'pragma omp ...' directive.
This represents clause 'in_reduction' in the 'pragma omp task' directives.
This represents clause 'inclusive' in the 'pragma omp scan' directive.
This represents the 'init' clause in 'pragma omp ...' directives.
This represents clause 'lastprivate' in the 'pragma omp ...' directives.
This represents clause 'linear' in the 'pragma omp ...' directives.
This represents the 'message' clause in the 'pragma omp error' and the 'pragma omp parallel' directiv...
Expr * getMessageString() const
Returns message string of the clause.
This represents 'nogroup' clause in the 'pragma omp ...' directive.
This represents 'nowait' clause in the 'pragma omp ...' directive.
This represents 'num_tasks' clause in the 'pragma omp ...' directive.
This represents 'num_teams' clause in the 'pragma omp ...' directive.
This represents 'num_threads' clause in the 'pragma omp ...' directive.
This represents 'order' clause in the 'pragma omp ...' directive.
This represents 'ordered' clause in the 'pragma omp ...' directive.
Representation of the 'partial' clause of the 'pragma omp unroll' directive.
This represents 'priority' clause in the 'pragma omp ...' directive.
This represents clause 'private' in the 'pragma omp ...' directives.
This represents 'proc_bind' clause in the 'pragma omp ...' directive.
This represents clause 'reduction' in the 'pragma omp ...' directives.
This represents 'relaxed' clause in the 'pragma omp atomic' directives.
This represents 'release' clause in the 'pragma omp atomic|flush' directives.
This represents 'simd' clause in the 'pragma omp ...' directive.
This represents 'safelen' clause in the 'pragma omp ...' directive.
This represents 'schedule' clause in the 'pragma omp ...' directive.
This represents 'seq_cst' clause in the 'pragma omp atomic|flush' directives.
This represents the 'severity' clause in the 'pragma omp error' and the 'pragma omp parallel' directi...
OpenMPSeverityClauseKind getSeverityKind() const
Returns kind of the clause.
This represents 'simdlen' clause in the 'pragma omp ...' directive.
This represents clause 'task_reduction' in the 'pragma omp taskgroup' directives.
This represents 'thread_limit' clause in the 'pragma omp ...' directive.
This represents 'untied' clause in the 'pragma omp ...' directive.
This represents 'update' clause in the 'pragma omp atomic' directive.
This represents the 'use' clause in 'pragma omp ...' directives.
This represents clause 'use_device_addr' in the 'pragma omp ...' directives.
This represents clause 'use_device_ptr' in the 'pragma omp ...' directives.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
PointerType - C99 6.7.5.1 - Pointer Declarators.
Represents an unpacked "presumed" location which can be presented to the user.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
If a crash happens while one of these objects are live, the message is printed out along with the spe...
A (possibly-)qualified type.
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Represents a struct/union/class.
field_range fields() const
field_iterator field_begin() const
Base for LValueReferenceType and RValueReferenceType.
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
Stmt - This represents one statement.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
SourceLocation getBeginLoc() const LLVM_READONLY
bool isPointerType() const
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isLValueReferenceType() const
bool isAnyComplexType() const
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
static UnaryOperator * Create(const ASTContext &C, Expr *input, Opcode opc, QualType type, ExprValueKind VK, ExprObjectKind OK, SourceLocation l, bool CanOverflow, FPOptionsOverride FPFeatures)
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
TLSKind getTLSKind() const
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
@ CInit
C-style initialization with assignment.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
const Expr * getInit() const
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
@ TLS_None
Not a TLS variable.
Represents a C array with a specified size that is not an integer-constant-expression.
Expr * getSizeExpr() const
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
bool Inc(InterpState &S, CodePtr OpPC, bool CanOverflow)
1) Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value increased by ...
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool needsTaskBasedThreadLimit(OpenMPDirectiveKind DKind)
Checks if the specified target directive, combined or not, needs task based thread_limit.
@ Ctor_Complete
Complete object ctor.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
@ OK_Ordinary
An ordinary object is located at an address in memory.
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ Tile
'tile' clause, allowed on 'loop' and Combined constructs.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_unknown
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
@ OMPC_DIST_SCHEDULE_unknown
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
bool isOpenMPGenericLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive constitutes a 'loop' directive in the outermost nest.
OpenMPBindClauseKind
OpenMP bindings for the 'bind' clause.
const FunctionProtoType * T
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
bool IsXLHSInRHSPart
True if UE has the first form and false if the second.
bool IsPostfixUpdate
True if original value of 'x' must be stored in 'v', not an updated one.
@ Dtor_Complete
Complete object dtor.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of the composite or combined directives that need loop ...
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPNumThreadsClauseModifier
@ OMPC_NUMTHREADS_unknown
bool IsFailOnly
True if 'v' is updated only when the condition is false (compare capture only).
U cast(CodeGen::Address addr)
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
@ ThreadPrivateVar
Parameter for Thread private variable.
@ Other
Other implicit parameter.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
A jump destination is an abstract label, branching to which may require a jump out through normal cle...
llvm::BasicBlock * getBlock() const
static Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc)
Returns address of the threadprivate variable for the current thread.
llvm::OpenMPIRBuilder::InsertPointTy InsertPointTy
static void EmitOMPOutlinedRegionBody(CodeGenFunction &CGF, const Stmt *RegionBodyStmt, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Twine RegionName)
Emit the body of an OMP region that will be outlined in OpenMPIRBuilder::finalize().
static Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD)
Gets the OpenMP-specific address of the local variable /p VD.
static void EmitCaptureStmt(CodeGenFunction &CGF, InsertPointTy CodeGenIP, llvm::BasicBlock &FiniBB, llvm::Function *Fn, ArrayRef< llvm::Value * > Args)
static std::string getNameWithSeparators(ArrayRef< StringRef > Parts, StringRef FirstSeparator=".", StringRef Separator=".")
Get the platform-specific name separator.
static void FinalizeOMPRegion(CodeGenFunction &CGF, InsertPointTy IP)
Emit the Finalization for an OMP region.
static void EmitOMPInlinedRegionBody(CodeGenFunction &CGF, const Stmt *RegionBodyStmt, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Twine RegionName)
Emit the body of an OMP region.
unsigned NumberOfTargetItems
Address BasePointersArray
llvm::PointerType * VoidPtrTy
llvm::IntegerType * Int64Ty
llvm::IntegerType * SizeTy
SmallVector< const Expr *, 4 > DepExprs
EvalResult is a struct with detailed info about an evaluated expression.
Extra information about a function prototype.
Scheduling data for loop-based OpenMP directives.
OpenMPScheduleClauseModifier M2
OpenMPScheduleClauseModifier M1
OpenMPScheduleClauseKind Schedule