31#include "llvm/ADT/SmallSet.h"
32#include "llvm/BinaryFormat/Dwarf.h"
33#include "llvm/Frontend/OpenMP/OMPConstants.h"
34#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
35#include "llvm/IR/Constants.h"
36#include "llvm/IR/DebugInfoMetadata.h"
37#include "llvm/IR/Instructions.h"
38#include "llvm/IR/IntrinsicInst.h"
39#include "llvm/IR/Metadata.h"
40#include "llvm/Support/AtomicOrdering.h"
41#include "llvm/Support/Debug.h"
45using namespace llvm::omp;
47#define TTL_CODEGEN_TYPE "target-teams-loop-codegen"
58 for (
const auto *
C : S.clauses()) {
60 if (
const auto *PreInit =
61 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
62 for (
const auto *I : PreInit->decls()) {
63 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
66 CodeGenFunction::AutoVarEmission Emission =
75 CodeGenFunction::OMPPrivateScope InlinedShareds;
77 static bool isCapturedVar(CodeGenFunction &CGF,
const VarDecl *VD) {
86 CodeGenFunction &CGF,
const OMPExecutableDirective &S,
87 const std::optional<OpenMPDirectiveKind> CapturedRegion = std::nullopt,
88 const bool EmitPreInitStmt =
true)
92 emitPreInitStmt(CGF, S);
95 assert(S.hasAssociatedStmt() &&
96 "Expected associated statement for inlined directive.");
97 const CapturedStmt *CS = S.getCapturedStmt(*CapturedRegion);
99 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
100 auto *VD =
C.getCapturedVar();
102 "Canonical decl must be captured.");
106 InlinedShareds.isGlobalVarCaptured(VD)),
111 (void)InlinedShareds.Privatize();
117class OMPParallelScope final :
public OMPLexicalScope {
118 bool EmitPreInitStmt(
const OMPExecutableDirective &S) {
126 OMPParallelScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
127 : OMPLexicalScope(CGF, S, std::nullopt,
128 EmitPreInitStmt(S)) {}
133class OMPTeamsScope final :
public OMPLexicalScope {
134 bool EmitPreInitStmt(
const OMPExecutableDirective &S) {
141 OMPTeamsScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
142 : OMPLexicalScope(CGF, S, std::nullopt,
143 EmitPreInitStmt(S)) {}
149 void emitPreInitStmt(CodeGenFunction &CGF,
const OMPLoopBasedDirective &S) {
150 const Stmt *PreInits;
151 CodeGenFunction::OMPMapVars PreCondVars;
152 if (
auto *LD = dyn_cast<OMPLoopDirective>(&S)) {
153 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
154 for (
const auto *E : LD->counters()) {
161 for (
const auto *
C : LD->getClausesOfKind<OMPPrivateClause>()) {
162 for (
const Expr *IRef :
C->varlist()) {
165 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
166 QualType OrigVDTy = OrigVD->getType().getNonReferenceType();
176 (void)PreCondVars.
apply(CGF);
178 (void)OMPLoopBasedDirective::doForAllLoops(
179 LD->getInnermostCapturedStmt()->getCapturedStmt(),
180 true, LD->getLoopsNumber(),
181 [&CGF](
unsigned Cnt,
const Stmt *CurStmt) {
182 if (const auto *CXXFor = dyn_cast<CXXForRangeStmt>(CurStmt)) {
183 if (const Stmt *Init = CXXFor->getInit())
185 CGF.EmitStmt(CXXFor->getRangeStmt());
186 CGF.EmitStmt(CXXFor->getEndStmt());
190 PreInits = LD->getPreInits();
191 }
else if (
const auto *
Tile = dyn_cast<OMPTileDirective>(&S)) {
192 PreInits =
Tile->getPreInits();
193 }
else if (
const auto *Stripe = dyn_cast<OMPStripeDirective>(&S)) {
194 PreInits = Stripe->getPreInits();
195 }
else if (
const auto *Unroll = dyn_cast<OMPUnrollDirective>(&S)) {
196 PreInits = Unroll->getPreInits();
197 }
else if (
const auto *Reverse = dyn_cast<OMPReverseDirective>(&S)) {
198 PreInits = Reverse->getPreInits();
199 }
else if (
const auto *Interchange =
200 dyn_cast<OMPInterchangeDirective>(&S)) {
201 PreInits = Interchange->getPreInits();
203 llvm_unreachable(
"Unknown loop-based directive kind.");
205 doEmitPreinits(PreInits);
212 const Stmt *PreInits;
213 if (
const auto *Fuse = dyn_cast<OMPFuseDirective>(&S)) {
214 PreInits = Fuse->getPreInits();
217 "Unknown canonical loop sequence transform directive kind.");
219 doEmitPreinits(PreInits);
222 void doEmitPreinits(
const Stmt *PreInits) {
228 if (
auto *PreInitCompound = dyn_cast<CompoundStmt>(PreInits))
229 llvm::append_range(PreInitStmts, PreInitCompound->body());
231 PreInitStmts.push_back(PreInits);
233 for (
const Stmt *S : PreInitStmts) {
236 if (
auto *PreInitDecl = dyn_cast<DeclStmt>(S)) {
237 for (
Decl *I : PreInitDecl->decls())
249 emitPreInitStmt(CGF, S);
254 emitPreInitStmt(CGF, S);
259 CodeGenFunction::OMPPrivateScope InlinedShareds;
261 static bool isCapturedVar(CodeGenFunction &CGF,
const VarDecl *VD) {
269 OMPSimdLexicalScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
271 InlinedShareds(CGF) {
272 for (
const auto *
C : S.clauses()) {
273 if (const auto *CPI = OMPClauseWithPreInit::get(C)) {
274 if (const auto *PreInit =
275 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
276 for (const auto *I : PreInit->decls()) {
277 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
278 CGF.EmitVarDecl(cast<VarDecl>(*I));
280 CodeGenFunction::AutoVarEmission Emission =
281 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
282 CGF.EmitAutoVarCleanups(Emission);
286 }
else if (
const auto *UDP = dyn_cast<OMPUseDevicePtrClause>(
C)) {
287 for (
const Expr *E : UDP->varlist()) {
289 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
292 }
else if (
const auto *UDP = dyn_cast<OMPUseDeviceAddrClause>(
C)) {
293 for (
const Expr *E : UDP->varlist()) {
295 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
302 if (
const auto *TG = dyn_cast<OMPTaskgroupDirective>(&S)) {
303 if (
const Expr *E = TG->getReductionRef())
308 llvm::DenseSet<CanonicalDeclPtr<const Decl>> CopyArrayTemps;
309 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
310 if (C->getModifier() != OMPC_REDUCTION_inscan)
312 for (const Expr *E : C->copy_array_temps())
313 CopyArrayTemps.insert(cast<DeclRefExpr>(E)->getDecl());
315 const auto *CS = cast_or_null<CapturedStmt>(S.getAssociatedStmt());
318 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
319 auto *VD =
C.getCapturedVar();
320 if (CopyArrayTemps.contains(VD))
323 "Canonical decl must be captured.");
324 DeclRefExpr DRE(CGF.
getContext(),
const_cast<VarDecl *
>(VD),
325 isCapturedVar(CGF, VD) ||
327 InlinedShareds.isGlobalVarCaptured(VD)),
335 (void)InlinedShareds.Privatize();
346 if (Kind != OMPD_loop)
351 BindKind =
C->getBindKind();
354 case OMPC_BIND_parallel:
356 case OMPC_BIND_teams:
357 return OMPD_distribute;
358 case OMPC_BIND_thread:
370 if (
const auto *OrigDRE = dyn_cast<DeclRefExpr>(E)) {
371 if (
const auto *OrigVD = dyn_cast<VarDecl>(OrigDRE->getDecl())) {
372 OrigVD = OrigVD->getCanonicalDecl();
378 OrigDRE->getType(),
VK_LValue, OrigDRE->getExprLoc());
387 llvm::Value *Size =
nullptr;
388 auto SizeInChars =
C.getTypeSizeInChars(Ty);
389 if (SizeInChars.isZero()) {
397 SizeInChars =
C.getTypeSizeInChars(Ty);
398 if (SizeInChars.isZero())
399 return llvm::ConstantInt::get(
SizeTy, 0);
400 return Builder.CreateNUWMul(Size,
CGM.getSize(SizeInChars));
402 return CGM.getSize(SizeInChars);
412 I != E; ++I, ++CurField, ++CurCap) {
413 if (CurField->hasCapturedVLAType()) {
416 CapturedVars.push_back(Val);
417 }
else if (CurCap->capturesThis()) {
418 CapturedVars.push_back(CXXThisValue);
419 }
else if (CurCap->capturesVariableByCopy()) {
424 if (!CurField->getType()->isAnyPointerType()) {
428 Twine(CurCap->getCapturedVar()->getName(),
".casted"));
444 CapturedVars.push_back(CV);
446 assert(CurCap->capturesVariable() &&
"Expected capture by reference.");
467 if (
T->isLValueReferenceType())
468 return C.getLValueReferenceType(
471 if (
T->isPointerType())
473 if (
const ArrayType *A =
T->getAsArrayTypeUnsafe()) {
474 if (
const auto *VLA = dyn_cast<VariableArrayType>(A))
476 if (!A->isVariablyModifiedType())
477 return C.getCanonicalType(
T);
479 return C.getCanonicalParamType(
T);
484struct FunctionOptions {
486 const CapturedStmt *S =
nullptr;
489 const bool UIntPtrCastRequired =
true;
492 const bool RegisterCastedArgsOnly =
false;
494 const StringRef FunctionName;
497 const bool IsDeviceKernel =
false;
498 explicit FunctionOptions(
const CapturedStmt *S,
bool UIntPtrCastRequired,
499 bool RegisterCastedArgsOnly, StringRef FunctionName,
500 SourceLocation Loc,
bool IsDeviceKernel)
501 : S(S), UIntPtrCastRequired(UIntPtrCastRequired),
502 RegisterCastedArgsOnly(UIntPtrCastRequired && RegisterCastedArgsOnly),
503 FunctionName(FunctionName), Loc(Loc), IsDeviceKernel(IsDeviceKernel) {}
509 llvm::MapVector<
const Decl *, std::pair<const VarDecl *, Address>>
511 llvm::DenseMap<
const Decl *, std::pair<const Expr *, llvm::Value *>>
513 llvm::Value *&CXXThisValue,
const FunctionOptions &FO) {
516 assert(CD->
hasBody() &&
"missing CapturedDecl body");
518 CXXThisValue =
nullptr;
530 if (!FO.UIntPtrCastRequired) {
550 if (FO.UIntPtrCastRequired &&
551 ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) ||
552 I->capturesVariableArrayType()))
555 if (I->capturesVariable() || I->capturesVariableByCopy()) {
556 CapVar = I->getCapturedVar();
558 }
else if (I->capturesThis()) {
561 assert(I->capturesVariableArrayType());
564 if (ArgType->isVariablyModifiedType())
571 }
else if (DebugFunctionDecl && (CapVar || I->capturesThis())) {
573 Ctx, DebugFunctionDecl,
574 CapVar ? CapVar->
getBeginLoc() : FD->getBeginLoc(),
575 CapVar ? CapVar->
getLocation() : FD->getLocation(), II, ArgType,
581 Args.emplace_back(Arg);
583 TargetArgs.emplace_back(
584 FO.UIntPtrCastRequired
605 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
609 F->setDoesNotThrow();
610 F->setDoesNotRecurse();
614 F->removeFnAttr(llvm::Attribute::NoInline);
615 F->addFnAttr(llvm::Attribute::AlwaysInline);
618 F->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
622 FO.UIntPtrCastRequired ? FO.Loc : FO.S->
getBeginLoc(),
623 FO.UIntPtrCastRequired ? FO.Loc
630 if (!FO.UIntPtrCastRequired && Args[Cnt] != TargetArgs[Cnt]) {
638 if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
639 const VarDecl *CurVD = I->getCapturedVar();
640 if (!FO.RegisterCastedArgsOnly)
641 LocalAddrs.insert({Args[Cnt], {CurVD, LocalAddr}});
649 if (FD->hasCapturedVLAType()) {
650 if (FO.UIntPtrCastRequired) {
653 Args[Cnt]->getName(), ArgLVal),
658 VLASizes.try_emplace(Args[Cnt], VAT->
getSizeExpr(), ExprArg);
659 }
else if (I->capturesVariable()) {
660 const VarDecl *Var = I->getCapturedVar();
662 Address ArgAddr = ArgLVal.getAddress();
663 if (ArgLVal.getType()->isLValueReferenceType()) {
666 assert(ArgLVal.getType()->isPointerType());
668 ArgAddr, ArgLVal.getType()->castAs<
PointerType>());
670 if (!FO.RegisterCastedArgsOnly) {
674 }
else if (I->capturesVariableByCopy()) {
675 assert(!FD->getType()->isAnyPointerType() &&
676 "Not expecting a captured pointer.");
677 const VarDecl *Var = I->getCapturedVar();
678 LocalAddrs.insert({Args[Cnt],
679 {Var, FO.UIntPtrCastRequired
681 CGF, I->getLocation(), FD->getType(),
682 Args[Cnt]->getName(), ArgLVal)
683 : ArgLVal.getAddress()}});
686 assert(I->capturesThis());
688 LocalAddrs.insert({Args[Cnt], {
nullptr, ArgLVal.getAddress()}});
702 "CapturedStmtInfo should be set when generating the captured function");
705 bool NeedWrapperFunction =
708 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs,
710 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes,
713 llvm::raw_svector_ostream Out(Buffer);
716 bool IsDeviceKernel =
CGM.getOpenMPRuntime().isGPU() &&
718 D.getCapturedStmt(OMPD_target) == &S;
719 CodeGenFunction WrapperCGF(
CGM,
true);
720 llvm::Function *WrapperF =
nullptr;
721 if (NeedWrapperFunction) {
724 FunctionOptions WrapperFO(&S,
true,
731 WrapperCGF.CXXThisValue, WrapperFO);
734 FunctionOptions FO(&S, !NeedWrapperFunction,
false,
735 Out.str(), Loc, !NeedWrapperFunction && IsDeviceKernel);
737 *
this, WrapperArgs, WrapperLocalAddrs, WrapperVLASizes, CXXThisValue, FO);
739 for (
const auto &LocalAddrPair : WrapperLocalAddrs) {
740 if (LocalAddrPair.second.first) {
741 LocalScope.addPrivate(LocalAddrPair.second.first,
742 LocalAddrPair.second.second);
745 (void)LocalScope.Privatize();
746 for (
const auto &VLASizePair : WrapperVLASizes)
747 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
750 LocalScope.ForceCleanup();
752 if (!NeedWrapperFunction)
756 WrapperF->removeFromParent();
757 F->getParent()->getFunctionList().insertAfter(F->getIterator(), WrapperF);
760 auto *PI = F->arg_begin();
761 for (
const auto *Arg : Args) {
763 auto I = LocalAddrs.find(Arg);
764 if (I != LocalAddrs.end()) {
767 I->second.first ? I->second.first->getType() : Arg->getType(),
773 auto EI = VLASizes.find(Arg);
774 if (EI != VLASizes.end()) {
786 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
802 llvm::Value *NumElements =
emitArrayLength(ArrayTy, ElementTy, DestAddr);
809 DestBegin, NumElements);
814 llvm::Value *IsEmpty =
815 Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arraycpy.isempty");
816 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
819 llvm::BasicBlock *EntryBB =
Builder.GetInsertBlock();
824 llvm::PHINode *SrcElementPHI =
825 Builder.CreatePHI(SrcBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
826 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
831 llvm::PHINode *DestElementPHI =
Builder.CreatePHI(
832 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
833 DestElementPHI->addIncoming(DestBegin, EntryBB);
839 CopyGen(DestElementCurrent, SrcElementCurrent);
842 llvm::Value *DestElementNext =
844 1,
"omp.arraycpy.dest.element");
845 llvm::Value *SrcElementNext =
847 1,
"omp.arraycpy.src.element");
850 Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
851 Builder.CreateCondBr(Done, DoneBB, BodyBB);
852 DestElementPHI->addIncoming(DestElementNext,
Builder.GetInsertBlock());
853 SrcElementPHI->addIncoming(SrcElementNext,
Builder.GetInsertBlock());
863 const auto *BO = dyn_cast<BinaryOperator>(
Copy);
864 if (BO && BO->getOpcode() == BO_Assign) {
873 DestAddr, SrcAddr, OriginalType,
901 bool DeviceConstTarget =
getLangOpts().OpenMPIsTargetDevice &&
903 bool FirstprivateIsLastprivate =
false;
904 llvm::DenseMap<const VarDecl *, OpenMPLastprivateModifier> Lastprivates;
905 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
906 for (
const auto *D :
C->varlist())
907 Lastprivates.try_emplace(
911 llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
916 bool MustEmitFirstprivateCopy =
917 CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown;
918 for (
const auto *
C : D.getClausesOfKind<OMPFirstprivateClause>()) {
919 const auto *IRef =
C->varlist_begin();
920 const auto *InitsRef =
C->inits().begin();
921 for (
const Expr *IInit :
C->private_copies()) {
923 bool ThisFirstprivateIsLastprivate =
924 Lastprivates.count(OrigVD->getCanonicalDecl()) > 0;
927 if (!MustEmitFirstprivateCopy && !ThisFirstprivateIsLastprivate && FD &&
929 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
930 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
937 if (DeviceConstTarget && OrigVD->getType().isConstant(
getContext()) &&
939 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
940 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
945 FirstprivateIsLastprivate =
946 FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate;
947 if (EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()).second) {
967 assert(!CE &&
"Expected non-constant firstprivate.");
974 if (
Type->isArrayType()) {
990 RunCleanupsScope InitScope(*this);
992 setAddrOfLocalVar(VDInit, SrcElement);
993 EmitAnyExprToMem(Init, DestElement,
994 Init->getType().getQualifiers(),
996 LocalDeclMap.erase(VDInit);
1007 setAddrOfLocalVar(VDInit, OriginalAddr);
1009 LocalDeclMap.erase(VDInit);
1011 if (ThisFirstprivateIsLastprivate &&
1012 Lastprivates[OrigVD->getCanonicalDecl()] ==
1013 OMPC_LASTPRIVATE_conditional) {
1018 (*IRef)->getExprLoc());
1019 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1023 LocalDeclMap.erase(VD);
1024 setAddrOfLocalVar(VD, VDAddr);
1026 IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1028 assert(IsRegistered &&
1029 "firstprivate var already registered as private");
1037 return FirstprivateIsLastprivate && !EmittedAsFirstprivate.empty();
1045 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
1046 for (
const auto *
C : D.getClausesOfKind<OMPPrivateClause>()) {
1047 auto IRef =
C->varlist_begin();
1048 for (
const Expr *IInit :
C->private_copies()) {
1050 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
1056 assert(IsRegistered &&
"private var already registered as private");
1072 llvm::DenseSet<const VarDecl *> CopiedVars;
1073 llvm::BasicBlock *CopyBegin =
nullptr, *CopyEnd =
nullptr;
1075 auto IRef =
C->varlist_begin();
1076 auto ISrcRef =
C->source_exprs().begin();
1077 auto IDestRef =
C->destination_exprs().begin();
1078 for (
const Expr *AssignOp :
C->assignment_ops()) {
1087 getContext().getTargetInfo().isTLSSupported()) {
1089 "Copyin threadprivates should have been captured!");
1093 LocalDeclMap.erase(VD);
1097 :
CGM.GetAddrOfGlobal(VD),
1098 CGM.getTypes().ConvertTypeForMem(VD->
getType()),
1103 if (CopiedVars.size() == 1) {
1109 auto *MasterAddrInt =
Builder.CreatePtrToInt(
1111 auto *PrivateAddrInt =
Builder.CreatePtrToInt(
1114 Builder.CreateICmpNE(MasterAddrInt, PrivateAddrInt), CopyBegin,
1120 const auto *DestVD =
1141 bool HasAtLeastOneLastprivate =
false;
1143 llvm::DenseSet<const VarDecl *> SIMDLCVs;
1146 for (
const Expr *
C : LoopDirective->counters()) {
1151 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1152 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1153 HasAtLeastOneLastprivate =
true;
1156 const auto *IRef =
C->varlist_begin();
1157 const auto *IDestRef =
C->destination_exprs().begin();
1158 for (
const Expr *IInit :
C->private_copies()) {
1164 if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) {
1165 const auto *DestVD =
1170 (*IRef)->getType(),
VK_LValue, (*IRef)->getExprLoc());
1175 if (IInit && !SIMDLCVs.count(OrigVD->getCanonicalDecl())) {
1178 if (
C->getKind() == OMPC_LASTPRIVATE_conditional) {
1179 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1181 setAddrOfLocalVar(VD, VDAddr);
1187 bool IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1188 assert(IsRegistered &&
1189 "lastprivate var already registered as private");
1197 return HasAtLeastOneLastprivate;
1202 llvm::Value *IsLastIterCond) {
1211 llvm::BasicBlock *ThenBB =
nullptr;
1212 llvm::BasicBlock *DoneBB =
nullptr;
1213 if (IsLastIterCond) {
1217 llvm::any_of(D.getClausesOfKind<OMPLastprivateClause>(),
1218 [](
const OMPLastprivateClause *
C) {
1219 return C->getKind() == OMPC_LASTPRIVATE_conditional;
1221 CGM.getOpenMPRuntime().emitBarrierCall(*
this, D.getBeginLoc(),
1228 Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB);
1231 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1232 llvm::DenseMap<const VarDecl *, const Expr *> LoopCountersAndUpdates;
1233 if (
const auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) {
1234 auto IC = LoopDirective->counters().begin();
1235 for (
const Expr *F : LoopDirective->finals()) {
1239 AlreadyEmittedVars.insert(D);
1241 LoopCountersAndUpdates[D] = F;
1245 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1246 auto IRef =
C->varlist_begin();
1247 auto ISrcRef =
C->source_exprs().begin();
1248 auto IDestRef =
C->destination_exprs().begin();
1249 for (
const Expr *AssignOp :
C->assignment_ops()) {
1250 const auto *PrivateVD =
1253 const auto *CanonicalVD = PrivateVD->getCanonicalDecl();
1254 if (AlreadyEmittedVars.insert(CanonicalVD).second) {
1258 if (
const Expr *FinalExpr = LoopCountersAndUpdates.lookup(CanonicalVD))
1262 const auto *DestVD =
1266 if (
const auto *RefTy = PrivateVD->getType()->getAs<
ReferenceType>())
1268 Builder.CreateLoad(PrivateAddr),
1269 CGM.getTypes().ConvertTypeForMem(RefTy->getPointeeType()),
1270 CGM.getNaturalTypeAlignment(RefTy->getPointeeType()));
1272 if (
C->getKind() == OMPC_LASTPRIVATE_conditional)
1273 CGM.getOpenMPRuntime().emitLastprivateConditionalFinalUpdate(
1275 (*IRef)->getExprLoc());
1278 EmitOMPCopy(
Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp);
1284 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
1304 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1305 if (ForInscan != (
C->getModifier() == OMPC_REDUCTION_inscan))
1307 Shareds.append(
C->varlist_begin(),
C->varlist_end());
1308 Privates.append(
C->privates().begin(),
C->privates().end());
1309 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1310 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1311 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1312 if (
C->getModifier() == OMPC_REDUCTION_task) {
1313 Data.ReductionVars.append(
C->privates().begin(),
C->privates().end());
1314 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
1315 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
1316 Data.ReductionOps.append(
C->reduction_ops().begin(),
1317 C->reduction_ops().end());
1318 TaskLHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1319 TaskRHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1324 auto *ILHS = LHSs.begin();
1325 auto *IRHS = RHSs.begin();
1327 for (
const Expr *IRef : Shareds) {
1335 [&Emission](CodeGenFunction &CGF) {
1336 CGF.EmitAutoVarInit(Emission);
1344 assert(IsRegistered &&
"private var already registered as private");
1352 if (isaOMPArraySectionExpr &&
Type->isVariablyModifiedType()) {
1357 }
else if ((isaOMPArraySectionExpr &&
Type->isScalarType()) ||
1375 PrivateScope.
addPrivate(LHSVD, OriginalAddr);
1386 if (!
Data.ReductionVars.empty()) {
1388 Data.IsReductionWithTaskMod =
true;
1390 llvm::Value *ReductionDesc =
CGM.getOpenMPRuntime().emitTaskReductionInit(
1391 *
this, D.getBeginLoc(), TaskLHSs, TaskRHSs,
Data);
1392 const Expr *TaskRedRef =
nullptr;
1403 case OMPD_parallel_for:
1406 case OMPD_parallel_master:
1410 case OMPD_parallel_sections:
1414 case OMPD_target_parallel:
1418 case OMPD_target_parallel_for:
1422 case OMPD_distribute_parallel_for:
1426 case OMPD_teams_distribute_parallel_for:
1428 .getTaskReductionRefExpr();
1430 case OMPD_target_teams_distribute_parallel_for:
1432 .getTaskReductionRefExpr();
1440 case OMPD_parallel_for_simd:
1442 case OMPD_taskyield:
1446 case OMPD_taskgroup:
1454 case OMPD_cancellation_point:
1456 case OMPD_target_data:
1457 case OMPD_target_enter_data:
1458 case OMPD_target_exit_data:
1460 case OMPD_taskloop_simd:
1461 case OMPD_master_taskloop:
1462 case OMPD_master_taskloop_simd:
1463 case OMPD_parallel_master_taskloop:
1464 case OMPD_parallel_master_taskloop_simd:
1465 case OMPD_distribute:
1466 case OMPD_target_update:
1467 case OMPD_distribute_parallel_for_simd:
1468 case OMPD_distribute_simd:
1469 case OMPD_target_parallel_for_simd:
1470 case OMPD_target_simd:
1471 case OMPD_teams_distribute:
1472 case OMPD_teams_distribute_simd:
1473 case OMPD_teams_distribute_parallel_for_simd:
1474 case OMPD_target_teams:
1475 case OMPD_target_teams_distribute:
1476 case OMPD_target_teams_distribute_parallel_for_simd:
1477 case OMPD_target_teams_distribute_simd:
1478 case OMPD_declare_target:
1479 case OMPD_end_declare_target:
1480 case OMPD_threadprivate:
1482 case OMPD_declare_reduction:
1483 case OMPD_declare_mapper:
1484 case OMPD_declare_simd:
1486 case OMPD_declare_variant:
1487 case OMPD_begin_declare_variant:
1488 case OMPD_end_declare_variant:
1491 llvm_unreachable(
"Unexpected directive with task reductions.");
1497 false, TaskRedRef->
getType());
1510 bool HasAtLeastOneReduction =
false;
1511 bool IsReductionWithTaskMod =
false;
1512 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1514 if (
C->getModifier() == OMPC_REDUCTION_inscan)
1516 HasAtLeastOneReduction =
true;
1517 Privates.append(
C->privates().begin(),
C->privates().end());
1518 LHSExprs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1519 RHSExprs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1520 IsPrivateVarReduction.append(
C->private_var_reduction_flags().begin(),
1521 C->private_var_reduction_flags().end());
1522 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1523 IsReductionWithTaskMod =
1524 IsReductionWithTaskMod ||
C->getModifier() == OMPC_REDUCTION_task;
1526 if (HasAtLeastOneReduction) {
1528 if (IsReductionWithTaskMod) {
1529 CGM.getOpenMPRuntime().emitTaskReductionFini(
1532 bool TeamsLoopCanBeParallel =
false;
1533 if (
auto *TTLD = dyn_cast<OMPTargetTeamsGenericLoopDirective>(&D))
1534 TeamsLoopCanBeParallel = TTLD->canBeParallelFor();
1535 bool WithNowait = D.getSingleClause<OMPNowaitClause>() ||
1537 TeamsLoopCanBeParallel || ReductionKind == OMPD_simd;
1538 bool SimpleReduction = ReductionKind == OMPD_simd;
1541 CGM.getOpenMPRuntime().emitReduction(
1542 *
this, D.getEndLoc(),
Privates, LHSExprs, RHSExprs, ReductionOps,
1543 {WithNowait, SimpleReduction, IsPrivateVarReduction, ReductionKind});
1552 llvm::BasicBlock *DoneBB =
nullptr;
1553 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1554 if (
const Expr *PostUpdate =
C->getPostUpdateExpr()) {
1556 if (llvm::Value *
Cond = CondGen(CGF)) {
1577 const OMPExecutableDirective &,
1578 llvm::SmallVectorImpl<llvm::Value *> &)>
1579 CodeGenBoundParametersTy;
1587 llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> PrivateDecls;
1588 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
1589 for (
const Expr *Ref :
C->varlist()) {
1590 if (!Ref->getType()->isScalarType())
1592 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1599 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
1600 for (
const Expr *Ref :
C->varlist()) {
1601 if (!Ref->getType()->isScalarType())
1603 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1610 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
1611 for (
const Expr *Ref :
C->varlist()) {
1612 if (!Ref->getType()->isScalarType())
1614 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1625 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
1626 for (
const Expr *Ref :
C->varlist()) {
1627 if (!Ref->getType()->isScalarType())
1629 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1636 CGF, S, PrivateDecls);
1642 const CodeGenBoundParametersTy &CodeGenBoundParameters) {
1643 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
1644 llvm::Value *NumThreads =
nullptr;
1653 llvm::Function *OutlinedFn =
1660 NumThreads = CGF.
EmitScalarExpr(NumThreadsClause->getNumThreads(),
1662 Modifier = NumThreadsClause->getModifier();
1663 if (
const auto *MessageClause = S.getSingleClause<OMPMessageClause>()) {
1664 Message = MessageClause->getMessageString();
1665 MessageLoc = MessageClause->getBeginLoc();
1667 if (
const auto *SeverityClause = S.getSingleClause<OMPSeverityClause>()) {
1668 Severity = SeverityClause->getSeverityKind();
1669 SeverityLoc = SeverityClause->getBeginLoc();
1672 CGF, NumThreads, NumThreadsClause->getBeginLoc(), Modifier, Severity,
1673 SeverityLoc, Message, MessageLoc);
1675 if (
const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>()) {
1678 CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getBeginLoc());
1680 const Expr *IfCond =
nullptr;
1681 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
1682 if (
C->getNameModifier() == OMPD_unknown ||
1683 C->getNameModifier() == OMPD_parallel) {
1684 IfCond =
C->getCondition();
1689 OMPParallelScope
Scope(CGF, S);
1695 CodeGenBoundParameters(CGF, S, CapturedVars);
1698 CapturedVars, IfCond, NumThreads,
1699 Modifier, Severity, Message);
1704 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
1706 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
1708 return !((AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc ||
1709 AA->getAllocatorType() == OMPAllocateDeclAttr::OMPNullMemAlloc) &&
1710 !AA->getAllocator());
1725 CGF, S.getBeginLoc(), OMPD_unknown,
false,
1731 CodeGenFunction &CGF,
const VarDecl *VD) {
1733 auto &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1745 Size = CGF.
Builder.CreateNUWAdd(
1747 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
1748 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
1754 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
1755 assert(AA->getAllocator() &&
1756 "Expected allocator expression for non-default allocator.");
1760 if (Allocator->getType()->isIntegerTy())
1761 Allocator = CGF.
Builder.CreateIntToPtr(Allocator,
CGM.VoidPtrTy);
1762 else if (Allocator->getType()->isPointerTy())
1766 llvm::Value *
Addr = OMPBuilder.createOMPAlloc(
1769 llvm::CallInst *FreeCI =
1770 OMPBuilder.createOMPFree(CGF.
Builder,
Addr, Allocator);
1784 if (
CGM.getLangOpts().OpenMPUseTLS &&
1785 CGM.getContext().getTargetInfo().isTLSSupported())
1788 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1793 llvm::ConstantInt *Size =
CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy));
1795 llvm::Twine CacheName = Twine(
CGM.getMangledName(VD)).concat(Suffix);
1797 llvm::CallInst *ThreadPrivateCacheCall =
1798 OMPBuilder.createCachedThreadPrivate(CGF.
Builder,
Data, Size, CacheName);
1806 llvm::raw_svector_ostream OS(Buffer);
1807 StringRef Sep = FirstSeparator;
1808 for (StringRef Part : Parts) {
1812 return OS.str().str();
1820 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
1821 "." + RegionName +
".after");
1837 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
1838 "." + RegionName +
".after");
1850 if (
CGM.getLangOpts().OpenMPIRBuilder) {
1851 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1853 llvm::Value *IfCond =
nullptr;
1858 llvm::Value *NumThreads =
nullptr;
1863 ProcBindKind ProcBind = OMP_PROC_BIND_default;
1864 if (
const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>())
1865 ProcBind = ProcBindClause->getProcBindKind();
1867 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1871 auto FiniCB = [
this](InsertPointTy IP) {
1873 return llvm::Error::success();
1880 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
1881 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
1892 auto BodyGenCB = [&,
this](InsertPointTy AllocaIP,
1893 InsertPointTy CodeGenIP) {
1895 *
this, ParallelRegionBodyStmt, AllocaIP, CodeGenIP,
"parallel");
1896 return llvm::Error::success();
1901 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
1903 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
1904 OMPBuilder.createParallel(
Builder, AllocaIP, BodyGenCB, PrivCB, FiniCB,
1905 IfCond, NumThreads, ProcBind, S.hasCancel()));
1919 CGF.
EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt());
1928 [](CodeGenFunction &) {
return nullptr; });
1940class OMPTransformDirectiveScopeRAII {
1941 OMPLoopScope *
Scope =
nullptr;
1945 OMPTransformDirectiveScopeRAII(
const OMPTransformDirectiveScopeRAII &) =
1947 OMPTransformDirectiveScopeRAII &
1948 operator=(
const OMPTransformDirectiveScopeRAII &) =
delete;
1952 if (
const auto *Dir = dyn_cast<OMPLoopBasedDirective>(S)) {
1953 Scope =
new OMPLoopScope(CGF, *Dir);
1956 }
else if (
const auto *Dir =
1957 dyn_cast<OMPCanonicalLoopSequenceTransformationDirective>(
1962 Scope =
new OMPLoopScope(CGF, *Dir);
1967 ~OMPTransformDirectiveScopeRAII() {
1978 int MaxLevel,
int Level = 0) {
1979 assert(Level < MaxLevel &&
"Too deep lookup during loop body codegen.");
1981 if (
const auto *CS = dyn_cast<CompoundStmt>(SimplifiedS)) {
1984 "LLVM IR generation of compound statement ('{}')");
1988 for (
const Stmt *CurStmt : CS->body())
1989 emitBody(CGF, CurStmt, NextLoop, MaxLevel, Level);
1992 if (SimplifiedS == NextLoop) {
1993 if (
auto *Dir = dyn_cast<OMPLoopTransformationDirective>(SimplifiedS))
1994 SimplifiedS = Dir->getTransformedStmt();
1995 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(SimplifiedS))
1996 SimplifiedS = CanonLoop->getLoopStmt();
1997 if (
const auto *For = dyn_cast<ForStmt>(SimplifiedS)) {
2001 "Expected canonical for loop or range-based for loop.");
2003 CGF.
EmitStmt(CXXFor->getLoopVarStmt());
2004 S = CXXFor->getBody();
2006 if (Level + 1 < MaxLevel) {
2007 NextLoop = OMPLoopDirective::tryToFindNextInnerLoop(
2009 emitBody(CGF, S, NextLoop, MaxLevel, Level + 1);
2020 for (
const Expr *UE : D.updates())
2027 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2028 for (
const Expr *UE :
C->updates())
2035 BreakContinueStack.push_back(BreakContinue(D,
LoopExit, Continue));
2036 for (
const Expr *E : D.finals_conditions()) {
2049 bool IsInscanRegion = InscanScope.
Privatize();
2050 if (IsInscanRegion) {
2060 if (EKind != OMPD_simd && !
getLangOpts().OpenMPSimd)
2069 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
2072 OMPLoopBasedDirective::tryToFindNextInnerLoop(
2074 D.getLoopsNumber());
2082 BreakContinueStack.pop_back();
2093 std::unique_ptr<CodeGenFunction::CGCapturedStmtInfo> CSI =
2094 std::make_unique<CodeGenFunction::CGCapturedStmtInfo>(*S);
2098 return {F, CapStruct.getPointer(
ParentCGF)};
2102static llvm::CallInst *
2107 EffectiveArgs.reserve(Args.size() + 1);
2108 llvm::append_range(EffectiveArgs, Args);
2109 EffectiveArgs.push_back(Cap.second);
2114llvm::CanonicalLoopInfo *
2116 assert(Depth == 1 &&
"Nested loops with OpenMPIRBuilder not yet implemented");
2142 const Stmt *SyntacticalLoop = S->getLoopStmt();
2153 const Stmt *BodyStmt;
2154 if (
const auto *For = dyn_cast<ForStmt>(SyntacticalLoop)) {
2155 if (
const Stmt *InitStmt = For->getInit())
2157 BodyStmt = For->getBody();
2158 }
else if (
const auto *RangeFor =
2159 dyn_cast<CXXForRangeStmt>(SyntacticalLoop)) {
2160 if (
const DeclStmt *RangeStmt = RangeFor->getRangeStmt())
2162 if (
const DeclStmt *BeginStmt = RangeFor->getBeginStmt())
2164 if (
const DeclStmt *EndStmt = RangeFor->getEndStmt())
2166 if (
const DeclStmt *LoopVarStmt = RangeFor->getLoopVarStmt())
2168 BodyStmt = RangeFor->getBody();
2170 llvm_unreachable(
"Expected for-stmt or range-based for-stmt");
2173 const CapturedStmt *DistanceFunc = S->getDistanceFunc();
2186 llvm::Value *DistVal =
Builder.CreateLoad(CountAddr,
".count");
2189 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2190 auto BodyGen = [&,
this](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP,
2191 llvm::Value *IndVar) {
2196 const DeclRefExpr *LoopVarRef = S->getLoopVarRef();
2204 return llvm::Error::success();
2207 llvm::CanonicalLoopInfo *
CL =
2208 cantFail(OMPBuilder.createCanonicalLoop(
Builder, BodyGen, DistVal));
2220 const Expr *IncExpr,
2221 const llvm::function_ref<
void(CodeGenFunction &)> BodyGen,
2222 const llvm::function_ref<
void(CodeGenFunction &)> PostIncGen) {
2232 const CapturedStmt *ICS = OMPED.getInnermostCapturedStmt();
2246 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
2247 if (RequiresCleanup)
2254 if (ExitBlock !=
LoopExit.getBlock()) {
2264 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
2272 BreakContinueStack.pop_back();
2283 bool HasLinears =
false;
2284 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2288 if (
const auto *Ref =
2307 if (
const auto *CS = cast_or_null<BinaryOperator>(
C->getCalcStep()))
2319 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2322 llvm::BasicBlock *DoneBB =
nullptr;
2324 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2325 auto IC =
C->varlist_begin();
2326 for (
const Expr *F :
C->finals()) {
2328 if (llvm::Value *
Cond = CondGen(*
this)) {
2340 (*IC)->getType(),
VK_LValue, (*IC)->getExprLoc());
2348 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
2360 llvm::APInt ClauseAlignment(64, 0);
2361 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
2364 ClauseAlignment = AlignmentCI->getValue();
2366 for (
const Expr *E : Clause->varlist()) {
2367 llvm::APInt Alignment(ClauseAlignment);
2368 if (Alignment == 0) {
2375 E->getType()->getPointeeType()))
2378 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2379 "alignment is not power of 2");
2380 if (Alignment != 0) {
2394 auto I = S.private_counters().begin();
2395 for (
const Expr *E : S.counters()) {
2401 LocalDeclMap.erase(PrivateVD);
2407 E->getType(),
VK_LValue, E->getExprLoc());
2415 for (
const auto *
C : S.getClausesOfKind<OMPOrderedClause>()) {
2416 if (!
C->getNumForLoops())
2418 for (
unsigned I = S.getLoopsNumber(), E =
C->getLoopNumIterations().size();
2424 if (DRE->refersToEnclosingVariableOrCapture()) {
2433 const Expr *
Cond, llvm::BasicBlock *TrueBlock,
2434 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
2442 for (
const Expr *I : S.inits()) {
2449 for (
const Expr *E : S.dependent_counters()) {
2452 assert(!E->getType().getNonReferenceType()->isRecordType() &&
2453 "dependent counter must not be an iterator.");
2457 (void)PreCondVars.
setVarAddr(CGF, VD, CounterAddr);
2459 (void)PreCondVars.
apply(CGF);
2460 for (
const Expr *E : S.dependent_inits()) {
2474 llvm::DenseSet<const VarDecl *> SIMDLCVs;
2478 for (
const Expr *
C : LoopDirective->counters()) {
2483 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2484 auto CurPrivate =
C->privates().begin();
2485 for (
const Expr *E :
C->varlist()) {
2487 const auto *PrivateVD =
2494 assert(IsRegistered &&
"linear var already registered as private");
2582 if (
const auto *CS = dyn_cast<CapturedStmt>(S))
2600 if (HasOrderedDirective)
2608 const Stmt *AssociatedStmt = D.getAssociatedStmt();
2612 if (
C->getKind() == OMPC_ORDER_concurrent)
2615 if ((EKind == OMPD_simd ||
2617 llvm::any_of(D.getClausesOfKind<OMPReductionClause>(),
2618 [](
const OMPReductionClause *
C) {
2619 return C->getModifier() == OMPC_REDUCTION_inscan;
2627 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2630 llvm::BasicBlock *DoneBB =
nullptr;
2631 auto IC = D.counters().begin();
2632 auto IPC = D.private_counters().begin();
2633 for (
const Expr *F : D.finals()) {
2636 const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
2638 OrigVD->hasGlobalStorage() || CED) {
2640 if (llvm::Value *
Cond = CondGen(*
this)) {
2688 auto &&ThenGen = [&S, &SimdInitGen, &BodyCodeGen](
CodeGenFunction &CGF,
2702 const Expr *IfCond =
nullptr;
2705 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
2707 (
C->getNameModifier() == OMPD_unknown ||
2708 C->getNameModifier() == OMPD_simd)) {
2709 IfCond =
C->getCondition();
2725 OMPLoopScope PreInitScope(CGF, S);
2747 llvm::BasicBlock *ContBlock =
nullptr;
2754 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
2761 const Expr *IVExpr = S.getIterationVariable();
2769 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
2784 CGF, S, CGF.
EmitLValue(S.getIterationVariable()));
2799 emitOMPLoopBodyWithStopPoint(CGF, S,
2800 CodeGenFunction::JumpDest());
2806 if (HasLastprivateClause)
2835 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(S.getRawStmt())) {
2836 if (
const Stmt *SyntacticalLoop = CanonLoop->getLoopStmt()) {
2837 for (
const Stmt *SubStmt : SyntacticalLoop->
children()) {
2840 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(SubStmt)) {
2855static llvm::MapVector<llvm::Value *, llvm::Value *>
2857 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars;
2859 llvm::APInt ClauseAlignment(64, 0);
2860 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
2863 ClauseAlignment = AlignmentCI->getValue();
2865 for (
const Expr *E : Clause->varlist()) {
2866 llvm::APInt Alignment(ClauseAlignment);
2867 if (Alignment == 0) {
2874 E->getType()->getPointeeType()))
2877 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2878 "alignment is not power of 2");
2880 AlignedVars[PtrValue] = CGF.
Builder.getInt64(Alignment.getSExtValue());
2890 bool UseOMPIRBuilder =
2892 if (UseOMPIRBuilder) {
2896 if (UseOMPIRBuilder) {
2897 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars =
2900 const Stmt *Inner = S.getRawStmt();
2901 llvm::CanonicalLoopInfo *CLI =
2902 CGF.EmitOMPCollapsedCanonicalLoopNest(Inner, 1);
2904 llvm::OpenMPIRBuilder &OMPBuilder =
2907 llvm::ConstantInt *Simdlen =
nullptr;
2914 llvm::ConstantInt *Safelen =
nullptr;
2921 llvm::omp::OrderKind Order = llvm::omp::OrderKind::OMP_ORDER_unknown;
2923 if (
C->getKind() == OpenMPOrderClauseKind::OMPC_ORDER_concurrent) {
2924 Order = llvm::omp::OrderKind::OMP_ORDER_concurrent;
2929 OMPBuilder.applySimd(CLI, AlignedVars,
2930 nullptr, Order, Simdlen, Safelen);
2937 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
2952 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
2965 OMPTransformDirectiveScopeRAII TileScope(*
this, &S);
2971 OMPTransformDirectiveScopeRAII StripeScope(*
this, &S);
2977 OMPTransformDirectiveScopeRAII ReverseScope(*
this, &S);
2984 OMPTransformDirectiveScopeRAII InterchangeScope(*
this, &S);
2990 OMPTransformDirectiveScopeRAII FuseScope(*
this, &S);
2995 bool UseOMPIRBuilder =
CGM.getLangOpts().OpenMPIRBuilder;
2997 if (UseOMPIRBuilder) {
2999 const Stmt *Inner = S.getRawStmt();
3007 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
3010 llvm::CanonicalLoopInfo *UnrolledCLI =
nullptr;
3014 OMPBuilder.unrollLoopFull(DL, CLI);
3016 uint64_t Factor = 0;
3017 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3018 Factor = FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
3019 assert(Factor >= 1 &&
"Only positive factors are valid");
3021 OMPBuilder.unrollLoopPartial(DL, CLI, Factor,
3022 NeedsUnrolledCLI ? &UnrolledCLI :
nullptr);
3024 OMPBuilder.unrollLoopHeuristic(DL, CLI);
3027 assert((!NeedsUnrolledCLI || UnrolledCLI) &&
3028 "NeedsUnrolledCLI implies UnrolledCLI to be set");
3045 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3047 FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
3048 assert(Factor >= 1 &&
"Only positive factors are valid");
3056void CodeGenFunction::EmitOMPOuterLoop(
3059 const CodeGenFunction::OMPLoopArguments &LoopArgs,
3064 const Expr *IVExpr = S.getIterationVariable();
3078 llvm::Value *BoolCondVal =
nullptr;
3079 if (!DynamicOrOrdered) {
3090 RT.
emitForNext(*
this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL,
3091 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST);
3096 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
3101 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
3102 if (ExitBlock !=
LoopExit.getBlock()) {
3110 if (DynamicOrOrdered)
3115 BreakContinueStack.push_back(BreakContinue(S, LoopExit, Continue));
3120 [&S, IsMonotonic, EKind](CodeGenFunction &CGF, PrePostActionTy &) {
3125 if (
const auto *
C = S.getSingleClause<OMPOrderClause>())
3126 if (
C->getKind() == OMPC_ORDER_concurrent)
3132 [&S, &LoopArgs, LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered,
3133 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
3134 SourceLocation Loc = S.getBeginLoc();
3140 CGF.EmitOMPInnerLoop(
3142 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
3143 CodeGenLoop(CGF, S, LoopExit);
3145 [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) {
3146 CodeGenOrdered(CGF, Loc, IVSize, IVSigned);
3151 BreakContinueStack.pop_back();
3152 if (!DynamicOrOrdered) {
3165 auto &&CodeGen = [DynamicOrOrdered, &S, &LoopArgs](CodeGenFunction &CGF) {
3166 if (!DynamicOrOrdered)
3167 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
3170 OMPCancelStack.emitExit(*
this, EKind, CodeGen);
3173void CodeGenFunction::EmitOMPForOuterLoop(
3174 const OpenMPScheduleTy &ScheduleKind,
bool IsMonotonic,
3176 const OMPLoopArguments &LoopArgs,
3178 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3184 LoopArgs.Chunk !=
nullptr)) &&
3185 "static non-chunked schedule does not need outer loop");
3239 const Expr *IVExpr = S.getIterationVariable();
3243 if (DynamicOrOrdered) {
3244 const std::pair<llvm::Value *, llvm::Value *> DispatchBounds =
3245 CGDispatchBounds(*
this, S, LoopArgs.LB, LoopArgs.UB);
3246 llvm::Value *LBVal = DispatchBounds.first;
3247 llvm::Value *UBVal = DispatchBounds.second;
3248 CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal,
3251 IVSigned, Ordered, DipatchRTInputValues);
3253 CGOpenMPRuntime::StaticRTInput StaticInit(
3254 IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
3255 LoopArgs.ST, LoopArgs.Chunk);
3261 auto &&CodeGenOrdered = [Ordered](CodeGenFunction &CGF, SourceLocation Loc,
3262 const unsigned IVSize,
3263 const bool IVSigned) {
3270 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST,
3271 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB);
3272 OuterLoopArgs.IncExpr = S.getInc();
3273 OuterLoopArgs.Init = S.getInit();
3274 OuterLoopArgs.Cond = S.getCond();
3275 OuterLoopArgs.NextLB = S.getNextLowerBound();
3276 OuterLoopArgs.NextUB = S.getNextUpperBound();
3277 OuterLoopArgs.DKind = LoopArgs.DKind;
3278 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
3280 if (DynamicOrOrdered) {
3286 const unsigned IVSize,
const bool IVSigned) {}
3288void CodeGenFunction::EmitOMPDistributeOuterLoop(
3293 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3300 const Expr *IVExpr = S.getIterationVariable();
3305 CGOpenMPRuntime::StaticRTInput StaticInit(
3306 IVSize, IVSigned,
false, LoopArgs.IL, LoopArgs.LB,
3307 LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
3314 IncExpr = S.getDistInc();
3316 IncExpr = S.getInc();
3321 OMPLoopArguments OuterLoopArgs;
3322 OuterLoopArgs.LB = LoopArgs.LB;
3323 OuterLoopArgs.UB = LoopArgs.UB;
3324 OuterLoopArgs.ST = LoopArgs.ST;
3325 OuterLoopArgs.IL = LoopArgs.IL;
3326 OuterLoopArgs.Chunk = LoopArgs.Chunk;
3328 ? S.getCombinedEnsureUpperBound()
3329 : S.getEnsureUpperBound();
3330 OuterLoopArgs.IncExpr = IncExpr;
3332 ? S.getCombinedInit()
3335 ? S.getCombinedCond()
3338 ? S.getCombinedNextLowerBound()
3339 : S.getNextLowerBound();
3341 ? S.getCombinedNextUpperBound()
3342 : S.getNextUpperBound();
3343 OuterLoopArgs.DKind = OMPD_distribute;
3345 EmitOMPOuterLoop(
false,
false, S,
3346 LoopScope, OuterLoopArgs, CodeGenLoopContent,
3350static std::pair<LValue, LValue>
3365 LValue PrevLB = CGF.
EmitLValue(LS.getPrevLowerBoundVariable());
3366 LValue PrevUB = CGF.
EmitLValue(LS.getPrevUpperBoundVariable());
3368 PrevLB, LS.getPrevLowerBoundVariable()->getExprLoc());
3370 PrevLBVal, LS.getPrevLowerBoundVariable()->getType(),
3371 LS.getIterationVariable()->getType(),
3372 LS.getPrevLowerBoundVariable()->getExprLoc());
3374 PrevUB, LS.getPrevUpperBoundVariable()->getExprLoc());
3376 PrevUBVal, LS.getPrevUpperBoundVariable()->getType(),
3377 LS.getIterationVariable()->getType(),
3378 LS.getPrevUpperBoundVariable()->getExprLoc());
3393static std::pair<llvm::Value *, llvm::Value *>
3398 const Expr *IVExpr = LS.getIterationVariable();
3404 llvm::Value *LBVal =
3406 llvm::Value *UBVal =
3408 return {LBVal, UBVal};
3417 llvm::Value *LBCast = CGF.
Builder.CreateIntCast(
3419 CapturedVars.push_back(LBCast);
3423 llvm::Value *UBCast = CGF.
Builder.CreateIntCast(
3425 CapturedVars.push_back(UBCast);
3436 bool HasCancel =
false;
3438 if (
const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
3439 HasCancel = D->hasCancel();
3440 else if (
const auto *D = dyn_cast<OMPDistributeParallelForDirective>(&S))
3441 HasCancel = D->hasCancel();
3442 else if (
const auto *D =
3443 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S))
3444 HasCancel = D->hasCancel();
3454 CGInlinedWorksharingLoop,
3464 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3465 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3474 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3475 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3483 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
3484 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
3494 llvm::Constant *
Addr;
3496 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
3498 assert(Fn &&
Addr &&
"Target device function emission failed.");
3510struct ScheduleKindModifiersTy {
3517 : Kind(Kind), M1(M1), M2(M2) {}
3533 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
3541 bool HasLastprivateClause;
3544 OMPLoopScope PreInitScope(*
this, S);
3549 llvm::BasicBlock *ContBlock =
nullptr;
3556 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
3563 bool Ordered =
false;
3564 if (
const auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) {
3565 if (OrderedClause->getNumForLoops())
3575 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*
this, S);
3576 LValue LB = Bounds.first;
3577 LValue UB = Bounds.second;
3591 CGM.getOpenMPRuntime().emitBarrierCall(
3592 *
this, S.getBeginLoc(), OMPD_unknown,
false,
3597 *
this, S,
EmitLValue(S.getIterationVariable()));
3604 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
3607 const Expr *ChunkExpr =
nullptr;
3609 if (
const auto *
C = S.getSingleClause<OMPScheduleClause>()) {
3610 ScheduleKind.
Schedule =
C->getScheduleKind();
3611 ScheduleKind.
M1 =
C->getFirstScheduleModifier();
3612 ScheduleKind.
M2 =
C->getSecondScheduleModifier();
3613 ChunkExpr =
C->getChunkSize();
3616 CGM.getOpenMPRuntime().getDefaultScheduleAndChunk(
3617 *
this, S, ScheduleKind.
Schedule, ChunkExpr);
3619 bool HasChunkSizeOne =
false;
3620 llvm::Value *Chunk =
nullptr;
3624 S.getIterationVariable()->getType(),
3628 llvm::APSInt EvaluatedChunk =
Result.Val.getInt();
3629 HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
3638 bool StaticChunkedOne =
3640 Chunk !=
nullptr) &&
3644 (ScheduleKind.
Schedule == OMPC_SCHEDULE_static &&
3645 !(ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
3646 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)) ||
3647 ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
3648 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
3650 Chunk !=
nullptr) ||
3651 StaticChunkedOne) &&
3661 if (
C->getKind() == OMPC_ORDER_concurrent)
3665 [IVSize, IVSigned, Ordered, IL, LB, UB, ST, StaticChunkedOne, Chunk,
3674 IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(),
3675 UB.getAddress(), ST.getAddress(),
3676 StaticChunkedOne ? Chunk :
nullptr);
3678 CGF, S.getBeginLoc(), EKind, ScheduleKind, StaticInit);
3680 if (!StaticChunkedOne)
3699 StaticChunkedOne ? S.getCombinedParForInDistCond()
3701 StaticChunkedOne ? S.getDistInc() : S.getInc(),
3702 [&S,
LoopExit](CodeGenFunction &CGF) {
3703 emitOMPLoopBodyWithStopPoint(CGF, S, LoopExit);
3705 [](CodeGenFunction &) {});
3709 auto &&
CodeGen = [&S](CodeGenFunction &CGF) {
3713 OMPCancelStack.emitExit(*
this, EKind,
CodeGen);
3720 LoopArguments.DKind = OMPD_for;
3721 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
3722 LoopArguments, CGDispatchBounds);
3726 return CGF.
Builder.CreateIsNotNull(
3732 ? OMPD_parallel_for_simd
3736 *
this, S, [IL, &S](CodeGenFunction &CGF) {
3737 return CGF.
Builder.CreateIsNotNull(
3741 if (HasLastprivateClause)
3747 return CGF.
Builder.CreateIsNotNull(
3758 return HasLastprivateClause;
3764static std::pair<LValue, LValue>
3778static std::pair<llvm::Value *, llvm::Value *>
3782 const Expr *IVExpr = LS.getIterationVariable();
3784 llvm::Value *LBVal = CGF.
Builder.getIntN(IVSize, 0);
3786 return {LBVal, UBVal};
3798 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
3799 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
3800 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
3805 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
3806 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
3807 "Only inscan reductions are expected.");
3808 Shareds.append(
C->varlist_begin(),
C->varlist_end());
3809 Privates.append(
C->privates().begin(),
C->privates().end());
3810 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
3811 CopyArrayTemps.append(
C->copy_array_temps().begin(),
3812 C->copy_array_temps().end());
3820 auto *ITA = CopyArrayTemps.begin();
3825 if (PrivateVD->getType()->isVariablyModifiedType()) {
3850 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
3851 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
3852 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
3859 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
3860 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
3861 "Only inscan reductions are expected.");
3862 Shareds.append(
C->varlist_begin(),
C->varlist_end());
3863 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
3864 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
3865 Privates.append(
C->privates().begin(),
C->privates().end());
3866 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
3867 CopyArrayElems.append(
C->copy_array_elems().begin(),
3868 C->copy_array_elems().end());
3872 llvm::Value *OMPLast = CGF.
Builder.CreateNSWSub(
3873 OMPScanNumIterations,
3874 llvm::ConstantInt::get(CGF.
SizeTy, 1,
false));
3875 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
3877 const Expr *OrigExpr = Shareds[I];
3878 const Expr *CopyArrayElem = CopyArrayElems[I];
3885 LValue SrcLVal = CGF.
EmitLValue(CopyArrayElem);
3887 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
3917 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
3918 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
3924 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
3925 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
3926 "Only inscan reductions are expected.");
3927 Privates.append(
C->privates().begin(),
C->privates().end());
3928 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
3929 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
3930 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
3931 CopyArrayElems.append(
C->copy_array_elems().begin(),
3932 C->copy_array_elems().end());
3947 auto &&
CodeGen = [&S, OMPScanNumIterations, &LHSs, &RHSs, &CopyArrayElems,
3954 llvm::BasicBlock *InputBB = CGF.Builder.GetInsertBlock();
3955 llvm::BasicBlock *LoopBB = CGF.createBasicBlock(
"omp.outer.log.scan.body");
3956 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
"omp.outer.log.scan.exit");
3958 CGF.CGM.getIntrinsic(llvm::Intrinsic::log2, CGF.DoubleTy);
3960 CGF.Builder.CreateUIToFP(OMPScanNumIterations, CGF.DoubleTy);
3961 llvm::Value *LogVal = CGF.EmitNounwindRuntimeCall(F, Arg);
3962 F = CGF.CGM.getIntrinsic(llvm::Intrinsic::ceil, CGF.DoubleTy);
3963 LogVal = CGF.EmitNounwindRuntimeCall(F, LogVal);
3964 LogVal = CGF.Builder.CreateFPToUI(LogVal, CGF.IntTy);
3965 llvm::Value *NMin1 = CGF.Builder.CreateNUWSub(
3966 OMPScanNumIterations, llvm::ConstantInt::get(CGF.SizeTy, 1));
3968 CGF.EmitBlock(LoopBB);
3969 auto *Counter = CGF.Builder.CreatePHI(CGF.IntTy, 2);
3971 auto *Pow2K = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
3972 Counter->addIncoming(llvm::ConstantInt::get(CGF.IntTy, 0), InputBB);
3973 Pow2K->addIncoming(llvm::ConstantInt::get(CGF.SizeTy, 1), InputBB);
3976 llvm::BasicBlock *InnerLoopBB =
3977 CGF.createBasicBlock(
"omp.inner.log.scan.body");
3978 llvm::BasicBlock *InnerExitBB =
3979 CGF.createBasicBlock(
"omp.inner.log.scan.exit");
3980 llvm::Value *CmpI = CGF.Builder.CreateICmpUGE(NMin1, Pow2K);
3981 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
3982 CGF.EmitBlock(InnerLoopBB);
3983 auto *IVal = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
3984 IVal->addIncoming(NMin1, LoopBB);
3987 auto *ILHS = LHSs.begin();
3988 auto *IRHS = RHSs.begin();
3989 for (
const Expr *CopyArrayElem : CopyArrayElems) {
3999 LHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4004 llvm::Value *OffsetIVal = CGF.Builder.CreateNUWSub(IVal, Pow2K);
4010 RHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4017 CGF.CGM.getOpenMPRuntime().emitReduction(
4018 CGF, S.getEndLoc(),
Privates, LHSs, RHSs, ReductionOps,
4022 llvm::Value *NextIVal =
4023 CGF.Builder.CreateNUWSub(IVal, llvm::ConstantInt::get(CGF.SizeTy, 1));
4024 IVal->addIncoming(NextIVal, CGF.Builder.GetInsertBlock());
4025 CmpI = CGF.Builder.CreateICmpUGE(NextIVal, Pow2K);
4026 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4027 CGF.EmitBlock(InnerExitBB);
4029 CGF.Builder.CreateNUWAdd(Counter, llvm::ConstantInt::get(CGF.IntTy, 1));
4030 Counter->addIncoming(
Next, CGF.Builder.GetInsertBlock());
4032 llvm::Value *NextPow2K =
4033 CGF.Builder.CreateShl(Pow2K, 1,
"",
true);
4034 Pow2K->addIncoming(NextPow2K, CGF.Builder.GetInsertBlock());
4035 llvm::Value *Cmp = CGF.Builder.CreateICmpNE(
Next, LogVal);
4036 CGF.Builder.CreateCondBr(Cmp, LoopBB, ExitBB);
4038 CGF.EmitBlock(ExitBB);
4044 CGF, S.getBeginLoc(), OMPD_unknown,
false,
4047 RegionCodeGenTy RCG(CodeGen);
4058 bool HasLastprivates;
4060 if (llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4061 [](
const OMPReductionClause *
C) {
4062 return C->getModifier() == OMPC_REDUCTION_inscan;
4066 OMPLoopScope LoopScope(CGF, S);
4069 const auto &&FirstGen = [&S, HasCancel, EKind](
CodeGenFunction &CGF) {
4078 const auto &&SecondGen = [&S, HasCancel, EKind,
4096 return HasLastprivates;
4109 if (
auto *SC = dyn_cast<OMPScheduleClause>(
C)) {
4114 switch (SC->getScheduleKind()) {
4115 case OMPC_SCHEDULE_auto:
4116 case OMPC_SCHEDULE_dynamic:
4117 case OMPC_SCHEDULE_runtime:
4118 case OMPC_SCHEDULE_guided:
4119 case OMPC_SCHEDULE_static:
4132static llvm::omp::ScheduleKind
4134 switch (ScheduleClauseKind) {
4136 return llvm::omp::OMP_SCHEDULE_Default;
4137 case OMPC_SCHEDULE_auto:
4138 return llvm::omp::OMP_SCHEDULE_Auto;
4139 case OMPC_SCHEDULE_dynamic:
4140 return llvm::omp::OMP_SCHEDULE_Dynamic;
4141 case OMPC_SCHEDULE_guided:
4142 return llvm::omp::OMP_SCHEDULE_Guided;
4143 case OMPC_SCHEDULE_runtime:
4144 return llvm::omp::OMP_SCHEDULE_Runtime;
4145 case OMPC_SCHEDULE_static:
4146 return llvm::omp::OMP_SCHEDULE_Static;
4148 llvm_unreachable(
"Unhandled schedule kind");
4155 bool HasLastprivates =
false;
4158 auto &&
CodeGen = [&S, &
CGM, HasCancel, &HasLastprivates,
4161 if (UseOMPIRBuilder) {
4162 bool NeedsBarrier = !S.getSingleClause<OMPNowaitClause>();
4164 llvm::omp::ScheduleKind SchedKind = llvm::omp::OMP_SCHEDULE_Default;
4165 llvm::Value *ChunkSize =
nullptr;
4166 if (
auto *SchedClause = S.getSingleClause<OMPScheduleClause>()) {
4169 if (
const Expr *ChunkSizeExpr = SchedClause->getChunkSize())
4174 const Stmt *Inner = S.getRawStmt();
4175 llvm::CanonicalLoopInfo *CLI =
4178 llvm::OpenMPIRBuilder &OMPBuilder =
4180 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4182 cantFail(OMPBuilder.applyWorkshareLoop(
4183 CGF.
Builder.getCurrentDebugLocation(), CLI, AllocaIP, NeedsBarrier,
4184 SchedKind, ChunkSize,
false,
4195 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
4200 if (!UseOMPIRBuilder) {
4202 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4214 bool HasLastprivates =
false;
4215 auto &&
CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
4222 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4223 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
4227 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4228 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_for);
4235 llvm::Value *
Init =
nullptr) {
4242void CodeGenFunction::EmitSections(
const OMPExecutableDirective &S) {
4243 const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4244 const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt);
4245 bool HasLastprivates =
false;
4247 auto &&CodeGen = [&S, CapturedStmt, CS, EKind,
4248 &HasLastprivates](CodeGenFunction &CGF, PrePostActionTy &) {
4249 const ASTContext &
C = CGF.getContext();
4250 QualType KmpInt32Ty =
4251 C.getIntTypeForBitwidth(32, 1);
4254 CGF.Builder.getInt32(0));
4255 llvm::ConstantInt *GlobalUBVal = CS !=
nullptr
4256 ? CGF.Builder.getInt32(CS->size() - 1)
4257 : CGF.Builder.getInt32(0);
4261 CGF.Builder.getInt32(1));
4263 CGF.Builder.getInt32(0));
4266 OpaqueValueExpr IVRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4267 CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
4268 OpaqueValueExpr UBRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4269 CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
4273 S.getBeginLoc(), FPOptionsOverride());
4277 S.getBeginLoc(),
true, FPOptionsOverride());
4278 auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
4290 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".omp.sections.exit");
4291 llvm::SwitchInst *SwitchStmt =
4292 CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.
getBeginLoc()),
4293 ExitBB, CS ==
nullptr ? 1 : CS->size());
4295 unsigned CaseNumber = 0;
4296 for (
const Stmt *SubStmt : CS->
children()) {
4297 auto CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4298 CGF.EmitBlock(CaseBB);
4299 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
4300 CGF.EmitStmt(SubStmt);
4301 CGF.EmitBranch(ExitBB);
4305 llvm::BasicBlock *CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4306 CGF.EmitBlock(CaseBB);
4307 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
4308 CGF.EmitStmt(CapturedStmt);
4309 CGF.EmitBranch(ExitBB);
4311 CGF.EmitBlock(ExitBB,
true);
4314 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
4315 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
4319 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
4323 CGF.EmitOMPPrivateClause(S, LoopScope);
4324 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(CGF, S, IV);
4325 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
4326 CGF.EmitOMPReductionClauseInit(S, LoopScope);
4327 (void)LoopScope.Privatize();
4329 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
4332 OpenMPScheduleTy ScheduleKind;
4333 ScheduleKind.
Schedule = OMPC_SCHEDULE_static;
4334 CGOpenMPRuntime::StaticRTInput StaticInit(
4335 32,
true,
false, IL.getAddress(),
4336 LB.getAddress(), UB.getAddress(), ST.getAddress());
4337 CGF.CGM.getOpenMPRuntime().emitForStaticInit(CGF, S.
getBeginLoc(), EKind,
4338 ScheduleKind, StaticInit);
4340 llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.
getBeginLoc());
4341 llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
4342 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
4343 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
4345 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.
getBeginLoc()), IV);
4347 CGF.EmitOMPInnerLoop(S,
false,
Cond, Inc, BodyGen,
4348 [](CodeGenFunction &) {});
4350 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
4351 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.
getEndLoc(),
4354 CGF.OMPCancelStack.emitExit(CGF, EKind, CodeGen);
4355 CGF.EmitOMPReductionClauseFinal(S, OMPD_parallel);
4358 return CGF.
Builder.CreateIsNotNull(
4363 if (HasLastprivates)
4370 bool HasCancel =
false;
4371 if (
auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
4372 HasCancel = OSD->hasCancel();
4373 else if (
auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
4374 HasCancel = OPSD->hasCancel();
4376 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_sections, CodeGen,
4381 if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) {
4399 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4404 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4405 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_scope,
CodeGen);
4408 if (!S.getSingleClause<OMPNowaitClause>()) {
4409 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_scope);
4416 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4417 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4418 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4419 using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
4421 auto FiniCB = [](InsertPointTy IP) {
4424 return llvm::Error::success();
4427 const CapturedStmt *ICS = S.getInnermostCapturedStmt();
4433 auto SectionCB = [
this, SubStmt](InsertPointTy AllocaIP,
4434 InsertPointTy CodeGenIP) {
4436 *
this, SubStmt, AllocaIP, CodeGenIP,
"section");
4437 return llvm::Error::success();
4439 SectionCBVector.push_back(SectionCB);
4442 auto SectionCB = [
this,
CapturedStmt](InsertPointTy AllocaIP,
4443 InsertPointTy CodeGenIP) {
4446 return llvm::Error::success();
4448 SectionCBVector.push_back(SectionCB);
4455 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
4456 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
4466 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4468 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4469 cantFail(OMPBuilder.createSections(
4470 Builder, AllocaIP, SectionCBVector, PrivCB, FiniCB, S.hasCancel(),
4471 S.getSingleClause<OMPNowaitClause>()));
4478 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4482 if (!S.getSingleClause<OMPNowaitClause>()) {
4483 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(),
4491 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4492 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4493 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4495 const Stmt *SectionRegionBodyStmt = S.getAssociatedStmt();
4496 auto FiniCB = [
this](InsertPointTy IP) {
4498 return llvm::Error::success();
4501 auto BodyGenCB = [SectionRegionBodyStmt,
this](InsertPointTy AllocaIP,
4502 InsertPointTy CodeGenIP) {
4504 *
this, SectionRegionBodyStmt, AllocaIP, CodeGenIP,
"section");
4505 return llvm::Error::success();
4510 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4511 cantFail(OMPBuilder.createSection(
Builder, BodyGenCB, FiniCB));
4531 CopyprivateVars.append(
C->varlist_begin(),
C->varlist_end());
4532 DestExprs.append(
C->destination_exprs().begin(),
4533 C->destination_exprs().end());
4534 SrcExprs.append(
C->source_exprs().begin(),
C->source_exprs().end());
4535 AssignmentOps.append(
C->assignment_ops().begin(),
4536 C->assignment_ops().end());
4545 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4550 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4551 CGM.getOpenMPRuntime().emitSingleRegion(*
this,
CodeGen, S.getBeginLoc(),
4552 CopyprivateVars, DestExprs,
4553 SrcExprs, AssignmentOps);
4557 if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) {
4558 CGM.getOpenMPRuntime().emitBarrierCall(
4559 *
this, S.getBeginLoc(),
4560 S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);
4575 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4576 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4577 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4579 const Stmt *MasterRegionBodyStmt = S.getAssociatedStmt();
4581 auto FiniCB = [
this](InsertPointTy IP) {
4583 return llvm::Error::success();
4586 auto BodyGenCB = [MasterRegionBodyStmt,
this](InsertPointTy AllocaIP,
4587 InsertPointTy CodeGenIP) {
4589 *
this, MasterRegionBodyStmt, AllocaIP, CodeGenIP,
"master");
4590 return llvm::Error::success();
4595 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4596 cantFail(OMPBuilder.createMaster(
Builder, BodyGenCB, FiniCB));
4611 Expr *Filter =
nullptr;
4613 Filter = FilterClause->getThreadID();
4619 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4620 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4621 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4623 const Stmt *MaskedRegionBodyStmt = S.getAssociatedStmt();
4624 const Expr *Filter =
nullptr;
4626 Filter = FilterClause->getThreadID();
4627 llvm::Value *FilterVal = Filter
4629 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
4631 auto FiniCB = [
this](InsertPointTy IP) {
4633 return llvm::Error::success();
4636 auto BodyGenCB = [MaskedRegionBodyStmt,
this](InsertPointTy AllocaIP,
4637 InsertPointTy CodeGenIP) {
4639 *
this, MaskedRegionBodyStmt, AllocaIP, CodeGenIP,
"masked");
4640 return llvm::Error::success();
4645 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
4646 OMPBuilder.createMasked(
Builder, BodyGenCB, FiniCB, FilterVal));
4657 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4658 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4659 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4661 const Stmt *CriticalRegionBodyStmt = S.getAssociatedStmt();
4662 const Expr *Hint =
nullptr;
4663 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4664 Hint = HintClause->getHint();
4669 llvm::Value *HintInst =
nullptr;
4674 auto FiniCB = [
this](InsertPointTy IP) {
4676 return llvm::Error::success();
4679 auto BodyGenCB = [CriticalRegionBodyStmt,
this](InsertPointTy AllocaIP,
4680 InsertPointTy CodeGenIP) {
4682 *
this, CriticalRegionBodyStmt, AllocaIP, CodeGenIP,
"critical");
4683 return llvm::Error::success();
4688 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4689 cantFail(OMPBuilder.createCritical(
Builder, BodyGenCB, FiniCB,
4690 S.getDirectiveName().getAsString(),
4699 CGF.
EmitStmt(S.getAssociatedStmt());
4701 const Expr *Hint =
nullptr;
4702 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4703 Hint = HintClause->getHint();
4706 CGM.getOpenMPRuntime().emitCriticalRegion(*
this,
4707 S.getDirectiveName().getAsString(),
4708 CodeGen, S.getBeginLoc(), Hint);
4712 const OMPParallelForDirective &S) {
4721 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
4725 OMPLoopScope LoopScope(CGF, S);
4728 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4729 [](
const OMPReductionClause *
C) {
4730 return C->getModifier() == OMPC_REDUCTION_inscan;
4746 const OMPParallelForSimdDirective &S) {
4755 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
4759 OMPLoopScope LoopScope(CGF, S);
4762 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4763 [](
const OMPReductionClause *
C) {
4764 return C->getModifier() == OMPC_REDUCTION_inscan;
4780 const OMPParallelMasterDirective &S) {
4800 [](CodeGenFunction &) {
return nullptr; });
4807 const OMPParallelMaskedDirective &S) {
4827 [](CodeGenFunction &) {
return nullptr; });
4834 const OMPParallelSectionsDirective &S) {
4840 CGF.EmitSections(S);
4854class CheckVarsEscapingUntiedTaskDeclContext final
4859 explicit CheckVarsEscapingUntiedTaskDeclContext() =
default;
4860 ~CheckVarsEscapingUntiedTaskDeclContext() =
default;
4861 void VisitDeclStmt(
const DeclStmt *S) {
4866 if (
const auto *VD = dyn_cast_or_null<VarDecl>(D))
4868 PrivateDecls.push_back(VD);
4872 void VisitCapturedStmt(
const CapturedStmt *) {}
4874 void VisitBlockExpr(
const BlockExpr *) {}
4875 void VisitStmt(
const Stmt *S) {
4878 for (
const Stmt *Child : S->
children())
4884 ArrayRef<const VarDecl *> getPrivateDecls()
const {
return PrivateDecls; }
4892 bool OmpAllMemory =
false;
4895 return C->getDependencyKind() == OMPC_DEPEND_outallmemory ||
4896 C->getDependencyKind() == OMPC_DEPEND_inoutallmemory;
4898 OmpAllMemory =
true;
4903 Data.Dependences.emplace_back(OMPC_DEPEND_outallmemory,
4912 if (Kind == OMPC_DEPEND_outallmemory || Kind == OMPC_DEPEND_inoutallmemory)
4914 if (OmpAllMemory && (Kind == OMPC_DEPEND_out || Kind == OMPC_DEPEND_inout))
4917 Data.Dependences.emplace_back(
C->getDependencyKind(),
C->getModifier());
4918 DD.
DepExprs.append(
C->varlist_begin(),
C->varlist_end());
4927 const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion);
4929 auto PartId = std::next(I);
4930 auto TaskT = std::next(I, 4);
4935 const Expr *
Cond = Clause->getCondition();
4938 Data.Final.setInt(CondConstant);
4943 Data.Final.setInt(
false);
4947 const Expr *Prio = Clause->getPriority();
4948 Data.Priority.setInt(
true);
4956 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
4958 for (
const auto *
C : S.getClausesOfKind<OMPPrivateClause>()) {
4959 auto IRef =
C->varlist_begin();
4960 for (
const Expr *IInit :
C->private_copies()) {
4962 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
4963 Data.PrivateVars.push_back(*IRef);
4964 Data.PrivateCopies.push_back(IInit);
4969 EmittedAsPrivate.clear();
4971 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
4972 auto IRef =
C->varlist_begin();
4973 auto IElemInitRef =
C->inits().begin();
4974 for (
const Expr *IInit :
C->private_copies()) {
4976 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
4977 Data.FirstprivateVars.push_back(*IRef);
4978 Data.FirstprivateCopies.push_back(IInit);
4979 Data.FirstprivateInits.push_back(*IElemInitRef);
4986 llvm::MapVector<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
4987 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
4988 auto IRef =
C->varlist_begin();
4989 auto ID =
C->destination_exprs().begin();
4990 for (
const Expr *IInit :
C->private_copies()) {
4992 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
4993 Data.LastprivateVars.push_back(*IRef);
4994 Data.LastprivateCopies.push_back(IInit);
4996 LastprivateDstsOrigs.insert(
5005 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
5006 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5007 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5008 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5009 Data.ReductionOps.append(
C->reduction_ops().begin(),
5010 C->reduction_ops().end());
5011 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5012 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5014 Data.Reductions =
CGM.getOpenMPRuntime().emitTaskReductionInit(
5015 *
this, S.getBeginLoc(), LHSs, RHSs,
Data);
5020 CheckVarsEscapingUntiedTaskDeclContext Checker;
5021 Checker.Visit(S.getInnermostCapturedStmt()->getCapturedStmt());
5022 Data.PrivateLocals.append(Checker.getPrivateDecls().begin(),
5023 Checker.getPrivateDecls().end());
5025 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
5026 CapturedRegion](CodeGenFunction &CGF,
5028 llvm::MapVector<CanonicalDeclPtr<const VarDecl>,
5029 std::pair<Address, Address>>
5034 if (
auto *DI = CGF.getDebugInfo()) {
5035 llvm::SmallDenseMap<const VarDecl *, FieldDecl *> CaptureFields =
5036 CGF.CapturedStmtInfo->getCaptureFields();
5037 llvm::Value *ContextValue = CGF.CapturedStmtInfo->getContextValue();
5038 if (CaptureFields.size() && ContextValue) {
5039 unsigned CharWidth = CGF.getContext().getCharWidth();
5053 for (
auto It = CaptureFields.begin(); It != CaptureFields.end(); ++It) {
5054 const VarDecl *SharedVar = It->first;
5057 CGF.getContext().getASTRecordLayout(CaptureRecord);
5060 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5061 (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue,
5062 CGF.Builder,
false);
5065 auto UpdateExpr = [](llvm::LLVMContext &Ctx,
auto *
Declare,
5070 Ops.push_back(llvm::dwarf::DW_OP_plus_uconst);
5071 Ops.push_back(Offset);
5073 Ops.push_back(llvm::dwarf::DW_OP_deref);
5074 Declare->setExpression(llvm::DIExpression::get(Ctx, Ops));
5076 llvm::Instruction &
Last = CGF.Builder.GetInsertBlock()->back();
5077 if (
auto DDI = dyn_cast<llvm::DbgVariableIntrinsic>(&
Last))
5078 UpdateExpr(DDI->getContext(), DDI, Offset);
5081 assert(!
Last.isTerminator() &&
"unexpected terminator");
5083 CGF.Builder.GetInsertBlock()->getTrailingDbgRecords()) {
5084 for (llvm::DbgVariableRecord &DVR : llvm::reverse(
5085 llvm::filterDbgVars(Marker->getDbgRecordRange()))) {
5086 UpdateExpr(
Last.getContext(), &DVR, Offset);
5094 if (!
Data.PrivateVars.empty() || !
Data.FirstprivateVars.empty() ||
5095 !
Data.LastprivateVars.empty() || !
Data.PrivateLocals.empty()) {
5096 enum { PrivatesParam = 2, CopyFnParam = 3 };
5097 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5099 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5105 CallArgs.push_back(PrivatesPtr);
5106 ParamTypes.push_back(PrivatesPtr->getType());
5107 for (
const Expr *E :
Data.PrivateVars) {
5110 CGF.getContext().getPointerType(E->
getType()),
".priv.ptr.addr");
5111 PrivatePtrs.emplace_back(VD, PrivatePtr);
5113 ParamTypes.push_back(PrivatePtr.
getType());
5115 for (
const Expr *E :
Data.FirstprivateVars) {
5118 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
5119 ".firstpriv.ptr.addr");
5120 PrivatePtrs.emplace_back(VD, PrivatePtr);
5121 FirstprivatePtrs.emplace_back(VD, PrivatePtr);
5123 ParamTypes.push_back(PrivatePtr.
getType());
5125 for (
const Expr *E :
Data.LastprivateVars) {
5128 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
5129 ".lastpriv.ptr.addr");
5130 PrivatePtrs.emplace_back(VD, PrivatePtr);
5132 ParamTypes.push_back(PrivatePtr.
getType());
5137 Ty = CGF.getContext().getPointerType(Ty);
5139 Ty = CGF.getContext().getPointerType(Ty);
5141 CGF.getContext().getPointerType(Ty),
".local.ptr.addr");
5142 auto Result = UntiedLocalVars.insert(
5145 if (
Result.second ==
false)
5146 *
Result.first = std::make_pair(
5149 ParamTypes.push_back(PrivatePtr.
getType());
5151 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5153 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5154 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5155 for (
const auto &Pair : LastprivateDstsOrigs) {
5159 CGF.CapturedStmtInfo->lookup(OrigVD) !=
nullptr,
5161 Pair.second->getExprLoc());
5162 Scope.addPrivate(Pair.first, CGF.EmitLValue(&DRE).getAddress());
5164 for (
const auto &Pair : PrivatePtrs) {
5166 CGF.Builder.CreateLoad(Pair.second),
5167 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5168 CGF.getContext().getDeclAlign(Pair.first));
5169 Scope.addPrivate(Pair.first, Replacement);
5170 if (
auto *DI = CGF.getDebugInfo())
5171 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5172 (void)DI->EmitDeclareOfAutoVariable(
5173 Pair.first, Pair.second.getBasePointer(), CGF.Builder,
5178 for (
auto &Pair : UntiedLocalVars) {
5179 QualType VDType = Pair.first->getType().getNonReferenceType();
5180 if (Pair.first->getType()->isLValueReferenceType())
5181 VDType = CGF.getContext().getPointerType(VDType);
5183 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5186 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(VDType)),
5187 CGF.getPointerAlign());
5188 Pair.second.first = Replacement;
5189 Ptr = CGF.Builder.CreateLoad(Replacement);
5190 Replacement =
Address(Ptr, CGF.ConvertTypeForMem(VDType),
5191 CGF.getContext().getDeclAlign(Pair.first));
5192 Pair.second.second = Replacement;
5194 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5195 Address Replacement(Ptr, CGF.ConvertTypeForMem(VDType),
5196 CGF.getContext().getDeclAlign(Pair.first));
5197 Pair.second.first = Replacement;
5201 if (
Data.Reductions) {
5203 for (
const auto &Pair : FirstprivatePtrs) {
5205 CGF.Builder.CreateLoad(Pair.second),
5206 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5207 CGF.getContext().getDeclAlign(Pair.first));
5208 FirstprivateScope.
addPrivate(Pair.first, Replacement);
5211 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5213 Data.ReductionCopies,
Data.ReductionOps);
5214 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
5216 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5222 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5224 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5227 CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF),
5228 CGF.getContext().VoidPtrTy,
5229 CGF.getContext().getPointerType(
5230 Data.ReductionCopies[Cnt]->getType()),
5231 Data.ReductionCopies[Cnt]->getExprLoc()),
5232 CGF.ConvertTypeForMem(
Data.ReductionCopies[Cnt]->getType()),
5233 Replacement.getAlignment());
5239 (void)
Scope.Privatize();
5244 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5245 auto IPriv =
C->privates().begin();
5246 auto IRed =
C->reduction_ops().begin();
5247 auto ITD =
C->taskgroup_descriptors().begin();
5248 for (
const Expr *Ref :
C->varlist()) {
5249 InRedVars.emplace_back(Ref);
5250 InRedPrivs.emplace_back(*IPriv);
5251 InRedOps.emplace_back(*IRed);
5252 TaskgroupDescriptors.emplace_back(*ITD);
5253 std::advance(IPriv, 1);
5254 std::advance(IRed, 1);
5255 std::advance(ITD, 1);
5261 if (!InRedVars.empty()) {
5263 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5271 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5273 llvm::Value *ReductionsPtr;
5274 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5275 ReductionsPtr = CGF.EmitLoadOfScalar(CGF.EmitLValue(TRExpr),
5276 TRExpr->getExprLoc());
5278 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5280 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5283 CGF.EmitScalarConversion(
5284 Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy,
5285 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
5286 InRedPrivs[Cnt]->getExprLoc()),
5287 CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()),
5288 Replacement.getAlignment());
5301 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5302 S, *I, *PartId, *TaskT, EKind,
CodeGen,
Data.Tied,
Data.NumberOfParts);
5303 OMPLexicalScope
Scope(*
this, S, std::nullopt,
5306 TaskGen(*
this, OutlinedFn,
Data);
5323 QualType ElemType =
C.getBaseElementType(Ty);
5333 Data.FirstprivateVars.emplace_back(OrigRef);
5334 Data.FirstprivateCopies.emplace_back(PrivateRef);
5335 Data.FirstprivateInits.emplace_back(InitRef);
5348 auto PartId = std::next(I);
5349 auto TaskT = std::next(I, 4);
5352 Data.Final.setInt(
false);
5354 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5355 auto IRef =
C->varlist_begin();
5356 auto IElemInitRef =
C->inits().begin();
5357 for (
auto *IInit :
C->private_copies()) {
5358 Data.FirstprivateVars.push_back(*IRef);
5359 Data.FirstprivateCopies.push_back(IInit);
5360 Data.FirstprivateInits.push_back(*IElemInitRef);
5367 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5368 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5369 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5370 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5371 Data.ReductionOps.append(
C->reduction_ops().begin(),
5372 C->reduction_ops().end());
5373 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5374 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5389 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5391 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5403 if (!isa_and_nonnull<llvm::ConstantPointerNull>(
5406 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5413 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, BPVD, PVD, SVD, MVD, EKind,
5417 if (!
Data.FirstprivateVars.empty()) {
5418 enum { PrivatesParam = 2, CopyFnParam = 3 };
5419 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5421 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5427 CallArgs.push_back(PrivatesPtr);
5428 ParamTypes.push_back(PrivatesPtr->getType());
5429 for (
const Expr *E :
Data.FirstprivateVars) {
5432 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
5433 ".firstpriv.ptr.addr");
5434 PrivatePtrs.emplace_back(VD, PrivatePtr);
5436 ParamTypes.push_back(PrivatePtr.
getType());
5438 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5440 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5441 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5442 for (
const auto &Pair : PrivatePtrs) {
5444 CGF.Builder.CreateLoad(Pair.second),
5445 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5446 CGF.getContext().getDeclAlign(Pair.first));
5447 Scope.addPrivate(Pair.first, Replacement);
5450 CGF.processInReduction(S,
Data, CGF, CS,
Scope);
5453 CGF.GetAddrOfLocalVar(BPVD), 0);
5455 CGF.GetAddrOfLocalVar(PVD), 0);
5456 InputInfo.
SizesArray = CGF.Builder.CreateConstArrayGEP(
5457 CGF.GetAddrOfLocalVar(SVD), 0);
5460 InputInfo.
MappersArray = CGF.Builder.CreateConstArrayGEP(
5461 CGF.GetAddrOfLocalVar(MVD), 0);
5465 OMPLexicalScope LexScope(CGF, S, OMPD_task,
false);
5467 if (CGF.CGM.getLangOpts().OpenMP >= 51 &&
5472 CGF.CGM.getOpenMPRuntime().emitThreadLimitClause(
5473 CGF, TL->getThreadLimit().front(), S.getBeginLoc());
5477 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5478 S, *I, *PartId, *TaskT, EKind,
CodeGen,
true,
5479 Data.NumberOfParts);
5480 llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<OMPNowaitClause>() ? 1 : 0);
5484 CGM.getOpenMPRuntime().emitTaskCall(*
this, S.getBeginLoc(), S, OutlinedFn,
5485 SharedsTy, CapturedStruct, &IfCond,
Data);
5490 CodeGenFunction &CGF,
5494 if (
Data.Reductions) {
5496 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5498 Data.ReductionCopies,
Data.ReductionOps);
5501 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5515 Data.ReductionCopies[Cnt]->getType()),
5516 Data.ReductionCopies[Cnt]->getExprLoc()),
5518 Replacement.getAlignment());
5523 (void)
Scope.Privatize();
5528 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5529 auto IPriv =
C->privates().begin();
5530 auto IRed =
C->reduction_ops().begin();
5531 auto ITD =
C->taskgroup_descriptors().begin();
5532 for (
const Expr *Ref :
C->varlist()) {
5533 InRedVars.emplace_back(Ref);
5534 InRedPrivs.emplace_back(*IPriv);
5535 InRedOps.emplace_back(*IRed);
5536 TaskgroupDescriptors.emplace_back(*ITD);
5537 std::advance(IPriv, 1);
5538 std::advance(IRed, 1);
5539 std::advance(ITD, 1);
5543 if (!InRedVars.empty()) {
5545 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5553 llvm::Value *ReductionsPtr;
5554 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5558 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
5566 InRedPrivs[Cnt]->getExprLoc()),
5568 Replacement.getAlignment());
5582 const Expr *IfCond =
nullptr;
5583 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
5584 if (
C->getNameModifier() == OMPD_unknown ||
5585 C->getNameModifier() == OMPD_task) {
5586 IfCond =
C->getCondition();
5593 Data.Tied = !S.getSingleClause<OMPUntiedClause>();
5597 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
5598 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
5601 SharedsTy, CapturedStruct, IfCond,
5610 const OMPTaskyieldDirective &S) {
5611 CGM.getOpenMPRuntime().emitTaskyieldCall(*
this, S.getBeginLoc());
5615 const OMPMessageClause *MC = S.getSingleClause<OMPMessageClause>();
5616 Expr *ME = MC ? MC->getMessageString() :
nullptr;
5617 const OMPSeverityClause *SC = S.getSingleClause<OMPSeverityClause>();
5618 bool IsFatal =
false;
5619 if (!SC || SC->getSeverityKind() == OMPC_SEVERITY_fatal)
5621 CGM.getOpenMPRuntime().emitErrorCall(*
this, S.getBeginLoc(), ME, IsFatal);
5625 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_barrier);
5632 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
5633 CGM.getOpenMPRuntime().emitTaskwaitCall(*
this, S.getBeginLoc(),
Data);
5637 return T.clauses().empty();
5641 const OMPTaskgroupDirective &S) {
5642 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
5644 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
5645 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5649 auto BodyGenCB = [&,
this](InsertPointTy AllocaIP,
5650 InsertPointTy CodeGenIP) {
5652 EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5653 return llvm::Error::success();
5658 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5659 cantFail(OMPBuilder.createTaskgroup(
Builder, AllocaIP, BodyGenCB));
5665 if (
const Expr *E = S.getReductionRef()) {
5669 for (
const auto *
C : S.getClausesOfKind<OMPTaskReductionClause>()) {
5670 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5671 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5672 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5673 Data.ReductionOps.append(
C->reduction_ops().begin(),
5674 C->reduction_ops().end());
5675 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5676 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5678 llvm::Value *ReductionDesc =
5686 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5688 CGM.getOpenMPRuntime().emitTaskgroupRegion(*
this,
CodeGen, S.getBeginLoc());
5693 ? llvm::AtomicOrdering::NotAtomic
5694 : llvm::AtomicOrdering::AcquireRelease;
5695 CGM.getOpenMPRuntime().emitFlush(
5698 if (
const auto *FlushClause = S.getSingleClause<
OMPFlushClause>())
5700 FlushClause->varlist_end());
5703 S.getBeginLoc(), AO);
5713 for (
auto &Dep :
Data.Dependences) {
5714 Address DepAddr =
CGM.getOpenMPRuntime().emitDepobjDependClause(
5715 *
this, Dep, DC->getBeginLoc());
5721 CGM.getOpenMPRuntime().emitDestroyClause(*
this, DOLVal, DC->getBeginLoc());
5724 if (
const auto *UC = S.getSingleClause<OMPUpdateClause>()) {
5725 CGM.getOpenMPRuntime().emitUpdateClause(
5726 *
this, DOLVal, UC->getDependencyKind(), UC->getBeginLoc());
5744 for (
const auto *
C : ParentDir.getClausesOfKind<OMPReductionClause>()) {
5745 if (
C->getModifier() != OMPC_REDUCTION_inscan)
5747 Shareds.append(
C->varlist_begin(),
C->varlist_end());
5748 Privates.append(
C->privates().begin(),
C->privates().end());
5749 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5750 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5751 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
5752 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
5753 CopyArrayTemps.append(
C->copy_array_temps().begin(),
5754 C->copy_array_temps().end());
5755 CopyArrayElems.append(
C->copy_array_elems().begin(),
5756 C->copy_array_elems().end());
5758 if (ParentDir.getDirectiveKind() == OMPD_simd ||
5800 : BreakContinueStack.back().ContinueBlock.getBlock());
5811 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
5813 const Expr *TempExpr = CopyArrayTemps[I];
5825 CGM.getOpenMPRuntime().emitReduction(
5826 *
this, ParentDir.getEndLoc(),
Privates, LHSs, RHSs, ReductionOps,
5829 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
5837 const Expr *TempExpr = CopyArrayTemps[I];
5849 ? BreakContinueStack.back().ContinueBlock.getBlock()
5855 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
5861 .getIterationVariable()
5862 ->IgnoreParenImpCasts();
5865 IdxVal = Builder.CreateIntCast(IdxVal,
SizeTy,
false);
5866 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
5868 const Expr *OrigExpr = Shareds[I];
5869 const Expr *CopyArrayElem = CopyArrayElems[I];
5870 OpaqueValueMapping IdxMapping(
5883 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
5886 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
5892 .getIterationVariable()
5893 ->IgnoreParenImpCasts();
5897 llvm::BasicBlock *ExclusiveExitBB =
nullptr;
5901 llvm::Value *Cmp =
Builder.CreateIsNull(IdxVal);
5902 Builder.CreateCondBr(Cmp, ExclusiveExitBB, ContBB);
5905 IdxVal =
Builder.CreateNUWSub(IdxVal, llvm::ConstantInt::get(
SizeTy, 1));
5907 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
5908 const Expr *PrivateExpr =
Privates[I];
5909 const Expr *OrigExpr = Shareds[I];
5910 const Expr *CopyArrayElem = CopyArrayElems[I];
5919 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
5943 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
5951 bool HasLastprivateClause =
false;
5954 OMPLoopScope PreInitScope(*
this, S);
5959 llvm::BasicBlock *ContBlock =
nullptr;
5966 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
5980 ? S.getCombinedLowerBoundVariable()
5981 : S.getLowerBoundVariable())));
5985 ? S.getCombinedUpperBoundVariable()
5986 : S.getUpperBoundVariable())));
5997 CGM.getOpenMPRuntime().emitBarrierCall(
5998 *
this, S.getBeginLoc(), OMPD_unknown,
false,
6010 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
6013 llvm::Value *Chunk =
nullptr;
6016 ScheduleKind =
C->getDistScheduleKind();
6017 if (
const Expr *Ch =
C->getChunkSize()) {
6020 S.getIterationVariable()->getType(),
6025 CGM.getOpenMPRuntime().getDefaultDistScheduleAndChunk(
6026 *
this, S, ScheduleKind, Chunk);
6039 bool StaticChunked =
6043 Chunk !=
nullptr) ||
6048 StaticChunked ? Chunk :
nullptr);
6055 ? S.getCombinedEnsureUpperBound()
6056 : S.getEnsureUpperBound());
6059 ? S.getCombinedInit()
6064 ? S.getCombinedCond()
6068 Cond = S.getCombinedDistCond();
6100 [&S, &LoopScope,
Cond, IncExpr,
LoopExit, &CodeGenLoop,
6103 S, LoopScope.requiresCleanups(),
Cond, IncExpr,
6104 [&S,
LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
6105 CodeGenLoop(CGF, S, LoopExit);
6107 [&S, StaticChunked](CodeGenFunction &CGF) {
6108 if (StaticChunked) {
6109 CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound());
6110 CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound());
6111 CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound());
6112 CGF.EmitIgnoredExpr(S.getCombinedInit());
6122 const OMPLoopArguments LoopArguments = {
6123 LB.getAddress(), UB.getAddress(), ST.getAddress(), IL.getAddress(),
6125 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments,
6130 return CGF.
Builder.CreateIsNotNull(
6140 *
this, S, [IL, &S](CodeGenFunction &CGF) {
6141 return CGF.
Builder.CreateIsNotNull(
6146 if (HasLastprivateClause) {
6169 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
6178static llvm::Function *
6185 Fn->setDoesNotRecurse();
6189template <
typename T>
6191 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP,
6192 llvm::OpenMPIRBuilder &OMPBuilder) {
6194 unsigned NumLoops =
C->getNumLoops();
6198 for (
unsigned I = 0; I < NumLoops; I++) {
6199 const Expr *CounterVal =
C->getLoopData(I);
6204 StoreValues.emplace_back(StoreValue);
6206 OMPDoacrossKind<T> ODK;
6207 bool IsDependSource = ODK.isSource(
C);
6209 OMPBuilder.createOrderedDepend(CGF.
Builder, AllocaIP, NumLoops,
6210 StoreValues,
".cnt.addr", IsDependSource));
6214 if (
CGM.getLangOpts().OpenMPIRBuilder) {
6215 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
6216 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6221 assert(!S.hasAssociatedStmt() &&
"No associated statement must be in "
6222 "ordered depend|doacross construct.");
6234 auto FiniCB = [
this](InsertPointTy IP) {
6236 return llvm::Error::success();
6239 auto BodyGenCB = [&S,
C,
this](InsertPointTy AllocaIP,
6240 InsertPointTy CodeGenIP) {
6245 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
6246 Builder,
false,
".ordered.after");
6250 assert(S.getBeginLoc().isValid() &&
6251 "Outlined function call location must be valid.");
6254 OutlinedFn, CapturedVars);
6259 return llvm::Error::success();
6262 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6263 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
6264 OMPBuilder.createOrderedThreadsSimd(
Builder, BodyGenCB, FiniCB, !
C));
6271 assert(!S.hasAssociatedStmt() &&
6272 "No associated statement must be in ordered depend construct.");
6274 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6278 assert(!S.hasAssociatedStmt() &&
6279 "No associated statement must be in ordered doacross construct.");
6281 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6285 auto &&
CodeGen = [&S,
C,
this](CodeGenFunction &CGF,
6290 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
6292 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
6293 OutlinedFn, CapturedVars);
6299 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6300 CGM.getOpenMPRuntime().emitOrderedRegion(*
this,
CodeGen, S.getBeginLoc(), !
C);
6307 "DestType must have scalar evaluation kind.");
6308 assert(!Val.
isAggregate() &&
"Must be a scalar or complex.");
6319 "DestType must have complex evaluation kind.");
6328 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
6330 assert(Val.
isComplex() &&
"Must be a scalar or complex.");
6335 Val.
getComplexVal().first, SrcElementType, DestElementType, Loc);
6337 Val.
getComplexVal().second, SrcElementType, DestElementType, Loc);
6343 LValue LVal,
RValue RVal) {
6344 if (LVal.isGlobalReg())
6351 llvm::AtomicOrdering AO, LValue LVal,
6353 if (LVal.isGlobalReg())
6356 LVal, Loc, llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO),
6365 *
this, RVal, RValTy, LVal.
getType(), Loc)),
6374 llvm_unreachable(
"Must be a scalar or complex.");
6382 assert(
V->isLValue() &&
"V of 'omp atomic read' is not lvalue");
6383 assert(
X->isLValue() &&
"X of 'omp atomic read' is not lvalue");
6392 case llvm::AtomicOrdering::Acquire:
6393 case llvm::AtomicOrdering::AcquireRelease:
6394 case llvm::AtomicOrdering::SequentiallyConsistent:
6396 llvm::AtomicOrdering::Acquire);
6398 case llvm::AtomicOrdering::Monotonic:
6399 case llvm::AtomicOrdering::Release:
6401 case llvm::AtomicOrdering::NotAtomic:
6402 case llvm::AtomicOrdering::Unordered:
6403 llvm_unreachable(
"Unexpected ordering.");
6410 llvm::AtomicOrdering AO,
const Expr *
X,
6413 assert(
X->isLValue() &&
"X of 'omp atomic write' is not lvalue");
6421 case llvm::AtomicOrdering::Release:
6422 case llvm::AtomicOrdering::AcquireRelease:
6423 case llvm::AtomicOrdering::SequentiallyConsistent:
6425 llvm::AtomicOrdering::Release);
6427 case llvm::AtomicOrdering::Acquire:
6428 case llvm::AtomicOrdering::Monotonic:
6430 case llvm::AtomicOrdering::NotAtomic:
6431 case llvm::AtomicOrdering::Unordered:
6432 llvm_unreachable(
"Unexpected ordering.");
6439 llvm::AtomicOrdering AO,
6445 if (BO == BO_Comma || !
Update.isScalar() || !
X.isSimple() ||
6447 (
Update.getScalarVal()->getType() !=
X.getAddress().getElementType())) ||
6448 !Context.getTargetInfo().hasBuiltinAtomic(
6449 Context.getTypeSize(
X.getType()), Context.toBits(
X.getAlignment())))
6450 return std::make_pair(
false,
RValue::get(
nullptr));
6453 if (
T->isIntegerTy())
6456 if (
T->isFloatingPointTy() && (BO == BO_Add || BO == BO_Sub))
6462 if (!CheckAtomicSupport(
Update.getScalarVal()->getType(), BO) ||
6463 !CheckAtomicSupport(
X.getAddress().getElementType(), BO))
6464 return std::make_pair(
false,
RValue::get(
nullptr));
6466 bool IsInteger =
X.getAddress().getElementType()->isIntegerTy();
6467 llvm::AtomicRMWInst::BinOp RMWOp;
6470 RMWOp = IsInteger ? llvm::AtomicRMWInst::Add : llvm::AtomicRMWInst::FAdd;
6474 return std::make_pair(
false,
RValue::get(
nullptr));
6475 RMWOp = IsInteger ? llvm::AtomicRMWInst::Sub : llvm::AtomicRMWInst::FSub;
6478 RMWOp = llvm::AtomicRMWInst::And;
6481 RMWOp = llvm::AtomicRMWInst::Or;
6484 RMWOp = llvm::AtomicRMWInst::Xor;
6488 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6490 : llvm::AtomicRMWInst::Max)
6492 : llvm::AtomicRMWInst::UMax);
6495 : llvm::AtomicRMWInst::FMax;
6499 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6501 : llvm::AtomicRMWInst::Min)
6503 : llvm::AtomicRMWInst::UMin);
6506 : llvm::AtomicRMWInst::FMin;
6509 RMWOp = llvm::AtomicRMWInst::Xchg;
6518 return std::make_pair(
false,
RValue::get(
nullptr));
6537 llvm_unreachable(
"Unsupported atomic update operation");
6539 llvm::Value *UpdateVal =
Update.getScalarVal();
6540 if (
auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
6542 UpdateVal = CGF.
Builder.CreateIntCast(
6543 IC,
X.getAddress().getElementType(),
6544 X.getType()->hasSignedIntegerRepresentation());
6546 UpdateVal = CGF.
Builder.CreateCast(llvm::Instruction::CastOps::UIToFP, IC,
6547 X.getAddress().getElementType());
6549 llvm::AtomicRMWInst *Res =
6566 if (
X.isGlobalReg()) {
6579 llvm::AtomicOrdering AO,
const Expr *
X,
6583 "Update expr in 'atomic update' must be a binary operator.");
6591 assert(
X->isLValue() &&
"X of 'omp atomic update' is not lvalue");
6598 auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](
RValue XRValue) {
6604 XLValue, ExprRValue, BOUE->getOpcode(),
IsXLHSInRHSPart, AO, Loc, Gen);
6611 case llvm::AtomicOrdering::Release:
6612 case llvm::AtomicOrdering::AcquireRelease:
6613 case llvm::AtomicOrdering::SequentiallyConsistent:
6615 llvm::AtomicOrdering::Release);
6617 case llvm::AtomicOrdering::Acquire:
6618 case llvm::AtomicOrdering::Monotonic:
6620 case llvm::AtomicOrdering::NotAtomic:
6621 case llvm::AtomicOrdering::Unordered:
6622 llvm_unreachable(
"Unexpected ordering.");
6640 llvm_unreachable(
"Must be a scalar or complex.");
6644 llvm::AtomicOrdering AO,
6649 assert(
X->isLValue() &&
"X of 'omp atomic capture' is not lvalue");
6650 assert(
V->isLValue() &&
"V of 'omp atomic capture' is not lvalue");
6659 "Update expr in 'atomic capture' must be a binary operator.");
6670 NewVValType = XRValExpr->
getType();
6672 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
6681 XLValue, ExprRValue, BOUE->getOpcode(),
IsXLHSInRHSPart, AO, Loc, Gen);
6687 NewVVal = Res.second;
6698 NewVValType =
X->getType().getNonReferenceType();
6700 X->getType().getNonReferenceType(), Loc);
6701 auto &&Gen = [&NewVVal, ExprRValue](
RValue XRValue) {
6707 XLValue, ExprRValue, BO_Assign,
false, AO,
6728 case llvm::AtomicOrdering::Release:
6730 llvm::AtomicOrdering::Release);
6732 case llvm::AtomicOrdering::Acquire:
6734 llvm::AtomicOrdering::Acquire);
6736 case llvm::AtomicOrdering::AcquireRelease:
6737 case llvm::AtomicOrdering::SequentiallyConsistent:
6739 CGF, {}, Loc, llvm::AtomicOrdering::AcquireRelease);
6741 case llvm::AtomicOrdering::Monotonic:
6743 case llvm::AtomicOrdering::NotAtomic:
6744 case llvm::AtomicOrdering::Unordered:
6745 llvm_unreachable(
"Unexpected ordering.");
6751 CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO,
6755 llvm::OpenMPIRBuilder &OMPBuilder =
6758 OMPAtomicCompareOp Op;
6762 Op = OMPAtomicCompareOp::EQ;
6765 Op = OMPAtomicCompareOp::MIN;
6768 Op = OMPAtomicCompareOp::MAX;
6771 llvm_unreachable(
"unsupported atomic compare binary operator");
6775 Address XAddr = XLVal.getAddress();
6777 auto EmitRValueWithCastIfNeeded = [&CGF, Loc](
const Expr *
X,
const Expr *E) {
6782 if (NewE->
getType() ==
X->getType())
6787 llvm::Value *EVal = EmitRValueWithCastIfNeeded(
X, E);
6788 llvm::Value *DVal = D ? EmitRValueWithCastIfNeeded(
X, D) :
nullptr;
6789 if (
auto *CI = dyn_cast<llvm::ConstantInt>(EVal))
6790 EVal = CGF.
Builder.CreateIntCast(
6791 CI, XLVal.getAddress().getElementType(),
6794 if (
auto *CI = dyn_cast<llvm::ConstantInt>(DVal))
6795 DVal = CGF.
Builder.CreateIntCast(
6796 CI, XLVal.getAddress().getElementType(),
6799 llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{
6801 X->getType()->hasSignedIntegerRepresentation(),
6802 X->getType().isVolatileQualified()};
6803 llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal;
6807 VOpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
6808 V->getType()->hasSignedIntegerRepresentation(),
6809 V->getType().isVolatileQualified()};
6814 ROpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
6819 if (FailAO == llvm::AtomicOrdering::NotAtomic) {
6822 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
6823 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
6826 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
6827 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
6832 llvm::AtomicOrdering AO,
6853 case OMPC_compare: {
6859 llvm_unreachable(
"Clause is not allowed in 'omp atomic'.");
6864 llvm::AtomicOrdering AO =
CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
6866 llvm::AtomicOrdering FailAO = llvm::AtomicOrdering::NotAtomic;
6867 bool MemOrderingSpecified =
false;
6868 if (S.getSingleClause<OMPSeqCstClause>()) {
6869 AO = llvm::AtomicOrdering::SequentiallyConsistent;
6870 MemOrderingSpecified =
true;
6871 }
else if (S.getSingleClause<OMPAcqRelClause>()) {
6872 AO = llvm::AtomicOrdering::AcquireRelease;
6873 MemOrderingSpecified =
true;
6874 }
else if (S.getSingleClause<OMPAcquireClause>()) {
6875 AO = llvm::AtomicOrdering::Acquire;
6876 MemOrderingSpecified =
true;
6877 }
else if (S.getSingleClause<OMPReleaseClause>()) {
6878 AO = llvm::AtomicOrdering::Release;
6879 MemOrderingSpecified =
true;
6880 }
else if (S.getSingleClause<OMPRelaxedClause>()) {
6881 AO = llvm::AtomicOrdering::Monotonic;
6882 MemOrderingSpecified =
true;
6884 llvm::SmallSet<OpenMPClauseKind, 2> KindsEncountered;
6893 if (K == OMPC_seq_cst || K == OMPC_acq_rel || K == OMPC_acquire ||
6894 K == OMPC_release || K == OMPC_relaxed || K == OMPC_hint)
6897 KindsEncountered.insert(K);
6902 if (KindsEncountered.contains(OMPC_compare) &&
6903 KindsEncountered.contains(OMPC_capture))
6904 Kind = OMPC_compare;
6905 if (!MemOrderingSpecified) {
6906 llvm::AtomicOrdering DefaultOrder =
6907 CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
6908 if (DefaultOrder == llvm::AtomicOrdering::Monotonic ||
6909 DefaultOrder == llvm::AtomicOrdering::SequentiallyConsistent ||
6910 (DefaultOrder == llvm::AtomicOrdering::AcquireRelease &&
6911 Kind == OMPC_capture)) {
6913 }
else if (DefaultOrder == llvm::AtomicOrdering::AcquireRelease) {
6914 if (Kind == OMPC_unknown || Kind == OMPC_update || Kind == OMPC_write) {
6915 AO = llvm::AtomicOrdering::Release;
6916 }
else if (Kind == OMPC_read) {
6917 assert(Kind == OMPC_read &&
"Unexpected atomic kind.");
6918 AO = llvm::AtomicOrdering::Acquire;
6923 if (KindsEncountered.contains(OMPC_compare) &&
6924 KindsEncountered.contains(OMPC_fail)) {
6925 Kind = OMPC_compare;
6926 const auto *FailClause = S.getSingleClause<OMPFailClause>();
6929 if (FailParameter == llvm::omp::OMPC_relaxed)
6930 FailAO = llvm::AtomicOrdering::Monotonic;
6931 else if (FailParameter == llvm::omp::OMPC_acquire)
6932 FailAO = llvm::AtomicOrdering::Acquire;
6933 else if (FailParameter == llvm::omp::OMPC_seq_cst)
6934 FailAO = llvm::AtomicOrdering::SequentiallyConsistent;
6941 S.getV(), S.getR(), S.getExpr(), S.getUpdateExpr(),
6942 S.getD(), S.getCondExpr(), S.isXLHSInRHSPart(),
6943 S.isFailOnly(), S.getBeginLoc());
6954 OMPLexicalScope
Scope(CGF, S, OMPD_target);
6957 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
6963 llvm::Function *Fn =
nullptr;
6964 llvm::Constant *FnID =
nullptr;
6966 const Expr *IfCond =
nullptr;
6968 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
6969 if (
C->getNameModifier() == OMPD_unknown ||
6970 C->getNameModifier() == OMPD_target) {
6971 IfCond =
C->getCondition();
6977 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device(
6980 Device.setPointerAndInt(
C->getDevice(),
C->getModifier());
6985 bool IsOffloadEntry =
true;
6989 IsOffloadEntry =
false;
6992 IsOffloadEntry =
false;
6994 if (
CGM.
getLangOpts().OpenMPOffloadMandatory && !IsOffloadEntry) {
6998 assert(CGF.
CurFuncDecl &&
"No parent declaration for target region!");
6999 StringRef ParentName;
7002 if (
const auto *D = dyn_cast<CXXConstructorDecl>(CGF.
CurFuncDecl))
7004 else if (
const auto *D = dyn_cast<CXXDestructorDecl>(CGF.
CurFuncDecl))
7013 OMPLexicalScope
Scope(CGF, S, OMPD_task);
7014 auto &&SizeEmitter =
7017 if (IsOffloadEntry) {
7018 OMPLoopScope(CGF, D);
7020 llvm::Value *NumIterations = CGF.
EmitScalarExpr(D.getNumIterations());
7021 NumIterations = CGF.
Builder.CreateIntCast(NumIterations, CGF.
Int64Ty,
7023 return NumIterations;
7041 CGF.
EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
7046 StringRef ParentName,
7052 llvm::Constant *
Addr;
7054 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7056 assert(Fn &&
Addr &&
"Target device function emission failed.");
7070 const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams);
7071 llvm::Function *OutlinedFn =
7079 const Expr *NumTeams = NT ? NT->getNumTeams().front() :
nullptr;
7080 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() :
nullptr;
7086 OMPTeamsScope
Scope(CGF, S);
7102 CGF.
EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt());
7107 [](CodeGenFunction &) {
return nullptr; });
7112 auto *CS = S.getCapturedStmt(OMPD_teams);
7139 llvm::Constant *
Addr;
7141 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7143 assert(Fn &&
Addr &&
"Target device function emission failed.");
7185 llvm::Constant *
Addr;
7187 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7189 assert(Fn &&
Addr &&
"Target device function emission failed.");
7231 llvm::Constant *
Addr;
7233 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7235 assert(Fn &&
Addr &&
"Target device function emission failed.");
7249 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7254 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7266 [](CodeGenFunction &) {
return nullptr; });
7271 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7276 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7288 [](CodeGenFunction &) {
return nullptr; });
7293 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7299 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7311 [](CodeGenFunction &) {
return nullptr; });
7316 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7322 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7329 CGF, OMPD_distribute, CodeGenDistribute,
false);
7335 [](CodeGenFunction &) {
return nullptr; });
7339 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7340 llvm::Value *
Device =
nullptr;
7341 llvm::Value *NumDependences =
nullptr;
7342 llvm::Value *DependenceList =
nullptr;
7350 if (!
Data.Dependences.empty()) {
7352 std::tie(NumDependences, DependenciesArray) =
7353 CGM.getOpenMPRuntime().emitDependClause(*
this,
Data.Dependences,
7357 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
7362 "OMPNowaitClause clause is used separately in OMPInteropDirective.");
7365 if (!ItOMPInitClause.empty()) {
7368 llvm::Value *InteropvarPtr =
7370 llvm::omp::OMPInteropType InteropType =
7371 llvm::omp::OMPInteropType::Unknown;
7372 if (
C->getIsTarget()) {
7373 InteropType = llvm::omp::OMPInteropType::Target;
7375 assert(
C->getIsTargetSync() &&
7376 "Expected interop-type target/targetsync");
7377 InteropType = llvm::omp::OMPInteropType::TargetSync;
7379 OMPBuilder.createOMPInteropInit(
Builder, InteropvarPtr, InteropType,
7380 Device, NumDependences, DependenceList,
7381 Data.HasNowaitClause);
7385 if (!ItOMPDestroyClause.empty()) {
7388 llvm::Value *InteropvarPtr =
7390 OMPBuilder.createOMPInteropDestroy(
Builder, InteropvarPtr,
Device,
7391 NumDependences, DependenceList,
7392 Data.HasNowaitClause);
7395 auto ItOMPUseClause = S.getClausesOfKind<
OMPUseClause>();
7396 if (!ItOMPUseClause.empty()) {
7399 llvm::Value *InteropvarPtr =
7401 OMPBuilder.createOMPInteropUse(
Builder, InteropvarPtr,
Device,
7402 NumDependences, DependenceList,
7403 Data.HasNowaitClause);
7425 CGF, OMPD_distribute, CodeGenDistribute,
false);
7444 llvm::Constant *
Addr;
7446 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7448 assert(Fn &&
Addr &&
"Target device function emission failed.");
7477 CGF, OMPD_distribute, CodeGenDistribute,
false);
7496 llvm::Constant *
Addr;
7498 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7500 assert(Fn &&
Addr &&
"Target device function emission failed.");
7513 CGM.getOpenMPRuntime().emitCancellationPointCall(*
this, S.getBeginLoc(),
7518 const Expr *IfCond =
nullptr;
7519 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7520 if (
C->getNameModifier() == OMPD_unknown ||
7521 C->getNameModifier() == OMPD_cancel) {
7522 IfCond =
C->getCondition();
7526 if (
CGM.getLangOpts().OpenMPIRBuilder) {
7527 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7533 llvm::Value *IfCondition =
nullptr;
7537 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
7539 return Builder.restoreIP(AfterIP);
7543 CGM.getOpenMPRuntime().emitCancelCall(*
this, S.getBeginLoc(), IfCond,
7549 if (Kind == OMPD_parallel || Kind == OMPD_task ||
7550 Kind == OMPD_target_parallel || Kind == OMPD_taskloop ||
7551 Kind == OMPD_master_taskloop || Kind == OMPD_parallel_master_taskloop)
7553 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
7554 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
7555 Kind == OMPD_distribute_parallel_for ||
7556 Kind == OMPD_target_parallel_for ||
7557 Kind == OMPD_teams_distribute_parallel_for ||
7558 Kind == OMPD_target_teams_distribute_parallel_for);
7559 return OMPCancelStack.getExitBlock();
7564 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7565 CaptureDeviceAddrMap) {
7566 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7567 for (
const Expr *OrigVarIt :
C.varlist()) {
7569 if (!Processed.insert(OrigVD).second)
7576 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7581 "Base should be the current struct!");
7582 MatchingVD = ME->getMemberDecl();
7587 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7588 if (InitAddrIt == CaptureDeviceAddrMap.end())
7596 Address(InitAddrIt->second, Ty,
7598 assert(IsRegistered &&
"firstprivate var already registered as private");
7606 while (
const auto *OASE = dyn_cast<ArraySectionExpr>(
Base))
7607 Base = OASE->getBase()->IgnoreParenImpCasts();
7608 while (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(
Base))
7609 Base = ASE->getBase()->IgnoreParenImpCasts();
7615 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7616 CaptureDeviceAddrMap) {
7617 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7618 for (
const Expr *Ref :
C.varlist()) {
7620 if (!Processed.insert(OrigVD).second)
7626 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7631 "Base should be the current struct!");
7632 MatchingVD = ME->getMemberDecl();
7637 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7638 if (InitAddrIt == CaptureDeviceAddrMap.end())
7644 Address(InitAddrIt->second, Ty,
7657 (void)PrivateScope.
addPrivate(OrigVD, PrivAddr);
7665 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
7666 CGM.getOpenMPRuntime().registerVTable(S);
7674 bool PrivatizeDevicePointers =
false;
7676 bool &PrivatizeDevicePointers;
7679 explicit DevicePointerPrivActionTy(
bool &PrivatizeDevicePointers)
7680 : PrivatizeDevicePointers(PrivatizeDevicePointers) {}
7681 void Enter(CodeGenFunction &CGF)
override {
7682 PrivatizeDevicePointers =
true;
7685 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
7688 auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7689 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
7693 auto &&PrivCodeGen = [&](CodeGenFunction &CGF,
PrePostActionTy &Action) {
7695 PrivatizeDevicePointers =
false;
7701 if (PrivatizeDevicePointers) {
7715 std::optional<OpenMPDirectiveKind> CaptureRegion;
7716 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
7719 for (
const Expr *E :
C->varlist()) {
7721 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
7725 for (
const Expr *E :
C->varlist()) {
7727 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
7731 CaptureRegion = OMPD_unknown;
7734 OMPLexicalScope
Scope(CGF, S, CaptureRegion);
7746 OMPLexicalScope
Scope(CGF, S);
7755 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
7761 const Expr *IfCond =
nullptr;
7763 IfCond =
C->getCondition();
7774 CGM.getOpenMPRuntime().emitTargetDataCalls(*
this, S, IfCond,
Device, RCG,
7782 if (
CGM.getLangOpts().OMPTargetTriples.empty())
7786 const Expr *IfCond =
nullptr;
7788 IfCond =
C->getCondition();
7795 OMPLexicalScope
Scope(*
this, S, OMPD_task);
7796 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
7803 if (
CGM.getLangOpts().OMPTargetTriples.empty())
7807 const Expr *IfCond =
nullptr;
7809 IfCond =
C->getCondition();
7816 OMPLexicalScope
Scope(*
this, S, OMPD_task);
7817 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
7824 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
7852 llvm::Constant *
Addr;
7854 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7856 assert(Fn &&
Addr &&
"Target device function emission failed.");
7876 CGF, OMPD_target_parallel_for, S.
hasCancel());
7892 llvm::Constant *
Addr;
7894 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7896 assert(Fn &&
Addr &&
"Target device function emission failed.");
7931 llvm::Constant *
Addr;
7933 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7935 assert(Fn &&
Addr &&
"Target device function emission failed.");
7957 const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop);
7960 OMPLexicalScope
Scope(*
this, S, OMPD_taskloop,
false);
7965 const Expr *IfCond =
nullptr;
7966 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7967 if (
C->getNameModifier() == OMPD_unknown ||
7968 C->getNameModifier() == OMPD_taskloop) {
7969 IfCond =
C->getCondition();
7982 Data.Schedule.setInt(
false);
7985 (Clause->getModifier() == OMPC_GRAINSIZE_strict) ?
true :
false;
7988 Data.Schedule.setInt(
true);
7991 (Clause->getModifier() == OMPC_NUMTASKS_strict) ?
true :
false;
8005 llvm::BasicBlock *ContBlock =
nullptr;
8006 OMPLoopScope PreInitScope(CGF, S);
8007 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
8011 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock(
"taskloop.if.then");
8012 ContBlock = CGF.createBasicBlock(
"taskloop.if.end");
8013 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
8014 CGF.getProfileCount(&S));
8015 CGF.EmitBlock(ThenBlock);
8016 CGF.incrementProfileCounter(&S);
8019 (void)CGF.EmitOMPLinearClauseInit(S);
8023 enum { LowerBound = 5, UpperBound, Stride, LastIter };
8025 auto *LBP = std::next(I, LowerBound);
8026 auto *UBP = std::next(I, UpperBound);
8027 auto *STP = std::next(I, Stride);
8028 auto *LIP = std::next(I, LastIter);
8036 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
8037 CGF.EmitOMPLinearClause(S, LoopScope);
8038 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
8041 const Expr *IVExpr = S.getIterationVariable();
8043 CGF.EmitVarDecl(*IVDecl);
8044 CGF.EmitIgnoredExpr(S.getInit());
8049 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
8052 CGF.EmitIgnoredExpr(S.getCalcLastIteration());
8056 OMPLexicalScope
Scope(CGF, S, OMPD_taskloop,
false);
8066 [&S](CodeGenFunction &CGF) {
8067 emitOMPLoopBodyWithStopPoint(CGF, S,
8068 CodeGenFunction::JumpDest());
8070 [](CodeGenFunction &) {});
8075 CGF.EmitBranch(ContBlock);
8076 CGF.EmitBlock(ContBlock,
true);
8079 if (HasLastprivateClause) {
8080 CGF.EmitOMPLastprivateClauseFinal(
8082 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
8083 CGF.GetAddrOfLocalVar(*LIP),
false,
8084 (*LIP)->getType(), S.getBeginLoc())));
8087 CGF.EmitOMPLinearClauseFinal(S, [LIP, &S](CodeGenFunction &CGF) {
8088 return CGF.
Builder.CreateIsNotNull(
8090 (*LIP)->
getType(), S.getBeginLoc()));
8093 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
8094 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
8096 auto &&
CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
8098 OMPLoopScope PreInitScope(CGF, S);
8099 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S,
8100 OutlinedFn, SharedsTy,
8101 CapturedStruct, IfCond,
Data);
8103 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
8109 CGM.getOpenMPRuntime().emitTaskgroupRegion(
8111 [&S, &BodyGen, &TaskGen, &
Data](CodeGenFunction &CGF,
8131 OMPLexicalScope
Scope(*
this, S);
8143 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8144 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8155 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8156 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8167 OMPLexicalScope
Scope(*
this, S);
8168 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8179 OMPLexicalScope
Scope(*
this, S);
8180 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8186 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8191 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8192 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8204 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8209 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8210 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8222 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8227 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8228 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8240 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8245 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8246 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8260 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8264 const Expr *IfCond =
nullptr;
8266 IfCond =
C->getCondition();
8273 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8274 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8284 BindKind =
C->getBindKind();
8287 case OMPC_BIND_parallel:
8289 case OMPC_BIND_teams:
8291 case OMPC_BIND_thread:
8302 const auto *ForS = dyn_cast<ForStmt>(CS);
8313 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
8314 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_loop,
CodeGen);
8340 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
8345 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
8357 [](CodeGenFunction &) {
return nullptr; });
8362 std::string StatusMsg,
8366 StatusMsg +=
": DEVICE";
8368 StatusMsg +=
": HOST";
8375 llvm::dbgs() << StatusMsg <<
": " <<
FileName <<
": " << LineNo <<
"\n";
8398 CGF, OMPD_distribute, CodeGenDistribute,
false);
8427 CGF, OMPD_distribute, CodeGenDistribute,
false);
8460 llvm::Constant *
Addr;
8462 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8464 assert(Fn &&
Addr &&
8465 "Target device function emission failed for 'target teams loop'.");
8476 CGF, OMPD_target_parallel_loop,
false);
8492 llvm::Constant *
Addr;
8494 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8496 assert(Fn &&
Addr &&
"Target device function emission failed.");
8511 if (
const auto *SD = dyn_cast<OMPScanDirective>(&D)) {
8515 if (!D.hasAssociatedStmt() || !D.getAssociatedStmt())
8521 for (
const auto *
C : D.getClausesOfKind<OMPFirstprivateClause>()) {
8522 for (
const Expr *Ref :
C->varlist()) {
8526 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
8529 if (!CGF.LocalDeclMap.count(VD)) {
8541 if (
const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
8542 for (
const Expr *E : LD->counters()) {
8550 if (!CGF.LocalDeclMap.count(VD))
8554 for (
const auto *
C : D.getClausesOfKind<OMPOrderedClause>()) {
8555 if (!
C->getNumForLoops())
8557 for (
unsigned I = LD->getLoopsNumber(),
8558 E =
C->getLoopNumIterations().size();
8560 if (
const auto *VD = dyn_cast<OMPCapturedExprDecl>(
8563 if (!CGF.LocalDeclMap.count(VD))
8570 CGF.
EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
8573 if (D.getDirectiveKind() == OMPD_atomic ||
8574 D.getDirectiveKind() == OMPD_critical ||
8575 D.getDirectiveKind() == OMPD_section ||
8576 D.getDirectiveKind() == OMPD_master ||
8577 D.getDirectiveKind() == OMPD_masked ||
8578 D.getDirectiveKind() == OMPD_unroll ||
8579 D.getDirectiveKind() == OMPD_assume) {
8584 OMPSimdLexicalScope
Scope(*
this, D);
8585 CGM.getOpenMPRuntime().emitInlinedDirective(
8588 : D.getDirectiveKind(),
Defines the clang::ASTContext interface.
static bool isAllocatableDecl(const VarDecl *VD)
static const VarDecl * getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE)
static void emitTargetRegion(CodeGenFunction &CGF, const OMPTargetDirective &S, PrePostActionTy &Action)
static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S, PrePostActionTy &Action)
static const VarDecl * getBaseDecl(const Expr *Ref)
static void emitTargetTeamsGenericLoopRegionAsParallel(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsGenericLoopDirective &S)
static void emitOMPAtomicReadExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, const Expr *X, const Expr *V, SourceLocation Loc)
static void emitOMPAtomicCaptureExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, bool IsPostfixUpdate, const Expr *V, const Expr *X, const Expr *E, const Expr *UE, bool IsXLHSInRHSPart, SourceLocation Loc)
static void emitScanBasedDirective(CodeGenFunction &CGF, const OMPLoopDirective &S, llvm::function_ref< llvm::Value *(CodeGenFunction &)> NumIteratorsGen, llvm::function_ref< void(CodeGenFunction &)> FirstGen, llvm::function_ref< void(CodeGenFunction &)> SecondGen)
Emits the code for the directive with inscan reductions.
static void emitSimpleAtomicStore(CodeGenFunction &CGF, llvm::AtomicOrdering AO, LValue LVal, RValue RVal)
static bool isSupportedByOpenMPIRBuilder(const OMPTaskgroupDirective &T)
static Address castValueFromUintptr(CodeGenFunction &CGF, SourceLocation Loc, QualType DstType, StringRef Name, LValue AddrLV)
static void emitDistributeParallelForDistributeInnerBoundParams(CodeGenFunction &CGF, const OMPExecutableDirective &S, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars)
static void emitScanBasedDirectiveFinals(CodeGenFunction &CGF, const OMPLoopDirective &S, llvm::function_ref< llvm::Value *(CodeGenFunction &)> NumIteratorsGen)
Copies final inscan reductions values to the original variables.
static void checkForLastprivateConditionalUpdate(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static std::pair< LValue, LValue > emitForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S)
The following two functions generate expressions for the loop lower and upper bounds in case of stati...
static void emitTargetParallelForRegion(CodeGenFunction &CGF, const OMPTargetParallelForDirective &S, PrePostActionTy &Action)
static LValue EmitOMPHelperVar(CodeGenFunction &CGF, const DeclRefExpr *Helper)
Emit a helper variable and return corresponding lvalue.
static void emitOMPAtomicUpdateExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, const Expr *X, const Expr *E, const Expr *UE, bool IsXLHSInRHSPart, SourceLocation Loc)
static llvm::Value * convertToScalarValue(CodeGenFunction &CGF, RValue Val, QualType SrcType, QualType DestType, SourceLocation Loc)
static llvm::Function * emitOutlinedOrderedFunction(CodeGenModule &CGM, const CapturedStmt *S, const OMPExecutableDirective &D)
static void emitPreCond(CodeGenFunction &CGF, const OMPLoopDirective &S, const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount)
static std::pair< bool, RValue > emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X, RValue Update, BinaryOperatorKind BO, llvm::AtomicOrdering AO, bool IsXLHSInRHSPart)
static std::pair< LValue, LValue > emitDistributeParallelForInnerBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitTargetTeamsGenericLoopRegionAsDistribute(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsGenericLoopDirective &S)
static void emitTargetParallelRegion(CodeGenFunction &CGF, const OMPTargetParallelDirective &S, PrePostActionTy &Action)
static std::pair< llvm::Value *, llvm::Value * > emitDispatchForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S, Address LB, Address UB)
When dealing with dispatch schedules (e.g.
static void emitMaster(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitRestoreIP(CodeGenFunction &CGF, const T *C, llvm::OpenMPIRBuilder::InsertPointTy AllocaIP, llvm::OpenMPIRBuilder &OMPBuilder)
static void emitCommonOMPTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, const RegionCodeGenTy &CodeGen)
static void emitSimdlenSafelenClause(CodeGenFunction &CGF, const OMPExecutableDirective &D)
static void emitAlignedClause(CodeGenFunction &CGF, const OMPExecutableDirective &D)
static bool isSimdSupportedByOpenMPIRBuilder(const OMPLoopDirective &S)
static void emitCommonOMPParallelDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, const CodeGenBoundParametersTy &CodeGenBoundParameters)
static void applyConservativeSimdOrderedDirective(const Stmt &AssociatedStmt, LoopInfoStack &LoopStack)
static bool emitWorksharingDirective(CodeGenFunction &CGF, const OMPLoopDirective &S, bool HasCancel)
static void emitPostUpdateForReductionClause(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
static void emitEmptyOrdered(CodeGenFunction &, SourceLocation Loc, const unsigned IVSize, const bool IVSigned)
static void emitTargetTeamsLoopCodegenStatus(CodeGenFunction &CGF, std::string StatusMsg, const OMPExecutableDirective &D)
static bool isForSupportedByOpenMPIRBuilder(const OMPLoopDirective &S, bool HasCancel)
static RValue emitSimpleAtomicLoad(CodeGenFunction &CGF, llvm::AtomicOrdering AO, LValue LVal, SourceLocation Loc)
static std::pair< llvm::Value *, llvm::Value * > emitDistributeParallelForDispatchBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S, Address LB, Address UB)
if the 'for' loop has a dispatch schedule (e.g.
static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO, bool IsPostfixUpdate, const Expr *X, const Expr *V, const Expr *R, const Expr *E, const Expr *UE, const Expr *D, const Expr *CE, bool IsXLHSInRHSPart, bool IsFailOnly, SourceLocation Loc)
static CodeGenFunction::ComplexPairTy convertToComplexValue(CodeGenFunction &CGF, RValue Val, QualType SrcType, QualType DestType, SourceLocation Loc)
static ImplicitParamDecl * createImplicitFirstprivateForType(ASTContext &C, OMPTaskDataTy &Data, QualType Ty, CapturedDecl *CD, SourceLocation Loc)
static EmittedClosureTy emitCapturedStmtFunc(CodeGenFunction &ParentCGF, const CapturedStmt *S)
Emit a captured statement and return the function as well as its captured closure context.
static void emitOMPLoopBodyWithStopPoint(CodeGenFunction &CGF, const OMPLoopDirective &S, CodeGenFunction::JumpDest LoopExit)
static void emitOMPDistributeDirective(const OMPLoopDirective &S, CodeGenFunction &CGF, CodeGenModule &CGM)
static void emitOMPCopyinClause(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitTargetTeamsDistributeParallelForRegion(CodeGenFunction &CGF, const OMPTargetTeamsDistributeParallelForDirective &S, PrePostActionTy &Action)
static bool hasOrderedDirective(const Stmt *S)
static llvm::CallInst * emitCapturedStmtCall(CodeGenFunction &ParentCGF, EmittedClosureTy Cap, llvm::ArrayRef< llvm::Value * > Args)
Emit a call to a previously captured closure.
static void emitMasked(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitBody(CodeGenFunction &CGF, const Stmt *S, const Stmt *NextLoop, int MaxLevel, int Level=0)
static void emitOMPForDirective(const OMPLoopDirective &S, CodeGenFunction &CGF, CodeGenModule &CGM, bool HasCancel)
static void emitEmptyBoundParameters(CodeGenFunction &, const OMPExecutableDirective &, llvm::SmallVectorImpl< llvm::Value * > &)
static void emitTargetParallelForSimdRegion(CodeGenFunction &CGF, const OMPTargetParallelForSimdDirective &S, PrePostActionTy &Action)
static void emitOMPSimdDirective(const OMPLoopDirective &S, CodeGenFunction &CGF, CodeGenModule &CGM)
static void emitOMPAtomicCompareExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO, const Expr *X, const Expr *V, const Expr *R, const Expr *E, const Expr *D, const Expr *CE, bool IsXBinopExpr, bool IsPostfixUpdate, bool IsFailOnly, SourceLocation Loc)
std::pair< llvm::Function *, llvm::Value * > EmittedClosureTy
static OpenMPDirectiveKind getEffectiveDirectiveKind(const OMPExecutableDirective &S)
static void emitTargetTeamsRegion(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsDirective &S)
static void buildDependences(const OMPExecutableDirective &S, OMPTaskDataTy &Data)
static RValue convertToType(CodeGenFunction &CGF, RValue Value, QualType SourceType, QualType ResType, SourceLocation Loc)
static void emitScanBasedDirectiveDecls(CodeGenFunction &CGF, const OMPLoopDirective &S, llvm::function_ref< llvm::Value *(CodeGenFunction &)> NumIteratorsGen)
Emits internal temp array declarations for the directive with inscan reductions.
static void emitTargetTeamsDistributeParallelForSimdRegion(CodeGenFunction &CGF, const OMPTargetTeamsDistributeParallelForSimdDirective &S, PrePostActionTy &Action)
static void emitTargetTeamsDistributeSimdRegion(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsDistributeSimdDirective &S)
static llvm::MapVector< llvm::Value *, llvm::Value * > GetAlignedMapping(const OMPLoopDirective &S, CodeGenFunction &CGF)
static llvm::omp::ScheduleKind convertClauseKindToSchedKind(OpenMPScheduleClauseKind ScheduleClauseKind)
static void mapParam(CodeGenFunction &CGF, const DeclRefExpr *Helper, const ImplicitParamDecl *PVD, CodeGenFunction::OMPPrivateScope &Privates)
Emit a helper variable and return corresponding lvalue.
static void emitCommonOMPTeamsDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
static void emitTargetParallelGenericLoopRegion(CodeGenFunction &CGF, const OMPTargetParallelGenericLoopDirective &S, PrePostActionTy &Action)
static QualType getCanonicalParamType(ASTContext &C, QualType T)
static void emitCommonSimdLoop(CodeGenFunction &CGF, const OMPLoopDirective &S, const RegionCodeGenTy &SimdInitGen, const RegionCodeGenTy &BodyCodeGen)
static LValue createSectionLVal(CodeGenFunction &CGF, QualType Ty, const Twine &Name, llvm::Value *Init=nullptr)
static void emitOMPAtomicWriteExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, const Expr *X, const Expr *E, SourceLocation Loc)
static llvm::Function * emitOutlinedFunctionPrologue(CodeGenFunction &CGF, FunctionArgList &Args, llvm::MapVector< const Decl *, std::pair< const VarDecl *, Address > > &LocalAddrs, llvm::DenseMap< const Decl *, std::pair< const Expr *, llvm::Value * > > &VLASizes, llvm::Value *&CXXThisValue, const FunctionOptions &FO)
static void emitInnerParallelForWhenCombined(CodeGenFunction &CGF, const OMPLoopDirective &S, CodeGenFunction::JumpDest LoopExit)
static void emitTargetTeamsDistributeRegion(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsDistributeDirective &S)
This file defines OpenMP nodes for declarative directives.
static const Decl * getCanonicalDecl(const Decl *D)
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
Defines the PrettyStackTraceEntry class, which is used to make crashes give more contextual informati...
Defines the SourceManager interface.
This file defines OpenMP AST classes for executable directives and clauses.
This represents clause 'aligned' in the 'pragma omp ...' directives.
This represents 'bind' clause in the 'pragma omp ...' directives.
This represents 'pragma omp cancel' directive.
OpenMPDirectiveKind getCancelRegion() const
Get cancellation region for the current cancellation point.
This represents 'pragma omp cancellation point' directive.
OpenMPDirectiveKind getCancelRegion() const
Get cancellation region for the current cancellation point.
This represents clause 'copyin' in the 'pragma omp ...' directives.
This represents clause 'copyprivate' in the 'pragma omp ...' directives.
This represents implicit clause 'depend' for the 'pragma omp task' directive.
This represents implicit clause 'depobj' for the 'pragma omp depobj' directive. This clause does not ...
This represents 'destroy' clause in the 'pragma omp depobj' directive or the 'pragma omp interop' dir...
This represents 'device' clause in the 'pragma omp ...' directive.
This represents 'dist_schedule' clause in the 'pragma omp ...' directive.
This represents 'pragma omp distribute' directive.
This represents 'pragma omp distribute parallel for' composite directive.
This represents 'pragma omp distribute parallel for simd' composite directive.
This represents 'pragma omp distribute simd' composite directive.
This represents the 'doacross' clause for the 'pragma omp ordered' directive.
This represents 'pragma omp error' directive.
This represents 'filter' clause in the 'pragma omp ...' directive.
This represents implicit clause 'flush' for the 'pragma omp flush' directive. This clause does not ex...
Represents the 'pragma omp fuse' loop transformation directive.
Stmt * getTransformedStmt() const
Gets the associated loops after the transformation.
This represents 'pragma omp loop' directive.
This represents 'grainsize' clause in the 'pragma omp ...' directive.
This represents 'hint' clause in the 'pragma omp ...' directive.
This represents clause 'inclusive' in the 'pragma omp scan' directive.
This represents the 'init' clause in 'pragma omp ...' directives.
Represents the 'pragma omp interchange' loop transformation directive.
Stmt * getTransformedStmt() const
Gets the associated loops after the transformation.
This represents 'pragma omp interop' directive.
This represents 'pragma omp masked' directive.
This represents 'pragma omp masked taskloop' directive.
This represents 'pragma omp masked taskloop simd' directive.
This represents 'pragma omp master taskloop' directive.
This represents 'pragma omp master taskloop simd' directive.
This represents 'nogroup' clause in the 'pragma omp ...' directive.
This represents 'num_tasks' clause in the 'pragma omp ...' directive.
This represents 'num_teams' clause in the 'pragma omp ...' directive.
This represents 'order' clause in the 'pragma omp ...' directive.
This represents 'pragma omp parallel masked taskloop' directive.
This represents 'pragma omp parallel masked taskloop simd' directive.
This represents 'pragma omp parallel master taskloop' directive.
This represents 'pragma omp parallel master taskloop simd' directive.
This represents 'priority' clause in the 'pragma omp ...' directive.
Represents the 'pragma omp reverse' loop transformation directive.
Stmt * getTransformedStmt() const
Gets/sets the associated loops after the transformation, i.e.
This represents 'simd' clause in the 'pragma omp ...' directive.
This represents 'pragma omp scan' directive.
This represents the 'pragma omp stripe' loop transformation directive.
Stmt * getTransformedStmt() const
Gets/sets the associated loops after striping.
This represents 'pragma omp target data' directive.
This represents 'pragma omp target' directive.
This represents 'pragma omp target enter data' directive.
This represents 'pragma omp target exit data' directive.
This represents 'pragma omp target parallel' directive.
This represents 'pragma omp target parallel for' directive.
bool hasCancel() const
Return true if current directive has inner cancel directive.
This represents 'pragma omp target parallel for simd' directive.
This represents 'pragma omp target parallel loop' directive.
This represents 'pragma omp target simd' directive.
This represents 'pragma omp target teams' directive.
This represents 'pragma omp target teams distribute' combined directive.
This represents 'pragma omp target teams distribute parallel for' combined directive.
This represents 'pragma omp target teams distribute parallel for simd' combined directive.
This represents 'pragma omp target teams distribute simd' combined directive.
This represents 'pragma omp target teams loop' directive.
bool canBeParallelFor() const
Return true if current loop directive's associated loop can be a parallel for.
This represents 'pragma omp target update' directive.
This represents 'pragma omp taskloop' directive.
This represents 'pragma omp taskloop simd' directive.
This represents 'pragma omp teams' directive.
This represents 'pragma omp teams distribute' directive.
This represents 'pragma omp teams distribute parallel for' composite directive.
This represents 'pragma omp teams distribute parallel for simd' composite directive.
This represents 'pragma omp teams distribute simd' combined directive.
This represents 'pragma omp teams loop' directive.
This represents 'thread_limit' clause in the 'pragma omp ...' directive.
This represents the 'pragma omp tile' loop transformation directive.
Stmt * getTransformedStmt() const
Gets/sets the associated loops after tiling.
This represents the 'pragma omp unroll' loop transformation directive.
This represents the 'use' clause in 'pragma omp ...' directives.
This represents clause 'use_device_addr' in the 'pragma omp ...' directives.
This represents clause 'use_device_ptr' in the 'pragma omp ...' directives.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
TranslationUnitDecl * getTranslationUnitDecl() const
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
QualType getUIntPtrType() const
Return a type compatible with "uintptr_t" (C99 7.18.1.4), as defined by the target.
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
unsigned getOpenMPDefaultSimdAlign(QualType T) const
Get default simd alignment of the specified complete type in bits.
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
CanQualType getCanonicalTagType(const TagDecl *TD) const
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Represents an attribute applied to a statement.
ArrayRef< const Attr * > getAttrs() const
static BinaryOperator * Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, FPOptionsOverride FPFeatures)
Represents the body of a CapturedStmt, and serves as its DeclContext.
unsigned getContextParamPosition() const
static CapturedDecl * Create(ASTContext &C, DeclContext *DC, unsigned NumParams)
param_iterator param_end() const
Retrieve an iterator one past the last parameter decl.
param_iterator param_begin() const
Retrieve an iterator pointing to the first parameter decl.
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
ImplicitParamDecl * getParam(unsigned i) const
This captures a statement into a function.
SourceLocation getEndLoc() const LLVM_READONLY
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
const RecordDecl * getCapturedRecordDecl() const
Retrieve the record declaration for captured variables.
Stmt * getCapturedStmt()
Retrieve the statement being captured.
capture_init_iterator capture_init_begin()
Retrieve the first initialization argument.
SourceLocation getBeginLoc() const LLVM_READONLY
capture_init_iterator capture_init_end()
Retrieve the iterator pointing one past the last initialization argument.
Expr *const * const_capture_init_iterator
Const iterator that walks over the capture initialization arguments.
CharUnits - This is an opaque type for sizes expressed in character units.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
std::string SampleProfileFile
Name of the profile file to use with -fprofile-sample-use.
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
CharUnits getAlignment() const
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
Address withAlignment(CharUnits NewAlignment) const
Return address with different alignment, but same pointer and element type.
llvm::PointerType * getType() const
Return the type of the pointer value.
static AggValueSlot ignored()
ignored - Returns an aggregate value slot indicating that the aggregate value is being ignored.
static ApplyDebugLocation CreateDefaultArtificial(CodeGenFunction &CGF, SourceLocation TemporaryLocation)
Apply TemporaryLocation if it is valid.
Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
CGFunctionInfo - Class to encapsulate the information about a function definition.
Manages list of lastprivate conditional decls for the specified directive.
static LastprivateConditionalRAII disable(CodeGenFunction &CGF, const OMPExecutableDirective &S)
Manages list of nontemporal decls for the specified directive.
Struct that keeps all the relevant information that should be kept throughout a 'target data' region.
llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap
Map between the a declaration of a capture and the corresponding new llvm address where the runtime r...
Manages list of nontemporal decls for the specified directive.
virtual void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the task directive.
virtual llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST)
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
virtual void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr)
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
virtual void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, SourceLocation SeverityLoc=SourceLocation(), const Expr *Message=nullptr, SourceLocation MessageLoc=SourceLocation())
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_tid, kmp_int32 num_threads) ...
virtual Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal)
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
virtual void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc)
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
virtual void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars)
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
virtual const VarDecl * translateParameter(const FieldDecl *FD, const VarDecl *NativeParam) const
Translates the native parameter of outlined function if this is required for target.
virtual llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP teams directive D.
virtual void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef< Expr * > NumIterations)
Emit initialization for doacross loop nesting support.
virtual void adjustTargetSpecificDataForLambdas(CodeGenFunction &CGF, const OMPExecutableDirective &D) const
Adjust some parameters for the target-based directives, like addresses of the variables captured by r...
virtual Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const
Gets the address of the native argument basing on the address of the target-specific parameter.
virtual void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc)
Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32global_tid, kmp_int32 num_teams,...
virtual llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data)
Emit a code for initialization of task reduction clause.
virtual void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO)
Emit flush of the variables specified in 'omp flush' directive.
virtual void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc)
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32global_tid, int proc_bind) to generate...
virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false)
Emit an implicit/explicit barrier for OpenMP threads.
virtual void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values)
virtual void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind)
Call the appropriate runtime routine to notify that we finished all the work with current loop.
void emitIfClause(CodeGenFunction &CGF, const Expr *Cond, const RegionCodeGenTy &ThenGen, const RegionCodeGenTy &ElseGen)
Emits code for OpenMP 'if' clause using specified CodeGen function.
virtual llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP parallel directive D.
virtual void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values)
Call the appropriate runtime routine to initialize it before start of loop.
virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static non-chunked.
virtual void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc)
Emits a master region.
virtual void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Required to resolve existing problems in the runtime.
virtual void checkAndEmitLastprivateConditional(CodeGenFunction &CGF, const Expr *LHS)
Checks if the provided LVal is lastprivate conditional and emits the code to update the value of the ...
llvm::OpenMPIRBuilder & getOMPBuilder()
virtual void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Emit outilined function for 'target' directive.
virtual void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned)
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
virtual void checkAndEmitSharedLastprivateConditional(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::DenseSet< CanonicalDeclPtr< const VarDecl > > &IgnoredDecls)
Checks if the lastprivate conditional was updated in inner region and writes the value.
virtual void emitInlinedDirective(CodeGenFunction &CGF, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool HasCancel=false)
Emit code for the directive that does not require outlining.
virtual bool isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static chunked.
virtual void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Emit the target offloading code associated with D.
virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const
Check if the specified ScheduleKind is dynamic.
virtual void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr)
Emits a masked region.
virtual void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues)
Call the appropriate runtime routine to initialize it before start of loop.
Address getAllocatedAddress() const
Returns the raw, allocated address, which is not necessarily the address of the object itself.
API for captured statement code generation.
virtual const FieldDecl * lookup(const VarDecl *VD) const
Lookup the captured field decl for a variable.
RAII for correct setting/restoring of CapturedStmtInfo.
LValue getReferenceLValue(CodeGenFunction &CGF, const Expr *RefExpr) const
void ForceCleanup()
Force the emission of cleanups now, instead of waiting until this object is destroyed.
RAII for preserving necessary info during inlined region body codegen.
Cleanup action for allocate support.
RAII for preserving necessary info during Outlined region body codegen.
Controls insertion of cancellation exit blocks in worksharing constructs.
Save/restore original map of previously emitted local vars in case when we need to duplicate emission...
The class used to assign some variables some temporarily addresses.
bool apply(CodeGenFunction &CGF)
Applies new addresses to the list of the variables.
void restore(CodeGenFunction &CGF)
Restores original addresses of the variables.
bool setVarAddr(CodeGenFunction &CGF, const VarDecl *LocalVD, Address TempAddr)
Sets the address of the variable LocalVD to be TempAddr in function CGF.
The scope used to remap some variables as private in the OpenMP loop body (or other captured region e...
void restoreMap()
Restore all mapped variables w/o clean up.
bool Privatize()
Privatizes local variables previously registered as private.
bool addPrivate(const VarDecl *LocalVD, Address Addr)
Registers LocalVD variable as a private with Addr as the address of the corresponding private variabl...
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
Manages parent directive for scan directives.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
void ForceCleanup(std::initializer_list< llvm::Value ** > ValuesToReload={})
Force the emission of cleanups now, instead of waiting until this object is destroyed.
bool requiresCleanups() const
Determine whether this scope requires any cleanups.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void EmitOMPParallelMaskedTaskLoopDirective(const OMPParallelMaskedTaskLoopDirective &S)
void EmitOMPParallelMaskedDirective(const OMPParallelMaskedDirective &S)
void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S)
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr, const VarDecl *ConditionalDecl=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
void EmitOMPLastprivateClauseFinal(const OMPExecutableDirective &D, bool NoFinals, llvm::Value *IsLastIterCond=nullptr)
Emit final copying of lastprivate values to original variables at the end of the worksharing or simd ...
void processInReduction(const OMPExecutableDirective &S, OMPTaskDataTy &Data, CodeGenFunction &CGF, const CapturedStmt *CS, OMPPrivateScope &Scope)
JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target)
The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...
void EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S)
void emitOMPSimpleStore(LValue LVal, RValue RVal, QualType RValTy, SourceLocation Loc)
static void EmitOMPTargetParallelDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelDirective &S)
void EmitOMPCanonicalLoop(const OMPCanonicalLoop *S)
Emit an OMPCanonicalLoop using the OpenMPIRBuilder.
void EmitOMPGenericLoopDirective(const OMPGenericLoopDirective &S)
void EmitOMPScanDirective(const OMPScanDirective &S)
static bool hasScalarEvaluationKind(QualType T)
llvm::function_ref< std::pair< llvm::Value *, llvm::Value * >(CodeGenFunction &, const OMPExecutableDirective &S, Address LB, Address UB)> CodeGenDispatchBoundsTy
LValue InitCapturedStruct(const CapturedStmt &S)
CGCapturedStmtInfo * CapturedStmtInfo
void EmitOMPDistributeDirective(const OMPDistributeDirective &S)
void EmitOMPParallelForDirective(const OMPParallelForDirective &S)
void EmitOMPMasterDirective(const OMPMasterDirective &S)
void EmitOMPParallelMasterTaskLoopSimdDirective(const OMPParallelMasterTaskLoopSimdDirective &S)
void EmitOMPSimdInit(const OMPLoopDirective &D)
Helpers for the OpenMP loop directives.
const OMPExecutableDirective * OMPParentLoopDirectiveForScan
Parent loop-based directive for scan directive.
void EmitOMPFlushDirective(const OMPFlushDirective &S)
static void EmitOMPTargetDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetDirective &S)
Emit device code for the target directive.
bool EmitOMPFirstprivateClause(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
void EmitOMPTaskgroupDirective(const OMPTaskgroupDirective &S)
void EmitOMPTargetTeamsDistributeParallelForSimdDirective(const OMPTargetTeamsDistributeParallelForSimdDirective &S)
static void EmitOMPTargetTeamsDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDirective &S)
Emit device code for the target teams directive.
void EmitOMPReductionClauseInit(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope, bool ForInscan=false)
Emit initial code for reduction variables.
void EmitOMPDistributeSimdDirective(const OMPDistributeSimdDirective &S)
void EmitAutoVarDecl(const VarDecl &D)
EmitAutoVarDecl - Emit an auto variable declaration.
static void EmitOMPTargetTeamsDistributeDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeDirective &S)
Emit device code for the target teams distribute directive.
void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
void EmitOMPTargetParallelForDirective(const OMPTargetParallelForDirective &S)
const LangOptions & getLangOpts() const
LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
EmitAutoVarAlloca - Emit the alloca and debug information for a local variable.
void EmitAtomicUpdate(LValue LVal, llvm::AtomicOrdering AO, const llvm::function_ref< RValue(RValue)> &UpdateOp, bool IsVolatile)
Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr)
Load a pointer with type PtrTy stored at address Ptr.
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
void EmitOMPReductionClauseFinal(const OMPExecutableDirective &D, const OpenMPDirectiveKind ReductionKind)
Emit final update of reduction values to original variables at the end of the directive.
void EmitOMPLoopBody(const OMPLoopDirective &D, JumpDest LoopExit)
Helper for the OpenMP loop directives.
void EmitOMPScopeDirective(const OMPScopeDirective &S)
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
llvm::AssertingVH< llvm::Instruction > AllocaInsertPt
AllocaInsertPoint - This is an instruction in the entry block before which we prefer to insert alloca...
void EmitAggregateAssign(LValue Dest, LValue Src, QualType EltTy)
Emit an aggregate assignment.
CodeGenFunction * ParentCGF
JumpDest ReturnBlock
ReturnBlock - Unified return block.
void EmitOMPTargetTeamsDistributeSimdDirective(const OMPTargetTeamsDistributeSimdDirective &S)
const llvm::function_ref< void(CodeGenFunction &, llvm::Function *, const OMPTaskDataTy &)> TaskGenTy
llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Location)
Converts Location to a DebugLoc, if debug information is enabled.
bool EmitOMPCopyinClause(const OMPExecutableDirective &D)
Emit code for copyin clause in D directive.
void EmitOMPLinearClause(const OMPLoopDirective &D, CodeGenFunction::OMPPrivateScope &PrivateScope)
Emit initial code for linear clauses.
llvm::BasicBlock * OMPBeforeScanBlock
void EmitOMPInterchangeDirective(const OMPInterchangeDirective &S)
void EmitOMPPrivateLoopCounters(const OMPLoopDirective &S, OMPPrivateScope &LoopScope)
Emit initial code for loop counters of loop-based directives.
void GenerateOpenMPCapturedVars(const CapturedStmt &S, SmallVectorImpl< llvm::Value * > &CapturedVars)
void EmitOMPDepobjDirective(const OMPDepobjDirective &S)
void EmitOMPMetaDirective(const OMPMetaDirective &S)
void EmitOMPCriticalDirective(const OMPCriticalDirective &S)
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
void EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S)
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
void EmitOMPCancelDirective(const OMPCancelDirective &S)
void EmitOMPBarrierDirective(const OMPBarrierDirective &S)
llvm::Value * EmitComplexToScalarConversion(ComplexPairTy Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified complex type to the specified destination type,...
void EmitOMPOrderedDirective(const OMPOrderedDirective &S)
bool EmitOMPWorksharingLoop(const OMPLoopDirective &S, Expr *EUB, const CodeGenLoopBoundsTy &CodeGenLoopBounds, const CodeGenDispatchBoundsTy &CGDispatchBounds)
Emit code for the worksharing loop-based directive.
LValue EmitOMPSharedLValue(const Expr *E)
Emits the lvalue for the expression with possibly captured variable.
llvm::CanonicalLoopInfo * EmitOMPCollapsedCanonicalLoopNest(const Stmt *S, int Depth)
Emit the Stmt S and return its topmost canonical loop, if any.
void EmitOMPSectionsDirective(const OMPSectionsDirective &S)
void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())
Emit code for the start of a function.
void EmitOMPInteropDirective(const OMPInteropDirective &S)
void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S)
void EmitOMPTargetParallelDirective(const OMPTargetParallelDirective &S)
void EmitOMPCopy(QualType OriginalType, Address DestAddr, Address SrcAddr, const VarDecl *DestVD, const VarDecl *SrcVD, const Expr *Copy)
Emit proper copying of data from one variable to another.
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
JumpDest getOMPCancelDestination(OpenMPDirectiveKind Kind)
void EmitOMPTargetParallelForSimdDirective(const OMPTargetParallelForSimdDirective &S)
void EmitOMPTargetParallelGenericLoopDirective(const OMPTargetParallelGenericLoopDirective &S)
Emit combined directive 'target parallel loop' as if its constituent constructs are 'target',...
void EmitOMPUseDeviceAddrClause(const OMPUseDeviceAddrClause &C, OMPPrivateScope &PrivateScope, const llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap)
void EmitOMPTeamsDistributeParallelForSimdDirective(const OMPTeamsDistributeParallelForSimdDirective &S)
void EmitOMPMaskedDirective(const OMPMaskedDirective &S)
llvm::Value * emitArrayLength(const ArrayType *arrayType, QualType &baseType, Address &addr)
emitArrayLength - Compute the length of an array, even if it's a VLA, and drill down to the base elem...
void EmitOMPAggregateAssign(Address DestAddr, Address SrcAddr, QualType OriginalType, const llvm::function_ref< void(Address, Address)> CopyGen)
Perform element by element copying of arrays with type OriginalType from SrcAddr to DestAddr using co...
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
void EmitOMPTeamsDistributeSimdDirective(const OMPTeamsDistributeSimdDirective &S)
RValue EmitAtomicLoad(LValue LV, SourceLocation SL, AggValueSlot Slot=AggValueSlot::ignored())
CGDebugInfo * getDebugInfo()
void EmitOMPDistributeLoop(const OMPLoopDirective &S, const CodeGenLoopTy &CodeGenLoop, Expr *IncExpr)
Emit code for the distribute loop-based directive.
void EmitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective &S)
void EmitOMPReverseDirective(const OMPReverseDirective &S)
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
void EmitOMPCancellationPointDirective(const OMPCancellationPointDirective &S)
void EmitOMPTargetTeamsDistributeParallelForDirective(const OMPTargetTeamsDistributeParallelForDirective &S)
void EmitOMPMaskedTaskLoopDirective(const OMPMaskedTaskLoopDirective &S)
llvm::BasicBlock * OMPScanDispatch
llvm::function_ref< std::pair< LValue, LValue >(CodeGenFunction &, const OMPExecutableDirective &S)> CodeGenLoopBoundsTy
void EmitOMPTargetExitDataDirective(const OMPTargetExitDataDirective &S)
void EmitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &S)
void EmitOMPMaskedTaskLoopSimdDirective(const OMPMaskedTaskLoopSimdDirective &S)
std::pair< bool, RValue > EmitOMPAtomicSimpleUpdateExpr(LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart, llvm::AtomicOrdering AO, SourceLocation Loc, const llvm::function_ref< RValue(RValue)> CommonGen)
Emit atomic update code for constructs: X = X BO E or X = E BO E.
VlaSizePair getVLASize(const VariableArrayType *vla)
Returns an LLVM value that corresponds to the size, in non-variably-sized elements,...
void EmitOMPParallelDirective(const OMPParallelDirective &S)
void EmitOMPTaskDirective(const OMPTaskDirective &S)
void EmitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective &S)
void EmitOMPDistributeParallelForDirective(const OMPDistributeParallelForDirective &S)
void EmitOMPAssumeDirective(const OMPAssumeDirective &S)
int ExpectedOMPLoopDepth
Number of nested loop to be consumed by the last surrounding loop-associated directive.
void EmitOMPPrivateClause(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
void EmitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &S)
ASTContext & getContext() const
void EmitStopPoint(const Stmt *S)
EmitStopPoint - Emit a debug stoppoint if we are emitting debug info.
void EmitOMPTargetUpdateDirective(const OMPTargetUpdateDirective &S)
llvm::Value * EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, AlignmentSource Source=AlignmentSource::Type, bool isNontemporal=false)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
void EmitOMPTargetTeamsGenericLoopDirective(const OMPTargetTeamsGenericLoopDirective &S)
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
void EmitAutoVarCleanups(const AutoVarEmission &emission)
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
SmallVector< llvm::CanonicalLoopInfo *, 4 > OMPLoopNestStack
List of recently emitted OMPCanonicalLoops.
void EmitOMPTeamsDistributeParallelForDirective(const OMPTeamsDistributeParallelForDirective &S)
llvm::AtomicRMWInst * emitAtomicRMWInst(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val, llvm::AtomicOrdering Order=llvm::AtomicOrdering::SequentiallyConsistent, llvm::SyncScope::ID SSID=llvm::SyncScope::System, const AtomicExpr *AE=nullptr)
Emit an atomicrmw instruction, and applying relevant metadata when applicable.
void EmitOMPFuseDirective(const OMPFuseDirective &S)
void EmitOMPTargetTeamsDistributeDirective(const OMPTargetTeamsDistributeDirective &S)
void EmitOMPUseDevicePtrClause(const OMPUseDevicePtrClause &C, OMPPrivateScope &PrivateScope, const llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap)
RValue EmitAnyExpr(const Expr *E, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
EmitAnyExpr - Emit code to compute the specified expression which can have any type.
void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs={})
EmitStmt - Emit the code for the statement.
llvm::DenseMap< const ValueDecl *, FieldDecl * > LambdaCaptureFields
void EmitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &S)
llvm::Type * ConvertTypeForMem(QualType T)
void EmitOMPInnerLoop(const OMPExecutableDirective &S, bool RequiresCleanup, const Expr *LoopCond, const Expr *IncExpr, const llvm::function_ref< void(CodeGenFunction &)> BodyGen, const llvm::function_ref< void(CodeGenFunction &)> PostIncGen)
Emit inner loop of the worksharing/simd construct.
void EmitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective &S)
static void EmitOMPTargetTeamsDistributeParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForDirective &S)
void EmitOMPTargetDirective(const OMPTargetDirective &S)
static void EmitOMPTargetParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForSimdDirective &S)
Emit device code for the target parallel for simd directive.
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
llvm::BasicBlock * OMPScanExitBlock
void EmitOMPTeamsDirective(const OMPTeamsDirective &S)
void EmitSimpleOMPExecutableDirective(const OMPExecutableDirective &D)
Emit simple code for OpenMP directives in Simd-only mode.
void EmitOMPErrorDirective(const OMPErrorDirective &S)
void EmitOMPTargetTaskBasedDirective(const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen, OMPTargetDataInfo &InputInfo)
void EmitOMPParallelMaskedTaskLoopSimdDirective(const OMPParallelMaskedTaskLoopSimdDirective &S)
void EmitOMPTargetTeamsDirective(const OMPTargetTeamsDirective &S)
void EmitOMPTargetDataDirective(const OMPTargetDataDirective &S)
Address GenerateCapturedStmtArgument(const CapturedStmt &S)
bool EmitOMPLastprivateClauseInit(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
Emit initial code for lastprivate variables.
static void EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForSimdDirective &S)
Emit device code for the target teams distribute parallel for simd directive.
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
llvm::Function * GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S, const OMPExecutableDirective &D)
void EmitOMPSimdDirective(const OMPSimdDirective &S)
RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
Address EmitLoadOfReference(LValue RefLVal, LValueBaseInfo *PointeeBaseInfo=nullptr, TBAAAccessInfo *PointeeTBAAInfo=nullptr)
void EmitOMPParallelGenericLoopDirective(const OMPLoopDirective &S)
void EmitOMPTargetSimdDirective(const OMPTargetSimdDirective &S)
void EmitOMPTeamsGenericLoopDirective(const OMPTeamsGenericLoopDirective &S)
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
bool EmitOMPLinearClauseInit(const OMPLoopDirective &D)
Emit initial code for linear variables.
static void EmitOMPTargetParallelGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelGenericLoopDirective &S)
Emit device code for the target parallel loop directive.
void EmitOMPUnrollDirective(const OMPUnrollDirective &S)
void EmitOMPStripeDirective(const OMPStripeDirective &S)
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitOMPSingleDirective(const OMPSingleDirective &S)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
llvm::function_ref< void(CodeGenFunction &, SourceLocation, const unsigned, const bool)> CodeGenOrderedTy
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
llvm::Value * EmitFromMemory(llvm::Value *Value, QualType Ty)
EmitFromMemory - Change a scalar value from its memory representation to its value representation.
static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S)
Emit device code for the target simd directive.
llvm::Function * GenerateCapturedStmtFunction(const CapturedStmt &S)
Creates the outlined function for a CapturedStmt.
static void EmitOMPTargetParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForDirective &S)
Emit device code for the target parallel for directive.
uint64_t getProfileCount(const Stmt *S)
Get the profiler's count for the given statement.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)
ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant,...
static void EmitOMPTargetTeamsGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsGenericLoopDirective &S)
Emit device code for the target teams loop directive.
void EmitOMPTileDirective(const OMPTileDirective &S)
void EmitDecl(const Decl &D, bool EvaluateConditionDecl=false)
EmitDecl - Emit a declaration.
void EmitOMPAtomicDirective(const OMPAtomicDirective &S)
llvm::BasicBlock * OMPAfterScanBlock
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
ConstantEmission tryEmitAsConstant(const DeclRefExpr *RefExpr)
Try to emit a reference to the given value without producing it as an l-value.
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
void EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst)
Store of global named registers are always calls to intrinsics.
void EmitOMPParallelMasterTaskLoopDirective(const OMPParallelMasterTaskLoopDirective &S)
void EmitOMPDistributeParallelForSimdDirective(const OMPDistributeParallelForSimdDirective &S)
void EmitOMPSectionDirective(const OMPSectionDirective &S)
void EnsureInsertPoint()
EnsureInsertPoint - Ensure that an insertion point is defined so that emitted IR has a place to go.
void EmitOMPForSimdDirective(const OMPForSimdDirective &S)
llvm::LLVMContext & getLLVMContext()
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
void emitAlignmentAssumption(llvm::Value *PtrValue, QualType Ty, SourceLocation Loc, SourceLocation AssumptionLoc, llvm::Value *Alignment, llvm::Value *OffsetValue=nullptr)
static void EmitOMPTargetTeamsDistributeSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeSimdDirective &S)
Emit device code for the target teams distribute simd directive.
llvm::function_ref< void(CodeGenFunction &, const OMPLoopDirective &, JumpDest)> CodeGenLoopTy
llvm::Value * EmitScalarConversion(llvm::Value *Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified type to the specified destination type, both of which are LLVM s...
bool isTrivialInitializer(const Expr *Init)
Determine whether the given initializer is trivial in the sense that it requires no code to be genera...
void EmitOMPParallelMasterDirective(const OMPParallelMasterDirective &S)
void EmitOMPTaskBasedDirective(const OMPExecutableDirective &S, const OpenMPDirectiveKind CapturedRegion, const RegionCodeGenTy &BodyGen, const TaskGenTy &TaskGen, OMPTaskDataTy &Data)
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
void EmitOMPForDirective(const OMPForDirective &S)
void EmitOMPLinearClauseFinal(const OMPLoopDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
Emit final code for linear clauses.
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
void EmitExprAsInit(const Expr *init, const ValueDecl *D, LValue lvalue, bool capturedByInit)
EmitExprAsInit - Emits the code necessary to initialize a location in memory with the given initializ...
void EmitOMPSimdFinal(const OMPLoopDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
This class organizes the cross-function state that is used while generating LLVM code.
void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)
Set the attributes on the LLVM function for the given decl and function info.
llvm::Module & getModule() const
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
CodeGenTypes & getTypes()
const llvm::DataLayout & getDataLayout() const
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
ASTContext & getContext() const
const CodeGenOptions & getCodeGenOpts() const
StringRef getMangledName(GlobalDecl GD)
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
const CGFunctionInfo & arrangeDeviceKernelCallerDeclaration(QualType resultType, const FunctionArgList &args)
A device kernel caller function is an offload device entry point function with a target device depend...
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
llvm::Value * getPointer(CodeGenFunction &CGF) const
Address getAddress() const
void setAddress(Address address)
A stack of loop information corresponding to loop nesting levels.
void setVectorizeWidth(unsigned W)
Set the vectorize width for the next loop pushed.
void setParallel(bool Enable=true)
Set the next pushed loop as parallel.
void push(llvm::BasicBlock *Header, const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc)
Begin a new structured loop.
void setVectorizeEnable(bool Enable=true)
Set the next pushed loop 'vectorize.enable'.
A basic class for pre|post-action for advanced codegen sequence for OpenMP region.
virtual void Enter(CodeGenFunction &CGF)
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
static RValue getComplex(llvm::Value *V1, llvm::Value *V2)
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
std::pair< llvm::Value *, llvm::Value * > getComplexVal() const
getComplexVal - Return the real/imag components of this complex value.
An abstract representation of an aligned address.
llvm::PointerType * getType() const
Return the type of the pointer value.
llvm::Value * getPointer() const
Class intended to support codegen of all kind of the reduction clauses.
LValue getSharedLValue(unsigned N) const
Returns LValue for the reduction item.
void emitAggregateType(CodeGenFunction &CGF, unsigned N)
Emits the code for the variable-modified type, if required.
const VarDecl * getBaseDecl(unsigned N) const
Returns the base declaration of the reduction item.
void emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N)
Emits lvalue for the shared and original reduction item.
void emitInitialization(CodeGenFunction &CGF, unsigned N, Address PrivateAddr, Address SharedAddr, llvm::function_ref< bool(CodeGenFunction &)> DefaultInit)
Performs initialization of the private copy for the reduction item.
Address adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Adjusts PrivatedAddr for using instead of the original variable address in normal operations.
Class provides a way to call simple version of codegen for OpenMP region, or an advanced with possibl...
void setAction(PrePostActionTy &Action) const
Complex values, per C99 6.2.5p11.
CompoundStmt - This represents a group of statements like { stmt stmt }.
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
A reference to a declared variable, function, enum, etc.
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Decl - This represents one declaration (or definition), e.g.
SourceLocation getBodyRBrace() const
getBodyRBrace - Gets the right brace of the body, if a body exists.
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
SourceLocation getLocation() const
The name of a declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreImplicitAsWritten() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
Represents a function declaration or definition.
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin=false, bool isInlineSpecified=false, bool hasWrittenPrototype=true, ConstexprSpecKind ConstexprKind=ConstexprSpecKind::Unspecified, const AssociatedConstraint &TrailingRequiresClause={})
GlobalDecl - represents a global declaration.
One of these records is kept for each identifier that is lexed.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
std::vector< llvm::Triple > OMPTargetTriples
Triples of the OpenMP targets that the host code codegen should take into account in order to generat...
Represents a point when we exit a loop.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
A C++ nested-name-specifier augmented with source location information.
static OMPClauseWithPreInit * get(OMPClause *C)
This is a basic class for representing single OpenMP clause.
This represents 'final' clause in the 'pragma omp ...' directive.
Representation of the 'full' clause of the 'pragma omp unroll' directive.
This represents 'if' clause in the 'pragma omp ...' directive.
This represents 'num_threads' clause in the 'pragma omp ...' directive.
Representation of the 'partial' clause of the 'pragma omp unroll' directive.
This represents 'safelen' clause in the 'pragma omp ...' directive.
This represents 'simdlen' clause in the 'pragma omp ...' directive.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
PointerType - C99 6.7.5.1 - Pointer Declarators.
Represents an unpacked "presumed" location which can be presented to the user.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
If a crash happens while one of these objects are live, the message is printed out along with the spe...
A (possibly-)qualified type.
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Represents a struct/union/class.
field_range fields() const
field_iterator field_begin() const
Base for LValueReferenceType and RValueReferenceType.
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
Stmt - This represents one statement.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
SourceLocation getBeginLoc() const LLVM_READONLY
bool isPointerType() const
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isLValueReferenceType() const
bool isAnyComplexType() const
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
static UnaryOperator * Create(const ASTContext &C, Expr *input, Opcode opc, QualType type, ExprValueKind VK, ExprObjectKind OK, SourceLocation l, bool CanOverflow, FPOptionsOverride FPFeatures)
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
TLSKind getTLSKind() const
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
@ CInit
C-style initialization with assignment.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
const Expr * getInit() const
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
@ TLS_None
Not a TLS variable.
Represents a C array with a specified size that is not an integer-constant-expression.
Expr * getSizeExpr() const
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
bool Inc(InterpState &S, CodePtr OpPC, bool CanOverflow)
1) Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value increased by ...
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool needsTaskBasedThreadLimit(OpenMPDirectiveKind DKind)
Checks if the specified target directive, combined or not, needs task based thread_limit.
@ Ctor_Complete
Complete object ctor.
Privates[]
This class represents the 'transparent' clause in the 'pragma omp task' directive.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
@ OK_Ordinary
An ordinary object is located at an address in memory.
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ Tile
'tile' clause, allowed on 'loop' and Combined constructs.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_unknown
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
@ OMPC_DIST_SCHEDULE_unknown
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
bool isOpenMPGenericLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive constitutes a 'loop' directive in the outermost nest.
OpenMPBindClauseKind
OpenMP bindings for the 'bind' clause.
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