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::InsertPointTy AfterIP = cantFail(
1843 OMPBuilder.createParallel(
Builder, AllocaIP, BodyGenCB, PrivCB, FiniCB,
1844 IfCond, NumThreads, ProcBind, S.hasCancel()));
1852 OMPPrivateScope PrivateScope(CGF);
1857 (void)PrivateScope.Privatize();
1858 CGF.
EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt());
1879class OMPTransformDirectiveScopeRAII {
1880 OMPLoopScope *
Scope =
nullptr;
1881 CodeGenFunction::CGCapturedStmtInfo *CGSI =
nullptr;
1882 CodeGenFunction::CGCapturedStmtRAII *CapInfoRAII =
nullptr;
1884 OMPTransformDirectiveScopeRAII(
const OMPTransformDirectiveScopeRAII &) =
1886 OMPTransformDirectiveScopeRAII &
1887 operator=(
const OMPTransformDirectiveScopeRAII &) =
delete;
1891 if (
const auto *Dir = dyn_cast<OMPLoopBasedDirective>(S)) {
1892 Scope =
new OMPLoopScope(CGF, *Dir);
1893 CGSI =
new CodeGenFunction::CGCapturedStmtInfo(
CR_OpenMP);
1894 CapInfoRAII =
new CodeGenFunction::CGCapturedStmtRAII(CGF, CGSI);
1897 ~OMPTransformDirectiveScopeRAII() {
1908 int MaxLevel,
int Level = 0) {
1909 assert(Level < MaxLevel &&
"Too deep lookup during loop body codegen.");
1910 const Stmt *SimplifiedS = S->IgnoreContainers();
1911 if (
const auto *CS = dyn_cast<CompoundStmt>(SimplifiedS)) {
1914 "LLVM IR generation of compound statement ('{}')");
1917 CodeGenFunction::LexicalScope
Scope(CGF, S->getSourceRange());
1918 for (
const Stmt *CurStmt : CS->body())
1919 emitBody(CGF, CurStmt, NextLoop, MaxLevel, Level);
1922 if (SimplifiedS == NextLoop) {
1923 if (
auto *Dir = dyn_cast<OMPLoopTransformationDirective>(SimplifiedS))
1924 SimplifiedS = Dir->getTransformedStmt();
1925 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(SimplifiedS))
1926 SimplifiedS = CanonLoop->getLoopStmt();
1927 if (
const auto *For = dyn_cast<ForStmt>(SimplifiedS)) {
1930 assert(isa<CXXForRangeStmt>(SimplifiedS) &&
1931 "Expected canonical for loop or range-based for loop.");
1932 const auto *CXXFor = cast<CXXForRangeStmt>(SimplifiedS);
1933 CGF.
EmitStmt(CXXFor->getLoopVarStmt());
1934 S = CXXFor->getBody();
1936 if (Level + 1 < MaxLevel) {
1939 emitBody(CGF, S, NextLoop, MaxLevel, Level + 1);
1948 RunCleanupsScope BodyScope(*
this);
1950 for (
const Expr *UE :
D.updates())
1958 for (
const Expr *UE :
C->updates())
1965 BreakContinueStack.push_back(BreakContinue(
LoopExit, Continue));
1966 for (
const Expr *
E :
D.finals_conditions()) {
1977 OMPPrivateScope InscanScope(*
this);
1979 bool IsInscanRegion = InscanScope.Privatize();
1980 if (IsInscanRegion) {
1990 if (EKind != OMPD_simd && !
getLangOpts().OpenMPSimd)
1999 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
2004 D.getLoopsNumber());
2012 BreakContinueStack.pop_back();
2023 std::unique_ptr<CodeGenFunction::CGCapturedStmtInfo> CSI =
2024 std::make_unique<CodeGenFunction::CGCapturedStmtInfo>(*S);
2025 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, CSI.get());
2032static llvm::CallInst *
2037 EffectiveArgs.reserve(Args.size() + 1);
2038 llvm::append_range(EffectiveArgs, Args);
2039 EffectiveArgs.push_back(Cap.second);
2044llvm::CanonicalLoopInfo *
2046 assert(Depth == 1 &&
"Nested loops with OpenMPIRBuilder not yet implemented");
2072 const Stmt *SyntacticalLoop = S->getLoopStmt();
2079 LexicalScope ForScope(*
this, S->getSourceRange());
2083 const Stmt *BodyStmt;
2084 if (
const auto *For = dyn_cast<ForStmt>(SyntacticalLoop)) {
2085 if (
const Stmt *InitStmt = For->getInit())
2087 BodyStmt = For->getBody();
2088 }
else if (
const auto *RangeFor =
2089 dyn_cast<CXXForRangeStmt>(SyntacticalLoop)) {
2090 if (
const DeclStmt *RangeStmt = RangeFor->getRangeStmt())
2092 if (
const DeclStmt *BeginStmt = RangeFor->getBeginStmt())
2094 if (
const DeclStmt *EndStmt = RangeFor->getEndStmt())
2096 if (
const DeclStmt *LoopVarStmt = RangeFor->getLoopVarStmt())
2098 BodyStmt = RangeFor->getBody();
2100 llvm_unreachable(
"Expected for-stmt or range-based for-stmt");
2103 const CapturedStmt *DistanceFunc = S->getDistanceFunc();
2120 auto BodyGen = [&,
this](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP,
2121 llvm::Value *IndVar) {
2126 const DeclRefExpr *LoopVarRef = S->getLoopVarRef();
2132 RunCleanupsScope BodyScope(*
this);
2134 return llvm::Error::success();
2137 llvm::CanonicalLoopInfo *CL =
2138 cantFail(OMPBuilder.createCanonicalLoop(
Builder, BodyGen, DistVal));
2141 Builder.restoreIP(CL->getAfterIP());
2142 ForScope.ForceCleanup();
2150 const Expr *IncExpr,
2161 const auto &OMPED = cast<OMPExecutableDirective>(S);
2162 const CapturedStmt *ICS = OMPED.getInnermostCapturedStmt();
2176 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
2177 if (RequiresCleanup)
2184 if (ExitBlock !=
LoopExit.getBlock()) {
2194 BreakContinueStack.push_back(BreakContinue(
LoopExit, Continue));
2202 BreakContinueStack.pop_back();
2213 bool HasLinears =
false;
2217 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
Init)->getDecl());
2218 if (
const auto *Ref =
2221 const auto *OrigVD = cast<VarDecl>(Ref->getDecl());
2237 if (
const auto *CS = cast_or_null<BinaryOperator>(
C->getCalcStep()))
2238 if (
const auto *SaveRef = cast<DeclRefExpr>(CS->getLHS())) {
2252 llvm::BasicBlock *DoneBB =
nullptr;
2255 auto IC =
C->varlist_begin();
2256 for (
const Expr *F :
C->finals()) {
2258 if (llvm::Value *Cond = CondGen(*
this)) {
2263 Builder.CreateCondBr(Cond, ThenBB, DoneBB);
2267 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl());
2272 CodeGenFunction::OMPPrivateScope VarScope(*
this);
2273 VarScope.addPrivate(OrigVD, OrigAddr);
2274 (void)VarScope.Privatize();
2278 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
2290 llvm::APInt ClauseAlignment(64, 0);
2291 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
2294 ClauseAlignment = AlignmentCI->getValue();
2296 for (
const Expr *
E : Clause->varlist()) {
2297 llvm::APInt Alignment(ClauseAlignment);
2298 if (Alignment == 0) {
2308 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2309 "alignment is not power of 2");
2310 if (Alignment != 0) {
2324 auto I = S.private_counters().begin();
2325 for (
const Expr *
E : S.counters()) {
2326 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
2327 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl());
2331 LocalDeclMap.erase(PrivateVD);
2332 (void)LoopScope.addPrivate(VD, VarEmission.getAllocatedAddress());
2340 (void)LoopScope.addPrivate(PrivateVD, VarEmission.getAllocatedAddress());
2346 if (!
C->getNumForLoops())
2348 for (
unsigned I = S.getLoopsNumber(),
E =
C->getLoopNumIterations().size();
2350 const auto *DRE = cast<DeclRefExpr>(
C->getLoopCounter(I));
2351 const auto *VD = cast<VarDecl>(DRE->getDecl());
2354 if (DRE->refersToEnclosingVariableOrCapture()) {
2355 (void)LoopScope.addPrivate(
2363 const Expr *Cond, llvm::BasicBlock *TrueBlock,
2364 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
2368 CodeGenFunction::OMPPrivateScope PreCondScope(CGF);
2370 (void)PreCondScope.Privatize();
2372 for (
const Expr *I : S.inits()) {
2378 CodeGenFunction::OMPMapVars PreCondVars;
2379 for (
const Expr *
E : S.dependent_counters()) {
2383 "dependent counter must not be an iterator.");
2384 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
2387 (void)PreCondVars.setVarAddr(CGF, VD, CounterAddr);
2389 (void)PreCondVars.apply(CGF);
2390 for (
const Expr *
E : S.dependent_inits()) {
2397 PreCondVars.restore(CGF);
2404 llvm::DenseSet<const VarDecl *> SIMDLCVs;
2407 const auto *LoopDirective = cast<OMPLoopDirective>(&
D);
2408 for (
const Expr *
C : LoopDirective->counters()) {
2414 auto CurPrivate =
C->privates().begin();
2415 for (
const Expr *
E :
C->varlist()) {
2416 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
2417 const auto *PrivateVD =
2418 cast<VarDecl>(cast<DeclRefExpr>(*CurPrivate)->getDecl());
2424 assert(IsRegistered &&
"linear var already registered as private");
2442 auto *Val = cast<llvm::ConstantInt>(Len.
getScalarVal());
2451 auto *Val = cast<llvm::ConstantInt>(Len.
getScalarVal());
2466 if (
C->getKind() == OMPC_ORDER_concurrent)
2469 if ((EKind == OMPD_simd ||
2473 return C->getModifier() == OMPC_REDUCTION_inscan;
2484 llvm::BasicBlock *DoneBB =
nullptr;
2485 auto IC =
D.counters().begin();
2486 auto IPC =
D.private_counters().begin();
2487 for (
const Expr *F :
D.finals()) {
2488 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>((*IC))->getDecl());
2489 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>((*IPC))->getDecl());
2490 const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
2492 OrigVD->hasGlobalStorage() || CED) {
2494 if (llvm::Value *Cond = CondGen(*
this)) {
2499 Builder.CreateCondBr(Cond, ThenBB, DoneBB);
2512 OMPPrivateScope VarScope(*
this);
2513 VarScope.addPrivate(OrigVD, OrigAddr);
2514 (void)VarScope.Privatize();
2526 CodeGenFunction::JumpDest
LoopExit) {
2534 auto VDecl = cast<VarDecl>(Helper->
getDecl());
2542 auto &&ThenGen = [&S, &SimdInitGen, &BodyCodeGen](
CodeGenFunction &CGF,
2545 CodeGenFunction::OMPLocalDeclMapRAII
Scope(CGF);
2551 CodeGenFunction::OMPLocalDeclMapRAII
Scope(CGF);
2556 const Expr *IfCond =
nullptr;
2559 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
2561 (
C->getNameModifier() == OMPD_unknown ||
2562 C->getNameModifier() == OMPD_simd)) {
2563 IfCond =
C->getCondition();
2579 OMPLoopScope PreInitScope(CGF, S);
2601 llvm::BasicBlock *ContBlock =
nullptr;
2608 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
2615 const Expr *IVExpr = S.getIterationVariable();
2616 const auto *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
2623 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
2624 CGF.
EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
2632 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
2638 CGF, S, CGF.
EmitLValue(S.getIterationVariable()));
2640 (void)LoopScope.Privatize();
2651 S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(),
2653 emitOMPLoopBodyWithStopPoint(CGF, S,
2654 CodeGenFunction::JumpDest());
2660 if (HasLastprivateClause)
2665 LoopScope.restoreMap();
2681 if (!(isa<OMPSimdlenClause>(
C) || isa<OMPSafelenClause>(
C) ||
2682 isa<OMPOrderClause>(
C) || isa<OMPAlignedClause>(
C)))
2689 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(S.getRawStmt())) {
2690 if (
const Stmt *SyntacticalLoop = CanonLoop->getLoopStmt()) {
2691 for (
const Stmt *SubStmt : SyntacticalLoop->
children()) {
2694 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(SubStmt)) {
2698 if (isa<OMPOrderedDirective>(CSSubStmt)) {
2709static llvm::MapVector<llvm::Value *, llvm::Value *>
2711 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars;
2713 llvm::APInt ClauseAlignment(64, 0);
2714 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
2717 ClauseAlignment = AlignmentCI->getValue();
2719 for (
const Expr *
E : Clause->varlist()) {
2720 llvm::APInt Alignment(ClauseAlignment);
2721 if (Alignment == 0) {
2731 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2732 "alignment is not power of 2");
2734 AlignedVars[PtrValue] = CGF.
Builder.getInt64(Alignment.getSExtValue());
2744 bool UseOMPIRBuilder =
2746 if (UseOMPIRBuilder) {
2750 if (UseOMPIRBuilder) {
2751 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars =
2754 const Stmt *Inner = S.getRawStmt();
2755 llvm::CanonicalLoopInfo *CLI =
2756 CGF.EmitOMPCollapsedCanonicalLoopNest(Inner, 1);
2758 llvm::OpenMPIRBuilder &OMPBuilder =
2761 llvm::ConstantInt *Simdlen =
nullptr;
2765 auto *Val = cast<llvm::ConstantInt>(Len.
getScalarVal());
2768 llvm::ConstantInt *Safelen =
nullptr;
2772 auto *Val = cast<llvm::ConstantInt>(Len.
getScalarVal());
2775 llvm::omp::OrderKind Order = llvm::omp::OrderKind::OMP_ORDER_unknown;
2777 if (
C->getKind() == OpenMPOrderClauseKind::OMPC_ORDER_concurrent) {
2778 Order = llvm::omp::OrderKind::OMP_ORDER_concurrent;
2783 OMPBuilder.applySimd(CLI, AlignedVars,
2784 nullptr, Order, Simdlen, Safelen);
2791 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
2798 CodeGenFunction::ParentLoopDirectiveForScanRegion ScanRegion(CGF, S);
2806 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
2819 OMPTransformDirectiveScopeRAII TileScope(*
this, &S);
2825 OMPTransformDirectiveScopeRAII ReverseScope(*
this, &S);
2832 OMPTransformDirectiveScopeRAII InterchangeScope(*
this, &S);
2839 if (UseOMPIRBuilder) {
2841 const Stmt *Inner = S.getRawStmt();
2852 llvm::CanonicalLoopInfo *UnrolledCLI =
nullptr;
2856 OMPBuilder.unrollLoopFull(DL, CLI);
2859 if (
Expr *FactorExpr = PartialClause->getFactor()) {
2860 Factor = FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
2861 assert(Factor >= 1 &&
"Only positive factors are valid");
2863 OMPBuilder.unrollLoopPartial(DL, CLI, Factor,
2864 NeedsUnrolledCLI ? &UnrolledCLI :
nullptr);
2866 OMPBuilder.unrollLoopHeuristic(DL, CLI);
2869 assert((!NeedsUnrolledCLI || UnrolledCLI) &&
2870 "NeedsUnrolledCLI implies UnrolledCLI to be set");
2887 if (
Expr *FactorExpr = PartialClause->getFactor()) {
2889 FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
2890 assert(Factor >= 1 &&
"Only positive factors are valid");
2898void CodeGenFunction::EmitOMPOuterLoop(
2900 CodeGenFunction::OMPPrivateScope &LoopScope,
2901 const CodeGenFunction::OMPLoopArguments &LoopArgs,
2906 const Expr *IVExpr = S.getIterationVariable();
2920 llvm::Value *BoolCondVal =
nullptr;
2921 if (!DynamicOrOrdered) {
2932 RT.
emitForNext(*
this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL,
2933 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST);
2938 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
2939 if (LoopScope.requiresCleanups())
2943 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
2944 if (ExitBlock !=
LoopExit.getBlock()) {
2952 if (DynamicOrOrdered)
2957 BreakContinueStack.push_back(BreakContinue(
LoopExit, Continue));
2968 if (
C->getKind() == OMPC_ORDER_concurrent)
2974 [&S, &LoopArgs,
LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered,
2982 CGF.EmitOMPInnerLoop(
2983 S, LoopScope.requiresCleanups(), LoopArgs.Cond, LoopArgs.IncExpr,
2985 CodeGenLoop(CGF, S, LoopExit);
2988 CodeGenOrdered(CGF, Loc, IVSize, IVSigned);
2993 BreakContinueStack.pop_back();
2994 if (!DynamicOrOrdered) {
3007 auto &&CodeGen = [DynamicOrOrdered, &S, &LoopArgs](
CodeGenFunction &CGF) {
3008 if (!DynamicOrOrdered)
3009 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
3012 OMPCancelStack.emitExit(*
this, EKind, CodeGen);
3015void CodeGenFunction::EmitOMPForOuterLoop(
3018 const OMPLoopArguments &LoopArgs,
3026 LoopArgs.Chunk !=
nullptr)) &&
3027 "static non-chunked schedule does not need outer loop");
3081 const Expr *IVExpr = S.getIterationVariable();
3085 if (DynamicOrOrdered) {
3086 const std::pair<llvm::Value *, llvm::Value *> DispatchBounds =
3087 CGDispatchBounds(*
this, S, LoopArgs.LB, LoopArgs.UB);
3088 llvm::Value *LBVal = DispatchBounds.first;
3089 llvm::Value *UBVal = DispatchBounds.second;
3093 IVSigned, Ordered, DipatchRTInputValues);
3096 IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
3097 LoopArgs.ST, LoopArgs.Chunk);
3104 const unsigned IVSize,
3105 const bool IVSigned) {
3112 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST,
3113 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB);
3114 OuterLoopArgs.IncExpr = S.getInc();
3115 OuterLoopArgs.Init = S.getInit();
3116 OuterLoopArgs.Cond = S.getCond();
3117 OuterLoopArgs.NextLB = S.getNextLowerBound();
3118 OuterLoopArgs.NextUB = S.getNextUpperBound();
3119 OuterLoopArgs.DKind = LoopArgs.DKind;
3120 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
3122 if (DynamicOrOrdered) {
3128 const unsigned IVSize,
const bool IVSigned) {}
3130void CodeGenFunction::EmitOMPDistributeOuterLoop(
3132 OMPPrivateScope &LoopScope,
const OMPLoopArguments &LoopArgs,
3142 const Expr *IVExpr = S.getIterationVariable();
3148 IVSize, IVSigned,
false, LoopArgs.IL, LoopArgs.LB,
3149 LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
3156 IncExpr = S.getDistInc();
3158 IncExpr = S.getInc();
3163 OMPLoopArguments OuterLoopArgs;
3164 OuterLoopArgs.LB = LoopArgs.LB;
3165 OuterLoopArgs.UB = LoopArgs.UB;
3166 OuterLoopArgs.ST = LoopArgs.ST;
3167 OuterLoopArgs.IL = LoopArgs.IL;
3168 OuterLoopArgs.Chunk = LoopArgs.Chunk;
3170 ? S.getCombinedEnsureUpperBound()
3171 : S.getEnsureUpperBound();
3172 OuterLoopArgs.IncExpr = IncExpr;
3174 ? S.getCombinedInit()
3177 ? S.getCombinedCond()
3180 ? S.getCombinedNextLowerBound()
3181 : S.getNextLowerBound();
3183 ? S.getCombinedNextUpperBound()
3184 : S.getNextUpperBound();
3185 OuterLoopArgs.DKind = OMPD_distribute;
3187 EmitOMPOuterLoop(
false,
false, S,
3188 LoopScope, OuterLoopArgs, CodeGenLoopContent,
3192static std::pair<LValue, LValue>
3235static std::pair<llvm::Value *, llvm::Value *>
3246 llvm::Value *LBVal =
3248 llvm::Value *UBVal =
3250 return {LBVal, UBVal};
3256 const auto &Dir = cast<OMPLoopDirective>(S);
3258 CGF.
EmitLValue(cast<DeclRefExpr>(Dir.getCombinedLowerBoundVariable()));
3259 llvm::Value *LBCast = CGF.
Builder.CreateIntCast(
3261 CapturedVars.push_back(LBCast);
3263 CGF.
EmitLValue(cast<DeclRefExpr>(Dir.getCombinedUpperBoundVariable()));
3265 llvm::Value *UBCast = CGF.
Builder.CreateIntCast(
3267 CapturedVars.push_back(UBCast);
3273 CodeGenFunction::JumpDest
LoopExit) {
3278 bool HasCancel =
false;
3280 if (
const auto *
D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
3281 HasCancel =
D->hasCancel();
3282 else if (
const auto *
D = dyn_cast<OMPDistributeParallelForDirective>(&S))
3283 HasCancel =
D->hasCancel();
3284 else if (
const auto *
D =
3285 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S))
3286 HasCancel =
D->hasCancel();
3288 CodeGenFunction::OMPCancelStackRAII CancelRegion(CGF, EKind, HasCancel);
3296 CGInlinedWorksharingLoop,
3306 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3316 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3325 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
3336 llvm::Constant *Addr;
3339 S, ParentName, Fn, Addr,
true, CodeGen);
3340 assert(Fn && Addr &&
"Target device function emission failed.");
3352struct ScheduleKindModifiersTy {
3368 const auto *IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
3369 const auto *IVDecl = cast<VarDecl>(IVExpr->getDecl());
3375 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
3383 bool HasLastprivateClause;
3386 OMPLoopScope PreInitScope(*
this, S);
3391 llvm::BasicBlock *ContBlock =
nullptr;
3398 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
3404 RunCleanupsScope DoacrossCleanupScope(*
this);
3405 bool Ordered =
false;
3407 if (OrderedClause->getNumForLoops())
3413 llvm::DenseSet<const Expr *> EmittedFinals;
3418 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*
this, S);
3419 LValue LB = Bounds.first;
3420 LValue UB = Bounds.second;
3429 OMPPrivateScope LoopScope(*
this);
3435 *
this, S.getBeginLoc(), OMPD_unknown,
false,
3440 *
this, S,
EmitLValue(S.getIterationVariable()));
3445 (void)LoopScope.Privatize();
3450 const Expr *ChunkExpr =
nullptr;
3453 ScheduleKind.
Schedule =
C->getScheduleKind();
3454 ScheduleKind.
M1 =
C->getFirstScheduleModifier();
3455 ScheduleKind.
M2 =
C->getSecondScheduleModifier();
3456 ChunkExpr =
C->getChunkSize();
3460 *
this, S, ScheduleKind.
Schedule, ChunkExpr);
3462 bool HasChunkSizeOne =
false;
3463 llvm::Value *Chunk =
nullptr;
3467 S.getIterationVariable()->getType(),
3471 llvm::APSInt EvaluatedChunk =
Result.Val.getInt();
3472 HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
3481 bool StaticChunkedOne =
3483 Chunk !=
nullptr) &&
3487 (ScheduleKind.
Schedule == OMPC_SCHEDULE_static &&
3488 !(ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
3489 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)) ||
3490 ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
3491 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
3493 Chunk !=
nullptr) ||
3494 StaticChunkedOne) &&
3504 if (C->getKind() == OMPC_ORDER_concurrent)
3505 CGF.LoopStack.setParallel(true);
3508 [IVSize, IVSigned, Ordered, IL, LB, UB, ST, StaticChunkedOne, Chunk,
3517 IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(),
3518 UB.getAddress(), ST.getAddress(),
3519 StaticChunkedOne ? Chunk :
nullptr);
3520 CGF.CGM.getOpenMPRuntime().emitForStaticInit(
3521 CGF, S.getBeginLoc(), EKind, ScheduleKind, StaticInit);
3523 if (!StaticChunkedOne)
3524 CGF.EmitIgnoredExpr(S.getEnsureUpperBound());
3526 CGF.EmitIgnoredExpr(S.getInit());
3540 CGF.EmitOMPInnerLoop(
3541 S, LoopScope.requiresCleanups(),
3542 StaticChunkedOne ? S.getCombinedParForInDistCond()
3544 StaticChunkedOne ? S.getDistInc() : S.getInc(),
3546 emitOMPLoopBodyWithStopPoint(CGF, S, LoopExit);
3553 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
3556 OMPCancelStack.emitExit(*
this, EKind, CodeGen);
3560 OMPLoopArguments LoopArguments(LB.getAddress(), UB.getAddress(),
3561 ST.getAddress(), IL.getAddress(), Chunk,
3563 LoopArguments.DKind = OMPD_for;
3564 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
3565 LoopArguments, CGDispatchBounds);
3569 return CGF.
Builder.CreateIsNotNull(
3575 ? OMPD_parallel_for_simd
3580 return CGF.
Builder.CreateIsNotNull(
3584 if (HasLastprivateClause)
3588 LoopScope.restoreMap();
3590 return CGF.
Builder.CreateIsNotNull(
3594 DoacrossCleanupScope.ForceCleanup();
3601 return HasLastprivateClause;
3607static std::pair<LValue, LValue>
3609 const auto &LS = cast<OMPLoopDirective>(S);
3621static std::pair<llvm::Value *, llvm::Value *>
3624 const auto &LS = cast<OMPLoopDirective>(S);
3625 const Expr *IVExpr = LS.getIterationVariable();
3627 llvm::Value *LBVal = CGF.
Builder.getIntN(IVSize, 0);
3629 return {LBVal, UBVal};
3641 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
3642 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
3643 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
3649 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
3650 "Only inscan reductions are expected.");
3651 Shareds.append(
C->varlist_begin(),
C->varlist_end());
3652 Privates.append(
C->privates().begin(),
C->privates().end());
3653 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
3654 CopyArrayTemps.append(
C->copy_array_temps().begin(),
3655 C->copy_array_temps().end());
3663 auto *ITA = CopyArrayTemps.begin();
3664 for (
const Expr *IRef : Privates) {
3665 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(IRef)->getDecl());
3668 if (PrivateVD->getType()->isVariablyModifiedType()) {
3672 CodeGenFunction::OpaqueValueMapping DimMapping(
3674 cast<OpaqueValueExpr>(
3675 cast<VariableArrayType>((*ITA)->getType()->getAsArrayTypeUnsafe())
3679 CGF.
EmitVarDecl(*cast<VarDecl>(cast<DeclRefExpr>(*ITA)->getDecl()));
3693 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
3694 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
3695 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
3703 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
3704 "Only inscan reductions are expected.");
3705 Shareds.append(
C->varlist_begin(),
C->varlist_end());
3706 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
3707 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
3708 Privates.append(
C->privates().begin(),
C->privates().end());
3709 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
3710 CopyArrayElems.append(
C->copy_array_elems().begin(),
3711 C->copy_array_elems().end());
3715 llvm::Value *OMPLast = CGF.
Builder.CreateNSWSub(
3716 OMPScanNumIterations,
3717 llvm::ConstantInt::get(CGF.
SizeTy, 1,
false));
3718 for (
unsigned I = 0,
E = CopyArrayElems.size(); I <
E; ++I) {
3719 const Expr *PrivateExpr = Privates[I];
3720 const Expr *OrigExpr = Shareds[I];
3721 const Expr *CopyArrayElem = CopyArrayElems[I];
3722 CodeGenFunction::OpaqueValueMapping IdxMapping(
3724 cast<OpaqueValueExpr>(
3725 cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()),
3731 cast<VarDecl>(cast<DeclRefExpr>(LHSs[I])->getDecl()),
3732 cast<VarDecl>(cast<DeclRefExpr>(RHSs[I])->getDecl()), CopyOps[I]);
3760 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
3761 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
3768 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
3769 "Only inscan reductions are expected.");
3770 Privates.append(
C->privates().begin(),
C->privates().end());
3771 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
3772 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
3773 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
3774 CopyArrayElems.append(
C->copy_array_elems().begin(),
3775 C->copy_array_elems().end());
3777 CodeGenFunction::ParentLoopDirectiveForScanRegion ScanRegion(CGF, S);
3786 CodeGenFunction::OMPLocalDeclMapRAII
Scope(CGF);
3790 auto &&CodeGen = [&S, OMPScanNumIterations, &LHSs, &RHSs, &CopyArrayElems,
3797 llvm::BasicBlock *InputBB = CGF.Builder.GetInsertBlock();
3798 llvm::BasicBlock *LoopBB = CGF.createBasicBlock(
"omp.outer.log.scan.body");
3799 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
"omp.outer.log.scan.exit");
3801 CGF.CGM.getIntrinsic(llvm::Intrinsic::log2, CGF.DoubleTy);
3803 CGF.Builder.CreateUIToFP(OMPScanNumIterations, CGF.DoubleTy);
3804 llvm::Value *LogVal = CGF.EmitNounwindRuntimeCall(F, Arg);
3805 F = CGF.CGM.getIntrinsic(llvm::Intrinsic::ceil, CGF.DoubleTy);
3806 LogVal = CGF.EmitNounwindRuntimeCall(F, LogVal);
3807 LogVal = CGF.Builder.CreateFPToUI(LogVal, CGF.IntTy);
3808 llvm::Value *NMin1 = CGF.Builder.CreateNUWSub(
3809 OMPScanNumIterations, llvm::ConstantInt::get(CGF.SizeTy, 1));
3811 CGF.EmitBlock(LoopBB);
3812 auto *Counter = CGF.Builder.CreatePHI(CGF.IntTy, 2);
3814 auto *Pow2K = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
3815 Counter->addIncoming(llvm::ConstantInt::get(CGF.IntTy, 0), InputBB);
3816 Pow2K->addIncoming(llvm::ConstantInt::get(CGF.SizeTy, 1), InputBB);
3819 llvm::BasicBlock *InnerLoopBB =
3820 CGF.createBasicBlock(
"omp.inner.log.scan.body");
3821 llvm::BasicBlock *InnerExitBB =
3822 CGF.createBasicBlock(
"omp.inner.log.scan.exit");
3823 llvm::Value *CmpI = CGF.Builder.CreateICmpUGE(NMin1, Pow2K);
3824 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
3825 CGF.EmitBlock(InnerLoopBB);
3826 auto *IVal = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
3827 IVal->addIncoming(NMin1, LoopBB);
3829 CodeGenFunction::OMPPrivateScope PrivScope(CGF);
3830 auto *ILHS = LHSs.begin();
3831 auto *IRHS = RHSs.begin();
3832 for (
const Expr *CopyArrayElem : CopyArrayElems) {
3833 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
3834 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
3837 CodeGenFunction::OpaqueValueMapping IdxMapping(
3839 cast<OpaqueValueExpr>(
3840 cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()),
3842 LHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
3844 PrivScope.addPrivate(LHSVD, LHSAddr);
3847 llvm::Value *OffsetIVal = CGF.Builder.CreateNUWSub(IVal, Pow2K);
3848 CodeGenFunction::OpaqueValueMapping IdxMapping(
3850 cast<OpaqueValueExpr>(
3851 cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()),
3853 RHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
3855 PrivScope.addPrivate(RHSVD, RHSAddr);
3859 PrivScope.Privatize();
3860 CGF.CGM.getOpenMPRuntime().emitReduction(
3861 CGF, S.getEndLoc(), Privates, LHSs, RHSs, ReductionOps,
3862 {true, true, OMPD_unknown});
3864 llvm::Value *NextIVal =
3865 CGF.Builder.CreateNUWSub(IVal, llvm::ConstantInt::get(CGF.SizeTy, 1));
3866 IVal->addIncoming(NextIVal, CGF.Builder.GetInsertBlock());
3867 CmpI = CGF.Builder.CreateICmpUGE(NextIVal, Pow2K);
3868 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
3869 CGF.EmitBlock(InnerExitBB);
3871 CGF.Builder.CreateNUWAdd(Counter, llvm::ConstantInt::get(CGF.IntTy, 1));
3872 Counter->addIncoming(Next, CGF.Builder.GetInsertBlock());
3874 llvm::Value *NextPow2K =
3875 CGF.Builder.CreateShl(Pow2K, 1,
"",
true);
3876 Pow2K->addIncoming(NextPow2K, CGF.Builder.GetInsertBlock());
3877 llvm::Value *Cmp = CGF.Builder.CreateICmpNE(Next, LogVal);
3878 CGF.Builder.CreateCondBr(Cmp, LoopBB, ExitBB);
3880 CGF.EmitBlock(ExitBB);
3884 CGF.CGM.getOpenMPRuntime().emitMasterRegion(CGF, CodeGen, S.getBeginLoc());
3885 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
3886 CGF, S.getBeginLoc(), OMPD_unknown,
false,
3893 CGF.OMPFirstScanLoop =
false;
3900 bool HasLastprivates;
3904 return C->getModifier() == OMPC_REDUCTION_inscan;
3907 CodeGenFunction::OMPLocalDeclMapRAII
Scope(CGF);
3908 OMPLoopScope LoopScope(CGF, S);
3911 const auto &&FirstGen = [&S, HasCancel, EKind](
CodeGenFunction &CGF) {
3912 CodeGenFunction::OMPCancelStackRAII CancelRegion(CGF, EKind, HasCancel);
3920 const auto &&SecondGen = [&S, HasCancel, EKind,
3922 CodeGenFunction::OMPCancelStackRAII CancelRegion(CGF, EKind, HasCancel);
3933 CodeGenFunction::OMPCancelStackRAII CancelRegion(CGF, EKind, HasCancel);
3938 return HasLastprivates;
3948 if (isa<OMPNowaitClause, OMPBindClause>(
C))
3951 if (
auto *SC = dyn_cast<OMPScheduleClause>(
C)) {
3956 switch (SC->getScheduleKind()) {
3957 case OMPC_SCHEDULE_auto:
3958 case OMPC_SCHEDULE_dynamic:
3959 case OMPC_SCHEDULE_runtime:
3960 case OMPC_SCHEDULE_guided:
3961 case OMPC_SCHEDULE_static:
3974static llvm::omp::ScheduleKind
3976 switch (ScheduleClauseKind) {
3978 return llvm::omp::OMP_SCHEDULE_Default;
3979 case OMPC_SCHEDULE_auto:
3980 return llvm::omp::OMP_SCHEDULE_Auto;
3981 case OMPC_SCHEDULE_dynamic:
3982 return llvm::omp::OMP_SCHEDULE_Dynamic;
3983 case OMPC_SCHEDULE_guided:
3984 return llvm::omp::OMP_SCHEDULE_Guided;
3985 case OMPC_SCHEDULE_runtime:
3986 return llvm::omp::OMP_SCHEDULE_Runtime;
3987 case OMPC_SCHEDULE_static:
3988 return llvm::omp::OMP_SCHEDULE_Static;
3990 llvm_unreachable(
"Unhandled schedule kind");
3997 bool HasLastprivates =
false;
4000 auto &&CodeGen = [&S, &
CGM, HasCancel, &HasLastprivates,
4003 if (UseOMPIRBuilder) {
4006 llvm::omp::ScheduleKind SchedKind = llvm::omp::OMP_SCHEDULE_Default;
4007 llvm::Value *ChunkSize =
nullptr;
4011 if (
const Expr *ChunkSizeExpr = SchedClause->getChunkSize())
4016 const Stmt *Inner = S.getRawStmt();
4017 llvm::CanonicalLoopInfo *CLI =
4020 llvm::OpenMPIRBuilder &OMPBuilder =
4022 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4024 cantFail(OMPBuilder.applyWorkshareLoop(
4025 CGF.
Builder.getCurrentDebugLocation(), CLI, AllocaIP, NeedsBarrier,
4026 SchedKind, ChunkSize,
false,
4037 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
4042 if (!UseOMPIRBuilder) {
4056 bool HasLastprivates =
false;
4064 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4077 llvm::Value *
Init =
nullptr) {
4085 const Stmt *
CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4087 bool HasLastprivates =
false;
4093 C.getIntTypeForBitwidth(32, 1);
4096 CGF.Builder.getInt32(0));
4097 llvm::ConstantInt *GlobalUBVal = CS !=
nullptr
4098 ? CGF.Builder.getInt32(CS->size() - 1)
4099 : CGF.Builder.getInt32(0);
4103 CGF.Builder.getInt32(1));
4105 CGF.Builder.getInt32(0));
4109 CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
4111 CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
4132 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".omp.sections.exit");
4134 CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.getBeginLoc()),
4135 ExitBB, CS ==
nullptr ? 1 : CS->size());
4137 unsigned CaseNumber = 0;
4139 auto CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4140 CGF.EmitBlock(CaseBB);
4141 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
4142 CGF.EmitStmt(SubStmt);
4143 CGF.EmitBranch(ExitBB);
4147 llvm::BasicBlock *CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4148 CGF.EmitBlock(CaseBB);
4149 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
4151 CGF.EmitBranch(ExitBB);
4153 CGF.EmitBlock(ExitBB,
true);
4156 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
4157 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
4161 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
4162 CGF, S.getBeginLoc(), OMPD_unknown,
false,
4165 CGF.EmitOMPPrivateClause(S, LoopScope);
4167 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
4168 CGF.EmitOMPReductionClauseInit(S, LoopScope);
4169 (void)LoopScope.Privatize();
4171 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
4175 ScheduleKind.
Schedule = OMPC_SCHEDULE_static;
4179 CGF.CGM.getOpenMPRuntime().emitForStaticInit(CGF, S.getBeginLoc(), EKind,
4180 ScheduleKind, StaticInit);
4182 llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.getBeginLoc());
4183 llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
4184 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
4185 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
4187 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.getBeginLoc()), IV);
4189 CGF.EmitOMPInnerLoop(S,
false, Cond, Inc, BodyGen,
4193 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
4196 CGF.OMPCancelStack.emitExit(CGF, EKind, CodeGen);
4197 CGF.EmitOMPReductionClauseFinal(S, OMPD_parallel);
4200 return CGF.
Builder.CreateIsNotNull(
4205 if (HasLastprivates)
4212 bool HasCancel =
false;
4213 if (
auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
4214 HasCancel = OSD->hasCancel();
4215 else if (
auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
4216 HasCancel = OPSD->hasCancel();
4217 OMPCancelStackRAII CancelRegion(*
this, EKind, HasCancel);
4236 OMPPrivateScope PrivateScope(CGF);
4240 (void)PrivateScope.Privatize();
4241 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4246 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4260 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4261 using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
4263 auto FiniCB = [
this](InsertPointTy IP) {
4265 return llvm::Error::success();
4268 const CapturedStmt *ICS = S.getInnermostCapturedStmt();
4269 const Stmt *
CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4274 auto SectionCB = [
this, SubStmt](InsertPointTy AllocaIP,
4275 InsertPointTy CodeGenIP) {
4277 *
this, SubStmt, AllocaIP, CodeGenIP,
"section");
4278 return llvm::Error::success();
4280 SectionCBVector.push_back(SectionCB);
4283 auto SectionCB = [
this,
CapturedStmt](InsertPointTy AllocaIP,
4284 InsertPointTy CodeGenIP) {
4287 return llvm::Error::success();
4289 SectionCBVector.push_back(SectionCB);
4296 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
4297 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
4305 CGCapturedStmtInfo CGSI(*ICS,
CR_OpenMP);
4306 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(*
this, &CGSI);
4307 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4309 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4310 cantFail(OMPBuilder.createSections(
4311 Builder, AllocaIP, SectionCBVector, PrivCB, FiniCB, S.hasCancel(),
4319 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4334 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4336 const Stmt *SectionRegionBodyStmt = S.getAssociatedStmt();
4337 auto FiniCB = [
this](InsertPointTy IP) {
4339 return llvm::Error::success();
4342 auto BodyGenCB = [SectionRegionBodyStmt,
this](InsertPointTy AllocaIP,
4343 InsertPointTy CodeGenIP) {
4345 *
this, SectionRegionBodyStmt, AllocaIP, CodeGenIP,
"section");
4346 return llvm::Error::success();
4349 LexicalScope
Scope(*
this, S.getSourceRange());
4351 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4352 cantFail(OMPBuilder.createSection(
Builder, BodyGenCB, FiniCB));
4357 LexicalScope
Scope(*
this, S.getSourceRange());
4372 CopyprivateVars.append(
C->varlist_begin(),
C->varlist_end());
4373 DestExprs.append(
C->destination_exprs().begin(),
4374 C->destination_exprs().end());
4375 SrcExprs.append(
C->source_exprs().begin(),
C->source_exprs().end());
4376 AssignmentOps.append(
C->assignment_ops().begin(),
4377 C->assignment_ops().end());
4386 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4391 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4393 CopyprivateVars, DestExprs,
4394 SrcExprs, AssignmentOps);
4398 if (!S.getSingleClause<
OMPNowaitClause>() && CopyprivateVars.empty()) {
4400 *
this, S.getBeginLoc(),
4418 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4420 const Stmt *MasterRegionBodyStmt = S.getAssociatedStmt();
4422 auto FiniCB = [
this](InsertPointTy IP) {
4424 return llvm::Error::success();
4427 auto BodyGenCB = [MasterRegionBodyStmt,
this](InsertPointTy AllocaIP,
4428 InsertPointTy CodeGenIP) {
4430 *
this, MasterRegionBodyStmt, AllocaIP, CodeGenIP,
"master");
4431 return llvm::Error::success();
4434 LexicalScope
Scope(*
this, S.getSourceRange());
4436 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4437 cantFail(OMPBuilder.createMaster(
Builder, BodyGenCB, FiniCB));
4442 LexicalScope
Scope(*
this, S.getSourceRange());
4452 Expr *Filter =
nullptr;
4454 Filter = FilterClause->getThreadID();
4462 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4464 const Stmt *MaskedRegionBodyStmt = S.getAssociatedStmt();
4467 Filter = FilterClause->getThreadID();
4468 llvm::Value *FilterVal =
Filter
4472 auto FiniCB = [
this](InsertPointTy IP) {
4474 return llvm::Error::success();
4477 auto BodyGenCB = [MaskedRegionBodyStmt,
this](InsertPointTy AllocaIP,
4478 InsertPointTy CodeGenIP) {
4480 *
this, MaskedRegionBodyStmt, AllocaIP, CodeGenIP,
"masked");
4481 return llvm::Error::success();
4484 LexicalScope
Scope(*
this, S.getSourceRange());
4486 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
4487 OMPBuilder.createMasked(
Builder, BodyGenCB, FiniCB, FilterVal));
4492 LexicalScope
Scope(*
this, S.getSourceRange());
4500 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4502 const Stmt *CriticalRegionBodyStmt = S.getAssociatedStmt();
4503 const Expr *Hint =
nullptr;
4504 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4505 Hint = HintClause->getHint();
4510 llvm::Value *HintInst =
nullptr;
4515 auto FiniCB = [
this](InsertPointTy IP) {
4517 return llvm::Error::success();
4520 auto BodyGenCB = [CriticalRegionBodyStmt,
this](InsertPointTy AllocaIP,
4521 InsertPointTy CodeGenIP) {
4523 *
this, CriticalRegionBodyStmt, AllocaIP, CodeGenIP,
"critical");
4524 return llvm::Error::success();
4527 LexicalScope
Scope(*
this, S.getSourceRange());
4529 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4530 cantFail(OMPBuilder.createCritical(
Builder, BodyGenCB, FiniCB,
4531 S.getDirectiveName().getAsString(),
4540 CGF.
EmitStmt(S.getAssociatedStmt());
4542 const Expr *Hint =
nullptr;
4543 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4544 Hint = HintClause->getHint();
4545 LexicalScope
Scope(*
this, S.getSourceRange());
4548 S.getDirectiveName().getAsString(),
4549 CodeGen, S.getBeginLoc(), Hint);
4563 CodeGenFunction::OMPLocalDeclMapRAII
Scope(CGF);
4565 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGSI);
4566 OMPLoopScope LoopScope(CGF, S);
4571 return C->getModifier() == OMPC_REDUCTION_inscan;
4597 CodeGenFunction::OMPLocalDeclMapRAII
Scope(CGF);
4599 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGSI);
4600 OMPLoopScope LoopScope(CGF, S);
4605 return C->getModifier() == OMPC_REDUCTION_inscan;
4626 OMPPrivateScope PrivateScope(CGF);
4631 (void)PrivateScope.Privatize();
4653 OMPPrivateScope PrivateScope(CGF);
4658 (void)PrivateScope.Privatize();
4681 CGF.EmitSections(S);
4695class CheckVarsEscapingUntiedTaskDeclContext final
4700 explicit CheckVarsEscapingUntiedTaskDeclContext() =
default;
4701 virtual ~CheckVarsEscapingUntiedTaskDeclContext() =
default;
4702 void VisitDeclStmt(
const DeclStmt *S) {
4706 for (
const Decl *
D : S->decls()) {
4707 if (
const auto *VD = dyn_cast_or_null<VarDecl>(
D))
4709 PrivateDecls.push_back(VD);
4715 void VisitBlockExpr(
const BlockExpr *) {}
4716 void VisitStmt(
const Stmt *S) {
4719 for (
const Stmt *Child : S->children())
4733 bool OmpAllMemory =
false;
4736 return C->getDependencyKind() == OMPC_DEPEND_outallmemory ||
4737 C->getDependencyKind() == OMPC_DEPEND_inoutallmemory;
4739 OmpAllMemory =
true;
4744 Data.Dependences.emplace_back(OMPC_DEPEND_outallmemory,
4753 if (Kind == OMPC_DEPEND_outallmemory || Kind == OMPC_DEPEND_inoutallmemory)
4755 if (OmpAllMemory && (Kind == OMPC_DEPEND_out || Kind == OMPC_DEPEND_inout))
4758 Data.Dependences.emplace_back(
C->getDependencyKind(),
C->getModifier());
4759 DD.
DepExprs.append(
C->varlist_begin(),
C->varlist_end());
4768 const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion);
4770 auto PartId = std::next(I);
4771 auto TaskT = std::next(I, 4);
4776 const Expr *Cond = Clause->getCondition();
4779 Data.Final.setInt(CondConstant);
4784 Data.Final.setInt(
false);
4788 const Expr *Prio = Clause->getPriority();
4789 Data.Priority.setInt(
true);
4797 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
4800 auto IRef =
C->varlist_begin();
4801 for (
const Expr *IInit :
C->private_copies()) {
4802 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
4803 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
4804 Data.PrivateVars.push_back(*IRef);
4805 Data.PrivateCopies.push_back(IInit);
4810 EmittedAsPrivate.clear();
4813 auto IRef =
C->varlist_begin();
4814 auto IElemInitRef =
C->inits().begin();
4815 for (
const Expr *IInit :
C->private_copies()) {
4816 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
4817 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
4818 Data.FirstprivateVars.push_back(*IRef);
4819 Data.FirstprivateCopies.push_back(IInit);
4820 Data.FirstprivateInits.push_back(*IElemInitRef);
4827 llvm::MapVector<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
4829 auto IRef =
C->varlist_begin();
4830 auto ID =
C->destination_exprs().begin();
4831 for (
const Expr *IInit :
C->private_copies()) {
4832 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
4833 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
4834 Data.LastprivateVars.push_back(*IRef);
4835 Data.LastprivateCopies.push_back(IInit);
4837 LastprivateDstsOrigs.insert(
4838 std::make_pair(cast<VarDecl>(cast<DeclRefExpr>(*ID)->getDecl()),
4839 cast<DeclRefExpr>(*IRef)));
4847 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
4848 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
4849 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
4850 Data.ReductionOps.append(
C->reduction_ops().begin(),
4851 C->reduction_ops().end());
4852 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
4853 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
4856 *
this, S.getBeginLoc(), LHSs, RHSs,
Data);
4861 CheckVarsEscapingUntiedTaskDeclContext Checker;
4862 Checker.Visit(S.getInnermostCapturedStmt()->getCapturedStmt());
4863 Data.PrivateLocals.append(Checker.getPrivateDecls().begin(),
4864 Checker.getPrivateDecls().end());
4866 auto &&CodeGen = [&
Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
4869 llvm::MapVector<CanonicalDeclPtr<const VarDecl>,
4870 std::pair<Address, Address>>
4873 OMPPrivateScope
Scope(CGF);
4875 if (
auto *DI = CGF.getDebugInfo()) {
4876 llvm::SmallDenseMap<const VarDecl *, FieldDecl *> CaptureFields =
4877 CGF.CapturedStmtInfo->getCaptureFields();
4878 llvm::Value *ContextValue = CGF.CapturedStmtInfo->getContextValue();
4879 if (CaptureFields.size() && ContextValue) {
4880 unsigned CharWidth = CGF.getContext().getCharWidth();
4894 for (
auto It = CaptureFields.begin(); It != CaptureFields.end(); ++It) {
4895 const VarDecl *SharedVar = It->first;
4898 CGF.getContext().getASTRecordLayout(CaptureRecord);
4901 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
4902 (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue,
4903 CGF.Builder,
false);
4906 auto UpdateExpr = [](llvm::LLVMContext &Ctx,
auto *
Declare,
4911 Ops.push_back(llvm::dwarf::DW_OP_plus_uconst);
4912 Ops.push_back(Offset);
4914 Ops.push_back(llvm::dwarf::DW_OP_deref);
4915 Declare->setExpression(llvm::DIExpression::get(Ctx, Ops));
4917 llvm::Instruction &
Last = CGF.Builder.GetInsertBlock()->back();
4918 if (
auto DDI = dyn_cast<llvm::DbgVariableIntrinsic>(&
Last))
4919 UpdateExpr(DDI->getContext(), DDI, Offset);
4922 assert(!
Last.isTerminator() &&
"unexpected terminator");
4924 CGF.Builder.GetInsertBlock()->getTrailingDbgRecords()) {
4925 for (llvm::DbgVariableRecord &DVR : llvm::reverse(
4926 llvm::filterDbgVars(Marker->getDbgRecordRange()))) {
4927 UpdateExpr(
Last.getContext(), &DVR, Offset);
4935 if (!
Data.PrivateVars.empty() || !
Data.FirstprivateVars.empty() ||
4936 !
Data.LastprivateVars.empty() || !
Data.PrivateLocals.empty()) {
4937 enum { PrivatesParam = 2, CopyFnParam = 3 };
4938 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
4939 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(CopyFnParam)));
4940 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
4941 CS->getCapturedDecl()->getParam(PrivatesParam)));
4946 CallArgs.push_back(PrivatesPtr);
4947 ParamTypes.push_back(PrivatesPtr->getType());
4948 for (
const Expr *
E :
Data.PrivateVars) {
4949 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
4951 CGF.getContext().getPointerType(
E->
getType()),
".priv.ptr.addr");
4952 PrivatePtrs.emplace_back(VD, PrivatePtr);
4954 ParamTypes.push_back(PrivatePtr.
getType());
4956 for (
const Expr *
E :
Data.FirstprivateVars) {
4957 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
4959 CGF.CreateMemTemp(CGF.getContext().getPointerType(
E->
getType()),
4960 ".firstpriv.ptr.addr");
4961 PrivatePtrs.emplace_back(VD, PrivatePtr);
4962 FirstprivatePtrs.emplace_back(VD, PrivatePtr);
4964 ParamTypes.push_back(PrivatePtr.
getType());
4966 for (
const Expr *
E :
Data.LastprivateVars) {
4967 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
4969 CGF.CreateMemTemp(CGF.getContext().getPointerType(
E->
getType()),
4970 ".lastpriv.ptr.addr");
4971 PrivatePtrs.emplace_back(VD, PrivatePtr);
4973 ParamTypes.push_back(PrivatePtr.
getType());
4978 Ty = CGF.getContext().getPointerType(Ty);
4980 Ty = CGF.getContext().getPointerType(Ty);
4982 CGF.getContext().getPointerType(Ty),
".local.ptr.addr");
4983 auto Result = UntiedLocalVars.insert(
4986 if (
Result.second ==
false)
4987 *
Result.first = std::make_pair(
4990 ParamTypes.push_back(PrivatePtr.
getType());
4992 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
4994 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
4995 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
4996 for (
const auto &Pair : LastprivateDstsOrigs) {
4997 const auto *OrigVD = cast<VarDecl>(Pair.second->getDecl());
5000 CGF.CapturedStmtInfo->lookup(OrigVD) !=
nullptr,
5002 Pair.second->getExprLoc());
5003 Scope.addPrivate(Pair.first, CGF.EmitLValue(&DRE).getAddress());
5005 for (
const auto &Pair : PrivatePtrs) {
5007 CGF.Builder.CreateLoad(Pair.second),
5008 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5009 CGF.getContext().getDeclAlign(Pair.first));
5010 Scope.addPrivate(Pair.first, Replacement);
5011 if (
auto *DI = CGF.getDebugInfo())
5012 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5013 (void)DI->EmitDeclareOfAutoVariable(
5014 Pair.first, Pair.second.getBasePointer(), CGF.Builder,
5019 for (
auto &Pair : UntiedLocalVars) {
5020 QualType VDType = Pair.first->getType().getNonReferenceType();
5021 if (Pair.first->getType()->isLValueReferenceType())
5022 VDType = CGF.getContext().getPointerType(VDType);
5024 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5027 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(VDType)),
5028 CGF.getPointerAlign());
5029 Pair.second.first = Replacement;
5030 Ptr = CGF.Builder.CreateLoad(Replacement);
5031 Replacement =
Address(Ptr, CGF.ConvertTypeForMem(VDType),
5032 CGF.getContext().getDeclAlign(Pair.first));
5033 Pair.second.second = Replacement;
5035 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5036 Address Replacement(Ptr, CGF.ConvertTypeForMem(VDType),
5037 CGF.getContext().getDeclAlign(Pair.first));
5038 Pair.second.first = Replacement;
5042 if (
Data.Reductions) {
5043 OMPPrivateScope FirstprivateScope(CGF);
5044 for (
const auto &Pair : FirstprivatePtrs) {
5046 CGF.Builder.CreateLoad(Pair.second),
5047 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5048 CGF.getContext().getDeclAlign(Pair.first));
5049 FirstprivateScope.addPrivate(Pair.first, Replacement);
5051 (void)FirstprivateScope.Privatize();
5052 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5054 Data.ReductionCopies,
Data.ReductionOps);
5055 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
5056 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(9)));
5057 for (
unsigned Cnt = 0,
E =
Data.ReductionVars.size(); Cnt <
E; ++Cnt) {
5058 RedCG.emitSharedOrigLValue(CGF, Cnt);
5059 RedCG.emitAggregateType(CGF, Cnt);
5063 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5065 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5066 CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
5068 CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF),
5069 CGF.getContext().VoidPtrTy,
5070 CGF.getContext().getPointerType(
5071 Data.ReductionCopies[Cnt]->getType()),
5072 Data.ReductionCopies[Cnt]->getExprLoc()),
5073 CGF.ConvertTypeForMem(
Data.ReductionCopies[Cnt]->getType()),
5074 Replacement.getAlignment());
5075 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
5076 Scope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement);
5080 (void)
Scope.Privatize();
5086 auto IPriv =
C->privates().begin();
5087 auto IRed =
C->reduction_ops().begin();
5088 auto ITD =
C->taskgroup_descriptors().begin();
5089 for (
const Expr *Ref :
C->varlist()) {
5090 InRedVars.emplace_back(Ref);
5091 InRedPrivs.emplace_back(*IPriv);
5092 InRedOps.emplace_back(*IRed);
5093 TaskgroupDescriptors.emplace_back(*ITD);
5094 std::advance(IPriv, 1);
5095 std::advance(IRed, 1);
5096 std::advance(ITD, 1);
5101 OMPPrivateScope InRedScope(CGF);
5102 if (!InRedVars.empty()) {
5104 for (
unsigned Cnt = 0,
E = InRedVars.size(); Cnt <
E; ++Cnt) {
5105 RedCG.emitSharedOrigLValue(CGF, Cnt);
5106 RedCG.emitAggregateType(CGF, Cnt);
5112 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5114 llvm::Value *ReductionsPtr;
5115 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5116 ReductionsPtr = CGF.EmitLoadOfScalar(CGF.EmitLValue(TRExpr),
5117 TRExpr->getExprLoc());
5119 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5121 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5122 CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
5124 CGF.EmitScalarConversion(
5125 Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy,
5126 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
5127 InRedPrivs[Cnt]->getExprLoc()),
5128 CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()),
5129 Replacement.getAlignment());
5130 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
5131 InRedScope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement);
5134 (void)InRedScope.Privatize();
5143 S, *I, *PartId, *TaskT, EKind, CodeGen,
Data.Tied,
Data.NumberOfParts);
5144 OMPLexicalScope
Scope(*
this, S, std::nullopt,
5147 TaskGen(*
this, OutlinedFn,
Data);
5164 QualType ElemType =
C.getBaseElementType(Ty);
5174 Data.FirstprivateVars.emplace_back(OrigRef);
5175 Data.FirstprivateCopies.emplace_back(PrivateRef);
5176 Data.FirstprivateInits.emplace_back(InitRef);
5182 OMPTargetDataInfo &InputInfo) {
5188 auto PartId = std::next(I);
5189 auto TaskT = std::next(I, 4);
5192 Data.Final.setInt(
false);
5195 auto IRef =
C->varlist_begin();
5196 auto IElemInitRef =
C->inits().begin();
5197 for (
auto *IInit :
C->private_copies()) {
5198 Data.FirstprivateVars.push_back(*IRef);
5199 Data.FirstprivateCopies.push_back(IInit);
5200 Data.FirstprivateInits.push_back(*IElemInitRef);
5208 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5209 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5210 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5211 Data.ReductionOps.append(
C->reduction_ops().begin(),
5212 C->reduction_ops().end());
5213 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5214 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5216 OMPPrivateScope TargetScope(*
this);
5221 if (InputInfo.NumberOfTargetItems > 0) {
5224 llvm::APInt ArrSize(32, InputInfo.NumberOfTargetItems);
5229 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5231 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5238 TargetScope.addPrivate(BPVD, InputInfo.BasePointersArray);
5239 TargetScope.addPrivate(PVD, InputInfo.PointersArray);
5240 TargetScope.addPrivate(SVD, InputInfo.SizesArray);
5243 if (!isa_and_nonnull<llvm::ConstantPointerNull>(
5244 InputInfo.MappersArray.emitRawPointer(*
this))) {
5246 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5247 TargetScope.addPrivate(MVD, InputInfo.MappersArray);
5250 (void)TargetScope.Privatize();
5253 auto &&CodeGen = [&
Data, &S, CS, &BodyGen, BPVD, PVD, SVD, MVD, EKind,
5256 OMPPrivateScope
Scope(CGF);
5257 if (!
Data.FirstprivateVars.empty()) {
5258 enum { PrivatesParam = 2, CopyFnParam = 3 };
5259 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5260 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(CopyFnParam)));
5261 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5262 CS->getCapturedDecl()->getParam(PrivatesParam)));
5267 CallArgs.push_back(PrivatesPtr);
5268 ParamTypes.push_back(PrivatesPtr->getType());
5269 for (
const Expr *
E :
Data.FirstprivateVars) {
5270 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
5272 CGF.CreateMemTemp(CGF.getContext().getPointerType(
E->
getType()),
5273 ".firstpriv.ptr.addr");
5274 PrivatePtrs.emplace_back(VD, PrivatePtr);
5276 ParamTypes.push_back(PrivatePtr.
getType());
5278 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5280 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5281 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5282 for (
const auto &Pair : PrivatePtrs) {
5284 CGF.Builder.CreateLoad(Pair.second),
5285 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5286 CGF.getContext().getDeclAlign(Pair.first));
5287 Scope.addPrivate(Pair.first, Replacement);
5290 CGF.processInReduction(S,
Data, CGF, CS,
Scope);
5291 if (InputInfo.NumberOfTargetItems > 0) {
5292 InputInfo.BasePointersArray = CGF.Builder.CreateConstArrayGEP(
5293 CGF.GetAddrOfLocalVar(BPVD), 0);
5294 InputInfo.PointersArray = CGF.Builder.CreateConstArrayGEP(
5295 CGF.GetAddrOfLocalVar(PVD), 0);
5296 InputInfo.SizesArray = CGF.Builder.CreateConstArrayGEP(
5297 CGF.GetAddrOfLocalVar(SVD), 0);
5300 InputInfo.MappersArray = CGF.Builder.CreateConstArrayGEP(
5301 CGF.GetAddrOfLocalVar(MVD), 0);
5305 OMPLexicalScope LexScope(CGF, S, OMPD_task,
false);
5307 if (CGF.CGM.getLangOpts().OpenMP >= 51 &&
5312 CGF.CGM.getOpenMPRuntime().emitThreadLimitClause(
5313 CGF, TL->getThreadLimit().front(), S.getBeginLoc());
5318 S, *I, *PartId, *TaskT, EKind, CodeGen,
true,
5319 Data.NumberOfParts);
5320 llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<
OMPNowaitClause>() ? 1 : 0);
5325 SharedsTy, CapturedStruct, &IfCond,
Data);
5332 OMPPrivateScope &
Scope) {
5334 if (
Data.Reductions) {
5336 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5338 Data.ReductionCopies,
Data.ReductionOps);
5341 for (
unsigned Cnt = 0,
E =
Data.ReductionVars.size(); Cnt <
E; ++Cnt) {
5342 RedCG.emitSharedOrigLValue(CGF, Cnt);
5343 RedCG.emitAggregateType(CGF, Cnt);
5350 CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
5355 Data.ReductionCopies[Cnt]->getType()),
5356 Data.ReductionCopies[Cnt]->getExprLoc()),
5358 Replacement.getAlignment());
5359 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
5360 Scope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement);
5363 (void)
Scope.Privatize();
5369 auto IPriv =
C->privates().begin();
5370 auto IRed =
C->reduction_ops().begin();
5371 auto ITD =
C->taskgroup_descriptors().begin();
5372 for (
const Expr *Ref :
C->varlist()) {
5373 InRedVars.emplace_back(Ref);
5374 InRedPrivs.emplace_back(*IPriv);
5375 InRedOps.emplace_back(*IRed);
5376 TaskgroupDescriptors.emplace_back(*ITD);
5377 std::advance(IPriv, 1);
5378 std::advance(IRed, 1);
5379 std::advance(ITD, 1);
5382 OMPPrivateScope InRedScope(CGF);
5383 if (!InRedVars.empty()) {
5385 for (
unsigned Cnt = 0,
E = InRedVars.size(); Cnt <
E; ++Cnt) {
5386 RedCG.emitSharedOrigLValue(CGF, Cnt);
5387 RedCG.emitAggregateType(CGF, Cnt);
5393 llvm::Value *ReductionsPtr;
5394 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5398 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
5401 CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
5406 InRedPrivs[Cnt]->getExprLoc()),
5408 Replacement.getAlignment());
5409 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
5410 InRedScope.addPrivate(RedCG.getBaseDecl(Cnt), Replacement);
5413 (void)InRedScope.Privatize();
5421 const Expr *IfCond =
nullptr;
5422 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
5423 if (
C->getNameModifier() == OMPD_unknown ||
5424 C->getNameModifier() == OMPD_task) {
5425 IfCond =
C->getCondition();
5436 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
5439 CGF.CGM.getOpenMPRuntime().emitTaskCall(CGF, S.getBeginLoc(), S, OutlinedFn,
5440 SharedsTy, CapturedStruct, IfCond,
5457 bool IsFatal =
false;
5476 return T.clauses().empty();
5481 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
5484 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5488 auto BodyGenCB = [&,
this](InsertPointTy AllocaIP,
5489 InsertPointTy CodeGenIP) {
5491 EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5492 return llvm::Error::success();
5494 CodeGenFunction::CGCapturedStmtInfo CapStmtInfo;
5497 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5498 cantFail(OMPBuilder.createTaskgroup(
Builder, AllocaIP, BodyGenCB));
5504 if (
const Expr *
E = S.getReductionRef()) {
5509 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5510 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5511 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5512 Data.ReductionOps.append(
C->reduction_ops().begin(),
5513 C->reduction_ops().end());
5514 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5515 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5517 llvm::Value *ReductionDesc =
5520 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
5525 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5532 ? llvm::AtomicOrdering::NotAtomic
5533 : llvm::AtomicOrdering::AcquireRelease;
5537 if (
const auto *FlushClause = S.getSingleClause<
OMPFlushClause>())
5539 FlushClause->varlist_end());
5542 S.getBeginLoc(), AO);
5552 for (
auto &Dep :
Data.Dependences) {
5554 *
this, Dep, DC->getBeginLoc());
5565 *
this, DOLVal, UC->getDependencyKind(), UC->getBeginLoc());
5584 if (
C->getModifier() != OMPC_REDUCTION_inscan)
5586 Shareds.append(
C->varlist_begin(),
C->varlist_end());
5587 Privates.append(
C->privates().begin(),
C->privates().end());
5588 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5589 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5590 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
5591 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
5592 CopyArrayTemps.append(
C->copy_array_temps().begin(),
5593 C->copy_array_temps().end());
5594 CopyArrayElems.append(
C->copy_array_elems().begin(),
5595 C->copy_array_elems().end());
5639 : BreakContinueStack.back().ContinueBlock.getBlock());
5644 LexicalScope
Scope(*
this, S.getSourceRange());
5650 for (
unsigned I = 0,
E = CopyArrayElems.size(); I <
E; ++I) {
5651 const Expr *PrivateExpr = Privates[I];
5652 const Expr *TempExpr = CopyArrayTemps[I];
5654 *cast<VarDecl>(cast<DeclRefExpr>(TempExpr)->getDecl()));
5659 cast<VarDecl>(cast<DeclRefExpr>(LHSs[I])->getDecl()),
5660 cast<VarDecl>(cast<DeclRefExpr>(RHSs[I])->getDecl()),
5665 *
this, ParentDir.
getEndLoc(), Privates, LHSs, RHSs, ReductionOps,
5666 {true, true, OMPD_simd});
5667 for (
unsigned I = 0,
E = CopyArrayElems.size(); I <
E; ++I) {
5668 const Expr *PrivateExpr = Privates[I];
5675 const Expr *TempExpr = CopyArrayTemps[I];
5681 cast<VarDecl>(cast<DeclRefExpr>(LHSs[I])->getDecl()),
5682 cast<VarDecl>(cast<DeclRefExpr>(RHSs[I])->getDecl()), CopyOps[I]);
5687 ? BreakContinueStack.back().ContinueBlock.getBlock()
5693 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
5698 const auto *IVExpr = cast<OMPLoopDirective>(ParentDir)
5699 .getIterationVariable()
5704 for (
unsigned I = 0,
E = CopyArrayElems.size(); I <
E; ++I) {
5705 const Expr *PrivateExpr = Privates[I];
5706 const Expr *OrigExpr = Shareds[I];
5707 const Expr *CopyArrayElem = CopyArrayElems[I];
5708 OpaqueValueMapping IdxMapping(
5710 cast<OpaqueValueExpr>(
5711 cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()),
5717 cast<VarDecl>(cast<DeclRefExpr>(LHSs[I])->getDecl()),
5718 cast<VarDecl>(cast<DeclRefExpr>(RHSs[I])->getDecl()), CopyOps[I]);
5721 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
5724 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
5729 const auto *IVExpr = cast<OMPLoopDirective>(ParentDir)
5730 .getIterationVariable()
5735 llvm::BasicBlock *ExclusiveExitBB =
nullptr;
5740 Builder.CreateCondBr(Cmp, ExclusiveExitBB, ContBB);
5743 IdxVal =
Builder.CreateNUWSub(IdxVal, llvm::ConstantInt::get(
SizeTy, 1));
5745 for (
unsigned I = 0,
E = CopyArrayElems.size(); I <
E; ++I) {
5746 const Expr *PrivateExpr = Privates[I];
5747 const Expr *OrigExpr = Shareds[I];
5748 const Expr *CopyArrayElem = CopyArrayElems[I];
5749 OpaqueValueMapping IdxMapping(
5751 cast<OpaqueValueExpr>(
5752 cast<ArraySubscriptExpr>(CopyArrayElem)->getIdx()),
5758 cast<VarDecl>(cast<DeclRefExpr>(LHSs[I])->getDecl()),
5759 cast<VarDecl>(cast<DeclRefExpr>(RHSs[I])->getDecl()), CopyOps[I]);
5774 const auto *IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
5775 const auto *IVDecl = cast<VarDecl>(IVExpr->getDecl());
5781 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
5789 bool HasLastprivateClause =
false;
5792 OMPLoopScope PreInitScope(*
this, S);
5797 llvm::BasicBlock *ContBlock =
nullptr;
5804 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
5816 *
this, cast<DeclRefExpr>(
5818 ? S.getCombinedLowerBoundVariable()
5819 : S.getLowerBoundVariable())));
5821 *
this, cast<DeclRefExpr>(
5823 ? S.getCombinedUpperBoundVariable()
5824 : S.getUpperBoundVariable())));
5830 OMPPrivateScope LoopScope(*
this);
5836 *
this, S.getBeginLoc(), OMPD_unknown,
false,
5846 (void)LoopScope.Privatize();
5851 llvm::Value *Chunk =
nullptr;
5854 ScheduleKind =
C->getDistScheduleKind();
5855 if (
const Expr *Ch =
C->getChunkSize()) {
5858 S.getIterationVariable()->getType(),
5864 *
this, S, ScheduleKind, Chunk);
5877 bool StaticChunked =
5881 Chunk !=
nullptr) ||
5886 StaticChunked ? Chunk :
nullptr);
5893 ? S.getCombinedEnsureUpperBound()
5894 : S.getEnsureUpperBound());
5897 ? S.getCombinedInit()
5902 ? S.getCombinedCond()
5906 Cond = S.getCombinedDistCond();
5938 [&S, &LoopScope, Cond, IncExpr,
LoopExit, &CodeGenLoop,
5940 CGF.EmitOMPInnerLoop(
5941 S, LoopScope.requiresCleanups(), Cond, IncExpr,
5943 CodeGenLoop(CGF, S, LoopExit);
5946 if (StaticChunked) {
5947 CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound());
5948 CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound());
5949 CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound());
5950 CGF.EmitIgnoredExpr(S.getCombinedInit());
5960 const OMPLoopArguments LoopArguments = {
5963 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments,
5968 return CGF.
Builder.CreateIsNotNull(
5979 return CGF.
Builder.CreateIsNotNull(
5984 if (HasLastprivateClause) {
6007 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
6020 CodeGenFunction::CGCapturedStmtInfo CapStmtInfo;
6023 Fn->setDoesNotRecurse();
6027template <
typename T>
6029 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP,
6030 llvm::OpenMPIRBuilder &OMPBuilder) {
6032 unsigned NumLoops =
C->getNumLoops();
6036 for (
unsigned I = 0; I < NumLoops; I++) {
6037 const Expr *CounterVal =
C->getLoopData(I);
6042 StoreValues.emplace_back(StoreValue);
6044 OMPDoacrossKind<T> ODK;
6045 bool IsDependSource = ODK.isSource(
C);
6047 OMPBuilder.createOrderedDepend(CGF.
Builder, AllocaIP, NumLoops,
6048 StoreValues,
".cnt.addr", IsDependSource));
6054 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6059 assert(!S.hasAssociatedStmt() &&
"No associated statement must be in "
6060 "ordered depend|doacross construct.");
6072 auto FiniCB = [
this](InsertPointTy IP) {
6074 return llvm::Error::success();
6077 auto BodyGenCB = [&S,
C,
this](InsertPointTy AllocaIP,
6078 InsertPointTy CodeGenIP) {
6083 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
6084 Builder,
false,
".ordered.after");
6087 llvm::Function *OutlinedFn =
6089 assert(S.getBeginLoc().isValid() &&
6090 "Outlined function call location must be valid.");
6093 OutlinedFn, CapturedVars);
6098 return llvm::Error::success();
6101 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6102 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
6103 OMPBuilder.createOrderedThreadsSimd(
Builder, BodyGenCB, FiniCB, !
C));
6110 assert(!S.hasAssociatedStmt() &&
6111 "No associated statement must be in ordered depend construct.");
6117 assert(!S.hasAssociatedStmt() &&
6118 "No associated statement must be in ordered doacross construct.");
6129 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
6130 llvm::Function *OutlinedFn =
6133 OutlinedFn, CapturedVars);
6139 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6147 "DestType must have scalar evaluation kind.");
6148 assert(!Val.
isAggregate() &&
"Must be a scalar or complex.");
6159 "DestType must have complex evaluation kind.");
6168 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
6170 assert(Val.
isComplex() &&
"Must be a scalar or complex.");
6191 llvm::AtomicOrdering AO,
LValue LVal,
6196 LVal,
Loc, llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO),
6214 llvm_unreachable(
"Must be a scalar or complex.");
6222 assert(
V->isLValue() &&
"V of 'omp atomic read' is not lvalue");
6223 assert(
X->isLValue() &&
"X of 'omp atomic read' is not lvalue");
6232 case llvm::AtomicOrdering::Acquire:
6233 case llvm::AtomicOrdering::AcquireRelease:
6234 case llvm::AtomicOrdering::SequentiallyConsistent:
6236 llvm::AtomicOrdering::Acquire);
6238 case llvm::AtomicOrdering::Monotonic:
6239 case llvm::AtomicOrdering::Release:
6241 case llvm::AtomicOrdering::NotAtomic:
6242 case llvm::AtomicOrdering::Unordered:
6243 llvm_unreachable(
"Unexpected ordering.");
6250 llvm::AtomicOrdering AO,
const Expr *
X,
6253 assert(
X->isLValue() &&
"X of 'omp atomic write' is not lvalue");
6261 case llvm::AtomicOrdering::Release:
6262 case llvm::AtomicOrdering::AcquireRelease:
6263 case llvm::AtomicOrdering::SequentiallyConsistent:
6265 llvm::AtomicOrdering::Release);
6267 case llvm::AtomicOrdering::Acquire:
6268 case llvm::AtomicOrdering::Monotonic:
6270 case llvm::AtomicOrdering::NotAtomic:
6271 case llvm::AtomicOrdering::Unordered:
6272 llvm_unreachable(
"Unexpected ordering.");
6279 llvm::AtomicOrdering AO,
6280 bool IsXLHSInRHSPart) {
6285 if (BO == BO_Comma || !
Update.isScalar() || !
X.isSimple() ||
6286 (!isa<llvm::ConstantInt>(
Update.getScalarVal()) &&
6287 (
Update.getScalarVal()->getType() !=
X.getAddress().getElementType())) ||
6290 return std::make_pair(
false,
RValue::get(
nullptr));
6293 if (
T->isIntegerTy())
6296 if (
T->isFloatingPointTy() && (BO == BO_Add || BO == BO_Sub))
6302 if (!CheckAtomicSupport(
Update.getScalarVal()->getType(), BO) ||
6303 !CheckAtomicSupport(
X.getAddress().getElementType(), BO))
6304 return std::make_pair(
false,
RValue::get(
nullptr));
6306 bool IsInteger =
X.getAddress().getElementType()->isIntegerTy();
6307 llvm::AtomicRMWInst::BinOp RMWOp;
6310 RMWOp = IsInteger ? llvm::AtomicRMWInst::Add : llvm::AtomicRMWInst::FAdd;
6313 if (!IsXLHSInRHSPart)
6314 return std::make_pair(
false,
RValue::get(
nullptr));
6315 RMWOp = IsInteger ? llvm::AtomicRMWInst::Sub : llvm::AtomicRMWInst::FSub;
6318 RMWOp = llvm::AtomicRMWInst::And;
6321 RMWOp = llvm::AtomicRMWInst::Or;
6324 RMWOp = llvm::AtomicRMWInst::Xor;
6328 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6329 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Min
6330 : llvm::AtomicRMWInst::Max)
6331 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMin
6332 : llvm::AtomicRMWInst::UMax);
6334 RMWOp = IsXLHSInRHSPart ? llvm::AtomicRMWInst::FMin
6335 : llvm::AtomicRMWInst::FMax;
6339 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6340 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Max
6341 : llvm::AtomicRMWInst::Min)
6342 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMax
6343 : llvm::AtomicRMWInst::UMin);
6345 RMWOp = IsXLHSInRHSPart ? llvm::AtomicRMWInst::FMax
6346 : llvm::AtomicRMWInst::FMin;
6349 RMWOp = llvm::AtomicRMWInst::Xchg;
6358 return std::make_pair(
false,
RValue::get(
nullptr));
6377 llvm_unreachable(
"Unsupported atomic update operation");
6379 llvm::Value *UpdateVal =
Update.getScalarVal();
6380 if (
auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
6382 UpdateVal = CGF.
Builder.CreateIntCast(
6383 IC,
X.getAddress().getElementType(),
6384 X.getType()->hasSignedIntegerRepresentation());
6386 UpdateVal = CGF.
Builder.CreateCast(llvm::Instruction::CastOps::UIToFP, IC,
6387 X.getAddress().getElementType());
6389 llvm::AtomicRMWInst *Res =
6406 if (
X.isGlobalReg()) {
6419 llvm::AtomicOrdering AO,
const Expr *
X,
6423 "Update expr in 'atomic update' must be a binary operator.");
6431 assert(
X->isLValue() &&
"X of 'omp atomic update' is not lvalue");
6434 const auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
6435 const auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
6438 auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](
RValue XRValue) {
6439 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
6440 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue);
6444 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO,
Loc, Gen);
6451 case llvm::AtomicOrdering::Release:
6452 case llvm::AtomicOrdering::AcquireRelease:
6453 case llvm::AtomicOrdering::SequentiallyConsistent:
6455 llvm::AtomicOrdering::Release);
6457 case llvm::AtomicOrdering::Acquire:
6458 case llvm::AtomicOrdering::Monotonic:
6460 case llvm::AtomicOrdering::NotAtomic:
6461 case llvm::AtomicOrdering::Unordered:
6462 llvm_unreachable(
"Unexpected ordering.");
6480 llvm_unreachable(
"Must be a scalar or complex.");
6484 llvm::AtomicOrdering AO,
6485 bool IsPostfixUpdate,
const Expr *
V,
6487 const Expr *UE,
bool IsXLHSInRHSPart,
6489 assert(
X->isLValue() &&
"X of 'omp atomic capture' is not lvalue");
6490 assert(
V->isLValue() &&
"V of 'omp atomic capture' is not lvalue");
6499 "Update expr in 'atomic capture' must be a binary operator.");
6507 const auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
6508 const auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
6510 NewVValType = XRValExpr->
getType();
6512 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
6513 IsPostfixUpdate](
RValue XRValue) {
6514 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
6515 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue);
6517 NewVVal = IsPostfixUpdate ? XRValue : Res;
6521 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO,
Loc, Gen);
6525 if (IsPostfixUpdate) {
6527 NewVVal = Res.second;
6531 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
6532 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, Res.second);
6538 NewVValType =
X->getType().getNonReferenceType();
6540 X->getType().getNonReferenceType(),
Loc);
6541 auto &&Gen = [&NewVVal, ExprRValue](
RValue XRValue) {
6547 XLValue, ExprRValue, BO_Assign,
false, AO,
6552 NewVVal = IsPostfixUpdate ? Res.
second : ExprRValue;
6568 case llvm::AtomicOrdering::Release:
6570 llvm::AtomicOrdering::Release);
6572 case llvm::AtomicOrdering::Acquire:
6574 llvm::AtomicOrdering::Acquire);
6576 case llvm::AtomicOrdering::AcquireRelease:
6577 case llvm::AtomicOrdering::SequentiallyConsistent:
6579 CGF, {},
Loc, llvm::AtomicOrdering::AcquireRelease);
6581 case llvm::AtomicOrdering::Monotonic:
6583 case llvm::AtomicOrdering::NotAtomic:
6584 case llvm::AtomicOrdering::Unordered:
6585 llvm_unreachable(
"Unexpected ordering.");
6591 CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO,
6593 const Expr *CE,
bool IsXBinopExpr,
bool IsPostfixUpdate,
bool IsFailOnly,
6595 llvm::OpenMPIRBuilder &OMPBuilder =
6598 OMPAtomicCompareOp Op;
6599 assert(isa<BinaryOperator>(CE) &&
"CE is not a BinaryOperator");
6600 switch (cast<BinaryOperator>(CE)->getOpcode()) {
6602 Op = OMPAtomicCompareOp::EQ;
6605 Op = OMPAtomicCompareOp::MIN;
6608 Op = OMPAtomicCompareOp::MAX;
6611 llvm_unreachable(
"unsupported atomic compare binary operator");
6617 auto EmitRValueWithCastIfNeeded = [&CGF,
Loc](
const Expr *
X,
const Expr *
E) {
6622 if (NewE->
getType() ==
X->getType())
6627 llvm::Value *EVal = EmitRValueWithCastIfNeeded(
X,
E);
6628 llvm::Value *DVal =
D ? EmitRValueWithCastIfNeeded(
X,
D) :
nullptr;
6629 if (
auto *CI = dyn_cast<llvm::ConstantInt>(EVal))
6630 EVal = CGF.
Builder.CreateIntCast(
6634 if (
auto *CI = dyn_cast<llvm::ConstantInt>(DVal))
6635 DVal = CGF.
Builder.CreateIntCast(
6637 D->getType()->hasSignedIntegerRepresentation());
6639 llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{
6641 X->getType()->hasSignedIntegerRepresentation(),
6642 X->getType().isVolatileQualified()};
6643 llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal;
6648 V->getType()->hasSignedIntegerRepresentation(),
6649 V->getType().isVolatileQualified()};
6659 if (FailAO == llvm::AtomicOrdering::NotAtomic) {
6662 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
6663 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
6664 IsPostfixUpdate, IsFailOnly));
6666 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
6667 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
6668 IsPostfixUpdate, IsFailOnly, FailAO));
6672 llvm::AtomicOrdering AO,
6673 llvm::AtomicOrdering FailAO,
bool IsPostfixUpdate,
6676 const Expr *CE,
bool IsXLHSInRHSPart,
6691 IsXLHSInRHSPart,
Loc);
6693 case OMPC_compare: {
6695 IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly,
Loc);
6699 llvm_unreachable(
"Clause is not allowed in 'omp atomic'.");
6706 llvm::AtomicOrdering FailAO = llvm::AtomicOrdering::NotAtomic;
6707 bool MemOrderingSpecified =
false;
6709 AO = llvm::AtomicOrdering::SequentiallyConsistent;
6710 MemOrderingSpecified =
true;
6712 AO = llvm::AtomicOrdering::AcquireRelease;
6713 MemOrderingSpecified =
true;
6715 AO = llvm::AtomicOrdering::Acquire;
6716 MemOrderingSpecified =
true;
6718 AO = llvm::AtomicOrdering::Release;
6719 MemOrderingSpecified =
true;
6721 AO = llvm::AtomicOrdering::Monotonic;
6722 MemOrderingSpecified =
true;
6724 llvm::SmallSet<OpenMPClauseKind, 2> KindsEncountered;
6733 if (K == OMPC_seq_cst || K == OMPC_acq_rel || K == OMPC_acquire ||
6734 K == OMPC_release || K == OMPC_relaxed || K == OMPC_hint)
6737 KindsEncountered.insert(K);
6742 if (KindsEncountered.contains(OMPC_compare) &&
6743 KindsEncountered.contains(OMPC_capture))
6744 Kind = OMPC_compare;
6745 if (!MemOrderingSpecified) {
6746 llvm::AtomicOrdering DefaultOrder =
6748 if (DefaultOrder == llvm::AtomicOrdering::Monotonic ||
6749 DefaultOrder == llvm::AtomicOrdering::SequentiallyConsistent ||
6750 (DefaultOrder == llvm::AtomicOrdering::AcquireRelease &&
6751 Kind == OMPC_capture)) {
6753 }
else if (DefaultOrder == llvm::AtomicOrdering::AcquireRelease) {
6754 if (Kind == OMPC_unknown || Kind == OMPC_update || Kind == OMPC_write) {
6755 AO = llvm::AtomicOrdering::Release;
6756 }
else if (Kind == OMPC_read) {
6757 assert(Kind == OMPC_read &&
"Unexpected atomic kind.");
6758 AO = llvm::AtomicOrdering::Acquire;
6763 if (KindsEncountered.contains(OMPC_compare) &&
6764 KindsEncountered.contains(OMPC_fail)) {
6765 Kind = OMPC_compare;
6766 const auto *FailClause = S.getSingleClause<
OMPFailClause>();
6769 if (FailParameter == llvm::omp::OMPC_relaxed)
6770 FailAO = llvm::AtomicOrdering::Monotonic;
6771 else if (FailParameter == llvm::omp::OMPC_acquire)
6772 FailAO = llvm::AtomicOrdering::Acquire;
6773 else if (FailParameter == llvm::omp::OMPC_seq_cst)
6774 FailAO = llvm::AtomicOrdering::SequentiallyConsistent;
6778 LexicalScope
Scope(*
this, S.getSourceRange());
6781 S.getV(), S.getR(), S.getExpr(), S.getUpdateExpr(),
6782 S.getD(), S.getCondExpr(), S.isXLHSInRHSPart(),
6783 S.isFailOnly(), S.getBeginLoc());
6794 OMPLexicalScope
Scope(CGF, S, OMPD_target);
6797 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
6803 llvm::Function *Fn =
nullptr;
6804 llvm::Constant *FnID =
nullptr;
6806 const Expr *IfCond =
nullptr;
6808 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
6809 if (
C->getNameModifier() == OMPD_unknown ||
6810 C->getNameModifier() == OMPD_target) {
6811 IfCond =
C->getCondition();
6817 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device(
6820 Device.setPointerAndInt(
C->getDevice(),
C->getModifier());
6825 bool IsOffloadEntry =
true;
6829 IsOffloadEntry =
false;
6832 IsOffloadEntry =
false;
6834 if (
CGM.
getLangOpts().OpenMPOffloadMandatory && !IsOffloadEntry) {
6837 "No offloading entry generated while offloading is mandatory.");
6841 assert(CGF.
CurFuncDecl &&
"No parent declaration for target region!");
6842 StringRef ParentName;
6845 if (
const auto *
D = dyn_cast<CXXConstructorDecl>(CGF.
CurFuncDecl))
6847 else if (
const auto *
D = dyn_cast<CXXDestructorDecl>(CGF.
CurFuncDecl))
6855 IsOffloadEntry, CodeGen);
6856 OMPLexicalScope
Scope(CGF, S, OMPD_task);
6857 auto &&SizeEmitter =
6860 if (IsOffloadEntry) {
6861 OMPLoopScope(CGF,
D);
6863 llvm::Value *NumIterations = CGF.
EmitScalarExpr(
D.getNumIterations());
6864 NumIterations = CGF.
Builder.CreateIntCast(NumIterations, CGF.
Int64Ty,
6866 return NumIterations;
6877 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
6880 (void)PrivateScope.Privatize();
6884 CGF.
EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
6889 StringRef ParentName,
6895 llvm::Constant *Addr;
6898 S, ParentName, Fn, Addr,
true, CodeGen);
6899 assert(Fn && Addr &&
"Target device function emission failed.");
6913 const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams);
6914 llvm::Function *OutlinedFn =
6922 const Expr *NumTeams = NT ? NT->getNumTeams().front() :
nullptr;
6923 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() :
nullptr;
6929 OMPTeamsScope
Scope(CGF, S);
6940 OMPPrivateScope PrivateScope(CGF);
6944 (void)PrivateScope.Privatize();
6945 CGF.
EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt());
6955 auto *CS = S.getCapturedStmt(OMPD_teams);
6960 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
6964 (void)PrivateScope.Privatize();
6982 llvm::Constant *Addr;
6985 S, ParentName, Fn, Addr,
true, CodeGen);
6986 assert(Fn && Addr &&
"Target device function emission failed.");
7009 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
7011 (void)PrivateScope.Privatize();
7028 llvm::Constant *Addr;
7031 S, ParentName, Fn, Addr,
true, CodeGen);
7032 assert(Fn && Addr &&
"Target device function emission failed.");
7055 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
7057 (void)PrivateScope.Privatize();
7074 llvm::Constant *Addr;
7077 S, ParentName, Fn, Addr,
true, CodeGen);
7078 assert(Fn && Addr &&
"Target device function emission failed.");
7100 OMPPrivateScope PrivateScope(CGF);
7101 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7102 (void)PrivateScope.Privatize();
7103 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
7105 CGF.EmitOMPReductionClauseFinal(S, OMPD_teams);
7122 OMPPrivateScope PrivateScope(CGF);
7123 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7124 (void)PrivateScope.Privatize();
7125 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_simd,
7127 CGF.EmitOMPReductionClauseFinal(S, OMPD_teams);
7145 OMPPrivateScope PrivateScope(CGF);
7146 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7147 (void)PrivateScope.Privatize();
7148 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
7150 CGF.EmitOMPReductionClauseFinal(S, OMPD_teams);
7168 OMPPrivateScope PrivateScope(CGF);
7169 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
7170 (void)PrivateScope.Privatize();
7171 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(
7172 CGF, OMPD_distribute, CodeGenDistribute,
false);
7173 CGF.EmitOMPReductionClauseFinal(S, OMPD_teams);
7183 llvm::Value *
Device =
nullptr;
7184 llvm::Value *NumDependences =
nullptr;
7185 llvm::Value *DependenceList =
nullptr;
7193 if (!
Data.Dependences.empty()) {
7195 std::tie(NumDependences, DependenciesArray) =
7205 "OMPNowaitClause clause is used separately in OMPInteropDirective.");
7208 if (!ItOMPInitClause.empty()) {
7211 llvm::Value *InteropvarPtr =
7213 llvm::omp::OMPInteropType InteropType =
7214 llvm::omp::OMPInteropType::Unknown;
7215 if (
C->getIsTarget()) {
7216 InteropType = llvm::omp::OMPInteropType::Target;
7218 assert(
C->getIsTargetSync() &&
7219 "Expected interop-type target/targetsync");
7220 InteropType = llvm::omp::OMPInteropType::TargetSync;
7222 OMPBuilder.createOMPInteropInit(
Builder, InteropvarPtr, InteropType,
7223 Device, NumDependences, DependenceList,
7224 Data.HasNowaitClause);
7228 if (!ItOMPDestroyClause.empty()) {
7231 llvm::Value *InteropvarPtr =
7233 OMPBuilder.createOMPInteropDestroy(
Builder, InteropvarPtr,
Device,
7234 NumDependences, DependenceList,
7235 Data.HasNowaitClause);
7238 auto ItOMPUseClause = S.getClausesOfKind<
OMPUseClause>();
7239 if (!ItOMPUseClause.empty()) {
7242 llvm::Value *InteropvarPtr =
7244 OMPBuilder.createOMPInteropUse(
Builder, InteropvarPtr,
Device,
7245 NumDependences, DependenceList,
7246 Data.HasNowaitClause);
7264 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
7266 (void)PrivateScope.Privatize();
7268 CGF, OMPD_distribute, CodeGenDistribute,
false);
7287 llvm::Constant *Addr;
7290 S, ParentName, Fn, Addr,
true, CodeGen);
7291 assert(Fn && Addr &&
"Target device function emission failed.");
7316 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
7318 (void)PrivateScope.Privatize();
7320 CGF, OMPD_distribute, CodeGenDistribute,
false);
7339 llvm::Constant *Addr;
7342 S, ParentName, Fn, Addr,
true, CodeGen);
7343 assert(Fn && Addr &&
"Target device function emission failed.");
7357 S.getCancelRegion());
7361 const Expr *IfCond =
nullptr;
7362 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7363 if (
C->getNameModifier() == OMPD_unknown ||
7364 C->getNameModifier() == OMPD_cancel) {
7365 IfCond =
C->getCondition();
7373 if (S.getCancelRegion() == OMPD_parallel ||
7374 S.getCancelRegion() == OMPD_sections ||
7375 S.getCancelRegion() == OMPD_section) {
7376 llvm::Value *IfCondition =
nullptr;
7380 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
7381 OMPBuilder.createCancel(
Builder, IfCondition, S.getCancelRegion()));
7382 return Builder.restoreIP(AfterIP);
7387 S.getCancelRegion());
7390CodeGenFunction::JumpDest
7392 if (Kind == OMPD_parallel || Kind == OMPD_task ||
7393 Kind == OMPD_target_parallel || Kind == OMPD_taskloop ||
7394 Kind == OMPD_master_taskloop || Kind == OMPD_parallel_master_taskloop)
7396 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
7397 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
7398 Kind == OMPD_distribute_parallel_for ||
7399 Kind == OMPD_target_parallel_for ||
7400 Kind == OMPD_teams_distribute_parallel_for ||
7401 Kind == OMPD_target_teams_distribute_parallel_for);
7402 return OMPCancelStack.getExitBlock();
7407 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7408 CaptureDeviceAddrMap) {
7409 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7410 for (
const Expr *OrigVarIt :
C.varlist()) {
7411 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(OrigVarIt)->getDecl());
7412 if (!Processed.insert(OrigVD).second)
7419 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7422 const auto *ME = cast<MemberExpr>(OED->getInit());
7423 assert(isa<CXXThisExpr>(ME->getBase()->IgnoreImpCasts()) &&
7424 "Base should be the current struct!");
7425 MatchingVD = ME->getMemberDecl();
7430 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7431 if (InitAddrIt == CaptureDeviceAddrMap.end())
7437 bool IsRegistered = PrivateScope.addPrivate(
7439 Address(InitAddrIt->second, Ty,
7441 assert(IsRegistered &&
"firstprivate var already registered as private");
7449 while (
const auto *OASE = dyn_cast<ArraySectionExpr>(
Base))
7450 Base = OASE->getBase()->IgnoreParenImpCasts();
7451 while (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(
Base))
7452 Base = ASE->getBase()->IgnoreParenImpCasts();
7453 return cast<VarDecl>(cast<DeclRefExpr>(
Base)->getDecl());
7458 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7459 CaptureDeviceAddrMap) {
7460 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7461 for (
const Expr *Ref :
C.varlist()) {
7463 if (!Processed.insert(OrigVD).second)
7469 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7472 const auto *ME = cast<MemberExpr>(OED->getInit());
7473 assert(isa<CXXThisExpr>(ME->getBase()) &&
7474 "Base should be the current struct!");
7475 MatchingVD = ME->getMemberDecl();
7480 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7481 if (InitAddrIt == CaptureDeviceAddrMap.end())
7487 Address(InitAddrIt->second, Ty,
7491 if (isa<DeclRefExpr>(Ref->IgnoreParenImpCasts()) ||
7500 (void)PrivateScope.addPrivate(OrigVD, PrivAddr);
7513 bool PrivatizeDevicePointers =
false;
7515 bool &PrivatizeDevicePointers;
7518 explicit DevicePointerPrivActionTy(
bool &PrivatizeDevicePointers)
7519 : PrivatizeDevicePointers(PrivatizeDevicePointers) {}
7521 PrivatizeDevicePointers =
true;
7524 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
7528 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
7534 PrivatizeDevicePointers =
false;
7540 if (PrivatizeDevicePointers) {
7541 OMPPrivateScope PrivateScope(CGF);
7545 Info.CaptureDeviceAddrMap);
7548 Info.CaptureDeviceAddrMap);
7549 (void)PrivateScope.Privatize();
7554 std::optional<OpenMPDirectiveKind> CaptureRegion;
7558 for (
const Expr *
E :
C->varlist()) {
7559 const Decl *
D = cast<DeclRefExpr>(
E)->getDecl();
7560 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(
D))
7564 for (
const Expr *
E :
C->varlist()) {
7566 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(
D))
7570 CaptureRegion = OMPD_unknown;
7573 OMPLexicalScope
Scope(CGF, S, CaptureRegion);
7580 PrivRCG.setAction(Action);
7585 OMPLexicalScope
Scope(CGF, S);
7600 const Expr *IfCond =
nullptr;
7602 IfCond =
C->getCondition();
7610 RCG.setAction(PrivAction);
7625 const Expr *IfCond =
nullptr;
7627 IfCond =
C->getCondition();
7634 OMPLexicalScope
Scope(*
this, S, OMPD_task);
7646 const Expr *IfCond =
nullptr;
7648 IfCond =
C->getCondition();
7655 OMPLexicalScope
Scope(*
this, S, OMPD_task);
7663 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
7667 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
7671 (void)PrivateScope.Privatize();
7691 llvm::Constant *Addr;
7694 S, ParentName, Fn, Addr,
true, CodeGen);
7695 assert(Fn && Addr &&
"Target device function emission failed.");
7714 CodeGenFunction::OMPCancelStackRAII CancelRegion(
7715 CGF, OMPD_target_parallel_for, S.hasCancel());
7731 llvm::Constant *Addr;
7734 S, ParentName, Fn, Addr,
true, CodeGen);
7735 assert(Fn && Addr &&
"Target device function emission failed.");
7770 llvm::Constant *Addr;
7773 S, ParentName, Fn, Addr,
true, CodeGen);
7774 assert(Fn && Addr &&
"Target device function emission failed.");
7788 CodeGenFunction::OMPPrivateScope &Privates) {
7789 const auto *VDecl = cast<VarDecl>(Helper->
getDecl());
7796 const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop);
7799 OMPLexicalScope
Scope(*
this, S, OMPD_taskloop,
false);
7803 const Expr *IfCond =
nullptr;
7804 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7805 if (
C->getNameModifier() == OMPD_unknown ||
7806 C->getNameModifier() == OMPD_taskloop) {
7807 IfCond =
C->getCondition();
7820 Data.Schedule.setInt(
false);
7823 (Clause->getModifier() == OMPC_GRAINSIZE_strict) ?
true :
false;
7826 Data.Schedule.setInt(
true);
7829 (Clause->getModifier() == OMPC_NUMTASKS_strict) ?
true :
false;
7843 llvm::BasicBlock *ContBlock =
nullptr;
7844 OMPLoopScope PreInitScope(CGF, S);
7845 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
7849 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock(
"taskloop.if.then");
7850 ContBlock = CGF.createBasicBlock(
"taskloop.if.end");
7851 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
7852 CGF.getProfileCount(&S));
7853 CGF.EmitBlock(ThenBlock);
7854 CGF.incrementProfileCounter(&S);
7857 (void)CGF.EmitOMPLinearClauseInit(S);
7859 OMPPrivateScope LoopScope(CGF);
7861 enum { LowerBound = 5, UpperBound, Stride, LastIter };
7863 auto *LBP = std::next(I, LowerBound);
7864 auto *UBP = std::next(I, UpperBound);
7865 auto *STP = std::next(I, Stride);
7866 auto *LIP = std::next(I, LastIter);
7867 mapParam(CGF, cast<DeclRefExpr>(S.getLowerBoundVariable()), *LBP,
7869 mapParam(CGF, cast<DeclRefExpr>(S.getUpperBoundVariable()), *UBP,
7871 mapParam(CGF, cast<DeclRefExpr>(S.getStrideVariable()), *STP, LoopScope);
7872 mapParam(CGF, cast<DeclRefExpr>(S.getIsLastIterVariable()), *LIP,
7874 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
7875 CGF.EmitOMPLinearClause(S, LoopScope);
7876 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
7877 (void)LoopScope.Privatize();
7879 const Expr *IVExpr = S.getIterationVariable();
7880 const auto *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
7881 CGF.EmitVarDecl(*IVDecl);
7882 CGF.EmitIgnoredExpr(S.getInit());
7887 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
7888 CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
7890 CGF.EmitIgnoredExpr(S.getCalcLastIteration());
7894 OMPLexicalScope
Scope(CGF, S, OMPD_taskloop,
false);
7902 CGF.EmitOMPInnerLoop(
7903 S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(),
7905 emitOMPLoopBodyWithStopPoint(CGF, S,
7906 CodeGenFunction::JumpDest());
7913 CGF.EmitBranch(ContBlock);
7914 CGF.EmitBlock(ContBlock,
true);
7917 if (HasLastprivateClause) {
7918 CGF.EmitOMPLastprivateClauseFinal(
7920 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
7921 CGF.GetAddrOfLocalVar(*LIP),
false,
7922 (*LIP)->getType(), S.getBeginLoc())));
7924 LoopScope.restoreMap();
7926 return CGF.
Builder.CreateIsNotNull(
7928 (*LIP)->
getType(), S.getBeginLoc()));
7931 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
7934 auto &&CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
7936 OMPLoopScope PreInitScope(CGF, S);
7937 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S,
7938 OutlinedFn, SharedsTy,
7939 CapturedStruct, IfCond,
Data);
7941 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
7969 OMPLexicalScope
Scope(*
this, S);
7981 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
7993 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8005 OMPLexicalScope
Scope(*
this, S);
8017 OMPLexicalScope
Scope(*
this, S);
8029 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8047 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8065 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8084 const Expr *IfCond =
nullptr;
8086 IfCond =
C->getCondition();
8093 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8104 BindKind =
C->getBindKind();
8107 case OMPC_BIND_parallel:
8109 case OMPC_BIND_teams:
8111 case OMPC_BIND_thread:
8122 const auto *ForS = dyn_cast<ForStmt>(CS);
8123 if (ForS && !isa<DeclStmt>(ForS->getInit())) {
8124 OMPPrivateScope LoopScope(CGF);
8126 (void)LoopScope.Privatize();
8128 LoopScope.restoreMap();
8133 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
8168 OMPPrivateScope PrivateScope(CGF);
8169 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
8170 (void)PrivateScope.Privatize();
8171 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
8173 CGF.EmitOMPReductionClauseFinal(S, OMPD_teams);
8182 std::string StatusMsg,
8186 StatusMsg +=
": DEVICE";
8188 StatusMsg +=
": HOST";
8195 llvm::dbgs() << StatusMsg <<
": " <<
FileName <<
": " << LineNo <<
"\n";
8214 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
8216 (void)PrivateScope.Privatize();
8218 CGF, OMPD_distribute, CodeGenDistribute,
false);
8243 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
8245 (void)PrivateScope.Privatize();
8247 CGF, OMPD_distribute, CodeGenDistribute,
false);
8261 if (S.canBeParallelFor())
8274 if (S.canBeParallelFor())
8280 llvm::Constant *Addr;
8283 S, ParentName, Fn, Addr,
true, CodeGen);
8284 assert(Fn && Addr &&
8285 "Target device function emission failed for 'target teams loop'.");
8295 CodeGenFunction::OMPCancelStackRAII CancelRegion(
8296 CGF, OMPD_target_parallel_loop,
false);
8312 llvm::Constant *Addr;
8315 S, ParentName, Fn, Addr,
true, CodeGen);
8316 assert(Fn && Addr &&
"Target device function emission failed.");
8331 if (
const auto *SD = dyn_cast<OMPScanDirective>(&
D)) {
8335 if (!
D.hasAssociatedStmt() || !
D.getAssociatedStmt())
8338 OMPPrivateScope GlobalsScope(CGF);
8342 for (
const Expr *Ref :
C->varlist()) {
8343 const auto *DRE = cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
8346 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
8349 if (!CGF.LocalDeclMap.count(VD)) {
8351 GlobalsScope.addPrivate(VD, GlobLVal.
getAddress());
8357 (void)GlobalsScope.Privatize();
8358 ParentLoopDirectiveForScanRegion ScanRegion(CGF,
D);
8361 if (
const auto *LD = dyn_cast<OMPLoopDirective>(&
D)) {
8362 for (
const Expr *
E : LD->counters()) {
8363 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(
E)->getDecl());
8366 GlobalsScope.addPrivate(VD, GlobLVal.
getAddress());
8368 if (isa<OMPCapturedExprDecl>(VD)) {
8370 if (!CGF.LocalDeclMap.count(VD))
8375 if (!
C->getNumForLoops())
8377 for (
unsigned I = LD->getLoopsNumber(),
8378 E =
C->getLoopNumIterations().size();
8380 if (
const auto *VD = dyn_cast<OMPCapturedExprDecl>(
8381 cast<DeclRefExpr>(
C->getLoopCounter(I))->getDecl())) {
8383 if (!CGF.LocalDeclMap.count(VD))
8389 (void)GlobalsScope.Privatize();
8390 CGF.
EmitStmt(
D.getInnermostCapturedStmt()->getCapturedStmt());
8393 if (
D.getDirectiveKind() == OMPD_atomic ||
8394 D.getDirectiveKind() == OMPD_critical ||
8395 D.getDirectiveKind() == OMPD_section ||
8396 D.getDirectiveKind() == OMPD_master ||
8397 D.getDirectiveKind() == OMPD_masked ||
8398 D.getDirectiveKind() == OMPD_unroll ||
8399 D.getDirectiveKind() == OMPD_assume) {
8404 OMPSimdLexicalScope
Scope(*
this,
D);
8408 :
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::@1724::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...
void EmitOMPMaskedTaskLoopSimdDirective(const OMPMaskedTaskLoopSimdDirective &S)
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 EmitOMPParallelMaskedTaskLoopDirective(const OMPParallelMaskedTaskLoopDirective &S)
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)
void EmitOMPMaskedTaskLoopDirective(const OMPMaskedTaskLoopDirective &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 masked taskloop' directive.
This represents '#pragma omp masked taskloop simd' 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 masked taskloop' 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