28#include "llvm/ADT/SmallSet.h"
29#include "llvm/BinaryFormat/Dwarf.h"
30#include "llvm/Frontend/OpenMP/OMPConstants.h"
31#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
32#include "llvm/IR/Constants.h"
33#include "llvm/IR/DebugInfoMetadata.h"
34#include "llvm/IR/Instructions.h"
35#include "llvm/IR/IntrinsicInst.h"
36#include "llvm/IR/Metadata.h"
37#include "llvm/Support/AtomicOrdering.h"
38#include "llvm/Support/Debug.h"
41using namespace CodeGen;
42using namespace llvm::omp;
44#define TTL_CODEGEN_TYPE "target-teams-loop-codegen"
53class OMPLexicalScope :
public CodeGenFunction::LexicalScope {
55 for (
const auto *
C : S.clauses()) {
57 if (
const auto *PreInit =
58 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
59 for (
const auto *I : PreInit->decls()) {
60 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
63 CodeGenFunction::AutoVarEmission Emission =
72 CodeGenFunction::OMPPrivateScope InlinedShareds;
78 cast<BlockDecl>(CGF.
CurCodeDecl)->capturesVariable(VD));
84 const std::optional<OpenMPDirectiveKind> CapturedRegion = std::nullopt,
85 const bool EmitPreInitStmt =
true)
89 emitPreInitStmt(CGF, S);
92 assert(S.hasAssociatedStmt() &&
93 "Expected associated statement for inlined directive.");
94 const CapturedStmt *CS = S.getCapturedStmt(*CapturedRegion);
96 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
97 auto *VD =
C.getCapturedVar();
99 "Canonical decl must be captured.");
103 InlinedShareds.isGlobalVarCaptured(VD)),
108 (void)InlinedShareds.Privatize();
114class OMPParallelScope final :
public OMPLexicalScope {
124 : OMPLexicalScope(CGF, S,
std::nullopt,
125 EmitPreInitStmt(S)) {}
130class OMPTeamsScope final :
public OMPLexicalScope {
139 : OMPLexicalScope(CGF, S,
std::nullopt,
140 EmitPreInitStmt(S)) {}
145class OMPLoopScope :
public CodeGenFunction::RunCleanupsScope {
147 const Stmt *PreInits;
148 CodeGenFunction::OMPMapVars PreCondVars;
149 if (
auto *LD = dyn_cast<OMPLoopDirective>(&S)) {
150 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
151 for (
const auto *
E : LD->counters()) {
152 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
154 (void)PreCondVars.setVarAddr(
159 for (
const Expr *IRef :
C->varlist()) {
161 cast<VarDecl>(cast<DeclRefExpr>(IRef)->getDecl());
162 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
163 QualType OrigVDTy = OrigVD->getType().getNonReferenceType();
164 (void)PreCondVars.setVarAddr(
173 (void)PreCondVars.apply(CGF);
176 LD->getInnermostCapturedStmt()->getCapturedStmt(),
177 true, LD->getLoopsNumber(),
178 [&CGF](
unsigned Cnt,
const Stmt *CurStmt) {
179 if (
const auto *CXXFor = dyn_cast<CXXForRangeStmt>(CurStmt)) {
180 if (
const Stmt *
Init = CXXFor->getInit())
182 CGF.
EmitStmt(CXXFor->getRangeStmt());
187 PreInits = LD->getPreInits();
188 }
else if (
const auto *
Tile = dyn_cast<OMPTileDirective>(&S)) {
189 PreInits =
Tile->getPreInits();
190 }
else if (
const auto *Unroll = dyn_cast<OMPUnrollDirective>(&S)) {
191 PreInits = Unroll->getPreInits();
192 }
else if (
const auto *Reverse = dyn_cast<OMPReverseDirective>(&S)) {
193 PreInits = Reverse->getPreInits();
194 }
else if (
const auto *Interchange =
195 dyn_cast<OMPInterchangeDirective>(&S)) {
196 PreInits = Interchange->getPreInits();
198 llvm_unreachable(
"Unknown loop-based directive kind.");
205 if (
auto *PreInitCompound = dyn_cast<CompoundStmt>(PreInits))
206 llvm::append_range(PreInitStmts, PreInitCompound->body());
208 PreInitStmts.push_back(PreInits);
210 for (
const Stmt *S : PreInitStmts) {
213 if (
auto *PreInitDecl = dyn_cast<DeclStmt>(S)) {
214 for (
Decl *I : PreInitDecl->decls())
221 PreCondVars.restore(CGF);
227 emitPreInitStmt(CGF, S);
231class OMPSimdLexicalScope :
public CodeGenFunction::LexicalScope {
232 CodeGenFunction::OMPPrivateScope InlinedShareds;
238 cast<BlockDecl>(CGF.
CurCodeDecl)->capturesVariable(VD));
244 InlinedShareds(CGF) {
245 for (
const auto *
C : S.clauses()) {
247 if (
const auto *PreInit =
248 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
249 for (
const auto *I : PreInit->decls()) {
250 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
253 CodeGenFunction::AutoVarEmission Emission =
259 }
else if (
const auto *UDP = dyn_cast<OMPUseDevicePtrClause>(
C)) {
260 for (
const Expr *
E : UDP->varlist()) {
261 const Decl *
D = cast<DeclRefExpr>(
E)->getDecl();
262 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(
D))
265 }
else if (
const auto *UDP = dyn_cast<OMPUseDeviceAddrClause>(
C)) {
266 for (
const Expr *
E : UDP->varlist()) {
268 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(
D))
275 if (
const auto *TG = dyn_cast<OMPTaskgroupDirective>(&S)) {
276 if (
const Expr *
E = TG->getReductionRef())
277 CGF.
EmitVarDecl(*cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl()));
281 llvm::DenseSet<CanonicalDeclPtr<const Decl>> CopyArrayTemps;
283 if (
C->getModifier() != OMPC_REDUCTION_inscan)
285 for (
const Expr *
E :
C->copy_array_temps())
286 CopyArrayTemps.insert(cast<DeclRefExpr>(
E)->getDecl());
288 const auto *CS = cast_or_null<CapturedStmt>(S.getAssociatedStmt());
291 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
292 auto *VD =
C.getCapturedVar();
293 if (CopyArrayTemps.contains(VD))
296 "Canonical decl must be captured.");
298 isCapturedVar(CGF, VD) ||
300 InlinedShareds.isGlobalVarCaptured(VD)),
308 (void)InlinedShareds.Privatize();
319 if (Kind != OMPD_loop)
324 BindKind =
C->getBindKind();
327 case OMPC_BIND_parallel:
329 case OMPC_BIND_teams:
330 return OMPD_distribute;
331 case OMPC_BIND_thread:
342LValue CodeGenFunction::EmitOMPSharedLValue(
const Expr *
E) {
343 if (
const auto *OrigDRE = dyn_cast<DeclRefExpr>(
E)) {
344 if (
const auto *OrigVD = dyn_cast<VarDecl>(OrigDRE->getDecl())) {
345 OrigVD = OrigVD->getCanonicalDecl();
360 llvm::Value *
Size =
nullptr;
361 auto SizeInChars =
C.getTypeSizeInChars(Ty);
362 if (SizeInChars.isZero()) {
368 Size ?
Builder.CreateNUWMul(Size, VlaSize.NumElts) : VlaSize.NumElts;
370 SizeInChars =
C.getTypeSizeInChars(Ty);
371 if (SizeInChars.isZero())
372 return llvm::ConstantInt::get(
SizeTy, 0);
380 const RecordDecl *RD = S.getCapturedRecordDecl();
382 auto CurCap = S.captures().begin();
384 E = S.capture_init_end();
385 I !=
E; ++I, ++CurField, ++CurCap) {
386 if (CurField->hasCapturedVLAType()) {
389 CapturedVars.push_back(Val);
390 }
else if (CurCap->capturesThis()) {
391 CapturedVars.push_back(CXXThisValue);
392 }
else if (CurCap->capturesVariableByCopy()) {
397 if (!CurField->getType()->isAnyPointerType()) {
401 Twine(CurCap->getCapturedVar()->getName(),
".casted"));
417 CapturedVars.push_back(CV);
419 assert(CurCap->capturesVariable() &&
"Expected capture by reference.");
441 return C.getLValueReferenceType(
447 if (
const auto *VLA = dyn_cast<VariableArrayType>(A))
449 if (!A->isVariablyModifiedType())
450 return C.getCanonicalType(
T);
452 return C.getCanonicalParamType(
T);
457struct FunctionOptions {
462 const bool UIntPtrCastRequired =
true;
465 const bool RegisterCastedArgsOnly =
false;
467 const StringRef FunctionName;
470 explicit FunctionOptions(
const CapturedStmt *S,
bool UIntPtrCastRequired,
471 bool RegisterCastedArgsOnly, StringRef FunctionName,
473 : S(S), UIntPtrCastRequired(UIntPtrCastRequired),
474 RegisterCastedArgsOnly(UIntPtrCastRequired && RegisterCastedArgsOnly),
475 FunctionName(FunctionName),
Loc(
Loc) {}
481 llvm::MapVector<
const Decl *, std::pair<const VarDecl *, Address>>
483 llvm::DenseMap<
const Decl *, std::pair<const Expr *, llvm::Value *>>
485 llvm::Value *&CXXThisValue,
const FunctionOptions &FO) {
487 const RecordDecl *RD = FO.S->getCapturedRecordDecl();
488 assert(CD->
hasBody() &&
"missing CapturedDecl body");
490 CXXThisValue =
nullptr;
500 auto I = FO.S->captures().begin();
502 if (!FO.UIntPtrCastRequired) {
522 if (FO.UIntPtrCastRequired &&
524 I->capturesVariableArrayType()))
527 if (I->capturesVariable() || I->capturesVariableByCopy()) {
528 CapVar = I->getCapturedVar();
530 }
else if (I->capturesThis()) {
533 assert(I->capturesVariableArrayType());
543 }
else if (DebugFunctionDecl && (CapVar || I->capturesThis())) {
545 Ctx, DebugFunctionDecl,
546 CapVar ? CapVar->
getBeginLoc() : FD->getBeginLoc(),
547 CapVar ? CapVar->
getLocation() : FD->getLocation(), II, ArgType,
553 Args.emplace_back(Arg);
555 TargetArgs.emplace_back(
556 FO.UIntPtrCastRequired
573 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
577 F->setDoesNotThrow();
578 F->setDoesNotRecurse();
582 F->removeFnAttr(llvm::Attribute::NoInline);
583 F->addFnAttr(llvm::Attribute::AlwaysInline);
588 FO.UIntPtrCastRequired ? FO.Loc : FO.S->getBeginLoc(),
589 FO.UIntPtrCastRequired ? FO.Loc
592 I = FO.S->captures().begin();
596 if (!FO.UIntPtrCastRequired && Args[Cnt] != TargetArgs[Cnt]) {
604 if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
605 const VarDecl *CurVD = I->getCapturedVar();
606 if (!FO.RegisterCastedArgsOnly)
607 LocalAddrs.insert({Args[Cnt], {CurVD, LocalAddr}});
615 if (FD->hasCapturedVLAType()) {
616 if (FO.UIntPtrCastRequired) {
619 Args[Cnt]->getName(), ArgLVal),
624 VLASizes.try_emplace(Args[Cnt], VAT->
getSizeExpr(), ExprArg);
625 }
else if (I->capturesVariable()) {
626 const VarDecl *Var = I->getCapturedVar();
636 if (!FO.RegisterCastedArgsOnly) {
640 }
else if (I->capturesVariableByCopy()) {
641 assert(!FD->getType()->isAnyPointerType() &&
642 "Not expecting a captured pointer.");
643 const VarDecl *Var = I->getCapturedVar();
644 LocalAddrs.insert({Args[Cnt],
645 {Var, FO.UIntPtrCastRequired
647 CGF, I->getLocation(), FD->getType(),
648 Args[Cnt]->getName(), ArgLVal)
652 assert(I->capturesThis());
654 LocalAddrs.insert({Args[Cnt], {
nullptr, ArgLVal.
getAddress()}});
668 "CapturedStmtInfo should be set when generating the captured function");
671 bool NeedWrapperFunction =
674 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs,
676 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes,
679 llvm::raw_svector_ostream Out(Buffer);
683 llvm::Function *WrapperF =
nullptr;
684 if (NeedWrapperFunction) {
687 FunctionOptions WrapperFO(&S,
true,
693 WrapperCGF.CXXThisValue, WrapperFO);
696 FunctionOptions FO(&S, !NeedWrapperFunction,
false,
699 *
this, WrapperArgs, WrapperLocalAddrs, WrapperVLASizes, CXXThisValue, FO);
700 CodeGenFunction::OMPPrivateScope LocalScope(*
this);
701 for (
const auto &LocalAddrPair : WrapperLocalAddrs) {
702 if (LocalAddrPair.second.first) {
703 LocalScope.addPrivate(LocalAddrPair.second.first,
704 LocalAddrPair.second.second);
707 (void)LocalScope.Privatize();
708 for (
const auto &VLASizePair : WrapperVLASizes)
709 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
712 (void)LocalScope.ForceCleanup();
714 if (!NeedWrapperFunction)
718 WrapperF->removeFromParent();
719 F->getParent()->getFunctionList().insertAfter(F->getIterator(), WrapperF);
722 auto *PI = F->arg_begin();
723 for (
const auto *Arg : Args) {
725 auto I = LocalAddrs.find(Arg);
726 if (I != LocalAddrs.end()) {
727 LValue LV = WrapperCGF.MakeAddrLValue(
729 I->second.first ? I->second.first->getType() : Arg->getType(),
733 CallArg = WrapperCGF.EmitLoadOfScalar(LV, S.getBeginLoc());
735 auto EI = VLASizes.find(Arg);
736 if (EI != VLASizes.end()) {
740 WrapperCGF.MakeAddrLValue(WrapperCGF.GetAddrOfLocalVar(Arg),
742 CallArg = WrapperCGF.EmitLoadOfScalar(LV, S.getBeginLoc());
745 CallArgs.emplace_back(WrapperCGF.EmitFromMemory(
CallArg, Arg->
getType()));
749 WrapperCGF.FinishFunction();
764 llvm::Value *NumElements =
emitArrayLength(ArrayTy, ElementTy, DestAddr);
771 DestBegin, NumElements);
776 llvm::Value *IsEmpty =
777 Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arraycpy.isempty");
778 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
781 llvm::BasicBlock *EntryBB =
Builder.GetInsertBlock();
786 llvm::PHINode *SrcElementPHI =
787 Builder.CreatePHI(SrcBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
788 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
793 llvm::PHINode *DestElementPHI =
Builder.CreatePHI(
794 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
795 DestElementPHI->addIncoming(DestBegin, EntryBB);
801 CopyGen(DestElementCurrent, SrcElementCurrent);
804 llvm::Value *DestElementNext =
806 1,
"omp.arraycpy.dest.element");
807 llvm::Value *SrcElementNext =
809 1,
"omp.arraycpy.src.element");
812 Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
813 Builder.CreateCondBr(Done, DoneBB, BodyBB);
814 DestElementPHI->addIncoming(DestElementNext,
Builder.GetInsertBlock());
815 SrcElementPHI->addIncoming(SrcElementNext,
Builder.GetInsertBlock());
825 const auto *BO = dyn_cast<BinaryOperator>(
Copy);
826 if (BO && BO->getOpcode() == BO_Assign) {
835 DestAddr, SrcAddr, OriginalType,
840 CodeGenFunction::OMPPrivateScope Remap(*
this);
841 Remap.addPrivate(DestVD, DestElement);
842 Remap.addPrivate(SrcVD, SrcElement);
843 (void)Remap.Privatize();
849 CodeGenFunction::OMPPrivateScope Remap(*
this);
850 Remap.addPrivate(SrcVD, SrcAddr);
851 Remap.addPrivate(DestVD, DestAddr);
852 (void)Remap.Privatize();
859 OMPPrivateScope &PrivateScope) {
863 bool DeviceConstTarget =
getLangOpts().OpenMPIsTargetDevice &&
865 bool FirstprivateIsLastprivate =
false;
866 llvm::DenseMap<const VarDecl *, OpenMPLastprivateModifier> Lastprivates;
868 for (
const auto *
D :
C->varlist())
869 Lastprivates.try_emplace(
873 llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
878 bool MustEmitFirstprivateCopy =
879 CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown;
881 const auto *IRef =
C->varlist_begin();
882 const auto *InitsRef =
C->inits().begin();
883 for (
const Expr *IInit :
C->private_copies()) {
884 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
885 bool ThisFirstprivateIsLastprivate =
886 Lastprivates.count(OrigVD->getCanonicalDecl()) > 0;
888 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
889 if (!MustEmitFirstprivateCopy && !ThisFirstprivateIsLastprivate && FD &&
891 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
892 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
899 if (DeviceConstTarget && OrigVD->getType().isConstant(
getContext()) &&
901 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
902 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
907 FirstprivateIsLastprivate =
908 FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate;
909 if (EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()).second) {
911 cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl());
920 if (CE && !CE.isReference()) {
926 if (CE && CE.isReference()) {
927 OriginalLVal = CE.getReferenceLValue(*
this, &DRE);
929 assert(!CE &&
"Expected non-constant firstprivate.");
952 RunCleanupsScope InitScope(*this);
954 setAddrOfLocalVar(VDInit, SrcElement);
955 EmitAnyExprToMem(Init, DestElement,
956 Init->getType().getQualifiers(),
958 LocalDeclMap.erase(VDInit);
963 PrivateScope.addPrivate(OrigVD, Emission.getAllocatedAddress());
969 setAddrOfLocalVar(VDInit, OriginalAddr);
971 LocalDeclMap.erase(VDInit);
973 if (ThisFirstprivateIsLastprivate &&
974 Lastprivates[OrigVD->getCanonicalDecl()] ==
975 OMPC_LASTPRIVATE_conditional) {
980 (*IRef)->getExprLoc());
985 LocalDeclMap.erase(VD);
986 setAddrOfLocalVar(VD, VDAddr);
988 IsRegistered = PrivateScope.addPrivate(OrigVD, VDAddr);
990 assert(IsRegistered &&
991 "firstprivate var already registered as private");
999 return FirstprivateIsLastprivate && !EmittedAsFirstprivate.empty();
1004 CodeGenFunction::OMPPrivateScope &PrivateScope) {
1007 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
1009 auto IRef =
C->varlist_begin();
1010 for (
const Expr *IInit :
C->private_copies()) {
1011 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
1012 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
1013 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
1018 assert(IsRegistered &&
"private var already registered as private");
1034 llvm::DenseSet<const VarDecl *> CopiedVars;
1035 llvm::BasicBlock *CopyBegin =
nullptr, *CopyEnd =
nullptr;
1037 auto IRef =
C->varlist_begin();
1038 auto ISrcRef =
C->source_exprs().begin();
1039 auto IDestRef =
C->destination_exprs().begin();
1040 for (
const Expr *AssignOp :
C->assignment_ops()) {
1041 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
1049 getContext().getTargetInfo().isTLSSupported()) {
1051 "Copyin threadprivates should have been captured!");
1055 LocalDeclMap.erase(VD);
1065 if (CopiedVars.size() == 1) {
1071 auto *MasterAddrInt =
Builder.CreatePtrToInt(
1073 auto *PrivateAddrInt =
Builder.CreatePtrToInt(
1076 Builder.CreateICmpNE(MasterAddrInt, PrivateAddrInt), CopyBegin,
1081 cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
1082 const auto *DestVD =
1083 cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
1103 bool HasAtLeastOneLastprivate =
false;
1105 llvm::DenseSet<const VarDecl *> SIMDLCVs;
1107 const auto *LoopDirective = cast<OMPLoopDirective>(&
D);
1108 for (
const Expr *
C : LoopDirective->counters()) {
1113 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1115 HasAtLeastOneLastprivate =
true;
1118 const auto *IRef =
C->varlist_begin();
1119 const auto *IDestRef =
C->destination_exprs().begin();
1120 for (
const Expr *IInit :
C->private_copies()) {
1123 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
1126 if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) {
1127 const auto *DestVD =
1128 cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
1133 PrivateScope.addPrivate(DestVD,
EmitLValue(&DRE).getAddress());
1137 if (IInit && !SIMDLCVs.count(OrigVD->getCanonicalDecl())) {
1138 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
1140 if (
C->getKind() == OMPC_LASTPRIVATE_conditional) {
1143 setAddrOfLocalVar(VD, VDAddr);
1149 bool IsRegistered = PrivateScope.addPrivate(OrigVD, VDAddr);
1150 assert(IsRegistered &&
1151 "lastprivate var already registered as private");
1159 return HasAtLeastOneLastprivate;
1164 llvm::Value *IsLastIterCond) {
1173 llvm::BasicBlock *ThenBB =
nullptr;
1174 llvm::BasicBlock *DoneBB =
nullptr;
1175 if (IsLastIterCond) {
1181 return C->getKind() == OMPC_LASTPRIVATE_conditional;
1190 Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB);
1193 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1194 llvm::DenseMap<const VarDecl *, const Expr *> LoopCountersAndUpdates;
1195 if (
const auto *LoopDirective = dyn_cast<OMPLoopDirective>(&
D)) {
1196 auto IC = LoopDirective->counters().begin();
1197 for (
const Expr *F : LoopDirective->finals()) {
1201 AlreadyEmittedVars.insert(
D);
1203 LoopCountersAndUpdates[
D] = F;
1208 auto IRef =
C->varlist_begin();
1209 auto ISrcRef =
C->source_exprs().begin();
1210 auto IDestRef =
C->destination_exprs().begin();
1211 for (
const Expr *AssignOp :
C->assignment_ops()) {
1212 const auto *PrivateVD =
1213 cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
1215 const auto *CanonicalVD = PrivateVD->getCanonicalDecl();
1216 if (AlreadyEmittedVars.insert(CanonicalVD).second) {
1220 if (
const Expr *FinalExpr = LoopCountersAndUpdates.lookup(CanonicalVD))
1223 cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
1224 const auto *DestVD =
1225 cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
1228 if (
const auto *RefTy = PrivateVD->getType()->getAs<
ReferenceType>())
1234 if (
C->getKind() == OMPC_LASTPRIVATE_conditional)
1236 *
this,
MakeAddrLValue(PrivateAddr, (*IRef)->getType()), PrivateVD,
1237 (*IRef)->getExprLoc());
1240 EmitOMPCopy(
Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp);
1246 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
1255 CodeGenFunction::OMPPrivateScope &PrivateScope,
bool ForInscan) {
1267 if (ForInscan != (
C->getModifier() == OMPC_REDUCTION_inscan))
1269 Shareds.append(
C->varlist_begin(),
C->varlist_end());
1270 Privates.append(
C->privates().begin(),
C->privates().end());
1271 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1272 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1273 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1274 if (
C->getModifier() == OMPC_REDUCTION_task) {
1275 Data.ReductionVars.append(
C->privates().begin(),
C->privates().end());
1276 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
1277 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
1278 Data.ReductionOps.append(
C->reduction_ops().begin(),
1279 C->reduction_ops().end());
1280 TaskLHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1281 TaskRHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1286 auto *ILHS = LHSs.begin();
1287 auto *IRHS = RHSs.begin();
1288 auto *IPriv = Privates.begin();
1289 for (
const Expr *IRef : Shareds) {
1290 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IPriv)->getDecl());
1292 RedCG.emitSharedOrigLValue(*
this, Count);
1293 RedCG.emitAggregateType(*
this, Count);
1295 RedCG.emitInitialization(*
this, Count, Emission.getAllocatedAddress(),
1296 RedCG.getSharedLValue(Count).getAddress(),
1298 CGF.EmitAutoVarInit(Emission);
1302 Address BaseAddr = RedCG.adjustPrivateAddress(
1303 *
this, Count, Emission.getAllocatedAddress());
1305 PrivateScope.addPrivate(RedCG.getBaseDecl(Count), BaseAddr);
1306 assert(IsRegistered &&
"private var already registered as private");
1310 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
1311 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
1313 bool isaOMPArraySectionExpr = isa<ArraySectionExpr>(IRef);
1317 PrivateScope.addPrivate(LHSVD, RedCG.getSharedLValue(Count).getAddress());
1320 isa<ArraySubscriptExpr>(IRef)) {
1323 PrivateScope.addPrivate(LHSVD, RedCG.getSharedLValue(Count).getAddress());
1324 PrivateScope.addPrivate(RHSVD,
1330 Address OriginalAddr = RedCG.getSharedLValue(Count).getAddress();
1337 PrivateScope.addPrivate(LHSVD, OriginalAddr);
1338 PrivateScope.addPrivate(
1348 if (!
Data.ReductionVars.empty()) {
1350 Data.IsReductionWithTaskMod =
true;
1354 const Expr *TaskRedRef =
nullptr;
1357 TaskRedRef = cast<OMPParallelDirective>(
D).getTaskReductionRefExpr();
1360 TaskRedRef = cast<OMPForDirective>(
D).getTaskReductionRefExpr();
1363 TaskRedRef = cast<OMPSectionsDirective>(
D).getTaskReductionRefExpr();
1365 case OMPD_parallel_for:
1366 TaskRedRef = cast<OMPParallelForDirective>(
D).getTaskReductionRefExpr();
1368 case OMPD_parallel_master:
1370 cast<OMPParallelMasterDirective>(
D).getTaskReductionRefExpr();
1372 case OMPD_parallel_sections:
1374 cast<OMPParallelSectionsDirective>(
D).getTaskReductionRefExpr();
1376 case OMPD_target_parallel:
1378 cast<OMPTargetParallelDirective>(
D).getTaskReductionRefExpr();
1380 case OMPD_target_parallel_for:
1382 cast<OMPTargetParallelForDirective>(
D).getTaskReductionRefExpr();
1384 case OMPD_distribute_parallel_for:
1386 cast<OMPDistributeParallelForDirective>(
D).getTaskReductionRefExpr();
1388 case OMPD_teams_distribute_parallel_for:
1389 TaskRedRef = cast<OMPTeamsDistributeParallelForDirective>(
D)
1390 .getTaskReductionRefExpr();
1392 case OMPD_target_teams_distribute_parallel_for:
1393 TaskRedRef = cast<OMPTargetTeamsDistributeParallelForDirective>(
D)
1394 .getTaskReductionRefExpr();
1402 case OMPD_parallel_for_simd:
1404 case OMPD_taskyield:
1408 case OMPD_taskgroup:
1416 case OMPD_cancellation_point:
1418 case OMPD_target_data:
1419 case OMPD_target_enter_data:
1420 case OMPD_target_exit_data:
1422 case OMPD_taskloop_simd:
1423 case OMPD_master_taskloop:
1424 case OMPD_master_taskloop_simd:
1425 case OMPD_parallel_master_taskloop:
1426 case OMPD_parallel_master_taskloop_simd:
1427 case OMPD_distribute:
1428 case OMPD_target_update:
1429 case OMPD_distribute_parallel_for_simd:
1430 case OMPD_distribute_simd:
1431 case OMPD_target_parallel_for_simd:
1432 case OMPD_target_simd:
1433 case OMPD_teams_distribute:
1434 case OMPD_teams_distribute_simd:
1435 case OMPD_teams_distribute_parallel_for_simd:
1436 case OMPD_target_teams:
1437 case OMPD_target_teams_distribute:
1438 case OMPD_target_teams_distribute_parallel_for_simd:
1439 case OMPD_target_teams_distribute_simd:
1440 case OMPD_declare_target:
1441 case OMPD_end_declare_target:
1442 case OMPD_threadprivate:
1444 case OMPD_declare_reduction:
1445 case OMPD_declare_mapper:
1446 case OMPD_declare_simd:
1448 case OMPD_declare_variant:
1449 case OMPD_begin_declare_variant:
1450 case OMPD_end_declare_variant:
1453 llvm_unreachable(
"Unexpected directive with task reductions.");
1456 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(TaskRedRef)->getDecl());
1459 false, TaskRedRef->
getType());
1471 bool HasAtLeastOneReduction =
false;
1472 bool IsReductionWithTaskMod =
false;
1475 if (
C->getModifier() == OMPC_REDUCTION_inscan)
1477 HasAtLeastOneReduction =
true;
1478 Privates.append(
C->privates().begin(),
C->privates().end());
1479 LHSExprs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1480 RHSExprs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1481 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1482 IsReductionWithTaskMod =
1483 IsReductionWithTaskMod ||
C->getModifier() == OMPC_REDUCTION_task;
1485 if (HasAtLeastOneReduction) {
1487 if (IsReductionWithTaskMod) {
1491 bool TeamsLoopCanBeParallel =
false;
1492 if (
auto *TTLD = dyn_cast<OMPTargetTeamsGenericLoopDirective>(&
D))
1493 TeamsLoopCanBeParallel = TTLD->canBeParallelFor();
1496 TeamsLoopCanBeParallel || ReductionKind == OMPD_simd;
1497 bool SimpleReduction = ReductionKind == OMPD_simd;
1501 *
this,
D.
getEndLoc(), Privates, LHSExprs, RHSExprs, ReductionOps,
1502 {WithNowait, SimpleReduction, ReductionKind});
1511 llvm::BasicBlock *DoneBB =
nullptr;
1513 if (
const Expr *PostUpdate =
C->getPostUpdateExpr()) {
1515 if (llvm::Value *Cond = CondGen(CGF)) {
1520 CGF.
Builder.CreateCondBr(Cond, ThenBB, DoneBB);
1538 CodeGenBoundParametersTy;
1546 llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> PrivateDecls;
1548 for (
const Expr *Ref :
C->varlist()) {
1549 if (!Ref->getType()->isScalarType())
1551 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1554 PrivateDecls.insert(cast<VarDecl>(DRE->getDecl()));
1559 for (
const Expr *Ref :
C->varlist()) {
1560 if (!Ref->getType()->isScalarType())
1562 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1565 PrivateDecls.insert(cast<VarDecl>(DRE->getDecl()));
1570 for (
const Expr *Ref :
C->varlist()) {
1571 if (!Ref->getType()->isScalarType())
1573 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1576 PrivateDecls.insert(cast<VarDecl>(DRE->getDecl()));
1585 for (
const Expr *Ref :
C->varlist()) {
1586 if (!Ref->getType()->isScalarType())
1588 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1591 PrivateDecls.insert(cast<VarDecl>(DRE->getDecl()));
1595 CGF, S, PrivateDecls);
1601 const CodeGenBoundParametersTy &CodeGenBoundParameters) {
1602 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
1603 llvm::Value *NumThreads =
nullptr;
1604 llvm::Function *OutlinedFn =
1609 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
1610 NumThreads = CGF.
EmitScalarExpr(NumThreadsClause->getNumThreads(),
1613 CGF, NumThreads, NumThreadsClause->getBeginLoc());
1616 CodeGenFunction::RunCleanupsScope ProcBindScope(CGF);
1618 CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getBeginLoc());
1620 const Expr *IfCond =
nullptr;
1621 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
1622 if (
C->getNameModifier() == OMPD_unknown ||
1623 C->getNameModifier() == OMPD_parallel) {
1624 IfCond =
C->getCondition();
1629 OMPParallelScope
Scope(CGF, S);
1635 CodeGenBoundParameters(CGF, S, CapturedVars);
1638 CapturedVars, IfCond, NumThreads);
1643 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
1645 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
1647 return !((AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc ||
1648 AA->getAllocatorType() == OMPAllocateDeclAttr::OMPNullMemAlloc) &&
1649 !AA->getAllocator());
1664 CGF, S.getBeginLoc(), OMPD_unknown,
false,
1684 Size = CGF.
Builder.CreateNUWAdd(
1693 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
1694 assert(AA->getAllocator() &&
1695 "Expected allocator expression for non-default allocator.");
1699 if (Allocator->getType()->isIntegerTy())
1701 else if (Allocator->getType()->isPointerTy())
1705 llvm::Value *Addr = OMPBuilder.createOMPAlloc(
1708 llvm::CallInst *FreeCI =
1709 OMPBuilder.createOMPFree(CGF.
Builder, Addr, Allocator);
1733 std::string Suffix = getNameWithSeparators({
"cache",
""});
1736 llvm::CallInst *ThreadPrivateCacheCall =
1737 OMPBuilder.createCachedThreadPrivate(CGF.
Builder,
Data, Size, CacheName);
1745 llvm::raw_svector_ostream OS(Buffer);
1746 StringRef Sep = FirstSeparator;
1747 for (StringRef Part : Parts) {
1751 return OS.str().str();
1759 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
1760 "." + RegionName +
".after");
1776 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
1777 "." + RegionName +
".after");
1792 llvm::Value *IfCond =
nullptr;
1797 llvm::Value *NumThreads =
nullptr;
1802 ProcBindKind ProcBind = OMP_PROC_BIND_default;
1804 ProcBind = ProcBindClause->getProcBindKind();
1806 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1810 auto FiniCB = [
this](InsertPointTy IP) {
1812 return llvm::Error::success();
1819 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
1820 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
1828 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
1831 auto BodyGenCB = [&,
this](InsertPointTy AllocaIP,
1832 InsertPointTy CodeGenIP) {
1834 *
this, ParallelRegionBodyStmt, AllocaIP, CodeGenIP,
"parallel");
1835 return llvm::Error::success();
1838 CGCapturedStmtInfo CGSI(*CS,
CR_OpenMP);
1839 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(*
this, &CGSI);
1840 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
1842 llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
1843 OMPBuilder.createParallel(
Builder, AllocaIP, BodyGenCB, PrivCB, FiniCB,
1844 IfCond, NumThreads, ProcBind, S.hasCancel());
1845 assert(AfterIP &&
"unexpected error creating parallel");
1853 OMPPrivateScope PrivateScope(CGF);
1858 (void)PrivateScope.Privatize();
1859 CGF.
EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt());
1880class OMPTransformDirectiveScopeRAII {
1881 OMPLoopScope *
Scope =
nullptr;
1882 CodeGenFunction::CGCapturedStmtInfo *CGSI =
nullptr;
1883 CodeGenFunction::CGCapturedStmtRAII *CapInfoRAII =
nullptr;
1885 OMPTransformDirectiveScopeRAII(
const OMPTransformDirectiveScopeRAII &) =
1887 OMPTransformDirectiveScopeRAII &
1888 operator=(
const OMPTransformDirectiveScopeRAII &) =
delete;
1892 if (
const auto *Dir = dyn_cast<OMPLoopBasedDirective>(S)) {
1893 Scope =
new OMPLoopScope(CGF, *Dir);
1894 CGSI =
new CodeGenFunction::CGCapturedStmtInfo(
CR_OpenMP);
1895 CapInfoRAII =
new CodeGenFunction::CGCapturedStmtRAII(CGF, CGSI);
1898 ~OMPTransformDirectiveScopeRAII() {
1909 int MaxLevel,
int Level = 0) {
1910 assert(Level < MaxLevel &&
"Too deep lookup during loop body codegen.");
1911 const Stmt *SimplifiedS = S->IgnoreContainers();
1912 if (
const auto *CS = dyn_cast<CompoundStmt>(SimplifiedS)) {
1915 "LLVM IR generation of compound statement ('{}')");
1918 CodeGenFunction::LexicalScope
Scope(CGF, S->getSourceRange());
1919 for (
const Stmt *CurStmt : CS->body())
1920 emitBody(CGF, CurStmt, NextLoop, MaxLevel, Level);
1923 if (SimplifiedS == NextLoop) {
1924 if (
auto *Dir = dyn_cast<OMPLoopTransformationDirective>(SimplifiedS))
1925 SimplifiedS = Dir->getTransformedStmt();
1926 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(SimplifiedS))
1927 SimplifiedS = CanonLoop->getLoopStmt();
1928 if (
const auto *For = dyn_cast<ForStmt>(SimplifiedS)) {
1931 assert(isa<CXXForRangeStmt>(SimplifiedS) &&
1932 "Expected canonical for loop or range-based for loop.");
1933 const auto *CXXFor = cast<CXXForRangeStmt>(SimplifiedS);
1934 CGF.
EmitStmt(CXXFor->getLoopVarStmt());
1935 S = CXXFor->getBody();
1937 if (Level + 1 < MaxLevel) {
1940 emitBody(CGF, S, NextLoop, MaxLevel, Level + 1);
1949 RunCleanupsScope BodyScope(*
this);
1951 for (
const Expr *UE :
D.updates())
1959 for (
const Expr *UE :
C->updates())
1966 BreakContinueStack.push_back(BreakContinue(
LoopExit, Continue));
1967 for (
const Expr *
E :
D.finals_conditions()) {
1978 OMPPrivateScope InscanScope(*
this);
1980 bool IsInscanRegion = InscanScope.Privatize();
1981 if (IsInscanRegion) {
1991 if (EKind != OMPD_simd && !
getLangOpts().OpenMPSimd)
2000 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
2005 D.getLoopsNumber());
2013 BreakContinueStack.pop_back();
2024 std::unique_ptr<CodeGenFunction::CGCapturedStmtInfo> CSI =
2025 std::make_unique<CodeGenFunction::CGCapturedStmtInfo>(*S);
2026 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, CSI.get());
2033static llvm::CallInst *
2038 EffectiveArgs.reserve(Args.size() + 1);
2039 llvm::append_range(EffectiveArgs, Args);
2040 EffectiveArgs.push_back(Cap.second);
2045llvm::CanonicalLoopInfo *
2047 assert(Depth == 1 &&
"Nested loops with OpenMPIRBuilder not yet implemented");
2073 const Stmt *SyntacticalLoop = S->getLoopStmt();
2080 LexicalScope ForScope(*
this, S->getSourceRange());
2084 const Stmt *BodyStmt;
2085 if (
const auto *For = dyn_cast<ForStmt>(SyntacticalLoop)) {
2086 if (
const Stmt *InitStmt = For->getInit())
2088 BodyStmt = For->getBody();
2089 }
else if (
const auto *RangeFor =
2090 dyn_cast<CXXForRangeStmt>(SyntacticalLoop)) {
2091 if (
const DeclStmt *RangeStmt = RangeFor->getRangeStmt())
2093 if (
const DeclStmt *BeginStmt = RangeFor->getBeginStmt())
2095 if (
const DeclStmt *EndStmt = RangeFor->getEndStmt())
2097 if (
const DeclStmt *LoopVarStmt = RangeFor->getLoopVarStmt())
2099 BodyStmt = RangeFor->getBody();
2101 llvm_unreachable(
"Expected for-stmt or range-based for-stmt");
2104 const CapturedStmt *DistanceFunc = S->getDistanceFunc();
2121 auto BodyGen = [&,
this](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP,
2122 llvm::Value *IndVar) {
2127 const DeclRefExpr *LoopVarRef = S->getLoopVarRef();
2133 RunCleanupsScope BodyScope(*
this);
2135 return llvm::Error::success();
2139 OMPBuilder.createCanonicalLoop(
Builder, BodyGen, DistVal);
2140 assert(
Result &&
"unexpected error creating canonical loop");
2141 llvm::CanonicalLoopInfo *CL = *
Result;
2144 Builder.restoreIP(CL->getAfterIP());
2145 ForScope.ForceCleanup();
2153 const Expr *IncExpr,
2164 const auto &OMPED = cast<OMPExecutableDirective>(S);
2165 const CapturedStmt *ICS = OMPED.getInnermostCapturedStmt();
2179 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
2180 if (RequiresCleanup)
2187 if (ExitBlock !=
LoopExit.getBlock()) {
2197 BreakContinueStack.push_back(BreakContinue(
LoopExit, Continue));
2205 BreakContinueStack.pop_back();
2216 bool HasLinears =
false;
2220 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
Init)->getDecl());
2221 if (
const auto *Ref =
2224 const auto *OrigVD = cast<VarDecl>(Ref->getDecl());
2240 if (
const auto *CS = cast_or_null<BinaryOperator>(
C->getCalcStep()))
2241 if (
const auto *SaveRef = cast<DeclRefExpr>(CS->getLHS())) {
2255 llvm::BasicBlock *DoneBB =
nullptr;
2258 auto IC =
C->varlist_begin();
2259 for (
const Expr *F :
C->finals()) {
2261 if (llvm::Value *Cond = CondGen(*
this)) {
2266 Builder.CreateCondBr(Cond, ThenBB, DoneBB);
2270 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl());
2275 CodeGenFunction::OMPPrivateScope VarScope(*
this);
2276 VarScope.addPrivate(OrigVD, OrigAddr);
2277 (void)VarScope.Privatize();
2281 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
2293 llvm::APInt ClauseAlignment(64, 0);
2294 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
2297 ClauseAlignment = AlignmentCI->getValue();
2299 for (
const Expr *
E : Clause->varlist()) {
2300 llvm::APInt Alignment(ClauseAlignment);
2301 if (Alignment == 0) {
2311 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2312 "alignment is not power of 2");
2313 if (Alignment != 0) {
2327 auto I = S.private_counters().begin();
2328 for (
const Expr *
E : S.counters()) {
2329 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
2330 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl());
2334 LocalDeclMap.erase(PrivateVD);
2335 (void)LoopScope.addPrivate(VD, VarEmission.getAllocatedAddress());
2343 (void)LoopScope.addPrivate(PrivateVD, VarEmission.getAllocatedAddress());
2349 if (!
C->getNumForLoops())
2351 for (
unsigned I = S.getLoopsNumber(),
E =
C->getLoopNumIterations().size();
2353 const auto *DRE = cast<DeclRefExpr>(
C->getLoopCounter(I));
2354 const auto *VD = cast<VarDecl>(DRE->getDecl());
2357 if (DRE->refersToEnclosingVariableOrCapture()) {
2358 (void)LoopScope.addPrivate(
2366 const Expr *Cond, llvm::BasicBlock *TrueBlock,
2367 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
2371 CodeGenFunction::OMPPrivateScope PreCondScope(CGF);
2373 (void)PreCondScope.Privatize();
2375 for (
const Expr *I : S.inits()) {
2381 CodeGenFunction::OMPMapVars PreCondVars;
2382 for (
const Expr *
E : S.dependent_counters()) {
2386 "dependent counter must not be an iterator.");
2387 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
2390 (void)PreCondVars.setVarAddr(CGF, VD, CounterAddr);
2392 (void)PreCondVars.apply(CGF);
2393 for (
const Expr *
E : S.dependent_inits()) {
2400 PreCondVars.restore(CGF);
2407 llvm::DenseSet<const VarDecl *> SIMDLCVs;
2410 const auto *LoopDirective = cast<OMPLoopDirective>(&
D);
2411 for (
const Expr *
C : LoopDirective->counters()) {
2417 auto CurPrivate =
C->privates().begin();
2418 for (
const Expr *
E :
C->varlist()) {
2419 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
2420 const auto *PrivateVD =
2421 cast<VarDecl>(cast<DeclRefExpr>(*CurPrivate)->getDecl());
2427 assert(IsRegistered &&
"linear var already registered as private");
2445 auto *Val = cast<llvm::ConstantInt>(Len.
getScalarVal());
2454 auto *Val = cast<llvm::ConstantInt>(Len.
getScalarVal());
2469 if (
C->getKind() == OMPC_ORDER_concurrent)
2472 if ((EKind == OMPD_simd ||
2476 return C->getModifier() == OMPC_REDUCTION_inscan;
2487 llvm::BasicBlock *DoneBB =
nullptr;
2488 auto IC =
D.counters().begin();
2489 auto IPC =
D.private_counters().begin();
2490 for (
const Expr *F :
D.finals()) {
2491 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>((*IC))->getDecl());
2492 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>((*IPC))->getDecl());
2493 const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
2495 OrigVD->hasGlobalStorage() || CED) {
2497 if (llvm::Value *Cond = CondGen(*
this)) {
2502 Builder.CreateCondBr(Cond, ThenBB, DoneBB);
2515 OMPPrivateScope VarScope(*
this);
2516 VarScope.addPrivate(OrigVD, OrigAddr);
2517 (void)VarScope.Privatize();
2529 CodeGenFunction::JumpDest
LoopExit) {
2537 auto VDecl = cast<VarDecl>(Helper->
getDecl());
2545 auto &&ThenGen = [&S, &SimdInitGen, &BodyCodeGen](
CodeGenFunction &CGF,
2548 CodeGenFunction::OMPLocalDeclMapRAII
Scope(CGF);
2554 CodeGenFunction::OMPLocalDeclMapRAII
Scope(CGF);
2559 const Expr *IfCond =
nullptr;
2562 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
2564 (
C->getNameModifier() == OMPD_unknown ||
2565 C->getNameModifier() == OMPD_simd)) {
2566 IfCond =
C->getCondition();
2582 OMPLoopScope PreInitScope(CGF, S);
2604 llvm::BasicBlock *ContBlock =
nullptr;
2611 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
2618 const Expr *IVExpr = S.getIterationVariable();
2619 const auto *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
2626 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
2627 CGF.
EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
2635 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
2641 CGF, S, CGF.
EmitLValue(S.getIterationVariable()));
2643 (void)LoopScope.Privatize();
2654 S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(),
2656 emitOMPLoopBodyWithStopPoint(CGF, S,
2657 CodeGenFunction::JumpDest());
2663 if (HasLastprivateClause)
2668 LoopScope.restoreMap();
2684 if (!(isa<OMPSimdlenClause>(
C) || isa<OMPSafelenClause>(
C) ||
2685 isa<OMPOrderClause>(
C) || isa<OMPAlignedClause>(
C)))
2692 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(S.getRawStmt())) {
2693 if (
const Stmt *SyntacticalLoop = CanonLoop->getLoopStmt()) {
2694 for (
const Stmt *SubStmt : SyntacticalLoop->
children()) {
2697 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(SubStmt)) {
2701 if (isa<OMPOrderedDirective>(CSSubStmt)) {
2712static llvm::MapVector<llvm::Value *, llvm::Value *>
2714 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars;
2716 llvm::APInt ClauseAlignment(64, 0);
2717 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
2720 ClauseAlignment = AlignmentCI->getValue();
2722 for (
const Expr *
E : Clause->varlist()) {
2723 llvm::APInt Alignment(ClauseAlignment);
2724 if (Alignment == 0) {
2734 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2735 "alignment is not power of 2");
2737 AlignedVars[PtrValue] = CGF.
Builder.getInt64(Alignment.getSExtValue());
2747 bool UseOMPIRBuilder =
2749 if (UseOMPIRBuilder) {
2753 if (UseOMPIRBuilder) {
2754 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars =
2757 const Stmt *Inner = S.getRawStmt();
2758 llvm::CanonicalLoopInfo *CLI =
2759 CGF.EmitOMPCollapsedCanonicalLoopNest(Inner, 1);
2761 llvm::OpenMPIRBuilder &OMPBuilder =
2764 llvm::ConstantInt *Simdlen =
nullptr;
2768 auto *Val = cast<llvm::ConstantInt>(Len.
getScalarVal());
2771 llvm::ConstantInt *Safelen =
nullptr;
2775 auto *Val = cast<llvm::ConstantInt>(Len.
getScalarVal());
2778 llvm::omp::OrderKind Order = llvm::omp::OrderKind::OMP_ORDER_unknown;
2780 if (
C->getKind() == OpenMPOrderClauseKind::OMPC_ORDER_concurrent) {
2781 Order = llvm::omp::OrderKind::OMP_ORDER_concurrent;
2786 OMPBuilder.applySimd(CLI, AlignedVars,
2787 nullptr, Order, Simdlen, Safelen);
2794 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
2801 CodeGenFunction::ParentLoopDirectiveForScanRegion ScanRegion(CGF, S);
2809 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
2822 OMPTransformDirectiveScopeRAII TileScope(*
this, &S);
2828 OMPTransformDirectiveScopeRAII ReverseScope(*
this, &S);
2835 OMPTransformDirectiveScopeRAII InterchangeScope(*
this, &S);
2842 if (UseOMPIRBuilder) {
2844 const Stmt *Inner = S.getRawStmt();
2855 llvm::CanonicalLoopInfo *UnrolledCLI =
nullptr;
2859 OMPBuilder.unrollLoopFull(DL, CLI);
2862 if (
Expr *FactorExpr = PartialClause->getFactor()) {
2863 Factor = FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
2864 assert(Factor >= 1 &&
"Only positive factors are valid");
2866 OMPBuilder.unrollLoopPartial(DL, CLI, Factor,
2867 NeedsUnrolledCLI ? &UnrolledCLI :
nullptr);
2869 OMPBuilder.unrollLoopHeuristic(DL, CLI);
2872 assert((!NeedsUnrolledCLI || UnrolledCLI) &&
2873 "NeedsUnrolledCLI implies UnrolledCLI to be set");
2890 if (
Expr *FactorExpr = PartialClause->getFactor()) {
2892 FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
2893 assert(Factor >= 1 &&
"Only positive factors are valid");
2901void CodeGenFunction::EmitOMPOuterLoop(
2903 CodeGenFunction::OMPPrivateScope &LoopScope,
2904 const CodeGenFunction::OMPLoopArguments &LoopArgs,
2909 const Expr *IVExpr = S.getIterationVariable();
2923 llvm::Value *BoolCondVal =
nullptr;
2924 if (!DynamicOrOrdered) {
2935 RT.
emitForNext(*
this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL,
2936 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST);
2941 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
2942 if (LoopScope.requiresCleanups())
2946 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
2947 if (ExitBlock !=
LoopExit.getBlock()) {
2955 if (DynamicOrOrdered)
2960 BreakContinueStack.push_back(BreakContinue(
LoopExit, Continue));
2971 if (
C->getKind() == OMPC_ORDER_concurrent)
2977 [&S, &LoopArgs,
LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered,
2985 CGF.EmitOMPInnerLoop(
2986 S, LoopScope.requiresCleanups(), LoopArgs.Cond, LoopArgs.IncExpr,
2988 CodeGenLoop(CGF, S, LoopExit);
2991 CodeGenOrdered(CGF, Loc, IVSize, IVSigned);
2996 BreakContinueStack.pop_back();
2997 if (!DynamicOrOrdered) {
3010 auto &&CodeGen = [DynamicOrOrdered, &S, &LoopArgs](
CodeGenFunction &CGF) {
3011 if (!DynamicOrOrdered)
3012 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
3015 OMPCancelStack.emitExit(*
this, EKind, CodeGen);
3018void CodeGenFunction::EmitOMPForOuterLoop(
3021 const OMPLoopArguments &LoopArgs,
3029 LoopArgs.Chunk !=
nullptr)) &&
3030 "static non-chunked schedule does not need outer loop");
3084 const Expr *IVExpr = S.getIterationVariable();
3088 if (DynamicOrOrdered) {
3089 const std::pair<llvm::Value *, llvm::Value *> DispatchBounds =
3090 CGDispatchBounds(*
this, S, LoopArgs.LB, LoopArgs.UB);
3091 llvm::Value *LBVal = DispatchBounds.first;
3092 llvm::Value *UBVal = DispatchBounds.second;
3096 IVSigned, Ordered, DipatchRTInputValues);
3099 IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
3100 LoopArgs.ST, LoopArgs.Chunk);
3107 const unsigned IVSize,
3108 const bool IVSigned) {
3115 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST,
3116 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB);
3117 OuterLoopArgs.IncExpr = S.getInc();
3118 OuterLoopArgs.Init = S.getInit();
3119 OuterLoopArgs.Cond = S.getCond();
3120 OuterLoopArgs.NextLB = S.getNextLowerBound();
3121 OuterLoopArgs.NextUB = S.getNextUpperBound();
3122 OuterLoopArgs.DKind = LoopArgs.DKind;
3123 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
3125 if (DynamicOrOrdered) {
3131 const unsigned IVSize,
const bool IVSigned) {}
3133void CodeGenFunction::EmitOMPDistributeOuterLoop(
3135 OMPPrivateScope &LoopScope,
const OMPLoopArguments &LoopArgs,
3145 const Expr *IVExpr = S.getIterationVariable();
3151 IVSize, IVSigned,
false, LoopArgs.IL, LoopArgs.LB,
3152 LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
3159 IncExpr = S.getDistInc();
3161 IncExpr = S.getInc();
3166 OMPLoopArguments OuterLoopArgs;
3167 OuterLoopArgs.LB = LoopArgs.LB;
3168 OuterLoopArgs.UB = LoopArgs.UB;
3169 OuterLoopArgs.ST = LoopArgs.ST;
3170 OuterLoopArgs.IL = LoopArgs.IL;
3171 OuterLoopArgs.Chunk = LoopArgs.Chunk;
3173 ? S.getCombinedEnsureUpperBound()
3174 : S.getEnsureUpperBound();
3175 OuterLoopArgs.IncExpr = IncExpr;
3177 ? S.getCombinedInit()
3180 ? S.getCombinedCond()
3183 ? S.getCombinedNextLowerBound()
3184 : S.getNextLowerBound();
3186 ? S.getCombinedNextUpperBound()
3187 : S.getNextUpperBound();
3188 OuterLoopArgs.DKind = OMPD_distribute;
3190 EmitOMPOuterLoop(
false,
false, S,
3191 LoopScope, OuterLoopArgs, CodeGenLoopContent,
3195static std::pair<LValue, LValue>
3238static std::pair<llvm::Value *, llvm::Value *>
3249 llvm::Value *LBVal =
3251 llvm::Value *UBVal =
3253 return {LBVal, UBVal};
3259 const auto &Dir = cast<OMPLoopDirective>(S);
3261 CGF.
EmitLValue(cast<DeclRefExpr>(Dir.getCombinedLowerBoundVariable()));
3262 llvm::Value *LBCast = CGF.
Builder.CreateIntCast(
3264 CapturedVars.push_back(LBCast);
3266 CGF.
EmitLValue(cast<DeclRefExpr>(Dir.getCombinedUpperBoundVariable()));
3268 llvm::Value *UBCast = CGF.
Builder.CreateIntCast(
3270 CapturedVars.push_back(UBCast);
3276 CodeGenFunction::JumpDest
LoopExit) {
3281 bool HasCancel =
false;
3283 if (
const auto *
D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
3284 HasCancel =
D->hasCancel();
3285 else if (
const auto *
D = dyn_cast<OMPDistributeParallelForDirective>(&S))
3286 HasCancel =
D->hasCancel();
3287 else if (
const auto *
D =
3288 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S))
3289 HasCancel =
D->hasCancel();
3291 CodeGenFunction::OMPCancelStackRAII CancelRegion(CGF, EKind, HasCancel);
3299 CGInlinedWorksharingLoop,
3309 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3319 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3328 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
3339 llvm::Constant *Addr;
3342 S, ParentName, Fn, Addr,
true, CodeGen);
3343 assert(Fn && Addr &&
"Target device function emission failed.");
3355struct ScheduleKindModifiersTy {
3371 const auto *IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
3372 const auto *IVDecl = cast<VarDecl>(IVExpr->getDecl());
3378 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
3386 bool HasLastprivateClause;
3389 OMPLoopScope PreInitScope(*
this, S);
3394 llvm::BasicBlock *ContBlock =
nullptr;
3401 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
3407 RunCleanupsScope DoacrossCleanupScope(*
this);
3408 bool Ordered =
false;
3410 if (OrderedClause->getNumForLoops())
3416 llvm::DenseSet<const Expr *> EmittedFinals;
3421 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*
this, S);
3422 LValue LB = Bounds.first;
3423 LValue UB = Bounds.second;
3432 OMPPrivateScope LoopScope(*
this);
3438 *
this, S.getBeginLoc(), OMPD_unknown,
false,
3443 *
this, S,
EmitLValue(S.getIterationVariable()));
3448 (void)LoopScope.Privatize();
3453 const Expr *ChunkExpr =
nullptr;
3456 ScheduleKind.
Schedule =
C->getScheduleKind();
3457 ScheduleKind.
M1 =
C->getFirstScheduleModifier();
3458 ScheduleKind.
M2 =
C->getSecondScheduleModifier();
3459 ChunkExpr =
C->getChunkSize();
3463 *
this, S, ScheduleKind.
Schedule, ChunkExpr);
3465 bool HasChunkSizeOne =
false;
3466 llvm::Value *Chunk =
nullptr;
3470 S.getIterationVariable()->getType(),
3474 llvm::APSInt EvaluatedChunk =
Result.Val.getInt();
3475 HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
3484 bool StaticChunkedOne =
3486 Chunk !=
nullptr) &&
3490 (ScheduleKind.
Schedule == OMPC_SCHEDULE_static &&
3491 !(ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
3492 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)) ||
3493 ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
3494 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
3496 Chunk !=
nullptr) ||
3497 StaticChunkedOne) &&
3507 if (C->getKind() == OMPC_ORDER_concurrent)
3508 CGF.LoopStack.setParallel(true);
3511 [IVSize, IVSigned, Ordered, IL, LB, UB, ST, StaticChunkedOne, Chunk,
3520 IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(),
3521 UB.getAddress(), ST.getAddress(),
3522 StaticChunkedOne ? Chunk :
nullptr);
3523 CGF.CGM.getOpenMPRuntime().emitForStaticInit(
3524 CGF, S.getBeginLoc(), EKind, ScheduleKind, StaticInit);
3526 if (!StaticChunkedOne)
3527 CGF.EmitIgnoredExpr(S.getEnsureUpperBound());
3529 CGF.EmitIgnoredExpr(S.getInit());
3543 CGF.EmitOMPInnerLoop(
3544 S, LoopScope.requiresCleanups(),
3545 StaticChunkedOne ? S.getCombinedParForInDistCond()
3547 StaticChunkedOne ? S.getDistInc() : S.getInc(),
3549 emitOMPLoopBodyWithStopPoint(CGF, S, LoopExit);
3556 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
3559 OMPCancelStack.emitExit(*
this, EKind, CodeGen);
3563 OMPLoopArguments LoopArguments(LB.getAddress(), UB.getAddress(),
3564 ST.getAddress(), IL.getAddress(), Chunk,
3566 LoopArguments.DKind = OMPD_for;
3567 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
3568 LoopArguments, CGDispatchBounds);
3572 return CGF.
Builder.CreateIsNotNull(
3578 ? OMPD_parallel_for_simd
3583 return CGF.
Builder.CreateIsNotNull(
3587 if (HasLastprivateClause)
3591 LoopScope.restoreMap();
3593 return CGF.
Builder.CreateIsNotNull(
3597 DoacrossCleanupScope.ForceCleanup();
3604 return HasLastprivateClause;
3610static std::pair<LValue, LValue>
3612 const auto &LS = cast<OMPLoopDirective>(S);
3624static std::pair<llvm::Value *, llvm::Value *>
3627 const auto &LS = cast<OMPLoopDirective>(S);
3628 const Expr *IVExpr = LS.getIterationVariable();
3630 llvm::Value *LBVal = CGF.
Builder.getIntN(IVSize, 0);
3632 return {LBVal, UBVal};
3644 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
3645 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
3646 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
3652 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
3653 "Only inscan reductions are expected.");
3654 Shareds.append(
C->varlist_begin(),
C->varlist_end());
3655 Privates.append(
C->privates().begin(),
C->privates().end());
3656 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
3657 CopyArrayTemps.append(
C->copy_array_temps().begin(),
3658 C->copy_array_temps().end());
3666 auto *ITA = CopyArrayTemps.begin();
3667 for (
const Expr *IRef : Privates) {
3668 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(IRef)->getDecl());
3671 if (PrivateVD->getType()->isVariablyModifiedType()) {
3675 CodeGenFunction::OpaqueValueMapping DimMapping(
3677 cast<OpaqueValueExpr>(
3678 cast<VariableArrayType>((*ITA)->getType()->getAsArrayTypeUnsafe())
3682 CGF.
EmitVarDecl(*cast<VarDecl>(cast<DeclRefExpr>(*ITA)->getDecl()));
3696 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
3697 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
3698 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
3706 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
3707 "Only inscan reductions are expected.");
3708 Shareds.append(
C->varlist_begin(),
C->varlist_end());
3709 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
3710 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
3711 Privates.append(
C->privates().begin(),
C->privates().end());
3712 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
3713 CopyArrayElems.append(
C->copy_array_elems().begin(),
3714 C->copy_array_elems().end());
3718 llvm::Value *OMPLast = CGF.
Builder.CreateNSWSub(
3719 OMPScanNumIterations,
3720 llvm::ConstantInt::get(CGF.
SizeTy, 1,
false));
3721 for (
unsigned I = 0,
E = CopyArrayElems.size(); I <
E; ++I) {
3722 const Expr *PrivateExpr = Privates[I];
3723 const Expr *OrigExpr = Shareds[I];
3724 const Expr *CopyArrayElem = CopyArrayElems[I];
3725 CodeGenFunction::OpaqueValueMapping IdxMapping(
3727 cast<OpaqueValueExpr>(
3728 cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()),
3734 cast<VarDecl>(cast<DeclRefExpr>(LHSs[I])->getDecl()),
3735 cast<VarDecl>(cast<DeclRefExpr>(RHSs[I])->getDecl()), CopyOps[I]);
3763 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
3764 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
3771 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
3772 "Only inscan reductions are expected.");
3773 Privates.append(
C->privates().begin(),
C->privates().end());
3774 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
3775 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
3776 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
3777 CopyArrayElems.append(
C->copy_array_elems().begin(),
3778 C->copy_array_elems().end());
3780 CodeGenFunction::ParentLoopDirectiveForScanRegion ScanRegion(CGF, S);
3789 CodeGenFunction::OMPLocalDeclMapRAII
Scope(CGF);
3793 auto &&CodeGen = [&S, OMPScanNumIterations, &LHSs, &RHSs, &CopyArrayElems,
3800 llvm::BasicBlock *InputBB = CGF.Builder.GetInsertBlock();
3801 llvm::BasicBlock *LoopBB = CGF.createBasicBlock(
"omp.outer.log.scan.body");
3802 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
"omp.outer.log.scan.exit");
3804 CGF.CGM.getIntrinsic(llvm::Intrinsic::log2, CGF.DoubleTy);
3806 CGF.Builder.CreateUIToFP(OMPScanNumIterations, CGF.DoubleTy);
3807 llvm::Value *LogVal = CGF.EmitNounwindRuntimeCall(F, Arg);
3808 F = CGF.CGM.getIntrinsic(llvm::Intrinsic::ceil, CGF.DoubleTy);
3809 LogVal = CGF.EmitNounwindRuntimeCall(F, LogVal);
3810 LogVal = CGF.Builder.CreateFPToUI(LogVal, CGF.IntTy);
3811 llvm::Value *NMin1 = CGF.Builder.CreateNUWSub(
3812 OMPScanNumIterations, llvm::ConstantInt::get(CGF.SizeTy, 1));
3814 CGF.EmitBlock(LoopBB);
3815 auto *Counter = CGF.Builder.CreatePHI(CGF.IntTy, 2);
3817 auto *Pow2K = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
3818 Counter->addIncoming(llvm::ConstantInt::get(CGF.IntTy, 0), InputBB);
3819 Pow2K->addIncoming(llvm::ConstantInt::get(CGF.SizeTy, 1), InputBB);
3822 llvm::BasicBlock *InnerLoopBB =
3823 CGF.createBasicBlock(
"omp.inner.log.scan.body");
3824 llvm::BasicBlock *InnerExitBB =
3825 CGF.createBasicBlock(
"omp.inner.log.scan.exit");
3826 llvm::Value *CmpI = CGF.Builder.CreateICmpUGE(NMin1, Pow2K);
3827 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
3828 CGF.EmitBlock(InnerLoopBB);
3829 auto *IVal = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
3830 IVal->addIncoming(NMin1, LoopBB);
3832 CodeGenFunction::OMPPrivateScope PrivScope(CGF);
3833 auto *ILHS = LHSs.begin();
3834 auto *IRHS = RHSs.begin();
3835 for (
const Expr *CopyArrayElem : CopyArrayElems) {
3836 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
3837 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
3840 CodeGenFunction::OpaqueValueMapping IdxMapping(
3842 cast<OpaqueValueExpr>(
3843 cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()),
3845 LHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
3847 PrivScope.addPrivate(LHSVD, LHSAddr);
3850 llvm::Value *OffsetIVal = CGF.Builder.CreateNUWSub(IVal, Pow2K);
3851 CodeGenFunction::OpaqueValueMapping IdxMapping(
3853 cast<OpaqueValueExpr>(
3854 cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()),
3856 RHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
3858 PrivScope.addPrivate(RHSVD, RHSAddr);
3862 PrivScope.Privatize();
3863 CGF.CGM.getOpenMPRuntime().emitReduction(
3864 CGF, S.getEndLoc(), Privates, LHSs, RHSs, ReductionOps,
3865 {true, true, OMPD_unknown});
3867 llvm::Value *NextIVal =
3868 CGF.Builder.CreateNUWSub(IVal, llvm::ConstantInt::get(CGF.SizeTy, 1));
3869 IVal->addIncoming(NextIVal, CGF.Builder.GetInsertBlock());
3870 CmpI = CGF.Builder.CreateICmpUGE(NextIVal, Pow2K);
3871 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
3872 CGF.EmitBlock(InnerExitBB);
3874 CGF.Builder.CreateNUWAdd(Counter, llvm::ConstantInt::get(CGF.IntTy, 1));
3875 Counter->addIncoming(Next, CGF.Builder.GetInsertBlock());
3877 llvm::Value *NextPow2K =
3878 CGF.Builder.CreateShl(Pow2K, 1,
"",
true);
3879 Pow2K->addIncoming(NextPow2K, CGF.Builder.GetInsertBlock());
3880 llvm::Value *Cmp = CGF.Builder.CreateICmpNE(Next, LogVal);
3881 CGF.Builder.CreateCondBr(Cmp, LoopBB, ExitBB);
3883 CGF.EmitBlock(ExitBB);
3887 CGF.CGM.getOpenMPRuntime().emitMasterRegion(CGF, CodeGen, S.getBeginLoc());
3888 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
3889 CGF, S.getBeginLoc(), OMPD_unknown,
false,
3896 CGF.OMPFirstScanLoop =
false;
3903 bool HasLastprivates;
3907 return C->getModifier() == OMPC_REDUCTION_inscan;
3910 CodeGenFunction::OMPLocalDeclMapRAII
Scope(CGF);
3911 OMPLoopScope LoopScope(CGF, S);
3914 const auto &&FirstGen = [&S, HasCancel, EKind](
CodeGenFunction &CGF) {
3915 CodeGenFunction::OMPCancelStackRAII CancelRegion(CGF, EKind, HasCancel);
3923 const auto &&SecondGen = [&S, HasCancel, EKind,
3925 CodeGenFunction::OMPCancelStackRAII CancelRegion(CGF, EKind, HasCancel);
3936 CodeGenFunction::OMPCancelStackRAII CancelRegion(CGF, EKind, HasCancel);
3941 return HasLastprivates;
3951 if (isa<OMPNowaitClause, OMPBindClause>(
C))
3954 if (
auto *SC = dyn_cast<OMPScheduleClause>(
C)) {
3959 switch (SC->getScheduleKind()) {
3960 case OMPC_SCHEDULE_auto:
3961 case OMPC_SCHEDULE_dynamic:
3962 case OMPC_SCHEDULE_runtime:
3963 case OMPC_SCHEDULE_guided:
3964 case OMPC_SCHEDULE_static:
3977static llvm::omp::ScheduleKind
3979 switch (ScheduleClauseKind) {
3981 return llvm::omp::OMP_SCHEDULE_Default;
3982 case OMPC_SCHEDULE_auto:
3983 return llvm::omp::OMP_SCHEDULE_Auto;
3984 case OMPC_SCHEDULE_dynamic:
3985 return llvm::omp::OMP_SCHEDULE_Dynamic;
3986 case OMPC_SCHEDULE_guided:
3987 return llvm::omp::OMP_SCHEDULE_Guided;
3988 case OMPC_SCHEDULE_runtime:
3989 return llvm::omp::OMP_SCHEDULE_Runtime;
3990 case OMPC_SCHEDULE_static:
3991 return llvm::omp::OMP_SCHEDULE_Static;
3993 llvm_unreachable(
"Unhandled schedule kind");
4000 bool HasLastprivates =
false;
4003 auto &&CodeGen = [&S, &
CGM, HasCancel, &HasLastprivates,
4006 if (UseOMPIRBuilder) {
4009 llvm::omp::ScheduleKind SchedKind = llvm::omp::OMP_SCHEDULE_Default;
4010 llvm::Value *ChunkSize =
nullptr;
4014 if (
const Expr *ChunkSizeExpr = SchedClause->getChunkSize())
4019 const Stmt *Inner = S.getRawStmt();
4020 llvm::CanonicalLoopInfo *CLI =
4023 llvm::OpenMPIRBuilder &OMPBuilder =
4025 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4027 llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
4028 OMPBuilder.applyWorkshareLoop(
4029 CGF.
Builder.getCurrentDebugLocation(), CLI, AllocaIP,
4030 NeedsBarrier, SchedKind, ChunkSize,
false,
4033 assert(AfterIP &&
"unexpected error creating workshare loop");
4042 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
4047 if (!UseOMPIRBuilder) {
4061 bool HasLastprivates =
false;
4069 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4082 llvm::Value *
Init =
nullptr) {
4090 const Stmt *
CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4092 bool HasLastprivates =
false;
4098 C.getIntTypeForBitwidth(32, 1);
4101 CGF.Builder.getInt32(0));
4102 llvm::ConstantInt *GlobalUBVal = CS !=
nullptr
4103 ? CGF.Builder.getInt32(CS->size() - 1)
4104 : CGF.Builder.getInt32(0);
4108 CGF.Builder.getInt32(1));
4110 CGF.Builder.getInt32(0));
4114 CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
4116 CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
4137 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".omp.sections.exit");
4139 CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.getBeginLoc()),
4140 ExitBB, CS ==
nullptr ? 1 : CS->size());
4142 unsigned CaseNumber = 0;
4144 auto CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4145 CGF.EmitBlock(CaseBB);
4146 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
4147 CGF.EmitStmt(SubStmt);
4148 CGF.EmitBranch(ExitBB);
4152 llvm::BasicBlock *CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4153 CGF.EmitBlock(CaseBB);
4154 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
4156 CGF.EmitBranch(ExitBB);
4158 CGF.EmitBlock(ExitBB,
true);
4161 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
4162 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
4166 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
4167 CGF, S.getBeginLoc(), OMPD_unknown,
false,
4170 CGF.EmitOMPPrivateClause(S, LoopScope);
4172 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
4173 CGF.EmitOMPReductionClauseInit(S, LoopScope);
4174 (void)LoopScope.Privatize();
4176 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
4180 ScheduleKind.
Schedule = OMPC_SCHEDULE_static;
4184 CGF.CGM.getOpenMPRuntime().emitForStaticInit(CGF, S.getBeginLoc(), EKind,
4185 ScheduleKind, StaticInit);
4187 llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.getBeginLoc());
4188 llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
4189 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
4190 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
4192 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.getBeginLoc()), IV);
4194 CGF.EmitOMPInnerLoop(S,
false, Cond, Inc, BodyGen,
4198 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
4201 CGF.OMPCancelStack.emitExit(CGF, EKind, CodeGen);
4202 CGF.EmitOMPReductionClauseFinal(S, OMPD_parallel);
4205 return CGF.
Builder.CreateIsNotNull(
4210 if (HasLastprivates)
4217 bool HasCancel =
false;
4218 if (
auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
4219 HasCancel = OSD->hasCancel();
4220 else if (
auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
4221 HasCancel = OPSD->hasCancel();
4222 OMPCancelStackRAII CancelRegion(*
this, EKind, HasCancel);
4241 OMPPrivateScope PrivateScope(CGF);
4245 (void)PrivateScope.Privatize();
4246 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4251 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4265 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4266 using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
4268 auto FiniCB = [
this](InsertPointTy IP) {
4270 return llvm::Error::success();
4273 const CapturedStmt *ICS = S.getInnermostCapturedStmt();
4274 const Stmt *
CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4279 auto SectionCB = [
this, SubStmt](InsertPointTy AllocaIP,
4280 InsertPointTy CodeGenIP) {
4282 *
this, SubStmt, AllocaIP, CodeGenIP,
"section");
4283 return llvm::Error::success();
4285 SectionCBVector.push_back(SectionCB);
4288 auto SectionCB = [
this,
CapturedStmt](InsertPointTy AllocaIP,
4289 InsertPointTy CodeGenIP) {
4292 return llvm::Error::success();
4294 SectionCBVector.push_back(SectionCB);
4301 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
4302 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
4310 CGCapturedStmtInfo CGSI(*ICS,
CR_OpenMP);
4311 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(*
this, &CGSI);
4312 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4314 llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
4315 OMPBuilder.createSections(
Builder, AllocaIP, SectionCBVector, PrivCB,
4316 FiniCB, S.hasCancel(),
4318 assert(AfterIP &&
"unexpected error creating sections");
4325 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4340 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4342 const Stmt *SectionRegionBodyStmt = S.getAssociatedStmt();
4343 auto FiniCB = [
this](InsertPointTy IP) {
4345 return llvm::Error::success();
4348 auto BodyGenCB = [SectionRegionBodyStmt,
this](InsertPointTy AllocaIP,
4349 InsertPointTy CodeGenIP) {
4351 *
this, SectionRegionBodyStmt, AllocaIP, CodeGenIP,
"section");
4352 return llvm::Error::success();
4355 LexicalScope
Scope(*
this, S.getSourceRange());
4357 llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
4358 OMPBuilder.createSection(
Builder, BodyGenCB, FiniCB);
4359 assert(AfterIP &&
"unexpected error creating section");
4364 LexicalScope
Scope(*
this, S.getSourceRange());
4379 CopyprivateVars.append(
C->varlist_begin(),
C->varlist_end());
4380 DestExprs.append(
C->destination_exprs().begin(),
4381 C->destination_exprs().end());
4382 SrcExprs.append(
C->source_exprs().begin(),
C->source_exprs().end());
4383 AssignmentOps.append(
C->assignment_ops().begin(),
4384 C->assignment_ops().end());
4393 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4398 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4400 CopyprivateVars, DestExprs,
4401 SrcExprs, AssignmentOps);
4405 if (!S.getSingleClause<
OMPNowaitClause>() && CopyprivateVars.empty()) {
4407 *
this, S.getBeginLoc(),
4425 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4427 const Stmt *MasterRegionBodyStmt = S.getAssociatedStmt();
4429 auto FiniCB = [
this](InsertPointTy IP) {
4431 return llvm::Error::success();
4434 auto BodyGenCB = [MasterRegionBodyStmt,
this](InsertPointTy AllocaIP,
4435 InsertPointTy CodeGenIP) {
4437 *
this, MasterRegionBodyStmt, AllocaIP, CodeGenIP,
"master");
4438 return llvm::Error::success();
4441 LexicalScope
Scope(*
this, S.getSourceRange());
4443 llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
4444 OMPBuilder.createMaster(
Builder, BodyGenCB, FiniCB);
4445 assert(AfterIP &&
"unexpected error creating master");
4450 LexicalScope
Scope(*
this, S.getSourceRange());
4460 Expr *Filter =
nullptr;
4462 Filter = FilterClause->getThreadID();
4470 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4472 const Stmt *MaskedRegionBodyStmt = S.getAssociatedStmt();
4475 Filter = FilterClause->getThreadID();
4476 llvm::Value *FilterVal =
Filter
4480 auto FiniCB = [
this](InsertPointTy IP) {
4482 return llvm::Error::success();
4485 auto BodyGenCB = [MaskedRegionBodyStmt,
this](InsertPointTy AllocaIP,
4486 InsertPointTy CodeGenIP) {
4488 *
this, MaskedRegionBodyStmt, AllocaIP, CodeGenIP,
"masked");
4489 return llvm::Error::success();
4492 LexicalScope
Scope(*
this, S.getSourceRange());
4494 llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
4495 OMPBuilder.createMasked(
Builder, BodyGenCB, FiniCB, FilterVal);
4496 assert(AfterIP &&
"unexpected error creating masked");
4501 LexicalScope
Scope(*
this, S.getSourceRange());
4509 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4511 const Stmt *CriticalRegionBodyStmt = S.getAssociatedStmt();
4512 const Expr *Hint =
nullptr;
4513 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4514 Hint = HintClause->getHint();
4519 llvm::Value *HintInst =
nullptr;
4524 auto FiniCB = [
this](InsertPointTy IP) {
4526 return llvm::Error::success();
4529 auto BodyGenCB = [CriticalRegionBodyStmt,
this](InsertPointTy AllocaIP,
4530 InsertPointTy CodeGenIP) {
4532 *
this, CriticalRegionBodyStmt, AllocaIP, CodeGenIP,
"critical");
4533 return llvm::Error::success();
4536 LexicalScope
Scope(*
this, S.getSourceRange());
4538 llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
4539 OMPBuilder.createCritical(
Builder, BodyGenCB, FiniCB,
4540 S.getDirectiveName().getAsString(), HintInst);
4541 assert(AfterIP &&
"unexpected error creating critical");
4549 CGF.
EmitStmt(S.getAssociatedStmt());
4551 const Expr *Hint =
nullptr;
4552 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4553 Hint = HintClause->getHint();
4554 LexicalScope
Scope(*
this, S.getSourceRange());
4557 S.getDirectiveName().getAsString(),
4558 CodeGen, S.getBeginLoc(), Hint);
4572 CodeGenFunction::OMPLocalDeclMapRAII
Scope(CGF);
4574 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGSI);
4575 OMPLoopScope LoopScope(CGF, S);
4580 return C->getModifier() == OMPC_REDUCTION_inscan;
4606 CodeGenFunction::OMPLocalDeclMapRAII
Scope(CGF);
4608 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGSI);
4609 OMPLoopScope LoopScope(CGF, S);
4614 return C->getModifier() == OMPC_REDUCTION_inscan;
4635 OMPPrivateScope PrivateScope(CGF);
4640 (void)PrivateScope.Privatize();
4662 OMPPrivateScope PrivateScope(CGF);
4667 (void)PrivateScope.Privatize();
4690 CGF.EmitSections(S);
4704class CheckVarsEscapingUntiedTaskDeclContext final
4709 explicit CheckVarsEscapingUntiedTaskDeclContext() =
default;
4710 virtual ~CheckVarsEscapingUntiedTaskDeclContext() =
default;
4711 void VisitDeclStmt(
const DeclStmt *S) {
4715 for (
const Decl *
D : S->decls()) {
4716 if (
const auto *VD = dyn_cast_or_null<VarDecl>(
D))
4718 PrivateDecls.push_back(VD);
4724 void VisitBlockExpr(
const BlockExpr *) {}
4725 void VisitStmt(
const Stmt *S) {
4728 for (
const Stmt *Child : S->children())
4742 bool OmpAllMemory =
false;
4745 return C->getDependencyKind() == OMPC_DEPEND_outallmemory ||
4746 C->getDependencyKind() == OMPC_DEPEND_inoutallmemory;
4748 OmpAllMemory =
true;
4753 Data.Dependences.emplace_back(OMPC_DEPEND_outallmemory,
4762 if (Kind == OMPC_DEPEND_outallmemory || Kind == OMPC_DEPEND_inoutallmemory)
4764 if (OmpAllMemory && (Kind == OMPC_DEPEND_out || Kind == OMPC_DEPEND_inout))
4767 Data.Dependences.emplace_back(
C->getDependencyKind(),
C->getModifier());
4768 DD.
DepExprs.append(
C->varlist_begin(),
C->varlist_end());
4777 const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion);
4779 auto PartId = std::next(I);
4780 auto TaskT = std::next(I, 4);
4785 const Expr *Cond = Clause->getCondition();
4788 Data.Final.setInt(CondConstant);
4793 Data.Final.setInt(
false);
4797 const Expr *Prio = Clause->getPriority();
4798 Data.Priority.setInt(
true);
4806 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
4809 auto IRef =
C->varlist_begin();
4810 for (
const Expr *IInit :
C->private_copies()) {
4811 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
4812 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
4813 Data.PrivateVars.push_back(*IRef);
4814 Data.PrivateCopies.push_back(IInit);
4819 EmittedAsPrivate.clear();
4822 auto IRef =
C->varlist_begin();
4823 auto IElemInitRef =
C->inits().begin();
4824 for (
const Expr *IInit :
C->private_copies()) {
4825 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
4826 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
4827 Data.FirstprivateVars.push_back(*IRef);
4828 Data.FirstprivateCopies.push_back(IInit);
4829 Data.FirstprivateInits.push_back(*IElemInitRef);
4836 llvm::MapVector<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
4838 auto IRef =
C->varlist_begin();
4839 auto ID =
C->destination_exprs().begin();
4840 for (
const Expr *IInit :
C->private_copies()) {
4841 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
4842 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
4843 Data.LastprivateVars.push_back(*IRef);
4844 Data.LastprivateCopies.push_back(IInit);
4846 LastprivateDstsOrigs.insert(
4847 std::make_pair(cast<VarDecl>(cast<DeclRefExpr>(*ID)->getDecl()),
4848 cast<DeclRefExpr>(*IRef)));
4856 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
4857 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
4858 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
4859 Data.ReductionOps.append(
C->reduction_ops().begin(),
4860 C->reduction_ops().end());
4861 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
4862 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
4865 *
this, S.getBeginLoc(), LHSs, RHSs,
Data);
4870 CheckVarsEscapingUntiedTaskDeclContext Checker;
4871 Checker.Visit(S.getInnermostCapturedStmt()->getCapturedStmt());
4872 Data.PrivateLocals.append(Checker.getPrivateDecls().begin(),
4873 Checker.getPrivateDecls().end());
4875 auto &&CodeGen = [&
Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
4878 llvm::MapVector<CanonicalDeclPtr<const VarDecl>,
4879 std::pair<Address, Address>>
4882 OMPPrivateScope
Scope(CGF);
4884 if (
auto *DI = CGF.getDebugInfo()) {
4885 llvm::SmallDenseMap<const VarDecl *, FieldDecl *> CaptureFields =
4886 CGF.CapturedStmtInfo->getCaptureFields();
4887 llvm::Value *ContextValue = CGF.CapturedStmtInfo->getContextValue();
4888 if (CaptureFields.size() && ContextValue) {
4889 unsigned CharWidth = CGF.getContext().getCharWidth();
4903 for (
auto It = CaptureFields.begin(); It != CaptureFields.end(); ++It) {
4904 const VarDecl *SharedVar = It->first;
4907 CGF.getContext().getASTRecordLayout(CaptureRecord);
4910 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
4911 (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue,
4912 CGF.Builder,
false);
4915 auto UpdateExpr = [](llvm::LLVMContext &Ctx,
auto *
Declare,
4920 Ops.push_back(llvm::dwarf::DW_OP_plus_uconst);
4921 Ops.push_back(Offset);
4923 Ops.push_back(llvm::dwarf::DW_OP_deref);
4924 Declare->setExpression(llvm::DIExpression::get(Ctx, Ops));
4926 llvm::Instruction &
Last = CGF.Builder.GetInsertBlock()->back();
4927 if (
auto DDI = dyn_cast<llvm::DbgVariableIntrinsic>(&
Last))
4928 UpdateExpr(DDI->getContext(), DDI, Offset);
4931 assert(!
Last.isTerminator() &&
"unexpected terminator");
4933 CGF.Builder.GetInsertBlock()->getTrailingDbgRecords()) {
4934 for (llvm::DbgVariableRecord &DVR : llvm::reverse(
4935 llvm::filterDbgVars(Marker->getDbgRecordRange()))) {
4936 UpdateExpr(
Last.getContext(), &DVR, Offset);
4944 if (!
Data.PrivateVars.empty() || !
Data.FirstprivateVars.empty() ||
4945 !
Data.LastprivateVars.empty() || !
Data.PrivateLocals.empty()) {
4946 enum { PrivatesParam = 2, CopyFnParam = 3 };
4947 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
4948 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(CopyFnParam)));
4949 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
4950 CS->getCapturedDecl()->getParam(PrivatesParam)));
4955 CallArgs.push_back(PrivatesPtr);
4956 ParamTypes.push_back(PrivatesPtr->getType());
4957 for (
const Expr *
E :
Data.PrivateVars) {
4958 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
4960 CGF.getContext().getPointerType(
E->
getType()),
".priv.ptr.addr");
4961 PrivatePtrs.emplace_back(VD, PrivatePtr);
4963 ParamTypes.push_back(PrivatePtr.
getType());
4965 for (
const Expr *
E :
Data.FirstprivateVars) {
4966 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
4968 CGF.CreateMemTemp(CGF.getContext().getPointerType(
E->
getType()),
4969 ".firstpriv.ptr.addr");
4970 PrivatePtrs.emplace_back(VD, PrivatePtr);
4971 FirstprivatePtrs.emplace_back(VD, PrivatePtr);
4973 ParamTypes.push_back(PrivatePtr.
getType());
4975 for (
const Expr *
E :
Data.LastprivateVars) {
4976 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
4978 CGF.CreateMemTemp(CGF.getContext().getPointerType(
E->
getType()),
4979 ".lastpriv.ptr.addr");
4980 PrivatePtrs.emplace_back(VD, PrivatePtr);
4982 ParamTypes.push_back(PrivatePtr.
getType());
4987 Ty = CGF.getContext().getPointerType(Ty);
4989 Ty = CGF.getContext().getPointerType(Ty);
4991 CGF.getContext().getPointerType(Ty),
".local.ptr.addr");
4992 auto Result = UntiedLocalVars.insert(
4995 if (
Result.second ==
false)
4996 *
Result.first = std::make_pair(
4999 ParamTypes.push_back(PrivatePtr.
getType());
5001 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5003 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5004 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5005 for (
const auto &Pair : LastprivateDstsOrigs) {
5006 const auto *OrigVD = cast<VarDecl>(Pair.second->getDecl());
5009 CGF.CapturedStmtInfo->lookup(OrigVD) !=
nullptr,
5011 Pair.second->getExprLoc());
5012 Scope.addPrivate(Pair.first, CGF.EmitLValue(&DRE).getAddress());
5014 for (
const auto &Pair : PrivatePtrs) {
5016 CGF.Builder.CreateLoad(Pair.second),
5017 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5018 CGF.getContext().getDeclAlign(Pair.first));
5019 Scope.addPrivate(Pair.first, Replacement);
5020 if (
auto *DI = CGF.getDebugInfo())
5021 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5022 (void)DI->EmitDeclareOfAutoVariable(
5023 Pair.first, Pair.second.getBasePointer(), CGF.Builder,
5028 for (
auto &Pair : UntiedLocalVars) {
5029 QualType VDType = Pair.first->getType().getNonReferenceType();
5030 if (Pair.first->getType()->isLValueReferenceType())
5031 VDType = CGF.getContext().getPointerType(VDType);
5033 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5036 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(VDType)),
5037 CGF.getPointerAlign());
5038 Pair.second.first = Replacement;
5039 Ptr = CGF.Builder.CreateLoad(Replacement);
5040 Replacement =
Address(Ptr, CGF.ConvertTypeForMem(VDType),
5041 CGF.getContext().getDeclAlign(Pair.first));
5042 Pair.second.second = Replacement;
5044 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5045 Address Replacement(Ptr, CGF.ConvertTypeForMem(VDType),
5046 CGF.getContext().getDeclAlign(Pair.first));
5047 Pair.second.first = Replacement;
5051 if (
Data.Reductions) {
5052 OMPPrivateScope FirstprivateScope(CGF);
5053 for (
const auto &Pair : FirstprivatePtrs) {
5055 CGF.Builder.CreateLoad(Pair.second),
5056 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5057 CGF.getContext().getDeclAlign(Pair.first));
5058 FirstprivateScope.addPrivate(Pair.first, Replacement);
5060 (void)FirstprivateScope.Privatize();
5061 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5063 Data.ReductionCopies,
Data.ReductionOps);
5064 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
5065 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(9)));
5066 for (
unsigned Cnt = 0,
E =
Data.ReductionVars.size(); Cnt <
E; ++Cnt) {
5067 RedCG.emitSharedOrigLValue(CGF, Cnt);
5068 RedCG.emitAggregateType(CGF, Cnt);
5072 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5074 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5075 CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
5077 CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF),
5078 CGF.getContext().VoidPtrTy,
5079 CGF.getContext().getPointerType(
5080 Data.ReductionCopies[Cnt]->getType()),
5081 Data.ReductionCopies[Cnt]->getExprLoc()),
5082 CGF.ConvertTypeForMem(
Data.ReductionCopies[Cnt]->getType()),
5083 Replacement.getAlignment());
5084 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
5085 Scope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement);
5089 (void)
Scope.Privatize();
5095 auto IPriv =
C->privates().begin();
5096 auto IRed =
C->reduction_ops().begin();
5097 auto ITD =
C->taskgroup_descriptors().begin();
5098 for (
const Expr *Ref :
C->varlist()) {
5099 InRedVars.emplace_back(Ref);
5100 InRedPrivs.emplace_back(*IPriv);
5101 InRedOps.emplace_back(*IRed);
5102 TaskgroupDescriptors.emplace_back(*ITD);
5103 std::advance(IPriv, 1);
5104 std::advance(IRed, 1);
5105 std::advance(ITD, 1);
5110 OMPPrivateScope InRedScope(CGF);
5111 if (!InRedVars.empty()) {
5113 for (
unsigned Cnt = 0,
E = InRedVars.size(); Cnt <
E; ++Cnt) {
5114 RedCG.emitSharedOrigLValue(CGF, Cnt);
5115 RedCG.emitAggregateType(CGF, Cnt);
5121 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5123 llvm::Value *ReductionsPtr;
5124 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5125 ReductionsPtr = CGF.EmitLoadOfScalar(CGF.EmitLValue(TRExpr),
5126 TRExpr->getExprLoc());
5128 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5130 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5131 CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
5133 CGF.EmitScalarConversion(
5134 Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy,
5135 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
5136 InRedPrivs[Cnt]->getExprLoc()),
5137 CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()),
5138 Replacement.getAlignment());
5139 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
5140 InRedScope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement);
5143 (void)InRedScope.Privatize();
5152 S, *I, *PartId, *TaskT, EKind, CodeGen,
Data.Tied,
Data.NumberOfParts);
5153 OMPLexicalScope
Scope(*
this, S, std::nullopt,
5156 TaskGen(*
this, OutlinedFn,
Data);
5173 QualType ElemType =
C.getBaseElementType(Ty);
5183 Data.FirstprivateVars.emplace_back(OrigRef);
5184 Data.FirstprivateCopies.emplace_back(PrivateRef);
5185 Data.FirstprivateInits.emplace_back(InitRef);
5191 OMPTargetDataInfo &InputInfo) {
5197 auto PartId = std::next(I);
5198 auto TaskT = std::next(I, 4);
5201 Data.Final.setInt(
false);
5204 auto IRef =
C->varlist_begin();
5205 auto IElemInitRef =
C->inits().begin();
5206 for (
auto *IInit :
C->private_copies()) {
5207 Data.FirstprivateVars.push_back(*IRef);
5208 Data.FirstprivateCopies.push_back(IInit);
5209 Data.FirstprivateInits.push_back(*IElemInitRef);
5217 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5218 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5219 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5220 Data.ReductionOps.append(
C->reduction_ops().begin(),
5221 C->reduction_ops().end());
5222 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5223 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5225 OMPPrivateScope TargetScope(*
this);
5230 if (InputInfo.NumberOfTargetItems > 0) {
5233 llvm::APInt ArrSize(32, InputInfo.NumberOfTargetItems);
5238 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5240 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5247 TargetScope.addPrivate(BPVD, InputInfo.BasePointersArray);
5248 TargetScope.addPrivate(PVD, InputInfo.PointersArray);
5249 TargetScope.addPrivate(SVD, InputInfo.SizesArray);
5252 if (!isa_and_nonnull<llvm::ConstantPointerNull>(
5253 InputInfo.MappersArray.emitRawPointer(*
this))) {
5255 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5256 TargetScope.addPrivate(MVD, InputInfo.MappersArray);
5259 (void)TargetScope.Privatize();
5262 auto &&CodeGen = [&
Data, &S, CS, &BodyGen, BPVD, PVD, SVD, MVD, EKind,
5265 OMPPrivateScope
Scope(CGF);
5266 if (!
Data.FirstprivateVars.empty()) {
5267 enum { PrivatesParam = 2, CopyFnParam = 3 };
5268 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5269 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(CopyFnParam)));
5270 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5271 CS->getCapturedDecl()->getParam(PrivatesParam)));
5276 CallArgs.push_back(PrivatesPtr);
5277 ParamTypes.push_back(PrivatesPtr->getType());
5278 for (
const Expr *
E :
Data.FirstprivateVars) {
5279 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
5281 CGF.CreateMemTemp(CGF.getContext().getPointerType(
E->
getType()),
5282 ".firstpriv.ptr.addr");
5283 PrivatePtrs.emplace_back(VD, PrivatePtr);
5285 ParamTypes.push_back(PrivatePtr.
getType());
5287 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5289 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5290 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5291 for (
const auto &Pair : PrivatePtrs) {
5293 CGF.Builder.CreateLoad(Pair.second),
5294 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5295 CGF.getContext().getDeclAlign(Pair.first));
5296 Scope.addPrivate(Pair.first, Replacement);
5299 CGF.processInReduction(S,
Data, CGF, CS,
Scope);
5300 if (InputInfo.NumberOfTargetItems > 0) {
5301 InputInfo.BasePointersArray = CGF.Builder.CreateConstArrayGEP(
5302 CGF.GetAddrOfLocalVar(BPVD), 0);
5303 InputInfo.PointersArray = CGF.Builder.CreateConstArrayGEP(
5304 CGF.GetAddrOfLocalVar(PVD), 0);
5305 InputInfo.SizesArray = CGF.Builder.CreateConstArrayGEP(
5306 CGF.GetAddrOfLocalVar(SVD), 0);
5309 InputInfo.MappersArray = CGF.Builder.CreateConstArrayGEP(
5310 CGF.GetAddrOfLocalVar(MVD), 0);
5314 OMPLexicalScope LexScope(CGF, S, OMPD_task,
false);
5316 if (CGF.CGM.getLangOpts().OpenMP >= 51 &&
5321 CGF.CGM.getOpenMPRuntime().emitThreadLimitClause(
5322 CGF, TL->getThreadLimit().front(), S.getBeginLoc());
5327 S, *I, *PartId, *TaskT, EKind, CodeGen,
true,
5328 Data.NumberOfParts);
5329 llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<
OMPNowaitClause>() ? 1 : 0);
5334 SharedsTy, CapturedStruct, &IfCond,
Data);
5341 OMPPrivateScope &
Scope) {
5343 if (
Data.Reductions) {
5345 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5347 Data.ReductionCopies,
Data.ReductionOps);
5350 for (
unsigned Cnt = 0,
E =
Data.ReductionVars.size(); Cnt <
E; ++Cnt) {
5351 RedCG.emitSharedOrigLValue(CGF, Cnt);
5352 RedCG.emitAggregateType(CGF, Cnt);
5359 CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
5364 Data.ReductionCopies[Cnt]->getType()),
5365 Data.ReductionCopies[Cnt]->getExprLoc()),
5367 Replacement.getAlignment());
5368 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
5369 Scope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement);
5372 (void)
Scope.Privatize();
5378 auto IPriv =
C->privates().begin();
5379 auto IRed =
C->reduction_ops().begin();
5380 auto ITD =
C->taskgroup_descriptors().begin();
5381 for (
const Expr *Ref :
C->varlist()) {
5382 InRedVars.emplace_back(Ref);
5383 InRedPrivs.emplace_back(*IPriv);
5384 InRedOps.emplace_back(*IRed);
5385 TaskgroupDescriptors.emplace_back(*ITD);
5386 std::advance(IPriv, 1);
5387 std::advance(IRed, 1);
5388 std::advance(ITD, 1);
5391 OMPPrivateScope InRedScope(CGF);
5392 if (!InRedVars.empty()) {
5394 for (
unsigned Cnt = 0,
E = InRedVars.size(); Cnt <
E; ++Cnt) {
5395 RedCG.emitSharedOrigLValue(CGF, Cnt);
5396 RedCG.emitAggregateType(CGF, Cnt);
5402 llvm::Value *ReductionsPtr;
5403 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5407 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
5410 CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
5415 InRedPrivs[Cnt]->getExprLoc()),
5417 Replacement.getAlignment());
5418 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
5419 InRedScope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement);
5422 (void)InRedScope.Privatize();
5430 const Expr *IfCond =
nullptr;
5431 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
5432 if (
C->getNameModifier() == OMPD_unknown ||
5433 C->getNameModifier() == OMPD_task) {
5434 IfCond =
C->getCondition();
5445 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
5448 CGF.CGM.getOpenMPRuntime().emitTaskCall(CGF, S.getBeginLoc(), S, OutlinedFn,
5449 SharedsTy, CapturedStruct, IfCond,
5466 bool IsFatal =
false;
5485 return T.clauses().empty();
5490 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
5493 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5497 auto BodyGenCB = [&,
this](InsertPointTy AllocaIP,
5498 InsertPointTy CodeGenIP) {
5500 EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5501 return llvm::Error::success();
5503 CodeGenFunction::CGCapturedStmtInfo CapStmtInfo;
5506 llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
5507 OMPBuilder.createTaskgroup(
Builder, AllocaIP, BodyGenCB);
5508 assert(AfterIP &&
"unexpected error creating taskgroup");
5514 if (
const Expr *
E = S.getReductionRef()) {
5519 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5520 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5521 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5522 Data.ReductionOps.append(
C->reduction_ops().begin(),
5523 C->reduction_ops().end());
5524 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5525 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5527 llvm::Value *ReductionDesc =
5530 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
5535 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5542 ? llvm::AtomicOrdering::NotAtomic
5543 : llvm::AtomicOrdering::AcquireRelease;
5547 if (
const auto *FlushClause = S.getSingleClause<
OMPFlushClause>())
5549 FlushClause->varlist_end());
5552 S.getBeginLoc(), AO);
5562 for (
auto &Dep :
Data.Dependences) {
5564 *
this, Dep, DC->getBeginLoc());
5575 *
this, DOLVal, UC->getDependencyKind(), UC->getBeginLoc());
5594 if (
C->getModifier() != OMPC_REDUCTION_inscan)
5596 Shareds.append(
C->varlist_begin(),
C->varlist_end());
5597 Privates.append(
C->privates().begin(),
C->privates().end());
5598 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5599 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5600 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
5601 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
5602 CopyArrayTemps.append(
C->copy_array_temps().begin(),
5603 C->copy_array_temps().end());
5604 CopyArrayElems.append(
C->copy_array_elems().begin(),
5605 C->copy_array_elems().end());
5649 : BreakContinueStack.back().ContinueBlock.getBlock());
5654 LexicalScope
Scope(*
this, S.getSourceRange());
5660 for (
unsigned I = 0,
E = CopyArrayElems.size(); I <
E; ++I) {
5661 const Expr *PrivateExpr = Privates[I];
5662 const Expr *TempExpr = CopyArrayTemps[I];
5664 *cast<VarDecl>(cast<DeclRefExpr>(TempExpr)->getDecl()));
5669 cast<VarDecl>(cast<DeclRefExpr>(LHSs[I])->getDecl()),
5670 cast<VarDecl>(cast<DeclRefExpr>(RHSs[I])->getDecl()),
5675 *
this, ParentDir.
getEndLoc(), Privates, LHSs, RHSs, ReductionOps,
5676 {true, true, OMPD_simd});
5677 for (
unsigned I = 0,
E = CopyArrayElems.size(); I <
E; ++I) {
5678 const Expr *PrivateExpr = Privates[I];
5685 const Expr *TempExpr = CopyArrayTemps[I];
5691 cast<VarDecl>(cast<DeclRefExpr>(LHSs[I])->getDecl()),
5692 cast<VarDecl>(cast<DeclRefExpr>(RHSs[I])->getDecl()), CopyOps[I]);
5697 ? BreakContinueStack.back().ContinueBlock.getBlock()
5703 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
5708 const auto *IVExpr = cast<OMPLoopDirective>(ParentDir)
5709 .getIterationVariable()
5714 for (
unsigned I = 0,
E = CopyArrayElems.size(); I <
E; ++I) {
5715 const Expr *PrivateExpr = Privates[I];
5716 const Expr *OrigExpr = Shareds[I];
5717 const Expr *CopyArrayElem = CopyArrayElems[I];
5718 OpaqueValueMapping IdxMapping(
5720 cast<OpaqueValueExpr>(
5721 cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()),
5727 cast<VarDecl>(cast<DeclRefExpr>(LHSs[I])->getDecl()),
5728 cast<VarDecl>(cast<DeclRefExpr>(RHSs[I])->getDecl()), CopyOps[I]);
5731 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
5734 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
5739 const auto *IVExpr = cast<OMPLoopDirective>(ParentDir)
5740 .getIterationVariable()
5745 llvm::BasicBlock *ExclusiveExitBB =
nullptr;
5750 Builder.CreateCondBr(Cmp, ExclusiveExitBB, ContBB);
5753 IdxVal =
Builder.CreateNUWSub(IdxVal, llvm::ConstantInt::get(
SizeTy, 1));
5755 for (
unsigned I = 0,
E = CopyArrayElems.size(); I <
E; ++I) {
5756 const Expr *PrivateExpr = Privates[I];
5757 const Expr *OrigExpr = Shareds[I];
5758 const Expr *CopyArrayElem = CopyArrayElems[I];
5759 OpaqueValueMapping IdxMapping(
5761 cast<OpaqueValueExpr>(
5762 cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()),
5768 cast<VarDecl>(cast<DeclRefExpr>(LHSs[I])->getDecl()),
5769 cast<VarDecl>(cast<DeclRefExpr>(RHSs[I])->getDecl()), CopyOps[I]);
5784 const auto *IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
5785 const auto *IVDecl = cast<VarDecl>(IVExpr->getDecl());
5791 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
5799 bool HasLastprivateClause =
false;
5802 OMPLoopScope PreInitScope(*
this, S);
5807 llvm::BasicBlock *ContBlock =
nullptr;
5814 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
5826 *
this, cast<DeclRefExpr>(
5828 ? S.getCombinedLowerBoundVariable()
5829 : S.getLowerBoundVariable())));
5831 *
this, cast<DeclRefExpr>(
5833 ? S.getCombinedUpperBoundVariable()
5834 : S.getUpperBoundVariable())));
5840 OMPPrivateScope LoopScope(*
this);
5846 *
this, S.getBeginLoc(), OMPD_unknown,
false,
5856 (void)LoopScope.Privatize();
5861 llvm::Value *Chunk =
nullptr;
5864 ScheduleKind =
C->getDistScheduleKind();
5865 if (
const Expr *Ch =
C->getChunkSize()) {
5868 S.getIterationVariable()->getType(),
5874 *
this, S, ScheduleKind, Chunk);
5887 bool StaticChunked =
5891 Chunk !=
nullptr) ||
5896 StaticChunked ? Chunk :
nullptr);
5903 ? S.getCombinedEnsureUpperBound()
5904 : S.getEnsureUpperBound());
5907 ? S.getCombinedInit()
5912 ? S.getCombinedCond()
5916 Cond = S.getCombinedDistCond();
5948 [&S, &LoopScope, Cond, IncExpr,
LoopExit, &CodeGenLoop,
5950 CGF.EmitOMPInnerLoop(
5951 S, LoopScope.requiresCleanups(), Cond, IncExpr,
5953 CodeGenLoop(CGF, S, LoopExit);
5956 if (StaticChunked) {
5957 CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound());
5958 CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound());
5959 CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound());
5960 CGF.EmitIgnoredExpr(S.getCombinedInit());
5970 const OMPLoopArguments LoopArguments = {
5973 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments,
5978 return CGF.
Builder.CreateIsNotNull(
5989 return CGF.
Builder.CreateIsNotNull(
5994 if (HasLastprivateClause) {
6017 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
6030 CodeGenFunction::CGCapturedStmtInfo CapStmtInfo;
6033 Fn->setDoesNotRecurse();
6037template <
typename T>
6039 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP,
6040 llvm::OpenMPIRBuilder &OMPBuilder) {
6042 unsigned NumLoops =
C->getNumLoops();
6046 for (
unsigned I = 0; I < NumLoops; I++) {
6047 const Expr *CounterVal =
C->getLoopData(I);
6052 StoreValues.emplace_back(StoreValue);
6054 OMPDoacrossKind<T> ODK;
6055 bool IsDependSource = ODK.isSource(
C);
6057 OMPBuilder.createOrderedDepend(CGF.
Builder, AllocaIP, NumLoops,
6058 StoreValues,
".cnt.addr", IsDependSource));
6064 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6069 assert(!S.hasAssociatedStmt() &&
"No associated statement must be in "
6070 "ordered depend|doacross construct.");
6082 auto FiniCB = [
this](InsertPointTy IP) {
6084 return llvm::Error::success();
6087 auto BodyGenCB = [&S,
C,
this](InsertPointTy AllocaIP,
6088 InsertPointTy CodeGenIP) {
6093 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
6094 Builder,
false,
".ordered.after");
6097 llvm::Function *OutlinedFn =
6099 assert(S.getBeginLoc().isValid() &&
6100 "Outlined function call location must be valid.");
6103 OutlinedFn, CapturedVars);
6108 return llvm::Error::success();
6111 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6112 llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
6113 OMPBuilder.createOrderedThreadsSimd(
Builder, BodyGenCB, FiniCB, !
C);
6114 assert(AfterIP &&
"unexpected error creating ordered");
6121 assert(!S.hasAssociatedStmt() &&
6122 "No associated statement must be in ordered depend construct.");
6128 assert(!S.hasAssociatedStmt() &&
6129 "No associated statement must be in ordered doacross construct.");
6140 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
6141 llvm::Function *OutlinedFn =
6144 OutlinedFn, CapturedVars);
6150 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6158 "DestType must have scalar evaluation kind.");
6159 assert(!Val.
isAggregate() &&
"Must be a scalar or complex.");
6170 "DestType must have complex evaluation kind.");
6179 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
6181 assert(Val.
isComplex() &&
"Must be a scalar or complex.");
6202 llvm::AtomicOrdering AO,
LValue LVal,
6207 LVal,
Loc, llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO),
6225 llvm_unreachable(
"Must be a scalar or complex.");
6233 assert(
V->isLValue() &&
"V of 'omp atomic read' is not lvalue");
6234 assert(
X->isLValue() &&
"X of 'omp atomic read' is not lvalue");
6243 case llvm::AtomicOrdering::Acquire:
6244 case llvm::AtomicOrdering::AcquireRelease:
6245 case llvm::AtomicOrdering::SequentiallyConsistent:
6247 llvm::AtomicOrdering::Acquire);
6249 case llvm::AtomicOrdering::Monotonic:
6250 case llvm::AtomicOrdering::Release:
6252 case llvm::AtomicOrdering::NotAtomic:
6253 case llvm::AtomicOrdering::Unordered:
6254 llvm_unreachable(
"Unexpected ordering.");
6261 llvm::AtomicOrdering AO,
const Expr *
X,
6264 assert(
X->isLValue() &&
"X of 'omp atomic write' is not lvalue");
6272 case llvm::AtomicOrdering::Release:
6273 case llvm::AtomicOrdering::AcquireRelease:
6274 case llvm::AtomicOrdering::SequentiallyConsistent:
6276 llvm::AtomicOrdering::Release);
6278 case llvm::AtomicOrdering::Acquire:
6279 case llvm::AtomicOrdering::Monotonic:
6281 case llvm::AtomicOrdering::NotAtomic:
6282 case llvm::AtomicOrdering::Unordered:
6283 llvm_unreachable(
"Unexpected ordering.");
6290 llvm::AtomicOrdering AO,
6291 bool IsXLHSInRHSPart) {
6296 if (BO == BO_Comma || !
Update.isScalar() || !
X.isSimple() ||
6297 (!isa<llvm::ConstantInt>(
Update.getScalarVal()) &&
6298 (
Update.getScalarVal()->getType() !=
X.getAddress().getElementType())) ||
6301 return std::make_pair(
false,
RValue::get(
nullptr));
6304 if (
T->isIntegerTy())
6307 if (
T->isFloatingPointTy() && (BO == BO_Add || BO == BO_Sub))
6313 if (!CheckAtomicSupport(
Update.getScalarVal()->getType(), BO) ||
6314 !CheckAtomicSupport(
X.getAddress().getElementType(), BO))
6315 return std::make_pair(
false,
RValue::get(
nullptr));
6317 bool IsInteger =
X.getAddress().getElementType()->isIntegerTy();
6318 llvm::AtomicRMWInst::BinOp RMWOp;
6321 RMWOp = IsInteger ? llvm::AtomicRMWInst::Add : llvm::AtomicRMWInst::FAdd;
6324 if (!IsXLHSInRHSPart)
6325 return std::make_pair(
false,
RValue::get(
nullptr));
6326 RMWOp = IsInteger ? llvm::AtomicRMWInst::Sub : llvm::AtomicRMWInst::FSub;
6329 RMWOp = llvm::AtomicRMWInst::And;
6332 RMWOp = llvm::AtomicRMWInst::Or;
6335 RMWOp = llvm::AtomicRMWInst::Xor;
6339 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6340 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Min
6341 : llvm::AtomicRMWInst::Max)
6342 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMin
6343 : llvm::AtomicRMWInst::UMax);
6345 RMWOp = IsXLHSInRHSPart ? llvm::AtomicRMWInst::FMin
6346 : llvm::AtomicRMWInst::FMax;
6350 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6351 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Max
6352 : llvm::AtomicRMWInst::Min)
6353 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMax
6354 : llvm::AtomicRMWInst::UMin);
6356 RMWOp = IsXLHSInRHSPart ? llvm::AtomicRMWInst::FMax
6357 : llvm::AtomicRMWInst::FMin;
6360 RMWOp = llvm::AtomicRMWInst::Xchg;
6369 return std::make_pair(
false,
RValue::get(
nullptr));
6388 llvm_unreachable(
"Unsupported atomic update operation");
6390 llvm::Value *UpdateVal =
Update.getScalarVal();
6391 if (
auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
6393 UpdateVal = CGF.
Builder.CreateIntCast(
6394 IC,
X.getAddress().getElementType(),
6395 X.getType()->hasSignedIntegerRepresentation());
6397 UpdateVal = CGF.
Builder.CreateCast(llvm::Instruction::CastOps::UIToFP, IC,
6398 X.getAddress().getElementType());
6400 llvm::AtomicRMWInst *Res =
6417 if (
X.isGlobalReg()) {
6430 llvm::AtomicOrdering AO,
const Expr *
X,
6434 "Update expr in 'atomic update' must be a binary operator.");
6442 assert(
X->isLValue() &&
"X of 'omp atomic update' is not lvalue");
6445 const auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
6446 const auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
6449 auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](
RValue XRValue) {
6450 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
6451 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue);
6455 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO,
Loc, Gen);
6462 case llvm::AtomicOrdering::Release:
6463 case llvm::AtomicOrdering::AcquireRelease:
6464 case llvm::AtomicOrdering::SequentiallyConsistent:
6466 llvm::AtomicOrdering::Release);
6468 case llvm::AtomicOrdering::Acquire:
6469 case llvm::AtomicOrdering::Monotonic:
6471 case llvm::AtomicOrdering::NotAtomic:
6472 case llvm::AtomicOrdering::Unordered:
6473 llvm_unreachable(
"Unexpected ordering.");
6491 llvm_unreachable(
"Must be a scalar or complex.");
6495 llvm::AtomicOrdering AO,
6496 bool IsPostfixUpdate,
const Expr *
V,
6498 const Expr *UE,
bool IsXLHSInRHSPart,
6500 assert(
X->isLValue() &&
"X of 'omp atomic capture' is not lvalue");
6501 assert(
V->isLValue() &&
"V of 'omp atomic capture' is not lvalue");
6510 "Update expr in 'atomic capture' must be a binary operator.");
6518 const auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
6519 const auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
6521 NewVValType = XRValExpr->
getType();
6523 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
6524 IsPostfixUpdate](
RValue XRValue) {
6525 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
6526 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue);
6528 NewVVal = IsPostfixUpdate ? XRValue : Res;
6532 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO,
Loc, Gen);
6536 if (IsPostfixUpdate) {
6538 NewVVal = Res.second;
6542 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
6543 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, Res.second);
6549 NewVValType =
X->getType().getNonReferenceType();
6551 X->getType().getNonReferenceType(),
Loc);
6552 auto &&Gen = [&NewVVal, ExprRValue](
RValue XRValue) {
6558 XLValue, ExprRValue, BO_Assign,
false, AO,
6563 NewVVal = IsPostfixUpdate ? Res.
second : ExprRValue;
6579 case llvm::AtomicOrdering::Release:
6581 llvm::AtomicOrdering::Release);
6583 case llvm::AtomicOrdering::Acquire:
6585 llvm::AtomicOrdering::Acquire);
6587 case llvm::AtomicOrdering::AcquireRelease:
6588 case llvm::AtomicOrdering::SequentiallyConsistent:
6590 CGF, {},
Loc, llvm::AtomicOrdering::AcquireRelease);
6592 case llvm::AtomicOrdering::Monotonic:
6594 case llvm::AtomicOrdering::NotAtomic:
6595 case llvm::AtomicOrdering::Unordered:
6596 llvm_unreachable(
"Unexpected ordering.");
6602 CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO,
6604 const Expr *CE,
bool IsXBinopExpr,
bool IsPostfixUpdate,
bool IsFailOnly,
6606 llvm::OpenMPIRBuilder &OMPBuilder =
6609 OMPAtomicCompareOp Op;
6610 assert(isa<BinaryOperator>(CE) &&
"CE is not a BinaryOperator");
6611 switch (cast<BinaryOperator>(CE)->getOpcode()) {
6613 Op = OMPAtomicCompareOp::EQ;
6616 Op = OMPAtomicCompareOp::MIN;
6619 Op = OMPAtomicCompareOp::MAX;
6622 llvm_unreachable(
"unsupported atomic compare binary operator");
6628 auto EmitRValueWithCastIfNeeded = [&CGF,
Loc](
const Expr *
X,
const Expr *
E) {
6633 if (NewE->
getType() ==
X->getType())
6638 llvm::Value *EVal = EmitRValueWithCastIfNeeded(
X,
E);
6639 llvm::Value *DVal =
D ? EmitRValueWithCastIfNeeded(
X,
D) :
nullptr;
6640 if (
auto *CI = dyn_cast<llvm::ConstantInt>(EVal))
6641 EVal = CGF.
Builder.CreateIntCast(
6645 if (
auto *CI = dyn_cast<llvm::ConstantInt>(DVal))
6646 DVal = CGF.
Builder.CreateIntCast(
6648 D->getType()->hasSignedIntegerRepresentation());
6650 llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{
6652 X->getType()->hasSignedIntegerRepresentation(),
6653 X->getType().isVolatileQualified()};
6654 llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal;
6659 V->getType()->hasSignedIntegerRepresentation(),
6660 V->getType().isVolatileQualified()};
6670 if (FailAO == llvm::AtomicOrdering::NotAtomic) {
6673 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
6674 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
6675 IsPostfixUpdate, IsFailOnly));
6677 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
6678 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
6679 IsPostfixUpdate, IsFailOnly, FailAO));
6683 llvm::AtomicOrdering AO,
6684 llvm::AtomicOrdering FailAO,
bool IsPostfixUpdate,
6687 const Expr *CE,
bool IsXLHSInRHSPart,
6702 IsXLHSInRHSPart,
Loc);
6704 case OMPC_compare: {
6706 IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly,
Loc);
6710 llvm_unreachable(
"Clause is not allowed in 'omp atomic'.");
6717 llvm::AtomicOrdering FailAO = llvm::AtomicOrdering::NotAtomic;
6718 bool MemOrderingSpecified =
false;
6720 AO = llvm::AtomicOrdering::SequentiallyConsistent;
6721 MemOrderingSpecified =
true;
6723 AO = llvm::AtomicOrdering::AcquireRelease;
6724 MemOrderingSpecified =
true;
6726 AO = llvm::AtomicOrdering::Acquire;
6727 MemOrderingSpecified =
true;
6729 AO = llvm::AtomicOrdering::Release;
6730 MemOrderingSpecified =
true;
6732 AO = llvm::AtomicOrdering::Monotonic;
6733 MemOrderingSpecified =
true;
6735 llvm::SmallSet<OpenMPClauseKind, 2> KindsEncountered;
6744 if (K == OMPC_seq_cst || K == OMPC_acq_rel || K == OMPC_acquire ||
6745 K == OMPC_release || K == OMPC_relaxed || K == OMPC_hint)
6748 KindsEncountered.insert(K);
6753 if (KindsEncountered.contains(OMPC_compare) &&
6754 KindsEncountered.contains(OMPC_capture))
6755 Kind = OMPC_compare;
6756 if (!MemOrderingSpecified) {
6757 llvm::AtomicOrdering DefaultOrder =
6759 if (DefaultOrder == llvm::AtomicOrdering::Monotonic ||
6760 DefaultOrder == llvm::AtomicOrdering::SequentiallyConsistent ||
6761 (DefaultOrder == llvm::AtomicOrdering::AcquireRelease &&
6762 Kind == OMPC_capture)) {
6764 }
else if (DefaultOrder == llvm::AtomicOrdering::AcquireRelease) {
6765 if (Kind == OMPC_unknown || Kind == OMPC_update || Kind == OMPC_write) {
6766 AO = llvm::AtomicOrdering::Release;
6767 }
else if (Kind == OMPC_read) {
6768 assert(Kind == OMPC_read &&
"Unexpected atomic kind.");
6769 AO = llvm::AtomicOrdering::Acquire;
6774 if (KindsEncountered.contains(OMPC_compare) &&
6775 KindsEncountered.contains(OMPC_fail)) {
6776 Kind = OMPC_compare;
6777 const auto *FailClause = S.getSingleClause<
OMPFailClause>();
6780 if (FailParameter == llvm::omp::OMPC_relaxed)
6781 FailAO = llvm::AtomicOrdering::Monotonic;
6782 else if (FailParameter == llvm::omp::OMPC_acquire)
6783 FailAO = llvm::AtomicOrdering::Acquire;
6784 else if (FailParameter == llvm::omp::OMPC_seq_cst)
6785 FailAO = llvm::AtomicOrdering::SequentiallyConsistent;
6789 LexicalScope
Scope(*
this, S.getSourceRange());
6792 S.getV(), S.getR(), S.getExpr(), S.getUpdateExpr(),
6793 S.getD(), S.getCondExpr(), S.isXLHSInRHSPart(),
6794 S.isFailOnly(), S.getBeginLoc());
6805 OMPLexicalScope
Scope(CGF, S, OMPD_target);
6808 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
6814 llvm::Function *Fn =
nullptr;
6815 llvm::Constant *FnID =
nullptr;
6817 const Expr *IfCond =
nullptr;
6819 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
6820 if (
C->getNameModifier() == OMPD_unknown ||
6821 C->getNameModifier() == OMPD_target) {
6822 IfCond =
C->getCondition();
6828 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device(
6831 Device.setPointerAndInt(
C->getDevice(),
C->getModifier());
6836 bool IsOffloadEntry =
true;
6840 IsOffloadEntry =
false;
6843 IsOffloadEntry =
false;
6845 if (
CGM.
getLangOpts().OpenMPOffloadMandatory && !IsOffloadEntry) {
6848 "No offloading entry generated while offloading is mandatory.");
6852 assert(CGF.
CurFuncDecl &&
"No parent declaration for target region!");
6853 StringRef ParentName;
6856 if (
const auto *
D = dyn_cast<CXXConstructorDecl>(CGF.
CurFuncDecl))
6858 else if (
const auto *
D = dyn_cast<CXXDestructorDecl>(CGF.
CurFuncDecl))
6866 IsOffloadEntry, CodeGen);
6867 OMPLexicalScope
Scope(CGF, S, OMPD_task);
6868 auto &&SizeEmitter =
6871 if (IsOffloadEntry) {
6872 OMPLoopScope(CGF,
D);
6874 llvm::Value *NumIterations = CGF.
EmitScalarExpr(
D.getNumIterations());
6875 NumIterations = CGF.
Builder.CreateIntCast(NumIterations, CGF.
Int64Ty,
6877 return NumIterations;
6888 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
6891 (void)PrivateScope.Privatize();
6895 CGF.
EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
6900 StringRef ParentName,
6906 llvm::Constant *Addr;
6909 S, ParentName, Fn, Addr,
true, CodeGen);
6910 assert(Fn && Addr &&
"Target device function emission failed.");
6924 const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams);
6925 llvm::Function *OutlinedFn =
6933 const Expr *NumTeams = NT ? NT->getNumTeams().front() :
nullptr;
6934 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() :
nullptr;
6940 OMPTeamsScope
Scope(CGF, S);
6951 OMPPrivateScope PrivateScope(CGF);
6955 (void)PrivateScope.Privatize();
6956 CGF.
EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt());
6966 auto *CS = S.getCapturedStmt(OMPD_teams);
6971 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
6975 (void)PrivateScope.Privatize();
6993 llvm::Constant *Addr;
6996 S, ParentName, Fn, Addr,
true, CodeGen);
6997 assert(Fn && Addr &&
"Target device function emission failed.");
7020 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
7022 (void)PrivateScope.Privatize();
7039 llvm::Constant *Addr;
7042 S, ParentName, Fn, Addr,
true, CodeGen);
7043 assert(Fn && Addr &&
"Target device function emission failed.");
7066 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
7068 (void)PrivateScope.Privatize();
7085 llvm::Constant *Addr;
7088 S, ParentName, Fn, Addr,
true, CodeGen);
7089 assert(Fn && Addr &&
"Target device function emission failed.");
7111 OMPPrivateScope PrivateScope(CGF);
7112 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7113 (void)PrivateScope.Privatize();
7114 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
7116 CGF.EmitOMPReductionClauseFinal(S, OMPD_teams);
7133 OMPPrivateScope PrivateScope(CGF);
7134 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7135 (void)PrivateScope.Privatize();
7136 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_simd,
7138 CGF.EmitOMPReductionClauseFinal(S, OMPD_teams);
7156 OMPPrivateScope PrivateScope(CGF);
7157 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7158 (void)PrivateScope.Privatize();
7159 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
7161 CGF.EmitOMPReductionClauseFinal(S, OMPD_teams);
7179 OMPPrivateScope PrivateScope(CGF);
7180 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7181 (void)PrivateScope.Privatize();
7182 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(
7183 CGF, OMPD_distribute, CodeGenDistribute,
false);
7184 CGF.EmitOMPReductionClauseFinal(S, OMPD_teams);
7194 llvm::Value *
Device =
nullptr;
7195 llvm::Value *NumDependences =
nullptr;
7196 llvm::Value *DependenceList =
nullptr;
7204 if (!
Data.Dependences.empty()) {
7206 std::tie(NumDependences, DependenciesArray) =
7216 "OMPNowaitClause clause is used separately in OMPInteropDirective.");
7219 if (!ItOMPInitClause.empty()) {
7222 llvm::Value *InteropvarPtr =
7224 llvm::omp::OMPInteropType InteropType =
7225 llvm::omp::OMPInteropType::Unknown;
7226 if (
C->getIsTarget()) {
7227 InteropType = llvm::omp::OMPInteropType::Target;
7229 assert(
C->getIsTargetSync() &&
7230 "Expected interop-type target/targetsync");
7231 InteropType = llvm::omp::OMPInteropType::TargetSync;
7233 OMPBuilder.createOMPInteropInit(
Builder, InteropvarPtr, InteropType,
7234 Device, NumDependences, DependenceList,
7235 Data.HasNowaitClause);
7239 if (!ItOMPDestroyClause.empty()) {
7242 llvm::Value *InteropvarPtr =
7244 OMPBuilder.createOMPInteropDestroy(
Builder, InteropvarPtr,
Device,
7245 NumDependences, DependenceList,
7246 Data.HasNowaitClause);
7249 auto ItOMPUseClause = S.getClausesOfKind<
OMPUseClause>();
7250 if (!ItOMPUseClause.empty()) {
7253 llvm::Value *InteropvarPtr =
7255 OMPBuilder.createOMPInteropUse(
Builder, InteropvarPtr,
Device,
7256 NumDependences, DependenceList,
7257 Data.HasNowaitClause);
7275 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
7277 (void)PrivateScope.Privatize();
7279 CGF, OMPD_distribute, CodeGenDistribute,
false);
7298 llvm::Constant *Addr;
7301 S, ParentName, Fn, Addr,
true, CodeGen);
7302 assert(Fn && Addr &&
"Target device function emission failed.");
7327 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
7329 (void)PrivateScope.Privatize();
7331 CGF, OMPD_distribute, CodeGenDistribute,
false);
7350 llvm::Constant *Addr;
7353 S, ParentName, Fn, Addr,
true, CodeGen);
7354 assert(Fn && Addr &&
"Target device function emission failed.");
7368 S.getCancelRegion());
7372 const Expr *IfCond =
nullptr;
7373 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7374 if (
C->getNameModifier() == OMPD_unknown ||
7375 C->getNameModifier() == OMPD_cancel) {
7376 IfCond =
C->getCondition();
7384 if (S.getCancelRegion() == OMPD_parallel ||
7385 S.getCancelRegion() == OMPD_sections ||
7386 S.getCancelRegion() == OMPD_section) {
7387 llvm::Value *IfCondition =
nullptr;
7391 llvm::OpenMPIRBuilder::InsertPointOrErrorTy AfterIP =
7392 OMPBuilder.createCancel(
Builder, IfCondition, S.getCancelRegion());
7393 assert(AfterIP &&
"unexpected error creating cancel");
7394 return Builder.restoreIP(*AfterIP);
7399 S.getCancelRegion());
7402CodeGenFunction::JumpDest
7404 if (Kind == OMPD_parallel || Kind == OMPD_task ||
7405 Kind == OMPD_target_parallel || Kind == OMPD_taskloop ||
7406 Kind == OMPD_master_taskloop || Kind == OMPD_parallel_master_taskloop)
7408 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
7409 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
7410 Kind == OMPD_distribute_parallel_for ||
7411 Kind == OMPD_target_parallel_for ||
7412 Kind == OMPD_teams_distribute_parallel_for ||
7413 Kind == OMPD_target_teams_distribute_parallel_for);
7414 return OMPCancelStack.getExitBlock();
7419 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7420 CaptureDeviceAddrMap) {
7421 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7422 for (
const Expr *OrigVarIt :
C.varlist()) {
7423 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(OrigVarIt)->getDecl());
7424 if (!Processed.insert(OrigVD).second)
7431 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7434 const auto *ME = cast<MemberExpr>(OED->getInit());
7435 assert(isa<CXXThisExpr>(ME->getBase()->IgnoreImpCasts()) &&
7436 "Base should be the current struct!");
7437 MatchingVD = ME->getMemberDecl();
7442 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7443 if (InitAddrIt == CaptureDeviceAddrMap.end())
7449 bool IsRegistered = PrivateScope.addPrivate(
7451 Address(InitAddrIt->second, Ty,
7453 assert(IsRegistered &&
"firstprivate var already registered as private");
7461 while (
const auto *OASE = dyn_cast<ArraySectionExpr>(
Base))
7462 Base = OASE->getBase()->IgnoreParenImpCasts();
7463 while (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(
Base))
7464 Base = ASE->getBase()->IgnoreParenImpCasts();
7465 return cast<VarDecl>(cast<DeclRefExpr>(
Base)->getDecl());
7470 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7471 CaptureDeviceAddrMap) {
7472 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7473 for (
const Expr *Ref :
C.varlist()) {
7475 if (!Processed.insert(OrigVD).second)
7481 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7484 const auto *ME = cast<MemberExpr>(OED->getInit());
7485 assert(isa<CXXThisExpr>(ME->getBase()) &&
7486 "Base should be the current struct!");
7487 MatchingVD = ME->getMemberDecl();
7492 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7493 if (InitAddrIt == CaptureDeviceAddrMap.end())
7499 Address(InitAddrIt->second, Ty,
7503 if (isa<DeclRefExpr>(Ref->IgnoreParenImpCasts()) ||
7512 (void)PrivateScope.addPrivate(OrigVD, PrivAddr);
7525 bool PrivatizeDevicePointers =
false;
7527 bool &PrivatizeDevicePointers;
7530 explicit DevicePointerPrivActionTy(
bool &PrivatizeDevicePointers)
7531 : PrivatizeDevicePointers(PrivatizeDevicePointers) {}
7533 PrivatizeDevicePointers =
true;
7536 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
7540 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
7546 PrivatizeDevicePointers =
false;
7552 if (PrivatizeDevicePointers) {
7553 OMPPrivateScope PrivateScope(CGF);
7557 Info.CaptureDeviceAddrMap);
7560 Info.CaptureDeviceAddrMap);
7561 (void)PrivateScope.Privatize();
7566 std::optional<OpenMPDirectiveKind> CaptureRegion;
7570 for (
const Expr *
E :
C->varlist()) {
7571 const Decl *
D = cast<DeclRefExpr>(
E)->getDecl();
7572 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(
D))
7576 for (
const Expr *
E :
C->varlist()) {
7578 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(
D))
7582 CaptureRegion = OMPD_unknown;
7585 OMPLexicalScope
Scope(CGF, S, CaptureRegion);
7592 PrivRCG.setAction(Action);
7597 OMPLexicalScope
Scope(CGF, S);
7612 const Expr *IfCond =
nullptr;
7614 IfCond =
C->getCondition();
7622 RCG.setAction(PrivAction);
7637 const Expr *IfCond =
nullptr;
7639 IfCond =
C->getCondition();
7646 OMPLexicalScope
Scope(*
this, S, OMPD_task);
7658 const Expr *IfCond =
nullptr;
7660 IfCond =
C->getCondition();
7667 OMPLexicalScope
Scope(*
this, S, OMPD_task);
7675 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
7679 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
7683 (void)PrivateScope.Privatize();
7703 llvm::Constant *Addr;
7706 S, ParentName, Fn, Addr,
true, CodeGen);
7707 assert(Fn && Addr &&
"Target device function emission failed.");
7726 CodeGenFunction::OMPCancelStackRAII CancelRegion(
7727 CGF, OMPD_target_parallel_for, S.hasCancel());
7743 llvm::Constant *Addr;
7746 S, ParentName, Fn, Addr,
true, CodeGen);
7747 assert(Fn && Addr &&
"Target device function emission failed.");
7782 llvm::Constant *Addr;
7785 S, ParentName, Fn, Addr,
true, CodeGen);
7786 assert(Fn && Addr &&
"Target device function emission failed.");
7800 CodeGenFunction::OMPPrivateScope &Privates) {
7801 const auto *VDecl = cast<VarDecl>(Helper->
getDecl());
7808 const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop);
7811 OMPLexicalScope
Scope(*
this, S, OMPD_taskloop,
false);
7815 const Expr *IfCond =
nullptr;
7816 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7817 if (
C->getNameModifier() == OMPD_unknown ||
7818 C->getNameModifier() == OMPD_taskloop) {
7819 IfCond =
C->getCondition();
7832 Data.Schedule.setInt(
false);
7835 (Clause->getModifier() == OMPC_GRAINSIZE_strict) ?
true :
false;
7838 Data.Schedule.setInt(
true);
7841 (Clause->getModifier() == OMPC_NUMTASKS_strict) ?
true :
false;
7855 llvm::BasicBlock *ContBlock =
nullptr;
7856 OMPLoopScope PreInitScope(CGF, S);
7857 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
7861 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock(
"taskloop.if.then");
7862 ContBlock = CGF.createBasicBlock(
"taskloop.if.end");
7863 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
7864 CGF.getProfileCount(&S));
7865 CGF.EmitBlock(ThenBlock);
7866 CGF.incrementProfileCounter(&S);
7869 (void)CGF.EmitOMPLinearClauseInit(S);
7871 OMPPrivateScope LoopScope(CGF);
7873 enum { LowerBound = 5, UpperBound, Stride, LastIter };
7875 auto *LBP = std::next(I, LowerBound);
7876 auto *UBP = std::next(I, UpperBound);
7877 auto *STP = std::next(I, Stride);
7878 auto *LIP = std::next(I, LastIter);
7879 mapParam(CGF, cast<DeclRefExpr>(S.getLowerBoundVariable()), *LBP,
7881 mapParam(CGF, cast<DeclRefExpr>(S.getUpperBoundVariable()), *UBP,
7883 mapParam(CGF, cast<DeclRefExpr>(S.getStrideVariable()), *STP, LoopScope);
7884 mapParam(CGF, cast<DeclRefExpr>(S.getIsLastIterVariable()), *LIP,
7886 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
7887 CGF.EmitOMPLinearClause(S, LoopScope);
7888 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
7889 (void)LoopScope.Privatize();
7891 const Expr *IVExpr = S.getIterationVariable();
7892 const auto *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
7893 CGF.EmitVarDecl(*IVDecl);
7894 CGF.EmitIgnoredExpr(S.getInit());
7899 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
7900 CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
7902 CGF.EmitIgnoredExpr(S.getCalcLastIteration());
7906 OMPLexicalScope
Scope(CGF, S, OMPD_taskloop,
false);
7914 CGF.EmitOMPInnerLoop(
7915 S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(),
7917 emitOMPLoopBodyWithStopPoint(CGF, S,
7918 CodeGenFunction::JumpDest());
7925 CGF.EmitBranch(ContBlock);
7926 CGF.EmitBlock(ContBlock,
true);
7929 if (HasLastprivateClause) {
7930 CGF.EmitOMPLastprivateClauseFinal(
7932 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
7933 CGF.GetAddrOfLocalVar(*LIP),
false,
7934 (*LIP)->getType(), S.getBeginLoc())));
7936 LoopScope.restoreMap();
7938 return CGF.
Builder.CreateIsNotNull(
7940 (*LIP)->
getType(), S.getBeginLoc()));
7943 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
7946 auto &&CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
7948 OMPLoopScope PreInitScope(CGF, S);
7949 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S,
7950 OutlinedFn, SharedsTy,
7951 CapturedStruct, IfCond,
Data);
7953 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
7981 OMPLexicalScope
Scope(*
this, S);
7993 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8005 OMPLexicalScope
Scope(*
this, S);
8017 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8035 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8054 const Expr *IfCond =
nullptr;
8056 IfCond =
C->getCondition();
8063 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8074 BindKind =
C->getBindKind();
8077 case OMPC_BIND_parallel:
8079 case OMPC_BIND_teams:
8081 case OMPC_BIND_thread:
8092 const auto *ForS = dyn_cast<ForStmt>(CS);
8093 if (ForS && !isa<DeclStmt>(ForS->getInit())) {
8094 OMPPrivateScope LoopScope(CGF);
8096 (void)LoopScope.Privatize();
8098 LoopScope.restoreMap();
8103 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
8138 OMPPrivateScope PrivateScope(CGF);
8139 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
8140 (void)PrivateScope.Privatize();
8141 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
8143 CGF.EmitOMPReductionClauseFinal(S, OMPD_teams);
8152 std::string StatusMsg,
8156 StatusMsg +=
": DEVICE";
8158 StatusMsg +=
": HOST";
8165 llvm::dbgs() << StatusMsg <<
": " <<
FileName <<
": " << LineNo <<
"\n";
8184 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
8186 (void)PrivateScope.Privatize();
8188 CGF, OMPD_distribute, CodeGenDistribute,
false);
8213 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
8215 (void)PrivateScope.Privatize();
8217 CGF, OMPD_distribute, CodeGenDistribute,
false);
8231 if (S.canBeParallelFor())
8244 if (S.canBeParallelFor())
8250 llvm::Constant *Addr;
8253 S, ParentName, Fn, Addr,
true, CodeGen);
8254 assert(Fn && Addr &&
8255 "Target device function emission failed for 'target teams loop'.");
8265 CodeGenFunction::OMPCancelStackRAII CancelRegion(
8266 CGF, OMPD_target_parallel_loop,
false);
8282 llvm::Constant *Addr;
8285 S, ParentName, Fn, Addr,
true, CodeGen);
8286 assert(Fn && Addr &&
"Target device function emission failed.");
8301 if (
const auto *SD = dyn_cast<OMPScanDirective>(&
D)) {
8305 if (!
D.hasAssociatedStmt() || !
D.getAssociatedStmt())
8308 OMPPrivateScope GlobalsScope(CGF);
8312 for (
const Expr *Ref :
C->varlist()) {
8313 const auto *DRE = cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
8316 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
8319 if (!CGF.LocalDeclMap.count(VD)) {
8321 GlobalsScope.addPrivate(VD, GlobLVal.
getAddress());
8327 (void)GlobalsScope.Privatize();
8328 ParentLoopDirectiveForScanRegion ScanRegion(CGF,
D);
8331 if (
const auto *LD = dyn_cast<OMPLoopDirective>(&
D)) {
8332 for (
const Expr *
E : LD->counters()) {
8333 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
8336 GlobalsScope.addPrivate(VD, GlobLVal.
getAddress());
8338 if (isa<OMPCapturedExprDecl>(VD)) {
8340 if (!CGF.LocalDeclMap.count(VD))
8345 if (!
C->getNumForLoops())
8347 for (
unsigned I = LD->getLoopsNumber(),
8348 E =
C->getLoopNumIterations().size();
8350 if (
const auto *VD = dyn_cast<OMPCapturedExprDecl>(
8351 cast<DeclRefExpr>(
C->getLoopCounter(I))->getDecl())) {
8353 if (!CGF.LocalDeclMap.count(VD))
8359 (void)GlobalsScope.Privatize();
8360 CGF.
EmitStmt(
D.getInnermostCapturedStmt()->getCapturedStmt());
8363 if (
D.getDirectiveKind() == OMPD_atomic ||
8364 D.getDirectiveKind() == OMPD_critical ||
8365 D.getDirectiveKind() == OMPD_section ||
8366 D.getDirectiveKind() == OMPD_master ||
8367 D.getDirectiveKind() == OMPD_masked ||
8368 D.getDirectiveKind() == OMPD_unroll ||
8369 D.getDirectiveKind() == OMPD_assume) {
8374 OMPSimdLexicalScope
Scope(*
this,
D);
8378 :
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 llvm::Function * emitOutlinedOrderedFunction(CodeGenModule &CGM, const CapturedStmt *S, SourceLocation Loc)
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 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 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 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)
enum clang::sema::@1712::IndirectLocalPathEntry::EntryKind Kind
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.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
TranslationUnitDecl * getTranslationUnitDecl() const
QualType getRecordType(const RecordDecl *Decl) 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.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
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.
const TargetInfo & getTargetInfo() const
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
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
A builtin binary operation expression such as "x + y" or "x <= y".
static BinaryOperator * Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, FPOptionsOverride FPFeatures)
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
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.
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.
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 ...
bool hasReducedDebugInfo() const
Check if type and variable info should be emitted.
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.
llvm::Value * CreateIsNull(Address Addr, const Twine &Name="")
Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
Address CreateInBoundsGEP(Address Addr, ArrayRef< llvm::Value * > IdxList, llvm::Type *ElementType, CharUnits Align, const 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.
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 emitTargetDataStandAloneCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device)
Emit the data mapping/movement code associated with the directive D that should be of the form 'targe...
virtual void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc)
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, kmp_int32 num_threads)...
virtual void emitSingleRegion(CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, SourceLocation Loc, ArrayRef< const Expr * > CopyprivateVars, ArrayRef< const Expr * > DestExprs, ArrayRef< const Expr * > SrcExprs, ArrayRef< const Expr * > AssignmentOps)
Emits a single region.
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 getDefaultScheduleAndChunk(CodeGenFunction &CGF, const OMPLoopDirective &S, OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const
Choose default schedule type and chunk value for the schedule clause.
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 void emitCancellationPointCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancellation point' construct.
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 void emitTargetDataCalls(CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, const Expr *Device, const RegionCodeGenTy &CodeGen, CGOpenMPRuntime::TargetDataInfo &Info)
Emit the target data mapping code associated with D.
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 emitTaskgroupRegion(CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, SourceLocation Loc)
Emit a taskgroup region.
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_int32 global_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.
void emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, OpenMPDependClauseKind NewDepKind, SourceLocation Loc)
Updates the dependency kind in the specified depobj object.
virtual void emitLastprivateConditionalFinalUpdate(CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, SourceLocation Loc)
Gets the address of the global copy used for lastprivate conditional update, if any.
virtual void emitErrorCall(CodeGenFunction &CGF, SourceLocation Loc, Expr *ME, bool IsFatal)
Emit __kmpc_error call for error directive extern void __kmpc_error(ident_t *loc, int severity,...
virtual void emitTaskyieldCall(CodeGenFunction &CGF, SourceLocation Loc)
Emits code for a taskyield directive.
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 emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPTaskDataTy &Data)
Emit code for 'taskwait' directive.
virtual void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc)
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, int proc_bind) to generat...
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.
Address emitDepobjDependClause(CodeGenFunction &CGF, const OMPTaskDataTy::DependData &Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs) for depob...
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.
llvm::AtomicOrdering getDefaultMemoryOrdering() const
Gets default memory ordering as specified in requires directive.
virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static non-chunked.
virtual void emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, const Expr *IfCond, OpenMPDirectiveKind CancelRegion)
Emit code for 'cancel' construct.
virtual void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc)
Emits a master region.
virtual llvm::Function * emitTaskOutlinedFunction(const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, const VarDecl *PartIDVar, const VarDecl *TaskTVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool Tied, unsigned &NumberOfParts)
Emits outlined function for the OpenMP task directive D.
void emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, SourceLocation Loc)
Emits the code to destroy the dependency object provided in depobj directive.
virtual void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Required to resolve existing problems in the runtime.
virtual void emitDoacrossOrdered(CodeGenFunction &CGF, const OMPDependClause *C)
Emit code for doacross ordered directive with 'depend' clause.
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 ...
virtual void getDefaultDistScheduleAndChunk(CodeGenFunction &CGF, const OMPLoopDirective &S, OpenMPDistScheduleClauseKind &ScheduleKind, llvm::Value *&Chunk) const
Choose default schedule type and chunk value for the dist_schedule clause.
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 emitCriticalRegion(CodeGenFunction &CGF, StringRef CriticalName, const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, const Expr *Hint=nullptr)
Emits a critical region.
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 emitOutlinedFunctionCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, ArrayRef< llvm::Value * > Args={}) const
Emits call of the outlined function with the provided arguments, translating these arguments to corre...
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 void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads)
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
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 void emitReduction(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > Privates, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, ArrayRef< const Expr * > ReductionOps, ReductionOptionsTy Options)
Emit a code for reduction clause.
std::pair< llvm::Value *, Address > emitDependClause(CodeGenFunction &CGF, ArrayRef< OMPTaskDataTy::DependData > Dependencies, SourceLocation Loc)
Emits list of dependecies based on the provided data (array of dependence/expression pairs).
virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const
Check if the specified ScheduleKind is dynamic.
Address emitLastprivateConditionalInit(CodeGenFunction &CGF, const VarDecl *VD)
Create specialized alloca to handle lastprivate conditionals.
virtual void emitOrderedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &OrderedOpGen, SourceLocation Loc, bool IsThreads)
Emit an ordered region.
virtual void emitTaskReductionFini(CodeGenFunction &CGF, SourceLocation Loc, bool IsWorksharingReduction)
Emits the following code for reduction clause with task modifier:
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.
virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S)
Emit the captured statement body.
virtual StringRef getHelperName() const
Get the name of the capture helper.
virtual const FieldDecl * lookup(const VarDecl *VD) const
Lookup the captured field decl for a variable.
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.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void EmitOMPTaskBasedDirective(const OMPExecutableDirective &S, const OpenMPDirectiveKind CapturedRegion, const RegionCodeGenTy &BodyGen, const TaskGenTy &TaskGen, OMPTaskDataTy &Data)
void EmitOMPTargetTeamsDirective(const OMPTargetTeamsDirective &S)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
void EmitOMPParallelGenericLoopDirective(const OMPLoopDirective &S)
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...
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
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 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.
void EmitOMPOrderedDirective(const OMPOrderedDirective &S)
void EmitOMPTargetDirective(const OMPTargetDirective &S)
bool EmitOMPFirstprivateClause(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
void EmitOMPReductionClauseInit(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope, bool ForInscan=false)
Emit initial code for reduction variables.
void EmitOMPAtomicDirective(const OMPAtomicDirective &S)
void EmitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &S)
void EmitOMPParallelMasterTaskLoopDirective(const OMPParallelMasterTaskLoopDirective &S)
void EmitAutoVarDecl(const VarDecl &D)
EmitAutoVarDecl - Emit an auto variable declaration.
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
static void EmitOMPTargetTeamsDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDirective &S)
Emit device code for the target teams directive.
void EmitOMPReverseDirective(const OMPReverseDirective &S)
static bool hasScalarEvaluationKind(QualType T)
llvm::function_ref< std::pair< llvm::Value *, llvm::Value * >(CodeGenFunction &, const OMPExecutableDirective &S, Address LB, Address UB)> CodeGenDispatchBoundsTy
CGCapturedStmtInfo * CapturedStmtInfo
void EmitDecl(const Decl &D)
EmitDecl - Emit a declaration.
static void EmitOMPTargetTeamsDistributeDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeDirective &S)
Emit device code for the target teams distribute directive.
Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr)
Load a pointer with type PtrTy stored at address Ptr.
static void EmitOMPTargetParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForSimdDirective &S)
Emit device code for the target parallel for simd directive.
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...
VlaSizePair getVLASize(const VariableArrayType *vla)
Returns an LLVM value that corresponds to the size, in non-variably-sized elements,...
const OMPExecutableDirective * OMPParentLoopDirectiveForScan
Parent loop-based directive for scan directive.
void EmitOMPTeamsDistributeParallelForDirective(const OMPTeamsDistributeParallelForDirective &S)
void EmitOMPTaskDirective(const OMPTaskDirective &S)
void EmitOMPScanDirective(const OMPScanDirective &S)
void EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S)
JumpDest getOMPCancelDestination(OpenMPDirectiveKind Kind)
void EmitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective &S)
void EmitOMPUseDevicePtrClause(const OMPUseDevicePtrClause &C, OMPPrivateScope &PrivateScope, const llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap)
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
RValue EmitAtomicLoad(LValue LV, SourceLocation SL, AggValueSlot Slot=AggValueSlot::ignored())
void EmitOMPDistributeLoop(const OMPLoopDirective &S, const CodeGenLoopTy &CodeGenLoop, Expr *IncExpr)
Emit code for the distribute loop-based directive.
void EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S)
static void EmitOMPTargetDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetDirective &S)
Emit device code for the target directive.
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
void EmitAtomicUpdate(LValue LVal, llvm::AtomicOrdering AO, const llvm::function_ref< RValue(RValue)> &UpdateOp, bool IsVolatile)
const LangOptions & getLangOpts() const
static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S)
Emit device code for the target simd directive.
void EmitOMPDistributeSimdDirective(const OMPDistributeSimdDirective &S)
void EmitOMPPrivateLoopCounters(const OMPLoopDirective &S, OMPPrivateScope &LoopScope)
Emit initial code for loop counters of loop-based directives.
void EmitOMPDistributeParallelForDirective(const OMPDistributeParallelForDirective &S)
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
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 EmitOMPInterchangeDirective(const OMPInterchangeDirective &S)
void EmitOMPTeamsGenericLoopDirective(const OMPTeamsGenericLoopDirective &S)
void EmitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &S)
Address EmitLoadOfReference(LValue RefLVal, LValueBaseInfo *PointeeBaseInfo=nullptr, TBAAAccessInfo *PointeeTBAAInfo=nullptr)
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...
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
void EmitOMPParallelDirective(const OMPParallelDirective &S)
void EmitOMPSimdFinal(const OMPLoopDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
llvm::Type * ConvertTypeForMem(QualType T)
void EmitOMPDistributeParallelForSimdDirective(const OMPDistributeParallelForSimdDirective &S)
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
void EmitOMPForSimdDirective(const OMPForSimdDirective &S)
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.
void GenerateOpenMPCapturedVars(const CapturedStmt &S, SmallVectorImpl< llvm::Value * > &CapturedVars)
CodeGenFunction * ParentCGF
JumpDest ReturnBlock
ReturnBlock - Unified return block.
const llvm::function_ref< void(CodeGenFunction &, llvm::Function *, const OMPTaskDataTy &)> TaskGenTy
static void EmitOMPTargetTeamsGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsGenericLoopDirective &S)
Emit device code for the target teams loop directive.
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...
void EmitOMPFlushDirective(const OMPFlushDirective &S)
llvm::BasicBlock * OMPBeforeScanBlock
void EmitOMPCancelDirective(const OMPCancelDirective &S)
void EmitOMPGenericLoopDirective(const OMPGenericLoopDirective &S)
void EmitOMPTargetTeamsDistributeDirective(const OMPTargetTeamsDistributeDirective &S)
ConstantEmission tryEmitAsConstant(DeclRefExpr *refExpr)
void EmitOMPTaskgroupDirective(const OMPTaskgroupDirective &S)
static void EmitOMPTargetTeamsDistributeParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForDirective &S)
void emitOMPSimpleStore(LValue LVal, RValue RVal, QualType RValTy, SourceLocation Loc)
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.
llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Location)
Converts Location to a DebugLoc, if debug information is enabled.
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
void EmitOMPDepobjDirective(const OMPDepobjDirective &S)
void EmitOMPSingleDirective(const OMPSingleDirective &S)
void EmitOMPTargetTeamsGenericLoopDirective(const OMPTargetTeamsGenericLoopDirective &S)
llvm::CanonicalLoopInfo * EmitOMPCollapsedCanonicalLoopNest(const Stmt *S, int Depth)
Emit the Stmt S and return its topmost canonical loop, if any.
void EmitSimpleOMPExecutableDirective(const OMPExecutableDirective &D)
Emit simple code for OpenMP directives in Simd-only mode.
void EmitOMPDistributeDirective(const OMPDistributeDirective &S)
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 EmitOMPParallelForDirective(const OMPParallelForDirective &S)
void EmitOMPTeamsDirective(const OMPTeamsDirective &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 EmitOMPUnrollDirective(const OMPUnrollDirective &S)
void EmitOMPParallelMasterTaskLoopSimdDirective(const OMPParallelMasterTaskLoopSimdDirective &S)
void EmitOMPTargetDataDirective(const OMPTargetDataDirective &S)
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
llvm::Value * EmitComplexToScalarConversion(ComplexPairTy Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified complex type to the specified destination type,...
bool isTrivialInitializer(const Expr *Init)
Determine whether the given initializer is trivial in the sense that it requires no code to be genera...
CGDebugInfo * getDebugInfo()
void EmitOMPTargetTeamsDistributeParallelForSimdDirective(const OMPTargetTeamsDistributeParallelForSimdDirective &S)
void EmitOMPTeamsDistributeParallelForSimdDirective(const OMPTeamsDistributeParallelForSimdDirective &S)
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
llvm::Function * GenerateCapturedStmtFunction(const CapturedStmt &S)
void EmitOMPInteropDirective(const OMPInteropDirective &S)
void EmitOMPReductionClauseFinal(const OMPExecutableDirective &D, const OpenMPDirectiveKind ReductionKind)
Emit final update of reduction values to original variables at the end of the directive.
llvm::BasicBlock * OMPScanDispatch
llvm::function_ref< std::pair< LValue, LValue >(CodeGenFunction &, const OMPExecutableDirective &S)> CodeGenLoopBoundsTy
void emitAlignmentAssumption(llvm::Value *PtrValue, QualType Ty, SourceLocation Loc, SourceLocation AssumptionLoc, llvm::Value *Alignment, llvm::Value *OffsetValue=nullptr)
void EmitOMPTargetTaskBasedDirective(const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen, OMPTargetDataInfo &InputInfo)
void EmitOMPScopeDirective(const OMPScopeDirective &S)
void EmitOMPTargetParallelDirective(const OMPTargetParallelDirective &S)
void EmitOMPParallelMaskedDirective(const OMPParallelMaskedDirective &S)
static void EmitOMPTargetParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForDirective &S)
Emit device code for the target parallel for directive.
void EmitOMPSimdInit(const OMPLoopDirective &D)
Helpers for the OpenMP loop directives.
int ExpectedOMPLoopDepth
Number of nested loop to be consumed by the last surrounding loop-associated directive.
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
void EmitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &S)
ASTContext & getContext() const
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...
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
static void EmitOMPTargetTeamsDistributeSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeSimdDirective &S)
Emit device code for the target teams distribute simd directive.
SmallVector< llvm::CanonicalLoopInfo *, 4 > OMPLoopNestStack
List of recently emitted OMPCanonicalLoops.
bool EmitOMPWorksharingLoop(const OMPLoopDirective &S, Expr *EUB, const CodeGenLoopBoundsTy &CodeGenLoopBounds, const CodeGenDispatchBoundsTy &CGDispatchBounds)
Emit code for the worksharing loop-based directive.
void EmitOMPLinearClause(const OMPLoopDirective &D, CodeGenFunction::OMPPrivateScope &PrivateScope)
Emit initial code for linear clauses.
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)
ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant,...
void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs={})
EmitStmt - Emit the code for the statement.
void EmitAutoVarCleanups(const AutoVarEmission &emission)
void EmitOMPTileDirective(const OMPTileDirective &S)
bool EmitOMPLinearClauseInit(const OMPLoopDirective &D)
Emit initial code for linear variables.
llvm::DenseMap< const ValueDecl *, FieldDecl * > LambdaCaptureFields
void EmitOMPLoopBody(const OMPLoopDirective &D, JumpDest LoopExit)
Helper for the OpenMP loop directives.
void EmitOMPLinearClauseFinal(const OMPLoopDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
Emit final code for linear clauses.
void EmitOMPSectionsDirective(const OMPSectionsDirective &S)
llvm::BasicBlock * OMPScanExitBlock
static void EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForSimdDirective &S)
Emit device code for the target teams distribute parallel for simd directive.
void EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst)
void EmitOMPUseDeviceAddrClause(const OMPUseDeviceAddrClause &C, OMPPrivateScope &PrivateScope, const llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap)
void EmitOMPTargetSimdDirective(const OMPTargetSimdDirective &S)
void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S)
void EmitOMPSimdDirective(const OMPSimdDirective &S)
void EmitOMPCriticalDirective(const OMPCriticalDirective &S)
void EmitOMPForDirective(const OMPForDirective &S)
void EmitOMPMetaDirective(const OMPMetaDirective &S)
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
void EmitOMPTargetUpdateDirective(const OMPTargetUpdateDirective &S)
LValue InitCapturedStruct(const CapturedStmt &S)
void EmitOMPParallelMasterDirective(const OMPParallelMasterDirective &S)
void EmitOMPTargetTeamsDistributeSimdDirective(const OMPTargetTeamsDistributeSimdDirective &S)
void processInReduction(const OMPExecutableDirective &S, OMPTaskDataTy &Data, CodeGenFunction &CGF, const CapturedStmt *CS, OMPPrivateScope &Scope)
void EmitOMPMasterDirective(const OMPMasterDirective &S)
void EmitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective &S)
void EmitOMPTargetParallelGenericLoopDirective(const OMPTargetParallelGenericLoopDirective &S)
void EmitOMPAssumeDirective(const OMPAssumeDirective &S)
bool EmitOMPCopyinClause(const OMPExecutableDirective &D)
Emit code for copyin clause in D directive.
void EmitOMPMaskedDirective(const OMPMaskedDirective &S)
uint64_t getProfileCount(const Stmt *S)
Get the profiler's count for the given statement.
void EmitOMPPrivateClause(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S)
llvm::Function * GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S, SourceLocation Loc)
void EmitOMPTargetParallelForSimdDirective(const OMPTargetParallelForSimdDirective &S)
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
Address GenerateCapturedStmtArgument(const CapturedStmt &S)
static void EmitOMPTargetParallelGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelGenericLoopDirective &S)
Emit device code for the target parallel loop directive.
llvm::function_ref< void(CodeGenFunction &, SourceLocation, const unsigned, const bool)> CodeGenOrderedTy
LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
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...
llvm::BasicBlock * OMPAfterScanBlock
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
void EmitOMPTargetExitDataDirective(const OMPTargetExitDataDirective &S)
void EmitOMPErrorDirective(const OMPErrorDirective &S)
void EmitOMPSectionDirective(const OMPSectionDirective &S)
static void EmitOMPTargetParallelDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelDirective &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 EmitOMPBarrierDirective(const OMPBarrierDirective &S)
void EmitStopPoint(const Stmt *S)
EmitStopPoint - Emit a debug stoppoint if we are emitting debug info.
void EmitOMPCancellationPointDirective(const OMPCancellationPointDirective &S)
void EnsureInsertPoint()
EnsureInsertPoint - Ensure that an insertion point is defined so that emitted IR has a place to go.
llvm::LLVMContext & getLLVMContext()
void EmitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective &S)
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
void EmitOMPTargetTeamsDistributeParallelForDirective(const OMPTargetTeamsDistributeParallelForDirective &S)
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
bool EmitOMPLastprivateClauseInit(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
Emit initial code for lastprivate variables.
void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S)
llvm::function_ref< void(CodeGenFunction &, const OMPLoopDirective &, JumpDest)> CodeGenLoopTy
void EmitOMPCanonicalLoop(const OMPCanonicalLoop *S)
Emit an OMPCanonicalLoop using the OpenMPIRBuilder.
void EmitOMPTeamsDistributeSimdDirective(const OMPTeamsDistributeSimdDirective &S)
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 EmitOMPTargetParallelForDirective(const OMPTargetParallelForDirective &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.
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
CharUnits GetTargetTypeStoreSize(llvm::Type *Ty) const
Return the store size, in character units, of the given LLVM type.
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
CharUnits getNaturalTypeAlignment(QualType T, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr, bool forPointeeType=false)
CodeGenTypes & getTypes()
const llvm::DataLayout & getDataLayout() const
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
llvm::Constant * GetAddrOfGlobal(GlobalDecl GD, ForDefinition_t IsForDefinition=NotForDefinition)
ASTContext & getContext() const
const CodeGenOptions & getCodeGenOpts() const
StringRef getMangledName(GlobalDecl GD)
llvm::Constant * getStaticLocalDeclAddress(const VarDecl *D)
llvm::ConstantInt * getSize(CharUnits numChars)
Emit the given number of characters as a value of type size_t.
void assignRegionCounters(GlobalDecl GD, llvm::Function *Fn)
Assign counters to regions and configure them for PGO of a given function.
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.
llvm::Type * ConvertTypeForMem(QualType T)
ConvertTypeForMem - Convert type T into a llvm::Type.
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)
void setUnrollCount(unsigned C)
Set the unroll count for the next loop pushed.
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 setUnrollState(const LoopAttributes::LVEnableState &State)
Set the next pushed loop unroll state.
void pop()
End the current loop.
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.
void emitAggregateType(CodeGenFunction &CGF, unsigned N)
Emits the code for the variable-modified type, if required.
void emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N)
Emits lvalue for the shared and original reduction item.
Class provides a way to call simple version of codegen for OpenMP region, or an advanced with possibl...
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 getEndLoc() const LLVM_READONLY
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
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
SourceLocation getBeginLoc() const LLVM_READONLY
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
The name of a declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreImplicitAsWritten() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
Represents a function declaration or definition.
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin=false, bool isInlineSpecified=false, bool hasWrittenPrototype=true, ConstexprSpecKind ConstexprKind=ConstexprSpecKind::Unspecified, Expr *TrailingRequiresClause=nullptr)
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.
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
std::vector< llvm::Triple > OMPTargetTriples
Triples of the OpenMP targets that the host code codegen should take into account in order to generat...
Represents a point when we exit a loop.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
A C++ nested-name-specifier augmented with source location information.
This represents 'acq_rel' clause in the '#pragma omp atomic|flush' directives.
This represents 'acquire' clause in the '#pragma omp atomic|flush' directives.
This represents clause 'aligned' in the '#pragma omp ...' directives.
This represents '#pragma omp atomic' directive.
This represents '#pragma omp barrier' directive.
This represents 'bind' clause in the '#pragma omp ...' directives.
This represents '#pragma omp cancel' directive.
This represents '#pragma omp cancellation point' directive.
Representation of an OpenMP canonical loop.
static OMPClauseWithPreInit * get(OMPClause *C)
This is a basic class for representing single OpenMP clause.
This represents clause 'copyin' in the '#pragma omp ...' directives.
This represents clause 'copyprivate' in the '#pragma omp ...' directives.
This represents '#pragma omp critical' directive.
This represents implicit clause 'depend' for the '#pragma omp task' directive.
This represents implicit clause 'depobj' for the '#pragma omp depobj' directive.
This represents '#pragma omp depobj' directive.
This represents 'destroy' clause in the '#pragma omp depobj' directive or the '#pragma omp interop' d...
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 is a basic class for representing single OpenMP executable directive.
OpenMPDirectiveKind getDirectiveKind() const
SourceLocation getEndLoc() const
Returns ending location of directive.
static llvm::iterator_range< specific_clause_iterator< SpecificClause > > getClausesOfKind(ArrayRef< OMPClause * > Clauses)
This represents 'fail' clause in the '#pragma omp atomic' directive.
OpenMPClauseKind getFailParameter() const
Gets the parameter (type memory-order-clause) in Fail clause.
This represents 'filter' clause in the '#pragma omp ...' directive.
This represents 'final' clause in the '#pragma omp ...' directive.
This represents clause 'firstprivate' in the '#pragma omp ...' directives.
This represents implicit clause 'flush' for the '#pragma omp flush' directive.
This represents '#pragma omp flush' directive.
This represents '#pragma omp for' directive.
This represents '#pragma omp for simd' directive.
Representation of the 'full' clause of the '#pragma omp unroll' directive.
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 'if' clause in the '#pragma omp ...' directive.
This represents clause 'in_reduction' in the '#pragma omp task' directives.
This represents clause 'inclusive' in the '#pragma omp scan' directive.
This represents the 'init' clause in '#pragma omp ...' directives.
Represents the '#pragma omp interchange' loop transformation directive.
This represents '#pragma omp interop' directive.
This represents clause 'lastprivate' in the '#pragma omp ...' directives.
This represents clause 'linear' in the '#pragma omp ...' directives.
The base class for all loop-based directives, including loop transformation directives.
static Stmt * tryToFindNextInnerLoop(Stmt *CurStmt, bool TryImperfectlyNestedLoops)
Try to find the next loop sub-statement in the specified statement CurStmt.
static bool doForAllLoops(Stmt *CurStmt, bool TryImperfectlyNestedLoops, unsigned NumLoops, llvm::function_ref< bool(unsigned, Stmt *)> Callback, llvm::function_ref< void(OMPLoopTransformationDirective *)> OnTransformationCallback)
Calls the specified callback function for all the loops in CurStmt, from the outermost to the innermo...
This is a common base class for loop directives ('omp simd', 'omp for', 'omp for simd' etc....
Expr * getPrevUpperBoundVariable() const
Expr * getPrevLowerBoundVariable() const
Expr * getIterationVariable() const
Expr * getUpperBoundVariable() const
Expr * getLowerBoundVariable() const
This represents '#pragma omp masked' directive.
This represents '#pragma omp master' directive.
This represents '#pragma omp master taskloop' directive.
This represents '#pragma omp master taskloop simd' directive.
This represents 'message' clause in the '#pragma omp error' directive.
Expr * getMessageString() const
Returns message string of the clause.
This represents 'nogroup' clause in the '#pragma omp ...' directive.
This represents 'nowait' clause in the '#pragma omp ...' directive.
This represents 'num_tasks' clause in the '#pragma omp ...' directive.
This represents 'num_teams' clause in the '#pragma omp ...' directive.
This represents 'num_threads' clause in the '#pragma omp ...' directive.
This represents 'order' clause in the '#pragma omp ...' directive.
This represents 'ordered' clause in the '#pragma omp ...' directive.
This represents '#pragma omp ordered' directive.
This represents '#pragma omp parallel' directive.
This represents '#pragma omp parallel for' directive.
This represents '#pragma omp parallel for simd' directive.
This represents '#pragma omp parallel masked' directive.
This represents '#pragma omp parallel master' directive.
This represents '#pragma omp parallel master taskloop' directive.
This represents '#pragma omp parallel master taskloop simd' directive.
This represents '#pragma omp parallel sections' directive.
Representation of the 'partial' clause of the '#pragma omp unroll' directive.
This represents 'priority' clause in the '#pragma omp ...' directive.
This represents clause 'private' in the '#pragma omp ...' directives.
This represents 'proc_bind' clause in the '#pragma omp ...' directive.
This represents clause 'reduction' in the '#pragma omp ...' directives.
This represents 'relaxed' clause in the '#pragma omp atomic' directives.
This represents 'release' clause in the '#pragma omp atomic|flush' directives.
Represents the '#pragma omp reverse' loop transformation directive.
This represents 'simd' clause in the '#pragma omp ...' directive.
This represents 'safelen' clause in the '#pragma omp ...' directive.
This represents '#pragma omp scan' directive.
This represents 'schedule' clause in the '#pragma omp ...' directive.
This represents '#pragma omp scope' directive.
This represents '#pragma omp section' directive.
This represents '#pragma omp sections' directive.
This represents 'seq_cst' clause in the '#pragma omp atomic|flush' directives.
This represents 'severity' clause in the '#pragma omp error' directive.
OpenMPSeverityClauseKind getSeverityKind() const
Returns kind of the clause.
This represents '#pragma omp simd' directive.
This represents 'simdlen' clause in the '#pragma omp ...' directive.
This represents '#pragma omp single' directive.
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.
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.
This represents '#pragma omp target update' directive.
This represents '#pragma omp task' directive.
This represents '#pragma omp taskloop' directive.
This represents '#pragma omp taskloop simd' directive.
This represents clause 'task_reduction' in the '#pragma omp taskgroup' directives.
This represents '#pragma omp taskgroup' directive.
This represents '#pragma omp taskwait' directive.
This represents '#pragma omp taskyield' 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.
This represents the '#pragma omp unroll' loop transformation directive.
This represents 'untied' clause in the '#pragma omp ...' directive.
This represents 'update' clause in the '#pragma omp atomic' directive.
This represents the 'use' clause in '#pragma omp ...' directives.
This represents clause 'use_device_addr' in the '#pragma omp ...' directives.
This represents clause 'use_device_ptr' in the '#pragma omp ...' directives.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
PointerType - C99 6.7.5.1 - Pointer Declarators.
Represents an unpacked "presumed" location which can be presented to the user.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
If a crash happens while one of these objects are live, the message is printed out along with the spe...
A (possibly-)qualified type.
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Represents a struct/union/class.
field_range fields() const
field_iterator field_begin() const
Base for LValueReferenceType and RValueReferenceType.
Scope - A scope is a transient data structure that is used while parsing the program.
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
Stmt - This represents one statement.
SourceLocation getBeginLoc() const LLVM_READONLY
SwitchStmt - This represents a 'switch' stmt.
virtual bool hasBuiltinAtomic(uint64_t AtomicSizeInBits, uint64_t AlignmentInBits) const
Returns true if the given target supports lock-free atomic operations at the specified width and alig...
bool isTLSSupported() const
Whether the target supports thread-local storage.
The base class of the type hierarchy.
bool isPointerType() const
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isScalarType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
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.
bool isAnyPointerType() const
bool isRecordType() const
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
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
@ 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)
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.
bool needsTaskBasedThreadLimit(OpenMPDirectiveKind DKind)
Checks if the specified target directive, combined or not, needs task based thread_limit.
@ Ctor_Complete
Complete object ctor.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
@ 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
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
@ OMPC_DIST_SCHEDULE_unknown
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
bool isOpenMPGenericLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive constitutes a 'loop' directive in the outermost nest.
OpenMPBindClauseKind
OpenMP bindings for the 'bind' clause.
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
@ Dtor_Complete
Complete object dtor.
bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of the composite or combined directives that need loop ...
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.
const FunctionProtoType * T
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
@ 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.
Diagnostic wrappers for TextAPI types for error reporting.
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.
llvm::PointerType * VoidPtrTy
llvm::IntegerType * Int64Ty
llvm::IntegerType * Int8Ty
i8, i16, i32, and i64
llvm::IntegerType * SizeTy
llvm::IntegerType * Int32Ty
llvm::IntegerType * IntPtrTy
llvm::PointerType * Int8PtrTy
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