31#include "llvm/ADT/SmallSet.h"
32#include "llvm/BinaryFormat/Dwarf.h"
33#include "llvm/Frontend/OpenMP/OMPConstants.h"
34#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
35#include "llvm/IR/Constants.h"
36#include "llvm/IR/DebugInfoMetadata.h"
37#include "llvm/IR/Instructions.h"
38#include "llvm/IR/IntrinsicInst.h"
39#include "llvm/IR/Metadata.h"
40#include "llvm/Support/AtomicOrdering.h"
41#include "llvm/Support/Debug.h"
45using namespace llvm::omp;
47#define TTL_CODEGEN_TYPE "target-teams-loop-codegen"
58 for (
const auto *
C : S.clauses()) {
60 if (
const auto *PreInit =
61 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
62 for (
const auto *I : PreInit->decls()) {
63 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
66 CodeGenFunction::AutoVarEmission Emission =
75 CodeGenFunction::OMPPrivateScope InlinedShareds;
77 static bool isCapturedVar(CodeGenFunction &CGF,
const VarDecl *VD) {
86 CodeGenFunction &CGF,
const OMPExecutableDirective &S,
87 const std::optional<OpenMPDirectiveKind> CapturedRegion = std::nullopt,
88 const bool EmitPreInitStmt =
true)
92 emitPreInitStmt(CGF, S);
95 assert(S.hasAssociatedStmt() &&
96 "Expected associated statement for inlined directive.");
97 const CapturedStmt *CS = S.getCapturedStmt(*CapturedRegion);
99 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
100 auto *VD =
C.getCapturedVar();
102 "Canonical decl must be captured.");
106 InlinedShareds.isGlobalVarCaptured(VD)),
111 (void)InlinedShareds.Privatize();
117class OMPParallelScope final :
public OMPLexicalScope {
118 bool EmitPreInitStmt(
const OMPExecutableDirective &S) {
126 OMPParallelScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
127 : OMPLexicalScope(CGF, S, std::nullopt,
128 EmitPreInitStmt(S)) {}
133class OMPTeamsScope final :
public OMPLexicalScope {
134 bool EmitPreInitStmt(
const OMPExecutableDirective &S) {
141 OMPTeamsScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
142 : OMPLexicalScope(CGF, S, std::nullopt,
143 EmitPreInitStmt(S)) {}
149 void emitPreInitStmt(CodeGenFunction &CGF,
const OMPLoopBasedDirective &S) {
150 const Stmt *PreInits;
151 CodeGenFunction::OMPMapVars PreCondVars;
152 if (
auto *LD = dyn_cast<OMPLoopDirective>(&S)) {
154 (void)OMPLoopBasedDirective::doForAllLoops(
155 LD->getInnermostCapturedStmt()->getCapturedStmt(),
156 true, LD->getLoopsNumber(),
157 [&CGF](
unsigned Cnt,
const Stmt *CurStmt) {
158 if (const auto *CXXFor = dyn_cast<CXXForRangeStmt>(CurStmt)) {
159 if (const Stmt *Init = CXXFor->getInit())
161 CGF.EmitStmt(CXXFor->getRangeStmt());
162 CGF.EmitStmt(CXXFor->getBeginStmt());
163 CGF.EmitStmt(CXXFor->getEndStmt());
167 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
168 for (
const auto *E : LD->counters()) {
175 for (
const auto *
C : LD->getClausesOfKind<OMPPrivateClause>()) {
176 for (
const Expr *IRef :
C->varlist()) {
179 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
180 QualType OrigVDTy = OrigVD->getType().getNonReferenceType();
190 (void)PreCondVars.
apply(CGF);
191 PreInits = LD->getPreInits();
192 }
else if (
const auto *
Tile = dyn_cast<OMPTileDirective>(&S)) {
193 PreInits =
Tile->getPreInits();
194 }
else if (
const auto *Stripe = dyn_cast<OMPStripeDirective>(&S)) {
195 PreInits = Stripe->getPreInits();
196 }
else if (
const auto *Unroll = dyn_cast<OMPUnrollDirective>(&S)) {
197 PreInits = Unroll->getPreInits();
198 }
else if (
const auto *Reverse = dyn_cast<OMPReverseDirective>(&S)) {
199 PreInits = Reverse->getPreInits();
200 }
else if (
const auto *Interchange =
201 dyn_cast<OMPInterchangeDirective>(&S)) {
202 PreInits = Interchange->getPreInits();
204 llvm_unreachable(
"Unknown loop-based directive kind.");
206 doEmitPreinits(PreInits);
213 const Stmt *PreInits;
214 if (
const auto *Fuse = dyn_cast<OMPFuseDirective>(&S)) {
215 PreInits = Fuse->getPreInits();
218 "Unknown canonical loop sequence transform directive kind.");
220 doEmitPreinits(PreInits);
223 void doEmitPreinits(
const Stmt *PreInits) {
229 if (
auto *PreInitCompound = dyn_cast<CompoundStmt>(PreInits))
230 llvm::append_range(PreInitStmts, PreInitCompound->body());
232 PreInitStmts.push_back(PreInits);
234 for (
const Stmt *S : PreInitStmts) {
237 if (
auto *PreInitDecl = dyn_cast<DeclStmt>(S)) {
238 for (
Decl *I : PreInitDecl->decls())
250 emitPreInitStmt(CGF, S);
255 emitPreInitStmt(CGF, S);
260 CodeGenFunction::OMPPrivateScope InlinedShareds;
262 static bool isCapturedVar(CodeGenFunction &CGF,
const VarDecl *VD) {
270 OMPSimdLexicalScope(CodeGenFunction &CGF,
const OMPExecutableDirective &S)
272 InlinedShareds(CGF) {
273 for (
const auto *
C : S.clauses()) {
274 if (const auto *CPI = OMPClauseWithPreInit::get(C)) {
275 if (const auto *PreInit =
276 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
277 for (const auto *I : PreInit->decls()) {
278 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
279 CGF.EmitVarDecl(cast<VarDecl>(*I));
281 CodeGenFunction::AutoVarEmission Emission =
282 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
283 CGF.EmitAutoVarCleanups(Emission);
287 }
else if (
const auto *UDP = dyn_cast<OMPUseDevicePtrClause>(
C)) {
288 for (
const Expr *E : UDP->varlist()) {
290 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
293 }
else if (
const auto *UDP = dyn_cast<OMPUseDeviceAddrClause>(
C)) {
294 for (
const Expr *E : UDP->varlist()) {
296 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
303 if (
const auto *TG = dyn_cast<OMPTaskgroupDirective>(&S)) {
304 if (
const Expr *E = TG->getReductionRef())
309 llvm::DenseSet<CanonicalDeclPtr<const Decl>> CopyArrayTemps;
310 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
311 if (C->getModifier() != OMPC_REDUCTION_inscan)
313 for (const Expr *E : C->copy_array_temps())
314 CopyArrayTemps.insert(cast<DeclRefExpr>(E)->getDecl());
316 const auto *CS = cast_or_null<CapturedStmt>(S.getAssociatedStmt());
319 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
320 auto *VD =
C.getCapturedVar();
321 if (CopyArrayTemps.contains(VD))
324 "Canonical decl must be captured.");
325 DeclRefExpr DRE(CGF.
getContext(),
const_cast<VarDecl *
>(VD),
326 isCapturedVar(CGF, VD) ||
328 InlinedShareds.isGlobalVarCaptured(VD)),
336 (void)InlinedShareds.Privatize();
347 if (Kind != OMPD_loop)
352 BindKind =
C->getBindKind();
355 case OMPC_BIND_parallel:
357 case OMPC_BIND_teams:
358 return OMPD_distribute;
359 case OMPC_BIND_thread:
371 if (
const auto *OrigDRE = dyn_cast<DeclRefExpr>(E)) {
372 if (
const auto *OrigVD = dyn_cast<VarDecl>(OrigDRE->getDecl())) {
373 OrigVD = OrigVD->getCanonicalDecl();
379 OrigDRE->getType(),
VK_LValue, OrigDRE->getExprLoc());
388 llvm::Value *Size =
nullptr;
389 auto SizeInChars =
C.getTypeSizeInChars(Ty);
390 if (SizeInChars.isZero()) {
398 SizeInChars =
C.getTypeSizeInChars(Ty);
399 if (SizeInChars.isZero())
400 return llvm::ConstantInt::get(
SizeTy, 0);
401 return Builder.CreateNUWMul(Size,
CGM.getSize(SizeInChars));
403 return CGM.getSize(SizeInChars);
413 I != E; ++I, ++CurField, ++CurCap) {
414 if (CurField->hasCapturedVLAType()) {
417 CapturedVars.push_back(Val);
418 }
else if (CurCap->capturesThis()) {
419 CapturedVars.push_back(CXXThisValue);
420 }
else if (CurCap->capturesVariableByCopy()) {
425 if (!CurField->getType()->isAnyPointerType()) {
429 Twine(CurCap->getCapturedVar()->getName(),
".casted"));
445 CapturedVars.push_back(CV);
447 assert(CurCap->capturesVariable() &&
"Expected capture by reference.");
468 if (T->isLValueReferenceType())
469 return C.getLValueReferenceType(
472 if (T->isPointerType())
475 if (
const auto *VLA = dyn_cast<VariableArrayType>(A))
477 if (!A->isVariablyModifiedType())
478 return C.getCanonicalType(T);
480 return C.getCanonicalParamType(T);
485struct FunctionOptions {
487 const CapturedStmt *S =
nullptr;
490 const bool UIntPtrCastRequired =
true;
493 const bool RegisterCastedArgsOnly =
false;
495 const StringRef FunctionName;
498 const bool IsDeviceKernel =
false;
499 explicit FunctionOptions(
const CapturedStmt *S,
bool UIntPtrCastRequired,
500 bool RegisterCastedArgsOnly, StringRef FunctionName,
501 SourceLocation Loc,
bool IsDeviceKernel)
502 : S(S), UIntPtrCastRequired(UIntPtrCastRequired),
503 RegisterCastedArgsOnly(UIntPtrCastRequired && RegisterCastedArgsOnly),
504 FunctionName(FunctionName), Loc(Loc), IsDeviceKernel(IsDeviceKernel) {}
510 llvm::MapVector<
const Decl *, std::pair<const VarDecl *, Address>>
512 llvm::DenseMap<
const Decl *, std::pair<const Expr *, llvm::Value *>>
514 llvm::Value *&CXXThisValue,
const FunctionOptions &FO) {
517 assert(CD->
hasBody() &&
"missing CapturedDecl body");
519 CXXThisValue =
nullptr;
531 if (!FO.UIntPtrCastRequired) {
551 if (FO.UIntPtrCastRequired &&
552 ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) ||
553 I->capturesVariableArrayType()))
556 if (I->capturesVariable() || I->capturesVariableByCopy()) {
557 CapVar = I->getCapturedVar();
559 }
else if (I->capturesThis()) {
562 assert(I->capturesVariableArrayType());
565 if (ArgType->isVariablyModifiedType())
572 }
else if (DebugFunctionDecl && (CapVar || I->capturesThis())) {
574 Ctx, DebugFunctionDecl,
575 CapVar ? CapVar->
getBeginLoc() : FD->getBeginLoc(),
576 CapVar ? CapVar->
getLocation() : FD->getLocation(), II, ArgType,
582 Args.emplace_back(Arg);
584 TargetArgs.emplace_back(
585 FO.UIntPtrCastRequired
606 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
610 F->setDoesNotThrow();
611 F->setDoesNotRecurse();
615 F->removeFnAttr(llvm::Attribute::NoInline);
616 F->addFnAttr(llvm::Attribute::AlwaysInline);
619 F->addFnAttr(
"sample-profile-suffix-elision-policy",
"selected");
623 FO.UIntPtrCastRequired ? FO.Loc : FO.S->
getBeginLoc(),
624 FO.UIntPtrCastRequired ? FO.Loc
631 if (!FO.UIntPtrCastRequired && Args[Cnt] != TargetArgs[Cnt]) {
639 if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
640 const VarDecl *CurVD = I->getCapturedVar();
641 if (!FO.RegisterCastedArgsOnly)
642 LocalAddrs.insert({Args[Cnt], {CurVD, LocalAddr}});
650 if (FD->hasCapturedVLAType()) {
651 if (FO.UIntPtrCastRequired) {
654 Args[Cnt]->getName(), ArgLVal),
659 VLASizes.try_emplace(Args[Cnt], VAT->
getSizeExpr(), ExprArg);
660 }
else if (I->capturesVariable()) {
661 const VarDecl *Var = I->getCapturedVar();
663 Address ArgAddr = ArgLVal.getAddress();
664 if (ArgLVal.getType()->isLValueReferenceType()) {
667 assert(ArgLVal.getType()->isPointerType());
669 ArgAddr, ArgLVal.getType()->castAs<
PointerType>());
671 if (!FO.RegisterCastedArgsOnly) {
675 }
else if (I->capturesVariableByCopy()) {
676 assert(!FD->getType()->isAnyPointerType() &&
677 "Not expecting a captured pointer.");
678 const VarDecl *Var = I->getCapturedVar();
679 LocalAddrs.insert({Args[Cnt],
680 {Var, FO.UIntPtrCastRequired
682 CGF, I->getLocation(), FD->getType(),
683 Args[Cnt]->getName(), ArgLVal)
684 : ArgLVal.getAddress()}});
687 assert(I->capturesThis());
689 LocalAddrs.insert({Args[Cnt], {
nullptr, ArgLVal.getAddress()}});
700 llvm::MapVector<
const Decl *, std::pair<const VarDecl *, Address>>
702 llvm::DenseMap<
const Decl *, std::pair<const Expr *, llvm::Value *>>
704 llvm::Value *&CXXThisValue, llvm::Value *&ContextV,
const CapturedStmt &CS,
709 CXXThisValue =
nullptr;
719 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
723 F->setDoesNotThrow();
724 F->setDoesNotRecurse();
731 llvm::Type *IntPtrTy = CGF.
IntPtrTy;
732 llvm::Type *PtrTy = CGF.
Builder.getPtrTy();
733 llvm::Align PtrAlign = CGM.
getDataLayout().getPointerABIAlignment(0);
736 for (
auto [FD,
C, FieldIdx] :
740 CGF.
Builder.CreateConstInBoundsGEP1_32(IntPtrTy, ContextV, FieldIdx);
745 if (
C.capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
746 const VarDecl *CurVD =
C.getCapturedVar();
747 Slot->setName(CurVD->
getName());
748 Address SlotAddr(Slot, PtrTy, SlotAlign);
749 LocalAddrs.insert({FD, {CurVD, SlotAddr}});
750 }
else if (FD->hasCapturedVLAType()) {
757 VLASizes.try_emplace(FD, VAT->
getSizeExpr(), ExprArg);
758 }
else if (
C.capturesVariable()) {
759 const VarDecl *Var =
C.getCapturedVar();
763 Slot->setName(Var->
getName() +
".addr");
764 Address SlotAddr(Slot, PtrTy, SlotAlign);
765 LocalAddrs.insert({FD, {Var, SlotAddr}});
768 PtrTy, Slot, PtrAlign, Var->
getName());
769 LocalAddrs.insert({FD,
773 }
else if (
C.capturesVariableByCopy()) {
774 assert(!FD->getType()->isAnyPointerType() &&
775 "Not expecting a captured pointer.");
776 const VarDecl *Var =
C.getCapturedVar();
791 LocalAddrs.insert({FD, {Var, CopyAddr}});
793 assert(
C.capturesThis() &&
"Default case expected to be CXX 'this'");
796 Address SlotAddr(Slot, PtrTy, SlotAlign);
797 LocalAddrs.insert({FD, {
nullptr, SlotAddr}});
809 "CapturedStmtInfo should be set when generating the captured function");
812 bool NeedWrapperFunction =
815 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs,
817 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes,
820 llvm::raw_svector_ostream Out(Buffer);
823 bool IsDeviceKernel =
CGM.getOpenMPRuntime().isGPU() &&
825 D.getCapturedStmt(OMPD_target) == &S;
826 CodeGenFunction WrapperCGF(
CGM,
true);
827 llvm::Function *WrapperF =
nullptr;
828 if (NeedWrapperFunction) {
831 FunctionOptions WrapperFO(&S,
true,
838 WrapperCGF.CXXThisValue, WrapperFO);
841 FunctionOptions FO(&S, !NeedWrapperFunction,
false,
842 Out.str(), Loc, !NeedWrapperFunction && IsDeviceKernel);
844 *
this, WrapperArgs, WrapperLocalAddrs, WrapperVLASizes, CXXThisValue, FO);
846 for (
const auto &LocalAddrPair : WrapperLocalAddrs) {
847 if (LocalAddrPair.second.first) {
848 LocalScope.addPrivate(LocalAddrPair.second.first,
849 LocalAddrPair.second.second);
852 (void)LocalScope.Privatize();
853 for (
const auto &VLASizePair : WrapperVLASizes)
854 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
857 LocalScope.ForceCleanup();
859 if (!NeedWrapperFunction)
863 WrapperF->removeFromParent();
864 F->getParent()->getFunctionList().insertAfter(F->getIterator(), WrapperF);
867 auto *PI = F->arg_begin();
868 for (
const auto *Arg : Args) {
870 auto I = LocalAddrs.find(Arg);
871 if (I != LocalAddrs.end()) {
874 I->second.first ? I->second.first->getType() : Arg->getType(),
880 auto EI = VLASizes.find(Arg);
881 if (EI != VLASizes.end()) {
893 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
903 "CapturedStmtInfo should be set when generating the captured function");
907 bool NeedWrapperFunction =
910 CodeGenFunction WrapperCGF(
CGM,
true);
911 llvm::Function *WrapperF =
nullptr;
912 llvm::Value *WrapperContextV =
nullptr;
913 if (NeedWrapperFunction) {
916 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>>
918 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>>
921 WrapperCGF, WrapperArgs, WrapperLocalAddrs, WrapperVLASizes,
922 WrapperCGF.CXXThisValue, WrapperContextV, S, Loc, FunctionName);
926 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs;
927 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes;
930 if (NeedWrapperFunction) {
932 llvm::raw_svector_ostream Out(Buffer);
933 Out << FunctionName <<
"_debug__";
935 FunctionOptions FO(&S,
false,
936 false, Out.str(), Loc,
941 llvm::Value *ContextV =
nullptr;
943 CXXThisValue, ContextV, S, Loc,
952 llvm::Value *ParamAddr =
Builder.CreateConstInBoundsGEP1_32(
953 IntPtrTy, ContextV, FieldIdx, Twine(Param->getName()) +
".addr");
954 llvm::Value *ParamVal =
Builder.CreateAlignedLoad(
956 CGM.getDataLayout().getPointerABIAlignment(0), Param->getName());
959 Builder.CreateStore(ParamVal, ParamLocalAddr);
960 LocalAddrs.insert({Param, {Param, ParamLocalAddr}});
966 for (
const auto &LocalAddrPair : LocalAddrs) {
967 if (LocalAddrPair.second.first)
968 LocalScope.addPrivate(LocalAddrPair.second.first,
969 LocalAddrPair.second.second);
971 (void)LocalScope.Privatize();
972 for (
const auto &VLASizePair : VLASizes)
973 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
976 (void)LocalScope.ForceCleanup();
979 if (!NeedWrapperFunction)
983 WrapperF->removeFromParent();
984 F->getParent()->getFunctionList().insertAfter(F->getIterator(), WrapperF);
986 llvm::Align PtrAlign =
CGM.getDataLayout().getPointerABIAlignment(0);
989 "Expected context param at position 0 for target regions");
991 "Argument count mismatch");
993 for (
auto [FD, InnerParam, SlotIdx] : llvm::zip(
995 llvm::Value *Slot = WrapperCGF.
Builder.CreateConstInBoundsGEP1_32(
996 WrapperCGF.
IntPtrTy, WrapperContextV, SlotIdx);
998 InnerParam.getType(), Slot, PtrAlign, InnerParam.getName());
999 CallArgs.push_back(Val);
1004 auto InnerParam = F->arg_begin() + SlotIdx;
1005 llvm::Value *Slot = WrapperCGF.
Builder.CreateConstInBoundsGEP1_32(
1006 WrapperCGF.
IntPtrTy, WrapperContextV, SlotIdx);
1008 InnerParam->getType(), Slot, PtrAlign, InnerParam->getName());
1009 CallArgs.push_back(Val);
1011 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
1027 llvm::Value *NumElements =
emitArrayLength(ArrayTy, ElementTy, DestAddr);
1034 DestBegin, NumElements);
1039 llvm::Value *IsEmpty =
1040 Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arraycpy.isempty");
1041 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
1044 llvm::BasicBlock *EntryBB =
Builder.GetInsertBlock();
1049 llvm::PHINode *SrcElementPHI =
1050 Builder.CreatePHI(SrcBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
1051 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
1056 llvm::PHINode *DestElementPHI =
Builder.CreatePHI(
1057 DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
1058 DestElementPHI->addIncoming(DestBegin, EntryBB);
1064 CopyGen(DestElementCurrent, SrcElementCurrent);
1067 llvm::Value *DestElementNext =
1069 1,
"omp.arraycpy.dest.element");
1070 llvm::Value *SrcElementNext =
1072 1,
"omp.arraycpy.src.element");
1075 Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
1076 Builder.CreateCondBr(Done, DoneBB, BodyBB);
1077 DestElementPHI->addIncoming(DestElementNext,
Builder.GetInsertBlock());
1078 SrcElementPHI->addIncoming(SrcElementNext,
Builder.GetInsertBlock());
1088 const auto *BO = dyn_cast<BinaryOperator>(
Copy);
1089 if (BO && BO->getOpcode() == BO_Assign) {
1098 DestAddr, SrcAddr, OriginalType,
1126 bool DeviceConstTarget =
getLangOpts().OpenMPIsTargetDevice &&
1128 bool FirstprivateIsLastprivate =
false;
1129 llvm::DenseMap<const VarDecl *, OpenMPLastprivateModifier> Lastprivates;
1130 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1131 for (
const auto *D :
C->varlist())
1132 Lastprivates.try_emplace(
1136 llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
1141 bool MustEmitFirstprivateCopy =
1142 CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown;
1143 for (
const auto *
C : D.getClausesOfKind<OMPFirstprivateClause>()) {
1144 const auto *IRef =
C->varlist_begin();
1145 const auto *InitsRef =
C->inits().begin();
1146 for (
const Expr *IInit :
C->private_copies()) {
1148 bool ThisFirstprivateIsLastprivate =
1149 Lastprivates.count(OrigVD->getCanonicalDecl()) > 0;
1152 if (!MustEmitFirstprivateCopy && !ThisFirstprivateIsLastprivate && FD &&
1154 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
1155 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
1162 if (DeviceConstTarget && OrigVD->getType().isConstant(
getContext()) &&
1164 (!VD || !VD->
hasAttr<OMPAllocateDeclAttr>())) {
1165 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
1170 FirstprivateIsLastprivate =
1171 FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate;
1172 if (EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()).second) {
1173 const auto *VDInit =
1192 assert(!CE &&
"Expected non-constant firstprivate.");
1199 if (
Type->isArrayType()) {
1215 RunCleanupsScope InitScope(*this);
1217 setAddrOfLocalVar(VDInit, SrcElement);
1218 EmitAnyExprToMem(Init, DestElement,
1219 Init->getType().getQualifiers(),
1221 LocalDeclMap.erase(VDInit);
1232 setAddrOfLocalVar(VDInit, OriginalAddr);
1234 LocalDeclMap.erase(VDInit);
1236 if (ThisFirstprivateIsLastprivate &&
1237 Lastprivates[OrigVD->getCanonicalDecl()] ==
1238 OMPC_LASTPRIVATE_conditional) {
1243 (*IRef)->getExprLoc());
1244 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1248 LocalDeclMap.erase(VD);
1249 setAddrOfLocalVar(VD, VDAddr);
1251 IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1253 assert(IsRegistered &&
1254 "firstprivate var already registered as private");
1262 return FirstprivateIsLastprivate && !EmittedAsFirstprivate.empty();
1270 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
1271 for (
const auto *
C : D.getClausesOfKind<OMPPrivateClause>()) {
1272 auto IRef =
C->varlist_begin();
1273 for (
const Expr *IInit :
C->private_copies()) {
1275 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
1281 assert(IsRegistered &&
"private var already registered as private");
1297 llvm::DenseSet<const VarDecl *> CopiedVars;
1298 llvm::BasicBlock *CopyBegin =
nullptr, *CopyEnd =
nullptr;
1300 auto IRef =
C->varlist_begin();
1301 auto ISrcRef =
C->source_exprs().begin();
1302 auto IDestRef =
C->destination_exprs().begin();
1303 for (
const Expr *AssignOp :
C->assignment_ops()) {
1312 getContext().getTargetInfo().isTLSSupported()) {
1314 "Copyin threadprivates should have been captured!");
1318 LocalDeclMap.erase(VD);
1322 :
CGM.GetAddrOfGlobal(VD),
1323 CGM.getTypes().ConvertTypeForMem(VD->
getType()),
1328 if (CopiedVars.size() == 1) {
1334 auto *MasterAddrInt =
Builder.CreatePtrToInt(
1336 auto *PrivateAddrInt =
Builder.CreatePtrToInt(
1339 Builder.CreateICmpNE(MasterAddrInt, PrivateAddrInt), CopyBegin,
1345 const auto *DestVD =
1366 bool HasAtLeastOneLastprivate =
false;
1368 llvm::DenseSet<const VarDecl *> SIMDLCVs;
1371 for (
const Expr *
C : LoopDirective->counters()) {
1376 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1377 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1378 HasAtLeastOneLastprivate =
true;
1381 const auto *IRef =
C->varlist_begin();
1382 const auto *IDestRef =
C->destination_exprs().begin();
1383 for (
const Expr *IInit :
C->private_copies()) {
1389 if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) {
1390 const auto *DestVD =
1395 (*IRef)->getType(),
VK_LValue, (*IRef)->getExprLoc());
1400 if (IInit && !SIMDLCVs.count(OrigVD->getCanonicalDecl())) {
1403 if (
C->getKind() == OMPC_LASTPRIVATE_conditional) {
1404 VDAddr =
CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
1406 setAddrOfLocalVar(VD, VDAddr);
1412 bool IsRegistered = PrivateScope.
addPrivate(OrigVD, VDAddr);
1413 assert(IsRegistered &&
1414 "lastprivate var already registered as private");
1422 return HasAtLeastOneLastprivate;
1427 llvm::Value *IsLastIterCond) {
1436 llvm::BasicBlock *ThenBB =
nullptr;
1437 llvm::BasicBlock *DoneBB =
nullptr;
1438 if (IsLastIterCond) {
1442 llvm::any_of(D.getClausesOfKind<OMPLastprivateClause>(),
1443 [](
const OMPLastprivateClause *
C) {
1444 return C->getKind() == OMPC_LASTPRIVATE_conditional;
1446 CGM.getOpenMPRuntime().emitBarrierCall(*
this, D.getBeginLoc(),
1453 Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB);
1456 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1457 llvm::DenseMap<const VarDecl *, const Expr *> LoopCountersAndUpdates;
1458 if (
const auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) {
1459 auto IC = LoopDirective->counters().begin();
1460 for (
const Expr *F : LoopDirective->finals()) {
1464 AlreadyEmittedVars.insert(D);
1466 LoopCountersAndUpdates[D] = F;
1470 for (
const auto *
C : D.getClausesOfKind<OMPLastprivateClause>()) {
1471 auto IRef =
C->varlist_begin();
1472 auto ISrcRef =
C->source_exprs().begin();
1473 auto IDestRef =
C->destination_exprs().begin();
1474 for (
const Expr *AssignOp :
C->assignment_ops()) {
1475 const auto *PrivateVD =
1478 const auto *CanonicalVD = PrivateVD->getCanonicalDecl();
1479 if (AlreadyEmittedVars.insert(CanonicalVD).second) {
1483 if (
const Expr *FinalExpr = LoopCountersAndUpdates.lookup(CanonicalVD))
1487 const auto *DestVD =
1491 if (
const auto *RefTy = PrivateVD->getType()->getAs<
ReferenceType>())
1493 Builder.CreateLoad(PrivateAddr),
1494 CGM.getTypes().ConvertTypeForMem(RefTy->getPointeeType()),
1495 CGM.getNaturalTypeAlignment(RefTy->getPointeeType()));
1497 if (
C->getKind() == OMPC_LASTPRIVATE_conditional)
1498 CGM.getOpenMPRuntime().emitLastprivateConditionalFinalUpdate(
1500 (*IRef)->getExprLoc());
1503 EmitOMPCopy(
Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp);
1509 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
1529 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1530 if (ForInscan != (
C->getModifier() == OMPC_REDUCTION_inscan))
1532 Shareds.append(
C->varlist_begin(),
C->varlist_end());
1533 Privates.append(
C->privates().begin(),
C->privates().end());
1534 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1535 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1536 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1537 if (
C->getModifier() == OMPC_REDUCTION_task) {
1538 Data.ReductionVars.append(
C->privates().begin(),
C->privates().end());
1539 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
1540 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
1541 Data.ReductionOps.append(
C->reduction_ops().begin(),
1542 C->reduction_ops().end());
1543 TaskLHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1544 TaskRHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1549 auto *ILHS = LHSs.begin();
1550 auto *IRHS = RHSs.begin();
1552 for (
const Expr *IRef : Shareds) {
1560 [&Emission](CodeGenFunction &CGF) {
1561 CGF.EmitAutoVarInit(Emission);
1569 assert(IsRegistered &&
"private var already registered as private");
1577 if (isaOMPArraySectionExpr &&
Type->isVariablyModifiedType()) {
1582 }
else if ((isaOMPArraySectionExpr &&
Type->isScalarType()) ||
1600 PrivateScope.
addPrivate(LHSVD, OriginalAddr);
1611 if (!
Data.ReductionVars.empty()) {
1613 Data.IsReductionWithTaskMod =
true;
1615 llvm::Value *ReductionDesc =
CGM.getOpenMPRuntime().emitTaskReductionInit(
1616 *
this, D.getBeginLoc(), TaskLHSs, TaskRHSs,
Data);
1617 const Expr *TaskRedRef =
nullptr;
1628 case OMPD_parallel_for:
1631 case OMPD_parallel_master:
1635 case OMPD_parallel_sections:
1639 case OMPD_target_parallel:
1643 case OMPD_target_parallel_for:
1647 case OMPD_distribute_parallel_for:
1651 case OMPD_teams_distribute_parallel_for:
1653 .getTaskReductionRefExpr();
1655 case OMPD_target_teams_distribute_parallel_for:
1657 .getTaskReductionRefExpr();
1665 case OMPD_parallel_for_simd:
1667 case OMPD_taskyield:
1671 case OMPD_taskgroup:
1679 case OMPD_cancellation_point:
1681 case OMPD_target_data:
1682 case OMPD_target_enter_data:
1683 case OMPD_target_exit_data:
1685 case OMPD_taskloop_simd:
1686 case OMPD_master_taskloop:
1687 case OMPD_master_taskloop_simd:
1688 case OMPD_parallel_master_taskloop:
1689 case OMPD_parallel_master_taskloop_simd:
1690 case OMPD_distribute:
1691 case OMPD_target_update:
1692 case OMPD_distribute_parallel_for_simd:
1693 case OMPD_distribute_simd:
1694 case OMPD_target_parallel_for_simd:
1695 case OMPD_target_simd:
1696 case OMPD_teams_distribute:
1697 case OMPD_teams_distribute_simd:
1698 case OMPD_teams_distribute_parallel_for_simd:
1699 case OMPD_target_teams:
1700 case OMPD_target_teams_distribute:
1701 case OMPD_target_teams_distribute_parallel_for_simd:
1702 case OMPD_target_teams_distribute_simd:
1703 case OMPD_declare_target:
1704 case OMPD_end_declare_target:
1705 case OMPD_threadprivate:
1707 case OMPD_declare_reduction:
1708 case OMPD_declare_mapper:
1709 case OMPD_declare_simd:
1711 case OMPD_declare_variant:
1712 case OMPD_begin_declare_variant:
1713 case OMPD_end_declare_variant:
1716 llvm_unreachable(
"Unexpected directive with task reductions.");
1722 false, TaskRedRef->
getType());
1735 bool HasAtLeastOneReduction =
false;
1736 bool IsReductionWithTaskMod =
false;
1737 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1739 if (
C->getModifier() == OMPC_REDUCTION_inscan)
1741 HasAtLeastOneReduction =
true;
1742 Privates.append(
C->privates().begin(),
C->privates().end());
1743 LHSExprs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
1744 RHSExprs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
1745 IsPrivateVarReduction.append(
C->private_var_reduction_flags().begin(),
1746 C->private_var_reduction_flags().end());
1747 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
1748 IsReductionWithTaskMod =
1749 IsReductionWithTaskMod ||
C->getModifier() == OMPC_REDUCTION_task;
1751 if (HasAtLeastOneReduction) {
1753 if (IsReductionWithTaskMod) {
1754 CGM.getOpenMPRuntime().emitTaskReductionFini(
1757 bool TeamsLoopCanBeParallel =
false;
1758 if (
auto *TTLD = dyn_cast<OMPTargetTeamsGenericLoopDirective>(&D))
1759 TeamsLoopCanBeParallel = TTLD->canBeParallelFor();
1760 bool WithNowait = D.getSingleClause<OMPNowaitClause>() ||
1762 TeamsLoopCanBeParallel || ReductionKind == OMPD_simd;
1763 bool SimpleReduction = ReductionKind == OMPD_simd;
1766 CGM.getOpenMPRuntime().emitReduction(
1767 *
this, D.getEndLoc(),
Privates, LHSExprs, RHSExprs, ReductionOps,
1768 {WithNowait, SimpleReduction, IsPrivateVarReduction, ReductionKind});
1777 llvm::BasicBlock *DoneBB =
nullptr;
1778 for (
const auto *
C : D.getClausesOfKind<OMPReductionClause>()) {
1779 if (
const Expr *PostUpdate =
C->getPostUpdateExpr()) {
1781 if (llvm::Value *
Cond = CondGen(CGF)) {
1802 const OMPExecutableDirective &,
1803 llvm::SmallVectorImpl<llvm::Value *> &)>
1804 CodeGenBoundParametersTy;
1812 llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> PrivateDecls;
1813 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
1814 for (
const Expr *Ref :
C->varlist()) {
1815 if (!Ref->getType()->isScalarType())
1817 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1824 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
1825 for (
const Expr *Ref :
C->varlist()) {
1826 if (!Ref->getType()->isScalarType())
1828 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1835 for (
const auto *
C : S.getClausesOfKind<OMPLinearClause>()) {
1836 for (
const Expr *Ref :
C->varlist()) {
1837 if (!Ref->getType()->isScalarType())
1839 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1850 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
1851 for (
const Expr *Ref :
C->varlist()) {
1852 if (!Ref->getType()->isScalarType())
1854 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1861 CGF, S, PrivateDecls);
1867 const CodeGenBoundParametersTy &CodeGenBoundParameters) {
1868 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
1869 llvm::Value *NumThreads =
nullptr;
1878 llvm::Function *OutlinedFn =
1885 NumThreads = CGF.
EmitScalarExpr(NumThreadsClause->getNumThreads(),
1887 Modifier = NumThreadsClause->getModifier();
1888 if (
const auto *MessageClause = S.getSingleClause<OMPMessageClause>()) {
1889 Message = MessageClause->getMessageString();
1890 MessageLoc = MessageClause->getBeginLoc();
1892 if (
const auto *SeverityClause = S.getSingleClause<OMPSeverityClause>()) {
1893 Severity = SeverityClause->getSeverityKind();
1894 SeverityLoc = SeverityClause->getBeginLoc();
1897 CGF, NumThreads, NumThreadsClause->getBeginLoc(), Modifier, Severity,
1898 SeverityLoc, Message, MessageLoc);
1900 if (
const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>()) {
1903 CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getBeginLoc());
1905 const Expr *IfCond =
nullptr;
1906 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
1907 if (
C->getNameModifier() == OMPD_unknown ||
1908 C->getNameModifier() == OMPD_parallel) {
1909 IfCond =
C->getCondition();
1914 OMPParallelScope
Scope(CGF, S);
1920 CodeGenBoundParameters(CGF, S, CapturedVars);
1923 CapturedVars, IfCond, NumThreads,
1924 Modifier, Severity, Message);
1929 if (!CVD->
hasAttr<OMPAllocateDeclAttr>())
1931 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
1933 return !((AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc ||
1934 AA->getAllocatorType() == OMPAllocateDeclAttr::OMPNullMemAlloc) &&
1935 !AA->getAllocator());
1950 CGF, S.getBeginLoc(), OMPD_unknown,
false,
1956 CodeGenFunction &CGF,
const VarDecl *VD) {
1958 auto &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
1970 Size = CGF.
Builder.CreateNUWAdd(
1972 Size = CGF.
Builder.CreateUDiv(Size,
CGM.getSize(Align));
1973 Size = CGF.
Builder.CreateNUWMul(Size,
CGM.getSize(Align));
1979 const auto *AA = CVD->
getAttr<OMPAllocateDeclAttr>();
1980 assert(AA->getAllocator() &&
1981 "Expected allocator expression for non-default allocator.");
1985 if (Allocator->getType()->isIntegerTy())
1986 Allocator = CGF.
Builder.CreateIntToPtr(Allocator,
CGM.VoidPtrTy);
1987 else if (Allocator->getType()->isPointerTy())
1991 llvm::Value *
Addr = OMPBuilder.createOMPAlloc(
1994 llvm::CallInst *FreeCI =
1995 OMPBuilder.createOMPFree(CGF.
Builder,
Addr, Allocator);
2009 if (
CGM.getLangOpts().OpenMPUseTLS &&
2010 CGM.getContext().getTargetInfo().isTLSSupported())
2013 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2018 llvm::ConstantInt *Size =
CGM.getSize(
CGM.GetTargetTypeStoreSize(VarTy));
2020 llvm::Twine CacheName = Twine(
CGM.getMangledName(VD)).concat(Suffix);
2022 llvm::CallInst *ThreadPrivateCacheCall =
2023 OMPBuilder.createCachedThreadPrivate(CGF.
Builder,
Data, Size, CacheName);
2031 llvm::raw_svector_ostream OS(Buffer);
2032 StringRef Sep = FirstSeparator;
2033 for (StringRef Part : Parts) {
2037 return OS.str().str();
2045 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
2046 "." + RegionName +
".after");
2062 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
Builder,
false,
2063 "." + RegionName +
".after");
2075 if (
CGM.getLangOpts().OpenMPIRBuilder) {
2076 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2078 llvm::Value *IfCond =
nullptr;
2083 llvm::Value *NumThreads =
nullptr;
2088 ProcBindKind ProcBind = OMP_PROC_BIND_default;
2089 if (
const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>())
2090 ProcBind = ProcBindClause->getProcBindKind();
2092 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
2096 auto FiniCB = [
this](InsertPointTy IP) {
2098 return llvm::Error::success();
2105 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
2106 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
2117 auto BodyGenCB = [&,
this](InsertPointTy AllocaIP,
2118 InsertPointTy CodeGenIP) {
2120 *
this, ParallelRegionBodyStmt, AllocaIP, CodeGenIP,
"parallel");
2121 return llvm::Error::success();
2126 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
2128 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
2129 OMPBuilder.createParallel(
Builder, AllocaIP, BodyGenCB, PrivCB, FiniCB,
2130 IfCond, NumThreads, ProcBind, S.hasCancel()));
2144 CGF.
EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt());
2153 [](CodeGenFunction &) {
return nullptr; });
2165class OMPTransformDirectiveScopeRAII {
2166 OMPLoopScope *
Scope =
nullptr;
2170 OMPTransformDirectiveScopeRAII(
const OMPTransformDirectiveScopeRAII &) =
2172 OMPTransformDirectiveScopeRAII &
2173 operator=(
const OMPTransformDirectiveScopeRAII &) =
delete;
2177 if (
const auto *Dir = dyn_cast<OMPLoopBasedDirective>(S)) {
2178 Scope =
new OMPLoopScope(CGF, *Dir);
2181 }
else if (
const auto *Dir =
2182 dyn_cast<OMPCanonicalLoopSequenceTransformationDirective>(
2187 Scope =
new OMPLoopScope(CGF, *Dir);
2192 ~OMPTransformDirectiveScopeRAII() {
2203 int MaxLevel,
int Level = 0) {
2204 assert(Level < MaxLevel &&
"Too deep lookup during loop body codegen.");
2206 if (
const auto *CS = dyn_cast<CompoundStmt>(SimplifiedS)) {
2209 "LLVM IR generation of compound statement ('{}')");
2213 for (
const Stmt *CurStmt : CS->body())
2214 emitBody(CGF, CurStmt, NextLoop, MaxLevel, Level);
2217 if (SimplifiedS == NextLoop) {
2218 if (
auto *Dir = dyn_cast<OMPLoopTransformationDirective>(SimplifiedS))
2219 SimplifiedS = Dir->getTransformedStmt();
2220 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(SimplifiedS))
2221 SimplifiedS = CanonLoop->getLoopStmt();
2222 if (
const auto *For = dyn_cast<ForStmt>(SimplifiedS)) {
2226 "Expected canonical for loop or range-based for loop.");
2228 CGF.
EmitStmt(CXXFor->getLoopVarStmt());
2229 S = CXXFor->getBody();
2231 if (Level + 1 < MaxLevel) {
2232 NextLoop = OMPLoopDirective::tryToFindNextInnerLoop(
2234 emitBody(CGF, S, NextLoop, MaxLevel, Level + 1);
2245 for (
const Expr *UE : D.updates())
2252 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2253 for (
const Expr *UE :
C->updates())
2260 BreakContinueStack.push_back(BreakContinue(D,
LoopExit, Continue));
2261 for (
const Expr *E : D.finals_conditions()) {
2274 bool IsInscanRegion = InscanScope.
Privatize();
2275 if (IsInscanRegion) {
2285 if (EKind != OMPD_simd && !
getLangOpts().OpenMPSimd)
2294 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
2297 OMPLoopBasedDirective::tryToFindNextInnerLoop(
2299 D.getLoopsNumber());
2307 BreakContinueStack.pop_back();
2318 std::unique_ptr<CodeGenFunction::CGCapturedStmtInfo> CSI =
2319 std::make_unique<CodeGenFunction::CGCapturedStmtInfo>(*S);
2323 return {F, CapStruct.getPointer(
ParentCGF)};
2327static llvm::CallInst *
2332 EffectiveArgs.reserve(Args.size() + 1);
2333 llvm::append_range(EffectiveArgs, Args);
2334 EffectiveArgs.push_back(Cap.second);
2339llvm::CanonicalLoopInfo *
2341 assert(Depth == 1 &&
"Nested loops with OpenMPIRBuilder not yet implemented");
2367 const Stmt *SyntacticalLoop = S->getLoopStmt();
2378 const Stmt *BodyStmt;
2379 if (
const auto *For = dyn_cast<ForStmt>(SyntacticalLoop)) {
2380 if (
const Stmt *InitStmt = For->getInit())
2382 BodyStmt = For->getBody();
2383 }
else if (
const auto *RangeFor =
2384 dyn_cast<CXXForRangeStmt>(SyntacticalLoop)) {
2385 if (
const DeclStmt *RangeStmt = RangeFor->getRangeStmt())
2387 if (
const DeclStmt *BeginStmt = RangeFor->getBeginStmt())
2389 if (
const DeclStmt *EndStmt = RangeFor->getEndStmt())
2391 if (
const DeclStmt *LoopVarStmt = RangeFor->getLoopVarStmt())
2393 BodyStmt = RangeFor->getBody();
2395 llvm_unreachable(
"Expected for-stmt or range-based for-stmt");
2398 const CapturedStmt *DistanceFunc = S->getDistanceFunc();
2411 llvm::Value *DistVal =
Builder.CreateLoad(CountAddr,
".count");
2414 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
2415 auto BodyGen = [&,
this](llvm::OpenMPIRBuilder::InsertPointTy CodeGenIP,
2416 llvm::Value *IndVar) {
2421 const DeclRefExpr *LoopVarRef = S->getLoopVarRef();
2429 return llvm::Error::success();
2432 llvm::CanonicalLoopInfo *
CL =
2433 cantFail(OMPBuilder.createCanonicalLoop(
Builder, BodyGen, DistVal));
2445 const Expr *IncExpr,
2446 const llvm::function_ref<
void(CodeGenFunction &)> BodyGen,
2447 const llvm::function_ref<
void(CodeGenFunction &)> PostIncGen) {
2457 const CapturedStmt *ICS = OMPED.getInnermostCapturedStmt();
2471 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
2472 if (RequiresCleanup)
2479 if (ExitBlock !=
LoopExit.getBlock()) {
2489 BreakContinueStack.push_back(BreakContinue(S,
LoopExit, Continue));
2497 BreakContinueStack.pop_back();
2508 bool HasLinears =
false;
2509 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2513 if (
const auto *Ref =
2532 if (
const auto *CS = cast_or_null<BinaryOperator>(
C->getCalcStep()))
2544 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2547 llvm::BasicBlock *DoneBB =
nullptr;
2549 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2550 auto IC =
C->varlist_begin();
2551 for (
const Expr *F :
C->finals()) {
2553 if (llvm::Value *
Cond = CondGen(*
this)) {
2565 (*IC)->getType(),
VK_LValue, (*IC)->getExprLoc());
2573 if (
const Expr *PostUpdate =
C->getPostUpdateExpr())
2585 llvm::APInt ClauseAlignment(64, 0);
2586 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
2589 ClauseAlignment = AlignmentCI->getValue();
2591 for (
const Expr *E : Clause->varlist()) {
2592 llvm::APInt Alignment(ClauseAlignment);
2593 if (Alignment == 0) {
2600 E->getType()->getPointeeType()))
2603 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
2604 "alignment is not power of 2");
2605 if (Alignment != 0) {
2619 auto I = S.private_counters().begin();
2620 for (
const Expr *E : S.counters()) {
2626 LocalDeclMap.erase(PrivateVD);
2632 E->getType(),
VK_LValue, E->getExprLoc());
2640 for (
const auto *
C : S.getClausesOfKind<OMPOrderedClause>()) {
2641 if (!
C->getNumForLoops())
2643 for (
unsigned I = S.getLoopsNumber(), E =
C->getLoopNumIterations().size();
2649 if (DRE->refersToEnclosingVariableOrCapture()) {
2658 const Expr *
Cond, llvm::BasicBlock *TrueBlock,
2659 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
2667 for (
const Expr *I : S.inits()) {
2674 for (
const Expr *E : S.dependent_counters()) {
2677 assert(!E->getType().getNonReferenceType()->isRecordType() &&
2678 "dependent counter must not be an iterator.");
2682 (void)PreCondVars.
setVarAddr(CGF, VD, CounterAddr);
2684 (void)PreCondVars.
apply(CGF);
2685 for (
const Expr *E : S.dependent_inits()) {
2699 llvm::DenseSet<const VarDecl *> SIMDLCVs;
2703 for (
const Expr *
C : LoopDirective->counters()) {
2708 for (
const auto *
C : D.getClausesOfKind<OMPLinearClause>()) {
2709 auto CurPrivate =
C->privates().begin();
2710 for (
const Expr *E :
C->varlist()) {
2712 const auto *PrivateVD =
2719 assert(IsRegistered &&
"linear var already registered as private");
2807 if (
const auto *CS = dyn_cast<CapturedStmt>(S))
2825 if (HasOrderedDirective)
2833 const Stmt *AssociatedStmt = D.getAssociatedStmt();
2837 if (
C->getKind() == OMPC_ORDER_concurrent)
2840 if ((EKind == OMPD_simd ||
2842 llvm::any_of(D.getClausesOfKind<OMPReductionClause>(),
2843 [](
const OMPReductionClause *
C) {
2844 return C->getModifier() == OMPC_REDUCTION_inscan;
2852 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
2855 llvm::BasicBlock *DoneBB =
nullptr;
2856 auto IC = D.counters().begin();
2857 auto IPC = D.private_counters().begin();
2858 for (
const Expr *F : D.finals()) {
2861 const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
2863 OrigVD->hasGlobalStorage() || CED) {
2865 if (llvm::Value *
Cond = CondGen(*
this)) {
2913 auto &&ThenGen = [&S, &SimdInitGen, &BodyCodeGen](
CodeGenFunction &CGF,
2927 const Expr *IfCond =
nullptr;
2930 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
2932 (
C->getNameModifier() == OMPD_unknown ||
2933 C->getNameModifier() == OMPD_simd)) {
2934 IfCond =
C->getCondition();
2950 OMPLoopScope PreInitScope(CGF, S);
2972 llvm::BasicBlock *ContBlock =
nullptr;
2979 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
2986 const Expr *IVExpr = S.getIterationVariable();
2994 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
3009 CGF, S, CGF.
EmitLValue(S.getIterationVariable()));
3024 emitOMPLoopBodyWithStopPoint(CGF, S,
3025 CodeGenFunction::JumpDest());
3031 if (HasLastprivateClause)
3060 if (
const auto *CanonLoop = dyn_cast<OMPCanonicalLoop>(S.getRawStmt())) {
3061 if (
const Stmt *SyntacticalLoop = CanonLoop->getLoopStmt()) {
3062 for (
const Stmt *SubStmt : SyntacticalLoop->
children()) {
3065 if (
const CompoundStmt *CS = dyn_cast<CompoundStmt>(SubStmt)) {
3080static llvm::MapVector<llvm::Value *, llvm::Value *>
3082 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars;
3084 llvm::APInt ClauseAlignment(64, 0);
3085 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
3088 ClauseAlignment = AlignmentCI->getValue();
3090 for (
const Expr *E : Clause->varlist()) {
3091 llvm::APInt Alignment(ClauseAlignment);
3092 if (Alignment == 0) {
3099 E->getType()->getPointeeType()))
3102 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
3103 "alignment is not power of 2");
3105 AlignedVars[PtrValue] = CGF.
Builder.getInt64(Alignment.getSExtValue());
3115 bool UseOMPIRBuilder =
3117 if (UseOMPIRBuilder) {
3121 if (UseOMPIRBuilder) {
3122 llvm::MapVector<llvm::Value *, llvm::Value *> AlignedVars =
3125 const Stmt *Inner = S.getRawStmt();
3126 llvm::CanonicalLoopInfo *CLI =
3127 CGF.EmitOMPCollapsedCanonicalLoopNest(Inner, 1);
3129 llvm::OpenMPIRBuilder &OMPBuilder =
3132 llvm::ConstantInt *Simdlen =
nullptr;
3139 llvm::ConstantInt *Safelen =
nullptr;
3146 llvm::omp::OrderKind Order = llvm::omp::OrderKind::OMP_ORDER_unknown;
3148 if (
C->getKind() == OpenMPOrderClauseKind::OMPC_ORDER_concurrent) {
3149 Order = llvm::omp::OrderKind::OMP_ORDER_concurrent;
3154 OMPBuilder.applySimd(CLI, AlignedVars,
3155 nullptr, Order, Simdlen, Safelen);
3162 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
3177 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
3190 OMPTransformDirectiveScopeRAII TileScope(*
this, &S);
3196 OMPTransformDirectiveScopeRAII StripeScope(*
this, &S);
3202 OMPTransformDirectiveScopeRAII ReverseScope(*
this, &S);
3209 OMPTransformDirectiveScopeRAII InterchangeScope(*
this, &S);
3215 OMPTransformDirectiveScopeRAII FuseScope(*
this, &S);
3220 bool UseOMPIRBuilder =
CGM.getLangOpts().OpenMPIRBuilder;
3222 if (UseOMPIRBuilder) {
3224 const Stmt *Inner = S.getRawStmt();
3232 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
3235 llvm::CanonicalLoopInfo *UnrolledCLI =
nullptr;
3239 OMPBuilder.unrollLoopFull(DL, CLI);
3241 uint64_t Factor = 0;
3242 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3243 Factor = FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
3244 assert(Factor >= 1 &&
"Only positive factors are valid");
3246 OMPBuilder.unrollLoopPartial(DL, CLI, Factor,
3247 NeedsUnrolledCLI ? &UnrolledCLI :
nullptr);
3249 OMPBuilder.unrollLoopHeuristic(DL, CLI);
3252 assert((!NeedsUnrolledCLI || UnrolledCLI) &&
3253 "NeedsUnrolledCLI implies UnrolledCLI to be set");
3270 if (
Expr *FactorExpr = PartialClause->getFactor()) {
3272 FactorExpr->EvaluateKnownConstInt(
getContext()).getZExtValue();
3273 assert(Factor >= 1 &&
"Only positive factors are valid");
3281void CodeGenFunction::EmitOMPOuterLoop(
3284 const CodeGenFunction::OMPLoopArguments &LoopArgs,
3289 const Expr *IVExpr = S.getIterationVariable();
3303 llvm::Value *BoolCondVal =
nullptr;
3304 if (!DynamicOrOrdered) {
3315 RT.
emitForNext(*
this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL,
3316 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST);
3321 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
3326 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
3327 if (ExitBlock !=
LoopExit.getBlock()) {
3335 if (DynamicOrOrdered)
3340 BreakContinueStack.push_back(BreakContinue(S, LoopExit, Continue));
3345 [&S, IsMonotonic, EKind](CodeGenFunction &CGF, PrePostActionTy &) {
3350 if (
const auto *
C = S.getSingleClause<OMPOrderClause>())
3351 if (
C->getKind() == OMPC_ORDER_concurrent)
3357 [&S, &LoopArgs, LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered,
3358 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
3359 SourceLocation Loc = S.getBeginLoc();
3365 CGF.EmitOMPInnerLoop(
3367 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
3368 CodeGenLoop(CGF, S, LoopExit);
3370 [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) {
3371 CodeGenOrdered(CGF, Loc, IVSize, IVSigned);
3376 BreakContinueStack.pop_back();
3377 if (!DynamicOrOrdered) {
3390 auto &&CodeGen = [DynamicOrOrdered, &S, &LoopArgs](CodeGenFunction &CGF) {
3391 if (!DynamicOrOrdered)
3392 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
3395 OMPCancelStack.emitExit(*
this, EKind, CodeGen);
3398void CodeGenFunction::EmitOMPForOuterLoop(
3399 const OpenMPScheduleTy &ScheduleKind,
bool IsMonotonic,
3401 const OMPLoopArguments &LoopArgs,
3403 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3409 LoopArgs.Chunk !=
nullptr)) &&
3410 "static non-chunked schedule does not need outer loop");
3464 const Expr *IVExpr = S.getIterationVariable();
3468 if (DynamicOrOrdered) {
3469 const std::pair<llvm::Value *, llvm::Value *> DispatchBounds =
3470 CGDispatchBounds(*
this, S, LoopArgs.LB, LoopArgs.UB);
3471 llvm::Value *LBVal = DispatchBounds.first;
3472 llvm::Value *UBVal = DispatchBounds.second;
3473 CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal,
3476 IVSigned, Ordered, DipatchRTInputValues);
3478 CGOpenMPRuntime::StaticRTInput StaticInit(
3479 IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
3480 LoopArgs.ST, LoopArgs.Chunk);
3486 auto &&CodeGenOrdered = [Ordered](CodeGenFunction &CGF, SourceLocation Loc,
3487 const unsigned IVSize,
3488 const bool IVSigned) {
3495 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST,
3496 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB);
3497 OuterLoopArgs.IncExpr = S.getInc();
3498 OuterLoopArgs.Init = S.getInit();
3499 OuterLoopArgs.Cond = S.getCond();
3500 OuterLoopArgs.NextLB = S.getNextLowerBound();
3501 OuterLoopArgs.NextUB = S.getNextUpperBound();
3502 OuterLoopArgs.DKind = LoopArgs.DKind;
3503 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
3505 if (DynamicOrOrdered) {
3511 const unsigned IVSize,
const bool IVSigned) {}
3513void CodeGenFunction::EmitOMPDistributeOuterLoop(
3518 CGOpenMPRuntime &RT =
CGM.getOpenMPRuntime();
3525 const Expr *IVExpr = S.getIterationVariable();
3530 CGOpenMPRuntime::StaticRTInput StaticInit(
3531 IVSize, IVSigned,
false, LoopArgs.IL, LoopArgs.LB,
3532 LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
3539 IncExpr = S.getDistInc();
3541 IncExpr = S.getInc();
3546 OMPLoopArguments OuterLoopArgs;
3547 OuterLoopArgs.LB = LoopArgs.LB;
3548 OuterLoopArgs.UB = LoopArgs.UB;
3549 OuterLoopArgs.ST = LoopArgs.ST;
3550 OuterLoopArgs.IL = LoopArgs.IL;
3551 OuterLoopArgs.Chunk = LoopArgs.Chunk;
3553 ? S.getCombinedEnsureUpperBound()
3554 : S.getEnsureUpperBound();
3555 OuterLoopArgs.IncExpr = IncExpr;
3557 ? S.getCombinedInit()
3560 ? S.getCombinedCond()
3563 ? S.getCombinedNextLowerBound()
3564 : S.getNextLowerBound();
3566 ? S.getCombinedNextUpperBound()
3567 : S.getNextUpperBound();
3568 OuterLoopArgs.DKind = OMPD_distribute;
3570 EmitOMPOuterLoop(
false,
false, S,
3571 LoopScope, OuterLoopArgs, CodeGenLoopContent,
3575static std::pair<LValue, LValue>
3590 LValue PrevLB = CGF.
EmitLValue(LS.getPrevLowerBoundVariable());
3591 LValue PrevUB = CGF.
EmitLValue(LS.getPrevUpperBoundVariable());
3593 PrevLB, LS.getPrevLowerBoundVariable()->getExprLoc());
3595 PrevLBVal, LS.getPrevLowerBoundVariable()->getType(),
3596 LS.getIterationVariable()->getType(),
3597 LS.getPrevLowerBoundVariable()->getExprLoc());
3599 PrevUB, LS.getPrevUpperBoundVariable()->getExprLoc());
3601 PrevUBVal, LS.getPrevUpperBoundVariable()->getType(),
3602 LS.getIterationVariable()->getType(),
3603 LS.getPrevUpperBoundVariable()->getExprLoc());
3618static std::pair<llvm::Value *, llvm::Value *>
3623 const Expr *IVExpr = LS.getIterationVariable();
3629 llvm::Value *LBVal =
3631 llvm::Value *UBVal =
3633 return {LBVal, UBVal};
3642 llvm::Value *LBCast = CGF.
Builder.CreateIntCast(
3644 CapturedVars.push_back(LBCast);
3648 llvm::Value *UBCast = CGF.
Builder.CreateIntCast(
3650 CapturedVars.push_back(UBCast);
3661 bool HasCancel =
false;
3663 if (
const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
3664 HasCancel = D->hasCancel();
3665 else if (
const auto *D = dyn_cast<OMPDistributeParallelForDirective>(&S))
3666 HasCancel = D->hasCancel();
3667 else if (
const auto *D =
3668 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S))
3669 HasCancel = D->hasCancel();
3679 CGInlinedWorksharingLoop,
3689 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3690 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3699 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
3700 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute,
CodeGen);
3708 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
3709 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
3719 llvm::Constant *
Addr;
3721 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
3723 assert(Fn &&
Addr &&
"Target device function emission failed.");
3735struct ScheduleKindModifiersTy {
3742 : Kind(Kind), M1(M1), M2(M2) {}
3758 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
3766 bool HasLastprivateClause;
3769 OMPLoopScope PreInitScope(*
this, S);
3774 llvm::BasicBlock *ContBlock =
nullptr;
3781 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
3788 bool Ordered =
false;
3789 if (
const auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) {
3790 if (OrderedClause->getNumForLoops())
3800 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*
this, S);
3801 LValue LB = Bounds.first;
3802 LValue UB = Bounds.second;
3816 CGM.getOpenMPRuntime().emitBarrierCall(
3817 *
this, S.getBeginLoc(), OMPD_unknown,
false,
3822 *
this, S,
EmitLValue(S.getIterationVariable()));
3829 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
3832 const Expr *ChunkExpr =
nullptr;
3834 if (
const auto *
C = S.getSingleClause<OMPScheduleClause>()) {
3835 ScheduleKind.
Schedule =
C->getScheduleKind();
3836 ScheduleKind.
M1 =
C->getFirstScheduleModifier();
3837 ScheduleKind.
M2 =
C->getSecondScheduleModifier();
3838 ChunkExpr =
C->getChunkSize();
3841 CGM.getOpenMPRuntime().getDefaultScheduleAndChunk(
3842 *
this, S, ScheduleKind.
Schedule, ChunkExpr);
3844 bool HasChunkSizeOne =
false;
3845 llvm::Value *Chunk =
nullptr;
3849 S.getIterationVariable()->getType(),
3853 llvm::APSInt EvaluatedChunk =
Result.Val.getInt();
3854 HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
3863 bool StaticChunkedOne =
3865 Chunk !=
nullptr) &&
3869 (ScheduleKind.
Schedule == OMPC_SCHEDULE_static &&
3870 !(ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
3871 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)) ||
3872 ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
3873 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
3875 Chunk !=
nullptr) ||
3876 StaticChunkedOne) &&
3886 if (
C->getKind() == OMPC_ORDER_concurrent)
3890 [IVSize, IVSigned, Ordered, IL, LB, UB, ST, StaticChunkedOne, Chunk,
3899 IVSize, IVSigned, Ordered, IL.getAddress(), LB.getAddress(),
3900 UB.getAddress(), ST.getAddress(),
3901 StaticChunkedOne ? Chunk :
nullptr);
3903 CGF, S.getBeginLoc(), EKind, ScheduleKind, StaticInit);
3905 if (!StaticChunkedOne)
3924 StaticChunkedOne ? S.getCombinedParForInDistCond()
3926 StaticChunkedOne ? S.getDistInc() : S.getInc(),
3927 [&S,
LoopExit](CodeGenFunction &CGF) {
3928 emitOMPLoopBodyWithStopPoint(CGF, S, LoopExit);
3930 [](CodeGenFunction &) {});
3934 auto &&
CodeGen = [&S](CodeGenFunction &CGF) {
3938 OMPCancelStack.emitExit(*
this, EKind,
CodeGen);
3945 LoopArguments.DKind = OMPD_for;
3946 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
3947 LoopArguments, CGDispatchBounds);
3951 return CGF.
Builder.CreateIsNotNull(
3957 ? OMPD_parallel_for_simd
3961 *
this, S, [IL, &S](CodeGenFunction &CGF) {
3962 return CGF.
Builder.CreateIsNotNull(
3966 if (HasLastprivateClause)
3972 return CGF.
Builder.CreateIsNotNull(
3983 return HasLastprivateClause;
3989static std::pair<LValue, LValue>
4003static std::pair<llvm::Value *, llvm::Value *>
4007 const Expr *IVExpr = LS.getIterationVariable();
4009 llvm::Value *LBVal = CGF.
Builder.getIntN(IVSize, 0);
4011 return {LBVal, UBVal};
4023 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
4024 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4025 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4030 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4031 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4032 "Only inscan reductions are expected.");
4033 Shareds.append(
C->varlist_begin(),
C->varlist_end());
4034 Privates.append(
C->privates().begin(),
C->privates().end());
4035 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
4036 CopyArrayTemps.append(
C->copy_array_temps().begin(),
4037 C->copy_array_temps().end());
4045 auto *ITA = CopyArrayTemps.begin();
4050 if (PrivateVD->getType()->isVariablyModifiedType()) {
4075 llvm::function_ref<llvm::Value *(
CodeGenFunction &)> NumIteratorsGen) {
4076 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4077 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4084 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4085 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4086 "Only inscan reductions are expected.");
4087 Shareds.append(
C->varlist_begin(),
C->varlist_end());
4088 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
4089 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
4090 Privates.append(
C->privates().begin(),
C->privates().end());
4091 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
4092 CopyArrayElems.append(
C->copy_array_elems().begin(),
4093 C->copy_array_elems().end());
4097 llvm::Value *OMPLast = CGF.
Builder.CreateNSWSub(
4098 OMPScanNumIterations,
4099 llvm::ConstantInt::get(CGF.
SizeTy, 1,
false));
4100 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
4102 const Expr *OrigExpr = Shareds[I];
4103 const Expr *CopyArrayElem = CopyArrayElems[I];
4110 LValue SrcLVal = CGF.
EmitLValue(CopyArrayElem);
4112 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
4142 llvm::Value *OMPScanNumIterations = CGF.
Builder.CreateIntCast(
4143 NumIteratorsGen(CGF), CGF.
SizeTy,
false);
4149 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
4150 assert(
C->getModifier() == OMPC_REDUCTION_inscan &&
4151 "Only inscan reductions are expected.");
4152 Privates.append(
C->privates().begin(),
C->privates().end());
4153 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
4154 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
4155 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
4156 CopyArrayElems.append(
C->copy_array_elems().begin(),
4157 C->copy_array_elems().end());
4172 auto &&
CodeGen = [&S, OMPScanNumIterations, &LHSs, &RHSs, &CopyArrayElems,
4179 llvm::BasicBlock *InputBB = CGF.Builder.GetInsertBlock();
4180 llvm::BasicBlock *LoopBB = CGF.createBasicBlock(
"omp.outer.log.scan.body");
4181 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
"omp.outer.log.scan.exit");
4183 CGF.CGM.getIntrinsic(llvm::Intrinsic::log2, CGF.DoubleTy);
4185 CGF.Builder.CreateUIToFP(OMPScanNumIterations, CGF.DoubleTy);
4186 llvm::Value *LogVal = CGF.EmitNounwindRuntimeCall(F, Arg);
4187 F = CGF.CGM.getIntrinsic(llvm::Intrinsic::ceil, CGF.DoubleTy);
4188 LogVal = CGF.EmitNounwindRuntimeCall(F, LogVal);
4189 LogVal = CGF.Builder.CreateFPToUI(LogVal, CGF.IntTy);
4190 llvm::Value *NMin1 = CGF.Builder.CreateNUWSub(
4191 OMPScanNumIterations, llvm::ConstantInt::get(CGF.SizeTy, 1));
4193 CGF.EmitBlock(LoopBB);
4194 auto *Counter = CGF.Builder.CreatePHI(CGF.IntTy, 2);
4196 auto *Pow2K = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
4197 Counter->addIncoming(llvm::ConstantInt::get(CGF.IntTy, 0), InputBB);
4198 Pow2K->addIncoming(llvm::ConstantInt::get(CGF.SizeTy, 1), InputBB);
4201 llvm::BasicBlock *InnerLoopBB =
4202 CGF.createBasicBlock(
"omp.inner.log.scan.body");
4203 llvm::BasicBlock *InnerExitBB =
4204 CGF.createBasicBlock(
"omp.inner.log.scan.exit");
4205 llvm::Value *CmpI = CGF.Builder.CreateICmpUGE(NMin1, Pow2K);
4206 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4207 CGF.EmitBlock(InnerLoopBB);
4208 auto *IVal = CGF.Builder.CreatePHI(CGF.SizeTy, 2);
4209 IVal->addIncoming(NMin1, LoopBB);
4212 auto *ILHS = LHSs.begin();
4213 auto *IRHS = RHSs.begin();
4214 for (
const Expr *CopyArrayElem : CopyArrayElems) {
4224 LHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4229 llvm::Value *OffsetIVal = CGF.Builder.CreateNUWSub(IVal, Pow2K);
4235 RHSAddr = CGF.EmitLValue(CopyArrayElem).getAddress();
4242 CGF.CGM.getOpenMPRuntime().emitReduction(
4243 CGF, S.getEndLoc(),
Privates, LHSs, RHSs, ReductionOps,
4247 llvm::Value *NextIVal =
4248 CGF.Builder.CreateNUWSub(IVal, llvm::ConstantInt::get(CGF.SizeTy, 1));
4249 IVal->addIncoming(NextIVal, CGF.Builder.GetInsertBlock());
4250 CmpI = CGF.Builder.CreateICmpUGE(NextIVal, Pow2K);
4251 CGF.Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
4252 CGF.EmitBlock(InnerExitBB);
4254 CGF.Builder.CreateNUWAdd(Counter, llvm::ConstantInt::get(CGF.IntTy, 1));
4255 Counter->addIncoming(
Next, CGF.Builder.GetInsertBlock());
4257 llvm::Value *NextPow2K =
4258 CGF.Builder.CreateShl(Pow2K, 1,
"",
true);
4259 Pow2K->addIncoming(NextPow2K, CGF.Builder.GetInsertBlock());
4260 llvm::Value *
Cmp = CGF.Builder.CreateICmpNE(
Next, LogVal);
4261 CGF.Builder.CreateCondBr(
Cmp, LoopBB, ExitBB);
4263 CGF.EmitBlock(ExitBB);
4269 CGF, S.getBeginLoc(), OMPD_unknown,
false,
4272 RegionCodeGenTy RCG(CodeGen);
4283 bool HasLastprivates;
4285 if (llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4286 [](
const OMPReductionClause *
C) {
4287 return C->getModifier() == OMPC_REDUCTION_inscan;
4291 OMPLoopScope LoopScope(CGF, S);
4294 const auto &&FirstGen = [&S, HasCancel, EKind](
CodeGenFunction &CGF) {
4303 const auto &&SecondGen = [&S, HasCancel, EKind,
4321 return HasLastprivates;
4334 if (
auto *SC = dyn_cast<OMPScheduleClause>(
C)) {
4339 switch (SC->getScheduleKind()) {
4340 case OMPC_SCHEDULE_auto:
4341 case OMPC_SCHEDULE_dynamic:
4342 case OMPC_SCHEDULE_runtime:
4343 case OMPC_SCHEDULE_guided:
4344 case OMPC_SCHEDULE_static:
4357static llvm::omp::ScheduleKind
4359 switch (ScheduleClauseKind) {
4361 return llvm::omp::OMP_SCHEDULE_Default;
4362 case OMPC_SCHEDULE_auto:
4363 return llvm::omp::OMP_SCHEDULE_Auto;
4364 case OMPC_SCHEDULE_dynamic:
4365 return llvm::omp::OMP_SCHEDULE_Dynamic;
4366 case OMPC_SCHEDULE_guided:
4367 return llvm::omp::OMP_SCHEDULE_Guided;
4368 case OMPC_SCHEDULE_runtime:
4369 return llvm::omp::OMP_SCHEDULE_Runtime;
4370 case OMPC_SCHEDULE_static:
4371 return llvm::omp::OMP_SCHEDULE_Static;
4373 llvm_unreachable(
"Unhandled schedule kind");
4380 bool HasLastprivates =
false;
4383 auto &&
CodeGen = [&S, &
CGM, HasCancel, &HasLastprivates,
4386 if (UseOMPIRBuilder) {
4387 bool NeedsBarrier = !S.getSingleClause<OMPNowaitClause>();
4389 llvm::omp::ScheduleKind SchedKind = llvm::omp::OMP_SCHEDULE_Default;
4390 llvm::Value *ChunkSize =
nullptr;
4391 if (
auto *SchedClause = S.getSingleClause<OMPScheduleClause>()) {
4394 if (
const Expr *ChunkSizeExpr = SchedClause->getChunkSize())
4399 const Stmt *Inner = S.getRawStmt();
4400 llvm::CanonicalLoopInfo *CLI =
4403 llvm::OpenMPIRBuilder &OMPBuilder =
4405 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4407 cantFail(OMPBuilder.applyWorkshareLoop(
4408 CGF.
Builder.getCurrentDebugLocation(), CLI, AllocaIP, NeedsBarrier,
4409 SchedKind, ChunkSize,
false,
4420 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
4425 if (!UseOMPIRBuilder) {
4427 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4439 bool HasLastprivates =
false;
4440 auto &&
CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
4447 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4448 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd,
CodeGen);
4452 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
4453 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_for);
4460 llvm::Value *
Init =
nullptr) {
4467void CodeGenFunction::EmitSections(
const OMPExecutableDirective &S) {
4468 const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
4469 const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt);
4470 bool HasLastprivates =
false;
4472 auto &&CodeGen = [&S, CapturedStmt, CS, EKind,
4473 &HasLastprivates](CodeGenFunction &CGF, PrePostActionTy &) {
4474 const ASTContext &
C = CGF.getContext();
4475 QualType KmpInt32Ty =
4476 C.getIntTypeForBitwidth(32, 1);
4479 CGF.Builder.getInt32(0));
4480 llvm::ConstantInt *GlobalUBVal = CS !=
nullptr
4481 ? CGF.Builder.getInt32(CS->size() - 1)
4482 : CGF.Builder.getInt32(0);
4486 CGF.Builder.getInt32(1));
4488 CGF.Builder.getInt32(0));
4491 OpaqueValueExpr IVRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4492 CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
4493 OpaqueValueExpr UBRefExpr(S.getBeginLoc(), KmpInt32Ty,
VK_LValue);
4494 CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
4498 S.getBeginLoc(), FPOptionsOverride());
4502 S.getBeginLoc(),
true, FPOptionsOverride());
4503 auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
4515 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".omp.sections.exit");
4516 llvm::SwitchInst *SwitchStmt =
4517 CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.
getBeginLoc()),
4518 ExitBB, CS ==
nullptr ? 1 : CS->size());
4520 unsigned CaseNumber = 0;
4521 for (
const Stmt *SubStmt : CS->
children()) {
4522 auto CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4523 CGF.EmitBlock(CaseBB);
4524 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
4525 CGF.EmitStmt(SubStmt);
4526 CGF.EmitBranch(ExitBB);
4530 llvm::BasicBlock *CaseBB = CGF.createBasicBlock(
".omp.sections.case");
4531 CGF.EmitBlock(CaseBB);
4532 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
4533 CGF.EmitStmt(CapturedStmt);
4534 CGF.EmitBranch(ExitBB);
4536 CGF.EmitBlock(ExitBB,
true);
4539 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
4540 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
4544 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
4548 CGF.EmitOMPPrivateClause(S, LoopScope);
4549 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(CGF, S, IV);
4550 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
4551 CGF.EmitOMPReductionClauseInit(S, LoopScope);
4552 (void)LoopScope.Privatize();
4554 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
4557 OpenMPScheduleTy ScheduleKind;
4558 ScheduleKind.
Schedule = OMPC_SCHEDULE_static;
4559 CGOpenMPRuntime::StaticRTInput StaticInit(
4560 32,
true,
false, IL.getAddress(),
4561 LB.getAddress(), UB.getAddress(), ST.getAddress());
4562 CGF.CGM.getOpenMPRuntime().emitForStaticInit(CGF, S.
getBeginLoc(), EKind,
4563 ScheduleKind, StaticInit);
4565 llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.
getBeginLoc());
4566 llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
4567 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
4568 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
4570 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.
getBeginLoc()), IV);
4572 CGF.EmitOMPInnerLoop(S,
false,
Cond, Inc, BodyGen,
4573 [](CodeGenFunction &) {});
4575 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
4576 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.
getEndLoc(),
4579 CGF.OMPCancelStack.emitExit(CGF, EKind, CodeGen);
4580 CGF.EmitOMPReductionClauseFinal(S, OMPD_parallel);
4583 return CGF.
Builder.CreateIsNotNull(
4588 if (HasLastprivates)
4595 bool HasCancel =
false;
4596 if (
auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
4597 HasCancel = OSD->hasCancel();
4598 else if (
auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
4599 HasCancel = OPSD->hasCancel();
4601 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_sections, CodeGen,
4606 if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) {
4624 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4629 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4630 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_scope,
CodeGen);
4633 if (!S.getSingleClause<OMPNowaitClause>()) {
4634 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_scope);
4641 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4642 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4643 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4644 using BodyGenCallbackTy = llvm::OpenMPIRBuilder::StorableBodyGenCallbackTy;
4646 auto FiniCB = [](InsertPointTy IP) {
4649 return llvm::Error::success();
4652 const CapturedStmt *ICS = S.getInnermostCapturedStmt();
4658 auto SectionCB = [
this, SubStmt](InsertPointTy AllocaIP,
4659 InsertPointTy CodeGenIP) {
4661 *
this, SubStmt, AllocaIP, CodeGenIP,
"section");
4662 return llvm::Error::success();
4664 SectionCBVector.push_back(SectionCB);
4667 auto SectionCB = [
this,
CapturedStmt](InsertPointTy AllocaIP,
4668 InsertPointTy CodeGenIP) {
4671 return llvm::Error::success();
4673 SectionCBVector.push_back(SectionCB);
4680 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
4681 llvm::Value &, llvm::Value &Val, llvm::Value *&ReplVal) {
4691 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP(
4693 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4694 cantFail(OMPBuilder.createSections(
4695 Builder, AllocaIP, SectionCBVector, PrivCB, FiniCB, S.hasCancel(),
4696 S.getSingleClause<OMPNowaitClause>()));
4703 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4707 if (!S.getSingleClause<OMPNowaitClause>()) {
4708 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(),
4716 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4717 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4718 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4720 const Stmt *SectionRegionBodyStmt = S.getAssociatedStmt();
4721 auto FiniCB = [
this](InsertPointTy IP) {
4723 return llvm::Error::success();
4726 auto BodyGenCB = [SectionRegionBodyStmt,
this](InsertPointTy AllocaIP,
4727 InsertPointTy CodeGenIP) {
4729 *
this, SectionRegionBodyStmt, AllocaIP, CodeGenIP,
"section");
4730 return llvm::Error::success();
4735 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4736 cantFail(OMPBuilder.createSection(
Builder, BodyGenCB, FiniCB));
4756 CopyprivateVars.append(
C->varlist_begin(),
C->varlist_end());
4757 DestExprs.append(
C->destination_exprs().begin(),
4758 C->destination_exprs().end());
4759 SrcExprs.append(
C->source_exprs().begin(),
C->source_exprs().end());
4760 AssignmentOps.append(
C->assignment_ops().begin(),
4761 C->assignment_ops().end());
4770 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
4775 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
4776 CGM.getOpenMPRuntime().emitSingleRegion(*
this,
CodeGen, S.getBeginLoc(),
4777 CopyprivateVars, DestExprs,
4778 SrcExprs, AssignmentOps);
4782 if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) {
4783 CGM.getOpenMPRuntime().emitBarrierCall(
4784 *
this, S.getBeginLoc(),
4785 S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);
4800 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4801 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4802 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4804 const Stmt *MasterRegionBodyStmt = S.getAssociatedStmt();
4806 auto FiniCB = [
this](InsertPointTy IP) {
4808 return llvm::Error::success();
4811 auto BodyGenCB = [MasterRegionBodyStmt,
this](InsertPointTy AllocaIP,
4812 InsertPointTy CodeGenIP) {
4814 *
this, MasterRegionBodyStmt, AllocaIP, CodeGenIP,
"master");
4815 return llvm::Error::success();
4820 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4821 cantFail(OMPBuilder.createMaster(
Builder, BodyGenCB, FiniCB));
4836 Expr *Filter =
nullptr;
4838 Filter = FilterClause->getThreadID();
4844 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4845 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4846 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4848 const Stmt *MaskedRegionBodyStmt = S.getAssociatedStmt();
4849 const Expr *Filter =
nullptr;
4851 Filter = FilterClause->getThreadID();
4852 llvm::Value *FilterVal = Filter
4854 : llvm::ConstantInt::get(
CGM.Int32Ty, 0);
4856 auto FiniCB = [
this](InsertPointTy IP) {
4858 return llvm::Error::success();
4861 auto BodyGenCB = [MaskedRegionBodyStmt,
this](InsertPointTy AllocaIP,
4862 InsertPointTy CodeGenIP) {
4864 *
this, MaskedRegionBodyStmt, AllocaIP, CodeGenIP,
"masked");
4865 return llvm::Error::success();
4870 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
4871 OMPBuilder.createMasked(
Builder, BodyGenCB, FiniCB, FilterVal));
4882 if (
CGM.getLangOpts().OpenMPIRBuilder) {
4883 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
4884 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
4886 const Stmt *CriticalRegionBodyStmt = S.getAssociatedStmt();
4887 const Expr *Hint =
nullptr;
4888 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4889 Hint = HintClause->getHint();
4894 llvm::Value *HintInst =
nullptr;
4899 auto FiniCB = [
this](InsertPointTy IP) {
4901 return llvm::Error::success();
4904 auto BodyGenCB = [CriticalRegionBodyStmt,
this](InsertPointTy AllocaIP,
4905 InsertPointTy CodeGenIP) {
4907 *
this, CriticalRegionBodyStmt, AllocaIP, CodeGenIP,
"critical");
4908 return llvm::Error::success();
4913 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
4914 cantFail(OMPBuilder.createCritical(
Builder, BodyGenCB, FiniCB,
4915 S.getDirectiveName().getAsString(),
4924 CGF.
EmitStmt(S.getAssociatedStmt());
4926 const Expr *Hint =
nullptr;
4927 if (
const auto *HintClause = S.getSingleClause<
OMPHintClause>())
4928 Hint = HintClause->getHint();
4931 CGM.getOpenMPRuntime().emitCriticalRegion(*
this,
4932 S.getDirectiveName().getAsString(),
4933 CodeGen, S.getBeginLoc(), Hint);
4937 const OMPParallelForDirective &S) {
4946 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
4950 OMPLoopScope LoopScope(CGF, S);
4953 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4954 [](
const OMPReductionClause *
C) {
4955 return C->getModifier() == OMPC_REDUCTION_inscan;
4971 const OMPParallelForSimdDirective &S) {
4980 const auto &&NumIteratorsGen = [&S](CodeGenFunction &CGF) {
4984 OMPLoopScope LoopScope(CGF, S);
4987 bool IsInscan = llvm::any_of(S.getClausesOfKind<OMPReductionClause>(),
4988 [](
const OMPReductionClause *
C) {
4989 return C->getModifier() == OMPC_REDUCTION_inscan;
5005 const OMPParallelMasterDirective &S) {
5025 [](CodeGenFunction &) {
return nullptr; });
5032 const OMPParallelMaskedDirective &S) {
5052 [](CodeGenFunction &) {
return nullptr; });
5059 const OMPParallelSectionsDirective &S) {
5065 CGF.EmitSections(S);
5079class CheckVarsEscapingUntiedTaskDeclContext final
5084 explicit CheckVarsEscapingUntiedTaskDeclContext() =
default;
5085 ~CheckVarsEscapingUntiedTaskDeclContext() =
default;
5086 void VisitDeclStmt(
const DeclStmt *S) {
5091 if (
const auto *VD = dyn_cast_or_null<VarDecl>(D))
5093 PrivateDecls.push_back(VD);
5097 void VisitCapturedStmt(
const CapturedStmt *) {}
5099 void VisitBlockExpr(
const BlockExpr *) {}
5100 void VisitStmt(
const Stmt *S) {
5103 for (
const Stmt *Child : S->
children())
5109 ArrayRef<const VarDecl *> getPrivateDecls()
const {
return PrivateDecls; }
5117 bool OmpAllMemory =
false;
5120 return C->getDependencyKind() == OMPC_DEPEND_outallmemory ||
5121 C->getDependencyKind() == OMPC_DEPEND_inoutallmemory;
5123 OmpAllMemory =
true;
5128 Data.Dependences.emplace_back(OMPC_DEPEND_outallmemory,
5137 if (Kind == OMPC_DEPEND_outallmemory || Kind == OMPC_DEPEND_inoutallmemory)
5139 if (OmpAllMemory && (Kind == OMPC_DEPEND_out || Kind == OMPC_DEPEND_inout))
5142 Data.Dependences.emplace_back(
C->getDependencyKind(),
C->getModifier());
5143 DD.
DepExprs.append(
C->varlist_begin(),
C->varlist_end());
5152 const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion);
5154 auto PartId = std::next(I);
5155 auto TaskT = std::next(I, 4);
5160 const Expr *
Cond = Clause->getCondition();
5163 Data.Final.setInt(CondConstant);
5168 Data.Final.setInt(
false);
5172 const Expr *Prio = Clause->getPriority();
5173 Data.Priority.setInt(
true);
5181 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
5183 for (
const auto *
C : S.getClausesOfKind<OMPPrivateClause>()) {
5184 auto IRef =
C->varlist_begin();
5185 for (
const Expr *IInit :
C->private_copies()) {
5187 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
5188 Data.PrivateVars.push_back(*IRef);
5189 Data.PrivateCopies.push_back(IInit);
5194 EmittedAsPrivate.clear();
5196 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5197 auto IRef =
C->varlist_begin();
5198 auto IElemInitRef =
C->inits().begin();
5199 for (
const Expr *IInit :
C->private_copies()) {
5201 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
5202 Data.FirstprivateVars.push_back(*IRef);
5203 Data.FirstprivateCopies.push_back(IInit);
5204 Data.FirstprivateInits.push_back(*IElemInitRef);
5211 llvm::MapVector<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
5212 for (
const auto *
C : S.getClausesOfKind<OMPLastprivateClause>()) {
5213 auto IRef =
C->varlist_begin();
5214 auto ID =
C->destination_exprs().begin();
5215 for (
const Expr *IInit :
C->private_copies()) {
5217 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
5218 Data.LastprivateVars.push_back(*IRef);
5219 Data.LastprivateCopies.push_back(IInit);
5221 LastprivateDstsOrigs.insert(
5230 for (
const auto *
C : S.getClausesOfKind<OMPReductionClause>()) {
5231 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5232 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5233 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5234 Data.ReductionOps.append(
C->reduction_ops().begin(),
5235 C->reduction_ops().end());
5236 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5237 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5239 Data.Reductions =
CGM.getOpenMPRuntime().emitTaskReductionInit(
5240 *
this, S.getBeginLoc(), LHSs, RHSs,
Data);
5245 CheckVarsEscapingUntiedTaskDeclContext Checker;
5246 Checker.Visit(S.getInnermostCapturedStmt()->getCapturedStmt());
5247 Data.PrivateLocals.append(Checker.getPrivateDecls().begin(),
5248 Checker.getPrivateDecls().end());
5250 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
5251 CapturedRegion](CodeGenFunction &CGF,
5253 llvm::MapVector<CanonicalDeclPtr<const VarDecl>,
5254 std::pair<Address, Address>>
5259 if (
auto *DI = CGF.getDebugInfo()) {
5260 llvm::SmallDenseMap<const VarDecl *, FieldDecl *> CaptureFields =
5261 CGF.CapturedStmtInfo->getCaptureFields();
5262 llvm::Value *ContextValue = CGF.CapturedStmtInfo->getContextValue();
5263 if (CaptureFields.size() && ContextValue) {
5264 unsigned CharWidth = CGF.getContext().getCharWidth();
5278 for (
auto It = CaptureFields.begin(); It != CaptureFields.end(); ++It) {
5279 const VarDecl *SharedVar = It->first;
5282 CGF.getContext().getASTRecordLayout(CaptureRecord);
5285 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5286 (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue,
5287 CGF.Builder,
false);
5290 auto UpdateExpr = [](llvm::LLVMContext &Ctx,
auto *
Declare,
5295 Ops.push_back(llvm::dwarf::DW_OP_plus_uconst);
5296 Ops.push_back(Offset);
5298 Ops.push_back(llvm::dwarf::DW_OP_deref);
5299 Declare->setExpression(llvm::DIExpression::get(Ctx, Ops));
5301 llvm::Instruction &
Last = CGF.Builder.GetInsertBlock()->back();
5302 if (
auto DDI = dyn_cast<llvm::DbgVariableIntrinsic>(&
Last))
5303 UpdateExpr(DDI->getContext(), DDI, Offset);
5306 assert(!
Last.isTerminator() &&
"unexpected terminator");
5308 CGF.Builder.GetInsertBlock()->getTrailingDbgRecords()) {
5309 for (llvm::DbgVariableRecord &DVR : llvm::reverse(
5310 llvm::filterDbgVars(Marker->getDbgRecordRange()))) {
5311 UpdateExpr(
Last.getContext(), &DVR, Offset);
5319 if (!
Data.PrivateVars.empty() || !
Data.FirstprivateVars.empty() ||
5320 !
Data.LastprivateVars.empty() || !
Data.PrivateLocals.empty()) {
5321 enum { PrivatesParam = 2, CopyFnParam = 3 };
5322 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5324 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5330 CallArgs.push_back(PrivatesPtr);
5331 ParamTypes.push_back(PrivatesPtr->getType());
5332 for (
const Expr *E :
Data.PrivateVars) {
5335 CGF.getContext().getPointerType(E->
getType()),
".priv.ptr.addr");
5336 PrivatePtrs.emplace_back(VD, PrivatePtr);
5338 ParamTypes.push_back(PrivatePtr.
getType());
5340 for (
const Expr *E :
Data.FirstprivateVars) {
5343 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
5344 ".firstpriv.ptr.addr");
5345 PrivatePtrs.emplace_back(VD, PrivatePtr);
5346 FirstprivatePtrs.emplace_back(VD, PrivatePtr);
5348 ParamTypes.push_back(PrivatePtr.
getType());
5350 for (
const Expr *E :
Data.LastprivateVars) {
5353 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
5354 ".lastpriv.ptr.addr");
5355 PrivatePtrs.emplace_back(VD, PrivatePtr);
5357 ParamTypes.push_back(PrivatePtr.
getType());
5362 Ty = CGF.getContext().getPointerType(Ty);
5364 Ty = CGF.getContext().getPointerType(Ty);
5366 CGF.getContext().getPointerType(Ty),
".local.ptr.addr");
5367 auto Result = UntiedLocalVars.insert(
5370 if (
Result.second ==
false)
5371 *
Result.first = std::make_pair(
5374 ParamTypes.push_back(PrivatePtr.
getType());
5376 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5378 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5379 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5380 for (
const auto &Pair : LastprivateDstsOrigs) {
5384 CGF.CapturedStmtInfo->lookup(OrigVD) !=
nullptr,
5386 Pair.second->getExprLoc());
5387 Scope.addPrivate(Pair.first, CGF.EmitLValue(&DRE).getAddress());
5389 for (
const auto &Pair : PrivatePtrs) {
5391 CGF.Builder.CreateLoad(Pair.second),
5392 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5393 CGF.getContext().getDeclAlign(Pair.first));
5394 Scope.addPrivate(Pair.first, Replacement);
5395 if (
auto *DI = CGF.getDebugInfo())
5396 if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
5397 (void)DI->EmitDeclareOfAutoVariable(
5398 Pair.first, Pair.second.getBasePointer(), CGF.Builder,
5403 for (
auto &Pair : UntiedLocalVars) {
5404 QualType VDType = Pair.first->getType().getNonReferenceType();
5405 if (Pair.first->getType()->isLValueReferenceType())
5406 VDType = CGF.getContext().getPointerType(VDType);
5408 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5411 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(VDType)),
5412 CGF.getPointerAlign());
5413 Pair.second.first = Replacement;
5414 Ptr = CGF.Builder.CreateLoad(Replacement);
5415 Replacement =
Address(Ptr, CGF.ConvertTypeForMem(VDType),
5416 CGF.getContext().getDeclAlign(Pair.first));
5417 Pair.second.second = Replacement;
5419 llvm::Value *Ptr = CGF.Builder.CreateLoad(Pair.second.first);
5420 Address Replacement(Ptr, CGF.ConvertTypeForMem(VDType),
5421 CGF.getContext().getDeclAlign(Pair.first));
5422 Pair.second.first = Replacement;
5426 if (
Data.Reductions) {
5428 for (
const auto &Pair : FirstprivatePtrs) {
5430 CGF.Builder.CreateLoad(Pair.second),
5431 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5432 CGF.getContext().getDeclAlign(Pair.first));
5433 FirstprivateScope.
addPrivate(Pair.first, Replacement);
5436 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5438 Data.ReductionCopies,
Data.ReductionOps);
5439 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
5441 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5447 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5449 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5452 CGF.EmitScalarConversion(Replacement.emitRawPointer(CGF),
5453 CGF.getContext().VoidPtrTy,
5454 CGF.getContext().getPointerType(
5455 Data.ReductionCopies[Cnt]->getType()),
5456 Data.ReductionCopies[Cnt]->getExprLoc()),
5457 CGF.ConvertTypeForMem(
Data.ReductionCopies[Cnt]->getType()),
5458 Replacement.getAlignment());
5464 (void)
Scope.Privatize();
5469 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5470 auto IPriv =
C->privates().begin();
5471 auto IRed =
C->reduction_ops().begin();
5472 auto ITD =
C->taskgroup_descriptors().begin();
5473 for (
const Expr *Ref :
C->varlist()) {
5474 InRedVars.emplace_back(Ref);
5475 InRedPrivs.emplace_back(*IPriv);
5476 InRedOps.emplace_back(*IRed);
5477 TaskgroupDescriptors.emplace_back(*ITD);
5478 std::advance(IPriv, 1);
5479 std::advance(IRed, 1);
5480 std::advance(ITD, 1);
5486 if (!InRedVars.empty()) {
5488 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5496 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
5498 llvm::Value *ReductionsPtr;
5499 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5500 ReductionsPtr = CGF.EmitLoadOfScalar(CGF.EmitLValue(TRExpr),
5501 TRExpr->getExprLoc());
5503 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5505 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
5508 CGF.EmitScalarConversion(
5509 Replacement.emitRawPointer(CGF), CGF.getContext().VoidPtrTy,
5510 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
5511 InRedPrivs[Cnt]->getExprLoc()),
5512 CGF.ConvertTypeForMem(InRedPrivs[Cnt]->getType()),
5513 Replacement.getAlignment());
5526 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5527 S, *I, *PartId, *TaskT, EKind,
CodeGen,
Data.Tied,
Data.NumberOfParts);
5528 OMPLexicalScope
Scope(*
this, S, std::nullopt,
5531 TaskGen(*
this, OutlinedFn,
Data);
5548 QualType ElemType =
C.getBaseElementType(Ty);
5558 Data.FirstprivateVars.emplace_back(OrigRef);
5559 Data.FirstprivateCopies.emplace_back(PrivateRef);
5560 Data.FirstprivateInits.emplace_back(InitRef);
5573 auto PartId = std::next(I);
5574 auto TaskT = std::next(I, 4);
5577 Data.Final.setInt(
false);
5579 for (
const auto *
C : S.getClausesOfKind<OMPFirstprivateClause>()) {
5580 auto IRef =
C->varlist_begin();
5581 auto IElemInitRef =
C->inits().begin();
5582 for (
auto *IInit :
C->private_copies()) {
5583 Data.FirstprivateVars.push_back(*IRef);
5584 Data.FirstprivateCopies.push_back(IInit);
5585 Data.FirstprivateInits.push_back(*IElemInitRef);
5592 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5593 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5594 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5595 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5596 Data.ReductionOps.append(
C->reduction_ops().begin(),
5597 C->reduction_ops().end());
5598 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5599 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5614 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5616 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5628 if (!isa_and_nonnull<llvm::ConstantPointerNull>(
5631 getContext(),
Data, BaseAndPointerAndMapperType, CD, S.getBeginLoc());
5638 auto &&
CodeGen = [&
Data, &S, CS, &BodyGen, BPVD, PVD, SVD, MVD, EKind,
5642 if (!
Data.FirstprivateVars.empty()) {
5643 enum { PrivatesParam = 2, CopyFnParam = 3 };
5644 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
5646 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
5652 CallArgs.push_back(PrivatesPtr);
5653 ParamTypes.push_back(PrivatesPtr->getType());
5654 for (
const Expr *E :
Data.FirstprivateVars) {
5657 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
5658 ".firstpriv.ptr.addr");
5659 PrivatePtrs.emplace_back(VD, PrivatePtr);
5661 ParamTypes.push_back(PrivatePtr.
getType());
5663 auto *CopyFnTy = llvm::FunctionType::get(CGF.Builder.getVoidTy(),
5665 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
5666 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
5667 for (
const auto &Pair : PrivatePtrs) {
5669 CGF.Builder.CreateLoad(Pair.second),
5670 CGF.ConvertTypeForMem(Pair.first->getType().getNonReferenceType()),
5671 CGF.getContext().getDeclAlign(Pair.first));
5672 Scope.addPrivate(Pair.first, Replacement);
5675 CGF.processInReduction(S,
Data, CGF, CS,
Scope);
5678 CGF.GetAddrOfLocalVar(BPVD), 0);
5680 CGF.GetAddrOfLocalVar(PVD), 0);
5681 InputInfo.
SizesArray = CGF.Builder.CreateConstArrayGEP(
5682 CGF.GetAddrOfLocalVar(SVD), 0);
5685 InputInfo.
MappersArray = CGF.Builder.CreateConstArrayGEP(
5686 CGF.GetAddrOfLocalVar(MVD), 0);
5690 OMPLexicalScope LexScope(CGF, S, OMPD_task,
false);
5692 if (CGF.CGM.getLangOpts().OpenMP >= 51 &&
5697 CGF.CGM.getOpenMPRuntime().emitThreadLimitClause(
5698 CGF, TL->getThreadLimit().front(), S.getBeginLoc());
5702 llvm::Function *OutlinedFn =
CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
5703 S, *I, *PartId, *TaskT, EKind,
CodeGen,
true,
5704 Data.NumberOfParts);
5705 llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<OMPNowaitClause>() ? 1 : 0);
5709 CGM.getOpenMPRuntime().emitTaskCall(*
this, S.getBeginLoc(), S, OutlinedFn,
5710 SharedsTy, CapturedStruct, &IfCond,
Data);
5715 CodeGenFunction &CGF,
5719 if (
Data.Reductions) {
5721 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
5723 Data.ReductionCopies,
Data.ReductionOps);
5726 for (
unsigned Cnt = 0, E =
Data.ReductionVars.size(); Cnt < E; ++Cnt) {
5740 Data.ReductionCopies[Cnt]->getType()),
5741 Data.ReductionCopies[Cnt]->getExprLoc()),
5743 Replacement.getAlignment());
5748 (void)
Scope.Privatize();
5753 for (
const auto *
C : S.getClausesOfKind<OMPInReductionClause>()) {
5754 auto IPriv =
C->privates().begin();
5755 auto IRed =
C->reduction_ops().begin();
5756 auto ITD =
C->taskgroup_descriptors().begin();
5757 for (
const Expr *Ref :
C->varlist()) {
5758 InRedVars.emplace_back(Ref);
5759 InRedPrivs.emplace_back(*IPriv);
5760 InRedOps.emplace_back(*IRed);
5761 TaskgroupDescriptors.emplace_back(*ITD);
5762 std::advance(IPriv, 1);
5763 std::advance(IRed, 1);
5764 std::advance(ITD, 1);
5768 if (!InRedVars.empty()) {
5770 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
5778 llvm::Value *ReductionsPtr;
5779 if (
const Expr *TRExpr = TaskgroupDescriptors[Cnt]) {
5783 ReductionsPtr = llvm::ConstantPointerNull::get(CGF.
VoidPtrTy);
5791 InRedPrivs[Cnt]->getExprLoc()),
5793 Replacement.getAlignment());
5807 const Expr *IfCond =
nullptr;
5808 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
5809 if (
C->getNameModifier() == OMPD_unknown ||
5810 C->getNameModifier() == OMPD_task) {
5811 IfCond =
C->getCondition();
5818 Data.Tied = !S.getSingleClause<OMPUntiedClause>();
5822 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
5823 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
5826 SharedsTy, CapturedStruct, IfCond,
5835 const OMPTaskyieldDirective &S) {
5836 CGM.getOpenMPRuntime().emitTaskyieldCall(*
this, S.getBeginLoc());
5840 const OMPMessageClause *MC = S.getSingleClause<OMPMessageClause>();
5841 Expr *ME = MC ? MC->getMessageString() :
nullptr;
5842 const OMPSeverityClause *SC = S.getSingleClause<OMPSeverityClause>();
5843 bool IsFatal =
false;
5844 if (!SC || SC->getSeverityKind() == OMPC_SEVERITY_fatal)
5846 CGM.getOpenMPRuntime().emitErrorCall(*
this, S.getBeginLoc(), ME, IsFatal);
5850 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.getBeginLoc(), OMPD_barrier);
5857 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
5858 CGM.getOpenMPRuntime().emitTaskwaitCall(*
this, S.getBeginLoc(),
Data);
5862 return T.clauses().empty();
5866 const OMPTaskgroupDirective &S) {
5867 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
5869 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
5870 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
5874 auto BodyGenCB = [&,
this](InsertPointTy AllocaIP,
5875 InsertPointTy CodeGenIP) {
5877 EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5878 return llvm::Error::success();
5883 llvm::OpenMPIRBuilder::InsertPointTy AfterIP =
5884 cantFail(OMPBuilder.createTaskgroup(
Builder, AllocaIP, BodyGenCB));
5890 if (
const Expr *E = S.getReductionRef()) {
5894 for (
const auto *
C : S.getClausesOfKind<OMPTaskReductionClause>()) {
5895 Data.ReductionVars.append(
C->varlist_begin(),
C->varlist_end());
5896 Data.ReductionOrigs.append(
C->varlist_begin(),
C->varlist_end());
5897 Data.ReductionCopies.append(
C->privates().begin(),
C->privates().end());
5898 Data.ReductionOps.append(
C->reduction_ops().begin(),
5899 C->reduction_ops().end());
5900 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5901 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5903 llvm::Value *ReductionDesc =
5911 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
5913 CGM.getOpenMPRuntime().emitTaskgroupRegion(*
this,
CodeGen, S.getBeginLoc());
5918 ? llvm::AtomicOrdering::NotAtomic
5919 : llvm::AtomicOrdering::AcquireRelease;
5920 CGM.getOpenMPRuntime().emitFlush(
5923 if (
const auto *FlushClause = S.getSingleClause<
OMPFlushClause>())
5925 FlushClause->varlist_end());
5928 S.getBeginLoc(), AO);
5938 for (
auto &Dep :
Data.Dependences) {
5939 Address DepAddr =
CGM.getOpenMPRuntime().emitDepobjDependClause(
5940 *
this, Dep, DC->getBeginLoc());
5946 CGM.getOpenMPRuntime().emitDestroyClause(*
this, DOLVal, DC->getBeginLoc());
5949 if (
const auto *UC = S.getSingleClause<OMPUpdateClause>()) {
5950 CGM.getOpenMPRuntime().emitUpdateClause(
5951 *
this, DOLVal, UC->getDependencyKind(), UC->getBeginLoc());
5969 for (
const auto *
C : ParentDir.getClausesOfKind<OMPReductionClause>()) {
5970 if (
C->getModifier() != OMPC_REDUCTION_inscan)
5972 Shareds.append(
C->varlist_begin(),
C->varlist_end());
5973 Privates.append(
C->privates().begin(),
C->privates().end());
5974 LHSs.append(
C->lhs_exprs().begin(),
C->lhs_exprs().end());
5975 RHSs.append(
C->rhs_exprs().begin(),
C->rhs_exprs().end());
5976 ReductionOps.append(
C->reduction_ops().begin(),
C->reduction_ops().end());
5977 CopyOps.append(
C->copy_ops().begin(),
C->copy_ops().end());
5978 CopyArrayTemps.append(
C->copy_array_temps().begin(),
5979 C->copy_array_temps().end());
5980 CopyArrayElems.append(
C->copy_array_elems().begin(),
5981 C->copy_array_elems().end());
5983 if (ParentDir.getDirectiveKind() == OMPD_simd ||
6025 : BreakContinueStack.back().ContinueBlock.getBlock());
6036 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6038 const Expr *TempExpr = CopyArrayTemps[I];
6050 CGM.getOpenMPRuntime().emitReduction(
6051 *
this, ParentDir.getEndLoc(),
Privates, LHSs, RHSs, ReductionOps,
6054 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6062 const Expr *TempExpr = CopyArrayTemps[I];
6074 ? BreakContinueStack.back().ContinueBlock.getBlock()
6080 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6086 .getIterationVariable()
6087 ->IgnoreParenImpCasts();
6090 IdxVal = Builder.CreateIntCast(IdxVal,
SizeTy,
false);
6091 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6093 const Expr *OrigExpr = Shareds[I];
6094 const Expr *CopyArrayElem = CopyArrayElems[I];
6095 OpaqueValueMapping IdxMapping(
6108 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6111 EmitBranch(BreakContinueStack.back().ContinueBlock.getBlock());
6117 .getIterationVariable()
6118 ->IgnoreParenImpCasts();
6122 llvm::BasicBlock *ExclusiveExitBB =
nullptr;
6126 llvm::Value *
Cmp =
Builder.CreateIsNull(IdxVal);
6127 Builder.CreateCondBr(
Cmp, ExclusiveExitBB, ContBB);
6130 IdxVal =
Builder.CreateNUWSub(IdxVal, llvm::ConstantInt::get(
SizeTy, 1));
6132 for (
unsigned I = 0, E = CopyArrayElems.size(); I < E; ++I) {
6133 const Expr *PrivateExpr =
Privates[I];
6134 const Expr *OrigExpr = Shareds[I];
6135 const Expr *CopyArrayElem = CopyArrayElems[I];
6144 PrivateExpr->
getType(), DestLVal.getAddress(), SrcLVal.getAddress(),
6168 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
6176 bool HasLastprivateClause =
false;
6179 OMPLoopScope PreInitScope(*
this, S);
6184 llvm::BasicBlock *ContBlock =
nullptr;
6191 emitPreCond(*
this, S, S.getPreCond(), ThenBlock, ContBlock,
6205 ? S.getCombinedLowerBoundVariable()
6206 : S.getLowerBoundVariable())));
6210 ? S.getCombinedUpperBoundVariable()
6211 : S.getUpperBoundVariable())));
6222 CGM.getOpenMPRuntime().emitBarrierCall(
6223 *
this, S.getBeginLoc(), OMPD_unknown,
false,
6235 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
6238 llvm::Value *Chunk =
nullptr;
6241 ScheduleKind =
C->getDistScheduleKind();
6242 if (
const Expr *Ch =
C->getChunkSize()) {
6245 S.getIterationVariable()->getType(),
6250 CGM.getOpenMPRuntime().getDefaultDistScheduleAndChunk(
6251 *
this, S, ScheduleKind, Chunk);
6264 bool StaticChunked =
6268 Chunk !=
nullptr) ||
6273 StaticChunked ? Chunk :
nullptr);
6280 ? S.getCombinedEnsureUpperBound()
6281 : S.getEnsureUpperBound());
6284 ? S.getCombinedInit()
6289 ? S.getCombinedCond()
6293 Cond = S.getCombinedDistCond();
6325 [&S, &LoopScope,
Cond, IncExpr,
LoopExit, &CodeGenLoop,
6328 S, LoopScope.requiresCleanups(),
Cond, IncExpr,
6329 [&S,
LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
6330 CodeGenLoop(CGF, S, LoopExit);
6332 [&S, StaticChunked](CodeGenFunction &CGF) {
6333 if (StaticChunked) {
6334 CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound());
6335 CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound());
6336 CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound());
6337 CGF.EmitIgnoredExpr(S.getCombinedInit());
6347 const OMPLoopArguments LoopArguments = {
6348 LB.getAddress(), UB.getAddress(), ST.getAddress(), IL.getAddress(),
6350 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments,
6355 return CGF.
Builder.CreateIsNotNull(
6365 *
this, S, [IL, &S](CodeGenFunction &CGF) {
6366 return CGF.
Builder.CreateIsNotNull(
6371 if (HasLastprivateClause) {
6394 OMPLexicalScope
Scope(CGF, S, OMPD_unknown);
6403static llvm::Function *
6410 Fn->setDoesNotRecurse();
6414template <
typename T>
6416 llvm::OpenMPIRBuilder::InsertPointTy AllocaIP,
6417 llvm::OpenMPIRBuilder &OMPBuilder) {
6419 unsigned NumLoops =
C->getNumLoops();
6423 for (
unsigned I = 0; I < NumLoops; I++) {
6424 const Expr *CounterVal =
C->getLoopData(I);
6429 StoreValues.emplace_back(StoreValue);
6431 OMPDoacrossKind<T> ODK;
6432 bool IsDependSource = ODK.isSource(
C);
6434 OMPBuilder.createOrderedDepend(CGF.
Builder, AllocaIP, NumLoops,
6435 StoreValues,
".cnt.addr", IsDependSource));
6439 if (
CGM.getLangOpts().OpenMPIRBuilder) {
6440 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
6441 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
6446 assert(!S.hasAssociatedStmt() &&
"No associated statement must be in "
6447 "ordered depend|doacross construct.");
6459 auto FiniCB = [
this](InsertPointTy IP) {
6461 return llvm::Error::success();
6464 auto BodyGenCB = [&S,
C,
this](InsertPointTy AllocaIP,
6465 InsertPointTy CodeGenIP) {
6470 llvm::BasicBlock *FiniBB = splitBBWithSuffix(
6471 Builder,
false,
".ordered.after");
6475 assert(S.getBeginLoc().isValid() &&
6476 "Outlined function call location must be valid.");
6479 OutlinedFn, CapturedVars);
6484 return llvm::Error::success();
6487 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6488 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
6489 OMPBuilder.createOrderedThreadsSimd(
Builder, BodyGenCB, FiniCB, !
C));
6496 assert(!S.hasAssociatedStmt() &&
6497 "No associated statement must be in ordered depend construct.");
6499 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6503 assert(!S.hasAssociatedStmt() &&
6504 "No associated statement must be in ordered doacross construct.");
6506 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
6510 auto &&
CodeGen = [&S,
C,
this](CodeGenFunction &CGF,
6515 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
6517 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
6518 OutlinedFn, CapturedVars);
6524 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
6525 CGM.getOpenMPRuntime().emitOrderedRegion(*
this,
CodeGen, S.getBeginLoc(), !
C);
6532 "DestType must have scalar evaluation kind.");
6533 assert(!Val.
isAggregate() &&
"Must be a scalar or complex.");
6544 "DestType must have complex evaluation kind.");
6553 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
6555 assert(Val.
isComplex() &&
"Must be a scalar or complex.");
6560 Val.
getComplexVal().first, SrcElementType, DestElementType, Loc);
6562 Val.
getComplexVal().second, SrcElementType, DestElementType, Loc);
6568 LValue LVal,
RValue RVal) {
6569 if (LVal.isGlobalReg())
6576 llvm::AtomicOrdering AO, LValue LVal,
6578 if (LVal.isGlobalReg())
6581 LVal, Loc, llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO),
6590 *
this, RVal, RValTy, LVal.
getType(), Loc)),
6599 llvm_unreachable(
"Must be a scalar or complex.");
6607 assert(
V->isLValue() &&
"V of 'omp atomic read' is not lvalue");
6608 assert(
X->isLValue() &&
"X of 'omp atomic read' is not lvalue");
6617 case llvm::AtomicOrdering::Acquire:
6618 case llvm::AtomicOrdering::AcquireRelease:
6619 case llvm::AtomicOrdering::SequentiallyConsistent:
6621 llvm::AtomicOrdering::Acquire);
6623 case llvm::AtomicOrdering::Monotonic:
6624 case llvm::AtomicOrdering::Release:
6626 case llvm::AtomicOrdering::NotAtomic:
6627 case llvm::AtomicOrdering::Unordered:
6628 llvm_unreachable(
"Unexpected ordering.");
6635 llvm::AtomicOrdering AO,
const Expr *
X,
6638 assert(
X->isLValue() &&
"X of 'omp atomic write' is not lvalue");
6646 case llvm::AtomicOrdering::Release:
6647 case llvm::AtomicOrdering::AcquireRelease:
6648 case llvm::AtomicOrdering::SequentiallyConsistent:
6650 llvm::AtomicOrdering::Release);
6652 case llvm::AtomicOrdering::Acquire:
6653 case llvm::AtomicOrdering::Monotonic:
6655 case llvm::AtomicOrdering::NotAtomic:
6656 case llvm::AtomicOrdering::Unordered:
6657 llvm_unreachable(
"Unexpected ordering.");
6664 llvm::AtomicOrdering AO,
6670 if (BO == BO_Comma || !
Update.isScalar() || !
X.isSimple() ||
6672 (
Update.getScalarVal()->getType() !=
X.getAddress().getElementType())) ||
6673 !Context.getTargetInfo().hasBuiltinAtomic(
6674 Context.getTypeSize(
X.getType()), Context.toBits(
X.getAlignment())))
6675 return std::make_pair(
false,
RValue::get(
nullptr));
6678 if (T->isIntegerTy())
6681 if (T->isFloatingPointTy() && (BO == BO_Add || BO == BO_Sub))
6687 if (!CheckAtomicSupport(
Update.getScalarVal()->getType(), BO) ||
6688 !CheckAtomicSupport(
X.getAddress().getElementType(), BO))
6689 return std::make_pair(
false,
RValue::get(
nullptr));
6691 bool IsInteger =
X.getAddress().getElementType()->isIntegerTy();
6692 llvm::AtomicRMWInst::BinOp RMWOp;
6695 RMWOp = IsInteger ? llvm::AtomicRMWInst::Add : llvm::AtomicRMWInst::FAdd;
6699 return std::make_pair(
false,
RValue::get(
nullptr));
6700 RMWOp = IsInteger ? llvm::AtomicRMWInst::Sub : llvm::AtomicRMWInst::FSub;
6703 RMWOp = llvm::AtomicRMWInst::And;
6706 RMWOp = llvm::AtomicRMWInst::Or;
6709 RMWOp = llvm::AtomicRMWInst::Xor;
6713 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6715 : llvm::AtomicRMWInst::Max)
6717 : llvm::AtomicRMWInst::UMax);
6720 : llvm::AtomicRMWInst::FMax;
6724 RMWOp =
X.getType()->hasSignedIntegerRepresentation()
6726 : llvm::AtomicRMWInst::Min)
6728 : llvm::AtomicRMWInst::UMin);
6731 : llvm::AtomicRMWInst::FMin;
6734 RMWOp = llvm::AtomicRMWInst::Xchg;
6743 return std::make_pair(
false,
RValue::get(
nullptr));
6762 llvm_unreachable(
"Unsupported atomic update operation");
6764 llvm::Value *UpdateVal =
Update.getScalarVal();
6765 if (
auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
6767 UpdateVal = CGF.
Builder.CreateIntCast(
6768 IC,
X.getAddress().getElementType(),
6769 X.getType()->hasSignedIntegerRepresentation());
6771 UpdateVal = CGF.
Builder.CreateCast(llvm::Instruction::CastOps::UIToFP, IC,
6772 X.getAddress().getElementType());
6774 llvm::AtomicRMWInst *Res =
6791 if (
X.isGlobalReg()) {
6804 llvm::AtomicOrdering AO,
const Expr *
X,
6808 "Update expr in 'atomic update' must be a binary operator.");
6816 assert(
X->isLValue() &&
"X of 'omp atomic update' is not lvalue");
6823 auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](
RValue XRValue) {
6829 XLValue, ExprRValue, BOUE->getOpcode(),
IsXLHSInRHSPart, AO, Loc, Gen);
6836 case llvm::AtomicOrdering::Release:
6837 case llvm::AtomicOrdering::AcquireRelease:
6838 case llvm::AtomicOrdering::SequentiallyConsistent:
6840 llvm::AtomicOrdering::Release);
6842 case llvm::AtomicOrdering::Acquire:
6843 case llvm::AtomicOrdering::Monotonic:
6845 case llvm::AtomicOrdering::NotAtomic:
6846 case llvm::AtomicOrdering::Unordered:
6847 llvm_unreachable(
"Unexpected ordering.");
6865 llvm_unreachable(
"Must be a scalar or complex.");
6869 llvm::AtomicOrdering AO,
6874 assert(
X->isLValue() &&
"X of 'omp atomic capture' is not lvalue");
6875 assert(
V->isLValue() &&
"V of 'omp atomic capture' is not lvalue");
6884 "Update expr in 'atomic capture' must be a binary operator.");
6895 NewVValType = XRValExpr->
getType();
6897 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
6906 XLValue, ExprRValue, BOUE->getOpcode(),
IsXLHSInRHSPart, AO, Loc, Gen);
6912 NewVVal = Res.second;
6923 NewVValType =
X->getType().getNonReferenceType();
6925 X->getType().getNonReferenceType(), Loc);
6926 auto &&Gen = [&NewVVal, ExprRValue](
RValue XRValue) {
6932 XLValue, ExprRValue, BO_Assign,
false, AO,
6953 case llvm::AtomicOrdering::Release:
6955 llvm::AtomicOrdering::Release);
6957 case llvm::AtomicOrdering::Acquire:
6959 llvm::AtomicOrdering::Acquire);
6961 case llvm::AtomicOrdering::AcquireRelease:
6962 case llvm::AtomicOrdering::SequentiallyConsistent:
6964 CGF, {}, Loc, llvm::AtomicOrdering::AcquireRelease);
6966 case llvm::AtomicOrdering::Monotonic:
6968 case llvm::AtomicOrdering::NotAtomic:
6969 case llvm::AtomicOrdering::Unordered:
6970 llvm_unreachable(
"Unexpected ordering.");
6976 CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO,
6980 llvm::OpenMPIRBuilder &OMPBuilder =
6983 OMPAtomicCompareOp Op;
6987 Op = OMPAtomicCompareOp::EQ;
6990 Op = OMPAtomicCompareOp::MIN;
6993 Op = OMPAtomicCompareOp::MAX;
6996 llvm_unreachable(
"unsupported atomic compare binary operator");
7000 Address XAddr = XLVal.getAddress();
7002 auto EmitRValueWithCastIfNeeded = [&CGF, Loc](
const Expr *
X,
const Expr *E) {
7007 if (NewE->
getType() ==
X->getType())
7012 llvm::Value *EVal = EmitRValueWithCastIfNeeded(
X, E);
7013 llvm::Value *DVal = D ? EmitRValueWithCastIfNeeded(
X, D) :
nullptr;
7014 if (
auto *CI = dyn_cast<llvm::ConstantInt>(EVal))
7015 EVal = CGF.
Builder.CreateIntCast(
7016 CI, XLVal.getAddress().getElementType(),
7019 if (
auto *CI = dyn_cast<llvm::ConstantInt>(DVal))
7020 DVal = CGF.
Builder.CreateIntCast(
7021 CI, XLVal.getAddress().getElementType(),
7024 llvm::OpenMPIRBuilder::AtomicOpValue XOpVal{
7026 X->getType()->hasSignedIntegerRepresentation(),
7027 X->getType().isVolatileQualified()};
7028 llvm::OpenMPIRBuilder::AtomicOpValue VOpVal, ROpVal;
7032 VOpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
7033 V->getType()->hasSignedIntegerRepresentation(),
7034 V->getType().isVolatileQualified()};
7039 ROpVal = {
Addr.emitRawPointer(CGF),
Addr.getElementType(),
7040 R->getType()->hasSignedIntegerRepresentation(),
7041 R->getType().isVolatileQualified()};
7044 if (FailAO == llvm::AtomicOrdering::NotAtomic) {
7047 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
7048 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
7051 CGF.
Builder.restoreIP(OMPBuilder.createAtomicCompare(
7052 CGF.
Builder, XOpVal, VOpVal, ROpVal, EVal, DVal, AO, Op, IsXBinopExpr,
7057 llvm::AtomicOrdering AO,
7078 case OMPC_compare: {
7084 llvm_unreachable(
"Clause is not allowed in 'omp atomic'.");
7089 llvm::AtomicOrdering AO =
CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
7091 llvm::AtomicOrdering FailAO = llvm::AtomicOrdering::NotAtomic;
7092 bool MemOrderingSpecified =
false;
7093 if (S.getSingleClause<OMPSeqCstClause>()) {
7094 AO = llvm::AtomicOrdering::SequentiallyConsistent;
7095 MemOrderingSpecified =
true;
7096 }
else if (S.getSingleClause<OMPAcqRelClause>()) {
7097 AO = llvm::AtomicOrdering::AcquireRelease;
7098 MemOrderingSpecified =
true;
7099 }
else if (S.getSingleClause<OMPAcquireClause>()) {
7100 AO = llvm::AtomicOrdering::Acquire;
7101 MemOrderingSpecified =
true;
7102 }
else if (S.getSingleClause<OMPReleaseClause>()) {
7103 AO = llvm::AtomicOrdering::Release;
7104 MemOrderingSpecified =
true;
7105 }
else if (S.getSingleClause<OMPRelaxedClause>()) {
7106 AO = llvm::AtomicOrdering::Monotonic;
7107 MemOrderingSpecified =
true;
7109 llvm::SmallSet<OpenMPClauseKind, 2> KindsEncountered;
7118 if (K == OMPC_seq_cst || K == OMPC_acq_rel || K == OMPC_acquire ||
7119 K == OMPC_release || K == OMPC_relaxed || K == OMPC_hint)
7122 KindsEncountered.insert(K);
7127 if (KindsEncountered.contains(OMPC_compare) &&
7128 KindsEncountered.contains(OMPC_capture))
7129 Kind = OMPC_compare;
7130 if (!MemOrderingSpecified) {
7131 llvm::AtomicOrdering DefaultOrder =
7132 CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
7133 if (DefaultOrder == llvm::AtomicOrdering::Monotonic ||
7134 DefaultOrder == llvm::AtomicOrdering::SequentiallyConsistent ||
7135 (DefaultOrder == llvm::AtomicOrdering::AcquireRelease &&
7136 Kind == OMPC_capture)) {
7138 }
else if (DefaultOrder == llvm::AtomicOrdering::AcquireRelease) {
7139 if (Kind == OMPC_unknown || Kind == OMPC_update || Kind == OMPC_write) {
7140 AO = llvm::AtomicOrdering::Release;
7141 }
else if (Kind == OMPC_read) {
7142 assert(Kind == OMPC_read &&
"Unexpected atomic kind.");
7143 AO = llvm::AtomicOrdering::Acquire;
7148 if (KindsEncountered.contains(OMPC_compare) &&
7149 KindsEncountered.contains(OMPC_fail)) {
7150 Kind = OMPC_compare;
7151 const auto *FailClause = S.getSingleClause<OMPFailClause>();
7154 if (FailParameter == llvm::omp::OMPC_relaxed)
7155 FailAO = llvm::AtomicOrdering::Monotonic;
7156 else if (FailParameter == llvm::omp::OMPC_acquire)
7157 FailAO = llvm::AtomicOrdering::Acquire;
7158 else if (FailParameter == llvm::omp::OMPC_seq_cst)
7159 FailAO = llvm::AtomicOrdering::SequentiallyConsistent;
7166 S.getV(), S.getR(), S.getExpr(), S.getUpdateExpr(),
7167 S.getD(), S.getCondExpr(), S.isXLHSInRHSPart(),
7168 S.isFailOnly(), S.getBeginLoc());
7179 OMPLexicalScope
Scope(CGF, S, OMPD_target);
7182 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
7188 llvm::Function *Fn =
nullptr;
7189 llvm::Constant *FnID =
nullptr;
7191 const Expr *IfCond =
nullptr;
7193 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7194 if (
C->getNameModifier() == OMPD_unknown ||
7195 C->getNameModifier() == OMPD_target) {
7196 IfCond =
C->getCondition();
7202 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier>
Device(
7205 Device.setPointerAndInt(
C->getDevice(),
C->getModifier());
7210 bool IsOffloadEntry =
true;
7214 IsOffloadEntry =
false;
7217 IsOffloadEntry =
false;
7219 if (
CGM.
getLangOpts().OpenMPOffloadMandatory && !IsOffloadEntry) {
7223 assert(CGF.
CurFuncDecl &&
"No parent declaration for target region!");
7224 StringRef ParentName;
7227 if (
const auto *D = dyn_cast<CXXConstructorDecl>(CGF.
CurFuncDecl))
7229 else if (
const auto *D = dyn_cast<CXXDestructorDecl>(CGF.
CurFuncDecl))
7238 OMPLexicalScope
Scope(CGF, S, OMPD_task);
7239 auto &&SizeEmitter =
7242 if (IsOffloadEntry) {
7243 OMPLoopScope(CGF, D);
7245 llvm::Value *NumIterations = CGF.
EmitScalarExpr(D.getNumIterations());
7246 NumIterations = CGF.
Builder.CreateIntCast(NumIterations, CGF.
Int64Ty,
7248 return NumIterations;
7266 CGF.
EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
7271 StringRef ParentName,
7277 llvm::Constant *
Addr;
7279 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7281 assert(Fn &&
Addr &&
"Target device function emission failed.");
7295 const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams);
7296 llvm::Function *OutlinedFn =
7304 const Expr *NumTeams = NT ? NT->getNumTeams().front() :
nullptr;
7305 const Expr *ThreadLimit = TL ? TL->getThreadLimit().front() :
nullptr;
7311 OMPTeamsScope
Scope(CGF, S);
7327 CGF.
EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt());
7332 [](CodeGenFunction &) {
return nullptr; });
7337 auto *CS = S.getCapturedStmt(OMPD_teams);
7364 llvm::Constant *
Addr;
7366 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7368 assert(Fn &&
Addr &&
"Target device function emission failed.");
7410 llvm::Constant *
Addr;
7412 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7414 assert(Fn &&
Addr &&
"Target device function emission failed.");
7456 llvm::Constant *
Addr;
7458 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7460 assert(Fn &&
Addr &&
"Target device function emission failed.");
7474 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7479 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7491 [](CodeGenFunction &) {
return nullptr; });
7496 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7501 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7513 [](CodeGenFunction &) {
return nullptr; });
7518 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7524 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7536 [](CodeGenFunction &) {
return nullptr; });
7541 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7547 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
7554 CGF, OMPD_distribute, CodeGenDistribute,
false);
7560 [](CodeGenFunction &) {
return nullptr; });
7564 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7565 llvm::Value *
Device =
nullptr;
7566 llvm::Value *NumDependences =
nullptr;
7567 llvm::Value *DependenceList =
nullptr;
7575 if (!
Data.Dependences.empty()) {
7577 std::tie(NumDependences, DependenciesArray) =
7578 CGM.getOpenMPRuntime().emitDependClause(*
this,
Data.Dependences,
7582 Data.HasNowaitClause = S.hasClausesOfKind<OMPNowaitClause>();
7587 "OMPNowaitClause clause is used separately in OMPInteropDirective.");
7590 if (!ItOMPInitClause.empty()) {
7593 llvm::Value *InteropvarPtr =
7595 llvm::omp::OMPInteropType InteropType =
7596 llvm::omp::OMPInteropType::Unknown;
7597 if (
C->getIsTarget()) {
7598 InteropType = llvm::omp::OMPInteropType::Target;
7600 assert(
C->getIsTargetSync() &&
7601 "Expected interop-type target/targetsync");
7602 InteropType = llvm::omp::OMPInteropType::TargetSync;
7604 OMPBuilder.createOMPInteropInit(
Builder, InteropvarPtr, InteropType,
7605 Device, NumDependences, DependenceList,
7606 Data.HasNowaitClause);
7610 if (!ItOMPDestroyClause.empty()) {
7613 llvm::Value *InteropvarPtr =
7615 OMPBuilder.createOMPInteropDestroy(
Builder, InteropvarPtr,
Device,
7616 NumDependences, DependenceList,
7617 Data.HasNowaitClause);
7620 auto ItOMPUseClause = S.getClausesOfKind<
OMPUseClause>();
7621 if (!ItOMPUseClause.empty()) {
7624 llvm::Value *InteropvarPtr =
7626 OMPBuilder.createOMPInteropUse(
Builder, InteropvarPtr,
Device,
7627 NumDependences, DependenceList,
7628 Data.HasNowaitClause);
7650 CGF, OMPD_distribute, CodeGenDistribute,
false);
7669 llvm::Constant *
Addr;
7671 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7673 assert(Fn &&
Addr &&
"Target device function emission failed.");
7702 CGF, OMPD_distribute, CodeGenDistribute,
false);
7721 llvm::Constant *
Addr;
7723 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
7725 assert(Fn &&
Addr &&
"Target device function emission failed.");
7738 CGM.getOpenMPRuntime().emitCancellationPointCall(*
this, S.getBeginLoc(),
7743 const Expr *IfCond =
nullptr;
7744 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
7745 if (
C->getNameModifier() == OMPD_unknown ||
7746 C->getNameModifier() == OMPD_cancel) {
7747 IfCond =
C->getCondition();
7751 if (
CGM.getLangOpts().OpenMPIRBuilder) {
7752 llvm::OpenMPIRBuilder &OMPBuilder =
CGM.getOpenMPRuntime().getOMPBuilder();
7758 llvm::Value *IfCondition =
nullptr;
7762 llvm::OpenMPIRBuilder::InsertPointTy AfterIP = cantFail(
7764 return Builder.restoreIP(AfterIP);
7768 CGM.getOpenMPRuntime().emitCancelCall(*
this, S.getBeginLoc(), IfCond,
7774 if (Kind == OMPD_parallel || Kind == OMPD_task ||
7775 Kind == OMPD_target_parallel || Kind == OMPD_taskloop ||
7776 Kind == OMPD_master_taskloop || Kind == OMPD_parallel_master_taskloop)
7778 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
7779 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
7780 Kind == OMPD_distribute_parallel_for ||
7781 Kind == OMPD_target_parallel_for ||
7782 Kind == OMPD_teams_distribute_parallel_for ||
7783 Kind == OMPD_target_teams_distribute_parallel_for);
7784 return OMPCancelStack.getExitBlock();
7789 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7790 CaptureDeviceAddrMap) {
7791 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7792 for (
const Expr *OrigVarIt :
C.varlist()) {
7794 if (!Processed.insert(OrigVD).second)
7801 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7806 "Base should be the current struct!");
7807 MatchingVD = ME->getMemberDecl();
7812 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7813 if (InitAddrIt == CaptureDeviceAddrMap.end())
7821 Address(InitAddrIt->second, Ty,
7823 assert(IsRegistered &&
"firstprivate var already registered as private");
7831 while (
const auto *OASE = dyn_cast<ArraySectionExpr>(
Base))
7832 Base = OASE->getBase()->IgnoreParenImpCasts();
7833 while (
const auto *ASE = dyn_cast<ArraySubscriptExpr>(
Base))
7834 Base = ASE->getBase()->IgnoreParenImpCasts();
7840 const llvm::DenseMap<const ValueDecl *, llvm::Value *>
7841 CaptureDeviceAddrMap) {
7842 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed;
7843 for (
const Expr *Ref :
C.varlist()) {
7845 if (!Processed.insert(OrigVD).second)
7851 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
7856 "Base should be the current struct!");
7857 MatchingVD = ME->getMemberDecl();
7862 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
7863 if (InitAddrIt == CaptureDeviceAddrMap.end())
7869 Address(InitAddrIt->second, Ty,
7882 (void)PrivateScope.
addPrivate(OrigVD, PrivAddr);
7890 if (!
CGM.getLangOpts().OpenMPIsTargetDevice)
7891 CGM.getOpenMPRuntime().registerVTable(S);
7899 bool PrivatizeDevicePointers =
false;
7901 bool &PrivatizeDevicePointers;
7904 explicit DevicePointerPrivActionTy(
bool &PrivatizeDevicePointers)
7905 : PrivatizeDevicePointers(PrivatizeDevicePointers) {}
7906 void Enter(CodeGenFunction &CGF)
override {
7907 PrivatizeDevicePointers =
true;
7910 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
7913 auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
7914 CGF.
EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
7918 auto &&PrivCodeGen = [&](CodeGenFunction &CGF,
PrePostActionTy &Action) {
7920 PrivatizeDevicePointers =
false;
7926 if (PrivatizeDevicePointers) {
7940 std::optional<OpenMPDirectiveKind> CaptureRegion;
7941 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
7944 for (
const Expr *E :
C->varlist()) {
7946 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
7950 for (
const Expr *E :
C->varlist()) {
7952 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
7956 CaptureRegion = OMPD_unknown;
7959 OMPLexicalScope
Scope(CGF, S, CaptureRegion);
7971 OMPLexicalScope
Scope(CGF, S);
7980 if (
CGM.getLangOpts().OMPTargetTriples.empty()) {
7986 const Expr *IfCond =
nullptr;
7988 IfCond =
C->getCondition();
7999 CGM.getOpenMPRuntime().emitTargetDataCalls(*
this, S, IfCond,
Device, RCG,
8007 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8011 const Expr *IfCond =
nullptr;
8013 IfCond =
C->getCondition();
8020 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8021 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8028 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8032 const Expr *IfCond =
nullptr;
8034 IfCond =
C->getCondition();
8041 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8042 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8049 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
8077 llvm::Constant *
Addr;
8079 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8081 assert(Fn &&
Addr &&
"Target device function emission failed.");
8101 CGF, OMPD_target_parallel_for, S.
hasCancel());
8117 llvm::Constant *
Addr;
8119 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8121 assert(Fn &&
Addr &&
"Target device function emission failed.");
8156 llvm::Constant *
Addr;
8158 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8160 assert(Fn &&
Addr &&
"Target device function emission failed.");
8182 const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop);
8185 OMPLexicalScope
Scope(*
this, S, OMPD_taskloop,
false);
8190 const Expr *IfCond =
nullptr;
8191 for (
const auto *
C : S.getClausesOfKind<
OMPIfClause>()) {
8192 if (
C->getNameModifier() == OMPD_unknown ||
8193 C->getNameModifier() == OMPD_taskloop) {
8194 IfCond =
C->getCondition();
8207 Data.Schedule.setInt(
false);
8210 (Clause->getModifier() == OMPC_GRAINSIZE_strict) ?
true :
false;
8213 Data.Schedule.setInt(
true);
8216 (Clause->getModifier() == OMPC_NUMTASKS_strict) ?
true :
false;
8230 llvm::BasicBlock *ContBlock =
nullptr;
8231 OMPLoopScope PreInitScope(CGF, S);
8232 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
8236 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock(
"taskloop.if.then");
8237 ContBlock = CGF.createBasicBlock(
"taskloop.if.end");
8238 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
8239 CGF.getProfileCount(&S));
8240 CGF.EmitBlock(ThenBlock);
8241 CGF.incrementProfileCounter(&S);
8244 (void)CGF.EmitOMPLinearClauseInit(S);
8248 enum { LowerBound = 5, UpperBound, Stride, LastIter };
8250 auto *LBP = std::next(I, LowerBound);
8251 auto *UBP = std::next(I, UpperBound);
8252 auto *STP = std::next(I, Stride);
8253 auto *LIP = std::next(I, LastIter);
8261 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
8262 CGF.EmitOMPLinearClause(S, LoopScope);
8263 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
8266 const Expr *IVExpr = S.getIterationVariable();
8268 CGF.EmitVarDecl(*IVDecl);
8269 CGF.EmitIgnoredExpr(S.getInit());
8274 if (
const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
8277 CGF.EmitIgnoredExpr(S.getCalcLastIteration());
8281 OMPLexicalScope
Scope(CGF, S, OMPD_taskloop,
false);
8291 [&S](CodeGenFunction &CGF) {
8292 emitOMPLoopBodyWithStopPoint(CGF, S,
8293 CodeGenFunction::JumpDest());
8295 [](CodeGenFunction &) {});
8300 CGF.EmitBranch(ContBlock);
8301 CGF.EmitBlock(ContBlock,
true);
8304 if (HasLastprivateClause) {
8305 CGF.EmitOMPLastprivateClauseFinal(
8307 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
8308 CGF.GetAddrOfLocalVar(*LIP),
false,
8309 (*LIP)->getType(), S.getBeginLoc())));
8312 CGF.EmitOMPLinearClauseFinal(S, [LIP, &S](CodeGenFunction &CGF) {
8313 return CGF.
Builder.CreateIsNotNull(
8315 (*LIP)->
getType(), S.getBeginLoc()));
8318 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
8319 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
8321 auto &&
CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
8323 OMPLoopScope PreInitScope(CGF, S);
8324 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S,
8325 OutlinedFn, SharedsTy,
8326 CapturedStruct, IfCond,
Data);
8328 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
8334 CGM.getOpenMPRuntime().emitTaskgroupRegion(
8336 [&S, &BodyGen, &TaskGen, &
Data](CodeGenFunction &CGF,
8356 OMPLexicalScope
Scope(*
this, S);
8368 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8369 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8380 OMPLexicalScope
Scope(*
this, S, std::nullopt,
false);
8381 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8392 OMPLexicalScope
Scope(*
this, S);
8393 CGM.getOpenMPRuntime().emitMasterRegion(*
this,
CodeGen, S.getBeginLoc());
8404 OMPLexicalScope
Scope(*
this, S);
8405 CGM.getOpenMPRuntime().emitMaskedRegion(*
this,
CodeGen, S.getBeginLoc());
8411 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8416 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8417 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8429 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8434 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8435 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8447 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8452 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8453 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
8465 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
8470 OMPLexicalScope
Scope(CGF, S, OMPD_parallel,
false);
8471 CGM.getOpenMPRuntime().emitMaskedRegion(CGF, TaskLoopCodeGen,
8485 if (
CGM.getLangOpts().OMPTargetTriples.empty())
8489 const Expr *IfCond =
nullptr;
8491 IfCond =
C->getCondition();
8498 OMPLexicalScope
Scope(*
this, S, OMPD_task);
8499 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond,
Device);
8509 BindKind =
C->getBindKind();
8512 case OMPC_BIND_parallel:
8514 case OMPC_BIND_teams:
8516 case OMPC_BIND_thread:
8527 const auto *ForS = dyn_cast<ForStmt>(CS);
8538 OMPLexicalScope
Scope(*
this, S, OMPD_unknown);
8539 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_loop,
CodeGen);
8565 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF,
PrePostActionTy &) {
8570 auto &&
CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
8582 [](CodeGenFunction &) {
return nullptr; });
8587 std::string StatusMsg,
8591 StatusMsg +=
": DEVICE";
8593 StatusMsg +=
": HOST";
8600 llvm::dbgs() << StatusMsg <<
": " <<
FileName <<
": " << LineNo <<
"\n";
8623 CGF, OMPD_distribute, CodeGenDistribute,
false);
8652 CGF, OMPD_distribute, CodeGenDistribute,
false);
8685 llvm::Constant *
Addr;
8687 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8689 assert(Fn &&
Addr &&
8690 "Target device function emission failed for 'target teams loop'.");
8701 CGF, OMPD_target_parallel_loop,
false);
8717 llvm::Constant *
Addr;
8719 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
8721 assert(Fn &&
Addr &&
"Target device function emission failed.");
8736 if (
const auto *SD = dyn_cast<OMPScanDirective>(&D)) {
8740 if (!D.hasAssociatedStmt() || !D.getAssociatedStmt())
8746 for (
const auto *
C : D.getClausesOfKind<OMPFirstprivateClause>()) {
8747 for (
const Expr *Ref :
C->varlist()) {
8751 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
8754 if (!CGF.LocalDeclMap.count(VD)) {
8766 if (
const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
8767 for (
const Expr *E : LD->counters()) {
8775 if (!CGF.LocalDeclMap.count(VD))
8779 for (
const auto *
C : D.getClausesOfKind<OMPOrderedClause>()) {
8780 if (!
C->getNumForLoops())
8782 for (
unsigned I = LD->getLoopsNumber(),
8783 E =
C->getLoopNumIterations().size();
8785 if (
const auto *VD = dyn_cast<OMPCapturedExprDecl>(
8788 if (!CGF.LocalDeclMap.count(VD))
8795 CGF.
EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
8798 if (D.getDirectiveKind() == OMPD_atomic ||
8799 D.getDirectiveKind() == OMPD_critical ||
8800 D.getDirectiveKind() == OMPD_section ||
8801 D.getDirectiveKind() == OMPD_master ||
8802 D.getDirectiveKind() == OMPD_masked ||
8803 D.getDirectiveKind() == OMPD_unroll ||
8804 D.getDirectiveKind() == OMPD_assume) {
8809 OMPSimdLexicalScope
Scope(*
this, D);
8810 CGM.getOpenMPRuntime().emitInlinedDirective(
8813 : D.getDirectiveKind(),
Defines the clang::ASTContext interface.
static bool isAllocatableDecl(const VarDecl *VD)
static const VarDecl * getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE)
static void emitTargetRegion(CodeGenFunction &CGF, const OMPTargetDirective &S, PrePostActionTy &Action)
static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S, PrePostActionTy &Action)
static const VarDecl * getBaseDecl(const Expr *Ref)
static void emitTargetTeamsGenericLoopRegionAsParallel(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsGenericLoopDirective &S)
static void emitOMPAtomicReadExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, const Expr *X, const Expr *V, SourceLocation Loc)
static void emitOMPAtomicCaptureExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, bool IsPostfixUpdate, const Expr *V, const Expr *X, const Expr *E, const Expr *UE, bool IsXLHSInRHSPart, SourceLocation Loc)
static void emitScanBasedDirective(CodeGenFunction &CGF, const OMPLoopDirective &S, llvm::function_ref< llvm::Value *(CodeGenFunction &)> NumIteratorsGen, llvm::function_ref< void(CodeGenFunction &)> FirstGen, llvm::function_ref< void(CodeGenFunction &)> SecondGen)
Emits the code for the directive with inscan reductions.
static void emitSimpleAtomicStore(CodeGenFunction &CGF, llvm::AtomicOrdering AO, LValue LVal, RValue RVal)
static bool isSupportedByOpenMPIRBuilder(const OMPTaskgroupDirective &T)
static Address castValueFromUintptr(CodeGenFunction &CGF, SourceLocation Loc, QualType DstType, StringRef Name, LValue AddrLV)
static void emitDistributeParallelForDistributeInnerBoundParams(CodeGenFunction &CGF, const OMPExecutableDirective &S, llvm::SmallVectorImpl< llvm::Value * > &CapturedVars)
static void emitScanBasedDirectiveFinals(CodeGenFunction &CGF, const OMPLoopDirective &S, llvm::function_ref< llvm::Value *(CodeGenFunction &)> NumIteratorsGen)
Copies final inscan reductions values to the original variables.
static void checkForLastprivateConditionalUpdate(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static std::pair< LValue, LValue > emitForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S)
The following two functions generate expressions for the loop lower and upper bounds in case of stati...
static void emitTargetParallelForRegion(CodeGenFunction &CGF, const OMPTargetParallelForDirective &S, PrePostActionTy &Action)
static llvm::Function * emitOutlinedFunctionPrologueAggregate(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, llvm::Value *&ContextV, const CapturedStmt &CS, SourceLocation Loc, StringRef FunctionName)
static LValue EmitOMPHelperVar(CodeGenFunction &CGF, const DeclRefExpr *Helper)
Emit a helper variable and return corresponding lvalue.
static void emitOMPAtomicUpdateExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, const Expr *X, const Expr *E, const Expr *UE, bool IsXLHSInRHSPart, SourceLocation Loc)
static llvm::Value * convertToScalarValue(CodeGenFunction &CGF, RValue Val, QualType SrcType, QualType DestType, SourceLocation Loc)
static llvm::Function * emitOutlinedOrderedFunction(CodeGenModule &CGM, const CapturedStmt *S, const OMPExecutableDirective &D)
static void emitPreCond(CodeGenFunction &CGF, const OMPLoopDirective &S, const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount)
static std::pair< bool, RValue > emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X, RValue Update, BinaryOperatorKind BO, llvm::AtomicOrdering AO, bool IsXLHSInRHSPart)
static std::pair< LValue, LValue > emitDistributeParallelForInnerBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitTargetTeamsGenericLoopRegionAsDistribute(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsGenericLoopDirective &S)
static void emitTargetParallelRegion(CodeGenFunction &CGF, const OMPTargetParallelDirective &S, PrePostActionTy &Action)
static std::pair< llvm::Value *, llvm::Value * > emitDispatchForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S, Address LB, Address UB)
When dealing with dispatch schedules (e.g.
static void emitMaster(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitRestoreIP(CodeGenFunction &CGF, const T *C, llvm::OpenMPIRBuilder::InsertPointTy AllocaIP, llvm::OpenMPIRBuilder &OMPBuilder)
static void emitCommonOMPTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, const RegionCodeGenTy &CodeGen)
static void emitSimdlenSafelenClause(CodeGenFunction &CGF, const OMPExecutableDirective &D)
static void emitAlignedClause(CodeGenFunction &CGF, const OMPExecutableDirective &D)
static bool isSimdSupportedByOpenMPIRBuilder(const OMPLoopDirective &S)
static void emitCommonOMPParallelDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, const CodeGenBoundParametersTy &CodeGenBoundParameters)
static void applyConservativeSimdOrderedDirective(const Stmt &AssociatedStmt, LoopInfoStack &LoopStack)
static bool emitWorksharingDirective(CodeGenFunction &CGF, const OMPLoopDirective &S, bool HasCancel)
static void emitPostUpdateForReductionClause(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
static void emitEmptyOrdered(CodeGenFunction &, SourceLocation Loc, const unsigned IVSize, const bool IVSigned)
static void emitTargetTeamsLoopCodegenStatus(CodeGenFunction &CGF, std::string StatusMsg, const OMPExecutableDirective &D)
static bool isForSupportedByOpenMPIRBuilder(const OMPLoopDirective &S, bool HasCancel)
static RValue emitSimpleAtomicLoad(CodeGenFunction &CGF, llvm::AtomicOrdering AO, LValue LVal, SourceLocation Loc)
static std::pair< llvm::Value *, llvm::Value * > emitDistributeParallelForDispatchBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S, Address LB, Address UB)
if the 'for' loop has a dispatch schedule (e.g.
static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO, bool IsPostfixUpdate, const Expr *X, const Expr *V, const Expr *R, const Expr *E, const Expr *UE, const Expr *D, const Expr *CE, bool IsXLHSInRHSPart, bool IsFailOnly, SourceLocation Loc)
static CodeGenFunction::ComplexPairTy convertToComplexValue(CodeGenFunction &CGF, RValue Val, QualType SrcType, QualType DestType, SourceLocation Loc)
static ImplicitParamDecl * createImplicitFirstprivateForType(ASTContext &C, OMPTaskDataTy &Data, QualType Ty, CapturedDecl *CD, SourceLocation Loc)
static EmittedClosureTy emitCapturedStmtFunc(CodeGenFunction &ParentCGF, const CapturedStmt *S)
Emit a captured statement and return the function as well as its captured closure context.
static void emitOMPLoopBodyWithStopPoint(CodeGenFunction &CGF, const OMPLoopDirective &S, CodeGenFunction::JumpDest LoopExit)
static void emitOMPDistributeDirective(const OMPLoopDirective &S, CodeGenFunction &CGF, CodeGenModule &CGM)
static void emitOMPCopyinClause(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitTargetTeamsDistributeParallelForRegion(CodeGenFunction &CGF, const OMPTargetTeamsDistributeParallelForDirective &S, PrePostActionTy &Action)
static bool hasOrderedDirective(const Stmt *S)
static llvm::CallInst * emitCapturedStmtCall(CodeGenFunction &ParentCGF, EmittedClosureTy Cap, llvm::ArrayRef< llvm::Value * > Args)
Emit a call to a previously captured closure.
static void emitMasked(CodeGenFunction &CGF, const OMPExecutableDirective &S)
static void emitBody(CodeGenFunction &CGF, const Stmt *S, const Stmt *NextLoop, int MaxLevel, int Level=0)
static void emitOMPForDirective(const OMPLoopDirective &S, CodeGenFunction &CGF, CodeGenModule &CGM, bool HasCancel)
static void emitEmptyBoundParameters(CodeGenFunction &, const OMPExecutableDirective &, llvm::SmallVectorImpl< llvm::Value * > &)
static void emitTargetParallelForSimdRegion(CodeGenFunction &CGF, const OMPTargetParallelForSimdDirective &S, PrePostActionTy &Action)
static void emitOMPSimdDirective(const OMPLoopDirective &S, CodeGenFunction &CGF, CodeGenModule &CGM)
static void emitOMPAtomicCompareExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, llvm::AtomicOrdering FailAO, const Expr *X, const Expr *V, const Expr *R, const Expr *E, const Expr *D, const Expr *CE, bool IsXBinopExpr, bool IsPostfixUpdate, bool IsFailOnly, SourceLocation Loc)
std::pair< llvm::Function *, llvm::Value * > EmittedClosureTy
static OpenMPDirectiveKind getEffectiveDirectiveKind(const OMPExecutableDirective &S)
static void emitTargetTeamsRegion(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsDirective &S)
static void buildDependences(const OMPExecutableDirective &S, OMPTaskDataTy &Data)
static RValue convertToType(CodeGenFunction &CGF, RValue Value, QualType SourceType, QualType ResType, SourceLocation Loc)
static void emitScanBasedDirectiveDecls(CodeGenFunction &CGF, const OMPLoopDirective &S, llvm::function_ref< llvm::Value *(CodeGenFunction &)> NumIteratorsGen)
Emits internal temp array declarations for the directive with inscan reductions.
static void emitTargetTeamsDistributeParallelForSimdRegion(CodeGenFunction &CGF, const OMPTargetTeamsDistributeParallelForSimdDirective &S, PrePostActionTy &Action)
static void emitTargetTeamsDistributeSimdRegion(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsDistributeSimdDirective &S)
static llvm::MapVector< llvm::Value *, llvm::Value * > GetAlignedMapping(const OMPLoopDirective &S, CodeGenFunction &CGF)
static llvm::omp::ScheduleKind convertClauseKindToSchedKind(OpenMPScheduleClauseKind ScheduleClauseKind)
static void mapParam(CodeGenFunction &CGF, const DeclRefExpr *Helper, const ImplicitParamDecl *PVD, CodeGenFunction::OMPPrivateScope &Privates)
Emit a helper variable and return corresponding lvalue.
static void emitCommonOMPTeamsDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
static void emitTargetParallelGenericLoopRegion(CodeGenFunction &CGF, const OMPTargetParallelGenericLoopDirective &S, PrePostActionTy &Action)
static QualType getCanonicalParamType(ASTContext &C, QualType T)
static void emitCommonSimdLoop(CodeGenFunction &CGF, const OMPLoopDirective &S, const RegionCodeGenTy &SimdInitGen, const RegionCodeGenTy &BodyCodeGen)
static LValue createSectionLVal(CodeGenFunction &CGF, QualType Ty, const Twine &Name, llvm::Value *Init=nullptr)
static void emitOMPAtomicWriteExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO, const Expr *X, const Expr *E, SourceLocation Loc)
static llvm::Function * emitOutlinedFunctionPrologue(CodeGenFunction &CGF, FunctionArgList &Args, llvm::MapVector< const Decl *, std::pair< const VarDecl *, Address > > &LocalAddrs, llvm::DenseMap< const Decl *, std::pair< const Expr *, llvm::Value * > > &VLASizes, llvm::Value *&CXXThisValue, const FunctionOptions &FO)
static void emitInnerParallelForWhenCombined(CodeGenFunction &CGF, const OMPLoopDirective &S, CodeGenFunction::JumpDest LoopExit)
static void emitTargetTeamsDistributeRegion(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsDistributeDirective &S)
This file defines OpenMP nodes for declarative directives.
static const Decl * getCanonicalDecl(const Decl *D)
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
Defines the PrettyStackTraceEntry class, which is used to make crashes give more contextual informati...
Defines the SourceManager interface.
This file defines OpenMP AST classes for executable directives and clauses.
This represents clause 'aligned' in the 'pragma omp ...' directives.
This represents 'bind' clause in the 'pragma omp ...' directives.
This represents 'pragma omp cancel' directive.
OpenMPDirectiveKind getCancelRegion() const
Get cancellation region for the current cancellation point.
This represents 'pragma omp cancellation point' directive.
OpenMPDirectiveKind getCancelRegion() const
Get cancellation region for the current cancellation point.
This represents clause 'copyin' in the 'pragma omp ...' directives.
This represents clause 'copyprivate' in the 'pragma omp ...' directives.
This represents implicit clause 'depend' for the 'pragma omp task' directive.
This represents implicit clause 'depobj' for the 'pragma omp depobj' directive. This clause does not ...
This represents 'destroy' clause in the 'pragma omp depobj' directive or the 'pragma omp interop' dir...
This represents 'device' clause in the 'pragma omp ...' directive.
This represents 'dist_schedule' clause in the 'pragma omp ...' directive.
This represents 'pragma omp distribute' directive.
This represents 'pragma omp distribute parallel for' composite directive.
This represents 'pragma omp distribute parallel for simd' composite directive.
This represents 'pragma omp distribute simd' composite directive.
This represents the 'doacross' clause for the 'pragma omp ordered' directive.
This represents 'pragma omp error' directive.
This represents 'filter' clause in the 'pragma omp ...' directive.
This represents implicit clause 'flush' for the 'pragma omp flush' directive. This clause does not ex...
Represents the 'pragma omp fuse' loop transformation directive.
Stmt * getTransformedStmt() const
Gets the associated loops after the transformation.
This represents 'pragma omp loop' directive.
This represents 'grainsize' clause in the 'pragma omp ...' directive.
This represents 'hint' clause in the 'pragma omp ...' directive.
This represents clause 'inclusive' in the 'pragma omp scan' directive.
This represents the 'init' clause in 'pragma omp ...' directives.
Represents the 'pragma omp interchange' loop transformation directive.
Stmt * getTransformedStmt() const
Gets the associated loops after the transformation.
This represents 'pragma omp interop' directive.
This represents 'pragma omp masked' directive.
This represents 'pragma omp masked taskloop' directive.
This represents 'pragma omp masked taskloop simd' directive.
This represents 'pragma omp master taskloop' directive.
This represents 'pragma omp master taskloop simd' directive.
This represents 'nogroup' clause in the 'pragma omp ...' directive.
This represents 'num_tasks' clause in the 'pragma omp ...' directive.
This represents 'num_teams' clause in the 'pragma omp ...' directive.
This represents 'order' clause in the 'pragma omp ...' directive.
This represents 'pragma omp parallel masked taskloop' directive.
This represents 'pragma omp parallel masked taskloop simd' directive.
This represents 'pragma omp parallel master taskloop' directive.
This represents 'pragma omp parallel master taskloop simd' directive.
This represents 'priority' clause in the 'pragma omp ...' directive.
Represents the 'pragma omp reverse' loop transformation directive.
Stmt * getTransformedStmt() const
Gets/sets the associated loops after the transformation, i.e.
This represents 'simd' clause in the 'pragma omp ...' directive.
This represents 'pragma omp scan' directive.
This represents the 'pragma omp stripe' loop transformation directive.
Stmt * getTransformedStmt() const
Gets/sets the associated loops after striping.
This represents 'pragma omp target data' directive.
This represents 'pragma omp target' directive.
This represents 'pragma omp target enter data' directive.
This represents 'pragma omp target exit data' directive.
This represents 'pragma omp target parallel' directive.
This represents 'pragma omp target parallel for' directive.
bool hasCancel() const
Return true if current directive has inner cancel directive.
This represents 'pragma omp target parallel for simd' directive.
This represents 'pragma omp target parallel loop' directive.
This represents 'pragma omp target simd' directive.
This represents 'pragma omp target teams' directive.
This represents 'pragma omp target teams distribute' combined directive.
This represents 'pragma omp target teams distribute parallel for' combined directive.
This represents 'pragma omp target teams distribute parallel for simd' combined directive.
This represents 'pragma omp target teams distribute simd' combined directive.
This represents 'pragma omp target teams loop' directive.
bool canBeParallelFor() const
Return true if current loop directive's associated loop can be a parallel for.
This represents 'pragma omp target update' directive.
This represents 'pragma omp taskloop' directive.
This represents 'pragma omp taskloop simd' directive.
This represents 'pragma omp teams' directive.
This represents 'pragma omp teams distribute' directive.
This represents 'pragma omp teams distribute parallel for' composite directive.
This represents 'pragma omp teams distribute parallel for simd' composite directive.
This represents 'pragma omp teams distribute simd' combined directive.
This represents 'pragma omp teams loop' directive.
This represents 'thread_limit' clause in the 'pragma omp ...' directive.
This represents the 'pragma omp tile' loop transformation directive.
Stmt * getTransformedStmt() const
Gets/sets the associated loops after tiling.
This represents the 'pragma omp unroll' loop transformation directive.
This represents the 'use' clause in 'pragma omp ...' directives.
This represents clause 'use_device_addr' in the 'pragma omp ...' directives.
This represents clause 'use_device_ptr' in the 'pragma omp ...' directives.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
TranslationUnitDecl * getTranslationUnitDecl() const
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
QualType getUIntPtrType() const
Return a type compatible with "uintptr_t" (C99 7.18.1.4), as defined by the target.
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
unsigned getOpenMPDefaultSimdAlign(QualType T) const
Get default simd alignment of the specified complete type in bits.
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
CanQualType getCanonicalTagType(const TagDecl *TD) const
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Represents an attribute applied to a statement.
ArrayRef< const Attr * > getAttrs() const
static BinaryOperator * Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, FPOptionsOverride FPFeatures)
Represents the body of a CapturedStmt, and serves as its DeclContext.
unsigned getNumParams() const
ImplicitParamDecl * getContextParam() const
Retrieve the parameter containing captured variables.
unsigned getContextParamPosition() const
static CapturedDecl * Create(ASTContext &C, DeclContext *DC, unsigned NumParams)
param_iterator param_end() const
Retrieve an iterator one past the last parameter decl.
param_iterator param_begin() const
Retrieve an iterator pointing to the first parameter decl.
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
ImplicitParamDecl * getParam(unsigned i) const
This captures a statement into a function.
SourceLocation getEndLoc() const LLVM_READONLY
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
const RecordDecl * getCapturedRecordDecl() const
Retrieve the record declaration for captured variables.
Stmt * getCapturedStmt()
Retrieve the statement being captured.
capture_init_iterator capture_init_begin()
Retrieve the first initialization argument.
SourceLocation getBeginLoc() const LLVM_READONLY
capture_init_iterator capture_init_end()
Retrieve the iterator pointing one past the last initialization argument.
Expr *const * const_capture_init_iterator
Const iterator that walks over the capture initialization arguments.
CharUnits - This is an opaque type for sizes expressed in character units.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
std::string SampleProfileFile
Name of the profile file to use with -fprofile-sample-use.
Like RawAddress, an abstract representation of an aligned address, but the pointer contained in this ...
llvm::Value * emitRawPointer(CodeGenFunction &CGF) const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
CharUnits getAlignment() const
llvm::Type * getElementType() const
Return the type of the values stored in this address.
Address withElementType(llvm::Type *ElemTy) const
Return address with different element type, but same pointer and alignment.
Address withAlignment(CharUnits NewAlignment) const
Return address with different alignment, but same pointer and element type.
llvm::PointerType * getType() const
Return the type of the pointer value.
static AggValueSlot ignored()
ignored - Returns an aggregate value slot indicating that the aggregate value is being ignored.
static ApplyDebugLocation CreateDefaultArtificial(CodeGenFunction &CGF, SourceLocation TemporaryLocation)
Apply TemporaryLocation if it is valid.
Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, llvm::Type *ElementTy, const llvm::Twine &Name="")
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
llvm::LoadInst * CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr, CharUnits Align, const llvm::Twine &Name="")
CGFunctionInfo - Class to encapsulate the information about a function definition.
Manages list of lastprivate conditional decls for the specified directive.
static LastprivateConditionalRAII disable(CodeGenFunction &CGF, const OMPExecutableDirective &S)
Manages list of nontemporal decls for the specified directive.
Struct that keeps all the relevant information that should be kept throughout a 'target data' region.
llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap
Map between the a declaration of a capture and the corresponding new llvm address where the runtime r...
Manages list of nontemporal decls for the specified directive.
virtual void emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, const OMPExecutableDirective &D, llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, const Expr *IfCond, const OMPTaskDataTy &Data)
Emit task region for the task directive.
virtual llvm::Value * emitForNext(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned, Address IL, Address LB, Address UB, Address ST)
Call __kmpc_dispatch_next( ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, kmp_int[32|64] *p_lowe...
virtual void emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars, const Expr *IfCond, llvm::Value *NumThreads, OpenMPNumThreadsClauseModifier NumThreadsModifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, const Expr *Message=nullptr)
Emits code for parallel or serial call of the OutlinedFn with variables captured in a record which ad...
virtual void emitNumThreadsClause(CodeGenFunction &CGF, llvm::Value *NumThreads, SourceLocation Loc, OpenMPNumThreadsClauseModifier Modifier=OMPC_NUMTHREADS_unknown, OpenMPSeverityClauseKind Severity=OMPC_SEVERITY_fatal, SourceLocation SeverityLoc=SourceLocation(), const Expr *Message=nullptr, SourceLocation MessageLoc=SourceLocation())
Emits call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32global_tid, kmp_int32 num_threads) ...
virtual Address getTaskReductionItem(CodeGenFunction &CGF, SourceLocation Loc, llvm::Value *ReductionsPtr, LValue SharedLVal)
Get the address of void * type of the privatue copy of the reduction item specified by the SharedLVal...
virtual void emitForDispatchDeinit(CodeGenFunction &CGF, SourceLocation Loc)
This is used for non static scheduled types and when the ordered clause is present on the loop constr...
virtual void emitTeamsCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, SourceLocation Loc, llvm::Function *OutlinedFn, ArrayRef< llvm::Value * > CapturedVars)
Emits code for teams call of the OutlinedFn with variables captured in a record which address is stor...
virtual const VarDecl * translateParameter(const FieldDecl *FD, const VarDecl *NativeParam) const
Translates the native parameter of outlined function if this is required for target.
virtual llvm::Function * emitTeamsOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP teams directive D.
virtual void emitDoacrossInit(CodeGenFunction &CGF, const OMPLoopDirective &D, ArrayRef< Expr * > NumIterations)
Emit initialization for doacross loop nesting support.
virtual void adjustTargetSpecificDataForLambdas(CodeGenFunction &CGF, const OMPExecutableDirective &D) const
Adjust some parameters for the target-based directives, like addresses of the variables captured by r...
virtual Address getParameterAddress(CodeGenFunction &CGF, const VarDecl *NativeParam, const VarDecl *TargetParam) const
Gets the address of the native argument basing on the address of the target-specific parameter.
virtual void emitNumTeamsClause(CodeGenFunction &CGF, const Expr *NumTeams, const Expr *ThreadLimit, SourceLocation Loc)
Emits call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32global_tid, kmp_int32 num_teams,...
virtual llvm::Value * emitTaskReductionInit(CodeGenFunction &CGF, SourceLocation Loc, ArrayRef< const Expr * > LHSExprs, ArrayRef< const Expr * > RHSExprs, const OMPTaskDataTy &Data)
Emit a code for initialization of task reduction clause.
virtual void emitFlush(CodeGenFunction &CGF, ArrayRef< const Expr * > Vars, SourceLocation Loc, llvm::AtomicOrdering AO)
Emit flush of the variables specified in 'omp flush' directive.
virtual void emitProcBindClause(CodeGenFunction &CGF, llvm::omp::ProcBindKind ProcBind, SourceLocation Loc)
Emit call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32global_tid, int proc_bind) to generate...
virtual void emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind Kind, bool EmitChecks=true, bool ForceSimpleCall=false)
Emit an implicit/explicit barrier for OpenMP threads.
virtual void emitDistributeStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values)
virtual void emitForStaticFinish(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind)
Call the appropriate runtime routine to notify that we finished all the work with current loop.
void emitIfClause(CodeGenFunction &CGF, const Expr *Cond, const RegionCodeGenTy &ThenGen, const RegionCodeGenTy &ElseGen)
Emits code for OpenMP 'if' clause using specified CodeGen function.
virtual llvm::Function * emitParallelOutlinedFunction(CodeGenFunction &CGF, const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
Emits outlined function for the specified OpenMP parallel directive D.
virtual void emitForStaticInit(CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values)
Call the appropriate runtime routine to initialize it before start of loop.
virtual bool isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static non-chunked.
virtual void emitMasterRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MasterOpGen, SourceLocation Loc)
Emits a master region.
virtual void emitTaskReductionFixups(CodeGenFunction &CGF, SourceLocation Loc, ReductionCodeGen &RCG, unsigned N)
Required to resolve existing problems in the runtime.
virtual void checkAndEmitLastprivateConditional(CodeGenFunction &CGF, const Expr *LHS)
Checks if the provided LVal is lastprivate conditional and emits the code to update the value of the ...
llvm::OpenMPIRBuilder & getOMPBuilder()
virtual void emitTargetOutlinedFunction(const OMPExecutableDirective &D, StringRef ParentName, llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, bool IsOffloadEntry, const RegionCodeGenTy &CodeGen)
Emit outilined function for 'target' directive.
virtual void emitForOrderedIterationEnd(CodeGenFunction &CGF, SourceLocation Loc, unsigned IVSize, bool IVSigned)
Call the appropriate runtime routine to notify that we finished iteration of the ordered loop with th...
virtual void checkAndEmitSharedLastprivateConditional(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::DenseSet< CanonicalDeclPtr< const VarDecl > > &IgnoredDecls)
Checks if the lastprivate conditional was updated in inner region and writes the value.
virtual void emitInlinedDirective(CodeGenFunction &CGF, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, bool HasCancel=false)
Emit code for the directive that does not require outlining.
virtual bool isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, bool Chunked) const
Check if the specified ScheduleKind is static chunked.
virtual void emitTargetCall(CodeGenFunction &CGF, const OMPExecutableDirective &D, llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, llvm::PointerIntPair< const Expr *, 2, OpenMPDeviceClauseModifier > Device, llvm::function_ref< llvm::Value *(CodeGenFunction &CGF, const OMPLoopDirective &D)> SizeEmitter)
Emit the target offloading code associated with D.
virtual bool isDynamic(OpenMPScheduleClauseKind ScheduleKind) const
Check if the specified ScheduleKind is dynamic.
virtual void emitMaskedRegion(CodeGenFunction &CGF, const RegionCodeGenTy &MaskedOpGen, SourceLocation Loc, const Expr *Filter=nullptr)
Emits a masked region.
virtual void emitForDispatchInit(CodeGenFunction &CGF, SourceLocation Loc, const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, bool Ordered, const DispatchRTInput &DispatchValues)
Call the appropriate runtime routine to initialize it before start of loop.
Address getAllocatedAddress() const
Returns the raw, allocated address, which is not necessarily the address of the object itself.
API for captured statement code generation.
virtual const FieldDecl * lookup(const VarDecl *VD) const
Lookup the captured field decl for a variable.
RAII for correct setting/restoring of CapturedStmtInfo.
LValue getReferenceLValue(CodeGenFunction &CGF, const Expr *RefExpr) const
void ForceCleanup()
Force the emission of cleanups now, instead of waiting until this object is destroyed.
RAII for preserving necessary info during inlined region body codegen.
Cleanup action for allocate support.
RAII for preserving necessary info during Outlined region body codegen.
Controls insertion of cancellation exit blocks in worksharing constructs.
Save/restore original map of previously emitted local vars in case when we need to duplicate emission...
The class used to assign some variables some temporarily addresses.
bool apply(CodeGenFunction &CGF)
Applies new addresses to the list of the variables.
void restore(CodeGenFunction &CGF)
Restores original addresses of the variables.
bool setVarAddr(CodeGenFunction &CGF, const VarDecl *LocalVD, Address TempAddr)
Sets the address of the variable LocalVD to be TempAddr in function CGF.
The scope used to remap some variables as private in the OpenMP loop body (or other captured region e...
void restoreMap()
Restore all mapped variables w/o clean up.
bool Privatize()
Privatizes local variables previously registered as private.
bool addPrivate(const VarDecl *LocalVD, Address Addr)
Registers LocalVD variable as a private with Addr as the address of the corresponding private variabl...
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
Manages parent directive for scan directives.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
void ForceCleanup(std::initializer_list< llvm::Value ** > ValuesToReload={})
Force the emission of cleanups now, instead of waiting until this object is destroyed.
bool requiresCleanups() const
Determine whether this scope requires any cleanups.
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void EmitOMPParallelMaskedTaskLoopDirective(const OMPParallelMaskedTaskLoopDirective &S)
void EmitOMPParallelMaskedDirective(const OMPParallelMaskedDirective &S)
void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S)
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount, Stmt::Likelihood LH=Stmt::LH_None, const Expr *ConditionalOp=nullptr, const VarDecl *ConditionalDecl=nullptr)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
void EmitOMPLastprivateClauseFinal(const OMPExecutableDirective &D, bool NoFinals, llvm::Value *IsLastIterCond=nullptr)
Emit final copying of lastprivate values to original variables at the end of the worksharing or simd ...
void processInReduction(const OMPExecutableDirective &S, OMPTaskDataTy &Data, CodeGenFunction &CGF, const CapturedStmt *CS, OMPPrivateScope &Scope)
JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target)
The given basic block lies in the current EH scope, but may be a target of a potentially scope-crossi...
void EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S)
void emitOMPSimpleStore(LValue LVal, RValue RVal, QualType RValTy, SourceLocation Loc)
static void EmitOMPTargetParallelDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelDirective &S)
void EmitOMPCanonicalLoop(const OMPCanonicalLoop *S)
Emit an OMPCanonicalLoop using the OpenMPIRBuilder.
void EmitOMPGenericLoopDirective(const OMPGenericLoopDirective &S)
void EmitOMPScanDirective(const OMPScanDirective &S)
static bool hasScalarEvaluationKind(QualType T)
llvm::function_ref< std::pair< llvm::Value *, llvm::Value * >(CodeGenFunction &, const OMPExecutableDirective &S, Address LB, Address UB)> CodeGenDispatchBoundsTy
LValue InitCapturedStruct(const CapturedStmt &S)
CGCapturedStmtInfo * CapturedStmtInfo
void EmitOMPDistributeDirective(const OMPDistributeDirective &S)
void EmitOMPParallelForDirective(const OMPParallelForDirective &S)
void EmitOMPMasterDirective(const OMPMasterDirective &S)
void EmitOMPParallelMasterTaskLoopSimdDirective(const OMPParallelMasterTaskLoopSimdDirective &S)
void EmitOMPSimdInit(const OMPLoopDirective &D)
Helpers for the OpenMP loop directives.
const OMPExecutableDirective * OMPParentLoopDirectiveForScan
Parent loop-based directive for scan directive.
void EmitOMPFlushDirective(const OMPFlushDirective &S)
static void EmitOMPTargetDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetDirective &S)
Emit device code for the target directive.
bool EmitOMPFirstprivateClause(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
void EmitOMPTaskgroupDirective(const OMPTaskgroupDirective &S)
void EmitOMPTargetTeamsDistributeParallelForSimdDirective(const OMPTargetTeamsDistributeParallelForSimdDirective &S)
static void EmitOMPTargetTeamsDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDirective &S)
Emit device code for the target teams directive.
void EmitOMPReductionClauseInit(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope, bool ForInscan=false)
Emit initial code for reduction variables.
void EmitOMPDistributeSimdDirective(const OMPDistributeSimdDirective &S)
void EmitAutoVarDecl(const VarDecl &D)
EmitAutoVarDecl - Emit an auto variable declaration.
static void EmitOMPTargetTeamsDistributeDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeDirective &S)
Emit device code for the target teams distribute directive.
llvm::Function * GenerateOpenMPCapturedStmtFunctionAggregate(const CapturedStmt &S, const OMPExecutableDirective &D)
void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
void EmitOMPTargetParallelForDirective(const OMPTargetParallelForDirective &S)
const LangOptions & getLangOpts() const
LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
EmitAutoVarAlloca - Emit the alloca and debug information for a local variable.
void EmitAtomicUpdate(LValue LVal, llvm::AtomicOrdering AO, const llvm::function_ref< RValue(RValue)> &UpdateOp, bool IsVolatile)
Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr)
Load a pointer with type PtrTy stored at address Ptr.
void EmitBranchThroughCleanup(JumpDest Dest)
EmitBranchThroughCleanup - Emit a branch from the current insert block through the normal cleanup han...
void EmitOMPReductionClauseFinal(const OMPExecutableDirective &D, const OpenMPDirectiveKind ReductionKind)
Emit final update of reduction values to original variables at the end of the directive.
void EmitOMPLoopBody(const OMPLoopDirective &D, JumpDest LoopExit)
Helper for the OpenMP loop directives.
void EmitOMPScopeDirective(const OMPScopeDirective &S)
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
llvm::AssertingVH< llvm::Instruction > AllocaInsertPt
AllocaInsertPoint - This is an instruction in the entry block before which we prefer to insert alloca...
void EmitAggregateAssign(LValue Dest, LValue Src, QualType EltTy)
Emit an aggregate assignment.
CodeGenFunction * ParentCGF
JumpDest ReturnBlock
ReturnBlock - Unified return block.
void EmitOMPTargetTeamsDistributeSimdDirective(const OMPTargetTeamsDistributeSimdDirective &S)
const llvm::function_ref< void(CodeGenFunction &, llvm::Function *, const OMPTaskDataTy &)> TaskGenTy
llvm::DebugLoc SourceLocToDebugLoc(SourceLocation Location)
Converts Location to a DebugLoc, if debug information is enabled.
bool EmitOMPCopyinClause(const OMPExecutableDirective &D)
Emit code for copyin clause in D directive.
void EmitOMPLinearClause(const OMPLoopDirective &D, CodeGenFunction::OMPPrivateScope &PrivateScope)
Emit initial code for linear clauses.
llvm::BasicBlock * OMPBeforeScanBlock
void EmitOMPInterchangeDirective(const OMPInterchangeDirective &S)
void EmitOMPPrivateLoopCounters(const OMPLoopDirective &S, OMPPrivateScope &LoopScope)
Emit initial code for loop counters of loop-based directives.
void GenerateOpenMPCapturedVars(const CapturedStmt &S, SmallVectorImpl< llvm::Value * > &CapturedVars)
void EmitOMPDepobjDirective(const OMPDepobjDirective &S)
void EmitOMPMetaDirective(const OMPMetaDirective &S)
void EmitOMPCriticalDirective(const OMPCriticalDirective &S)
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
void EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S)
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
void EmitOMPCancelDirective(const OMPCancelDirective &S)
void EmitOMPBarrierDirective(const OMPBarrierDirective &S)
llvm::Value * EmitComplexToScalarConversion(ComplexPairTy Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified complex type to the specified destination type,...
void EmitOMPOrderedDirective(const OMPOrderedDirective &S)
bool EmitOMPWorksharingLoop(const OMPLoopDirective &S, Expr *EUB, const CodeGenLoopBoundsTy &CodeGenLoopBounds, const CodeGenDispatchBoundsTy &CGDispatchBounds)
Emit code for the worksharing loop-based directive.
LValue EmitOMPSharedLValue(const Expr *E)
Emits the lvalue for the expression with possibly captured variable.
llvm::CanonicalLoopInfo * EmitOMPCollapsedCanonicalLoopNest(const Stmt *S, int Depth)
Emit the Stmt S and return its topmost canonical loop, if any.
void EmitOMPSectionsDirective(const OMPSectionsDirective &S)
void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc=SourceLocation(), SourceLocation StartLoc=SourceLocation())
Emit code for the start of a function.
void EmitOMPInteropDirective(const OMPInteropDirective &S)
void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S)
void EmitOMPTargetParallelDirective(const OMPTargetParallelDirective &S)
void EmitOMPCopy(QualType OriginalType, Address DestAddr, Address SrcAddr, const VarDecl *DestVD, const VarDecl *SrcVD, const Expr *Copy)
Emit proper copying of data from one variable to another.
llvm::Value * EvaluateExprAsBool(const Expr *E)
EvaluateExprAsBool - Perform the usual unary conversions on the specified expression and compare the ...
JumpDest getOMPCancelDestination(OpenMPDirectiveKind Kind)
void EmitOMPTargetParallelForSimdDirective(const OMPTargetParallelForSimdDirective &S)
void EmitOMPTargetParallelGenericLoopDirective(const OMPTargetParallelGenericLoopDirective &S)
Emit combined directive 'target parallel loop' as if its constituent constructs are 'target',...
void EmitOMPUseDeviceAddrClause(const OMPUseDeviceAddrClause &C, OMPPrivateScope &PrivateScope, const llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap)
void EmitOMPTeamsDistributeParallelForSimdDirective(const OMPTeamsDistributeParallelForSimdDirective &S)
void EmitOMPMaskedDirective(const OMPMaskedDirective &S)
llvm::Value * emitArrayLength(const ArrayType *arrayType, QualType &baseType, Address &addr)
emitArrayLength - Compute the length of an array, even if it's a VLA, and drill down to the base elem...
void EmitOMPAggregateAssign(Address DestAddr, Address SrcAddr, QualType OriginalType, const llvm::function_ref< void(Address, Address)> CopyGen)
Perform element by element copying of arrays with type OriginalType from SrcAddr to DestAddr using co...
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
void EmitOMPTeamsDistributeSimdDirective(const OMPTeamsDistributeSimdDirective &S)
RValue EmitAtomicLoad(LValue LV, SourceLocation SL, AggValueSlot Slot=AggValueSlot::ignored())
CGDebugInfo * getDebugInfo()
void EmitOMPDistributeLoop(const OMPLoopDirective &S, const CodeGenLoopTy &CodeGenLoop, Expr *IncExpr)
Emit code for the distribute loop-based directive.
void EmitOMPMasterTaskLoopDirective(const OMPMasterTaskLoopDirective &S)
void EmitOMPReverseDirective(const OMPReverseDirective &S)
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
void EmitOMPCancellationPointDirective(const OMPCancellationPointDirective &S)
void EmitOMPTargetTeamsDistributeParallelForDirective(const OMPTargetTeamsDistributeParallelForDirective &S)
void EmitOMPMaskedTaskLoopDirective(const OMPMaskedTaskLoopDirective &S)
llvm::BasicBlock * OMPScanDispatch
llvm::function_ref< std::pair< LValue, LValue >(CodeGenFunction &, const OMPExecutableDirective &S)> CodeGenLoopBoundsTy
void EmitOMPTargetExitDataDirective(const OMPTargetExitDataDirective &S)
void EmitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &S)
void EmitOMPMaskedTaskLoopSimdDirective(const OMPMaskedTaskLoopSimdDirective &S)
std::pair< bool, RValue > EmitOMPAtomicSimpleUpdateExpr(LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart, llvm::AtomicOrdering AO, SourceLocation Loc, const llvm::function_ref< RValue(RValue)> CommonGen)
Emit atomic update code for constructs: X = X BO E or X = E BO E.
VlaSizePair getVLASize(const VariableArrayType *vla)
Returns an LLVM value that corresponds to the size, in non-variably-sized elements,...
void EmitOMPParallelDirective(const OMPParallelDirective &S)
void EmitOMPTaskDirective(const OMPTaskDirective &S)
void EmitOMPMasterTaskLoopSimdDirective(const OMPMasterTaskLoopSimdDirective &S)
void EmitOMPDistributeParallelForDirective(const OMPDistributeParallelForDirective &S)
void EmitOMPAssumeDirective(const OMPAssumeDirective &S)
int ExpectedOMPLoopDepth
Number of nested loop to be consumed by the last surrounding loop-associated directive.
void EmitOMPPrivateClause(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
void EmitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &S)
ASTContext & getContext() const
void EmitStopPoint(const Stmt *S)
EmitStopPoint - Emit a debug stoppoint if we are emitting debug info.
void EmitOMPTargetUpdateDirective(const OMPTargetUpdateDirective &S)
llvm::Value * EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty, SourceLocation Loc, AlignmentSource Source=AlignmentSource::Type, bool isNontemporal=false)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
void EmitOMPTargetTeamsGenericLoopDirective(const OMPTargetTeamsGenericLoopDirective &S)
void EmitStoreOfComplex(ComplexPairTy V, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
void EmitAutoVarCleanups(const AutoVarEmission &emission)
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
SmallVector< llvm::CanonicalLoopInfo *, 4 > OMPLoopNestStack
List of recently emitted OMPCanonicalLoops.
void EmitOMPTeamsDistributeParallelForDirective(const OMPTeamsDistributeParallelForDirective &S)
llvm::AtomicRMWInst * emitAtomicRMWInst(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val, llvm::AtomicOrdering Order=llvm::AtomicOrdering::SequentiallyConsistent, llvm::SyncScope::ID SSID=llvm::SyncScope::System, const AtomicExpr *AE=nullptr)
Emit an atomicrmw instruction, and applying relevant metadata when applicable.
void EmitOMPFuseDirective(const OMPFuseDirective &S)
void EmitOMPTargetTeamsDistributeDirective(const OMPTargetTeamsDistributeDirective &S)
void EmitOMPUseDevicePtrClause(const OMPUseDevicePtrClause &C, OMPPrivateScope &PrivateScope, const llvm::DenseMap< const ValueDecl *, llvm::Value * > CaptureDeviceAddrMap)
RValue EmitAnyExpr(const Expr *E, AggValueSlot aggSlot=AggValueSlot::ignored(), bool ignoreResult=false)
EmitAnyExpr - Emit code to compute the specified expression which can have any type.
void EmitStmt(const Stmt *S, ArrayRef< const Attr * > Attrs={})
EmitStmt - Emit the code for the statement.
llvm::DenseMap< const ValueDecl *, FieldDecl * > LambdaCaptureFields
void EmitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &S)
llvm::Type * ConvertTypeForMem(QualType T)
void EmitOMPInnerLoop(const OMPExecutableDirective &S, bool RequiresCleanup, const Expr *LoopCond, const Expr *IncExpr, const llvm::function_ref< void(CodeGenFunction &)> BodyGen, const llvm::function_ref< void(CodeGenFunction &)> PostIncGen)
Emit inner loop of the worksharing/simd construct.
void EmitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective &S)
static void EmitOMPTargetTeamsDistributeParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForDirective &S)
void EmitOMPTargetDirective(const OMPTargetDirective &S)
static void EmitOMPTargetParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForSimdDirective &S)
Emit device code for the target parallel for simd directive.
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
llvm::BasicBlock * OMPScanExitBlock
void EmitOMPTeamsDirective(const OMPTeamsDirective &S)
void EmitSimpleOMPExecutableDirective(const OMPExecutableDirective &D)
Emit simple code for OpenMP directives in Simd-only mode.
void EmitOMPErrorDirective(const OMPErrorDirective &S)
void EmitOMPTargetTaskBasedDirective(const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen, OMPTargetDataInfo &InputInfo)
void EmitOMPParallelMaskedTaskLoopSimdDirective(const OMPParallelMaskedTaskLoopSimdDirective &S)
void EmitOMPTargetTeamsDirective(const OMPTargetTeamsDirective &S)
void EmitOMPTargetDataDirective(const OMPTargetDataDirective &S)
Address GenerateCapturedStmtArgument(const CapturedStmt &S)
bool EmitOMPLastprivateClauseInit(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
Emit initial code for lastprivate variables.
static void EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForSimdDirective &S)
Emit device code for the target teams distribute parallel for simd directive.
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block,...
llvm::Function * GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S, const OMPExecutableDirective &D)
void EmitOMPSimdDirective(const OMPSimdDirective &S)
RawAddress CreateMemTemp(QualType T, const Twine &Name="tmp", RawAddress *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
Address EmitLoadOfReference(LValue RefLVal, LValueBaseInfo *PointeeBaseInfo=nullptr, TBAAAccessInfo *PointeeTBAAInfo=nullptr)
void EmitOMPParallelGenericLoopDirective(const OMPLoopDirective &S)
void EmitOMPTargetSimdDirective(const OMPTargetSimdDirective &S)
void EmitOMPTeamsGenericLoopDirective(const OMPTeamsGenericLoopDirective &S)
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
bool EmitOMPLinearClauseInit(const OMPLoopDirective &D)
Emit initial code for linear variables.
static void EmitOMPTargetParallelGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelGenericLoopDirective &S)
Emit device code for the target parallel loop directive.
void EmitOMPUnrollDirective(const OMPUnrollDirective &S)
void EmitOMPStripeDirective(const OMPStripeDirective &S)
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type,...
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
void EmitOMPSingleDirective(const OMPSingleDirective &S)
void FinishFunction(SourceLocation EndLoc=SourceLocation())
FinishFunction - Complete IR generation of the current function.
llvm::function_ref< void(CodeGenFunction &, SourceLocation, const unsigned, const bool)> CodeGenOrderedTy
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
llvm::Value * EmitFromMemory(llvm::Value *Value, QualType Ty)
EmitFromMemory - Change a scalar value from its memory representation to its value representation.
static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S)
Emit device code for the target simd directive.
llvm::Function * GenerateCapturedStmtFunction(const CapturedStmt &S)
Creates the outlined function for a CapturedStmt.
static void EmitOMPTargetParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForDirective &S)
Emit device code for the target parallel for directive.
uint64_t getProfileCount(const Stmt *S)
Get the profiler's count for the given statement.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)
ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant,...
static void EmitOMPTargetTeamsGenericLoopDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsGenericLoopDirective &S)
Emit device code for the target teams loop directive.
void EmitOMPTileDirective(const OMPTileDirective &S)
void EmitDecl(const Decl &D, bool EvaluateConditionDecl=false)
EmitDecl - Emit a declaration.
void EmitOMPAtomicDirective(const OMPAtomicDirective &S)
llvm::BasicBlock * OMPAfterScanBlock
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
ConstantEmission tryEmitAsConstant(const DeclRefExpr *RefExpr)
Try to emit a reference to the given value without producing it as an l-value.
LValue EmitLValue(const Expr *E, KnownNonNull_t IsKnownNonNull=NotKnownNonNull)
EmitLValue - Emit code to compute a designator that specifies the location of the expression.
void EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst)
Store of global named registers are always calls to intrinsics.
void EmitOMPParallelMasterTaskLoopDirective(const OMPParallelMasterTaskLoopDirective &S)
void EmitOMPDistributeParallelForSimdDirective(const OMPDistributeParallelForSimdDirective &S)
void EmitOMPSectionDirective(const OMPSectionDirective &S)
void EnsureInsertPoint()
EnsureInsertPoint - Ensure that an insertion point is defined so that emitted IR has a place to go.
void EmitOMPForSimdDirective(const OMPForSimdDirective &S)
llvm::LLVMContext & getLLVMContext()
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
void emitAlignmentAssumption(llvm::Value *PtrValue, QualType Ty, SourceLocation Loc, SourceLocation AssumptionLoc, llvm::Value *Alignment, llvm::Value *OffsetValue=nullptr)
static void EmitOMPTargetTeamsDistributeSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeSimdDirective &S)
Emit device code for the target teams distribute simd directive.
llvm::function_ref< void(CodeGenFunction &, const OMPLoopDirective &, JumpDest)> CodeGenLoopTy
llvm::Value * EmitScalarConversion(llvm::Value *Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified type to the specified destination type, both of which are LLVM s...
bool isTrivialInitializer(const Expr *Init)
Determine whether the given initializer is trivial in the sense that it requires no code to be genera...
void EmitOMPParallelMasterDirective(const OMPParallelMasterDirective &S)
void EmitOMPTaskBasedDirective(const OMPExecutableDirective &S, const OpenMPDirectiveKind CapturedRegion, const RegionCodeGenTy &BodyGen, const TaskGenTy &TaskGen, OMPTaskDataTy &Data)
void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, QualType Ty, AlignmentSource Source=AlignmentSource::Type, bool isInit=false, bool isNontemporal=false)
EmitStoreOfScalar - Store a scalar value to an address, taking care to appropriately convert from the...
void EmitOMPForDirective(const OMPForDirective &S)
void EmitOMPLinearClauseFinal(const OMPLoopDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
Emit final code for linear clauses.
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
void EmitExprAsInit(const Expr *init, const ValueDecl *D, LValue lvalue, bool capturedByInit)
EmitExprAsInit - Emits the code necessary to initialize a location in memory with the given initializ...
void EmitOMPSimdFinal(const OMPLoopDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
This class organizes the cross-function state that is used while generating LLVM code.
void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)
Set the attributes on the LLVM function for the given decl and function info.
llvm::Module & getModule() const
DiagnosticsEngine & getDiags() const
const LangOptions & getLangOpts() const
CodeGenTypes & getTypes()
const llvm::DataLayout & getDataLayout() const
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
ASTContext & getContext() const
const CodeGenOptions & getCodeGenOpts() const
StringRef getMangledName(GlobalDecl GD)
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
const CGFunctionInfo & arrangeDeviceKernelCallerDeclaration(QualType resultType, const FunctionArgList &args)
A device kernel caller function is an offload device entry point function with a target device depend...
FunctionArgList - Type for representing both the decl and type of parameters to a function.
LValue - This represents an lvalue references.
llvm::Value * getPointer(CodeGenFunction &CGF) const
Address getAddress() const
void setAddress(Address address)
A stack of loop information corresponding to loop nesting levels.
void setVectorizeWidth(unsigned W)
Set the vectorize width for the next loop pushed.
void setParallel(bool Enable=true)
Set the next pushed loop as parallel.
void push(llvm::BasicBlock *Header, const llvm::DebugLoc &StartLoc, const llvm::DebugLoc &EndLoc)
Begin a new structured loop.
void setVectorizeEnable(bool Enable=true)
Set the next pushed loop 'vectorize.enable'.
A basic class for pre|post-action for advanced codegen sequence for OpenMP region.
virtual void Enter(CodeGenFunction &CGF)
RValue - This trivial value class is used to represent the result of an expression that is evaluated.
static RValue get(llvm::Value *V)
static RValue getComplex(llvm::Value *V1, llvm::Value *V2)
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
std::pair< llvm::Value *, llvm::Value * > getComplexVal() const
getComplexVal - Return the real/imag components of this complex value.
An abstract representation of an aligned address.
llvm::PointerType * getType() const
Return the type of the pointer value.
llvm::Value * getPointer() const
Class intended to support codegen of all kind of the reduction clauses.
LValue getSharedLValue(unsigned N) const
Returns LValue for the reduction item.
void emitAggregateType(CodeGenFunction &CGF, unsigned N)
Emits the code for the variable-modified type, if required.
const VarDecl * getBaseDecl(unsigned N) const
Returns the base declaration of the reduction item.
void emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N)
Emits lvalue for the shared and original reduction item.
void emitInitialization(CodeGenFunction &CGF, unsigned N, Address PrivateAddr, Address SharedAddr, llvm::function_ref< bool(CodeGenFunction &)> DefaultInit)
Performs initialization of the private copy for the reduction item.
Address adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Adjusts PrivatedAddr for using instead of the original variable address in normal operations.
Class provides a way to call simple version of codegen for OpenMP region, or an advanced with possibl...
void setAction(PrePostActionTy &Action) const
Complex values, per C99 6.2.5p11.
CompoundStmt - This represents a group of statements like { stmt stmt }.
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
A reference to a declared variable, function, enum, etc.
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Decl - This represents one declaration (or definition), e.g.
SourceLocation getBodyRBrace() const
getBodyRBrace - Gets the right brace of the body, if a body exists.
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
SourceLocation getLocation() const
The name of a declaration.
SourceLocation getBeginLoc() const LLVM_READONLY
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
This represents one expression.
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Expr * IgnoreImplicitAsWritten() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
Represents a function declaration or definition.
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin=false, bool isInlineSpecified=false, bool hasWrittenPrototype=true, ConstexprSpecKind ConstexprKind=ConstexprSpecKind::Unspecified, const AssociatedConstraint &TrailingRequiresClause={})
GlobalDecl - represents a global declaration.
One of these records is kept for each identifier that is lexed.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
std::vector< llvm::Triple > OMPTargetTriples
Triples of the OpenMP targets that the host code codegen should take into account in order to generat...
Represents a point when we exit a loop.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
A C++ nested-name-specifier augmented with source location information.
static OMPClauseWithPreInit * get(OMPClause *C)
This is a basic class for representing single OpenMP clause.
This represents 'final' clause in the 'pragma omp ...' directive.
Representation of the 'full' clause of the 'pragma omp unroll' directive.
This represents 'if' clause in the 'pragma omp ...' directive.
This represents 'num_threads' clause in the 'pragma omp ...' directive.
Representation of the 'partial' clause of the 'pragma omp unroll' directive.
This represents 'safelen' clause in the 'pragma omp ...' directive.
This represents 'simdlen' clause in the 'pragma omp ...' directive.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
PointerType - C99 6.7.5.1 - Pointer Declarators.
Represents an unpacked "presumed" location which can be presented to the user.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
If a crash happens while one of these objects are live, the message is printed out along with the spe...
A (possibly-)qualified type.
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.
unsigned getNumFields() const
Returns the number of fields (non-static data members) in this record.
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.
Stmt - This represents one statement.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
SourceLocation getBeginLoc() const LLVM_READONLY
bool isPointerType() const
const T * castAs() const
Member-template castAs<specific type>.
bool isReferenceType() const
bool isLValueReferenceType() const
bool isAnyComplexType() const
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
static UnaryOperator * Create(const ASTContext &C, Expr *input, Opcode opc, QualType type, ExprValueKind VK, ExprObjectKind OK, SourceLocation l, bool CanOverflow, FPOptionsOverride FPFeatures)
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
TLSKind getTLSKind() const
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
@ CInit
C-style initialization with assignment.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
const Expr * getInit() const
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
@ TLS_None
Not a TLS variable.
Represents a C array with a specified size that is not an integer-constant-expression.
Expr * getSizeExpr() const
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
bool Inc(InterpState &S, CodePtr OpPC, bool CanOverflow)
1) Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value increased by ...
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool needsTaskBasedThreadLimit(OpenMPDirectiveKind DKind)
Checks if the specified target directive, combined or not, needs task based thread_limit.
@ Ctor_Complete
Complete object ctor.
Privates[]
This class represents the 'transparent' clause in the 'pragma omp task' directive.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
@ OK_Ordinary
An ordinary object is located at an address in memory.
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ Tile
'tile' clause, allowed on 'loop' and Combined constructs.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
@ OMPC_SCHEDULE_MODIFIER_unknown
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
@ OMPC_DIST_SCHEDULE_unknown
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
bool isOpenMPGenericLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive constitutes a 'loop' directive in the outermost nest.
OpenMPBindClauseKind
OpenMP bindings for the 'bind' clause.
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
bool IsXLHSInRHSPart
True if UE has the first form and false if the second.
bool IsPostfixUpdate
True if original value of 'x' must be stored in 'v', not an updated one.
@ Dtor_Complete
Complete object dtor.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of the composite or combined directives that need loop ...
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPNumThreadsClauseModifier
@ OMPC_NUMTHREADS_unknown
bool IsFailOnly
True if 'v' is updated only when the condition is false (compare capture only).
U cast(CodeGen::Address addr)
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
@ ThreadPrivateVar
Parameter for Thread private variable.
@ Other
Other implicit parameter.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
A jump destination is an abstract label, branching to which may require a jump out through normal cle...
llvm::BasicBlock * getBlock() const
static Address getAddrOfThreadPrivate(CodeGenFunction &CGF, const VarDecl *VD, Address VDAddr, SourceLocation Loc)
Returns address of the threadprivate variable for the current thread.
llvm::OpenMPIRBuilder::InsertPointTy InsertPointTy
static void EmitOMPOutlinedRegionBody(CodeGenFunction &CGF, const Stmt *RegionBodyStmt, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Twine RegionName)
Emit the body of an OMP region that will be outlined in OpenMPIRBuilder::finalize().
static Address getAddressOfLocalVariable(CodeGenFunction &CGF, const VarDecl *VD)
Gets the OpenMP-specific address of the local variable /p VD.
static void EmitCaptureStmt(CodeGenFunction &CGF, InsertPointTy CodeGenIP, llvm::BasicBlock &FiniBB, llvm::Function *Fn, ArrayRef< llvm::Value * > Args)
static std::string getNameWithSeparators(ArrayRef< StringRef > Parts, StringRef FirstSeparator=".", StringRef Separator=".")
Get the platform-specific name separator.
static void FinalizeOMPRegion(CodeGenFunction &CGF, InsertPointTy IP)
Emit the Finalization for an OMP region.
static void EmitOMPInlinedRegionBody(CodeGenFunction &CGF, const Stmt *RegionBodyStmt, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Twine RegionName)
Emit the body of an OMP region.
unsigned NumberOfTargetItems
Address BasePointersArray
llvm::PointerType * VoidPtrTy
llvm::IntegerType * Int64Ty
llvm::IntegerType * SizeTy
llvm::IntegerType * IntPtrTy
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