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;
1625 llvm::Function *OutlinedFn =
1631 NumThreads = CGF.
EmitScalarExpr(NumThreadsClause->getNumThreads(),
1633 Modifier = NumThreadsClause->getModifier();
1635 Message = MessageClause->getMessageString();
1637 Severity = SeverityClause->getSeverityKind();
1639 CGF, NumThreads, NumThreadsClause->getBeginLoc(), Modifier, Severity,
1645 CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getBeginLoc());
1647 const Expr *IfCond =
nullptr;
1648 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
1649 if (
C->getNameModifier() == OMPD_unknown ||
1650 C->getNameModifier() == OMPD_parallel) {
1651 IfCond =
C->getCondition();
1656 OMPParallelScope
Scope(CGF, S);
1662 CodeGenBoundParameters(CGF, S, CapturedVars);
1665 CapturedVars, IfCond, NumThreads,
1666 Modifier, Severity, Message);
1671 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
1673 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
1675 return !((AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc ||
1676 AA->getAllocatorType() == OMPAllocateDeclAttr::OMPNullMemAlloc) &&
1677 !AA->getAllocator());
1692 CGF, S.getBeginLoc(), OMPD_unknown,
false,
1698 CodeGenFunction &CGF,
const VarDecl *VD) {
1700 auto &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1712 Size = CGF.
Builder.CreateNUWAdd(
1714 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
1715 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
1721 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
1722 assert(AA->getAllocator() &&
1723 "Expected allocator expression for non-default allocator.");
1727 if (Allocator->getType()->isIntegerTy())
1728 Allocator = CGF.
Builder.CreateIntToPtr(Allocator,
CGM.VoidPtrTy);
1729 else if (Allocator->getType()->isPointerTy())
1733 llvm::Value *
Addr = OMPBuilder.createOMPAlloc(
1736 llvm::CallInst *FreeCI =
1737 OMPBuilder.createOMPFree(CGF.
Builder,
Addr, Allocator);
1751 if (
CGM.getLangOpts().OpenMPUseTLS &&
1752 CGM.getContext().getTargetInfo().isTLSSupported())
1755 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1760 llvm::ConstantInt *Size =
CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy));
1762 llvm::Twine CacheName = Twine(
CGM.getMangledName(VD)).concat(Suffix);
1764 llvm::CallInst *ThreadPrivateCacheCall =
1765 OMPBuilder.createCachedThreadPrivate(CGF.
Builder,
Data, Size, CacheName);
1773 llvm::raw_svector_ostream OS(Buffer);
1774 StringRef Sep = FirstSeparator;
1775 for (StringRef Part : Parts) {
1779 return OS.str().str();
1787 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
1788 "." + RegionName +
".after");
1804 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
1805 "." + RegionName +
".after");
1817 if (
CGM.getLangOpts().OpenMPIRBuilder) {
1818 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1820 llvm::Value *IfCond =
nullptr;
1825 llvm::Value *NumThreads =
nullptr;
1830 ProcBindKind ProcBind = OMP_PROC_BIND_default;
1832 ProcBind = ProcBindClause->getProcBindKind();
1834 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1838 auto FiniCB = [
this](InsertPointTy IP) {
1840 return llvm::Error::success();
1847 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
1848 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
1859 auto BodyGenCB = [&,
this](InsertPointTy AllocaIP,
1860 InsertPointTy CodeGenIP) {
1862 *
this, ParallelRegionBodyStmt, AllocaIP, CodeGenIP,
"parallel");
1863 return llvm::Error::success();
1868 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
1870 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
1871 OMPBuilder.createParallel(
Builder, AllocaIP, BodyGenCB, PrivCB, FiniCB,
1872 IfCond, NumThreads, ProcBind, S.hasCancel()));
1886 CGF.
EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt());
1895 [](CodeGenFunction &) {
return nullptr; });
1907class OMPTransformDirectiveScopeRAII {
1908 OMPLoopScope *
Scope =
nullptr;
1912 OMPTransformDirectiveScopeRAII(
const OMPTransformDirectiveScopeRAII &) =
1914 OMPTransformDirectiveScopeRAII &
1915 operator=(
const OMPTransformDirectiveScopeRAII &) =
delete;
1919 if (
const auto *Dir = dyn_cast<OMPLoopBasedDirective>(S)) {
1920 Scope =
new OMPLoopScope(CGF, *Dir);
1925 ~OMPTransformDirectiveScopeRAII() {
1936 int MaxLevel,
int Level = 0) {
1937 assert(Level < MaxLevel &&
"Too deep lookup during loop body codegen.");
1939 if (
const auto *CS = dyn_cast<CompoundStmt>(SimplifiedS)) {
1942 "LLVM IR generation of compound statement ('{}')");
1946 for (
const Stmt *CurStmt : CS->body())
1947 emitBody(CGF, CurStmt, NextLoop, MaxLevel, Level);
1950 if (SimplifiedS == NextLoop) {
1952 dyn_cast<OMPCanonicalLoopNestTransformationDirective>(SimplifiedS))
1953 SimplifiedS = Dir->getTransformedStmt();
1954 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(SimplifiedS))
1955 SimplifiedS = CanonLoop->getLoopStmt();
1956 if (
const auto *For = dyn_cast<ForStmt>(SimplifiedS)) {
1960 "Expected canonical for loop or range-based for loop.");
1962 CGF.
EmitStmt(CXXFor->getLoopVarStmt());
1963 S = CXXFor->getBody();
1965 if (Level + 1 < MaxLevel) {
1966 NextLoop = OMPLoopDirective::tryToFindNextInnerLoop(
1968 emitBody(CGF, S, NextLoop, MaxLevel, Level + 1);
1979 for (
const Expr *UE : D.updates())
1987 for (
const Expr *UE :
C->updates())
1994 BreakContinueStack.push_back(BreakContinue(D,
LoopExit, Continue));
1995 for (
const Expr *E : D.finals_conditions()) {
2008 bool IsInscanRegion = InscanScope.
Privatize();
2009 if (IsInscanRegion) {
2019 if (EKind != OMPD_simd && !
getLangOpts().OpenMPSimd)
2028 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
2031 OMPLoopBasedDirective::tryToFindNextInnerLoop(
2033 D.getLoopsNumber());
2041 BreakContinueStack.pop_back();
2052 std::unique_ptr<CodeGenFunction::CGCapturedStmtInfo> CSI =
2053 std::make_unique<CodeGenFunction::CGCapturedStmtInfo>(*S);
2057 return {F, CapStruct.getPointer(
ParentCGF)};
2061static llvm::CallInst *
2066 EffectiveArgs.reserve(Args.size() + 1);
2067 llvm::append_range(EffectiveArgs, Args);
2068 EffectiveArgs.push_back(Cap.second);
2073llvm::CanonicalLoopInfo *
2075 assert(Depth == 1 &&
"Nested loops with OpenMPIRBuilder not yet implemented");
2101 const Stmt *SyntacticalLoop = S->getLoopStmt();
2112 const Stmt *BodyStmt;
2113 if (
const auto *For = dyn_cast<ForStmt>(SyntacticalLoop)) {
2114 if (
const Stmt *InitStmt = For->getInit())
2116 BodyStmt = For->getBody();
2117 }
else if (
const auto *RangeFor =
2118 dyn_cast<CXXForRangeStmt>(SyntacticalLoop)) {
2119 if (
const DeclStmt *RangeStmt = RangeFor->getRangeStmt())
2121 if (
const DeclStmt *BeginStmt = RangeFor->getBeginStmt())
2123 if (
const DeclStmt *EndStmt = RangeFor->getEndStmt())
2125 if (
const DeclStmt *LoopVarStmt = RangeFor->getLoopVarStmt())
2127 BodyStmt = RangeFor->getBody();
2129 llvm_unreachable(
"Expected for-stmt or range-based for-stmt");
2132 const CapturedStmt *DistanceFunc = S->getDistanceFunc();
2145 llvm::Value *DistVal =
Builder.CreateLoad(CountAddr,
".count");
2148 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2149 auto BodyGen = [&,
this](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP,
2150 llvm::Value *IndVar) {
2155 const DeclRefExpr *LoopVarRef = S->getLoopVarRef();
2163 return llvm::Error::success();
2166 llvm::CanonicalLoopInfo *
CL =
2167 cantFail(OMPBuilder.createCanonicalLoop(
Builder, BodyGen, DistVal));
2179 const Expr *IncExpr,
2180 const llvm::function_ref<
void(CodeGenFunction &)> BodyGen,
2181 const llvm::function_ref<
void(CodeGenFunction &)> PostIncGen) {
2191 const CapturedStmt *ICS = OMPED.getInnermostCapturedStmt();
2205 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
2206 if (RequiresCleanup)
2213 if (ExitBlock !=
LoopExit.getBlock()) {
2223 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
2231 BreakContinueStack.pop_back();
2242 bool HasLinears =
false;
2247 if (
const auto *Ref =
2266 if (
const auto *CS = cast_or_null<BinaryOperator>(
C->getCalcStep()))
2278 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2281 llvm::BasicBlock *DoneBB =
nullptr;
2284 auto IC =
C->varlist_begin();
2285 for (
const Expr *F :
C->finals()) {
2287 if (llvm::Value *
Cond = CondGen(*
this)) {
2299 (*IC)->getType(),
VK_LValue, (*IC)->getExprLoc());
2307 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
2319 llvm::APInt ClauseAlignment(64, 0);
2320 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
2323 ClauseAlignment = AlignmentCI->getValue();
2325 for (
const Expr *E : Clause->varlist()) {
2326 llvm::APInt Alignment(ClauseAlignment);
2327 if (Alignment == 0) {
2334 E->getType()->getPointeeType()))
2337 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2338 "alignment is not power of 2");
2339 if (Alignment != 0) {
2353 auto I = S.private_counters().begin();
2354 for (
const Expr *E : S.counters()) {
2360 LocalDeclMap.erase(PrivateVD);
2366 E->getType(),
VK_LValue, E->getExprLoc());
2375 if (!
C->getNumForLoops())
2377 for (
unsigned I = S.getLoopsNumber(), E =
C->getLoopNumIterations().size();
2383 if (DRE->refersToEnclosingVariableOrCapture()) {
2392 const Expr *
Cond, llvm::BasicBlock *TrueBlock,
2393 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
2401 for (
const Expr *I : S.inits()) {
2408 for (
const Expr *E : S.dependent_counters()) {
2411 assert(!E->getType().getNonReferenceType()->isRecordType() &&
2412 "dependent counter must not be an iterator.");
2416 (void)PreCondVars.
setVarAddr(CGF, VD, CounterAddr);
2418 (void)PreCondVars.
apply(CGF);
2419 for (
const Expr *E : S.dependent_inits()) {
2433 llvm::DenseSet<const VarDecl *> SIMDLCVs;
2437 for (
const Expr *
C : LoopDirective->counters()) {
2443 auto CurPrivate =
C->privates().begin();
2444 for (
const Expr *E :
C->varlist()) {
2446 const auto *PrivateVD =
2453 assert(IsRegistered &&
"linear var already registered as private");
2541 if (
const auto *CS = dyn_cast<CapturedStmt>(S))
2559 if (HasOrderedDirective)
2567 const Stmt *AssociatedStmt = D.getAssociatedStmt();
2571 if (
C->getKind() == OMPC_ORDER_concurrent)
2574 if ((EKind == OMPD_simd ||
2578 return C->getModifier() == OMPC_REDUCTION_inscan;
2586 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2589 llvm::BasicBlock *DoneBB =
nullptr;
2590 auto IC = D.counters().begin();
2591 auto IPC = D.private_counters().begin();
2592 for (
const Expr *F : D.finals()) {
2595 const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
2597 OrigVD->hasGlobalStorage() || CED) {
2599 if (llvm::Value *
Cond = CondGen(*
this)) {
2647 auto &&ThenGen = [&S, &SimdInitGen, &BodyCodeGen](
CodeGenFunction &CGF,
2661 const Expr *IfCond =
nullptr;
2664 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
2666 (
C->getNameModifier() == OMPD_unknown ||
2667 C->getNameModifier() == OMPD_simd)) {
2668 IfCond =
C->getCondition();
2684 OMPLoopScope PreInitScope(CGF, S);
2706 llvm::BasicBlock *ContBlock =
nullptr;
2713 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
2720 const Expr *IVExpr = S.getIterationVariable();
2728 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
2743 CGF, S, CGF.
EmitLValue(S.getIterationVariable()));
2758 emitOMPLoopBodyWithStopPoint(CGF, S,
2759 CodeGenFunction::JumpDest());
2765 if (HasLastprivateClause)
2794 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(S.getRawStmt())) {
2795 if (
const Stmt *SyntacticalLoop = CanonLoop->getLoopStmt()) {
2796 for (
const Stmt *SubStmt : SyntacticalLoop->
children()) {
2799 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(SubStmt)) {
2814static llvm::MapVector<llvm::Value *, llvm::Value *>
2816 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars;
2818 llvm::APInt ClauseAlignment(64, 0);
2819 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
2822 ClauseAlignment = AlignmentCI->getValue();
2824 for (
const Expr *E : Clause->varlist()) {
2825 llvm::APInt Alignment(ClauseAlignment);
2826 if (Alignment == 0) {
2833 E->getType()->getPointeeType()))
2836 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2837 "alignment is not power of 2");
2839 AlignedVars[PtrValue] = CGF.
Builder.getInt64(Alignment.getSExtValue());
2849 bool UseOMPIRBuilder =
2851 if (UseOMPIRBuilder) {
2855 if (UseOMPIRBuilder) {
2856 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars =
2859 const Stmt *Inner = S.getRawStmt();
2860 llvm::CanonicalLoopInfo *CLI =
2861 CGF.EmitOMPCollapsedCanonicalLoopNest(Inner, 1);
2863 llvm::OpenMPIRBuilder &OMPBuilder =
2866 llvm::ConstantInt *Simdlen =
nullptr;
2873 llvm::ConstantInt *Safelen =
nullptr;
2880 llvm::omp::OrderKind Order = llvm::omp::OrderKind::OMP_ORDER_unknown;
2882 if (
C->getKind() == OpenMPOrderClauseKind::OMPC_ORDER_concurrent) {
2883 Order = llvm::omp::OrderKind::OMP_ORDER_concurrent;
2888 OMPBuilder.applySimd(CLI, AlignedVars,
2889 nullptr, Order, Simdlen, Safelen);
2896 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
2911 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
2924 OMPTransformDirectiveScopeRAII TileScope(*
this, &S);
2930 OMPTransformDirectiveScopeRAII StripeScope(*
this, &S);
2936 OMPTransformDirectiveScopeRAII ReverseScope(*
this, &S);
2943 OMPTransformDirectiveScopeRAII InterchangeScope(*
this, &S);
2948 bool UseOMPIRBuilder =
CGM.getLangOpts().OpenMPIRBuilder;
2950 if (UseOMPIRBuilder) {
2952 const Stmt *Inner = S.getRawStmt();
2960 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2963 llvm::CanonicalLoopInfo *UnrolledCLI =
nullptr;
2967 OMPBuilder.unrollLoopFull(DL, CLI);
2969 uint64_t Factor = 0;
2970 if (
Expr *FactorExpr = PartialClause->getFactor()) {
2971 Factor = FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
2972 assert(Factor >= 1 &&
"Only positive factors are valid");
2974 OMPBuilder.unrollLoopPartial(DL, CLI, Factor,
2975 NeedsUnrolledCLI ? &UnrolledCLI :
nullptr);
2977 OMPBuilder.unrollLoopHeuristic(DL, CLI);
2980 assert((!NeedsUnrolledCLI || UnrolledCLI) &&
2981 "NeedsUnrolledCLI implies UnrolledCLI to be set");
2998 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3000 FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
3001 assert(Factor >= 1 &&
"Only positive factors are valid");
3009void CodeGenFunction::EmitOMPOuterLoop(
3012 const CodeGenFunction::OMPLoopArguments &LoopArgs,
3017 const Expr *IVExpr = S.getIterationVariable();
3031 llvm::Value *BoolCondVal =
nullptr;
3032 if (!DynamicOrOrdered) {
3043 RT.
emitForNext(*
this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL,
3044 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST);
3049 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
3054 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
3055 if (ExitBlock !=
LoopExit.getBlock()) {
3063 if (DynamicOrOrdered)
3068 BreakContinueStack.push_back(BreakContinue(S, LoopExit, Continue));
3073 [&S, IsMonotonic, EKind](CodeGenFunction &CGF, PrePostActionTy &) {
3078 if (
const auto *
C = S.getSingleClause<OMPOrderClause>())
3079 if (
C->getKind() == OMPC_ORDER_concurrent)
3085 [&S, &LoopArgs, LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered,
3086 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
3087 SourceLocation Loc = S.getBeginLoc();
3093 CGF.EmitOMPInnerLoop(
3095 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
3096 CodeGenLoop(CGF, S, LoopExit);
3098 [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) {
3099 CodeGenOrdered(CGF, Loc, IVSize, IVSigned);
3104 BreakContinueStack.pop_back();
3105 if (!DynamicOrOrdered) {
3118 auto &&CodeGen = [DynamicOrOrdered, &S, &LoopArgs](CodeGenFunction &CGF) {
3119 if (!DynamicOrOrdered)
3120 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
3123 OMPCancelStack.emitExit(*
this, EKind, CodeGen);
3126void CodeGenFunction::EmitOMPForOuterLoop(
3127 const OpenMPScheduleTy &ScheduleKind,
bool IsMonotonic,
3129 const OMPLoopArguments &LoopArgs,
3131 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3137 LoopArgs.Chunk !=
nullptr)) &&
3138 "static non-chunked schedule does not need outer loop");
3192 const Expr *IVExpr = S.getIterationVariable();
3196 if (DynamicOrOrdered) {
3197 const std::pair<llvm::Value *, llvm::Value *> DispatchBounds =
3198 CGDispatchBounds(*
this, S, LoopArgs.LB, LoopArgs.UB);
3199 llvm::Value *LBVal = DispatchBounds.first;
3200 llvm::Value *UBVal = DispatchBounds.second;
3201 CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal,
3204 IVSigned, Ordered, DipatchRTInputValues);
3206 CGOpenMPRuntime::StaticRTInput StaticInit(
3207 IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
3208 LoopArgs.ST, LoopArgs.Chunk);
3214 auto &&CodeGenOrdered = [Ordered](CodeGenFunction &CGF, SourceLocation Loc,
3215 const unsigned IVSize,
3216 const bool IVSigned) {
3223 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST,
3224 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB);
3225 OuterLoopArgs.IncExpr = S.getInc();
3226 OuterLoopArgs.Init = S.getInit();
3227 OuterLoopArgs.Cond = S.getCond();
3228 OuterLoopArgs.NextLB = S.getNextLowerBound();
3229 OuterLoopArgs.NextUB = S.getNextUpperBound();
3230 OuterLoopArgs.DKind = LoopArgs.DKind;
3231 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
3233 if (DynamicOrOrdered) {
3239 const unsigned IVSize,
const bool IVSigned) {}
3241void CodeGenFunction::EmitOMPDistributeOuterLoop(
3246 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3253 const Expr *IVExpr = S.getIterationVariable();
3258 CGOpenMPRuntime::StaticRTInput StaticInit(
3259 IVSize, IVSigned,
false, LoopArgs.IL, LoopArgs.LB,
3260 LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
3267 IncExpr = S.getDistInc();
3269 IncExpr = S.getInc();
3274 OMPLoopArguments OuterLoopArgs;
3275 OuterLoopArgs.LB = LoopArgs.LB;
3276 OuterLoopArgs.UB = LoopArgs.UB;
3277 OuterLoopArgs.ST = LoopArgs.ST;
3278 OuterLoopArgs.IL = LoopArgs.IL;
3279 OuterLoopArgs.Chunk = LoopArgs.Chunk;
3281 ? S.getCombinedEnsureUpperBound()
3282 : S.getEnsureUpperBound();
3283 OuterLoopArgs.IncExpr = IncExpr;
3285 ? S.getCombinedInit()
3288 ? S.getCombinedCond()
3291 ? S.getCombinedNextLowerBound()
3292 : S.getNextLowerBound();
3294 ? S.getCombinedNextUpperBound()
3295 : S.getNextUpperBound();
3296 OuterLoopArgs.DKind = OMPD_distribute;
3298 EmitOMPOuterLoop(
false,
false, S,
3299 LoopScope, OuterLoopArgs, CodeGenLoopContent,
3303static std::pair<LValue, LValue>
3318 LValue PrevLB = CGF.
EmitLValue(LS.getPrevLowerBoundVariable());
3319 LValue PrevUB = CGF.
EmitLValue(LS.getPrevUpperBoundVariable());
3321 PrevLB, LS.getPrevLowerBoundVariable()->getExprLoc());
3323 PrevLBVal, LS.getPrevLowerBoundVariable()->getType(),
3324 LS.getIterationVariable()->getType(),
3325 LS.getPrevLowerBoundVariable()->getExprLoc());
3327 PrevUB, LS.getPrevUpperBoundVariable()->getExprLoc());
3329 PrevUBVal, LS.getPrevUpperBoundVariable()->getType(),
3330 LS.getIterationVariable()->getType(),
3331 LS.getPrevUpperBoundVariable()->getExprLoc());
3346static std::pair<llvm::Value *, llvm::Value *>
3351 const Expr *IVExpr = LS.getIterationVariable();
3357 llvm::Value *LBVal =
3359 llvm::Value *UBVal =
3361 return {LBVal, UBVal};
3370 llvm::Value *LBCast = CGF.
Builder.CreateIntCast(
3372 CapturedVars.push_back(LBCast);
3376 llvm::Value *UBCast = CGF.
Builder.CreateIntCast(
3378 CapturedVars.push_back(UBCast);
3389 bool HasCancel =
false;
3391 if (
const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
3392 HasCancel = D->hasCancel();
3393 else if (
const auto *D = dyn_cast<OMPDistributeParallelForDirective>(&S))
3394 HasCancel = D->hasCancel();
3395 else if (
const auto *D =
3396 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S))
3397 HasCancel = D->hasCancel();
3407 CGInlinedWorksharingLoop,
3417 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3418 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3427 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3428 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3436 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
3437 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
3447 llvm::Constant *
Addr;
3449 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
3451 assert(Fn &&
Addr &&
"Target device function emission failed.");
3463struct ScheduleKindModifiersTy {
3470 : Kind(Kind), M1(M1), M2(M2) {}
3486 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
3494 bool HasLastprivateClause;
3497 OMPLoopScope PreInitScope(*
this, S);
3502 llvm::BasicBlock *ContBlock =
nullptr;
3509 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
3516 bool Ordered =
false;
3518 if (OrderedClause->getNumForLoops())
3528 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*
this, S);
3529 LValue LB = Bounds.first;
3530 LValue UB = Bounds.second;
3544 CGM.getOpenMPRuntime().emitBarrierCall(
3545 *
this, S.getBeginLoc(), OMPD_unknown,
false,
3550 *
this, S,
EmitLValue(S.getIterationVariable()));
3557 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
3560 const Expr *ChunkExpr =
nullptr;
3563 ScheduleKind.
Schedule =
C->getScheduleKind();
3564 ScheduleKind.
M1 =
C->getFirstScheduleModifier();
3565 ScheduleKind.
M2 =
C->getSecondScheduleModifier();
3566 ChunkExpr =
C->getChunkSize();
3569 CGM.getOpenMPRuntime().getDefaultScheduleAndChunk(
3570 *
this, S, ScheduleKind.
Schedule, ChunkExpr);
3572 bool HasChunkSizeOne =
false;
3573 llvm::Value *Chunk =
nullptr;
3577 S.getIterationVariable()->getType(),
3581 llvm::APSInt EvaluatedChunk =
Result.Val.getInt();
3582 HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
3591 bool StaticChunkedOne =
3593 Chunk !=
nullptr) &&
3597 (ScheduleKind.
Schedule == OMPC_SCHEDULE_static &&
3598 !(ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
3599 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)) ||
3600 ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
3601 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
3603 Chunk !=
nullptr) ||
3604 StaticChunkedOne) &&
3614 if (
C->getKind() == OMPC_ORDER_concurrent)
3618 [IVSize, IVSigned, Ordered, IL, LB, UB, ST, StaticChunkedOne, Chunk,
3627 IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(),
3628 UB.getAddress(), ST.getAddress(),
3629 StaticChunkedOne ? Chunk :
nullptr);
3631 CGF, S.getBeginLoc(), EKind, ScheduleKind, StaticInit);
3633 if (!StaticChunkedOne)
3652 StaticChunkedOne ? S.getCombinedParForInDistCond()
3654 StaticChunkedOne ? S.getDistInc() : S.getInc(),
3655 [&S,
LoopExit](CodeGenFunction &CGF) {
3656 emitOMPLoopBodyWithStopPoint(CGF, S, LoopExit);
3658 [](CodeGenFunction &) {});
3662 auto &&
CodeGen = [&S](CodeGenFunction &CGF) {
3666 OMPCancelStack.emitExit(*
this, EKind,
CodeGen);
3673 LoopArguments.DKind = OMPD_for;
3674 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
3675 LoopArguments, CGDispatchBounds);
3679 return CGF.
Builder.CreateIsNotNull(
3685 ? OMPD_parallel_for_simd
3689 *
this, S, [IL, &S](CodeGenFunction &CGF) {
3690 return CGF.
Builder.CreateIsNotNull(
3694 if (HasLastprivateClause)
3700 return CGF.
Builder.CreateIsNotNull(
3711 return HasLastprivateClause;
3717static std::pair<LValue, LValue>
3731static std::pair<llvm::Value *, llvm::Value *>
3735 const Expr *IVExpr = LS.getIterationVariable();
3737 llvm::Value *LBVal = CGF.
Builder.getIntN(IVSize, 0);
3739 return {LBVal, UBVal};
3751 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
3752 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
3753 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
3759 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
3760 "Only inscan reductions are expected.");
3761 Shareds.append(
C->varlist_begin(),
C->varlist_end());
3762 Privates.append(
C->privates().begin(),
C->privates().end());
3763 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
3764 CopyArrayTemps.append(
C->copy_array_temps().begin(),
3765 C->copy_array_temps().end());
3773 auto *ITA = CopyArrayTemps.begin();
3774 for (
const Expr *IRef : Privates) {
3778 if (PrivateVD->getType()->isVariablyModifiedType()) {
3803 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
3804 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
3805 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
3813 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
3814 "Only inscan reductions are expected.");
3815 Shareds.append(
C->varlist_begin(),
C->varlist_end());
3816 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
3817 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
3818 Privates.append(
C->privates().begin(),
C->privates().end());
3819 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
3820 CopyArrayElems.append(
C->copy_array_elems().begin(),
3821 C->copy_array_elems().end());
3825 llvm::Value *OMPLast = CGF.
Builder.CreateNSWSub(
3826 OMPScanNumIterations,
3827 llvm::ConstantInt::get(CGF.
SizeTy, 1,
false));
3828 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
3829 const Expr *PrivateExpr = Privates[I];
3830 const Expr *OrigExpr = Shareds[I];
3831 const Expr *CopyArrayElem = CopyArrayElems[I];
3838 LValue SrcLVal = CGF.
EmitLValue(CopyArrayElem);
3840 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
3870 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
3871 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
3878 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
3879 "Only inscan reductions are expected.");
3880 Privates.append(
C->privates().begin(),
C->privates().end());
3881 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
3882 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
3883 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
3884 CopyArrayElems.append(
C->copy_array_elems().begin(),
3885 C->copy_array_elems().end());
3900 auto &&
CodeGen = [&S, OMPScanNumIterations, &LHSs, &RHSs, &CopyArrayElems,
3907 llvm::BasicBlock *InputBB = CGF.Builder.GetInsertBlock();
3908 llvm::BasicBlock *LoopBB = CGF.createBasicBlock(
"omp.outer.log.scan.body");
3909 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
"omp.outer.log.scan.exit");
3911 CGF.CGM.getIntrinsic(llvm::Intrinsic::log2, CGF.DoubleTy);
3913 CGF.Builder.CreateUIToFP(OMPScanNumIterations, CGF.DoubleTy);
3914 llvm::Value *LogVal = CGF.EmitNounwindRuntimeCall(F, Arg);
3915 F = CGF.CGM.getIntrinsic(llvm::Intrinsic::ceil, CGF.DoubleTy);
3916 LogVal = CGF.EmitNounwindRuntimeCall(F, LogVal);
3917 LogVal = CGF.Builder.CreateFPToUI(LogVal, CGF.IntTy);
3918 llvm::Value *NMin1 = CGF.Builder.CreateNUWSub(
3919 OMPScanNumIterations, llvm::ConstantInt::get(CGF.SizeTy, 1));
3921 CGF.EmitBlock(LoopBB);
3922 auto *Counter = CGF.Builder.CreatePHI(CGF.IntTy, 2);
3924 auto *Pow2K = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
3925 Counter->addIncoming(llvm::ConstantInt::get(CGF.IntTy, 0), InputBB);
3926 Pow2K->addIncoming(llvm::ConstantInt::get(CGF.SizeTy, 1), InputBB);
3929 llvm::BasicBlock *InnerLoopBB =
3930 CGF.createBasicBlock(
"omp.inner.log.scan.body");
3931 llvm::BasicBlock *InnerExitBB =
3932 CGF.createBasicBlock(
"omp.inner.log.scan.exit");
3933 llvm::Value *CmpI = CGF.Builder.CreateICmpUGE(NMin1, Pow2K);
3934 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
3935 CGF.EmitBlock(InnerLoopBB);
3936 auto *IVal = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
3937 IVal->addIncoming(NMin1, LoopBB);
3940 auto *ILHS = LHSs.begin();
3941 auto *IRHS = RHSs.begin();
3942 for (
const Expr *CopyArrayElem : CopyArrayElems) {
3952 LHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
3957 llvm::Value *OffsetIVal = CGF.Builder.CreateNUWSub(IVal, Pow2K);
3963 RHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
3970 CGF.CGM.getOpenMPRuntime().emitReduction(
3971 CGF, S.getEndLoc(), Privates, LHSs, RHSs, ReductionOps,
3975 llvm::Value *NextIVal =
3976 CGF.Builder.CreateNUWSub(IVal, llvm::ConstantInt::get(CGF.SizeTy, 1));
3977 IVal->addIncoming(NextIVal, CGF.Builder.GetInsertBlock());
3978 CmpI = CGF.Builder.CreateICmpUGE(NextIVal, Pow2K);
3979 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
3980 CGF.EmitBlock(InnerExitBB);
3982 CGF.Builder.CreateNUWAdd(Counter, llvm::ConstantInt::get(CGF.IntTy, 1));
3983 Counter->addIncoming(
Next, CGF.Builder.GetInsertBlock());
3985 llvm::Value *NextPow2K =
3986 CGF.Builder.CreateShl(Pow2K, 1,
"",
true);
3987 Pow2K->addIncoming(NextPow2K, CGF.Builder.GetInsertBlock());
3988 llvm::Value *Cmp = CGF.Builder.CreateICmpNE(
Next, LogVal);
3989 CGF.Builder.CreateCondBr(Cmp, LoopBB, ExitBB);
3991 CGF.EmitBlock(ExitBB);
3997 CGF, S.getBeginLoc(), OMPD_unknown,
false,
4000 RegionCodeGenTy RCG(CodeGen);
4011 bool HasLastprivates;
4015 return C->getModifier() == OMPC_REDUCTION_inscan;
4019 OMPLoopScope LoopScope(CGF, S);
4022 const auto &&FirstGen = [&S, HasCancel, EKind](
CodeGenFunction &CGF) {
4031 const auto &&SecondGen = [&S, HasCancel, EKind,
4049 return HasLastprivates;
4062 if (
auto *SC = dyn_cast<OMPScheduleClause>(
C)) {
4067 switch (SC->getScheduleKind()) {
4068 case OMPC_SCHEDULE_auto:
4069 case OMPC_SCHEDULE_dynamic:
4070 case OMPC_SCHEDULE_runtime:
4071 case OMPC_SCHEDULE_guided:
4072 case OMPC_SCHEDULE_static:
4085static llvm::omp::ScheduleKind
4087 switch (ScheduleClauseKind) {
4089 return llvm::omp::OMP_SCHEDULE_Default;
4090 case OMPC_SCHEDULE_auto:
4091 return llvm::omp::OMP_SCHEDULE_Auto;
4092 case OMPC_SCHEDULE_dynamic:
4093 return llvm::omp::OMP_SCHEDULE_Dynamic;
4094 case OMPC_SCHEDULE_guided:
4095 return llvm::omp::OMP_SCHEDULE_Guided;
4096 case OMPC_SCHEDULE_runtime:
4097 return llvm::omp::OMP_SCHEDULE_Runtime;
4098 case OMPC_SCHEDULE_static:
4099 return llvm::omp::OMP_SCHEDULE_Static;
4101 llvm_unreachable(
"Unhandled schedule kind");
4108 bool HasLastprivates =
false;
4111 auto &&
CodeGen = [&S, &
CGM, HasCancel, &HasLastprivates,
4114 if (UseOMPIRBuilder) {
4117 llvm::omp::ScheduleKind SchedKind = llvm::omp::OMP_SCHEDULE_Default;
4118 llvm::Value *ChunkSize =
nullptr;
4122 if (
const Expr *ChunkSizeExpr = SchedClause->getChunkSize())
4127 const Stmt *Inner = S.getRawStmt();
4128 llvm::CanonicalLoopInfo *CLI =
4131 llvm::OpenMPIRBuilder &OMPBuilder =
4133 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4135 cantFail(OMPBuilder.applyWorkshareLoop(
4136 CGF.
Builder.getCurrentDebugLocation(), CLI, AllocaIP, NeedsBarrier,
4137 SchedKind, ChunkSize,
false,
4148 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
4153 if (!UseOMPIRBuilder) {
4167 bool HasLastprivates =
false;
4168 auto &&
CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
4175 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4176 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
4181 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_for);
4188 llvm::Value *
Init =
nullptr) {
4195void CodeGenFunction::EmitSections(
const OMPExecutableDirective &S) {
4196 const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4197 const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt);
4198 bool HasLastprivates =
false;
4200 auto &&CodeGen = [&S, CapturedStmt, CS, EKind,
4201 &HasLastprivates](CodeGenFunction &CGF, PrePostActionTy &) {
4202 const ASTContext &
C = CGF.getContext();
4203 QualType KmpInt32Ty =
4204 C.getIntTypeForBitwidth(32, 1);
4207 CGF.Builder.getInt32(0));
4208 llvm::ConstantInt *GlobalUBVal = CS !=
nullptr
4209 ? CGF.Builder.getInt32(CS->size() - 1)
4210 : CGF.Builder.getInt32(0);
4214 CGF.Builder.getInt32(1));
4216 CGF.Builder.getInt32(0));
4219 OpaqueValueExpr IVRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4220 CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
4221 OpaqueValueExpr UBRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4222 CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
4226 S.getBeginLoc(), FPOptionsOverride());
4230 S.getBeginLoc(),
true, FPOptionsOverride());
4231 auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
4243 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".omp.sections.exit");
4244 llvm::SwitchInst *SwitchStmt =
4245 CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.
getBeginLoc()),
4246 ExitBB, CS ==
nullptr ? 1 : CS->size());
4248 unsigned CaseNumber = 0;
4249 for (
const Stmt *SubStmt : CS->
children()) {
4250 auto CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4251 CGF.EmitBlock(CaseBB);
4252 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
4253 CGF.EmitStmt(SubStmt);
4254 CGF.EmitBranch(ExitBB);
4258 llvm::BasicBlock *CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4259 CGF.EmitBlock(CaseBB);
4260 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
4261 CGF.EmitStmt(CapturedStmt);
4262 CGF.EmitBranch(ExitBB);
4264 CGF.EmitBlock(ExitBB,
true);
4267 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
4268 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
4272 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
4276 CGF.EmitOMPPrivateClause(S, LoopScope);
4277 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(CGF, S, IV);
4278 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
4279 CGF.EmitOMPReductionClauseInit(S, LoopScope);
4280 (void)LoopScope.Privatize();
4282 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
4285 OpenMPScheduleTy ScheduleKind;
4286 ScheduleKind.
Schedule = OMPC_SCHEDULE_static;
4287 CGOpenMPRuntime::StaticRTInput StaticInit(
4288 32,
true,
false, IL.getAddress(),
4289 LB.getAddress(), UB.getAddress(), ST.getAddress());
4290 CGF.CGM.getOpenMPRuntime().emitForStaticInit(CGF, S.
getBeginLoc(), EKind,
4291 ScheduleKind, StaticInit);
4293 llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.
getBeginLoc());
4294 llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
4295 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
4296 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
4298 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.
getBeginLoc()), IV);
4300 CGF.EmitOMPInnerLoop(S,
false,
Cond, Inc, BodyGen,
4301 [](CodeGenFunction &) {});
4303 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
4304 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.
getEndLoc(),
4307 CGF.OMPCancelStack.emitExit(CGF, EKind, CodeGen);
4308 CGF.EmitOMPReductionClauseFinal(S, OMPD_parallel);
4311 return CGF.
Builder.CreateIsNotNull(
4316 if (HasLastprivates)
4323 bool HasCancel =
false;
4324 if (
auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
4325 HasCancel = OSD->hasCancel();
4326 else if (
auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
4327 HasCancel = OPSD->hasCancel();
4329 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_sections, CodeGen,
4334 if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) {
4352 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4357 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4358 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_scope,
CodeGen);
4362 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_scope);
4369 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4370 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4371 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4372 using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
4374 auto FiniCB = [](InsertPointTy IP) {
4377 return llvm::Error::success();
4380 const CapturedStmt *ICS = S.getInnermostCapturedStmt();
4386 auto SectionCB = [
this, SubStmt](InsertPointTy AllocaIP,
4387 InsertPointTy CodeGenIP) {
4389 *
this, SubStmt, AllocaIP, CodeGenIP,
"section");
4390 return llvm::Error::success();
4392 SectionCBVector.push_back(SectionCB);
4395 auto SectionCB = [
this,
CapturedStmt](InsertPointTy AllocaIP,
4396 InsertPointTy CodeGenIP) {
4399 return llvm::Error::success();
4401 SectionCBVector.push_back(SectionCB);
4408 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
4409 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
4419 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4421 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4422 cantFail(OMPBuilder.createSections(
4423 Builder, AllocaIP, SectionCBVector, PrivCB, FiniCB, S.hasCancel(),
4431 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4436 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(),
4444 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4445 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4446 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4448 const Stmt *SectionRegionBodyStmt = S.getAssociatedStmt();
4449 auto FiniCB = [
this](InsertPointTy IP) {
4451 return llvm::Error::success();
4454 auto BodyGenCB = [SectionRegionBodyStmt,
this](InsertPointTy AllocaIP,
4455 InsertPointTy CodeGenIP) {
4457 *
this, SectionRegionBodyStmt, AllocaIP, CodeGenIP,
"section");
4458 return llvm::Error::success();
4463 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4464 cantFail(OMPBuilder.createSection(
Builder, BodyGenCB, FiniCB));
4484 CopyprivateVars.append(
C->varlist_begin(),
C->varlist_end());
4485 DestExprs.append(
C->destination_exprs().begin(),
4486 C->destination_exprs().end());
4487 SrcExprs.append(
C->source_exprs().begin(),
C->source_exprs().end());
4488 AssignmentOps.append(
C->assignment_ops().begin(),
4489 C->assignment_ops().end());
4498 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4503 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4504 CGM.getOpenMPRuntime().emitSingleRegion(*
this,
CodeGen, S.getBeginLoc(),
4505 CopyprivateVars, DestExprs,
4506 SrcExprs, AssignmentOps);
4510 if (!S.getSingleClause<
OMPNowaitClause>() && CopyprivateVars.empty()) {
4511 CGM.getOpenMPRuntime().emitBarrierCall(
4512 *
this, S.getBeginLoc(),
4528 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4529 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4530 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4532 const Stmt *MasterRegionBodyStmt = S.getAssociatedStmt();
4534 auto FiniCB = [
this](InsertPointTy IP) {
4536 return llvm::Error::success();
4539 auto BodyGenCB = [MasterRegionBodyStmt,
this](InsertPointTy AllocaIP,
4540 InsertPointTy CodeGenIP) {
4542 *
this, MasterRegionBodyStmt, AllocaIP, CodeGenIP,
"master");
4543 return llvm::Error::success();
4548 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4549 cantFail(OMPBuilder.createMaster(
Builder, BodyGenCB, FiniCB));
4564 Expr *Filter =
nullptr;
4566 Filter = FilterClause->getThreadID();
4572 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4573 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4574 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4576 const Stmt *MaskedRegionBodyStmt = S.getAssociatedStmt();
4577 const Expr *Filter =
nullptr;
4579 Filter = FilterClause->getThreadID();
4580 llvm::Value *FilterVal = Filter
4582 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
4584 auto FiniCB = [
this](InsertPointTy IP) {
4586 return llvm::Error::success();
4589 auto BodyGenCB = [MaskedRegionBodyStmt,
this](InsertPointTy AllocaIP,
4590 InsertPointTy CodeGenIP) {
4592 *
this, MaskedRegionBodyStmt, AllocaIP, CodeGenIP,
"masked");
4593 return llvm::Error::success();
4598 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
4599 OMPBuilder.createMasked(
Builder, BodyGenCB, FiniCB, FilterVal));
4610 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4611 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4612 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4614 const Stmt *CriticalRegionBodyStmt = S.getAssociatedStmt();
4615 const Expr *Hint =
nullptr;
4616 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4617 Hint = HintClause->getHint();
4622 llvm::Value *HintInst =
nullptr;
4627 auto FiniCB = [
this](InsertPointTy IP) {
4629 return llvm::Error::success();
4632 auto BodyGenCB = [CriticalRegionBodyStmt,
this](InsertPointTy AllocaIP,
4633 InsertPointTy CodeGenIP) {
4635 *
this, CriticalRegionBodyStmt, AllocaIP, CodeGenIP,
"critical");
4636 return llvm::Error::success();
4641 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4642 cantFail(OMPBuilder.createCritical(
Builder, BodyGenCB, FiniCB,
4643 S.getDirectiveName().getAsString(),
4652 CGF.
EmitStmt(S.getAssociatedStmt());
4654 const Expr *Hint =
nullptr;
4655 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4656 Hint = HintClause->getHint();
4659 CGM.getOpenMPRuntime().emitCriticalRegion(*
this,
4660 S.getDirectiveName().getAsString(),
4661 CodeGen, S.getBeginLoc(), Hint);
4665 const OMPParallelForDirective &S) {
4674 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
4678 OMPLoopScope LoopScope(CGF, S);
4683 return C->getModifier() == OMPC_REDUCTION_inscan;
4699 const OMPParallelForSimdDirective &S) {
4708 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
4712 OMPLoopScope LoopScope(CGF, S);
4717 return C->getModifier() == OMPC_REDUCTION_inscan;
4733 const OMPParallelMasterDirective &S) {
4753 [](CodeGenFunction &) {
return nullptr; });
4760 const OMPParallelMaskedDirective &S) {
4780 [](CodeGenFunction &) {
return nullptr; });
4787 const OMPParallelSectionsDirective &S) {
4793 CGF.EmitSections(S);
4807class CheckVarsEscapingUntiedTaskDeclContext final
4812 explicit CheckVarsEscapingUntiedTaskDeclContext() =
default;
4813 ~CheckVarsEscapingUntiedTaskDeclContext() =
default;
4814 void VisitDeclStmt(
const DeclStmt *S) {
4819 if (
const auto *VD = dyn_cast_or_null<VarDecl>(D))
4821 PrivateDecls.push_back(VD);
4825 void VisitCapturedStmt(
const CapturedStmt *) {}
4827 void VisitBlockExpr(
const BlockExpr *) {}
4828 void VisitStmt(
const Stmt *S) {
4831 for (
const Stmt *Child : S->
children())
4837 ArrayRef<const VarDecl *> getPrivateDecls()
const {
return PrivateDecls; }
4845 bool OmpAllMemory =
false;
4848 return C->getDependencyKind() == OMPC_DEPEND_outallmemory ||
4849 C->getDependencyKind() == OMPC_DEPEND_inoutallmemory;
4851 OmpAllMemory =
true;
4856 Data.Dependences.emplace_back(OMPC_DEPEND_outallmemory,
4865 if (Kind == OMPC_DEPEND_outallmemory || Kind == OMPC_DEPEND_inoutallmemory)
4867 if (OmpAllMemory && (Kind == OMPC_DEPEND_out || Kind == OMPC_DEPEND_inout))
4870 Data.Dependences.emplace_back(
C->getDependencyKind(),
C->getModifier());
4871 DD.
DepExprs.append(
C->varlist_begin(),
C->varlist_end());
4880 const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion);
4882 auto PartId = std::next(I);
4883 auto TaskT = std::next(I, 4);
4888 const Expr *
Cond = Clause->getCondition();
4891 Data.Final.setInt(CondConstant);
4896 Data.Final.setInt(
false);
4900 const Expr *Prio = Clause->getPriority();
4901 Data.Priority.setInt(
true);
4909 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
4912 auto IRef =
C->varlist_begin();
4913 for (
const Expr *IInit :
C->private_copies()) {
4915 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
4916 Data.PrivateVars.push_back(*IRef);
4917 Data.PrivateCopies.push_back(IInit);
4922 EmittedAsPrivate.clear();
4925 auto IRef =
C->varlist_begin();
4926 auto IElemInitRef =
C->inits().begin();
4927 for (
const Expr *IInit :
C->private_copies()) {
4929 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
4930 Data.FirstprivateVars.push_back(*IRef);
4931 Data.FirstprivateCopies.push_back(IInit);
4932 Data.FirstprivateInits.push_back(*IElemInitRef);
4939 llvm::MapVector<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
4941 auto IRef =
C->varlist_begin();
4942 auto ID =
C->destination_exprs().begin();
4943 for (
const Expr *IInit :
C->private_copies()) {
4945 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
4946 Data.LastprivateVars.push_back(*IRef);
4947 Data.LastprivateCopies.push_back(IInit);
4949 LastprivateDstsOrigs.insert(
4959 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
4960 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
4961 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
4962 Data.ReductionOps.append(
C->reduction_ops().begin(),
4963 C->reduction_ops().end());
4964 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
4965 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
4967 Data.Reductions =
CGM.getOpenMPRuntime().emitTaskReductionInit(
4968 *
this, S.getBeginLoc(), LHSs, RHSs,
Data);
4973 CheckVarsEscapingUntiedTaskDeclContext Checker;
4974 Checker.Visit(S.getInnermostCapturedStmt()->getCapturedStmt());
4975 Data.PrivateLocals.append(Checker.getPrivateDecls().begin(),
4976 Checker.getPrivateDecls().end());
4978 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
4979 CapturedRegion](CodeGenFunction &CGF,
4981 llvm::MapVector<CanonicalDeclPtr<const VarDecl>,
4982 std::pair<Address, Address>>
4987 if (
auto *DI = CGF.getDebugInfo()) {
4988 llvm::SmallDenseMap<const VarDecl *, FieldDecl *> CaptureFields =
4989 CGF.CapturedStmtInfo->getCaptureFields();
4990 llvm::Value *ContextValue = CGF.CapturedStmtInfo->getContextValue();
4991 if (CaptureFields.size() && ContextValue) {
4992 unsigned CharWidth = CGF.getContext().getCharWidth();
5006 for (
auto It = CaptureFields.begin(); It != CaptureFields.end(); ++It) {
5007 const VarDecl *SharedVar = It->first;
5010 CGF.getContext().getASTRecordLayout(CaptureRecord);
5013 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5014 (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue,
5015 CGF.Builder,
false);
5018 auto UpdateExpr = [](llvm::LLVMContext &Ctx,
auto *
Declare,
5023 Ops.push_back(llvm::dwarf::DW_OP_plus_uconst);
5024 Ops.push_back(Offset);
5026 Ops.push_back(llvm::dwarf::DW_OP_deref);
5027 Declare->setExpression(llvm::DIExpression::get(Ctx, Ops));
5029 llvm::Instruction &
Last = CGF.Builder.GetInsertBlock()->back();
5030 if (
auto DDI = dyn_cast<llvm::DbgVariableIntrinsic>(&
Last))
5031 UpdateExpr(DDI->getContext(), DDI, Offset);
5034 assert(!
Last.isTerminator() &&
"unexpected terminator");
5036 CGF.Builder.GetInsertBlock()->getTrailingDbgRecords()) {
5037 for (llvm::DbgVariableRecord &DVR : llvm::reverse(
5038 llvm::filterDbgVars(Marker->getDbgRecordRange()))) {
5039 UpdateExpr(
Last.getContext(), &DVR, Offset);
5047 if (!
Data.PrivateVars.empty() || !
Data.FirstprivateVars.empty() ||
5048 !
Data.LastprivateVars.empty() || !
Data.PrivateLocals.empty()) {
5049 enum { PrivatesParam = 2, CopyFnParam = 3 };
5050 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5052 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5058 CallArgs.push_back(PrivatesPtr);
5059 ParamTypes.push_back(PrivatesPtr->getType());
5060 for (
const Expr *E :
Data.PrivateVars) {
5063 CGF.getContext().getPointerType(E->
getType()),
".priv.ptr.addr");
5064 PrivatePtrs.emplace_back(VD, PrivatePtr);
5066 ParamTypes.push_back(PrivatePtr.
getType());
5068 for (
const Expr *E :
Data.FirstprivateVars) {
5071 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
5072 ".firstpriv.ptr.addr");
5073 PrivatePtrs.emplace_back(VD, PrivatePtr);
5074 FirstprivatePtrs.emplace_back(VD, PrivatePtr);
5076 ParamTypes.push_back(PrivatePtr.
getType());
5078 for (
const Expr *E :
Data.LastprivateVars) {
5081 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
5082 ".lastpriv.ptr.addr");
5083 PrivatePtrs.emplace_back(VD, PrivatePtr);
5085 ParamTypes.push_back(PrivatePtr.
getType());
5090 Ty = CGF.getContext().getPointerType(Ty);
5092 Ty = CGF.getContext().getPointerType(Ty);
5094 CGF.getContext().getPointerType(Ty),
".local.ptr.addr");
5095 auto Result = UntiedLocalVars.insert(
5098 if (
Result.second ==
false)
5099 *
Result.first = std::make_pair(
5102 ParamTypes.push_back(PrivatePtr.
getType());
5104 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5106 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5107 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5108 for (
const auto &Pair : LastprivateDstsOrigs) {
5112 CGF.CapturedStmtInfo->lookup(OrigVD) !=
nullptr,
5114 Pair.second->getExprLoc());
5115 Scope.addPrivate(Pair.first, CGF.EmitLValue(&DRE).getAddress());
5117 for (
const auto &Pair : PrivatePtrs) {
5119 CGF.Builder.CreateLoad(Pair.second),
5120 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5121 CGF.getContext().getDeclAlign(Pair.first));
5122 Scope.addPrivate(Pair.first, Replacement);
5123 if (
auto *DI = CGF.getDebugInfo())
5124 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5125 (void)DI->EmitDeclareOfAutoVariable(
5126 Pair.first, Pair.second.getBasePointer(), CGF.Builder,
5131 for (
auto &Pair : UntiedLocalVars) {
5132 QualType VDType = Pair.first->getType().getNonReferenceType();
5133 if (Pair.first->getType()->isLValueReferenceType())
5134 VDType = CGF.getContext().getPointerType(VDType);
5136 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5139 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(VDType)),
5140 CGF.getPointerAlign());
5141 Pair.second.first = Replacement;
5142 Ptr = CGF.Builder.CreateLoad(Replacement);
5143 Replacement =
Address(Ptr, CGF.ConvertTypeForMem(VDType),
5144 CGF.getContext().getDeclAlign(Pair.first));
5145 Pair.second.second = Replacement;
5147 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5148 Address Replacement(Ptr, CGF.ConvertTypeForMem(VDType),
5149 CGF.getContext().getDeclAlign(Pair.first));
5150 Pair.second.first = Replacement;
5154 if (
Data.Reductions) {
5156 for (
const auto &Pair : FirstprivatePtrs) {
5158 CGF.Builder.CreateLoad(Pair.second),
5159 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5160 CGF.getContext().getDeclAlign(Pair.first));
5161 FirstprivateScope.
addPrivate(Pair.first, Replacement);
5164 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5166 Data.ReductionCopies,
Data.ReductionOps);
5167 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
5169 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5175 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5177 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5180 CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF),
5181 CGF.getContext().VoidPtrTy,
5182 CGF.getContext().getPointerType(
5183 Data.ReductionCopies[Cnt]->getType()),
5184 Data.ReductionCopies[Cnt]->getExprLoc()),
5185 CGF.ConvertTypeForMem(
Data.ReductionCopies[Cnt]->getType()),
5186 Replacement.getAlignment());
5192 (void)
Scope.Privatize();
5198 auto IPriv =
C->privates().begin();
5199 auto IRed =
C->reduction_ops().begin();
5200 auto ITD =
C->taskgroup_descriptors().begin();
5201 for (
const Expr *Ref :
C->varlist()) {
5202 InRedVars.emplace_back(Ref);
5203 InRedPrivs.emplace_back(*IPriv);
5204 InRedOps.emplace_back(*IRed);
5205 TaskgroupDescriptors.emplace_back(*ITD);
5206 std::advance(IPriv, 1);
5207 std::advance(IRed, 1);
5208 std::advance(ITD, 1);
5214 if (!InRedVars.empty()) {
5216 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5224 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5226 llvm::Value *ReductionsPtr;
5227 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5228 ReductionsPtr = CGF.EmitLoadOfScalar(CGF.EmitLValue(TRExpr),
5229 TRExpr->getExprLoc());
5231 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5233 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5236 CGF.EmitScalarConversion(
5237 Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy,
5238 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
5239 InRedPrivs[Cnt]->getExprLoc()),
5240 CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()),
5241 Replacement.getAlignment());
5254 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5255 S, *I, *PartId, *TaskT, EKind,
CodeGen,
Data.Tied,
Data.NumberOfParts);
5256 OMPLexicalScope
Scope(*
this, S, std::nullopt,
5259 TaskGen(*
this, OutlinedFn,
Data);
5276 QualType ElemType =
C.getBaseElementType(Ty);
5286 Data.FirstprivateVars.emplace_back(OrigRef);
5287 Data.FirstprivateCopies.emplace_back(PrivateRef);
5288 Data.FirstprivateInits.emplace_back(InitRef);
5301 auto PartId = std::next(I);
5302 auto TaskT = std::next(I, 4);
5305 Data.Final.setInt(
false);
5308 auto IRef =
C->varlist_begin();
5309 auto IElemInitRef =
C->inits().begin();
5310 for (
auto *IInit :
C->private_copies()) {
5311 Data.FirstprivateVars.push_back(*IRef);
5312 Data.FirstprivateCopies.push_back(IInit);
5313 Data.FirstprivateInits.push_back(*IElemInitRef);
5321 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5322 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5323 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5324 Data.ReductionOps.append(
C->reduction_ops().begin(),
5325 C->reduction_ops().end());
5326 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5327 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5342 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5344 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5356 if (!isa_and_nonnull<llvm::ConstantPointerNull>(
5359 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5366 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, BPVD, PVD, SVD, MVD, EKind,
5370 if (!
Data.FirstprivateVars.empty()) {
5371 enum { PrivatesParam = 2, CopyFnParam = 3 };
5372 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5374 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5380 CallArgs.push_back(PrivatesPtr);
5381 ParamTypes.push_back(PrivatesPtr->getType());
5382 for (
const Expr *E :
Data.FirstprivateVars) {
5385 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
5386 ".firstpriv.ptr.addr");
5387 PrivatePtrs.emplace_back(VD, PrivatePtr);
5389 ParamTypes.push_back(PrivatePtr.
getType());
5391 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5393 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5394 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5395 for (
const auto &Pair : PrivatePtrs) {
5397 CGF.Builder.CreateLoad(Pair.second),
5398 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5399 CGF.getContext().getDeclAlign(Pair.first));
5400 Scope.addPrivate(Pair.first, Replacement);
5403 CGF.processInReduction(S,
Data, CGF, CS,
Scope);
5406 CGF.GetAddrOfLocalVar(BPVD), 0);
5408 CGF.GetAddrOfLocalVar(PVD), 0);
5409 InputInfo.
SizesArray = CGF.Builder.CreateConstArrayGEP(
5410 CGF.GetAddrOfLocalVar(SVD), 0);
5413 InputInfo.
MappersArray = CGF.Builder.CreateConstArrayGEP(
5414 CGF.GetAddrOfLocalVar(MVD), 0);
5418 OMPLexicalScope LexScope(CGF, S, OMPD_task,
false);
5420 if (CGF.CGM.getLangOpts().OpenMP >= 51 &&
5425 CGF.CGM.getOpenMPRuntime().emitThreadLimitClause(
5426 CGF, TL->getThreadLimit().front(), S.getBeginLoc());
5430 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5431 S, *I, *PartId, *TaskT, EKind,
CodeGen,
true,
5432 Data.NumberOfParts);
5433 llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<
OMPNowaitClause>() ? 1 : 0);
5437 CGM.getOpenMPRuntime().emitTaskCall(*
this, S.getBeginLoc(), S, OutlinedFn,
5438 SharedsTy, CapturedStruct, &IfCond,
Data);
5443 CodeGenFunction &CGF,
5447 if (
Data.Reductions) {
5449 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5451 Data.ReductionCopies,
Data.ReductionOps);
5454 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5468 Data.ReductionCopies[Cnt]->getType()),
5469 Data.ReductionCopies[Cnt]->getExprLoc()),
5471 Replacement.getAlignment());
5476 (void)
Scope.Privatize();
5482 auto IPriv =
C->privates().begin();
5483 auto IRed =
C->reduction_ops().begin();
5484 auto ITD =
C->taskgroup_descriptors().begin();
5485 for (
const Expr *Ref :
C->varlist()) {
5486 InRedVars.emplace_back(Ref);
5487 InRedPrivs.emplace_back(*IPriv);
5488 InRedOps.emplace_back(*IRed);
5489 TaskgroupDescriptors.emplace_back(*ITD);
5490 std::advance(IPriv, 1);
5491 std::advance(IRed, 1);
5492 std::advance(ITD, 1);
5496 if (!InRedVars.empty()) {
5498 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5506 llvm::Value *ReductionsPtr;
5507 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5511 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
5519 InRedPrivs[Cnt]->getExprLoc()),
5521 Replacement.getAlignment());
5535 const Expr *IfCond =
nullptr;
5536 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
5537 if (
C->getNameModifier() == OMPD_unknown ||
5538 C->getNameModifier() == OMPD_task) {
5539 IfCond =
C->getCondition();
5550 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
5551 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
5554 SharedsTy, CapturedStruct, IfCond,
5563 const OMPTaskyieldDirective &S) {
5564 CGM.getOpenMPRuntime().emitTaskyieldCall(*
this, S.getBeginLoc());
5571 bool IsFatal =
false;
5574 CGM.getOpenMPRuntime().emitErrorCall(*
this, S.getBeginLoc(), ME, IsFatal);
5578 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_barrier);
5586 CGM.getOpenMPRuntime().emitTaskwaitCall(*
this, S.getBeginLoc(),
Data);
5590 return T.clauses().empty();
5594 const OMPTaskgroupDirective &S) {
5595 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
5597 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
5598 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5602 auto BodyGenCB = [&,
this](InsertPointTy AllocaIP,
5603 InsertPointTy CodeGenIP) {
5605 EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5606 return llvm::Error::success();
5611 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5612 cantFail(OMPBuilder.createTaskgroup(
Builder, AllocaIP, BodyGenCB));
5618 if (
const Expr *E = S.getReductionRef()) {
5623 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5624 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5625 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5626 Data.ReductionOps.append(
C->reduction_ops().begin(),
5627 C->reduction_ops().end());
5628 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5629 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5631 llvm::Value *ReductionDesc =
5639 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5641 CGM.getOpenMPRuntime().emitTaskgroupRegion(*
this,
CodeGen, S.getBeginLoc());
5646 ? llvm::AtomicOrdering::NotAtomic
5647 : llvm::AtomicOrdering::AcquireRelease;
5648 CGM.getOpenMPRuntime().emitFlush(
5651 if (
const auto *FlushClause = S.getSingleClause<
OMPFlushClause>())
5653 FlushClause->varlist_end());
5656 S.getBeginLoc(), AO);
5666 for (
auto &Dep :
Data.Dependences) {
5667 Address DepAddr =
CGM.getOpenMPRuntime().emitDepobjDependClause(
5668 *
this, Dep, DC->getBeginLoc());
5674 CGM.getOpenMPRuntime().emitDestroyClause(*
this, DOLVal, DC->getBeginLoc());
5678 CGM.getOpenMPRuntime().emitUpdateClause(
5679 *
this, DOLVal, UC->getDependencyKind(), UC->getBeginLoc());
5698 if (
C->getModifier() != OMPC_REDUCTION_inscan)
5700 Shareds.append(
C->varlist_begin(),
C->varlist_end());
5701 Privates.append(
C->privates().begin(),
C->privates().end());
5702 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5703 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5704 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
5705 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
5706 CopyArrayTemps.append(
C->copy_array_temps().begin(),
5707 C->copy_array_temps().end());
5708 CopyArrayElems.append(
C->copy_array_elems().begin(),
5709 C->copy_array_elems().end());
5711 if (ParentDir.getDirectiveKind() == OMPD_simd ||
5753 : BreakContinueStack.back().ContinueBlock.getBlock());
5764 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
5765 const Expr *PrivateExpr = Privates[I];
5766 const Expr *TempExpr = CopyArrayTemps[I];
5778 CGM.getOpenMPRuntime().emitReduction(
5779 *
this, ParentDir.getEndLoc(), Privates, LHSs, RHSs, ReductionOps,
5782 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
5783 const Expr *PrivateExpr = Privates[I];
5790 const Expr *TempExpr = CopyArrayTemps[I];
5802 ? BreakContinueStack.back().ContinueBlock.getBlock()
5808 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
5814 .getIterationVariable()
5815 ->IgnoreParenImpCasts();
5818 IdxVal = Builder.CreateIntCast(IdxVal,
SizeTy,
false);
5819 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
5820 const Expr *PrivateExpr = Privates[I];
5821 const Expr *OrigExpr = Shareds[I];
5822 const Expr *CopyArrayElem = CopyArrayElems[I];
5823 OpaqueValueMapping IdxMapping(
5836 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
5839 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
5845 .getIterationVariable()
5846 ->IgnoreParenImpCasts();
5850 llvm::BasicBlock *ExclusiveExitBB =
nullptr;
5854 llvm::Value *Cmp =
Builder.CreateIsNull(IdxVal);
5855 Builder.CreateCondBr(Cmp, ExclusiveExitBB, ContBB);
5858 IdxVal =
Builder.CreateNUWSub(IdxVal, llvm::ConstantInt::get(
SizeTy, 1));
5860 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
5861 const Expr *PrivateExpr = Privates[I];
5862 const Expr *OrigExpr = Shareds[I];
5863 const Expr *CopyArrayElem = CopyArrayElems[I];
5872 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
5896 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
5904 bool HasLastprivateClause =
false;
5907 OMPLoopScope PreInitScope(*
this, S);
5912 llvm::BasicBlock *ContBlock =
nullptr;
5919 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
5933 ? S.getCombinedLowerBoundVariable()
5934 : S.getLowerBoundVariable())));
5938 ? S.getCombinedUpperBoundVariable()
5939 : S.getUpperBoundVariable())));
5950 CGM.getOpenMPRuntime().emitBarrierCall(
5951 *
this, S.getBeginLoc(), OMPD_unknown,
false,
5963 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
5966 llvm::Value *Chunk =
nullptr;
5969 ScheduleKind =
C->getDistScheduleKind();
5970 if (
const Expr *Ch =
C->getChunkSize()) {
5973 S.getIterationVariable()->getType(),
5978 CGM.getOpenMPRuntime().getDefaultDistScheduleAndChunk(
5979 *
this, S, ScheduleKind, Chunk);
5992 bool StaticChunked =
5996 Chunk !=
nullptr) ||
6001 StaticChunked ? Chunk :
nullptr);
6008 ? S.getCombinedEnsureUpperBound()
6009 : S.getEnsureUpperBound());
6012 ? S.getCombinedInit()
6017 ? S.getCombinedCond()
6021 Cond = S.getCombinedDistCond();
6053 [&S, &LoopScope,
Cond, IncExpr,
LoopExit, &CodeGenLoop,
6056 S, LoopScope.requiresCleanups(),
Cond, IncExpr,
6057 [&S,
LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
6058 CodeGenLoop(CGF, S, LoopExit);
6060 [&S, StaticChunked](CodeGenFunction &CGF) {
6061 if (StaticChunked) {
6062 CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound());
6063 CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound());
6064 CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound());
6065 CGF.EmitIgnoredExpr(S.getCombinedInit());
6075 const OMPLoopArguments LoopArguments = {
6076 LB.getAddress(), UB.getAddress(), ST.getAddress(), IL.getAddress(),
6078 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments,
6083 return CGF.
Builder.CreateIsNotNull(
6093 *
this, S, [IL, &S](CodeGenFunction &CGF) {
6094 return CGF.
Builder.CreateIsNotNull(
6099 if (HasLastprivateClause) {
6122 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
6131static llvm::Function *
6138 Fn->setDoesNotRecurse();
6142template <
typename T>
6144 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP,
6145 llvm::OpenMPIRBuilder &OMPBuilder) {
6147 unsigned NumLoops =
C->getNumLoops();
6151 for (
unsigned I = 0; I < NumLoops; I++) {
6152 const Expr *CounterVal =
C->getLoopData(I);
6157 StoreValues.emplace_back(StoreValue);
6159 OMPDoacrossKind<T> ODK;
6160 bool IsDependSource = ODK.isSource(
C);
6162 OMPBuilder.createOrderedDepend(CGF.
Builder, AllocaIP, NumLoops,
6163 StoreValues,
".cnt.addr", IsDependSource));
6167 if (
CGM.getLangOpts().OpenMPIRBuilder) {
6168 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
6169 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6174 assert(!S.hasAssociatedStmt() &&
"No associated statement must be in "
6175 "ordered depend|doacross construct.");
6187 auto FiniCB = [
this](InsertPointTy IP) {
6189 return llvm::Error::success();
6192 auto BodyGenCB = [&S,
C,
this](InsertPointTy AllocaIP,
6193 InsertPointTy CodeGenIP) {
6198 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
6199 Builder,
false,
".ordered.after");
6203 assert(S.getBeginLoc().isValid() &&
6204 "Outlined function call location must be valid.");
6207 OutlinedFn, CapturedVars);
6212 return llvm::Error::success();
6215 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6216 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
6217 OMPBuilder.createOrderedThreadsSimd(
Builder, BodyGenCB, FiniCB, !
C));
6224 assert(!S.hasAssociatedStmt() &&
6225 "No associated statement must be in ordered depend construct.");
6227 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6231 assert(!S.hasAssociatedStmt() &&
6232 "No associated statement must be in ordered doacross construct.");
6234 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6238 auto &&
CodeGen = [&S,
C,
this](CodeGenFunction &CGF,
6243 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
6245 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
6246 OutlinedFn, CapturedVars);
6252 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6253 CGM.getOpenMPRuntime().emitOrderedRegion(*
this,
CodeGen, S.getBeginLoc(), !
C);
6260 "DestType must have scalar evaluation kind.");
6261 assert(!Val.
isAggregate() &&
"Must be a scalar or complex.");
6272 "DestType must have complex evaluation kind.");
6281 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
6283 assert(Val.
isComplex() &&
"Must be a scalar or complex.");
6288 Val.
getComplexVal().first, SrcElementType, DestElementType, Loc);
6290 Val.
getComplexVal().second, SrcElementType, DestElementType, Loc);
6296 LValue LVal,
RValue RVal) {
6297 if (LVal.isGlobalReg())
6304 llvm::AtomicOrdering AO, LValue LVal,
6306 if (LVal.isGlobalReg())
6309 LVal, Loc, llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO),
6318 *
this, RVal, RValTy, LVal.
getType(), Loc)),
6327 llvm_unreachable(
"Must be a scalar or complex.");
6335 assert(
V->isLValue() &&
"V of 'omp atomic read' is not lvalue");
6336 assert(
X->isLValue() &&
"X of 'omp atomic read' is not lvalue");
6345 case llvm::AtomicOrdering::Acquire:
6346 case llvm::AtomicOrdering::AcquireRelease:
6347 case llvm::AtomicOrdering::SequentiallyConsistent:
6349 llvm::AtomicOrdering::Acquire);
6351 case llvm::AtomicOrdering::Monotonic:
6352 case llvm::AtomicOrdering::Release:
6354 case llvm::AtomicOrdering::NotAtomic:
6355 case llvm::AtomicOrdering::Unordered:
6356 llvm_unreachable(
"Unexpected ordering.");
6363 llvm::AtomicOrdering AO,
const Expr *
X,
6366 assert(
X->isLValue() &&
"X of 'omp atomic write' is not lvalue");
6374 case llvm::AtomicOrdering::Release:
6375 case llvm::AtomicOrdering::AcquireRelease:
6376 case llvm::AtomicOrdering::SequentiallyConsistent:
6378 llvm::AtomicOrdering::Release);
6380 case llvm::AtomicOrdering::Acquire:
6381 case llvm::AtomicOrdering::Monotonic:
6383 case llvm::AtomicOrdering::NotAtomic:
6384 case llvm::AtomicOrdering::Unordered:
6385 llvm_unreachable(
"Unexpected ordering.");
6392 llvm::AtomicOrdering AO,
6398 if (BO == BO_Comma || !
Update.isScalar() || !
X.isSimple() ||
6400 (
Update.getScalarVal()->getType() !=
X.getAddress().getElementType())) ||
6401 !Context.getTargetInfo().hasBuiltinAtomic(
6402 Context.getTypeSize(
X.getType()), Context.toBits(
X.getAlignment())))
6403 return std::make_pair(
false,
RValue::get(
nullptr));
6406 if (
T->isIntegerTy())
6409 if (
T->isFloatingPointTy() && (BO == BO_Add || BO == BO_Sub))
6415 if (!CheckAtomicSupport(
Update.getScalarVal()->getType(), BO) ||
6416 !CheckAtomicSupport(
X.getAddress().getElementType(), BO))
6417 return std::make_pair(
false,
RValue::get(
nullptr));
6419 bool IsInteger =
X.getAddress().getElementType()->isIntegerTy();
6420 llvm::AtomicRMWInst::BinOp RMWOp;
6423 RMWOp = IsInteger ? llvm::AtomicRMWInst::Add : llvm::AtomicRMWInst::FAdd;
6427 return std::make_pair(
false,
RValue::get(
nullptr));
6428 RMWOp = IsInteger ? llvm::AtomicRMWInst::Sub : llvm::AtomicRMWInst::FSub;
6431 RMWOp = llvm::AtomicRMWInst::And;
6434 RMWOp = llvm::AtomicRMWInst::Or;
6437 RMWOp = llvm::AtomicRMWInst::Xor;
6441 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6443 : llvm::AtomicRMWInst::Max)
6445 : llvm::AtomicRMWInst::UMax);
6448 : llvm::AtomicRMWInst::FMax;
6452 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6454 : llvm::AtomicRMWInst::Min)
6456 : llvm::AtomicRMWInst::UMin);
6459 : llvm::AtomicRMWInst::FMin;
6462 RMWOp = llvm::AtomicRMWInst::Xchg;
6471 return std::make_pair(
false,
RValue::get(
nullptr));
6490 llvm_unreachable(
"Unsupported atomic update operation");
6492 llvm::Value *UpdateVal =
Update.getScalarVal();
6493 if (
auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
6495 UpdateVal = CGF.
Builder.CreateIntCast(
6496 IC,
X.getAddress().getElementType(),
6497 X.getType()->hasSignedIntegerRepresentation());
6499 UpdateVal = CGF.
Builder.CreateCast(llvm::Instruction::CastOps::UIToFP, IC,
6500 X.getAddress().getElementType());
6502 llvm::AtomicRMWInst *Res =
6519 if (
X.isGlobalReg()) {
6532 llvm::AtomicOrdering AO,
const Expr *
X,
6536 "Update expr in 'atomic update' must be a binary operator.");
6544 assert(
X->isLValue() &&
"X of 'omp atomic update' is not lvalue");
6551 auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](
RValue XRValue) {
6557 XLValue, ExprRValue, BOUE->getOpcode(),
IsXLHSInRHSPart, AO, Loc, Gen);
6564 case llvm::AtomicOrdering::Release:
6565 case llvm::AtomicOrdering::AcquireRelease:
6566 case llvm::AtomicOrdering::SequentiallyConsistent:
6568 llvm::AtomicOrdering::Release);
6570 case llvm::AtomicOrdering::Acquire:
6571 case llvm::AtomicOrdering::Monotonic:
6573 case llvm::AtomicOrdering::NotAtomic:
6574 case llvm::AtomicOrdering::Unordered:
6575 llvm_unreachable(
"Unexpected ordering.");
6593 llvm_unreachable(
"Must be a scalar or complex.");
6597 llvm::AtomicOrdering AO,
6602 assert(
X->isLValue() &&
"X of 'omp atomic capture' is not lvalue");
6603 assert(
V->isLValue() &&
"V of 'omp atomic capture' is not lvalue");
6612 "Update expr in 'atomic capture' must be a binary operator.");
6623 NewVValType = XRValExpr->
getType();
6625 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
6634 XLValue, ExprRValue, BOUE->getOpcode(),
IsXLHSInRHSPart, AO, Loc, Gen);
6640 NewVVal = Res.second;
6651 NewVValType =
X->getType().getNonReferenceType();
6653 X->getType().getNonReferenceType(), Loc);
6654 auto &&Gen = [&NewVVal, ExprRValue](
RValue XRValue) {
6660 XLValue, ExprRValue, BO_Assign,
false, AO,
6681 case llvm::AtomicOrdering::Release:
6683 llvm::AtomicOrdering::Release);
6685 case llvm::AtomicOrdering::Acquire:
6687 llvm::AtomicOrdering::Acquire);
6689 case llvm::AtomicOrdering::AcquireRelease:
6690 case llvm::AtomicOrdering::SequentiallyConsistent:
6692 CGF, {}, Loc, llvm::AtomicOrdering::AcquireRelease);
6694 case llvm::AtomicOrdering::Monotonic:
6696 case llvm::AtomicOrdering::NotAtomic:
6697 case llvm::AtomicOrdering::Unordered:
6698 llvm_unreachable(
"Unexpected ordering.");
6704 CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO,
6708 llvm::OpenMPIRBuilder &OMPBuilder =
6711 OMPAtomicCompareOp Op;
6715 Op = OMPAtomicCompareOp::EQ;
6718 Op = OMPAtomicCompareOp::MIN;
6721 Op = OMPAtomicCompareOp::MAX;
6724 llvm_unreachable(
"unsupported atomic compare binary operator");
6728 Address XAddr = XLVal.getAddress();
6730 auto EmitRValueWithCastIfNeeded = [&CGF, Loc](
const Expr *
X,
const Expr *E) {
6735 if (NewE->
getType() ==
X->getType())
6740 llvm::Value *EVal = EmitRValueWithCastIfNeeded(
X, E);
6741 llvm::Value *DVal = D ? EmitRValueWithCastIfNeeded(
X, D) :
nullptr;
6742 if (
auto *CI = dyn_cast<llvm::ConstantInt>(EVal))
6743 EVal = CGF.
Builder.CreateIntCast(
6744 CI, XLVal.getAddress().getElementType(),
6747 if (
auto *CI = dyn_cast<llvm::ConstantInt>(DVal))
6748 DVal = CGF.
Builder.CreateIntCast(
6749 CI, XLVal.getAddress().getElementType(),
6752 llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{
6754 X->getType()->hasSignedIntegerRepresentation(),
6755 X->getType().isVolatileQualified()};
6756 llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal;
6760 VOpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
6761 V->getType()->hasSignedIntegerRepresentation(),
6762 V->getType().isVolatileQualified()};
6767 ROpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
6772 if (FailAO == llvm::AtomicOrdering::NotAtomic) {
6775 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
6776 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
6779 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
6780 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
6785 llvm::AtomicOrdering AO,
6806 case OMPC_compare: {
6812 llvm_unreachable(
"Clause is not allowed in 'omp atomic'.");
6817 llvm::AtomicOrdering AO =
CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
6819 llvm::AtomicOrdering FailAO = llvm::AtomicOrdering::NotAtomic;
6820 bool MemOrderingSpecified =
false;
6822 AO = llvm::AtomicOrdering::SequentiallyConsistent;
6823 MemOrderingSpecified =
true;
6825 AO = llvm::AtomicOrdering::AcquireRelease;
6826 MemOrderingSpecified =
true;
6828 AO = llvm::AtomicOrdering::Acquire;
6829 MemOrderingSpecified =
true;
6831 AO = llvm::AtomicOrdering::Release;
6832 MemOrderingSpecified =
true;
6834 AO = llvm::AtomicOrdering::Monotonic;
6835 MemOrderingSpecified =
true;
6837 llvm::SmallSet<OpenMPClauseKind, 2> KindsEncountered;
6846 if (K == OMPC_seq_cst || K == OMPC_acq_rel || K == OMPC_acquire ||
6847 K == OMPC_release || K == OMPC_relaxed || K == OMPC_hint)
6850 KindsEncountered.insert(K);
6855 if (KindsEncountered.contains(OMPC_compare) &&
6856 KindsEncountered.contains(OMPC_capture))
6857 Kind = OMPC_compare;
6858 if (!MemOrderingSpecified) {
6859 llvm::AtomicOrdering DefaultOrder =
6860 CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
6861 if (DefaultOrder == llvm::AtomicOrdering::Monotonic ||
6862 DefaultOrder == llvm::AtomicOrdering::SequentiallyConsistent ||
6863 (DefaultOrder == llvm::AtomicOrdering::AcquireRelease &&
6864 Kind == OMPC_capture)) {
6866 }
else if (DefaultOrder == llvm::AtomicOrdering::AcquireRelease) {
6867 if (Kind == OMPC_unknown || Kind == OMPC_update || Kind == OMPC_write) {
6868 AO = llvm::AtomicOrdering::Release;
6869 }
else if (Kind == OMPC_read) {
6870 assert(Kind == OMPC_read &&
"Unexpected atomic kind.");
6871 AO = llvm::AtomicOrdering::Acquire;
6876 if (KindsEncountered.contains(OMPC_compare) &&
6877 KindsEncountered.contains(OMPC_fail)) {
6878 Kind = OMPC_compare;
6879 const auto *FailClause = S.getSingleClause<
OMPFailClause>();
6882 if (FailParameter == llvm::omp::OMPC_relaxed)
6883 FailAO = llvm::AtomicOrdering::Monotonic;
6884 else if (FailParameter == llvm::omp::OMPC_acquire)
6885 FailAO = llvm::AtomicOrdering::Acquire;
6886 else if (FailParameter == llvm::omp::OMPC_seq_cst)
6887 FailAO = llvm::AtomicOrdering::SequentiallyConsistent;
6894 S.getV(), S.getR(), S.getExpr(), S.getUpdateExpr(),
6895 S.getD(), S.getCondExpr(), S.isXLHSInRHSPart(),
6896 S.isFailOnly(), S.getBeginLoc());
6907 OMPLexicalScope
Scope(CGF, S, OMPD_target);
6910 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
6916 llvm::Function *Fn =
nullptr;
6917 llvm::Constant *FnID =
nullptr;
6919 const Expr *IfCond =
nullptr;
6921 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
6922 if (
C->getNameModifier() == OMPD_unknown ||
6923 C->getNameModifier() == OMPD_target) {
6924 IfCond =
C->getCondition();
6930 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device(
6933 Device.setPointerAndInt(
C->getDevice(),
C->getModifier());
6938 bool IsOffloadEntry =
true;
6942 IsOffloadEntry =
false;
6945 IsOffloadEntry =
false;
6947 if (
CGM.
getLangOpts().OpenMPOffloadMandatory && !IsOffloadEntry) {
6950 "No offloading entry generated while offloading is mandatory.");
6954 assert(CGF.
CurFuncDecl &&
"No parent declaration for target region!");
6955 StringRef ParentName;
6958 if (
const auto *D = dyn_cast<CXXConstructorDecl>(CGF.
CurFuncDecl))
6960 else if (
const auto *D = dyn_cast<CXXDestructorDecl>(CGF.
CurFuncDecl))
6969 OMPLexicalScope
Scope(CGF, S, OMPD_task);
6970 auto &&SizeEmitter =
6973 if (IsOffloadEntry) {
6974 OMPLoopScope(CGF, D);
6976 llvm::Value *NumIterations = CGF.
EmitScalarExpr(D.getNumIterations());
6977 NumIterations = CGF.
Builder.CreateIntCast(NumIterations, CGF.
Int64Ty,
6979 return NumIterations;
6997 CGF.
EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
7002 StringRef ParentName,
7008 llvm::Constant *
Addr;
7010 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7012 assert(Fn &&
Addr &&
"Target device function emission failed.");
7026 const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams);
7027 llvm::Function *OutlinedFn =
7035 const Expr *NumTeams = NT ? NT->getNumTeams().front() :
nullptr;
7036 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() :
nullptr;
7042 OMPTeamsScope
Scope(CGF, S);
7058 CGF.
EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt());
7063 [](CodeGenFunction &) {
return nullptr; });
7068 auto *CS = S.getCapturedStmt(OMPD_teams);
7095 llvm::Constant *
Addr;
7097 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7099 assert(Fn &&
Addr &&
"Target device function emission failed.");
7141 llvm::Constant *
Addr;
7143 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7145 assert(Fn &&
Addr &&
"Target device function emission failed.");
7187 llvm::Constant *
Addr;
7189 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7191 assert(Fn &&
Addr &&
"Target device function emission failed.");
7205 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7210 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7222 [](CodeGenFunction &) {
return nullptr; });
7227 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7232 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7244 [](CodeGenFunction &) {
return nullptr; });
7249 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7255 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7267 [](CodeGenFunction &) {
return nullptr; });
7272 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7278 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7285 CGF, OMPD_distribute, CodeGenDistribute,
false);
7291 [](CodeGenFunction &) {
return nullptr; });
7295 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7296 llvm::Value *
Device =
nullptr;
7297 llvm::Value *NumDependences =
nullptr;
7298 llvm::Value *DependenceList =
nullptr;
7306 if (!
Data.Dependences.empty()) {
7308 std::tie(NumDependences, DependenciesArray) =
7309 CGM.getOpenMPRuntime().emitDependClause(*
this,
Data.Dependences,
7318 "OMPNowaitClause clause is used separately in OMPInteropDirective.");
7321 if (!ItOMPInitClause.empty()) {
7324 llvm::Value *InteropvarPtr =
7326 llvm::omp::OMPInteropType InteropType =
7327 llvm::omp::OMPInteropType::Unknown;
7328 if (
C->getIsTarget()) {
7329 InteropType = llvm::omp::OMPInteropType::Target;
7331 assert(
C->getIsTargetSync() &&
7332 "Expected interop-type target/targetsync");
7333 InteropType = llvm::omp::OMPInteropType::TargetSync;
7335 OMPBuilder.createOMPInteropInit(
Builder, InteropvarPtr, InteropType,
7336 Device, NumDependences, DependenceList,
7337 Data.HasNowaitClause);
7341 if (!ItOMPDestroyClause.empty()) {
7344 llvm::Value *InteropvarPtr =
7346 OMPBuilder.createOMPInteropDestroy(
Builder, InteropvarPtr,
Device,
7347 NumDependences, DependenceList,
7348 Data.HasNowaitClause);
7351 auto ItOMPUseClause = S.getClausesOfKind<
OMPUseClause>();
7352 if (!ItOMPUseClause.empty()) {
7355 llvm::Value *InteropvarPtr =
7357 OMPBuilder.createOMPInteropUse(
Builder, InteropvarPtr,
Device,
7358 NumDependences, DependenceList,
7359 Data.HasNowaitClause);
7381 CGF, OMPD_distribute, CodeGenDistribute,
false);
7400 llvm::Constant *
Addr;
7402 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7404 assert(Fn &&
Addr &&
"Target device function emission failed.");
7433 CGF, OMPD_distribute, CodeGenDistribute,
false);
7452 llvm::Constant *
Addr;
7454 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7456 assert(Fn &&
Addr &&
"Target device function emission failed.");
7469 CGM.getOpenMPRuntime().emitCancellationPointCall(*
this, S.getBeginLoc(),
7474 const Expr *IfCond =
nullptr;
7475 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7476 if (
C->getNameModifier() == OMPD_unknown ||
7477 C->getNameModifier() == OMPD_cancel) {
7478 IfCond =
C->getCondition();
7482 if (
CGM.getLangOpts().OpenMPIRBuilder) {
7483 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7489 llvm::Value *IfCondition =
nullptr;
7493 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
7495 return Builder.restoreIP(AfterIP);
7499 CGM.getOpenMPRuntime().emitCancelCall(*
this, S.getBeginLoc(), IfCond,
7505 if (Kind == OMPD_parallel || Kind == OMPD_task ||
7506 Kind == OMPD_target_parallel || Kind == OMPD_taskloop ||
7507 Kind == OMPD_master_taskloop || Kind == OMPD_parallel_master_taskloop)
7509 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
7510 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
7511 Kind == OMPD_distribute_parallel_for ||
7512 Kind == OMPD_target_parallel_for ||
7513 Kind == OMPD_teams_distribute_parallel_for ||
7514 Kind == OMPD_target_teams_distribute_parallel_for);
7515 return OMPCancelStack.getExitBlock();
7520 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7521 CaptureDeviceAddrMap) {
7522 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7523 for (
const Expr *OrigVarIt :
C.varlist()) {
7525 if (!Processed.insert(OrigVD).second)
7532 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7537 "Base should be the current struct!");
7538 MatchingVD = ME->getMemberDecl();
7543 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7544 if (InitAddrIt == CaptureDeviceAddrMap.end())
7552 Address(InitAddrIt->second, Ty,
7554 assert(IsRegistered &&
"firstprivate var already registered as private");
7562 while (
const auto *OASE = dyn_cast<ArraySectionExpr>(
Base))
7563 Base = OASE->getBase()->IgnoreParenImpCasts();
7564 while (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(
Base))
7565 Base = ASE->getBase()->IgnoreParenImpCasts();
7571 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7572 CaptureDeviceAddrMap) {
7573 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7574 for (
const Expr *Ref :
C.varlist()) {
7576 if (!Processed.insert(OrigVD).second)
7582 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7587 "Base should be the current struct!");
7588 MatchingVD = ME->getMemberDecl();
7593 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7594 if (InitAddrIt == CaptureDeviceAddrMap.end())
7600 Address(InitAddrIt->second, Ty,
7613 (void)PrivateScope.
addPrivate(OrigVD, PrivAddr);
7626 bool PrivatizeDevicePointers =
false;
7628 bool &PrivatizeDevicePointers;
7631 explicit DevicePointerPrivActionTy(
bool &PrivatizeDevicePointers)
7632 : PrivatizeDevicePointers(PrivatizeDevicePointers) {}
7633 void Enter(CodeGenFunction &CGF)
override {
7634 PrivatizeDevicePointers =
true;
7637 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
7640 auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7641 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
7645 auto &&PrivCodeGen = [&](CodeGenFunction &CGF,
PrePostActionTy &Action) {
7647 PrivatizeDevicePointers =
false;
7653 if (PrivatizeDevicePointers) {
7667 std::optional<OpenMPDirectiveKind> CaptureRegion;
7668 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
7671 for (
const Expr *E :
C->varlist()) {
7673 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
7677 for (
const Expr *E :
C->varlist()) {
7679 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
7683 CaptureRegion = OMPD_unknown;
7686 OMPLexicalScope
Scope(CGF, S, CaptureRegion);
7698 OMPLexicalScope
Scope(CGF, S);
7707 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
7713 const Expr *IfCond =
nullptr;
7715 IfCond =
C->getCondition();
7726 CGM.getOpenMPRuntime().emitTargetDataCalls(*
this, S, IfCond,
Device, RCG,
7734 if (
CGM.getLangOpts().OMPTargetTriples.empty())
7738 const Expr *IfCond =
nullptr;
7740 IfCond =
C->getCondition();
7747 OMPLexicalScope
Scope(*
this, S, OMPD_task);
7748 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
7755 if (
CGM.getLangOpts().OMPTargetTriples.empty())
7759 const Expr *IfCond =
nullptr;
7761 IfCond =
C->getCondition();
7768 OMPLexicalScope
Scope(*
this, S, OMPD_task);
7769 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
7776 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
7804 llvm::Constant *
Addr;
7806 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7808 assert(Fn &&
Addr &&
"Target device function emission failed.");
7828 CGF, OMPD_target_parallel_for, S.
hasCancel());
7844 llvm::Constant *
Addr;
7846 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7848 assert(Fn &&
Addr &&
"Target device function emission failed.");
7883 llvm::Constant *
Addr;
7885 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7887 assert(Fn &&
Addr &&
"Target device function emission failed.");
7909 const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop);
7912 OMPLexicalScope
Scope(*
this, S, OMPD_taskloop,
false);
7917 const Expr *IfCond =
nullptr;
7918 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7919 if (
C->getNameModifier() == OMPD_unknown ||
7920 C->getNameModifier() == OMPD_taskloop) {
7921 IfCond =
C->getCondition();
7934 Data.Schedule.setInt(
false);
7937 (Clause->getModifier() == OMPC_GRAINSIZE_strict) ?
true :
false;
7940 Data.Schedule.setInt(
true);
7943 (Clause->getModifier() == OMPC_NUMTASKS_strict) ?
true :
false;
7957 llvm::BasicBlock *ContBlock =
nullptr;
7958 OMPLoopScope PreInitScope(CGF, S);
7959 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
7963 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock(
"taskloop.if.then");
7964 ContBlock = CGF.createBasicBlock(
"taskloop.if.end");
7965 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
7966 CGF.getProfileCount(&S));
7967 CGF.EmitBlock(ThenBlock);
7968 CGF.incrementProfileCounter(&S);
7971 (void)CGF.EmitOMPLinearClauseInit(S);
7975 enum { LowerBound = 5, UpperBound, Stride, LastIter };
7977 auto *LBP = std::next(I, LowerBound);
7978 auto *UBP = std::next(I, UpperBound);
7979 auto *STP = std::next(I, Stride);
7980 auto *LIP = std::next(I, LastIter);
7988 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
7989 CGF.EmitOMPLinearClause(S, LoopScope);
7990 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
7993 const Expr *IVExpr = S.getIterationVariable();
7995 CGF.EmitVarDecl(*IVDecl);
7996 CGF.EmitIgnoredExpr(S.getInit());
8001 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
8004 CGF.EmitIgnoredExpr(S.getCalcLastIteration());
8008 OMPLexicalScope
Scope(CGF, S, OMPD_taskloop,
false);
8018 [&S](CodeGenFunction &CGF) {
8019 emitOMPLoopBodyWithStopPoint(CGF, S,
8020 CodeGenFunction::JumpDest());
8022 [](CodeGenFunction &) {});
8027 CGF.EmitBranch(ContBlock);
8028 CGF.EmitBlock(ContBlock,
true);
8031 if (HasLastprivateClause) {
8032 CGF.EmitOMPLastprivateClauseFinal(
8034 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
8035 CGF.GetAddrOfLocalVar(*LIP),
false,
8036 (*LIP)->getType(), S.getBeginLoc())));
8039 CGF.EmitOMPLinearClauseFinal(S, [LIP, &S](CodeGenFunction &CGF) {
8040 return CGF.
Builder.CreateIsNotNull(
8042 (*LIP)->
getType(), S.getBeginLoc()));
8045 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
8046 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
8048 auto &&
CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
8050 OMPLoopScope PreInitScope(CGF, S);
8051 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S,
8052 OutlinedFn, SharedsTy,
8053 CapturedStruct, IfCond,
Data);
8055 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
8061 CGM.getOpenMPRuntime().emitTaskgroupRegion(
8063 [&S, &BodyGen, &TaskGen, &
Data](CodeGenFunction &CGF,
8083 OMPLexicalScope
Scope(*
this, S);
8095 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8096 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8107 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8108 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8119 OMPLexicalScope
Scope(*
this, S);
8120 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8131 OMPLexicalScope
Scope(*
this, S);
8132 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8138 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8143 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8144 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8156 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8161 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8162 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8174 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8179 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8180 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8192 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8197 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8198 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8212 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8216 const Expr *IfCond =
nullptr;
8218 IfCond =
C->getCondition();
8225 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8226 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8236 BindKind =
C->getBindKind();
8239 case OMPC_BIND_parallel:
8241 case OMPC_BIND_teams:
8243 case OMPC_BIND_thread:
8254 const auto *ForS = dyn_cast<ForStmt>(CS);
8265 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
8266 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_loop,
CodeGen);
8292 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
8297 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
8309 [](CodeGenFunction &) {
return nullptr; });
8314 std::string StatusMsg,
8318 StatusMsg +=
": DEVICE";
8320 StatusMsg +=
": HOST";
8327 llvm::dbgs() << StatusMsg <<
": " <<
FileName <<
": " << LineNo <<
"\n";
8350 CGF, OMPD_distribute, CodeGenDistribute,
false);
8379 CGF, OMPD_distribute, CodeGenDistribute,
false);
8412 llvm::Constant *
Addr;
8414 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8416 assert(Fn &&
Addr &&
8417 "Target device function emission failed for 'target teams loop'.");
8428 CGF, OMPD_target_parallel_loop,
false);
8444 llvm::Constant *
Addr;
8446 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8448 assert(Fn &&
Addr &&
"Target device function emission failed.");
8463 if (
const auto *SD = dyn_cast<OMPScanDirective>(&D)) {
8467 if (!D.hasAssociatedStmt() || !D.getAssociatedStmt())
8474 for (
const Expr *Ref :
C->varlist()) {
8478 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
8481 if (!CGF.LocalDeclMap.count(VD)) {
8493 if (
const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
8494 for (
const Expr *E : LD->counters()) {
8502 if (!CGF.LocalDeclMap.count(VD))
8507 if (!
C->getNumForLoops())
8509 for (
unsigned I = LD->getLoopsNumber(),
8510 E =
C->getLoopNumIterations().size();
8512 if (
const auto *VD = dyn_cast<OMPCapturedExprDecl>(
8515 if (!CGF.LocalDeclMap.count(VD))
8522 CGF.
EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
8525 if (D.getDirectiveKind() == OMPD_atomic ||
8526 D.getDirectiveKind() == OMPD_critical ||
8527 D.getDirectiveKind() == OMPD_section ||
8528 D.getDirectiveKind() == OMPD_master ||
8529 D.getDirectiveKind() == OMPD_masked ||
8530 D.getDirectiveKind() == OMPD_unroll ||
8531 D.getDirectiveKind() == OMPD_assume) {
8536 OMPSimdLexicalScope
Scope(*
this, D);
8537 CGM.getOpenMPRuntime().emitInlinedDirective(
8540 : 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 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 emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr)
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_tid, kmp_int32 num_threads) ...
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