22 #include "llvm/IR/CallSite.h" 23 using namespace clang;
24 using namespace CodeGen;
31 for (
const auto *C : S.
clauses()) {
33 if (
const auto *PreInit =
34 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
35 for (
const auto *I : PreInit->decls()) {
36 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
60 const bool EmitPreInitStmt =
true)
64 emitPreInitStmt(CGF, S);
65 if (!CapturedRegion.hasValue())
68 "Expected associated statement for inlined directive.");
70 for (
const auto &C : CS->captures()) {
71 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
72 auto *VD =
C.getCapturedVar();
74 "Canonical decl must be captured.");
91 class OMPParallelScope final :
public OMPLexicalScope {
101 : OMPLexicalScope(CGF, S,
llvm::
None,
102 EmitPreInitStmt(S)) {}
107 class OMPTeamsScope final :
public OMPLexicalScope {
116 : OMPLexicalScope(CGF, S,
llvm::
None,
117 EmitPreInitStmt(S)) {}
125 for (
const auto *E : S.
counters()) {
126 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
130 (void)PreCondVars.
apply(CGF);
131 if (
const auto *PreInits = cast_or_null<DeclStmt>(S.
getPreInits())) {
132 for (
const auto *I : PreInits->decls())
141 emitPreInitStmt(CGF, S);
152 cast<BlockDecl>(CGF.
CurCodeDecl)->capturesVariable(VD));
158 InlinedShareds(CGF) {
159 for (
const auto *C : S.
clauses()) {
161 if (
const auto *PreInit =
162 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
163 for (
const auto *I : PreInit->decls()) {
164 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
173 }
else if (
const auto *UDP = dyn_cast<OMPUseDevicePtrClause>(C)) {
174 for (
const Expr *E : UDP->varlists()) {
175 const Decl *D = cast<DeclRefExpr>(E)->getDecl();
176 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
183 if (
const auto *TG = dyn_cast<OMPTaskgroupDirective>(&S)) {
184 if (
const Expr *E = TG->getReductionRef())
185 CGF.
EmitVarDecl(*cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()));
189 for (
auto &C : CS->captures()) {
190 if (
C.capturesVariable() ||
C.capturesVariableByCopy()) {
191 auto *VD =
C.getCapturedVar();
193 "Canonical decl must be captured.");
195 isCapturedVar(CGF, VD) ||
218 if (
const auto *OrigDRE = dyn_cast<DeclRefExpr>(E)) {
219 if (
const auto *OrigVD = dyn_cast<VarDecl>(OrigDRE->getDecl())) {
220 OrigVD = OrigVD->getCanonicalDecl();
222 LambdaCaptureFields.lookup(OrigVD) ||
223 (CapturedStmtInfo && CapturedStmtInfo->lookup(OrigVD)) ||
224 (CurCodeDecl && isa<BlockDecl>(CurCodeDecl));
225 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD), IsCaptured,
226 OrigDRE->getType(),
VK_LValue, OrigDRE->getExprLoc());
227 return EmitLValue(&DRE);
230 return EmitLValue(E);
237 if (SizeInChars.isZero()) {
242 Size = Size ? Builder.CreateNUWMul(Size, VlaSize.
NumElts)
246 if (SizeInChars.isZero())
247 return llvm::ConstantInt::get(SizeTy, 0);
248 return Builder.CreateNUWMul(Size, CGM.getSize(SizeInChars));
250 return CGM.getSize(SizeInChars);
260 I != E; ++I, ++CurField, ++CurCap) {
261 if (CurField->hasCapturedVLAType()) {
264 CapturedVars.push_back(Val);
265 }
else if (CurCap->capturesThis()) {
266 CapturedVars.push_back(CXXThisValue);
267 }
else if (CurCap->capturesVariableByCopy()) {
268 llvm::Value *CV = EmitLoadOfScalar(EmitLValue(*I), CurCap->getLocation());
272 if (!CurField->getType()->isAnyPointerType()) {
274 Address DstAddr = CreateMemTemp(
276 Twine(CurCap->getCapturedVar()->getName(),
".casted"));
283 MakeNaturalAlignAddrLValue(SrcAddrVal, CurField->getType());
289 CV = EmitLoadOfScalar(DstLV, CurCap->getLocation());
291 CapturedVars.push_back(CV);
293 assert(CurCap->capturesVariable() &&
"Expected capture by reference.");
294 CapturedVars.push_back(EmitLValue(*I).getAddress().getPointer());
302 bool isReferenceType =
false) {
314 if (isReferenceType) {
333 if (
const auto *VLA = dyn_cast<VariableArrayType>(A))
335 if (!A->isVariablyModifiedType())
343 struct FunctionOptions {
348 const bool UIntPtrCastRequired =
true;
351 const bool RegisterCastedArgsOnly =
false;
353 const StringRef FunctionName;
354 explicit FunctionOptions(
const CapturedStmt *S,
bool UIntPtrCastRequired,
355 bool RegisterCastedArgsOnly,
356 StringRef FunctionName)
357 : S(S), UIntPtrCastRequired(UIntPtrCastRequired),
358 RegisterCastedArgsOnly(UIntPtrCastRequired && RegisterCastedArgsOnly),
359 FunctionName(FunctionName) {}
365 llvm::MapVector<
const Decl *, std::pair<const VarDecl *, Address>>
367 llvm::DenseMap<
const Decl *, std::pair<const Expr *, llvm::Value *>>
369 llvm::Value *&CXXThisValue,
const FunctionOptions &FO) {
371 const RecordDecl *RD = FO.S->getCapturedRecordDecl();
372 assert(CD->
hasBody() &&
"missing CapturedDecl body");
374 CXXThisValue =
nullptr;
384 auto I = FO.S->captures().begin();
386 if (!FO.UIntPtrCastRequired) {
405 if (FO.UIntPtrCastRequired &&
407 I->capturesVariableArrayType()))
410 if (I->capturesVariable() || I->capturesVariableByCopy()) {
411 CapVar = I->getCapturedVar();
413 }
else if (I->capturesThis()) {
416 assert(I->capturesVariableArrayType());
422 if (DebugFunctionDecl && (CapVar || I->capturesThis())) {
424 Ctx, DebugFunctionDecl,
425 CapVar ? CapVar->
getBeginLoc() : FD->getBeginLoc(),
426 CapVar ? CapVar->
getLocation() : FD->getLocation(), II, ArgType,
432 Args.emplace_back(Arg);
434 TargetArgs.emplace_back(
435 FO.UIntPtrCastRequired
457 F->setDoesNotThrow();
458 F->setDoesNotRecurse();
464 I = FO.S->captures().begin();
468 if (!FO.UIntPtrCastRequired && Args[Cnt] != TargetArgs[Cnt]) {
476 if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
477 const VarDecl *CurVD = I->getCapturedVar();
486 if (!FO.RegisterCastedArgsOnly)
487 LocalAddrs.insert({Args[Cnt], {CurVD, LocalAddr}});
495 if (FD->hasCapturedVLAType()) {
496 if (FO.UIntPtrCastRequired) {
499 Args[Cnt]->getName(), ArgLVal),
504 VLASizes.try_emplace(Args[Cnt], VAT->
getSizeExpr(), ExprArg);
505 }
else if (I->capturesVariable()) {
506 const VarDecl *Var = I->getCapturedVar();
519 if (!FO.RegisterCastedArgsOnly) {
524 }
else if (I->capturesVariableByCopy()) {
525 assert(!FD->getType()->isAnyPointerType() &&
526 "Not expecting a captured pointer.");
527 const VarDecl *Var = I->getCapturedVar();
531 {Var, FO.UIntPtrCastRequired
533 FD->getType(), Args[Cnt]->getName(),
538 assert(I->capturesThis());
540 LocalAddrs.insert({Args[Cnt], {
nullptr, ArgLVal.
getAddress()}});
553 "CapturedStmtInfo should be set when generating the captured function");
556 bool NeedWrapperFunction =
560 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs;
561 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes;
563 llvm::raw_svector_ostream Out(Buffer);
564 Out << CapturedStmtInfo->getHelperName();
565 if (NeedWrapperFunction)
567 FunctionOptions FO(&S, !NeedWrapperFunction,
false,
570 VLASizes, CXXThisValue, FO);
571 for (
const auto &LocalAddrPair : LocalAddrs) {
572 if (LocalAddrPair.second.first) {
573 setAddrOfLocalVar(LocalAddrPair.second.first,
574 LocalAddrPair.second.second);
577 for (
const auto &VLASizePair : VLASizes)
578 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
580 CapturedStmtInfo->EmitBody(*
this, CD->
getBody());
582 if (!NeedWrapperFunction)
585 FunctionOptions WrapperFO(&S,
true,
587 CapturedStmtInfo->getHelperName());
589 WrapperCGF.CapturedStmtInfo = CapturedStmtInfo;
593 llvm::Function *WrapperF =
595 WrapperCGF.CXXThisValue, WrapperFO);
597 for (
const auto *Arg : Args) {
599 auto I = LocalAddrs.find(Arg);
600 if (I != LocalAddrs.end()) {
601 LValue LV = WrapperCGF.MakeAddrLValue(
603 I->second.first ? I->second.first->getType() : Arg->getType(),
605 CallArg = WrapperCGF.EmitLoadOfScalar(LV, S.
getBeginLoc());
607 auto EI = VLASizes.find(Arg);
608 if (EI != VLASizes.end()) {
609 CallArg = EI->second.second;
611 LValue LV = WrapperCGF.MakeAddrLValue(WrapperCGF.GetAddrOfLocalVar(Arg),
614 CallArg = WrapperCGF.EmitLoadOfScalar(LV, S.
getBeginLoc());
617 CallArgs.emplace_back(WrapperCGF.EmitFromMemory(CallArg, Arg->getType()));
619 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, S.
getBeginLoc(),
621 WrapperCGF.FinishFunction();
636 llvm::Value *NumElements = emitArrayLength(ArrayTy, ElementTy, DestAddr);
637 SrcAddr = Builder.CreateElementBitCast(SrcAddr, DestAddr.
getElementType());
642 llvm::Value *DestEnd = Builder.CreateGEP(DestBegin, NumElements);
644 llvm::BasicBlock *BodyBB = createBasicBlock(
"omp.arraycpy.body");
645 llvm::BasicBlock *DoneBB = createBasicBlock(
"omp.arraycpy.done");
647 Builder.CreateICmpEQ(DestBegin, DestEnd,
"omp.arraycpy.isempty");
648 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
651 llvm::BasicBlock *EntryBB = Builder.GetInsertBlock();
654 CharUnits ElementSize = getContext().getTypeSizeInChars(ElementTy);
656 llvm::PHINode *SrcElementPHI =
657 Builder.CreatePHI(SrcBegin->getType(), 2,
"omp.arraycpy.srcElementPast");
658 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
663 llvm::PHINode *DestElementPHI =
664 Builder.CreatePHI(DestBegin->getType(), 2,
"omp.arraycpy.destElementPast");
665 DestElementPHI->addIncoming(DestBegin, EntryBB);
671 CopyGen(DestElementCurrent, SrcElementCurrent);
674 llvm::Value *DestElementNext = Builder.CreateConstGEP1_32(
675 DestElementPHI, 1,
"omp.arraycpy.dest.element");
676 llvm::Value *SrcElementNext = Builder.CreateConstGEP1_32(
677 SrcElementPHI, 1,
"omp.arraycpy.src.element");
680 Builder.CreateICmpEQ(DestElementNext, DestEnd,
"omp.arraycpy.done");
681 Builder.CreateCondBr(Done, DoneBB, BodyBB);
682 DestElementPHI->addIncoming(DestElementNext, Builder.GetInsertBlock());
683 SrcElementPHI->addIncoming(SrcElementNext, Builder.GetInsertBlock());
686 EmitBlock(DoneBB,
true);
694 if (BO && BO->getOpcode() == BO_Assign) {
696 LValue Dest = MakeAddrLValue(DestAddr, OriginalType);
697 LValue Src = MakeAddrLValue(SrcAddr, OriginalType);
698 EmitAggregateAssign(Dest, Src, OriginalType);
702 EmitOMPAggregateAssign(
703 DestAddr, SrcAddr, OriginalType,
704 [
this, Copy, SrcVD, DestVD](
Address DestElement,
Address SrcElement) {
709 Remap.
addPrivate(DestVD, [DestElement]() {
return DestElement; });
710 Remap.
addPrivate(SrcVD, [SrcElement]() {
return SrcElement; });
712 EmitIgnoredExpr(Copy);
718 Remap.
addPrivate(SrcVD, [SrcAddr]() {
return SrcAddr; });
719 Remap.
addPrivate(DestVD, [DestAddr]() {
return DestAddr; });
722 EmitIgnoredExpr(Copy);
728 if (!HaveInsertPoint())
730 bool FirstprivateIsLastprivate =
false;
733 for (
const auto *D : C->varlists())
742 bool MustEmitFirstprivateCopy =
743 CaptureRegions.size() == 1 && CaptureRegions.back() ==
OMPD_unknown;
745 auto IRef = C->varlist_begin();
746 auto InitsRef = C->inits().begin();
747 for (
const Expr *IInit : C->private_copies()) {
748 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
749 bool ThisFirstprivateIsLastprivate =
750 Lastprivates.count(OrigVD->getCanonicalDecl()) > 0;
751 const FieldDecl *FD = CapturedStmtInfo->lookup(OrigVD);
752 if (!MustEmitFirstprivateCopy && !ThisFirstprivateIsLastprivate && FD &&
754 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
759 FirstprivateIsLastprivate =
760 FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate;
761 if (EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()).second) {
762 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
764 cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl());
766 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD),
769 LValue OriginalLVal = EmitLValue(&DRE);
776 OrigVD, [
this, VD, Type, OriginalLVal, VDInit]() {
779 if (!isa<CXXConstructExpr>(Init) ||
780 isTrivialInitializer(Init)) {
784 EmitAggregateAssign(Dest, OriginalLVal, Type);
786 EmitOMPAggregateAssign(
789 [
this, VDInit, Init](
Address DestElement,
795 setAddrOfLocalVar(VDInit, SrcElement);
796 EmitAnyExprToMem(Init, DestElement,
799 LocalDeclMap.erase(VDInit);
802 EmitAutoVarCleanups(Emission);
806 Address OriginalAddr = OriginalLVal.getAddress();
808 OrigVD, [
this, VDInit, OriginalAddr, VD]() {
812 setAddrOfLocalVar(VDInit, OriginalAddr);
814 LocalDeclMap.erase(VDInit);
815 return GetAddrOfLocalVar(VD);
818 assert(IsRegistered &&
819 "firstprivate var already registered as private");
827 return FirstprivateIsLastprivate && !EmittedAsFirstprivate.empty();
833 if (!HaveInsertPoint())
837 auto IRef = C->varlist_begin();
838 for (
const Expr *IInit : C->private_copies()) {
839 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
840 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
841 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
842 bool IsRegistered = PrivateScope.
addPrivate(OrigVD, [
this, VD]() {
845 return GetAddrOfLocalVar(VD);
847 assert(IsRegistered &&
"private var already registered as private");
857 if (!HaveInsertPoint())
864 llvm::BasicBlock *CopyBegin =
nullptr, *CopyEnd =
nullptr;
866 auto IRef = C->varlist_begin();
867 auto ISrcRef = C->source_exprs().begin();
868 auto IDestRef = C->destination_exprs().begin();
869 for (
const Expr *AssignOp : C->assignment_ops()) {
870 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
877 if (getLangOpts().OpenMPUseTLS &&
878 getContext().getTargetInfo().isTLSSupported()) {
879 assert(CapturedStmtInfo->lookup(VD) &&
880 "Copyin threadprivates should have been captured!");
881 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(VD),
true,
882 (*IRef)->getType(),
VK_LValue, (*IRef)->getExprLoc());
883 MasterAddr = EmitLValue(&DRE).getAddress();
884 LocalDeclMap.erase(VD);
888 : CGM.GetAddrOfGlobal(VD),
889 getContext().getDeclAlign(VD));
892 Address PrivateAddr = EmitLValue(*IRef).getAddress();
893 if (CopiedVars.size() == 1) {
896 CopyBegin = createBasicBlock(
"copyin.not.master");
897 CopyEnd = createBasicBlock(
"copyin.not.master.end");
898 Builder.CreateCondBr(
899 Builder.CreateICmpNE(
900 Builder.CreatePtrToInt(MasterAddr.
getPointer(), CGM.IntPtrTy),
901 Builder.CreatePtrToInt(PrivateAddr.getPointer(),
904 EmitBlock(CopyBegin);
907 cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
909 cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
910 EmitOMPCopy(Type, PrivateAddr, MasterAddr, DestVD, SrcVD, AssignOp);
919 EmitBlock(CopyEnd,
true);
927 if (!HaveInsertPoint())
929 bool HasAtLeastOneLastprivate =
false;
932 const auto *LoopDirective = cast<OMPLoopDirective>(&D);
933 for (
const Expr *C : LoopDirective->counters()) {
940 HasAtLeastOneLastprivate =
true;
942 !getLangOpts().OpenMPSimd)
944 auto IRef = C->varlist_begin();
945 auto IDestRef = C->destination_exprs().begin();
946 for (
const Expr *IInit : C->private_copies()) {
949 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
952 if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) {
954 cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
955 PrivateScope.
addPrivate(DestVD, [
this, OrigVD, IRef]() {
956 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD),
958 CapturedStmtInfo->lookup(OrigVD) !=
nullptr,
959 (*IRef)->getType(),
VK_LValue, (*IRef)->getExprLoc());
960 return EmitLValue(&DRE).getAddress();
965 if (IInit && !SIMDLCVs.count(OrigVD->getCanonicalDecl())) {
966 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
967 bool IsRegistered = PrivateScope.
addPrivate(OrigVD, [
this, VD]() {
970 return GetAddrOfLocalVar(VD);
972 assert(IsRegistered &&
973 "lastprivate var already registered as private");
981 return HasAtLeastOneLastprivate;
987 if (!HaveInsertPoint())
995 llvm::BasicBlock *ThenBB =
nullptr;
996 llvm::BasicBlock *DoneBB =
nullptr;
997 if (IsLastIterCond) {
998 ThenBB = createBasicBlock(
".omp.lastprivate.then");
999 DoneBB = createBasicBlock(
".omp.lastprivate.done");
1000 Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB);
1004 llvm::DenseMap<const VarDecl *, const Expr *> LoopCountersAndUpdates;
1005 if (
const auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) {
1006 auto IC = LoopDirective->counters().begin();
1007 for (
const Expr *F : LoopDirective->finals()) {
1011 AlreadyEmittedVars.insert(D);
1013 LoopCountersAndUpdates[D] = F;
1018 auto IRef = C->varlist_begin();
1019 auto ISrcRef = C->source_exprs().begin();
1020 auto IDestRef = C->destination_exprs().begin();
1021 for (
const Expr *AssignOp : C->assignment_ops()) {
1022 const auto *PrivateVD =
1023 cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
1025 const auto *CanonicalVD = PrivateVD->getCanonicalDecl();
1026 if (AlreadyEmittedVars.insert(CanonicalVD).second) {
1030 if (
const Expr *FinalExpr = LoopCountersAndUpdates.lookup(CanonicalVD))
1031 EmitIgnoredExpr(FinalExpr);
1033 cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
1034 const auto *DestVD =
1035 cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
1037 Address OriginalAddr = GetAddrOfLocalVar(DestVD);
1039 Address PrivateAddr = GetAddrOfLocalVar(PrivateVD);
1040 if (
const auto *RefTy = PrivateVD->getType()->getAs<
ReferenceType>())
1042 Address(Builder.CreateLoad(PrivateAddr),
1043 getNaturalTypeAlignment(RefTy->getPointeeType()));
1044 EmitOMPCopy(Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp);
1050 if (
const Expr *PostUpdate = C->getPostUpdateExpr())
1051 EmitIgnoredExpr(PostUpdate);
1054 EmitBlock(DoneBB,
true);
1060 if (!HaveInsertPoint())
1068 auto IPriv = C->privates().begin();
1069 auto IRed = C->reduction_ops().begin();
1070 auto ILHS = C->lhs_exprs().begin();
1071 auto IRHS = C->rhs_exprs().begin();
1072 for (
const Expr *Ref : C->varlists()) {
1073 Shareds.emplace_back(Ref);
1074 Privates.emplace_back(*IPriv);
1075 ReductionOps.emplace_back(*IRed);
1076 LHSs.emplace_back(*ILHS);
1077 RHSs.emplace_back(*IRHS);
1078 std::advance(IPriv, 1);
1079 std::advance(IRed, 1);
1080 std::advance(ILHS, 1);
1081 std::advance(IRHS, 1);
1086 auto ILHS = LHSs.begin();
1087 auto IRHS = RHSs.begin();
1088 auto IPriv = Privates.begin();
1089 for (
const Expr *IRef : Shareds) {
1090 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IPriv)->getDecl());
1092 RedCG.emitSharedLValue(*
this, Count);
1101 EmitAutoVarCleanups(Emission);
1105 RedCG.
getBaseDecl(Count), [BaseAddr]() {
return BaseAddr; });
1106 assert(IsRegistered &&
"private var already registered as private");
1110 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
1111 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
1113 bool isaOMPArraySectionExpr = isa<OMPArraySectionExpr>(IRef);
1114 if (isaOMPArraySectionExpr && Type->isVariablyModifiedType()) {
1117 PrivateScope.
addPrivate(LHSVD, [&RedCG, Count]() {
1121 RHSVD, [
this, PrivateVD]() {
return GetAddrOfLocalVar(PrivateVD); });
1122 }
else if ((isaOMPArraySectionExpr && Type->isScalarType()) ||
1123 isa<ArraySubscriptExpr>(IRef)) {
1126 PrivateScope.
addPrivate(LHSVD, [&RedCG, Count]() {
1129 PrivateScope.
addPrivate(RHSVD, [
this, PrivateVD, RHSVD]() {
1130 return Builder.CreateElementBitCast(GetAddrOfLocalVar(PrivateVD),
1131 ConvertTypeForMem(RHSVD->getType()),
1135 QualType Type = PrivateVD->getType();
1136 bool IsArray = getContext().getAsArrayType(Type) !=
nullptr;
1141 OriginalAddr = Builder.CreateElementBitCast(
1142 OriginalAddr, ConvertTypeForMem(LHSVD->getType()),
"lhs.begin");
1144 PrivateScope.
addPrivate(LHSVD, [OriginalAddr]() {
return OriginalAddr; });
1146 RHSVD, [
this, PrivateVD, RHSVD, IsArray]() {
1148 ? Builder.CreateElementBitCast(
1149 GetAddrOfLocalVar(PrivateVD),
1150 ConvertTypeForMem(RHSVD->getType()),
"rhs.begin")
1151 : GetAddrOfLocalVar(PrivateVD);
1163 if (!HaveInsertPoint())
1169 bool HasAtLeastOneReduction =
false;
1171 HasAtLeastOneReduction =
true;
1172 Privates.append(C->privates().begin(), C->privates().end());
1173 LHSExprs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());
1174 RHSExprs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());
1175 ReductionOps.append(C->reduction_ops().begin(), C->reduction_ops().end());
1177 if (HasAtLeastOneReduction) {
1180 ReductionKind == OMPD_simd;
1181 bool SimpleReduction = ReductionKind == OMPD_simd;
1184 CGM.getOpenMPRuntime().emitReduction(
1186 {WithNowait, SimpleReduction, ReductionKind});
1195 llvm::BasicBlock *DoneBB =
nullptr;
1197 if (
const Expr *PostUpdate = C->getPostUpdateExpr()) {
1204 CGF.
Builder.CreateCondBr(Cond, ThenBB, DoneBB);
1222 CodeGenBoundParametersTy;
1228 const CodeGenBoundParametersTy &CodeGenBoundParameters) {
1239 CGF, NumThreads, NumThreadsClause->getBeginLoc());
1244 CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getBeginLoc());
1246 const Expr *IfCond =
nullptr;
1249 C->getNameModifier() == OMPD_parallel) {
1250 IfCond = C->getCondition();
1255 OMPParallelScope
Scope(CGF, S);
1261 CodeGenBoundParameters(CGF, S, CapturedVars);
1264 CapturedVars, IfCond);
1303 EmitIgnoredExpr(UE);
1309 for (
const Expr *UE : C->updates())
1310 EmitIgnoredExpr(UE);
1315 JumpDest Continue = getJumpDestInCurrentScope(
"omp.body.continue");
1316 BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
1321 BreakContinueStack.pop_back();
1325 const Stmt &S,
bool RequiresCleanup,
const Expr *LoopCond,
1326 const Expr *IncExpr,
1329 auto LoopExit = getJumpDestInCurrentScope(
"omp.inner.for.end");
1332 auto CondBlock = createBasicBlock(
"omp.inner.for.cond");
1333 EmitBlock(CondBlock);
1335 LoopStack.push(CondBlock, SourceLocToDebugLoc(R.
getBegin()),
1336 SourceLocToDebugLoc(R.
getEnd()));
1340 llvm::BasicBlock *ExitBlock =
LoopExit.getBlock();
1341 if (RequiresCleanup)
1342 ExitBlock = createBasicBlock(
"omp.inner.for.cond.cleanup");
1344 llvm::BasicBlock *LoopBody = createBasicBlock(
"omp.inner.for.body");
1347 EmitBranchOnBoolExpr(LoopCond, LoopBody, ExitBlock, getProfileCount(&S));
1348 if (ExitBlock !=
LoopExit.getBlock()) {
1349 EmitBlock(ExitBlock);
1350 EmitBranchThroughCleanup(
LoopExit);
1353 EmitBlock(LoopBody);
1354 incrementProfileCounter(&S);
1357 JumpDest Continue = getJumpDestInCurrentScope(
"omp.inner.for.inc");
1358 BreakContinueStack.push_back(BreakContinue(
LoopExit, Continue));
1364 EmitIgnoredExpr(IncExpr);
1366 BreakContinueStack.pop_back();
1367 EmitBranch(CondBlock);
1374 if (!HaveInsertPoint())
1377 bool HasLinears =
false;
1379 for (
const Expr *Init : C->inits()) {
1381 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(Init)->getDecl());
1382 if (
const auto *Ref =
1385 const auto *OrigVD = cast<VarDecl>(Ref->getDecl());
1386 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD),
1387 CapturedStmtInfo->lookup(OrigVD) !=
nullptr,
1393 EmitAutoVarCleanups(Emission);
1400 if (
const auto *CS = cast_or_null<BinaryOperator>(C->getCalcStep()))
1401 if (
const auto *SaveRef = cast<DeclRefExpr>(CS->getLHS())) {
1402 EmitVarDecl(*cast<VarDecl>(SaveRef->getDecl()));
1404 EmitIgnoredExpr(CS);
1413 if (!HaveInsertPoint())
1415 llvm::BasicBlock *DoneBB =
nullptr;
1418 auto IC = C->varlist_begin();
1419 for (
const Expr *F : C->finals()) {
1424 llvm::BasicBlock *ThenBB = createBasicBlock(
".omp.linear.pu");
1425 DoneBB = createBasicBlock(
".omp.linear.pu.done");
1426 Builder.CreateCondBr(Cond, ThenBB, DoneBB);
1430 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl());
1431 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD),
1432 CapturedStmtInfo->lookup(OrigVD) !=
nullptr,
1433 (*IC)->getType(),
VK_LValue, (*IC)->getExprLoc());
1434 Address OrigAddr = EmitLValue(&DRE).getAddress();
1436 VarScope.
addPrivate(OrigVD, [OrigAddr]() {
return OrigAddr; });
1441 if (
const Expr *PostUpdate = C->getPostUpdateExpr())
1442 EmitIgnoredExpr(PostUpdate);
1445 EmitBlock(DoneBB,
true);
1453 unsigned ClauseAlignment = 0;
1454 if (
const Expr *AlignmentExpr = Clause->getAlignment()) {
1457 ClauseAlignment =
static_cast<unsigned>(AlignmentCI->getZExtValue());
1459 for (
const Expr *E : Clause->varlists()) {
1460 unsigned Alignment = ClauseAlignment;
1461 if (Alignment == 0) {
1468 E->getType()->getPointeeType()))
1471 assert((Alignment == 0 || llvm::isPowerOf2_32(Alignment)) &&
1472 "alignment is not power of 2");
1473 if (Alignment != 0) {
1484 if (!HaveInsertPoint())
1488 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
1489 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl());
1492 EmitAutoVarCleanups(VarEmission);
1493 LocalDeclMap.erase(PrivateVD);
1494 (void)LoopScope.
addPrivate(VD, [&VarEmission]() {
1495 return VarEmission.getAllocatedAddress();
1497 if (LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD) ||
1499 (void)LoopScope.
addPrivate(PrivateVD, [
this, VD, E]() {
1500 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(VD),
1501 LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD),
1502 E->getType(), VK_LValue, E->getExprLoc());
1503 return EmitLValue(&DRE).getAddress();
1506 (void)LoopScope.
addPrivate(PrivateVD, [&VarEmission]() {
1507 return VarEmission.getAllocatedAddress();
1514 if (!C->getNumForLoops())
1517 E = C->getLoopNumIterations().size();
1519 const auto *DRE = cast<DeclRefExpr>(C->getLoopCounter(I));
1520 const auto *VD = cast<VarDecl>(DRE->getDecl());
1522 if (LocalDeclMap.count(VD)) {
1523 (void)LoopScope.
addPrivate(VD, [
this, DRE, VD]() {
1524 return CreateMemTemp(DRE->getType(), VD->getName());
1532 const Expr *Cond, llvm::BasicBlock *TrueBlock,
1533 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
1551 if (!HaveInsertPoint())
1555 const auto *LoopDirective = cast<OMPLoopDirective>(&D);
1556 for (
const Expr *C : LoopDirective->counters()) {
1562 auto CurPrivate = C->privates().begin();
1563 for (
const Expr *E : C->varlists()) {
1564 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
1565 const auto *PrivateVD =
1566 cast<VarDecl>(cast<DeclRefExpr>(*CurPrivate)->getDecl());
1568 bool IsRegistered = PrivateScope.
addPrivate(VD, [
this, PrivateVD]() {
1570 EmitVarDecl(*PrivateVD);
1571 return GetAddrOfLocalVar(PrivateVD);
1573 assert(IsRegistered &&
"linear var already registered as private");
1577 EmitVarDecl(*PrivateVD);
1592 auto *Val = cast<llvm::ConstantInt>(Len.
getScalarVal());
1602 auto *Val = cast<llvm::ConstantInt>(Len.
getScalarVal());
1614 LoopStack.setParallel(!IsMonotonic);
1615 LoopStack.setVectorizeEnable();
1622 if (!HaveInsertPoint())
1624 llvm::BasicBlock *DoneBB =
nullptr;
1628 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>((*IC))->getDecl());
1629 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>((*IPC))->getDecl());
1631 if (LocalDeclMap.count(OrigVD) || CapturedStmtInfo->lookup(OrigVD) ||
1632 OrigVD->hasGlobalStorage() || CED) {
1637 llvm::BasicBlock *ThenBB = createBasicBlock(
".omp.final.then");
1638 DoneBB = createBasicBlock(
".omp.final.done");
1639 Builder.CreateCondBr(Cond, ThenBB, DoneBB);
1645 OrigAddr = EmitLValue(CED->getInit()->IgnoreImpCasts()).getAddress();
1647 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(PrivateVD),
1649 (*IPC)->getType(),
VK_LValue, (*IPC)->getExprLoc());
1650 OrigAddr = EmitLValue(&DRE).getAddress();
1653 VarScope.
addPrivate(OrigVD, [OrigAddr]() {
return OrigAddr; });
1661 EmitBlock(DoneBB,
true);
1674 auto VDecl = cast<VarDecl>(Helper->
getDecl());
1683 "Expected simd directive");
1684 OMPLoopScope PreInitScope(CGF, S);
1701 llvm::BasicBlock *ContBlock =
nullptr;
1716 const auto *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
1724 CGF.
EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
1752 if (HasLastprivateClause)
1771 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd, CodeGen);
1774 void CodeGenFunction::EmitOMPOuterLoop(
1777 const CodeGenFunction::OMPLoopArguments &LoopArgs,
1783 const unsigned IVSize = getContext().getTypeSize(IVExpr->
getType());
1789 llvm::BasicBlock *CondBlock = createBasicBlock(
"omp.dispatch.cond");
1790 EmitBlock(CondBlock);
1792 LoopStack.push(CondBlock, SourceLocToDebugLoc(R.
getBegin()),
1793 SourceLocToDebugLoc(R.
getEnd()));
1796 if (!DynamicOrOrdered) {
1800 EmitIgnoredExpr(LoopArgs.EUB);
1802 EmitIgnoredExpr(LoopArgs.Init);
1804 BoolCondVal = EvaluateExprAsBool(LoopArgs.Cond);
1807 RT.emitForNext(*
this, S.
getBeginLoc(), IVSize, IVSigned, LoopArgs.IL,
1808 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST);
1813 llvm::BasicBlock *ExitBlock = LoopExit.
getBlock();
1815 ExitBlock = createBasicBlock(
"omp.dispatch.cleanup");
1817 llvm::BasicBlock *LoopBody = createBasicBlock(
"omp.dispatch.body");
1818 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
1819 if (ExitBlock != LoopExit.
getBlock()) {
1820 EmitBlock(ExitBlock);
1821 EmitBranchThroughCleanup(LoopExit);
1823 EmitBlock(LoopBody);
1827 if (DynamicOrOrdered)
1828 EmitIgnoredExpr(LoopArgs.Init);
1831 JumpDest Continue = getJumpDestInCurrentScope(
"omp.dispatch.inc");
1832 BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
1837 LoopStack.setParallel(!IsMonotonic);
1839 EmitOMPSimdInit(S, IsMonotonic);
1851 CodeGenLoop(CGF, S, LoopExit);
1854 CodeGenOrdered(CGF, Loc, IVSize, IVSigned);
1858 BreakContinueStack.pop_back();
1859 if (!DynamicOrOrdered) {
1861 EmitIgnoredExpr(LoopArgs.NextLB);
1862 EmitIgnoredExpr(LoopArgs.NextUB);
1865 EmitBranch(CondBlock);
1868 EmitBlock(LoopExit.getBlock());
1872 if (!DynamicOrOrdered)
1879 void CodeGenFunction::EmitOMPForOuterLoop(
1882 const OMPLoopArguments &LoopArgs,
1887 const bool DynamicOrOrdered =
1888 Ordered || RT.isDynamic(ScheduleKind.
Schedule);
1891 !RT.isStaticNonchunked(ScheduleKind.
Schedule,
1892 LoopArgs.Chunk !=
nullptr)) &&
1893 "static non-chunked schedule does not need outer loop");
1946 const unsigned IVSize = getContext().getTypeSize(IVExpr->
getType());
1949 if (DynamicOrOrdered) {
1950 const std::pair<llvm::Value *, llvm::Value *> DispatchBounds =
1951 CGDispatchBounds(*
this, S, LoopArgs.LB, LoopArgs.UB);
1954 CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal,
1956 RT.emitForDispatchInit(*
this, S.
getBeginLoc(), ScheduleKind, IVSize,
1957 IVSigned, Ordered, DipatchRTInputValues);
1959 CGOpenMPRuntime::StaticRTInput StaticInit(
1960 IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
1961 LoopArgs.ST, LoopArgs.Chunk);
1963 ScheduleKind, StaticInit);
1967 const unsigned IVSize,
1968 const bool IVSigned) {
1975 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST,
1976 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB);
1977 OuterLoopArgs.IncExpr = S.
getInc();
1978 OuterLoopArgs.Init = S.
getInit();
1979 OuterLoopArgs.Cond = S.
getCond();
1982 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
1987 const unsigned IVSize,
const bool IVSigned) {}
1989 void CodeGenFunction::EmitOMPDistributeOuterLoop(
1991 OMPPrivateScope &LoopScope,
const OMPLoopArguments &LoopArgs,
1992 const CodeGenLoopTy &CodeGenLoopContent) {
2002 const unsigned IVSize = getContext().getTypeSize(IVExpr->
getType());
2005 CGOpenMPRuntime::StaticRTInput StaticInit(
2006 IVSize, IVSigned,
false, LoopArgs.IL, LoopArgs.LB,
2007 LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
2008 RT.emitDistributeStaticInit(*
this, S.
getBeginLoc(), ScheduleKind, StaticInit);
2021 OMPLoopArguments OuterLoopArgs;
2022 OuterLoopArgs.LB = LoopArgs.LB;
2023 OuterLoopArgs.UB = LoopArgs.UB;
2024 OuterLoopArgs.ST = LoopArgs.ST;
2025 OuterLoopArgs.IL = LoopArgs.IL;
2026 OuterLoopArgs.Chunk = LoopArgs.Chunk;
2030 OuterLoopArgs.IncExpr = IncExpr;
2044 EmitOMPOuterLoop(
false,
false, S,
2045 LoopScope, OuterLoopArgs, CodeGenLoopContent,
2049 static std::pair<LValue, LValue>
2092 static std::pair<llvm::Value *, llvm::Value *>
2102 QualType IteratorTy = IVExpr->getType();
2107 return {LBVal, UBVal};
2113 const auto &Dir = cast<OMPLoopDirective>(S);
2115 CGF.
EmitLValue(cast<DeclRefExpr>(Dir.getCombinedLowerBoundVariable()));
2118 CapturedVars.push_back(LBCast);
2120 CGF.
EmitLValue(cast<DeclRefExpr>(Dir.getCombinedUpperBoundVariable()));
2124 CapturedVars.push_back(UBCast);
2134 bool HasCancel =
false;
2136 if (
const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
2137 HasCancel = D->hasCancel();
2138 else if (
const auto *D = dyn_cast<OMPDistributeParallelForDirective>(&S))
2139 HasCancel = D->hasCancel();
2140 else if (
const auto *D =
2141 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S))
2142 HasCancel = D->hasCancel();
2154 CGInlinedWorksharingLoop,
2164 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
2165 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute, CodeGen);
2174 OMPLexicalScope
Scope(*
this, S, OMPD_parallel);
2175 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute, CodeGen);
2184 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd, CodeGen);
2194 llvm::Constant *Addr;
2197 S, ParentName, Fn, Addr,
true, CodeGen);
2198 assert(Fn && Addr &&
"Target device function emission failed.");
2210 struct ScheduleKindModifiersTy {
2217 :
Kind(Kind), M1(M1), M2(M2) {}
2227 const auto *IVDecl = cast<VarDecl>(IVExpr->getDecl());
2228 EmitVarDecl(*IVDecl);
2234 EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
2241 bool HasLastprivateClause;
2244 OMPLoopScope PreInitScope(*
this, S);
2249 llvm::BasicBlock *ContBlock =
nullptr;
2250 if (ConstantFoldsToSimpleInteger(S.
getPreCond(), CondConstant)) {
2254 llvm::BasicBlock *ThenBlock = createBasicBlock(
"omp.precond.then");
2255 ContBlock = createBasicBlock(
"omp.precond.end");
2257 getProfileCount(&S));
2258 EmitBlock(ThenBlock);
2259 incrementProfileCounter(&S);
2263 bool Ordered =
false;
2265 if (OrderedClause->getNumForLoops())
2266 RT.emitDoacrossInit(*
this, S, OrderedClause->getLoopNumIterations());
2273 bool HasLinears = EmitOMPLinearClauseInit(S);
2276 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*
this, S);
2277 LValue LB = Bounds.first;
2278 LValue UB = Bounds.second;
2287 if (EmitOMPFirstprivateClause(S, LoopScope) || HasLinears) {
2291 CGM.getOpenMPRuntime().emitBarrierCall(
2295 EmitOMPPrivateClause(S, LoopScope);
2296 HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope);
2297 EmitOMPReductionClauseInit(S, LoopScope);
2298 EmitOMPPrivateLoopCounters(S, LoopScope);
2299 EmitOMPLinearClause(S, LoopScope);
2302 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
2305 const Expr *ChunkExpr =
nullptr;
2308 ScheduleKind.
Schedule = C->getScheduleKind();
2309 ScheduleKind.
M1 = C->getFirstScheduleModifier();
2310 ScheduleKind.
M2 = C->getSecondScheduleModifier();
2311 ChunkExpr = C->getChunkSize();
2314 CGM.getOpenMPRuntime().getDefaultScheduleAndChunk(
2315 *
this, S, ScheduleKind.
Schedule, ChunkExpr);
2317 bool HasChunkSizeOne =
false;
2320 Chunk = EmitScalarExpr(ChunkExpr);
2321 Chunk = EmitScalarConversion(Chunk, ChunkExpr->
getType(),
2326 llvm::APSInt EvaluatedChunk = Result.Val.getInt();
2327 HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
2330 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
2331 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
2336 bool StaticChunkedOne = RT.isStaticChunked(ScheduleKind.
Schedule,
2337 Chunk !=
nullptr) && HasChunkSizeOne &&
2339 if ((RT.isStaticNonchunked(ScheduleKind.
Schedule,
2340 Chunk !=
nullptr) ||
2341 StaticChunkedOne) &&
2344 EmitOMPSimdInit(S,
true);
2350 CGOpenMPRuntime::StaticRTInput StaticInit(
2353 StaticChunkedOne ? Chunk :
nullptr);
2355 ScheduleKind, StaticInit);
2357 getJumpDestInCurrentScope(createBasicBlock(
"omp.loop.exit"));
2359 if (!StaticChunkedOne)
2392 const bool IsMonotonic =
2393 Ordered || ScheduleKind.
Schedule == OMPC_SCHEDULE_static ||
2395 ScheduleKind.
M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
2396 ScheduleKind.
M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
2402 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
2403 LoopArguments, CGDispatchBounds);
2407 return CGF.
Builder.CreateIsNotNull(
2411 EmitOMPReductionClauseFinal(
2413 ? OMPD_parallel_for_simd
2418 return CGF.
Builder.CreateIsNotNull(
2422 if (HasLastprivateClause)
2423 EmitOMPLastprivateClauseFinal(
2425 Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.
getBeginLoc())));
2428 return CGF.
Builder.CreateIsNotNull(
2434 EmitBranch(ContBlock);
2435 EmitBlock(ContBlock,
true);
2438 return HasLastprivateClause;
2444 static std::pair<LValue, LValue>
2446 const auto &LS = cast<OMPLoopDirective>(S);
2458 static std::pair<llvm::Value *, llvm::Value *>
2461 const auto &LS = cast<OMPLoopDirective>(S);
2462 const Expr *IVExpr = LS.getIterationVariable();
2466 return {LBVal, UBVal};
2470 bool HasLastprivates =
false;
2480 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_for, CodeGen,
2486 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.
getBeginLoc(), OMPD_for);
2490 bool HasLastprivates =
false;
2499 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_simd, CodeGen);
2504 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.
getBeginLoc(), OMPD_for);
2519 bool HasLastprivates =
false;
2520 auto &&CodeGen = [&S, CapturedStmt, CS,
2527 CGF.Builder.getInt32(0));
2528 llvm::ConstantInt *GlobalUBVal = CS !=
nullptr 2529 ? CGF.Builder.getInt32(CS->size() - 1)
2530 : CGF.Builder.getInt32(0);
2534 CGF.Builder.getInt32(1));
2536 CGF.Builder.getInt32(0));
2561 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
".omp.sections.exit");
2563 CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.
getBeginLoc()),
2564 ExitBB, CS ==
nullptr ? 1 : CS->size());
2566 unsigned CaseNumber = 0;
2568 auto CaseBB = CGF.createBasicBlock(
".omp.sections.case");
2569 CGF.EmitBlock(CaseBB);
2570 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
2571 CGF.EmitStmt(SubStmt);
2572 CGF.EmitBranch(ExitBB);
2576 llvm::BasicBlock *CaseBB = CGF.createBasicBlock(
".omp.sections.case");
2577 CGF.EmitBlock(CaseBB);
2578 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
2579 CGF.EmitStmt(CapturedStmt);
2580 CGF.EmitBranch(ExitBB);
2582 CGF.EmitBlock(ExitBB,
true);
2586 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
2590 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
2594 CGF.EmitOMPPrivateClause(S, LoopScope);
2595 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
2596 CGF.EmitOMPReductionClauseInit(S, LoopScope);
2599 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
2603 ScheduleKind.
Schedule = OMPC_SCHEDULE_static;
2604 CGOpenMPRuntime::StaticRTInput StaticInit(
2605 32,
true,
false, IL.getAddress(),
2607 CGF.CGM.getOpenMPRuntime().emitForStaticInit(
2608 CGF, S.
getBeginLoc(), S.getDirectiveKind(), ScheduleKind, StaticInit);
2611 llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
2612 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
2613 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
2615 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.
getBeginLoc()), IV);
2617 CGF.EmitOMPInnerLoop(S,
false, &Cond, &Inc, BodyGen,
2621 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.
getEndLoc(),
2622 S.getDirectiveKind());
2624 CGF.OMPCancelStack.emitExit(CGF, S.getDirectiveKind(), CodeGen);
2625 CGF.EmitOMPReductionClauseFinal(S, OMPD_parallel);
2628 return CGF.
Builder.CreateIsNotNull(
2633 if (HasLastprivates)
2640 bool HasCancel =
false;
2641 if (
auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
2642 HasCancel = OSD->hasCancel();
2643 else if (
auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
2644 HasCancel = OPSD->hasCancel();
2646 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_sections, CodeGen,
2654 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.
getBeginLoc(),
2666 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.
getBeginLoc(),
2676 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_section, CodeGen,
2690 CopyprivateVars.append(C->varlists().begin(), C->varlists().end());
2691 DestExprs.append(C->destination_exprs().begin(),
2692 C->destination_exprs().end());
2693 SrcExprs.append(C->source_exprs().begin(), C->source_exprs().end());
2694 AssignmentOps.append(C->assignment_ops().begin(),
2695 C->assignment_ops().end());
2708 CGM.getOpenMPRuntime().emitSingleRegion(*
this, CodeGen, S.
getBeginLoc(),
2709 CopyprivateVars, DestExprs,
2710 SrcExprs, AssignmentOps);
2715 CGM.getOpenMPRuntime().emitBarrierCall(
2727 CGM.getOpenMPRuntime().emitMasterRegion(*
this, CodeGen, S.
getBeginLoc());
2735 const Expr *Hint =
nullptr;
2737 Hint = HintClause->getHint();
2739 CGM.getOpenMPRuntime().emitCriticalRegion(*
this,
2777 CGF.EmitSections(S);
2790 auto PartId = std::next(I);
2791 auto TaskT = std::next(I, 4);
2796 const Expr *Cond = Clause->getCondition();
2798 if (ConstantFoldsToSimpleInteger(Cond, CondConstant))
2799 Data.
Final.setInt(CondConstant);
2801 Data.
Final.setPointer(EvaluateExprAsBool(Cond));
2804 Data.
Final.setInt(
false);
2808 const Expr *Prio = Clause->getPriority();
2810 Data.
Priority.setPointer(EmitScalarConversion(
2811 EmitScalarExpr(Prio), Prio->
getType(),
2812 getContext().getIntTypeForBitwidth(32, 1),
2820 auto IRef = C->varlist_begin();
2821 for (
const Expr *IInit : C->private_copies()) {
2822 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
2823 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
2830 EmittedAsPrivate.clear();
2833 auto IRef = C->varlist_begin();
2834 auto IElemInitRef = C->inits().begin();
2835 for (
const Expr *IInit : C->private_copies()) {
2836 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
2837 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
2847 llvm::DenseMap<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
2849 auto IRef = C->varlist_begin();
2850 auto ID = C->destination_exprs().begin();
2851 for (
const Expr *IInit : C->private_copies()) {
2852 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
2853 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
2857 LastprivateDstsOrigs.insert(
2858 {cast<VarDecl>(cast<DeclRefExpr>(*ID)->getDecl()),
2859 cast<DeclRefExpr>(*IRef)});
2867 auto IPriv = C->privates().begin();
2868 auto IRed = C->reduction_ops().begin();
2869 auto ILHS = C->lhs_exprs().begin();
2870 auto IRHS = C->rhs_exprs().begin();
2871 for (
const Expr *Ref : C->varlists()) {
2875 LHSs.emplace_back(*ILHS);
2876 RHSs.emplace_back(*IRHS);
2877 std::advance(IPriv, 1);
2878 std::advance(IRed, 1);
2879 std::advance(ILHS, 1);
2880 std::advance(IRHS, 1);
2883 Data.
Reductions = CGM.getOpenMPRuntime().emitTaskReductionInit(
2887 for (
const Expr *IRef : C->varlists())
2888 Data.
Dependences.emplace_back(C->getDependencyKind(), IRef);
2889 auto &&CodeGen = [&Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
2896 enum { PrivatesParam = 2, CopyFnParam = 3 };
2898 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(CopyFnParam)));
2899 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
2900 CS->getCapturedDecl()->getParam(PrivatesParam)));
2904 CallArgs.push_back(PrivatesPtr);
2906 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2907 Address PrivatePtr = CGF.CreateMemTemp(
2908 CGF.getContext().getPointerType(E->
getType()),
".priv.ptr.addr");
2909 PrivatePtrs.emplace_back(VD, PrivatePtr);
2910 CallArgs.push_back(PrivatePtr.getPointer());
2913 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2915 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
2916 ".firstpriv.ptr.addr");
2917 PrivatePtrs.emplace_back(VD, PrivatePtr);
2918 CallArgs.push_back(PrivatePtr.getPointer());
2921 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
2923 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
2924 ".lastpriv.ptr.addr");
2925 PrivatePtrs.emplace_back(VD, PrivatePtr);
2926 CallArgs.push_back(PrivatePtr.getPointer());
2928 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
2930 for (
const auto &Pair : LastprivateDstsOrigs) {
2931 const auto *OrigVD = cast<VarDecl>(Pair.second->getDecl());
2934 CGF.CapturedStmtInfo->lookup(OrigVD) !=
nullptr,
2936 Pair.second->getExprLoc());
2937 Scope.
addPrivate(Pair.first, [&CGF, &DRE]() {
2938 return CGF.EmitLValue(&DRE).getAddress();
2941 for (
const auto &Pair : PrivatePtrs) {
2942 Address Replacement(CGF.Builder.CreateLoad(Pair.second),
2943 CGF.getContext().getDeclAlign(Pair.first));
2944 Scope.
addPrivate(Pair.first, [Replacement]() { return Replacement; });
2948 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
2951 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
2952 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(9)));
2953 for (
unsigned Cnt = 0, E = Data.
ReductionVars.size(); Cnt < E; ++Cnt) {
2954 RedCG.emitSharedLValue(CGF, Cnt);
2959 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
2961 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
2964 Address(CGF.EmitScalarConversion(
2965 Replacement.
getPointer(), CGF.getContext().VoidPtrTy,
2966 CGF.getContext().getPointerType(
2972 [Replacement]() {
return Replacement; });
2982 auto IPriv = C->privates().begin();
2983 auto IRed = C->reduction_ops().begin();
2984 auto ITD = C->taskgroup_descriptors().begin();
2985 for (
const Expr *Ref : C->varlists()) {
2986 InRedVars.emplace_back(Ref);
2987 InRedPrivs.emplace_back(*IPriv);
2988 InRedOps.emplace_back(*IRed);
2989 TaskgroupDescriptors.emplace_back(*ITD);
2990 std::advance(IPriv, 1);
2991 std::advance(IRed, 1);
2992 std::advance(ITD, 1);
2998 if (!InRedVars.empty()) {
3000 for (
unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
3001 RedCG.emitSharedLValue(CGF, Cnt);
3008 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
3011 CGF.EmitLoadOfScalar(CGF.EmitLValue(TaskgroupDescriptors[Cnt]),
3012 TaskgroupDescriptors[Cnt]->getExprLoc());
3013 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
3016 CGF.EmitScalarConversion(
3017 Replacement.
getPointer(), CGF.getContext().VoidPtrTy,
3018 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
3019 InRedPrivs[Cnt]->getExprLoc()),
3023 [Replacement]() {
return Replacement; });
3031 llvm::Value *OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
3032 S, *I, *PartId, *TaskT, S.getDirectiveKind(), CodeGen, Data.
Tied,
3034 OMPLexicalScope
Scope(*
this, S);
3035 TaskGen(*
this, OutlinedFn, Data);
3073 Address CapturedStruct = GenerateCapturedStmtArgument(*CS);
3076 auto PartId = std::next(I);
3077 auto TaskT = std::next(I, 4);
3080 Data.
Final.setInt(
false);
3083 auto IRef = C->varlist_begin();
3084 auto IElemInitRef = C->inits().begin();
3085 for (
auto *IInit : C->private_copies()) {
3099 getContext(), getContext().getTranslationUnitDecl(), 0);
3101 QualType BaseAndPointersType = getContext().getConstantArrayType(
3105 getContext(), Data, BaseAndPointersType, CD, S.
getBeginLoc());
3107 getContext(), Data, BaseAndPointersType, CD, S.
getBeginLoc());
3108 QualType SizesType = getContext().getConstantArrayType(
3118 [&InputInfo]() {
return InputInfo.
SizesArray; });
3123 for (
const Expr *IRef : C->varlists())
3124 Data.
Dependences.emplace_back(C->getDependencyKind(), IRef);
3125 auto &&CodeGen = [&Data, &S, CS, &BodyGen, BPVD, PVD, SVD,
3130 enum { PrivatesParam = 2, CopyFnParam = 3 };
3132 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(CopyFnParam)));
3133 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
3134 CS->getCapturedDecl()->getParam(PrivatesParam)));
3138 CallArgs.push_back(PrivatesPtr);
3140 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3142 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->
getType()),
3143 ".firstpriv.ptr.addr");
3144 PrivatePtrs.emplace_back(VD, PrivatePtr);
3145 CallArgs.push_back(PrivatePtr.getPointer());
3147 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
3149 for (
const auto &Pair : PrivatePtrs) {
3150 Address Replacement(CGF.Builder.CreateLoad(Pair.second),
3151 CGF.getContext().getDeclAlign(Pair.first));
3152 Scope.
addPrivate(Pair.first, [Replacement]() { return Replacement; });
3159 CGF.GetAddrOfLocalVar(BPVD), 0, CGF.getPointerSize());
3161 CGF.GetAddrOfLocalVar(PVD), 0, CGF.getPointerSize());
3162 InputInfo.
SizesArray = CGF.Builder.CreateConstArrayGEP(
3163 CGF.GetAddrOfLocalVar(SVD), 0, CGF.getSizeSize());
3167 OMPLexicalScope LexScope(CGF, S, OMPD_task,
false);
3170 llvm::Value *OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
3171 S, *I, *PartId, *TaskT, S.getDirectiveKind(), CodeGen,
true,
3173 llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<
OMPNowaitClause>() ? 1 : 0);
3175 getContext().getIntTypeForBitwidth(32, 0),
3178 CGM.getOpenMPRuntime().emitTaskCall(*
this, S.getBeginLoc(), S, OutlinedFn,
3179 SharedsTy, CapturedStruct, &IfCond, Data);
3185 Address CapturedStruct = GenerateCapturedStmtArgument(*CS);
3187 const Expr *IfCond =
nullptr;
3190 C->getNameModifier() == OMPD_task) {
3191 IfCond = C->getCondition();
3202 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
3205 CGF.CGM.getOpenMPRuntime().emitTaskCall(CGF, S.
getBeginLoc(), S, OutlinedFn,
3206 SharedsTy, CapturedStruct, IfCond,
3209 EmitOMPTaskBasedDirective(S, OMPD_task, BodyGen, TaskGen, Data);
3214 CGM.getOpenMPRuntime().emitTaskyieldCall(*
this, S.
getBeginLoc());
3218 CGM.getOpenMPRuntime().emitBarrierCall(*
this, S.
getBeginLoc(), OMPD_barrier);
3222 CGM.getOpenMPRuntime().emitTaskwaitCall(*
this, S.
getBeginLoc());
3234 auto IPriv = C->privates().begin();
3235 auto IRed = C->reduction_ops().begin();
3236 auto ILHS = C->lhs_exprs().begin();
3237 auto IRHS = C->rhs_exprs().begin();
3238 for (
const Expr *Ref : C->varlists()) {
3242 LHSs.emplace_back(*ILHS);
3243 RHSs.emplace_back(*IRHS);
3244 std::advance(IPriv, 1);
3245 std::advance(IRed, 1);
3246 std::advance(ILHS, 1);
3247 std::advance(IRHS, 1);
3253 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3261 CGM.getOpenMPRuntime().emitTaskgroupRegion(*
this, CodeGen, S.
getBeginLoc());
3265 CGM.getOpenMPRuntime().emitFlush(
3269 return llvm::makeArrayRef(FlushClause->varlist_begin(),
3270 FlushClause->varlist_end());
3281 const auto *IVDecl = cast<VarDecl>(IVExpr->getDecl());
3282 EmitVarDecl(*IVDecl);
3288 EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
3295 bool HasLastprivateClause =
false;
3298 OMPLoopScope PreInitScope(*
this, S);
3303 llvm::BasicBlock *ContBlock =
nullptr;
3304 if (ConstantFoldsToSimpleInteger(S.
getPreCond(), CondConstant)) {
3308 llvm::BasicBlock *ThenBlock = createBasicBlock(
"omp.precond.then");
3309 ContBlock = createBasicBlock(
"omp.precond.end");
3311 getProfileCount(&S));
3312 EmitBlock(ThenBlock);
3313 incrementProfileCounter(&S);
3322 *
this, cast<DeclRefExpr>(
3327 *
this, cast<DeclRefExpr>(
3337 if (EmitOMPFirstprivateClause(S, LoopScope)) {
3341 CGM.getOpenMPRuntime().emitBarrierCall(
3345 EmitOMPPrivateClause(S, LoopScope);
3349 EmitOMPReductionClauseInit(S, LoopScope);
3350 HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope);
3351 EmitOMPPrivateLoopCounters(S, LoopScope);
3354 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*
this, S);
3360 ScheduleKind = C->getDistScheduleKind();
3361 if (
const Expr *Ch = C->getChunkSize()) {
3362 Chunk = EmitScalarExpr(Ch);
3363 Chunk = EmitScalarConversion(Chunk, Ch->getType(),
3369 CGM.getOpenMPRuntime().getDefaultDistScheduleAndChunk(
3370 *
this, S, ScheduleKind, Chunk);
3372 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
3373 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
3383 bool StaticChunked = RT.isStaticChunked(
3384 ScheduleKind, Chunk !=
nullptr) &&
3386 if (RT.isStaticNonchunked(ScheduleKind,
3387 Chunk !=
nullptr) ||
3390 EmitOMPSimdInit(S,
true);
3391 CGOpenMPRuntime::StaticRTInput StaticInit(
3393 LB.
getAddress(), UB.getAddress(), ST.getAddress(),
3394 StaticChunked ? Chunk :
nullptr);
3395 RT.emitDistributeStaticInit(*
this, S.
getBeginLoc(), ScheduleKind,
3398 getJumpDestInCurrentScope(createBasicBlock(
"omp.loop.exit"));
3442 CodeGenLoop(CGF, S, LoopExit);
3445 if (StaticChunked) {
3452 EmitBlock(LoopExit.getBlock());
3454 RT.emitForStaticFinish(*
this, S.getBeginLoc(), S.getDirectiveKind());
3458 const OMPLoopArguments LoopArguments = {
3461 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments,
3466 return CGF.
Builder.CreateIsNotNull(
3473 EmitOMPReductionClauseFinal(S, OMPD_simd);
3477 return CGF.
Builder.CreateIsNotNull(
3482 if (HasLastprivateClause) {
3483 EmitOMPLastprivateClauseFinal(
3485 Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.
getBeginLoc())));
3491 EmitBranch(ContBlock);
3492 EmitBlock(ContBlock,
true);
3503 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_distribute, CodeGen);
3512 Fn->setDoesNotRecurse();
3519 "No associated statement must be in ordered depend construct.");
3521 CGM.getOpenMPRuntime().emitDoacrossOrdered(*
this, DC);
3530 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
3532 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.
getBeginLoc(),
3533 OutlinedFn, CapturedVars);
3540 CGM.getOpenMPRuntime().emitOrderedRegion(*
this, CodeGen, S.
getBeginLoc(), !C);
3547 "DestType must have scalar evaluation kind.");
3548 assert(!Val.
isAggregate() &&
"Must be a scalar or complex.");
3559 "DestType must have complex evaluation kind.");
3568 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
3570 assert(Val.
isComplex() &&
"Must be a scalar or complex.");
3575 Val.
getComplexVal().first, SrcElementType, DestElementType, Loc);
3577 Val.
getComplexVal().second, SrcElementType, DestElementType, Loc);
3588 IsSeqCst ? llvm::AtomicOrdering::SequentiallyConsistent
3589 : llvm::AtomicOrdering::Monotonic,
3596 switch (getEvaluationKind(LVal.
getType())) {
3599 *
this, RVal, RValTy, LVal.
getType(), Loc)),
3608 llvm_unreachable(
"Must be a scalar or complex.");
3616 assert(V->
isLValue() &&
"V of 'omp atomic read' is not lvalue");
3617 assert(X->
isLValue() &&
"X of 'omp atomic read' is not lvalue");
3620 RValue Res = XLValue.isGlobalReg()
3624 IsSeqCst ? llvm::AtomicOrdering::SequentiallyConsistent
3625 : llvm::AtomicOrdering::Monotonic,
3626 XLValue.isVolatile());
3640 assert(X->
isLValue() &&
"X of 'omp atomic write' is not lvalue");
3653 llvm::AtomicOrdering AO,
3654 bool IsXLHSInRHSPart) {
3659 if (BO == BO_Comma || !Update.
isScalar() ||
3667 return std::make_pair(
false,
RValue::get(
nullptr));
3669 llvm::AtomicRMWInst::BinOp RMWOp;
3672 RMWOp = llvm::AtomicRMWInst::Add;
3675 if (!IsXLHSInRHSPart)
3676 return std::make_pair(
false,
RValue::get(
nullptr));
3677 RMWOp = llvm::AtomicRMWInst::Sub;
3683 RMWOp = llvm::AtomicRMWInst::Or;
3686 RMWOp = llvm::AtomicRMWInst::Xor;
3690 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Min
3691 : llvm::AtomicRMWInst::Max)
3692 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMin
3693 : llvm::AtomicRMWInst::UMax);
3697 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Max
3698 : llvm::AtomicRMWInst::Min)
3699 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMax
3700 : llvm::AtomicRMWInst::UMin);
3703 RMWOp = llvm::AtomicRMWInst::Xchg;
3712 return std::make_pair(
false,
RValue::get(
nullptr));
3731 llvm_unreachable(
"Unsupported atomic update operation");
3734 if (
auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
3735 UpdateVal = CGF.
Builder.CreateIntCast(
3759 EmitStoreThroughLValue(CommonGen(EmitLoadOfLValue(X, Loc)), X);
3770 const Expr *UE,
bool IsXLHSInRHSPart,
3773 "Update expr in 'atomic update' must be a binary operator.");
3781 assert(X->
isLValue() &&
"X of 'omp atomic update' is not lvalue");
3784 llvm::AtomicOrdering AO = IsSeqCst
3785 ? llvm::AtomicOrdering::SequentiallyConsistent
3786 : llvm::AtomicOrdering::Monotonic;
3787 const auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
3788 const auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
3791 auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](
RValue XRValue) {
3797 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
3820 llvm_unreachable(
"Must be a scalar or complex.");
3824 bool IsPostfixUpdate,
const Expr *V,
3826 const Expr *UE,
bool IsXLHSInRHSPart,
3828 assert(X->
isLValue() &&
"X of 'omp atomic capture' is not lvalue");
3829 assert(V->
isLValue() &&
"V of 'omp atomic capture' is not lvalue");
3834 llvm::AtomicOrdering AO = IsSeqCst
3835 ? llvm::AtomicOrdering::SequentiallyConsistent
3836 : llvm::AtomicOrdering::Monotonic;
3841 "Update expr in 'atomic capture' must be a binary operator.");
3849 const auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
3850 const auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
3852 NewVValType = XRValExpr->getType();
3854 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
3855 IsPostfixUpdate](
RValue XRValue) {
3859 NewVVal = IsPostfixUpdate ? XRValue : Res;
3863 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
3866 if (IsPostfixUpdate) {
3868 NewVVal = Res.second;
3882 auto &&Gen = [&NewVVal, ExprRValue](
RValue XRValue) {
3888 XLValue, ExprRValue, BO_Assign,
false, AO,
3892 NewVVal = IsPostfixUpdate ? Res.second : ExprRValue;
3906 bool IsSeqCst,
bool IsPostfixUpdate,
3908 const Expr *UE,
bool IsXLHSInRHSPart,
3923 IsXLHSInRHSPart, Loc);
3927 case OMPC_num_threads:
3929 case OMPC_firstprivate:
3930 case OMPC_lastprivate:
3931 case OMPC_reduction:
3932 case OMPC_task_reduction:
3933 case OMPC_in_reduction:
3943 case OMPC_copyprivate:
3945 case OMPC_proc_bind:
3952 case OMPC_mergeable:
3957 case OMPC_num_teams:
3958 case OMPC_thread_limit:
3960 case OMPC_grainsize:
3962 case OMPC_num_tasks:
3964 case OMPC_dist_schedule:
3965 case OMPC_defaultmap:
3969 case OMPC_use_device_ptr:
3970 case OMPC_is_device_ptr:
3971 case OMPC_unified_address:
3972 case OMPC_unified_shared_memory:
3973 case OMPC_reverse_offload:
3974 case OMPC_dynamic_allocators:
3975 case OMPC_atomic_default_mem_order:
3976 llvm_unreachable(
"Clause is not allowed in 'omp atomic'.");
3985 if (C->getClauseKind() != OMPC_seq_cst) {
3986 Kind = C->getClauseKind();
3992 if (
const auto *FE = dyn_cast<FullExpr>(CS))
3993 enterFullExpression(FE);
3995 if (
const auto *Compound = dyn_cast<CompoundStmt>(CS)) {
3996 for (
const Stmt *C : Compound->body()) {
3997 if (
const auto *FE = dyn_cast<FullExpr>(C))
3998 enterFullExpression(FE);
4004 CGF.EmitStopPoint(CS);
4010 CGM.getOpenMPRuntime().emitInlinedDirective(*
this, OMPD_atomic, CodeGen);
4021 OMPLexicalScope
Scope(CGF, S, OMPD_target);
4029 llvm::Function *Fn =
nullptr;
4030 llvm::Constant *FnID =
nullptr;
4032 const Expr *IfCond =
nullptr;
4036 C->getNameModifier() == OMPD_target) {
4037 IfCond = C->getCondition();
4043 const Expr *Device =
nullptr;
4045 Device = C->getDevice();
4050 bool IsOffloadEntry =
true;
4054 IsOffloadEntry =
false;
4057 IsOffloadEntry =
false;
4059 assert(CGF.
CurFuncDecl &&
"No parent declaration for target region!");
4060 StringRef ParentName;
4063 if (
const auto *D = dyn_cast<CXXConstructorDecl>(CGF.
CurFuncDecl))
4065 else if (
const auto *D = dyn_cast<CXXDestructorDecl>(CGF.
CurFuncDecl))
4073 IsOffloadEntry, CodeGen);
4074 OMPLexicalScope
Scope(CGF, S, OMPD_task);
4076 OMPLoopScope(CGF, D);
4079 NumIterations = CGF.
Builder.CreateIntCast(NumIterations, CGF.
Int64Ty,
4081 return NumIterations;
4102 StringRef ParentName,
4108 llvm::Constant *Addr;
4111 S, ParentName, Fn, Addr,
true, CodeGen);
4112 assert(Fn && Addr &&
"Target device function emission failed.");
4134 const Expr *NumTeams = NT ? NT->getNumTeams() :
nullptr;
4135 const Expr *ThreadLimit = TL ? TL->getThreadLimit() :
nullptr;
4141 OMPTeamsScope
Scope(CGF, S);
4173 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
4174 CGF.EmitOMPPrivateClause(S, PrivateScope);
4175 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
4178 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
4179 CGF.EmitStmt(CS->getCapturedStmt());
4180 CGF.EmitOMPReductionClauseFinal(S, OMPD_teams);
4194 llvm::Constant *Addr;
4197 S, ParentName, Fn, Addr,
true, CodeGen);
4198 assert(Fn && Addr &&
"Target device function emission failed.");
4222 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
4224 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
4226 CGF.EmitOMPReductionClauseFinal(S, OMPD_teams);
4240 llvm::Constant *Addr;
4243 S, ParentName, Fn, Addr,
true, CodeGen);
4244 assert(Fn && Addr &&
"Target device function emission failed.");
4268 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
4270 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
4272 CGF.EmitOMPReductionClauseFinal(S, OMPD_teams);
4286 llvm::Constant *Addr;
4289 S, ParentName, Fn, Addr,
true, CodeGen);
4290 assert(Fn && Addr &&
"Target device function emission failed.");
4313 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
4315 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
4317 CGF.EmitOMPReductionClauseFinal(S, OMPD_teams);
4335 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
4337 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_simd,
4339 CGF.EmitOMPReductionClauseFinal(S, OMPD_teams);
4358 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
4360 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
4362 CGF.EmitOMPReductionClauseFinal(S, OMPD_teams);
4381 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
4383 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(
4384 CGF, OMPD_distribute, CodeGenDistribute,
false);
4385 CGF.EmitOMPReductionClauseFinal(S, OMPD_teams);
4406 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
4408 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(
4409 CGF, OMPD_distribute, CodeGenDistribute,
false);
4410 CGF.EmitOMPReductionClauseFinal(S, OMPD_teams);
4428 llvm::Constant *Addr;
4431 S, ParentName, Fn, Addr,
true, CodeGen);
4432 assert(Fn && Addr &&
"Target device function emission failed.");
4458 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
4460 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(
4461 CGF, OMPD_distribute, CodeGenDistribute,
false);
4462 CGF.EmitOMPReductionClauseFinal(S, OMPD_teams);
4480 llvm::Constant *Addr;
4483 S, ParentName, Fn, Addr,
true, CodeGen);
4484 assert(Fn && Addr &&
"Target device function emission failed.");
4497 CGM.getOpenMPRuntime().emitCancellationPointCall(*
this, S.
getBeginLoc(),
4502 const Expr *IfCond =
nullptr;
4505 C->getNameModifier() == OMPD_cancel) {
4506 IfCond = C->getCondition();
4510 CGM.getOpenMPRuntime().emitCancelCall(*
this, S.
getBeginLoc(), IfCond,
4516 if (Kind == OMPD_parallel || Kind == OMPD_task ||
4517 Kind == OMPD_target_parallel)
4519 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
4520 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
4521 Kind == OMPD_distribute_parallel_for ||
4522 Kind == OMPD_target_parallel_for ||
4523 Kind == OMPD_teams_distribute_parallel_for ||
4524 Kind == OMPD_target_teams_distribute_parallel_for);
4525 return OMPCancelStack.getExitBlock();
4530 const llvm::DenseMap<const ValueDecl *, Address> &CaptureDeviceAddrMap) {
4531 const auto &C = cast<OMPUseDevicePtrClause>(NC);
4532 auto OrigVarIt = C.varlist_begin();
4533 auto InitIt = C.inits().begin();
4534 for (
const Expr *PvtVarIt : C.private_copies()) {
4535 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*OrigVarIt)->getDecl());
4536 const auto *InitVD = cast<VarDecl>(cast<DeclRefExpr>(*InitIt)->getDecl());
4537 const auto *PvtVD = cast<VarDecl>(cast<DeclRefExpr>(PvtVarIt)->getDecl());
4543 if (
const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
4546 const auto *ME = cast<MemberExpr>(OED->getInit());
4547 assert(isa<CXXThisExpr>(ME->getBase()) &&
4548 "Base should be the current struct!");
4549 MatchingVD = ME->getMemberDecl();
4554 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
4555 if (InitAddrIt == CaptureDeviceAddrMap.end())
4558 bool IsRegistered = PrivateScope.
addPrivate(OrigVD, [
this, OrigVD,
4567 getContext().getPointerType(OrigVD->getType().getNonReferenceType());
4568 llvm::Type *AddrTy = ConvertTypeForMem(AddrQTy);
4569 Address InitAddr = Builder.CreateBitCast(InitAddrIt->second, AddrTy);
4570 setAddrOfLocalVar(InitVD, InitAddr);
4578 LocalDeclMap.erase(InitVD);
4581 return GetAddrOfLocalVar(PvtVD);
4583 assert(IsRegistered &&
"firstprivate var already registered as private");
4595 CGOpenMPRuntime::TargetDataInfo Info(
true);
4600 bool PrivatizeDevicePointers =
false;
4602 bool &PrivatizeDevicePointers;
4605 explicit DevicePointerPrivActionTy(
bool &PrivatizeDevicePointers)
4606 :
PrePostActionTy(), PrivatizeDevicePointers(PrivatizeDevicePointers) {}
4608 PrivatizeDevicePointers =
true;
4611 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
4613 auto &&CodeGen = [&S, &Info, &PrivatizeDevicePointers](
4620 auto &&PrivCodeGen = [&S, &Info, &PrivatizeDevicePointers,
4624 PrivatizeDevicePointers =
false;
4630 if (PrivatizeDevicePointers) {
4634 CGF.EmitOMPUseDevicePtrClause(*C, PrivateScope,
4635 Info.CaptureDeviceAddrMap);
4650 OMPLexicalScope
Scope(CGF, S);
4651 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_target_data,
4659 if (CGM.getLangOpts().OMPTargetTriples.empty()) {
4665 const Expr *IfCond =
nullptr;
4667 IfCond = C->getCondition();
4670 const Expr *Device =
nullptr;
4672 Device = C->getDevice();
4678 CGM.getOpenMPRuntime().emitTargetDataCalls(*
this, S, IfCond, Device, RCG,
4686 if (CGM.getLangOpts().OMPTargetTriples.empty())
4690 const Expr *IfCond =
nullptr;
4692 IfCond = C->getCondition();
4695 const Expr *Device =
nullptr;
4697 Device = C->getDevice();
4699 OMPLexicalScope
Scope(*
this, S, OMPD_task);
4700 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond, Device);
4707 if (CGM.getLangOpts().OMPTargetTriples.empty())
4711 const Expr *IfCond =
nullptr;
4713 IfCond = C->getCondition();
4716 const Expr *Device =
nullptr;
4718 Device = C->getDevice();
4720 OMPLexicalScope
Scope(*
this, S, OMPD_task);
4721 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond, Device);
4733 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
4734 CGF.EmitOMPPrivateClause(S, PrivateScope);
4735 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
4738 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
4741 CGF.EmitOMPReductionClauseFinal(S, OMPD_parallel);
4756 llvm::Constant *Addr;
4759 S, ParentName, Fn, Addr,
true, CodeGen);
4760 assert(Fn && Addr &&
"Target device function emission failed.");
4780 CGF, OMPD_target_parallel_for, S.
hasCancel());
4796 llvm::Constant *Addr;
4799 S, ParentName, Fn, Addr,
true, CodeGen);
4800 assert(Fn && Addr &&
"Target device function emission failed.");
4835 llvm::Constant *Addr;
4838 S, ParentName, Fn, Addr,
true, CodeGen);
4839 assert(Fn && Addr &&
"Target device function emission failed.");
4854 const auto *VDecl = cast<VarDecl>(Helper->
getDecl());
4863 Address CapturedStruct = GenerateCapturedStmtArgument(*CS);
4865 const Expr *IfCond =
nullptr;
4868 C->getNameModifier() == OMPD_taskloop) {
4869 IfCond = C->getCondition();
4883 Data.
Schedule.setPointer(EmitScalarExpr(Clause->getGrainsize()));
4887 Data.
Schedule.setPointer(EmitScalarExpr(Clause->getNumTasks()));
4901 llvm::BasicBlock *ContBlock =
nullptr;
4902 OMPLoopScope PreInitScope(CGF, S);
4903 if (CGF.ConstantFoldsToSimpleInteger(S.
getPreCond(), CondConstant)) {
4907 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock(
"taskloop.if.then");
4908 ContBlock = CGF.createBasicBlock(
"taskloop.if.end");
4910 CGF.getProfileCount(&S));
4911 CGF.EmitBlock(ThenBlock);
4912 CGF.incrementProfileCounter(&S);
4916 CGF.EmitOMPSimdInit(S);
4920 enum { LowerBound = 5, UpperBound, Stride, LastIter };
4922 auto *LBP = std::next(I, LowerBound);
4923 auto *UBP = std::next(I, UpperBound);
4924 auto *STP = std::next(I, Stride);
4925 auto *LIP = std::next(I, LastIter);
4933 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
4934 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
4938 const auto *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
4939 CGF.EmitVarDecl(*IVDecl);
4940 CGF.EmitIgnoredExpr(S.
getInit());
4946 CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
4954 CGF.EmitOMPLoopBody(S,
JumpDest());
4955 CGF.EmitStopPoint(&S);
4960 CGF.EmitBranch(ContBlock);
4961 CGF.EmitBlock(ContBlock,
true);
4964 if (HasLastprivateClause) {
4965 CGF.EmitOMPLastprivateClauseFinal(
4967 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
4968 CGF.GetAddrOfLocalVar(*LIP),
false,
4972 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
4975 auto &&CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
4977 OMPLoopScope PreInitScope(CGF, S);
4978 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.
getBeginLoc(), S,
4979 OutlinedFn, SharedsTy,
4980 CapturedStruct, IfCond, Data);
4982 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
4986 EmitOMPTaskBasedDirective(S, OMPD_taskloop, BodyGen, TaskGen, Data);
4988 CGM.getOpenMPRuntime().emitTaskgroupRegion(
5001 EmitOMPTaskLoopBasedDirective(S);
5006 EmitOMPTaskLoopBasedDirective(S);
5014 if (CGM.getLangOpts().OMPTargetTriples.empty())
5018 const Expr *IfCond =
nullptr;
5020 IfCond = C->getCondition();
5023 const Expr *Device =
nullptr;
5025 Device = C->getDevice();
5027 OMPLexicalScope
Scope(*
this, S, OMPD_task);
5028 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*
this, S, IfCond, Device);
5040 if (
const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
5041 for (
const Expr *E : LD->counters()) {
5042 const auto *VD = dyn_cast<
VarDecl>(cast<DeclRefExpr>(E)->getDecl());
5046 VD, [&GlobLVal]() {
return GlobLVal.
getAddress(); });
5048 if (isa<OMPCapturedExprDecl>(VD)) {
5050 if (!CGF.LocalDeclMap.count(VD))
5055 if (!C->getNumForLoops())
5057 for (
unsigned I = LD->getCollapsedNumber(),
5058 E = C->getLoopNumIterations().size();
5060 if (
const auto *VD = dyn_cast<OMPCapturedExprDecl>(
5061 cast<DeclRefExpr>(C->getLoopCounter(I))->getDecl())) {
5063 if (!CGF.LocalDeclMap.count(VD))
5073 OMPSimdLexicalScope
Scope(*
this, D);
5074 CGM.getOpenMPRuntime().emitInlinedDirective(
const CGFunctionInfo & arrangeBuiltinFunctionDeclaration(QualType resultType, const FunctionArgList &args)
A builtin function is a freestanding function using the default C conventions.
This represents '#pragma omp distribute simd' composite directive.
Expr * getNextUpperBound() const
This represents '#pragma omp master' directive.
This represents '#pragma omp task' directive.
static const Decl * getCanonicalDecl(const Decl *D)
Represents a function declaration or definition.
This represents 'thread_limit' clause in the '#pragma omp ...' directive.
Expr * getUpperBoundVariable() const
Other implicit parameter.
void EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S)
void EmitOMPTargetTaskBasedDirective(const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen, OMPTargetDataInfo &InputInfo)
static void emitOMPAtomicWriteExpr(CodeGenFunction &CGF, bool IsSeqCst, const Expr *X, const Expr *E, SourceLocation Loc)
This represents clause 'copyin' in the '#pragma omp ...' directives.
PointerType - C99 6.7.5.1 - Pointer Declarators.
Scheduling data for loop-based OpenMP directives.
A (possibly-)qualified type.
capture_init_iterator capture_init_begin()
Retrieve the first initialization argument.
CodeGenTypes & getTypes()
ArrayRef< OMPClause * > clauses()
void EmitBranchOnBoolExpr(const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount)
EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g.
static void emitOMPAtomicReadExpr(CodeGenFunction &CGF, bool IsSeqCst, const Expr *X, const Expr *V, SourceLocation Loc)
void EmitVarDecl(const VarDecl &D)
EmitVarDecl - Emit a local variable declaration.
param_iterator param_begin() const
Retrieve an iterator pointing to the first parameter decl.
Address CreateMemTemp(QualType T, const Twine &Name="tmp", Address *Alloca=nullptr)
CreateMemTemp - Create a temporary memory object of the given type, with appropriate alignmen and cas...
bool HaveInsertPoint() const
HaveInsertPoint - True if an insertion point is defined.
void EmitOMPDistributeDirective(const OMPDistributeDirective &S)
static void EmitOMPTargetParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForSimdDirective &S)
Emit device code for the target parallel for simd directive.
DominatorTree GraphTraits specialization so the DominatorTree can be iterable by generic graph iterat...
static std::pair< LValue, LValue > emitDistributeParallelForInnerBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S)
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer...
static OMPClauseWithPreInit * get(OMPClause *C)
Stmt - This represents one statement.
This represents clause 'in_reduction' in the '#pragma omp task' directives.
Expr * getLowerBoundVariable() const
void EmitStoreThroughGlobalRegLValue(RValue Src, LValue Dst)
Store of global named registers are always calls to intrinsics.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
bool requiresCleanups() const
Determine whether this scope requires any cleanups.
void EmitOMPTargetSimdDirective(const OMPTargetSimdDirective &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.
SmallVector< std::pair< OpenMPDependClauseKind, const Expr * >, 4 > Dependences
This represents '#pragma omp for simd' directive.
SmallVector< const Expr *, 4 > LastprivateCopies
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type...
Decl - This represents one declaration (or definition), e.g.
This represents 'grainsize' clause in the '#pragma omp ...' directive.
This represents '#pragma omp teams distribute parallel for' composite directive.
SourceLocation getBeginLoc() const
Returns starting location of directive kind.
const Decl * CurCodeDecl
CurCodeDecl - This is the inner-most code context, which includes blocks.
static void emitOMPAtomicUpdateExpr(CodeGenFunction &CGF, bool IsSeqCst, const Expr *X, const Expr *E, const Expr *UE, bool IsXLHSInRHSPart, SourceLocation Loc)
llvm::Value * getTypeSize(QualType Ty)
Returns calculated size of the specified type.
This represents 'if' clause in the '#pragma omp ...' directive.
CapturedStmt * getInnermostCapturedStmt()
Get innermost captured statement for the construct.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
void EmitOMPOrderedDirective(const OMPOrderedDirective &S)
This represents 'priority' clause in the '#pragma omp ...' directive.
static void mapParam(CodeGenFunction &CGF, const DeclRefExpr *Helper, const ImplicitParamDecl *PVD, CodeGenFunction::OMPPrivateScope &Privates)
Emit a helper variable and return corresponding lvalue.
The base class of the type hierarchy.
This represents '#pragma omp target teams distribute' combined directive.
void EmitStoreThroughLValue(RValue Src, LValue Dst, bool isInit=false)
EmitStoreThroughLValue - Store the specified rvalue into the specified lvalue, where both are guarant...
static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind, bool IsSeqCst, bool IsPostfixUpdate, const Expr *X, const Expr *V, const Expr *E, const Expr *UE, bool IsXLHSInRHSPart, SourceLocation Loc)
const RecordDecl * getCapturedRecordDecl() const
Retrieve the record declaration for captured variables.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
virtual const FieldDecl * lookup(const VarDecl *VD) const
Lookup the captured field decl for a variable.
const TargetInfo & getTargetInfo() const
Expr * getCombinedParForInDistCond() const
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
static void emitCommonOMPParallelDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, const CodeGenBoundParametersTy &CodeGenBoundParameters)
Address EmitLoadOfPointer(Address Ptr, const PointerType *PtrTy, LValueBaseInfo *BaseInfo=nullptr, TBAAAccessInfo *TBAAInfo=nullptr)
Floating point control options.
This represents '#pragma omp parallel for' directive.
void GenerateOpenMPCapturedVars(const CapturedStmt &S, SmallVectorImpl< llvm::Value *> &CapturedVars)
This represents '#pragma omp target teams distribute parallel for' combined directive.
Expr * getCombinedEnsureUpperBound() const
void EmitAtomicStore(RValue rvalue, LValue lvalue, bool isInit)
bool ConstantFoldsToSimpleInteger(const Expr *Cond, bool &Result, bool AllowLabels=false)
ConstantFoldsToSimpleInteger - If the specified expression does not fold to a constant, or if it does but contains a label, return false.
Represents a point when we exit a loop.
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.
SmallVector< const Expr *, 4 > ReductionCopies
SourceLocation getEndLoc() const
Returns ending location of directive.
void EmitOMPParallelForSimdDirective(const OMPParallelForSimdDirective &S)
static LValue createSectionLVal(CodeGenFunction &CGF, QualType Ty, const Twine &Name, llvm::Value *Init=nullptr)
This represents '#pragma omp target exit data' directive.
Address GetAddrOfLocalVar(const VarDecl *VD)
GetAddrOfLocalVar - Return the address of a local variable.
CanQualType getCanonicalParamType(QualType T) const
Return the canonical parameter type corresponding to the specific potentially non-canonical one...
llvm::Function * GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S)
Represents a variable declaration or definition.
This represents clause 'private' in the '#pragma omp ...' directives.
void EmitOMPCriticalDirective(const OMPCriticalDirective &S)
bool hasCancel() const
Return true if current directive has inner cancel directive.
This represents 'num_threads' clause in the '#pragma omp ...' directive.
const Stmt * getBody() const
Extra information about a function prototype.
uint64_t getProfileCount(const Stmt *S)
Get the profiler's count for the given statement.
Expr * getCombinedUpperBoundVariable() const
Expr * getCalcLastIteration() const
llvm::Value * getPointer() const
unsigned getContextParamPosition() const
void EmitOMPInnerLoop(const Stmt &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.
This represents implicit clause 'flush' for the '#pragma omp flush' directive.
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 EmitOMPTeamsDistributeDirective(const OMPTeamsDistributeDirective &S)
static void emitTargetTeamsDistributeRegion(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsDistributeDirective &S)
bool isXLHSInRHSPart() const
Return true if helper update expression has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' and...
static void EmitOMPTargetParallelDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelDirective &S)
This represents 'nogroup' clause in the '#pragma omp ...' directive.
A jump destination is an abstract label, branching to which may require a jump out through normal cle...
bool EmitOMPWorksharingLoop(const OMPLoopDirective &S, Expr *EUB, const CodeGenLoopBoundsTy &CodeGenLoopBounds, const CodeGenDispatchBoundsTy &CGDispatchBounds)
Emit code for the worksharing loop-based directive.
This represents 'safelen' clause in the '#pragma omp ...' directive.
void EmitOMPTargetTeamsDistributeParallelForSimdDirective(const OMPTargetTeamsDistributeParallelForSimdDirective &S)
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Expr * IgnoreImpCasts() LLVM_READONLY
IgnoreImpCasts - Skip past any implicit casts which might surround this expression.
void EmitOMPTaskLoopSimdDirective(const OMPTaskLoopSimdDirective &S)
SmallVector< const Expr *, 4 > PrivateVars
Represents a struct/union/class.
llvm::DenseMap< const VarDecl *, FieldDecl * > LambdaCaptureFields
One of these records is kept for each identifier that is lexed.
void EmitOMPSimdDirective(const OMPSimdDirective &S)
This represents '#pragma omp parallel' directive.
Address getAddress() const
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
A C++ nested-name-specifier augmented with source location information.
This represents 'simd' clause in the '#pragma omp ...' directive.
llvm::IntegerType * Int64Ty
void EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S)
The scope used to remap some variables as private in the OpenMP loop body (or other captured region e...
field_range fields() const
static void emitTargetRegion(CodeGenFunction &CGF, const OMPTargetDirective &S, PrePostActionTy &Action)
Expr * getEnsureUpperBound() const
SmallVector< const Expr *, 4 > LastprivateVars
SourceLocation getBeginLoc() const LLVM_READONLY
Address EmitLoadOfReference(LValue RefLVal, LValueBaseInfo *PointeeBaseInfo=nullptr, TBAAAccessInfo *PointeeTBAAInfo=nullptr)
Represents a member of a struct/union/class.
This represents clause 'lastprivate' in the '#pragma omp ...' directives.
void EmitOMPTaskBasedDirective(const OMPExecutableDirective &S, const OpenMPDirectiveKind CapturedRegion, const RegionCodeGenTy &BodyGen, const TaskGenTy &TaskGen, OMPTaskDataTy &Data)
void EmitOMPDistributeLoop(const OMPLoopDirective &S, const CodeGenLoopTy &CodeGenLoop, Expr *IncExpr)
Emit code for the distribute loop-based directive.
CharUnits getAlignment() const
llvm::IntegerType * SizeTy
const CapturedStmt * getCapturedStmt(OpenMPDirectiveKind RegionKind) const
Returns the captured statement associated with the component region within the (combined) directive...
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
static void emitSimdlenSafelenClause(CodeGenFunction &CGF, const OMPExecutableDirective &D, bool IsMonotonic)
ArrayRef< Expr * > updates()
bool isReferenceType() const
void EmitOMPAggregateAssign(Address DestAddr, Address SrcAddr, QualType OriginalType, const llvm::function_ref< void(Address, Address)> CopyGen)
Perform element by element copying of arrays with type OriginalType from SrcAddr to DestAddr using co...
void EmitOMPPrivateLoopCounters(const OMPLoopDirective &S, OMPPrivateScope &LoopScope)
Emit initial code for loop counters of loop-based directives.
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)
This represents '#pragma omp target simd' directive.
Address getAllocatedAddress() const
Returns the raw, allocated address, which is not necessarily the address of the object itself...
OpenMPDirectiveKind getDirectiveKind() const
SourceLocation getBeginLoc() const LLVM_READONLY
This represents '#pragma omp barrier' directive.
This is a common base class for loop directives ('omp simd', 'omp for', 'omp for simd' etc...
This represents '#pragma omp critical' directive.
static std::pair< bool, RValue > emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X, RValue Update, BinaryOperatorKind BO, llvm::AtomicOrdering AO, bool IsXLHSInRHSPart)
OpenMPDirectiveKind getCancelRegion() const
Get cancellation region for the current cancellation point.
static void emitOMPAtomicCaptureExpr(CodeGenFunction &CGF, bool IsSeqCst, bool IsPostfixUpdate, const Expr *V, const Expr *X, const Expr *E, const Expr *UE, bool IsXLHSInRHSPart, SourceLocation Loc)
An r-value expression (a pr-value in the C++11 taxonomy) produces a temporary value.
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 EmitOMPDistributeParallelForSimdDirective(const OMPDistributeParallelForSimdDirective &S)
bool EmitOMPLastprivateClauseInit(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
Emit initial code for lastprivate variables.
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.
This represents clause 'copyprivate' in the '#pragma omp ...' directives.
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
This represents '#pragma omp distribute parallel for' composite directive.
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
This represents '#pragma omp teams distribute parallel for simd' composite directive.
static bool hasScalarEvaluationKind(QualType T)
Expr *const * const_capture_init_iterator
Const iterator that walks over the capture initialization arguments.
void EmitOMPTargetTeamsDistributeSimdDirective(const OMPTargetTeamsDistributeSimdDirective &S)
ArrayRef< Expr * > finals()
Expr * getIsLastIterVariable() const
void emitOMPSimpleStore(LValue LVal, RValue RVal, QualType RValTy, SourceLocation Loc)
OpenMPScheduleClauseKind Schedule
CharUnits - This is an opaque type for sizes expressed in character units.
static void emitEmptyOrdered(CodeGenFunction &, SourceLocation Loc, const unsigned IVSize, const bool IVSigned)
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
static void emitDistributeParallelForDistributeInnerBoundParams(CodeGenFunction &CGF, const OMPExecutableDirective &S, llvm::SmallVectorImpl< llvm::Value *> &CapturedVars)
virtual bool hasBuiltinAtomic(uint64_t AtomicSizeInBits, uint64_t AlignmentInBits) const
Returns true if the given target supports lock-free atomic operations at the specified width and alig...
llvm::function_ref< std::pair< LValue, LValue > CodeGenFunction &, const OMPExecutableDirective &S)> CodeGenLoopBoundsTy
Expr * getX()
Get 'x' part of the associated expression/statement.
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type...
void EmitOMPCancellationPointDirective(const OMPCancellationPointDirective &S)
param_iterator param_end() const
Retrieve an iterator one past the last parameter decl.
CharUnits getAlignment() const
Return the alignment of this pointer.
void EmitOMPTeamsDistributeParallelForSimdDirective(const OMPTeamsDistributeParallelForSimdDirective &S)
void EmitOMPTargetDirective(const OMPTargetDirective &S)
Expr * getIterationVariable() const
A builtin binary operation expression such as "x + y" or "x <= y".
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
OpenMPScheduleClauseModifier M2
void setVectorizeWidth(unsigned W)
Set the vectorize width for the next loop pushed.
SmallVector< const Expr *, 4 > PrivateCopies
void restore(CodeGenFunction &CGF)
Restores original addresses of the variables.
static llvm::Function * emitOutlinedOrderedFunction(CodeGenModule &CGM, const CapturedStmt *S)
void EmitOMPTargetUpdateDirective(const OMPTargetUpdateDirective &S)
This represents '#pragma omp cancellation point' directive.
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
static LValue EmitOMPHelperVar(CodeGenFunction &CGF, const DeclRefExpr *Helper)
Emit a helper variable and return corresponding lvalue.
Address adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, Address PrivateAddr)
Adjusts PrivatedAddr for using instead of the original variable address in normal operations...
Expr * getSizeExpr() const
Scope - A scope is a transient data structure that is used while parsing the program.
field_iterator field_begin() const
This represents 'final' clause in the '#pragma omp ...' directive.
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
void EmitOMPParallelDirective(const OMPParallelDirective &S)
llvm::BasicBlock * createBasicBlock(const Twine &name="", llvm::Function *parent=nullptr, llvm::BasicBlock *before=nullptr)
createBasicBlock - Create an LLVM basic block.
This represents '#pragma omp teams' directive.
void EmitIgnoredExpr(const Expr *E)
EmitIgnoredExpr - Emit an expression in a context which ignores the result.
SmallVector< const Expr *, 4 > FirstprivateCopies
static void emitPostUpdateForReductionClause(CodeGenFunction &CGF, const OMPExecutableDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
This represents clause 'reduction' in the '#pragma omp ...' directives.
const VarDecl * getBaseDecl(unsigned N) const
Returns the base declaration of the reduction item.
This represents '#pragma omp teams distribute simd' combined directive.
void ForceCleanup(std::initializer_list< llvm::Value **> ValuesToReload={})
Force the emission of cleanups now, instead of waiting until this object is destroyed.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
CharUnits getPointerAlign() const
void EmitOMPSimdFinal(const OMPLoopDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
An ordinary object is located at an address in memory.
SmallVector< const Expr *, 4 > ReductionOps
Controls insertion of cancellation exit blocks in worksharing constructs.
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV=nullptr)
Increment the profiler's counter for the given statement by StepV.
llvm::function_ref< std::pair< llvm::Value *, llvm::Value * > CodeGenFunction &, const OMPExecutableDirective &S, Address LB, Address UB)> CodeGenDispatchBoundsTy
Represents the body of a CapturedStmt, and serves as its DeclContext.
SmallVector< const Expr *, 4 > ReductionVars
static llvm::Value * convertToScalarValue(CodeGenFunction &CGF, RValue Val, QualType SrcType, QualType DestType, SourceLocation Loc)
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool isInlineSpecified=false, bool hasWrittenPrototype=true, bool isConstexprSpecified=false)
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)
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...
static CodeGenFunction::ComplexPairTy convertToComplexValue(CodeGenFunction &CGF, RValue Val, QualType SrcType, QualType DestType, SourceLocation Loc)
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
This represents '#pragma omp target parallel for simd' directive.
ArrayRef< Expr * > private_counters()
CompoundStmt - This represents a group of statements like { stmt stmt }.
std::pair< llvm::Value *, llvm::Value * > ComplexPairTy
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var)
EmitAutoVarAlloca - Emit the alloca and debug information for a local variable.
ASTContext & getContext() const
bool hasCancel() const
Return true if current directive has inner cancel directive.
void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S)
This represents '#pragma omp taskgroup' directive.
RValue - This trivial value class is used to represent the result of an expression that is evaluated...
This represents clause 'aligned' in the '#pragma omp ...' directives.
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat)
Class intended to support codegen of all kind of the reduction clauses.
bool isGlobalVarCaptured(const VarDecl *VD) const
Checks if the global variable is captured in current function.
Expr * getCombinedLowerBoundVariable() const
The class used to assign some variables some temporarily addresses.
This represents clause 'task_reduction' in the '#pragma omp taskgroup' directives.
void EmitOMPLoopBody(const OMPLoopDirective &D, JumpDest LoopExit)
Helper for the OpenMP loop directives.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location, which defaults to the empty location.
static ImplicitParamDecl * createImplicitFirstprivateForType(ASTContext &C, OMPTaskDataTy &Data, QualType Ty, CapturedDecl *CD, SourceLocation Loc)
This represents '#pragma omp distribute' directive.
This represents implicit clause 'depend' for the '#pragma omp task' directive.
static TypeEvaluationKind getEvaluationKind(QualType T)
getEvaluationKind - Return the TypeEvaluationKind of QualType T.
unsigned NumberOfTargetItems
const Stmt * getAssociatedStmt() const
Returns statement associated with the directive.
bool addPrivate(const VarDecl *LocalVD, const llvm::function_ref< Address()> PrivateGen)
Registers LocalVD variable as a private and apply PrivateGen function for it to generate correspondin...
bool hasCancel() const
Return true if current directive has inner cancel directive.
This represents 'proc_bind' clause in the '#pragma omp ...' directive.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
This represents one expression.
static void emitTargetParallelForRegion(CodeGenFunction &CGF, const OMPTargetParallelForDirective &S, PrePostActionTy &Action)
Emit only debug info necessary for generating line number tables (-gline-tables-only).
void EmitAutoVarInit(const AutoVarEmission &emission)
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited...
This represents 'simdlen' clause in the '#pragma omp ...' directive.
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top, if IgnoreCaptured is true.
llvm::Value * EmitComplexToScalarConversion(ComplexPairTy Src, QualType SrcTy, QualType DstTy, SourceLocation Loc)
Emit a conversion from the specified complex type to the specified destination type, where the destination type is an LLVM scalar type.
llvm::function_ref< void(CodeGenFunction &, SourceLocation, const unsigned, const bool)> CodeGenOrderedTy
std::pair< llvm::Value *, llvm::Value * > getComplexVal() const
getComplexVal - Return the real/imag components of this complex value.
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
void EmitOMPTeamsDirective(const OMPTeamsDirective &S)
const T * castAs() const
Member-template castAs<specific type>.
llvm::BasicBlock * getBlock() const
static void emitTargetTeamsDistributeParallelForRegion(CodeGenFunction &CGF, const OMPTargetTeamsDistributeParallelForDirective &S, PrePostActionTy &Action)
bool hasCancel() const
Return true if current directive has inner cancel directive.
static std::pair< llvm::Value *, llvm::Value * > emitDispatchForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S, Address LB, Address UB)
When dealing with dispatch schedules (e.g.
This represents '#pragma omp target teams distribute parallel for simd' combined directive.
static void emitPreCond(CodeGenFunction &CGF, const OMPLoopDirective &S, const Expr *Cond, llvm::BasicBlock *TrueBlock, llvm::BasicBlock *FalseBlock, uint64_t TrueCount)
OpenMPClauseKind
OpenMP clauses.
llvm::PointerType * getType() const
Return the type of the pointer value.
static llvm::iterator_range< specific_clause_iterator< SpecificClause > > getClausesOfKind(ArrayRef< OMPClause *> Clauses)
This represents '#pragma omp target teams distribute simd' combined directive.
void EmitOMPSimdInit(const OMPLoopDirective &D, bool IsMonotonic=false)
Helpers for the OpenMP loop directives.
This represents 'ordered' clause in the '#pragma omp ...' directive.
Expr * getDistInc() const
Expr * getNextLowerBound() const
Expr * getPrevEnsureUpperBound() const
This represents '#pragma omp for' directive.
static void emitTargetTeamsRegion(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsDirective &S)
SmallVector< const Expr *, 4 > FirstprivateVars
static CapturedDecl * Create(ASTContext &C, DeclContext *DC, unsigned NumParams)
void EmitOMPMasterDirective(const OMPMasterDirective &S)
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.
CharUnits alignmentOfArrayElement(CharUnits elementSize) const
Given that this is the alignment of the first element of an array, return the minimum alignment of an...
void setParallel(bool Enable=true)
Set the next pushed loop as parallel.
This represents '#pragma omp target teams' directive.
LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T)
SourceLocation getEnd() const
UnaryOperator - This represents the unary-expression's (except sizeof and alignof), the postinc/postdec operators from postfix-expression, and various extensions.
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
void EmitOMPBarrierDirective(const OMPBarrierDirective &S)
bool EmitOMPLinearClauseInit(const OMPLoopDirective &D)
Emit initial code for linear variables.
This represents '#pragma omp cancel' directive.
This represents clause 'firstprivate' in the '#pragma omp ...' directives.
const LangOptions & getLangOpts() const
ASTContext & getContext() const
static void emitCommonOMPTargetDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, const RegionCodeGenTy &CodeGen)
RValue EmitAtomicLoad(LValue LV, SourceLocation SL, AggValueSlot Slot=AggValueSlot::ignored())
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...
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
GlobalDecl - represents a global declaration.
void EmitSimpleOMPExecutableDirective(const OMPExecutableDirective &D)
Emit simple code for OpenMP directives in Simd-only mode.
This represents '#pragma omp flush' directive.
bool hasClausesOfKind() const
Returns true if the current directive has one or more clauses of a specific kind. ...
This represents '#pragma omp parallel for simd' directive.
This represents 'seq_cst' clause in the '#pragma omp atomic' directive.
This represents 'untied' clause in the '#pragma omp ...' directive.
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
static Address castValueFromUintptr(CodeGenFunction &CGF, SourceLocation Loc, QualType DstType, StringRef Name, LValue AddrLV, bool isReferenceType=false)
static void emitAlignedClause(CodeGenFunction &CGF, const OMPExecutableDirective &D)
The l-value was considered opaque, so the alignment was determined from a type.
llvm::function_ref< void(CodeGenFunction &, const OMPLoopDirective &, JumpDest)> CodeGenLoopTy
Expr * getLastIteration() const
const SpecificClause * getSingleClause() const
Gets a single clause of the specified kind associated with the current directive iff there is only on...
bool isPostfixUpdate() const
Return true if 'v' expression must be updated to original value of 'x', false if 'v' must be updated ...
This represents '#pragma omp target enter data' directive.
void EmitOMPFlushDirective(const OMPFlushDirective &S)
Expr * getStrideVariable() const
This represents 'num_teams' clause in the '#pragma omp ...' directive.
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class...
Expr * getCombinedDistCond() const
const Stmt * getPreInits() const
This captures a statement into a function.
static void emitTargetParallelRegion(CodeGenFunction &CGF, const OMPTargetParallelDirective &S, PrePostActionTy &Action)
static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S, PrePostActionTy &Action)
This represents '#pragma omp single' directive.
Encodes a location in the source.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
This represents 'hint' clause in the '#pragma omp ...' directive.
void EmitOMPForDirective(const OMPForDirective &S)
QualType getUIntPtrType() const
Return a type compatible with "uintptr_t" (C99 7.18.1.4), as defined by the target.
unsigned getOpenMPDefaultSimdAlign(QualType T) const
Get default simd alignment of the specified complete type in bits.
Pseudo declaration for capturing expressions.
llvm::PointerIntPair< llvm::Value *, 1, bool > Final
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
static void emitInnerParallelForWhenCombined(CodeGenFunction &CGF, const OMPLoopDirective &S, CodeGenFunction::JumpDest LoopExit)
static void emitTargetParallelForSimdRegion(CodeGenFunction &CGF, const OMPTargetParallelForSimdDirective &S, PrePostActionTy &Action)
This is a basic class for representing single OpenMP executable directive.
This represents 'schedule' clause in the '#pragma omp ...' directive.
Expr * getExpr()
Get 'expr' part of the associated expression/statement.
OpenMPDirectiveKind
OpenMP directives.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
DeclarationNameInfo getDirectiveName() const
Return name of the directive.
void EmitStmt(const Stmt *S, ArrayRef< const Attr *> Attrs=None)
EmitStmt - Emit the code for the statement.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
C-style initialization with assignment.
This represents '#pragma omp taskwait' directive.
void EmitOMPTaskgroupDirective(const OMPTaskgroupDirective &S)
This file defines OpenMP nodes for declarative directives.
void EmitOMPTargetParallelForSimdDirective(const OMPTargetParallelForSimdDirective &S)
static void EmitOMPTargetSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S)
Emit device code for the target simd directive.
This is a basic class for representing single OpenMP clause.
void EmitOMPTeamsDistributeSimdDirective(const OMPTeamsDistributeSimdDirective &S)
bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of the composite or combined directives that need loop ...
void emitAggregateType(CodeGenFunction &CGF, unsigned N)
Emits the code for the variable-modified type, if required.
static void EmitOMPTargetTeamsDistributeParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForDirective &S)
bool isAnyPointerType() const
virtual void Enter(CodeGenFunction &CGF)
void EmitOMPSingleDirective(const OMPSingleDirective &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.
Stmt * getCapturedStmt()
Retrieve the statement being captured.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language...
This represents '#pragma omp target' directive.
void EmitOMPForSimdDirective(const OMPForSimdDirective &S)
Expr * getV()
Get 'v' part of the associated expression/statement.
constexpr XRayInstrMask None
void EmitOMPAtomicDirective(const OMPAtomicDirective &S)
void EmitOMPSectionDirective(const OMPSectionDirective &S)
void EmitOMPSectionsDirective(const OMPSectionsDirective &S)
This represents '#pragma omp ordered' directive.
This represents '#pragma omp target update' directive.
void EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S)
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
static void EmitOMPTargetTeamsDistributeDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeDirective &S)
Emit device code for the target teams distribute directive.
JumpDest getOMPCancelDestination(OpenMPDirectiveKind Kind)
llvm::Value * EmitScalarExpr(const Expr *E, bool IgnoreResultAssign=false)
EmitScalarExpr - Emit the computation of the specified expression of LLVM scalar type, returning the result.
FunctionArgList - Type for representing both the decl and type of parameters to a function...
llvm::Value * getScalarVal() const
getScalarVal() - Return the Value* of this scalar value.
void setAction(PrePostActionTy &Action) const
CGFunctionInfo - Class to encapsulate the information about a function definition.
This class organizes the cross-function state that is used while generating LLVM code.
CGOpenMPRuntime & getOpenMPRuntime()
Return a reference to the configured OpenMP runtime.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
LValue EmitOMPSharedLValue(const Expr *E)
Emits the lvalue for the expression with possibly captured variable.
void EmitOMPTargetTeamsDirective(const OMPTargetTeamsDirective &S)
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
Dataflow Directional Tag Classes.
std::string getAsString() const
getAsString - Retrieve the human-readable string for this name.
Expr * getPrevUpperBoundVariable() const
Class provides a way to call simple version of codegen for OpenMP region, or an advanced with possibl...
This represents 'device' clause in the '#pragma omp ...' directive.
static void emitEmptyBoundParameters(CodeGenFunction &, const OMPExecutableDirective &, llvm::SmallVectorImpl< llvm::Value *> &)
void EmitOMPTaskyieldDirective(const OMPTaskyieldDirective &S)
static RValue getComplex(llvm::Value *V1, llvm::Value *V2)
EvalResult is a struct with detailed info about an evaluated expression.
void EmitOMPTargetParallelDirective(const OMPTargetParallelDirective &S)
static AggValueSlot ignored()
ignored - Returns an aggregate value slot indicating that the aggregate value is being ignored...
void EmitOMPParallelForDirective(const OMPParallelForDirective &S)
This represents '#pragma omp section' directive.
std::vector< llvm::Triple > OMPTargetTriples
Triples of the OpenMP targets that the host code codegen should take into account in order to generat...
OpenMPScheduleClauseModifier M1
This represents '#pragma omp teams distribute' directive.
A basic class for pre|post-action for advanced codegen sequence for OpenMP region.
static void emitOMPLoopBodyWithStopPoint(CodeGenFunction &CGF, const OMPLoopDirective &S, CodeGenFunction::JumpDest LoopExit)
void EmitOMPPrivateClause(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
LValue getSharedLValue(unsigned N) const
Returns LValue for the reduction item.
void EmitOMPTargetParallelForDirective(const OMPTargetParallelForDirective &S)
const Expr * getInit() const
This represents '#pragma omp simd' directive.
llvm::LoadInst * CreateLoad(Address Addr, const llvm::Twine &Name="")
static void emitCommonOMPTeamsDirective(CodeGenFunction &CGF, const OMPExecutableDirective &S, OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen)
The name of a declaration.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
const Expr * getReductionRef() const
Returns reference to the task_reduction return variable.
llvm::PointerIntPair< llvm::Value *, 1, bool > Priority
static RValue convertToType(CodeGenFunction &CGF, RValue Value, QualType SourceType, QualType ResType, SourceLocation Loc)
void EmitOMPLinearClause(const OMPLoopDirective &D, CodeGenFunction::OMPPrivateScope &PrivateScope)
Emit initial code for linear clauses.
void EmitOMPTeamsDistributeParallelForDirective(const OMPTeamsDistributeParallelForDirective &S)
SourceLocation getEndLoc() const LLVM_READONLY
This represents clause 'linear' in the '#pragma omp ...' directives.
bool EmitOMPFirstprivateClause(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
void EmitOMPCancelDirective(const OMPCancelDirective &S)
Expr * getUpdateExpr()
Get helper expression of the form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or 'OpaqueValueExp...
SourceLocation getBeginLoc() const LLVM_READONLY
llvm::Module & getModule() const
This represents '#pragma omp atomic' directive.
LValue MakeAddrLValue(Address Addr, QualType T, AlignmentSource Source=AlignmentSource::Type)
Expr * getCombinedInit() const
unsigned getCollapsedNumber() const
Get number of collapsed loops.
Expr * getCombinedNextLowerBound() const
ArrayRef< Expr * > counters()
static void emitTargetTeamsDistributeSimdRegion(CodeGenFunction &CGF, PrePostActionTy &Action, const OMPTargetTeamsDistributeSimdDirective &S)
void emitInitialization(CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, llvm::function_ref< bool(CodeGenFunction &)> DefaultInit)
Performs initialization of the private copy for the reduction item.
void EmitOMPReductionClauseFinal(const OMPExecutableDirective &D, const OpenMPDirectiveKind ReductionKind)
Emit final update of reduction values to original variables at the end of the directive.
SwitchStmt - This represents a 'switch' stmt.
Expr * getCombinedNextUpperBound() const
void EmitAutoVarCleanups(const AutoVarEmission &emission)
API for captured statement code generation.
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
Complex values, per C99 6.2.5p11.
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
static void emitSimpleAtomicStore(CodeGenFunction &CGF, bool IsSeqCst, LValue LVal, RValue RVal)
This file defines OpenMP AST classes for executable directives and clauses.
ArrayRef< Expr * > inits()
static void EmitOMPTargetTeamsDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDirective &S)
Emit device code for the target teams directive.
llvm::Type * getElementType() const
Return the type of the values stored in this address.
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
Expr * getNumIterations() const
Base for LValueReferenceType and RValueReferenceType.
void SetInternalFunctionAttributes(GlobalDecl GD, llvm::Function *F, const CGFunctionInfo &FI)
Set the attributes on the LLVM function for the given decl and function info.
StringRef getMangledName(GlobalDecl GD)
Address BasePointersArray
Internal linkage, which indicates that the entity can be referred to from within the translation unit...
bool setVarAddr(CodeGenFunction &CGF, const VarDecl *LocalVD, Address TempAddr)
Sets the address of the variable LocalVD to be TempAddr in function CGF.
void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false)
EmitBlock - Emit the given block.
void EmitOMPTargetEnterDataDirective(const OMPTargetEnterDataDirective &S)
bool hasAssociatedStmt() const
Returns true if directive has associated statement.
Expr * getPrevLowerBoundVariable() const
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
void EmitOMPDistributeSimdDirective(const OMPDistributeSimdDirective &S)
const Decl * CurFuncDecl
CurFuncDecl - Holds the Decl for the current outermost non-closure context.
void EmitStopPoint(const Stmt *S)
EmitStopPoint - Emit a debug stoppoint if we are emitting debug info.
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
bool isLValueReferenceType() const
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
TranslationUnitDecl * getTranslationUnitDecl() const
void EmitOMPReductionClauseInit(const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope)
Emit initial code for reduction variables.
This represents '#pragma omp target parallel' directive.
void EmitOMPTargetTeamsDistributeDirective(const OMPTargetTeamsDistributeDirective &S)
static QualType getCanonicalParamType(ASTContext &C, QualType T)
This represents 'nowait' clause in the '#pragma omp ...' directive.
llvm::PointerIntPair< llvm::Value *, 1, bool > Schedule
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g., it is an signed integer type or a vector.
void EmitBranch(llvm::BasicBlock *Block)
EmitBranch - Emit a branch to the specified basic block from the current insert block, taking care to avoid creation of branches from dummy blocks.
This represents 'num_tasks' clause in the '#pragma omp ...' directive.
Privates[]
Gets the list of initial values for linear variables.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Expr * getCombinedCond() const
void EmitOMPLinearClauseFinal(const OMPLoopDirective &D, const llvm::function_ref< llvm::Value *(CodeGenFunction &)> CondGen)
Emit final code for linear clauses.
void EmitOMPUseDevicePtrClause(const OMPClause &C, OMPPrivateScope &PrivateScope, const llvm::DenseMap< const ValueDecl *, Address > &CaptureDeviceAddrMap)
LValue EmitLValue(const Expr *E)
EmitLValue - Emit code to compute a designator that specifies the location of the expression...
static void emitTargetTeamsDistributeParallelForSimdRegion(CodeGenFunction &CGF, const OMPTargetTeamsDistributeParallelForSimdDirective &S, PrePostActionTy &Action)
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
RValue EmitLoadOfLValue(LValue V, SourceLocation Loc)
EmitLoadOfLValue - Given an expression that represents a value lvalue, this method emits the address ...
This represents '#pragma omp taskloop simd' directive.
bool EmitOMPCopyinClause(const OMPExecutableDirective &D)
Emit code for copyin clause in D directive.
Expr * getPreCond() const
This represents 'dist_schedule' clause in the '#pragma omp ...' directive.
CGCapturedStmtInfo * CapturedStmtInfo
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...
const VariableArrayType * getAsVariableArrayType(QualType T) const
const llvm::function_ref< void(CodeGenFunction &, llvm::Value *, const OMPTaskDataTy &)> TaskGenTy
This represents '#pragma omp sections' directive.
This represents '#pragma omp target data' directive.
void EmitOMPTargetExitDataDirective(const OMPTargetExitDataDirective &S)
OpenMPDirectiveKind getCancelRegion() const
Get cancellation region for the current cancellation point.
A reference to a declared variable, function, enum, etc.
static RValue get(llvm::Value *V)
bool isPointerType() const
static void EmitOMPTargetDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetDirective &S)
Emit device code for the target directive.
void EmitOMPTargetDataDirective(const OMPTargetDataDirective &S)
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
static void EmitOMPTargetParallelForDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetParallelForDirective &S)
Emit device code for the target parallel for directive.
void EmitOMPDistributeParallelForDirective(const OMPDistributeParallelForDirective &S)
void EmitAlignmentAssumption(llvm::Value *PtrValue, QualType Ty, SourceLocation Loc, SourceLocation AssumptionLoc, llvm::Value *Alignment, llvm::Value *OffsetValue=nullptr)
An l-value expression is a reference to an object with independent storage.
A trivial tuple used to represent a source range.
LValue - This represents an lvalue references.
This represents '#pragma omp taskyield' directive.
This represents '#pragma omp distribute parallel for simd' composite directive.
Represents a C array with a specified size that is not an integer-constant-expression.
This represents '#pragma omp parallel sections' directive.
bool apply(CodeGenFunction &CGF)
Applies new addresses to the list of the variables.
SourceLocation getBegin() const
capture_init_iterator capture_init_end()
Retrieve the iterator pointing one past the last initialization argument.
llvm::Value * getPointer() const
void EmitOMPTaskDirective(const OMPTaskDirective &S)
SourceLocation getBodyRBrace() const
getBodyRBrace - Gets the right brace of the body, if a body exists.
This represents '#pragma omp target parallel for' directive.
SmallVector< const Expr *, 4 > FirstprivateInits
SourceLocation getLocation() const
This represents clause 'use_device_ptr' in the '#pragma omp ...' directives.
static void EmitOMPTargetTeamsDistributeSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeSimdDirective &S)
Emit device code for the target teams distribute simd directive.
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth, signed/unsigned.
void EmitOMPTargetTeamsDistributeParallelForDirective(const OMPTargetTeamsDistributeParallelForDirective &S)
static OMPLinearClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr *> VL, ArrayRef< Expr *> PL, ArrayRef< Expr *> IL, Expr *Step, Expr *CalcStep, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL and a linear step Step.
bool Privatize()
Privatizes local variables previously registered as private.
static void EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(CodeGenModule &CGM, StringRef ParentName, const OMPTargetTeamsDistributeParallelForSimdDirective &S)
Emit device code for the target teams distribute parallel for simd directive.
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
This represents '#pragma omp taskloop' directive.