63#define DEBUG_TYPE "openmp-ir-builder"
70 cl::desc(
"Use optimistic attributes describing "
71 "'as-if' properties of runtime calls."),
75 "openmp-ir-builder-unroll-threshold-factor",
cl::Hidden,
76 cl::desc(
"Factor for the unroll threshold to account for code "
77 "simplifications still taking place"),
88 if (!IP1.isSet() || !IP2.isSet())
90 return IP1.getBlock() == IP2.getBlock() && IP1.getPoint() == IP2.getPoint();
95 switch (SchedType & ~OMPScheduleType::MonotonicityMask) {
96 case OMPScheduleType::UnorderedStaticChunked:
97 case OMPScheduleType::UnorderedStatic:
98 case OMPScheduleType::UnorderedDynamicChunked:
99 case OMPScheduleType::UnorderedGuidedChunked:
100 case OMPScheduleType::UnorderedRuntime:
101 case OMPScheduleType::UnorderedAuto:
102 case OMPScheduleType::UnorderedTrapezoidal:
103 case OMPScheduleType::UnorderedGreedy:
104 case OMPScheduleType::UnorderedBalanced:
105 case OMPScheduleType::UnorderedGuidedIterativeChunked:
106 case OMPScheduleType::UnorderedGuidedAnalyticalChunked:
107 case OMPScheduleType::UnorderedSteal:
108 case OMPScheduleType::UnorderedStaticBalancedChunked:
109 case OMPScheduleType::UnorderedGuidedSimd:
110 case OMPScheduleType::UnorderedRuntimeSimd:
111 case OMPScheduleType::OrderedStaticChunked:
112 case OMPScheduleType::OrderedStatic:
113 case OMPScheduleType::OrderedDynamicChunked:
114 case OMPScheduleType::OrderedGuidedChunked:
115 case OMPScheduleType::OrderedRuntime:
116 case OMPScheduleType::OrderedAuto:
117 case OMPScheduleType::OrderdTrapezoidal:
118 case OMPScheduleType::NomergeUnorderedStaticChunked:
119 case OMPScheduleType::NomergeUnorderedStatic:
120 case OMPScheduleType::NomergeUnorderedDynamicChunked:
121 case OMPScheduleType::NomergeUnorderedGuidedChunked:
122 case OMPScheduleType::NomergeUnorderedRuntime:
123 case OMPScheduleType::NomergeUnorderedAuto:
124 case OMPScheduleType::NomergeUnorderedTrapezoidal:
125 case OMPScheduleType::NomergeUnorderedGreedy:
126 case OMPScheduleType::NomergeUnorderedBalanced:
127 case OMPScheduleType::NomergeUnorderedGuidedIterativeChunked:
128 case OMPScheduleType::NomergeUnorderedGuidedAnalyticalChunked:
129 case OMPScheduleType::NomergeUnorderedSteal:
130 case OMPScheduleType::NomergeOrderedStaticChunked:
131 case OMPScheduleType::NomergeOrderedStatic:
132 case OMPScheduleType::NomergeOrderedDynamicChunked:
133 case OMPScheduleType::NomergeOrderedGuidedChunked:
134 case OMPScheduleType::NomergeOrderedRuntime:
135 case OMPScheduleType::NomergeOrderedAuto:
136 case OMPScheduleType::NomergeOrderedTrapezoidal:
144 SchedType & OMPScheduleType::MonotonicityMask;
145 if (MonotonicityFlags == OMPScheduleType::MonotonicityMask)
156 if (Features.
count(
"+wavefrontsize64"))
157 return omp::getAMDGPUGridValues<64>();
158 return omp::getAMDGPUGridValues<32>();
169 bool HasSimdModifier) {
171 switch (ClauseKind) {
172 case OMP_SCHEDULE_Default:
173 case OMP_SCHEDULE_Static:
174 return HasChunks ? OMPScheduleType::BaseStaticChunked
175 : OMPScheduleType::BaseStatic;
176 case OMP_SCHEDULE_Dynamic:
177 return OMPScheduleType::BaseDynamicChunked;
178 case OMP_SCHEDULE_Guided:
179 return HasSimdModifier ? OMPScheduleType::BaseGuidedSimd
180 : OMPScheduleType::BaseGuidedChunked;
181 case OMP_SCHEDULE_Auto:
183 case OMP_SCHEDULE_Runtime:
184 return HasSimdModifier ? OMPScheduleType::BaseRuntimeSimd
185 : OMPScheduleType::BaseRuntime;
193 bool HasOrderedClause) {
194 assert((BaseScheduleType & OMPScheduleType::ModifierMask) ==
195 OMPScheduleType::None &&
196 "Must not have ordering nor monotonicity flags already set");
199 ? OMPScheduleType::ModifierOrdered
200 : OMPScheduleType::ModifierUnordered;
201 OMPScheduleType OrderingScheduleType = BaseScheduleType | OrderingModifier;
204 if (OrderingScheduleType ==
205 (OMPScheduleType::BaseGuidedSimd | OMPScheduleType::ModifierOrdered))
206 return OMPScheduleType::OrderedGuidedChunked;
207 else if (OrderingScheduleType == (OMPScheduleType::BaseRuntimeSimd |
208 OMPScheduleType::ModifierOrdered))
209 return OMPScheduleType::OrderedRuntime;
211 return OrderingScheduleType;
217 bool HasSimdModifier,
bool HasMonotonic,
218 bool HasNonmonotonic,
bool HasOrderedClause) {
219 assert((ScheduleType & OMPScheduleType::MonotonicityMask) ==
220 OMPScheduleType::None &&
221 "Must not have monotonicity flags already set");
222 assert((!HasMonotonic || !HasNonmonotonic) &&
223 "Monotonic and Nonmonotonic are contradicting each other");
226 return ScheduleType | OMPScheduleType::ModifierMonotonic;
227 }
else if (HasNonmonotonic) {
228 return ScheduleType | OMPScheduleType::ModifierNonmonotonic;
238 if ((BaseScheduleType == OMPScheduleType::BaseStatic) ||
239 (BaseScheduleType == OMPScheduleType::BaseStaticChunked) ||
245 return ScheduleType | OMPScheduleType::ModifierNonmonotonic;
253 bool HasSimdModifier,
bool HasMonotonicModifier,
254 bool HasNonmonotonicModifier,
bool HasOrderedClause) {
260 OrderedSchedule, HasSimdModifier, HasMonotonicModifier,
261 HasNonmonotonicModifier, HasOrderedClause);
275 auto *Br = cast<BranchInst>(Term);
276 assert(!Br->isConditional() &&
277 "BB's terminator must be an unconditional branch (or degenerate)");
280 Br->setSuccessor(0,
Target);
285 NewBr->setDebugLoc(
DL);
290 assert(New->getFirstInsertionPt() == New->begin() &&
291 "Target BB must not have PHI nodes");
295 New->splice(New->begin(), Old, IP.
getPoint(), Old->
end());
323 New->replaceSuccessorsPhiUsesWith(Old, New);
368 const Twine &
Name =
"",
bool AsPtr =
true) {
376 FakeVal = FakeValAddr;
404enum OpenMPOffloadingRequiresDirFlags {
406 OMP_REQ_UNDEFINED = 0x000,
408 OMP_REQ_NONE = 0x001,
410 OMP_REQ_REVERSE_OFFLOAD = 0x002,
412 OMP_REQ_UNIFIED_ADDRESS = 0x004,
414 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008,
416 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010,
423 : RequiresFlags(OMP_REQ_UNDEFINED) {}
426 bool IsTargetDevice,
bool IsGPU,
bool OpenMPOffloadMandatory,
427 bool HasRequiresReverseOffload,
bool HasRequiresUnifiedAddress,
428 bool HasRequiresUnifiedSharedMemory,
bool HasRequiresDynamicAllocators)
429 : IsTargetDevice(IsTargetDevice), IsGPU(IsGPU),
430 OpenMPOffloadMandatory(OpenMPOffloadMandatory),
431 RequiresFlags(OMP_REQ_UNDEFINED) {
432 if (HasRequiresReverseOffload)
433 RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
434 if (HasRequiresUnifiedAddress)
435 RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
436 if (HasRequiresUnifiedSharedMemory)
437 RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
438 if (HasRequiresDynamicAllocators)
439 RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
443 return RequiresFlags & OMP_REQ_REVERSE_OFFLOAD;
447 return RequiresFlags & OMP_REQ_UNIFIED_ADDRESS;
451 return RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY;
455 return RequiresFlags & OMP_REQ_DYNAMIC_ALLOCATORS;
460 :
static_cast<int64_t
>(OMP_REQ_NONE);
465 RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
467 RequiresFlags &= ~OMP_REQ_REVERSE_OFFLOAD;
472 RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
474 RequiresFlags &= ~OMP_REQ_UNIFIED_ADDRESS;
479 RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
481 RequiresFlags &= ~OMP_REQ_UNIFIED_SHARED_MEMORY;
486 RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
488 RequiresFlags &= ~OMP_REQ_DYNAMIC_ALLOCATORS;
501 constexpr const size_t MaxDim = 3;
509 Value *NumThreads3D =
512 seq<unsigned>(1, std::min(KernelArgs.
NumTeams.size(), MaxDim)))
516 seq<unsigned>(1, std::min(KernelArgs.
NumThreads.size(), MaxDim)))
540 auto FnAttrs = Attrs.getFnAttrs();
541 auto RetAttrs = Attrs.getRetAttrs();
543 for (
size_t ArgNo = 0; ArgNo < Fn.
arg_size(); ++ArgNo)
548 bool Param =
true) ->
void {
549 bool HasSignExt = AS.hasAttribute(Attribute::SExt);
550 bool HasZeroExt = AS.hasAttribute(Attribute::ZExt);
551 if (HasSignExt || HasZeroExt) {
552 assert(AS.getNumAttributes() == 1 &&
553 "Currently not handling extension attr combined with others.");
555 if (
auto AK = TargetLibraryInfo::getExtAttrForI32Param(
T, HasSignExt))
558 TargetLibraryInfo::getExtAttrForI32Return(
T, HasSignExt))
565#define OMP_ATTRS_SET(VarName, AttrSet) AttributeSet VarName = AttrSet;
566#include "llvm/Frontend/OpenMP/OMPKinds.def"
570#define OMP_RTL_ATTRS(Enum, FnAttrSet, RetAttrSet, ArgAttrSets) \
572 FnAttrs = FnAttrs.addAttributes(Ctx, FnAttrSet); \
573 addAttrSet(RetAttrs, RetAttrSet, false); \
574 for (size_t ArgNo = 0; ArgNo < ArgAttrSets.size(); ++ArgNo) \
575 addAttrSet(ArgAttrs[ArgNo], ArgAttrSets[ArgNo]); \
576 Fn.setAttributes(AttributeList::get(Ctx, FnAttrs, RetAttrs, ArgAttrs)); \
578#include "llvm/Frontend/OpenMP/OMPKinds.def"
592#define OMP_RTL(Enum, Str, IsVarArg, ReturnType, ...) \
594 FnTy = FunctionType::get(ReturnType, ArrayRef<Type *>{__VA_ARGS__}, \
596 Fn = M.getFunction(Str); \
598#include "llvm/Frontend/OpenMP/OMPKinds.def"
604#define OMP_RTL(Enum, Str, ...) \
606 Fn = Function::Create(FnTy, GlobalValue::ExternalLinkage, Str, M); \
608#include "llvm/Frontend/OpenMP/OMPKinds.def"
612 if (FnID == OMPRTL___kmpc_fork_call || FnID == OMPRTL___kmpc_fork_teams) {
622 LLVMContext::MD_callback,
624 2, {-1, -1},
true)}));
637 assert(Fn &&
"Failed to create OpenMP runtime function");
644 auto *Fn = dyn_cast<llvm::Function>(RTLFn.
getCallee());
645 assert(Fn &&
"Failed to create OpenMP runtime function pointer");
660 for (
auto Inst =
Block->getReverseIterator()->begin();
661 Inst !=
Block->getReverseIterator()->end();) {
662 if (
auto *
AllocaInst = dyn_cast_if_present<llvm::AllocaInst>(Inst)) {
686 ParallelRegionBlockSet.
clear();
688 OI.collectBlocks(ParallelRegionBlockSet,
Blocks);
707 ".omp_par", ArgsInZeroAddressSpace);
711 <<
" Exit: " << OI.ExitBB->getName() <<
"\n");
713 "Expected OpenMP outlining to be possible!");
715 for (
auto *V : OI.ExcludeArgsFromAggregate)
722 if (TargetCpuAttr.isStringAttribute())
725 auto TargetFeaturesAttr = OuterFn->
getFnAttribute(
"target-features");
726 if (TargetFeaturesAttr.isStringAttribute())
727 OutlinedFn->
addFnAttr(TargetFeaturesAttr);
730 LLVM_DEBUG(
dbgs() <<
" Outlined function: " << *OutlinedFn <<
"\n");
732 "OpenMP outlined functions should not return a value!");
744 assert(OI.EntryBB->getUniquePredecessor() == &ArtificialEntry);
751 "Expected instructions to add in the outlined region entry");
758 if (
I.isTerminator())
761 I.moveBeforePreserving(*OI.EntryBB, OI.EntryBB->getFirstInsertionPt());
764 OI.EntryBB->moveBefore(&ArtificialEntry);
771 if (OI.PostOutlineCB)
772 OI.PostOutlineCB(*OutlinedFn);
803 errs() <<
"Error of kind: " << Kind
804 <<
" when emitting offload entries and metadata during "
805 "OMPIRBuilder finalization \n";
812 std::vector<WeakTrackingVH> LLVMCompilerUsed = {
814 emitUsed(
"llvm.compiler.used", LLVMCompilerUsed);
840 for (
unsigned I = 0, E =
List.size();
I != E; ++
I)
844 if (UsedArray.
empty())
851 GV->setSection(
"llvm.metadata");
860 ConstantInt::get(Int8Ty, Mode),
Twine(KernelName,
"_exec_mode"));
868 unsigned Reserve2Flags) {
870 LocFlags |= OMP_IDENT_FLAG_KMPC;
878 ConstantInt::get(
Int32, Reserve2Flags),
879 ConstantInt::get(
Int32, SrcLocStrSize), SrcLocStr};
886 if (
GV.getValueType() == OpenMPIRBuilder::Ident &&
GV.hasInitializer())
887 if (
GV.getInitializer() == Initializer)
892 M, OpenMPIRBuilder::Ident,
907 SrcLocStrSize = LocStr.
size();
916 if (
GV.isConstant() &&
GV.hasInitializer() &&
917 GV.getInitializer() == Initializer)
928 unsigned Line,
unsigned Column,
934 Buffer.
append(FunctionName);
936 Buffer.
append(std::to_string(Line));
938 Buffer.
append(std::to_string(Column));
946 StringRef UnknownLoc =
";unknown;unknown;0;0;;";
957 if (
DIFile *DIF = DIL->getFile())
958 if (std::optional<StringRef> Source = DIF->getSource())
964 DIL->getColumn(), SrcLocStrSize);
976 "omp_global_thread_num");
981 bool ForceSimpleCall,
bool CheckCancelFlag) {
991 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_FOR;
994 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SECTIONS;
997 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SINGLE;
1000 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_EXPL;
1003 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL;
1016 bool UseCancelBarrier =
1021 UseCancelBarrier ? OMPRTL___kmpc_cancel_barrier
1022 : OMPRTL___kmpc_barrier),
1025 if (UseCancelBarrier && CheckCancelFlag)
1035 omp::Directive CanceledDirective) {
1047 Value *CancelKind =
nullptr;
1048 switch (CanceledDirective) {
1049#define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) \
1050 case DirectiveEnum: \
1051 CancelKind = Builder.getInt32(Value); \
1053#include "llvm/Frontend/OpenMP/OMPKinds.def"
1065 if (CanceledDirective == OMPD_parallel) {
1069 omp::Directive::OMPD_unknown,
1083 UI->eraseFromParent();
1096 auto *KernelArgsPtr =
1109 NumThreads, HostPtr, KernelArgsPtr};
1137 assert(OutlinedFnID &&
"Invalid outlined function ID!");
1141 Value *Return =
nullptr;
1161 Builder, AllocaIP, Return, RTLoc, DeviceID, Args.NumTeams.front(),
1162 Args.NumThreads.front(), OutlinedFnID, ArgsVector));
1178 emitBlock(OffloadContBlock, CurFn,
true);
1183 Value *CancelFlag, omp::Directive CanceledDirective,
1186 "Unexpected cancellation!");
1239 OutlinedFn.
addFnAttr(Attribute::NoUnwind);
1242 "Expected at least tid and bounded tid as arguments");
1243 unsigned NumCapturedVars = OutlinedFn.
arg_size() - 2;
1246 assert(CI &&
"Expected call instruction to outlined function");
1247 CI->
getParent()->setName(
"omp_parallel");
1250 Type *PtrTy = OMPIRBuilder->VoidPtr;
1254 OpenMPIRBuilder ::InsertPointTy CurrentIP = Builder.
saveIP();
1258 Value *Args = ArgsAlloca;
1266 for (
unsigned Idx = 0;
Idx < NumCapturedVars;
Idx++) {
1278 Value *Parallel51CallArgs[] = {
1282 NumThreads ? NumThreads : Builder.
getInt32(-1),
1285 Builder.
CreateBitCast(&OutlinedFn, OMPIRBuilder->ParallelTaskPtr),
1288 Builder.
getInt64(NumCapturedVars)};
1293 Builder.
CreateCall(RTLFn, Parallel51CallArgs);
1308 I->eraseFromParent();
1330 if (
auto *
F = dyn_cast<Function>(RTLFn.
getCallee())) {
1331 if (!
F->hasMetadata(LLVMContext::MD_callback)) {
1339 F->addMetadata(LLVMContext::MD_callback,
1348 OutlinedFn.
addFnAttr(Attribute::NoUnwind);
1351 "Expected at least tid and bounded tid as arguments");
1352 unsigned NumCapturedVars = OutlinedFn.
arg_size() - 2;
1355 CI->
getParent()->setName(
"omp_parallel");
1359 Value *ForkCallArgs[] = {
1360 Ident, Builder.
getInt32(NumCapturedVars),
1361 Builder.
CreateBitCast(&OutlinedFn, OMPIRBuilder->ParallelTaskPtr)};
1364 RealArgs.
append(std::begin(ForkCallArgs), std::end(ForkCallArgs));
1373 auto PtrTy = OMPIRBuilder->VoidPtr;
1374 if (IfCondition && NumCapturedVars == 0) {
1378 if (IfCondition && RealArgs.
back()->getType() != PtrTy)
1396 I->eraseFromParent();
1404 omp::ProcBindKind ProcBind,
bool IsCancellable) {
1431 if (ProcBind != OMP_PROC_BIND_default) {
1435 ConstantInt::get(
Int32,
unsigned(ProcBind),
true)};
1463 TIDAddrAlloca, PointerType ::get(
M.
getContext(), 0),
"tid.addr.ascast");
1468 "zero.addr.ascast");
1492 if (IP.getBlock()->end() == IP.getPoint()) {
1498 assert(IP.getBlock()->getTerminator()->getNumSuccessors() == 1 &&
1499 IP.getBlock()->getTerminator()->getSuccessor(0) == PRegExitBB &&
1500 "Unexpected insertion point for finalization call!");
1536 LLVM_DEBUG(
dbgs() <<
"Before body codegen: " << *OuterFn <<
"\n");
1539 assert(BodyGenCB &&
"Expected body generation callback!");
1541 if (
Error Err = BodyGenCB(InnerAllocaIP, CodeGenIP))
1544 LLVM_DEBUG(
dbgs() <<
"After body codegen: " << *OuterFn <<
"\n");
1550 std::move(ToBeDeleted)](
Function &OutlinedFn) {
1552 IfCondition, NumThreads, PrivTID, PrivTIDAddr,
1553 ThreadID, ToBeDeletedVec);
1558 std::move(ToBeDeleted)](
Function &OutlinedFn) {
1560 PrivTID, PrivTIDAddr, ToBeDeletedVec);
1577 PRegOutlinedExitBB->
setName(
"omp.par.outlined.exit");
1578 Blocks.push_back(PRegOutlinedExitBB);
1589 ".omp_par", ArgsInZeroAddressSpace);
1594 Extractor.
findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
1600 if (
auto *
GV = dyn_cast_if_present<GlobalVariable>(
I))
1601 return GV->getValueType() == OpenMPIRBuilder::Ident;
1606 LLVM_DEBUG(
dbgs() <<
"Before privatization: " << *OuterFn <<
"\n");
1612 if (&V == TIDAddr || &V == ZeroAddr) {
1618 for (
Use &U : V.uses())
1619 if (
auto *UserI = dyn_cast<Instruction>(U.getUser()))
1620 if (ParallelRegionBlockSet.
count(UserI->getParent()))
1630 if (!V.getType()->isPointerTy()) {
1649 Value *ReplacementValue =
nullptr;
1650 CallInst *CI = dyn_cast<CallInst>(&V);
1652 ReplacementValue = PrivTID;
1655 PrivCB(InnerAllocaIP,
Builder.
saveIP(), V, *Inner, ReplacementValue);
1663 assert(ReplacementValue &&
1664 "Expected copy/create callback to set replacement value!");
1665 if (ReplacementValue == &V)
1670 UPtr->set(ReplacementValue);
1689 for (
Value *Input : Inputs) {
1691 if (
Error Err = PrivHelper(*Input))
1695 for (
Value *Output : Outputs)
1699 "OpenMP outlining should not produce live-out values!");
1701 LLVM_DEBUG(
dbgs() <<
"After privatization: " << *OuterFn <<
"\n");
1704 dbgs() <<
" PBR: " << BB->getName() <<
"\n";
1712 assert(FiniInfo.DK == OMPD_parallel &&
1713 "Unexpected finalization stack state!");
1718 if (
Error Err = FiniCB(PreFiniIP))
1724 InsertPointTy AfterIP(UI->getParent(), UI->getParent()->end());
1725 UI->eraseFromParent();
1791 if (Dependencies.
empty())
1811 Type *DependInfo = OMPBuilder.DependInfo;
1814 Value *DepArray =
nullptr;
1820 DepArray = Builder.
CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
1822 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies)) {
1828 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr));
1833 DependInfo,
Base,
static_cast<unsigned int>(RTLDependInfoFields::Len));
1835 Builder.
getInt64(M.getDataLayout().getTypeStoreSize(Dep.DepValueType)),
1840 static_cast<unsigned int>(RTLDependInfoFields::Flags));
1843 static_cast<unsigned int>(Dep.DepKind)),
1886 if (
Error Err = BodyGenCB(TaskAllocaIP, TaskBodyIP))
1897 Builder, AllocaIP, ToBeDeleted, TaskAllocaIP,
"global.tid",
false));
1899 OI.
PostOutlineCB = [
this, Ident, Tied, Final, IfCondition, Dependencies,
1900 Mergeable, Priority, EventHandle, TaskAllocaBB,
1901 ToBeDeleted](
Function &OutlinedFn)
mutable {
1903 assert(OutlinedFn.getNumUses() == 1 &&
1904 "there must be a single user for the outlined function");
1905 CallInst *StaleCI = cast<CallInst>(OutlinedFn.user_back());
1909 bool HasShareds = StaleCI->
arg_size() > 1;
1957 assert(ArgStructAlloca &&
1958 "Unable to find the alloca instruction corresponding to arguments "
1959 "for extracted function");
1962 assert(ArgStructType &&
"Unable to find struct type corresponding to "
1963 "arguments for extracted function");
1971 TaskAllocFn, {Ident, ThreadID,
Flags,
1972 TaskSize, SharedsSize,
1980 OMPRTL___kmpc_task_allow_completion_event);
2008 Constant *Zero = ConstantInt::get(Int32Ty, 0);
2017 TaskStructType, TaskGEP, {Zero, ConstantInt::get(Int32Ty, 4)});
2021 PriorityData, {Zero, Zero});
2025 Value *DepArray =
nullptr;
2026 if (Dependencies.
size()) {
2041 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr));
2048 static_cast<unsigned int>(RTLDependInfoFields::Len));
2055 static_cast<unsigned int>(RTLDependInfoFields::Flags));
2058 static_cast<unsigned int>(Dep.DepKind)),
2089 Instruction *ThenTI = IfTerminator, *ElseTI =
nullptr;
2095 if (Dependencies.
size()) {
2119 if (Dependencies.
size()) {
2140 Shareds, [Shareds](
Use &U) {
return U.getUser() != Shareds; });
2144 I->eraseFromParent();
2193 if (IP.getBlock()->end() != IP.getPoint())
2204 auto *CaseBB = IP.getBlock()->getSinglePredecessor();
2205 auto *CondBB = CaseBB->getSinglePredecessor()->getSinglePredecessor();
2206 auto *ExitBB = CondBB->getTerminator()->getSuccessor(1);
2237 unsigned CaseNumber = 0;
2238 for (
auto SectionCB : SectionCBs) {
2256 Value *LB = ConstantInt::get(I32Ty, 0);
2257 Value *UB = ConstantInt::get(I32Ty, SectionCBs.
size());
2258 Value *ST = ConstantInt::get(I32Ty, 1);
2260 Loc, LoopBodyGenCB, LB, UB, ST,
true,
false, AllocaIP,
"section_loop");
2265 applyStaticWorkshareLoop(Loc.
DL, *
LoopInfo, AllocaIP, !IsNowait);
2272 assert(FiniInfo.DK == OMPD_sections &&
2273 "Unexpected finalization stack state!");
2280 AfterIP = {FiniBB, FiniBB->
begin()};
2294 if (IP.getBlock()->end() != IP.getPoint())
2313 Directive OMPD = Directive::OMPD_sections;
2316 return EmitOMPInlinedRegion(OMPD,
nullptr,
nullptr, BodyGenCB, FiniCBWrapper,
2327Value *OpenMPIRBuilder::getGPUThreadID() {
2330 OMPRTL___kmpc_get_hardware_thread_id_in_block),
2334Value *OpenMPIRBuilder::getGPUWarpSize() {
2339Value *OpenMPIRBuilder::getNVPTXWarpID() {
2344Value *OpenMPIRBuilder::getNVPTXLaneID() {
2346 assert(LaneIDBits < 32 &&
"Invalid LaneIDBits size in NVPTX device.");
2347 unsigned LaneIDMask = ~0
u >> (32u - LaneIDBits);
2352Value *OpenMPIRBuilder::castValueToType(InsertPointTy AllocaIP,
Value *
From,
2357 assert(FromSize > 0 &&
"From size must be greater than zero");
2358 assert(ToSize > 0 &&
"To size must be greater than zero");
2359 if (FromType == ToType)
2361 if (FromSize == ToSize)
2376Value *OpenMPIRBuilder::createRuntimeShuffleFunction(InsertPointTy AllocaIP,
2381 assert(
Size <= 8 &&
"Unsupported bitwidth in shuffle instruction");
2385 Value *ElemCast = castValueToType(AllocaIP, Element, CastTy);
2389 Size <= 4 ? RuntimeFunction::OMPRTL___kmpc_shuffle_int32
2390 : RuntimeFunction::OMPRTL___kmpc_shuffle_int64);
2391 Value *WarpSizeCast =
2393 Value *ShuffleCall =
2395 return castValueToType(AllocaIP, ShuffleCall, CastTy);
2398void OpenMPIRBuilder::shuffleAndStore(InsertPointTy AllocaIP,
Value *SrcAddr,
2414 Value *ElemPtr = DstAddr;
2416 for (
unsigned IntSize = 8; IntSize >= 1; IntSize /= 2) {
2428 if ((
Size / IntSize) > 1) {
2452 Value *Res = createRuntimeShuffleFunction(
2461 Value *LocalElemPtr =
2468 Value *Res = createRuntimeShuffleFunction(
2482void OpenMPIRBuilder::emitReductionListCopy(
2483 InsertPointTy AllocaIP, CopyAction Action,
Type *ReductionArrayTy,
2485 CopyOptionsTy CopyOptions) {
2488 Value *RemoteLaneOffset = CopyOptions.RemoteLaneOffset;
2492 for (
auto En :
enumerate(ReductionInfos)) {
2493 const ReductionInfo &RI = En.value();
2494 Value *SrcElementAddr =
nullptr;
2495 Value *DestElementAddr =
nullptr;
2496 Value *DestElementPtrAddr =
nullptr;
2498 bool ShuffleInElement =
false;
2501 bool UpdateDestListPtr =
false;
2505 ReductionArrayTy, SrcBase,
2506 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
2512 ReductionArrayTy, DestBase,
2513 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
2519 ".omp.reduction.element");
2522 DestElementAddr = DestAlloca;
2525 DestElementAddr->
getName() +
".ascast");
2527 ShuffleInElement =
true;
2528 UpdateDestListPtr =
true;
2540 if (ShuffleInElement) {
2541 shuffleAndStore(AllocaIP, SrcElementAddr, DestElementAddr, RI.ElementType,
2542 RemoteLaneOffset, ReductionArrayTy);
2544 switch (RI.EvaluationKind) {
2553 RI.ElementType, SrcElementAddr, 0, 0,
".realp");
2555 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
2557 RI.ElementType, SrcElementAddr, 0, 1,
".imagp");
2559 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
2562 RI.ElementType, DestElementAddr, 0, 0,
".realp");
2564 RI.ElementType, DestElementAddr, 0, 1,
".imagp");
2586 if (UpdateDestListPtr) {
2589 DestElementAddr->
getName() +
".ascast");
2605 "_omp_reduction_inter_warp_copy_func", &
M);
2628 "__openmp_nvptx_data_transfer_temporary_storage";
2632 if (!TransferMedium) {
2641 Value *GPUThreadID = getGPUThreadID();
2643 Value *LaneID = getNVPTXLaneID();
2645 Value *WarpID = getNVPTXWarpID();
2654 Arg0Type,
nullptr, ReduceListArg->
getName() +
".addr");
2658 ReduceListAlloca, Arg0Type, ReduceListAlloca->
getName() +
".ascast");
2661 NumWarpsAlloca->
getName() +
".ascast");
2672 for (
auto En :
enumerate(ReductionInfos)) {
2677 const ReductionInfo &RI = En.value();
2679 for (
unsigned TySize = 4; TySize > 0 && RealTySize > 0; TySize /= 2) {
2682 unsigned NumIters = RealTySize / TySize;
2685 Value *Cnt =
nullptr;
2686 Value *CntAddr =
nullptr;
2696 CntAddr->
getName() +
".ascast");
2716 omp::Directive::OMPD_unknown,
2720 return BarrierIP1.takeError();
2731 auto *RedListArrayTy =
2737 {ConstantInt::get(IndexTy, 0),
2738 ConstantInt::get(IndexTy, En.index())});
2764 omp::Directive::OMPD_unknown,
2768 return BarrierIP2.takeError();
2775 Value *NumWarpsVal =
2778 Value *IsActiveThread =
2789 Value *TargetElemPtrPtr =
2791 {ConstantInt::get(IndexTy, 0),
2792 ConstantInt::get(IndexTy, En.index())});
2793 Value *TargetElemPtrVal =
2795 Value *TargetElemPtr = TargetElemPtrVal;
2801 Value *SrcMediumValue =
2820 RealTySize %= TySize;
2830Function *OpenMPIRBuilder::emitShuffleAndReduceFunction(
2836 {Builder.getPtrTy(), Builder.getInt16Ty(),
2837 Builder.getInt16Ty(), Builder.getInt16Ty()},
2841 "_omp_reduction_shuffle_and_reduce_func", &
M);
2862 Type *ReduceListArgType = ReduceListArg->
getType();
2866 ReduceListArgType,
nullptr, ReduceListArg->
getName() +
".addr");
2868 LaneIDArg->
getName() +
".addr");
2870 LaneIDArgType,
nullptr, RemoteLaneOffsetArg->
getName() +
".addr");
2872 AlgoVerArg->
getName() +
".addr");
2879 RedListArrayTy,
nullptr,
".omp.reduction.remote_reduce_list");
2882 ReduceListAlloca, ReduceListArgType,
2883 ReduceListAlloca->
getName() +
".ascast");
2885 LaneIdAlloca, LaneIDArgPtrType, LaneIdAlloca->
getName() +
".ascast");
2887 RemoteLaneOffsetAlloca, LaneIDArgPtrType,
2888 RemoteLaneOffsetAlloca->
getName() +
".ascast");
2890 AlgoVerAlloca, LaneIDArgPtrType, AlgoVerAlloca->
getName() +
".ascast");
2893 RemoteReductionListAlloca->
getName() +
".ascast");
2902 Value *RemoteLaneOffset =
2911 emitReductionListCopy(
2913 ReduceList, RemoteListAddrCast, {RemoteLaneOffset,
nullptr,
nullptr});
2944 Value *RemoteOffsetComp =
2961 ->addFnAttr(Attribute::NoUnwind);
2982 ReductionInfos, RemoteListAddrCast, ReduceList);
2995Function *OpenMPIRBuilder::emitListToGlobalCopyFunction(
3002 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
3006 "_omp_reduction_list_to_global_copy_func", &
M);
3023 BufferArg->
getName() +
".addr");
3030 BufferArgAlloca->
getName() +
".ascast");
3035 ReduceListArgAlloca->
getName() +
".ascast");
3041 Value *LocalReduceList =
3043 Value *BufferArgVal =
3048 for (
auto En :
enumerate(ReductionInfos)) {
3049 const ReductionInfo &RI = En.value();
3050 auto *RedListArrayTy =
3054 RedListArrayTy, LocalReduceList,
3055 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3063 ReductionsBufferTy, BufferVD, 0, En.index());
3065 switch (RI.EvaluationKind) {
3073 RI.ElementType, ElemPtr, 0, 0,
".realp");
3075 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
3077 RI.ElementType, ElemPtr, 0, 1,
".imagp");
3079 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
3082 RI.ElementType, GlobVal, 0, 0,
".realp");
3084 RI.ElementType, GlobVal, 0, 1,
".imagp");
3105Function *OpenMPIRBuilder::emitListToGlobalReduceFunction(
3112 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
3116 "_omp_reduction_list_to_global_reduce_func", &
M);
3133 BufferArg->
getName() +
".addr");
3138 auto *RedListArrayTy =
3143 Value *LocalReduceList =
3148 BufferArgAlloca->
getName() +
".ascast");
3153 ReduceListArgAlloca->
getName() +
".ascast");
3156 LocalReduceList->
getName() +
".ascast");
3166 for (
auto En :
enumerate(ReductionInfos)) {
3168 RedListArrayTy, LocalReduceListAddrCast,
3169 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3174 ReductionsBufferTy, BufferVD, 0, En.index());
3182 ->addFnAttr(Attribute::NoUnwind);
3188Function *OpenMPIRBuilder::emitGlobalToListCopyFunction(
3195 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
3199 "_omp_reduction_global_to_list_copy_func", &
M);
3216 BufferArg->
getName() +
".addr");
3223 BufferArgAlloca->
getName() +
".ascast");
3228 ReduceListArgAlloca->
getName() +
".ascast");
3233 Value *LocalReduceList =
3239 for (
auto En :
enumerate(ReductionInfos)) {
3241 auto *RedListArrayTy =
3245 RedListArrayTy, LocalReduceList,
3246 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3253 ReductionsBufferTy, BufferVD, 0, En.index());
3296Function *OpenMPIRBuilder::emitGlobalToListReduceFunction(
3303 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
3307 "_omp_reduction_global_to_list_reduce_func", &
M);
3324 BufferArg->
getName() +
".addr");
3334 Value *LocalReduceList =
3339 BufferArgAlloca->
getName() +
".ascast");
3344 ReduceListArgAlloca->
getName() +
".ascast");
3347 LocalReduceList->
getName() +
".ascast");
3357 for (
auto En :
enumerate(ReductionInfos)) {
3359 RedListArrayTy, ReductionList,
3360 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3365 ReductionsBufferTy, BufferVD, 0, En.index());
3373 ->addFnAttr(Attribute::NoUnwind);
3379std::string OpenMPIRBuilder::getReductionFuncName(
StringRef Name)
const {
3380 std::string Suffix =
3382 return (
Name + Suffix).str();
3387 ReductionGenCBKind ReductionGenCBKind,
AttributeList FuncAttrs) {
3389 {Builder.getPtrTy(), Builder.getPtrTy()},
3391 std::string
Name = getReductionFuncName(ReducerName);
3403 Value *LHSArrayPtr =
nullptr;
3404 Value *RHSArrayPtr =
nullptr;
3415 LHSAlloca, Arg0Type, LHSAlloca->
getName() +
".ascast");
3417 RHSAlloca, Arg1Type, RHSAlloca->
getName() +
".ascast");
3427 for (
auto En :
enumerate(ReductionInfos)) {
3428 const ReductionInfo &RI = En.value();
3430 RedArrayTy, RHSArrayPtr,
3431 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3434 RHSI8Ptr, RI.PrivateVariable->getType(),
3435 RHSI8Ptr->
getName() +
".ascast");
3438 RedArrayTy, LHSArrayPtr,
3439 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3442 LHSI8Ptr, RI.Variable->getType(), LHSI8Ptr->
getName() +
".ascast");
3454 return AfterIP.takeError();
3456 return ReductionFunc;
3462 for (
auto En :
enumerate(ReductionInfos)) {
3463 unsigned Index = En.index();
3464 const ReductionInfo &RI = En.value();
3465 Value *LHSFixupPtr, *RHSFixupPtr;
3467 Builder.
saveIP(), Index, &LHSFixupPtr, &RHSFixupPtr, ReductionFunc));
3472 LHSPtrs[Index], [ReductionFunc](
const Use &U) {
3473 return cast<Instruction>(
U.getUser())->getParent()->getParent() ==
3477 RHSPtrs[Index], [ReductionFunc](
const Use &U) {
3478 return cast<Instruction>(
U.getUser())->getParent()->getParent() ==
3484 return ReductionFunc;
3492 assert(RI.Variable &&
"expected non-null variable");
3493 assert(RI.PrivateVariable &&
"expected non-null private variable");
3494 assert((RI.ReductionGen || RI.ReductionGenClang) &&
3495 "expected non-null reduction generator callback");
3498 RI.Variable->getType() == RI.PrivateVariable->getType() &&
3499 "expected variables and their private equivalents to have the same "
3502 assert(RI.Variable->getType()->isPointerTy() &&
3503 "expected variables to be pointers");
3510 bool IsNoWait,
bool IsTeamsReduction,
bool HasDistribute,
3512 unsigned ReductionBufNum,
Value *SrcLocInfo) {
3526 if (ReductionInfos.
size() == 0)
3541 if (!ReductionResult)
3543 Function *ReductionFunc = *ReductionResult;
3547 if (GridValue.has_value())
3565 Value *ReductionListAlloca =
3568 ReductionListAlloca, PtrTy, ReductionListAlloca->
getName() +
".ascast");
3572 for (
auto En :
enumerate(ReductionInfos)) {
3575 RedArrayTy, ReductionList,
3576 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3583 emitShuffleAndReduceFunction(ReductionInfos, ReductionFunc, FuncAttrs);
3585 emitInterWarpCopyFunction(Loc, ReductionInfos, FuncAttrs);
3593 unsigned MaxDataSize = 0;
3595 for (
auto En :
enumerate(ReductionInfos)) {
3597 if (
Size > MaxDataSize)
3599 ReductionTypeArgs.
emplace_back(En.value().ElementType);
3601 Value *ReductionDataSize =
3603 if (!IsTeamsReduction) {
3604 Value *SarFuncCast =
3608 Value *Args[] = {SrcLocInfo, ReductionDataSize, RL, SarFuncCast,
3611 RuntimeFunction::OMPRTL___kmpc_nvptx_parallel_reduce_nowait_v2);
3616 Ctx, ReductionTypeArgs,
"struct._globalized_locals_ty");
3618 RuntimeFunction::OMPRTL___kmpc_reduction_get_fixed_buffer);
3619 Function *LtGCFunc = emitListToGlobalCopyFunction(
3620 ReductionInfos, ReductionsBufferTy, FuncAttrs);
3621 Function *LtGRFunc = emitListToGlobalReduceFunction(
3622 ReductionInfos, ReductionFunc, ReductionsBufferTy, FuncAttrs);
3623 Function *GtLCFunc = emitGlobalToListCopyFunction(
3624 ReductionInfos, ReductionsBufferTy, FuncAttrs);
3625 Function *GtLRFunc = emitGlobalToListReduceFunction(
3626 ReductionInfos, ReductionFunc, ReductionsBufferTy, FuncAttrs);
3630 RedFixedBuferFn, {},
"_openmp_teams_reductions_buffer_$_$ptr");
3632 Value *Args3[] = {SrcLocInfo,
3633 KernelTeamsReductionPtr,
3645 RuntimeFunction::OMPRTL___kmpc_nvptx_teams_reduce_nowait_v2);
3662 for (
auto En :
enumerate(ReductionInfos)) {
3669 Value *LHSPtr, *RHSPtr;
3671 &LHSPtr, &RHSPtr, CurFunc));
3676 return cast<Instruction>(U.getUser())->getParent()->getParent() ==
3680 return cast<Instruction>(U.getUser())->getParent()->getParent() ==
3684 assert(
false &&
"Unhandled ReductionGenCBKind");
3700 ".omp.reduction.func", &M);
3711 assert(RI.Variable &&
"expected non-null variable");
3712 assert(RI.PrivateVariable &&
"expected non-null private variable");
3713 assert(RI.ReductionGen &&
"expected non-null reduction generator callback");
3714 assert(RI.Variable->getType() == RI.PrivateVariable->getType() &&
3715 "expected variables and their private equivalents to have the same "
3717 assert(RI.Variable->getType()->isPointerTy() &&
3718 "expected variables to be pointers");
3731 unsigned NumReductions = ReductionInfos.
size();
3738 for (
auto En :
enumerate(ReductionInfos)) {
3739 unsigned Index = En.index();
3742 RedArrayTy, RedArray, 0, Index,
"red.array.elem." +
Twine(Index));
3757 ? IdentFlag::OMP_IDENT_FLAG_ATOMIC_REDUCE
3762 unsigned RedArrayByteSize =
DL.getTypeStoreSize(RedArrayTy);
3765 Value *Lock = getOMPCriticalRegionLock(
".reduction");
3767 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_reduce_nowait
3768 : RuntimeFunction::OMPRTL___kmpc_reduce);
3771 {Ident, ThreadId, NumVariables, RedArraySize, RedArray,
3772 ReductionFunc, Lock},
3791 for (
auto En :
enumerate(ReductionInfos)) {
3797 if (!IsByRef[En.index()]) {
3799 "red.value." +
Twine(En.index()));
3801 Value *PrivateRedValue =
3803 "red.private.value." +
Twine(En.index()));
3814 if (!IsByRef[En.index()])
3818 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_end_reduce_nowait
3819 : RuntimeFunction::OMPRTL___kmpc_end_reduce);
3827 if (CanGenerateAtomic &&
llvm::none_of(IsByRef, [](
bool P) {
return P; })) {
3851 for (
auto En :
enumerate(ReductionInfos)) {
3854 RedArrayTy, LHSArrayPtr, 0, En.index());
3859 RedArrayTy, RHSArrayPtr, 0, En.index());
3873 if (!IsByRef[En.index()])
3889 Directive OMPD = Directive::OMPD_master;
3894 Value *Args[] = {Ident, ThreadId};
3902 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
3913 Directive OMPD = Directive::OMPD_masked;
3919 Value *ArgsEnd[] = {Ident, ThreadId};
3927 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
3962 IndVarPHI->
addIncoming(ConstantInt::get(IndVarTy, 0), Preheader);
3975 "omp_" +
Name +
".next",
true);
3986 CL->Header = Header;
4005 NextBB, NextBB,
Name);
4030 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
4040 auto *IndVarTy = cast<IntegerType>(Start->getType());
4041 assert(IndVarTy == Stop->
getType() &&
"Stop type mismatch");
4042 assert(IndVarTy == Step->
getType() &&
"Step type mismatch");
4048 ConstantInt *Zero = ConstantInt::get(IndVarTy, 0);
4076 Value *CountIfLooping;
4077 if (InclusiveStop) {
4087 "omp_" +
Name +
".tripcount");
4108 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_4u);
4111 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_8u);
4117 InsertPointTy AllocaIP,
4118 bool NeedsBarrier) {
4119 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
4121 "Require dedicated allocate IP");
4133 Type *IVTy =
IV->getType();
4153 Constant *One = ConstantInt::get(IVTy, 1);
4161 Constant *SchedulingType = ConstantInt::get(
4162 I32Type,
static_cast<int>(OMPScheduleType::UnorderedStatic));
4167 {SrcLoc, ThreadNum, SchedulingType, PLastIter, PLowerBound,
4168 PUpperBound, PStride, One,
Zero});
4173 CLI->setTripCount(TripCount);
4195 omp::Directive::OMPD_for,
false,
4198 return BarrierIP.takeError();
4208OpenMPIRBuilder::applyStaticChunkedWorkshareLoop(
DebugLoc DL,
4210 InsertPointTy AllocaIP,
4213 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
4214 assert(ChunkSize &&
"Chunk size is required");
4219 Type *IVTy =
IV->getType();
4221 "Max supported tripcount bitwidth is 64 bits");
4223 :
Type::getInt64Ty(Ctx);
4226 Constant *One = ConstantInt::get(InternalIVTy, 1);
4238 Value *PLowerBound =
4240 Value *PUpperBound =
4249 Value *CastedChunkSize =
4251 Value *CastedTripCount =
4254 Constant *SchedulingType = ConstantInt::get(
4255 I32Type,
static_cast<int>(OMPScheduleType::UnorderedStaticChunked));
4269 SchedulingType, PLastIter,
4270 PLowerBound, PUpperBound,
4275 Value *FirstChunkStart =
4277 Value *FirstChunkStop =
4282 Value *NextChunkStride =
4287 Value *DispatchCounter;
4295 DispatchCounter = Counter;
4298 FirstChunkStart, CastedTripCount, NextChunkStride,
4322 Value *IsLastChunk =
4324 Value *CountUntilOrigTripCount =
4327 IsLastChunk, CountUntilOrigTripCount, ChunkRange,
"omp_chunk.tripcount");
4328 Value *BackcastedChunkTC =
4330 CLI->setTripCount(BackcastedChunkTC);
4335 Value *BackcastedDispatchCounter =
4352 return AfterIP.takeError();
4373 case WorksharingLoopType::ForStaticLoop:
4376 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_4u);
4379 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_8u);
4381 case WorksharingLoopType::DistributeStaticLoop:
4384 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_4u);
4387 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_8u);
4389 case WorksharingLoopType::DistributeForStaticLoop:
4392 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_4u);
4395 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_8u);
4398 if (Bitwidth != 32 && Bitwidth != 64) {
4420 if (LoopType == WorksharingLoopType::DistributeStaticLoop) {
4421 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
4426 M, omp::RuntimeFunction::OMPRTL_omp_get_num_threads);
4427 Builder.
restoreIP({InsertBlock, std::prev(InsertBlock->
end())});
4432 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
4433 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
4434 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
4471 CleanUpInfo.
collectBlocks(RegionBlockSet, BlocksToBeRemoved);
4479 "Expected unique undroppable user of outlined function");
4480 CallInst *OutlinedFnCallInstruction = dyn_cast<CallInst>(OutlinedFnUser);
4481 assert(OutlinedFnCallInstruction &&
"Expected outlined function call");
4483 "Expected outlined function call to be located in loop preheader");
4485 if (OutlinedFnCallInstruction->
arg_size() > 1)
4492 LoopBodyArg, ParallelTaskPtr, TripCount,
4495 for (
auto &ToBeDeletedItem : ToBeDeleted)
4496 ToBeDeletedItem->eraseFromParent();
4502 InsertPointTy AllocaIP,
4515 OI.OuterAllocaBB = AllocaIP.getBlock();
4520 "omp.prelatch",
true);
4540 OI.collectBlocks(ParallelRegionBlockSet,
Blocks);
4542 ParallelRegionBlockSet.
end());
4562 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
4571 if (ParallelRegionBlockSet.
count(Inst->getParent())) {
4572 Inst->replaceUsesOfWith(CLI->
getIndVar(), NewLoopCntLoad);
4578 OI.ExcludeArgsFromAggregate.push_back(NewLoopCntLoad);
4585 OI.PostOutlineCB = [=, ToBeDeletedVec =
4586 std::move(ToBeDeleted)](
Function &OutlinedFn) {
4588 ToBeDeletedVec, LoopType);
4596 bool NeedsBarrier, omp::ScheduleKind SchedKind,
Value *ChunkSize,
4597 bool HasSimdModifier,
bool HasMonotonicModifier,
4598 bool HasNonmonotonicModifier,
bool HasOrderedClause,
4601 return applyWorkshareLoopTarget(
DL, CLI, AllocaIP, LoopType);
4603 SchedKind, ChunkSize, HasSimdModifier, HasMonotonicModifier,
4604 HasNonmonotonicModifier, HasOrderedClause);
4606 bool IsOrdered = (EffectiveScheduleType & OMPScheduleType::ModifierOrdered) ==
4607 OMPScheduleType::ModifierOrdered;
4608 switch (EffectiveScheduleType & ~OMPScheduleType::ModifierMask) {
4609 case OMPScheduleType::BaseStatic:
4610 assert(!ChunkSize &&
"No chunk size with static-chunked schedule");
4612 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
4613 NeedsBarrier, ChunkSize);
4615 return applyStaticWorkshareLoop(
DL, CLI, AllocaIP, NeedsBarrier);
4617 case OMPScheduleType::BaseStaticChunked:
4619 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
4620 NeedsBarrier, ChunkSize);
4622 return applyStaticChunkedWorkshareLoop(
DL, CLI, AllocaIP, NeedsBarrier,
4625 case OMPScheduleType::BaseRuntime:
4626 case OMPScheduleType::BaseAuto:
4627 case OMPScheduleType::BaseGreedy:
4628 case OMPScheduleType::BaseBalanced:
4629 case OMPScheduleType::BaseSteal:
4630 case OMPScheduleType::BaseGuidedSimd:
4631 case OMPScheduleType::BaseRuntimeSimd:
4633 "schedule type does not support user-defined chunk sizes");
4635 case OMPScheduleType::BaseDynamicChunked:
4636 case OMPScheduleType::BaseGuidedChunked:
4637 case OMPScheduleType::BaseGuidedIterativeChunked:
4638 case OMPScheduleType::BaseGuidedAnalyticalChunked:
4639 case OMPScheduleType::BaseStaticBalancedChunked:
4640 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
4641 NeedsBarrier, ChunkSize);
4657 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_4u);
4660 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_8u);
4673 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_4u);
4676 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_8u);
4688 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_4u);
4691 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_8u);
4697 InsertPointTy AllocaIP,
4699 bool NeedsBarrier,
Value *Chunk) {
4700 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
4702 "Require dedicated allocate IP");
4704 "Require valid schedule type");
4706 bool Ordered = (SchedType & OMPScheduleType::ModifierOrdered) ==
4707 OMPScheduleType::ModifierOrdered;
4718 Type *IVTy =
IV->getType();
4736 Constant *One = ConstantInt::get(IVTy, 1);
4757 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
4761 {SrcLoc, ThreadNum, SchedulingType, One,
4762 UpperBound, One, Chunk});
4772 PLowerBound, PUpperBound, PStride});
4773 Constant *Zero32 = ConstantInt::get(I32Type, 0);
4782 auto *PI = cast<PHINode>(Phi);
4783 PI->setIncomingBlock(0, OuterCond);
4784 PI->setIncomingValue(0, LowerBound);
4788 auto *Br = cast<BranchInst>(Term);
4789 Br->setSuccessor(0, OuterCond);
4797 auto *CI = cast<CmpInst>(Comp);
4798 CI->setOperand(1, UpperBound);
4801 auto *BI = cast<BranchInst>(Branch);
4802 assert(BI->getSuccessor(1) == Exit);
4803 BI->setSuccessor(1, OuterCond);
4817 omp::Directive::OMPD_for,
false,
4820 return BarrierIP.takeError();
4839 auto HasRemainingUses = [&BBsToErase](
BasicBlock *BB) {
4840 for (
Use &U : BB->uses()) {
4841 auto *UseInst = dyn_cast<Instruction>(U.getUser());
4844 if (BBsToErase.count(UseInst->getParent()))
4851 while (BBsToErase.remove_if(HasRemainingUses)) {
4862 assert(
Loops.size() >= 1 &&
"At least one loop required");
4863 size_t NumLoops =
Loops.size();
4867 return Loops.front();
4879 Loop->collectControlBlocks(OldControlBBs);
4883 if (ComputeIP.
isSet())
4890 Value *CollapsedTripCount =
nullptr;
4893 "All loops to collapse must be valid canonical loops");
4894 Value *OrigTripCount = L->getTripCount();
4895 if (!CollapsedTripCount) {
4896 CollapsedTripCount = OrigTripCount;
4908 OrigPreheader->
getNextNode(), OrigAfter,
"collapsed");
4916 Value *Leftover = Result->getIndVar();
4918 NewIndVars.
resize(NumLoops);
4919 for (
int i = NumLoops - 1; i >= 1; --i) {
4920 Value *OrigTripCount =
Loops[i]->getTripCount();
4923 NewIndVars[i] = NewIndVar;
4928 NewIndVars[0] = Leftover;
4937 BasicBlock *ContinueBlock = Result->getBody();
4939 auto ContinueWith = [&ContinueBlock, &ContinuePred,
DL](
BasicBlock *Dest,
4946 ContinueBlock =
nullptr;
4947 ContinuePred = NextSrc;
4954 for (
size_t i = 0; i < NumLoops - 1; ++i)
4955 ContinueWith(
Loops[i]->getBody(),
Loops[i + 1]->getHeader());
4961 for (
size_t i = NumLoops - 1; i > 0; --i)
4962 ContinueWith(
Loops[i]->getAfter(),
Loops[i - 1]->getLatch());
4965 ContinueWith(Result->getLatch(),
nullptr);
4972 for (
size_t i = 0; i < NumLoops; ++i)
4973 Loops[i]->getIndVar()->replaceAllUsesWith(NewIndVars[i]);
4987std::vector<CanonicalLoopInfo *>
4991 "Must pass as many tile sizes as there are loops");
4992 int NumLoops =
Loops.size();
4993 assert(NumLoops >= 1 &&
"At least one loop to tile required");
5005 Loop->collectControlBlocks(OldControlBBs);
5013 assert(L->isValid() &&
"All input loops must be valid canonical loops");
5014 OrigTripCounts.
push_back(L->getTripCount());
5025 for (
int i = 0; i < NumLoops - 1; ++i) {
5038 for (
int i = 0; i < NumLoops; ++i) {
5040 Value *OrigTripCount = OrigTripCounts[i];
5053 Value *FloorTripOverflow =
5059 "omp_floor" +
Twine(i) +
".tripcount",
true);
5067 std::vector<CanonicalLoopInfo *> Result;
5068 Result.reserve(NumLoops * 2);
5081 auto EmbeddNewLoop =
5082 [
this,
DL,
F, InnerEnter, &Enter, &
Continue, &OutroInsertBefore](
5085 DL, TripCount,
F, InnerEnter, OutroInsertBefore,
Name);
5090 Enter = EmbeddedLoop->
getBody();
5092 OutroInsertBefore = EmbeddedLoop->
getLatch();
5093 return EmbeddedLoop;
5097 const Twine &NameBase) {
5100 EmbeddNewLoop(
P.value(), NameBase +
Twine(
P.index()));
5101 Result.push_back(EmbeddedLoop);
5105 EmbeddNewLoops(FloorCount,
"floor");
5111 for (
int i = 0; i < NumLoops; ++i) {
5115 Value *FloorIsEpilogue =
5117 Value *TileTripCount =
5124 EmbeddNewLoops(TileCounts,
"tile");
5129 for (std::pair<BasicBlock *, BasicBlock *>
P : InbetweenCode) {
5138 BodyEnter =
nullptr;
5139 BodyEntered = ExitBB;
5152 for (
int i = 0; i < NumLoops; ++i) {
5155 Value *OrigIndVar = OrigIndVars[i];
5183 if (Properties.
empty())
5206 assert(
Loop->isValid() &&
"Expecting a valid CanonicalLoopInfo");
5210 assert(Latch &&
"A valid CanonicalLoopInfo must have a unique latch");
5218 if (
I.mayReadOrWriteMemory()) {
5222 I.setMetadata(LLVMContext::MD_access_group, AccessGroup);
5244 const Twine &NamePrefix) {
5291 VMap[
Block] = NewBB;
5301 if (TargetTriple.
isX86()) {
5302 if (Features.
lookup(
"avx512f"))
5304 else if (Features.
lookup(
"avx"))
5308 if (TargetTriple.
isPPC())
5310 if (TargetTriple.
isWasm())
5317 Value *IfCond, OrderKind Order,
5336 if (AlignedVars.
size()) {
5338 for (
auto &AlignedItem : AlignedVars) {
5339 Value *AlignedPtr = AlignedItem.first;
5340 Value *Alignment = AlignedItem.second;
5341 Instruction *loadInst = dyn_cast<Instruction>(AlignedPtr);
5351 createIfVersion(CanonicalLoop, IfCond, VMap,
"simd");
5355 "Cannot find value which corresponds to original loop latch");
5356 assert(isa<BasicBlock>(MappedLatch) &&
5357 "Cannot cast mapped latch block value to BasicBlock");
5358 BasicBlock *NewLatchBlock = dyn_cast<BasicBlock>(MappedLatch);
5387 if ((Safelen ==
nullptr) || (Order == OrderKind::OMP_ORDER_concurrent)) {
5395 Ctx, {
MDString::get(Ctx,
"llvm.loop.parallel_accesses"), AccessGroup}));
5403 Ctx, {
MDString::get(Ctx,
"llvm.loop.vectorize.enable"), BoolConst}));
5405 if (Simdlen || Safelen) {
5409 ConstantInt *VectorizeWidth = Simdlen ==
nullptr ? Safelen : Simdlen;
5435static std::unique_ptr<TargetMachine>
5439 StringRef CPU =
F->getFnAttribute(
"target-cpu").getValueAsString();
5440 StringRef Features =
F->getFnAttribute(
"target-features").getValueAsString();
5441 const std::string &
Triple = M->getTargetTriple();
5451 std::nullopt, OptLevel));
5475 [&](
const Function &
F) {
return TM->getTargetTransformInfo(
F); });
5490 assert(L &&
"Expecting CanonicalLoopInfo to be recognized as a loop");
5495 nullptr, ORE,
static_cast<int>(OptLevel),
5516 <<
" Threshold=" << UP.
Threshold <<
"\n"
5519 <<
" PartialOptSizeThreshold="
5538 if (
auto *Load = dyn_cast<LoadInst>(&
I)) {
5539 Ptr = Load->getPointerOperand();
5540 }
else if (
auto *Store = dyn_cast<StoreInst>(&
I)) {
5541 Ptr = Store->getPointerOperand();
5545 Ptr =
Ptr->stripPointerCasts();
5547 if (
auto *Alloca = dyn_cast<AllocaInst>(
Ptr)) {
5548 if (Alloca->getParent() == &
F->getEntryBlock())
5568 int MaxTripCount = 0;
5569 bool MaxOrZero =
false;
5570 unsigned TripMultiple = 0;
5572 bool UseUpperBound =
false;
5574 MaxTripCount, MaxOrZero, TripMultiple, UCE, UP, PP,
5576 unsigned Factor = UP.
Count;
5577 LLVM_DEBUG(
dbgs() <<
"Suggesting unroll factor of " << Factor <<
"\n");
5588 assert(Factor >= 0 &&
"Unroll factor must not be negative");
5604 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst}));
5617 *UnrolledCLI =
Loop;
5622 "unrolling only makes sense with a factor of 2 or larger");
5624 Type *IndVarTy =
Loop->getIndVarType();
5631 std::vector<CanonicalLoopInfo *>
LoopNest =
5646 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst})});
5649 (*UnrolledCLI)->assertOK();
5667 Value *Args[] = {Ident, ThreadId, BufSize, CpyBuf, CpyFn, DidItLD};
5686 if (!CPVars.
empty()) {
5691 Directive OMPD = Directive::OMPD_single;
5696 Value *Args[] = {Ident, ThreadId};
5705 if (
Error Err = FiniCB(IP))
5726 EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCBWrapper,
5733 for (
size_t I = 0, E = CPVars.
size();
I < E; ++
I)
5736 ConstantInt::get(
Int64, 0), CPVars[
I],
5739 }
else if (!IsNowait) {
5742 omp::Directive::OMPD_unknown,
false,
5757 Directive OMPD = Directive::OMPD_critical;
5762 Value *LockVar = getOMPCriticalRegionLock(CriticalName);
5763 Value *Args[] = {Ident, ThreadId, LockVar};
5780 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5788 const Twine &
Name,
bool IsDependSource) {
5791 [](
Value *SV) {
return SV->
getType()->isIntegerTy(64); }) &&
5792 "OpenMP runtime requires depend vec with i64 type");
5805 for (
unsigned I = 0;
I < NumLoops; ++
I) {
5819 Value *Args[] = {Ident, ThreadId, DependBaseAddrGEP};
5837 Directive OMPD = Directive::OMPD_ordered;
5846 Value *Args[] = {Ident, ThreadId};
5856 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5862 BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB,
bool Conditional,
5863 bool HasFinalize,
bool IsCancellable) {
5872 if (!isa_and_nonnull<BranchInst>(SplitPos))
5879 emitCommonDirectiveEntry(OMPD, EntryCall, ExitBB, Conditional);
5890 "Unexpected control flow graph state!!");
5892 emitCommonDirectiveExit(OMPD, FinIP, ExitCall, HasFinalize);
5894 return AfterIP.takeError();
5896 "Unexpected Control Flow State!");
5902 "Unexpected Insertion point location!");
5905 auto InsertBB = merged ? ExitPredBB : ExitBB;
5906 if (!isa_and_nonnull<BranchInst>(SplitPos))
5916 if (!Conditional || !EntryCall)
5936 UI->eraseFromParent();
5944 omp::Directive OMPD, InsertPointTy FinIP,
Instruction *ExitCall,
5952 "Unexpected finalization stack state!");
5955 assert(Fi.DK == OMPD &&
"Unexpected Directive for Finalization call!");
5957 if (
Error Err = Fi.FiniCB(FinIP))
6006 if (isa_and_nonnull<BranchInst>(OMP_Entry->
getTerminator())) {
6008 "copyin.not.master.end");
6063 Value *DependenceAddress,
bool HaveNowaitClause) {
6071 if (Device ==
nullptr)
6073 Constant *InteropTypeVal = ConstantInt::get(
Int32, (
int)InteropType);
6074 if (NumDependences ==
nullptr) {
6075 NumDependences = ConstantInt::get(
Int32, 0);
6079 Value *HaveNowaitClauseVal = ConstantInt::get(
Int32, HaveNowaitClause);
6081 Ident, ThreadId, InteropVar, InteropTypeVal,
6082 Device, NumDependences, DependenceAddress, HaveNowaitClauseVal};
6091 Value *NumDependences,
Value *DependenceAddress,
bool HaveNowaitClause) {
6099 if (Device ==
nullptr)
6101 if (NumDependences ==
nullptr) {
6102 NumDependences = ConstantInt::get(
Int32, 0);
6106 Value *HaveNowaitClauseVal = ConstantInt::get(
Int32, HaveNowaitClause);
6108 Ident, ThreadId, InteropVar, Device,
6109 NumDependences, DependenceAddress, HaveNowaitClauseVal};
6118 Value *NumDependences,
6119 Value *DependenceAddress,
6120 bool HaveNowaitClause) {
6127 if (Device ==
nullptr)
6129 if (NumDependences ==
nullptr) {
6130 NumDependences = ConstantInt::get(
Int32, 0);
6134 Value *HaveNowaitClauseVal = ConstantInt::get(
Int32, HaveNowaitClause);
6136 Ident, ThreadId, InteropVar, Device,
6137 NumDependences, DependenceAddress, HaveNowaitClauseVal};
6167 assert(!Attrs.MaxThreads.empty() && !Attrs.MaxTeams.empty() &&
6168 "expected num_threads and num_teams to be specified");
6187 const std::string DebugPrefix =
"_debug__";
6188 if (KernelName.
ends_with(DebugPrefix)) {
6189 KernelName = KernelName.
drop_back(DebugPrefix.length());
6196 if (Attrs.MinTeams > 1 || Attrs.MaxTeams.front() > 0)
6201 int32_t MaxThreadsVal = Attrs.MaxThreads.front();
6202 if (MaxThreadsVal < 0)
6203 MaxThreadsVal = std::max(
6206 if (MaxThreadsVal > 0)
6217 omp::RuntimeFunction::OMPRTL___kmpc_target_init);
6220 Twine DynamicEnvironmentName = KernelName +
"_dynamic_environment";
6221 Constant *DynamicEnvironmentInitializer =
6225 DynamicEnvironmentInitializer, DynamicEnvironmentName,
6227 DL.getDefaultGlobalsAddressSpace());
6231 DynamicEnvironmentGV->
getType() == DynamicEnvironmentPtr
6232 ? DynamicEnvironmentGV
6234 DynamicEnvironmentPtr);
6237 ConfigurationEnvironment, {
6238 UseGenericStateMachineVal,
6239 MayUseNestedParallelismVal,
6246 ReductionBufferLength,
6249 KernelEnvironment, {
6250 ConfigurationEnvironmentInitializer,
6254 std::string KernelEnvironmentName =
6255 (KernelName +
"_kernel_environment").str();
6258 KernelEnvironmentInitializer, KernelEnvironmentName,
6260 DL.getDefaultGlobalsAddressSpace());
6264 KernelEnvironmentGV->
getType() == KernelEnvironmentPtr
6265 ? KernelEnvironmentGV
6267 KernelEnvironmentPtr);
6268 Value *KernelLaunchEnvironment = DebugKernelWrapper->
getArg(0);
6296 UI->eraseFromParent();
6304 int32_t TeamsReductionDataSize,
6305 int32_t TeamsReductionBufferLength) {
6310 omp::RuntimeFunction::OMPRTL___kmpc_target_deinit);
6314 if (!TeamsReductionBufferLength || !TeamsReductionDataSize)
6320 const std::string DebugPrefix =
"_debug__";
6322 KernelName = KernelName.
drop_back(DebugPrefix.length());
6323 auto *KernelEnvironmentGV =
6325 assert(KernelEnvironmentGV &&
"Expected kernel environment global\n");
6326 auto *KernelEnvironmentInitializer = KernelEnvironmentGV->getInitializer();
6328 KernelEnvironmentInitializer,
6329 ConstantInt::get(
Int32, TeamsReductionDataSize), {0, 7});
6331 NewInitializer, ConstantInt::get(
Int32, TeamsReductionBufferLength),
6333 KernelEnvironmentGV->setInitializer(NewInitializer);
6338 NamedMDNode *MD = M.getOrInsertNamedMetadata(
"nvvm.annotations");
6342 auto *KernelOp = dyn_cast<ConstantAsMetadata>(
Op->getOperand(0));
6343 if (!KernelOp || KernelOp->getValue() != &
Kernel)
6345 auto *Prop = dyn_cast<MDString>(
Op->getOperand(1));
6346 if (!Prop || Prop->getString() !=
Name)
6358 auto *OldVal = cast<ConstantAsMetadata>(ExistingOp->
getOperand(2));
6359 int32_t OldLimit = cast<ConstantInt>(OldVal->getValue())->getZExtValue();
6362 OldVal->getValue()->getType(),
6363 Min ? std::min(OldLimit,
Value) : std::max(OldLimit,
Value))));
6372 NamedMDNode *MD = M.getOrInsertNamedMetadata(
"nvvm.annotations");
6377std::pair<int32_t, int32_t>
6379 int32_t ThreadLimit =
6384 if (!Attr.isValid() || !Attr.isStringAttribute())
6385 return {0, ThreadLimit};
6388 if (!llvm::to_integer(UBStr, UB, 10))
6389 return {0, ThreadLimit};
6390 UB = ThreadLimit ? std::min(ThreadLimit, UB) : UB;
6391 if (!llvm::to_integer(LBStr, LB, 10))
6397 auto *OldVal = cast<ConstantAsMetadata>(ExistingOp->getOperand(2));
6398 int32_t UB = cast<ConstantInt>(OldVal->getValue())->getZExtValue();
6399 return {0, ThreadLimit ? std::min(ThreadLimit, UB) : UB};
6401 return {0, ThreadLimit};
6411 llvm::utostr(LB) +
"," + llvm::utostr(UB));
6418std::pair<int32_t, int32_t>
6425 int32_t LB, int32_t UB) {
6430 Kernel.
addFnAttr(
"amdgpu-max-num-workgroups", llvm::utostr(LB) +
",1,1");
6435void OpenMPIRBuilder::setOutlinedTargetRegionFunctionAttributes(
6450 assert(OutlinedFn &&
"The outlined function must exist if embedded");
6459Constant *OpenMPIRBuilder::createTargetRegionEntryAddr(
Function *OutlinedFn,
6465 "Named kernel already exists?");
6483 OutlinedFn = *CBResult;
6485 OutlinedFn =
nullptr;
6491 if (!IsOffloadEntry)
6494 std::string EntryFnIDName =
6496 ? std::string(EntryFnName)
6500 EntryFnName, EntryFnIDName);
6508 setOutlinedTargetRegionFunctionAttributes(OutlinedFn);
6509 auto OutlinedFnID = createOutlinedFunctionID(OutlinedFn, EntryFnIDName);
6510 auto EntryAddr = createTargetRegionEntryAddr(OutlinedFn, EntryFnName);
6512 EntryInfo, EntryAddr, OutlinedFnID,
6514 return OutlinedFnID;
6543 bool IsStandAlone = !BodyGenCB;
6569 SrcLocInfo, DeviceID,
6576 assert(MapperFunc &&
"MapperFunc missing for standalone target data");
6580 if (
Info.HasNoWait) {
6590 if (
Info.HasNoWait) {
6594 emitBlock(OffloadContBlock, CurFn,
true);
6600 bool RequiresOuterTargetTask =
Info.HasNoWait;
6601 if (!RequiresOuterTargetTask)
6602 cantFail(TaskBodyCB(
nullptr,
nullptr,
6606 {},
Info.HasNoWait));
6609 omp::OMPRTL___tgt_target_data_begin_mapper);
6613 for (
auto DeviceMap :
Info.DevicePtrInfoMap) {
6614 if (isa<AllocaInst>(DeviceMap.second.second)) {
6662 Value *OffloadingArgs[] = {SrcLocInfo, DeviceID,
6684 return emitIfClause(IfCond, BeginThenGen, BeginElseGen, AllocaIP);
6700 return emitIfClause(IfCond, EndThenGen, EndElseGen, AllocaIP);
6704 return emitIfClause(IfCond, BeginThenGen, EndElseGen, AllocaIP);
6716 bool IsGPUDistribute) {
6717 assert((IVSize == 32 || IVSize == 64) &&
6718 "IV size is not compatible with the omp runtime");
6720 if (IsGPUDistribute)
6722 ? (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_4
6723 : omp::OMPRTL___kmpc_distribute_static_init_4u)
6724 : (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_8
6725 : omp::OMPRTL___kmpc_distribute_static_init_8u);
6727 Name = IVSize == 32 ? (IVSigned ? omp::OMPRTL___kmpc_for_static_init_4
6728 : omp::OMPRTL___kmpc_for_static_init_4u)
6729 : (IVSigned ? omp::OMPRTL___kmpc_for_static_init_8
6730 : omp::OMPRTL___kmpc_for_static_init_8u);
6737 assert((IVSize == 32 || IVSize == 64) &&
6738 "IV size is not compatible with the omp runtime");
6740 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_4
6741 : omp::OMPRTL___kmpc_dispatch_init_4u)
6742 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_8
6743 : omp::OMPRTL___kmpc_dispatch_init_8u);
6750 assert((IVSize == 32 || IVSize == 64) &&
6751 "IV size is not compatible with the omp runtime");
6753 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_4
6754 : omp::OMPRTL___kmpc_dispatch_next_4u)
6755 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_8
6756 : omp::OMPRTL___kmpc_dispatch_next_8u);
6763 assert((IVSize == 32 || IVSize == 64) &&
6764 "IV size is not compatible with the omp runtime");
6766 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_4
6767 : omp::OMPRTL___kmpc_dispatch_fini_4u)
6768 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_8
6769 : omp::OMPRTL___kmpc_dispatch_fini_8u);
6793 for (
auto &Arg : Inputs)
6794 ParameterTypes.
push_back(Arg->getType()->isPointerTy()
6798 for (
auto &Arg : Inputs)
6799 ParameterTypes.
push_back(Arg->getType());
6803 auto M = BB->getModule();
6814 if (TargetCpuAttr.isStringAttribute())
6815 Func->addFnAttr(TargetCpuAttr);
6817 auto TargetFeaturesAttr = ParentFn->
getFnAttribute(
"target-features");
6818 if (TargetFeaturesAttr.isStringAttribute())
6819 Func->addFnAttr(TargetFeaturesAttr);
6824 OMPBuilder.
emitUsed(
"llvm.compiler.used", {ExecMode});
6840 DB.createSubroutineType(DB.getOrCreateTypeArray({}));
6842 DISubprogram::SPFlagOptimized |
6843 DISubprogram::SPFlagLocalToUnit;
6846 CU, FuncName, FuncName, SP->getFile(),
DL.getLine(), Ty,
6847 DL.getLine(), DINode::DIFlags::FlagArtificial, SPFlags);
6850 Func->setSubprogram(OutlinedSP);
6855 OutlinedSP,
DL.getInlinedAt()));
6878 splitBB(Builder,
true,
"outlined.body");
6893 auto AllocaIP = Builder.
saveIP();
6898 const auto &ArgRange =
6900 ?
make_range(Func->arg_begin() + 1, Func->arg_end())
6921 if (
auto *Const = dyn_cast<Constant>(Input))
6926 if (
auto *Instr = dyn_cast<Instruction>(
User))
6927 if (Instr->getFunction() == Func)
6928 Instr->replaceUsesOfWith(Input, InputCopy);
6934 for (
auto InArg :
zip(Inputs, ArgRange)) {
6935 Value *Input = std::get<0>(InArg);
6936 Argument &Arg = std::get<1>(InArg);
6937 Value *InputCopy =
nullptr;
6940 ArgAccessorFuncCB(Arg, Input, InputCopy, AllocaIP, Builder.
saveIP());
6961 if (llvm::isa<llvm::GlobalValue>(std::get<0>(InArg)) ||
6962 llvm::isa<llvm::GlobalObject>(std::get<0>(InArg)) ||
6963 llvm::isa<llvm::GlobalVariable>(std::get<0>(InArg))) {
6964 DeferredReplacement.
push_back(std::make_pair(Input, InputCopy));
6968 ReplaceValue(Input, InputCopy, Func);
6972 for (
auto Deferred : DeferredReplacement)
6973 ReplaceValue(std::get<0>(Deferred), std::get<1>(Deferred), Func);
7013 Type *TaskPtrTy = OMPBuilder.TaskPtr;
7014 Type *TaskTy = OMPBuilder.Task;
7019 ".omp_target_task_proxy_func",
7021 ProxyFn->getArg(0)->setName(
"thread.id");
7022 ProxyFn->getArg(1)->setName(
"task");
7028 bool HasShareds = StaleCI->
arg_size() > 1;
7034 "StaleCI with shareds should have exactly two arguments.");
7036 auto *ArgStructAlloca = dyn_cast<AllocaInst>(StaleCI->
getArgOperand(1));
7037 assert(ArgStructAlloca &&
7038 "Unable to find the alloca instruction corresponding to arguments "
7039 "for extracted function");
7040 auto *ArgStructType = cast<StructType>(ArgStructAlloca->getAllocatedType());
7043 Builder.
CreateAlloca(ArgStructType,
nullptr,
"structArg");
7044 Value *TaskT = ProxyFn->getArg(1);
7045 Value *ThreadId = ProxyFn->getArg(0);
7046 Value *SharedsSize =
7047 Builder.
getInt64(M.getDataLayout().getTypeStoreSize(ArgStructType));
7054 NewArgStructAlloca, NewArgStructAlloca->
getAlign(), LoadShared,
7057 Builder.
CreateCall(KernelLaunchFunction, {ThreadId, NewArgStructAlloca});
7075 EntryFnName, Inputs, CBFunc,
7080 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
7188 TargetTaskAllocaBB->
begin());
7192 OI.
EntryBB = TargetTaskAllocaBB;
7198 Builder, AllocaIP, ToBeDeleted, TargetTaskAllocaIP,
"global.tid",
false));
7202 if (
Error Err = TaskBodyCB(DeviceID, RTLoc, TargetTaskAllocaIP))
7206 OI.
PostOutlineCB = [
this, ToBeDeleted, Dependencies, HasNoWait,
7207 DeviceID](
Function &OutlinedFn)
mutable {
7209 "there must be a single user for the outlined function");
7212 bool HasShareds = StaleCI->
arg_size() > 1;
7216 LLVM_DEBUG(
dbgs() <<
"Proxy task entry function created: " << *ProxyFn
7235 OMPRTL___kmpc_omp_target_task_alloc);
7253 auto *ArgStructAlloca = dyn_cast<AllocaInst>(StaleCI->
getArgOperand(1));
7254 assert(ArgStructAlloca &&
7255 "Unable to find the alloca instruction corresponding to arguments "
7256 "for extracted function");
7257 auto *ArgStructType =
7258 dyn_cast<StructType>(ArgStructAlloca->getAllocatedType());
7259 assert(ArgStructType &&
"Unable to find struct type corresponding to "
7260 "arguments for extracted function");
7281 TaskSize, SharedsSize,
7329 }
else if (DepArray) {
7348 I->eraseFromParent();
7366 DeviceAddrCB, CustomMapperCB);
7379 bool HasNoWait =
false) {
7390 bool HasDependencies = Dependencies.size() > 0;
7391 bool RequiresOuterTargetTask = HasNoWait || HasDependencies;
7410 EmitTargetCallFallbackCB, KArgs,
7411 DeviceID, RTLoc, TargetTaskAllocaIP);
7414 return EmitTargetCallFallbackCB(OMPBuilder.
Builder.
saveIP());
7421 auto &&EmitTargetCallElse =
7427 if (RequiresOuterTargetTask) {
7433 Dependencies, HasNoWait);
7435 return EmitTargetCallFallbackCB(Builder.
saveIP());
7442 auto &&EmitTargetCallThen =
7459 NumTeamsC.
push_back(RuntimeVal ? RuntimeVal
7464 auto InitMaxThreadsClause = [&Builder](
Value *
Clause) {
7481 Value *MaxThreadsClause =
7483 ? InitMaxThreadsClause(RuntimeAttrs.
MaxThreads)
7486 for (
auto [TeamsVal, TargetVal] :
zip_equal(
7488 Value *TeamsThreadLimitClause = InitMaxThreadsClause(TeamsVal);
7489 Value *NumThreads = InitMaxThreadsClause(TargetVal);
7491 CombineMaxThreadsClauses(TeamsThreadLimitClause, NumThreads);
7492 CombineMaxThreadsClauses(MaxThreadsClause, NumThreads);
7497 unsigned NumTargetItems =
Info.NumberOfPtrs;
7515 NumTeamsC, NumThreadsC,
7516 DynCGGroupMem, HasNoWait);
7523 if (RequiresOuterTargetTask)
7524 return OMPBuilder.
emitTargetTask(TaskBodyCB, DeviceID, RTLoc, AllocaIP,
7525 Dependencies, HasNoWait);
7528 EmitTargetCallFallbackCB, KArgs,
7529 DeviceID, RTLoc, AllocaIP);
7539 if (!OutlinedFnID) {
7551 EmitTargetCallElse, AllocaIP));
7575 *
this,
Builder, IsOffloadEntry, EntryInfo, DefaultAttrs, OutlinedFn,
7576 OutlinedFnID, Args, CBFunc, ArgAccessorFuncCB))
7584 OutlinedFn, OutlinedFnID, Args, GenMapInfoCB, Dependencies,
7599 return OS.str().str();
7613 assert(Elem.second->getValueType() == Ty &&
7614 "OMP internal variable has different type than requested");
7630 GV->setAlignment(std::max(TypeAlign, PtrAlign));
7637Value *OpenMPIRBuilder::getOMPCriticalRegionLock(
StringRef CriticalName) {
7638 std::string Prefix =
Twine(
"gomp_critical_user_", CriticalName).
str();
7639 std::string
Name = getNameWithSeparators({Prefix,
"var"},
".",
".");
7650 return SizePtrToInt;
7655 std::string VarName) {
7663 return MaptypesArrayGlobal;
7668 unsigned NumOperands,
7677 ArrI8PtrTy,
nullptr,
".offload_baseptrs");
7681 ArrI64Ty,
nullptr,
".offload_sizes");
7692 int64_t DeviceID,
unsigned NumOperands) {
7698 Value *ArgsBaseGEP =
7700 {Builder.getInt32(0), Builder.getInt32(0)});
7703 {Builder.getInt32(0), Builder.getInt32(0)});
7704 Value *ArgSizesGEP =
7706 {Builder.getInt32(0), Builder.getInt32(0)});
7712 ArgSizesGEP, MaptypesArg, MapnamesArg, NullPtr});
7719 assert((!ForEndCall ||
Info.separateBeginEndCalls()) &&
7720 "expected region end call to runtime only when end call is separate");
7722 auto VoidPtrTy = UnqualPtrTy;
7723 auto VoidPtrPtrTy = UnqualPtrTy;
7725 auto Int64PtrTy = UnqualPtrTy;
7727 if (!
Info.NumberOfPtrs) {
7739 Info.RTArgs.BasePointersArray,
7750 ForEndCall &&
Info.RTArgs.MapTypesArrayEnd ?
Info.RTArgs.MapTypesArrayEnd
7751 :
Info.RTArgs.MapTypesArray,
7757 if (!
Info.EmitDebug)
7766 if (!
Info.HasMapper)
7791 "struct.descriptor_dim");
7793 enum { OffsetFD = 0, CountFD, StrideFD };
7797 for (
unsigned I = 0, L = 0, E = NonContigInfo.
Dims.
size();
I < E; ++
I) {
7800 if (NonContigInfo.
Dims[
I] == 1)
7807 for (
unsigned II = 0, EE = NonContigInfo.
Dims[
I];
II < EE; ++
II) {
7808 unsigned RevIdx = EE -
II - 1;
7811 {Builder.getInt64(0), Builder.getInt64(II)});
7815 NonContigInfo.
Offsets[L][RevIdx], OffsetLVal,
7820 NonContigInfo.
Counts[L][RevIdx], CountLVal,
7825 NonContigInfo.
Strides[L][RevIdx], StrideLVal,
7834 Info.RTArgs.PointersArray, 0,
I);
7841void OpenMPIRBuilder::emitUDMapperArrayInitOrDel(
7845 StringRef Prefix = IsInit ?
".init" :
".del";
7855 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
7856 OpenMPOffloadMappingFlags::OMP_MAP_DELETE)));
7866 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
7867 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ)));
7892 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
7893 OpenMPOffloadMappingFlags::OMP_MAP_TO |
7894 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
7898 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
7899 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT)));
7903 Value *OffloadingArgs[] = {MapperHandle,
Base, Begin,
7904 ArraySize, MapTypeArg, MapName};
7931 MapperFn->
addFnAttr(Attribute::NoInline);
7932 MapperFn->
addFnAttr(Attribute::NoUnwind);
7963 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
7964 MapType, MapName, ElementSize, HeadBB,
7990 Value *OffloadingArgs[] = {MapperHandle};
7994 Value *ShiftedPreviousSize =
7998 for (
unsigned I = 0;
I <
Info.BasePointers.size(); ++
I) {
8001 Value *CurBeginArg =
8010 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
8012 Value *MemberMapType =
8030 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
8031 OpenMPOffloadMappingFlags::OMP_MAP_TO |
8032 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
8048 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
8049 OpenMPOffloadMappingFlags::OMP_MAP_TO |
8050 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
8056 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
8057 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
8064 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
8065 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
8071 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
8072 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
8079 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
8080 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
8091 Value *OffloadingArgs[] = {MapperHandle, CurBaseArg, CurBeginArg,
8092 CurSizeArg, CurMapType, CurNameArg};
8094 if (CustomMapperCB && CustomMapperCB(
I, &ChildMapperFn)) {
8109 "omp.arraymap.next");
8118 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
8119 MapType, MapName, ElementSize, DoneBB,
8137 Info.clearArrayInfo();
8140 if (
Info.NumberOfPtrs == 0)
8150 PointerArrayType,
nullptr,
".offload_baseptrs");
8153 PointerArrayType,
nullptr,
".offload_ptrs");
8155 PointerArrayType,
nullptr,
".offload_mappers");
8156 Info.RTArgs.MappersArray = MappersArray;
8163 ConstantInt::get(Int64Ty, 0));
8165 for (
unsigned I = 0, E = CombinedInfo.
Sizes.
size();
I < E; ++
I) {
8166 if (
auto *CI = dyn_cast<Constant>(CombinedInfo.
Sizes[
I])) {
8167 if (!isa<ConstantExpr>(CI) && !isa<GlobalValue>(CI)) {
8168 if (IsNonContiguous &&
8169 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
8171 OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG))
8179 RuntimeSizes.
set(
I);
8182 if (RuntimeSizes.
all()) {
8185 SizeArrayType,
nullptr,
".offload_sizes");
8191 auto *SizesArrayGbl =
8196 if (!RuntimeSizes.
any()) {
8197 Info.RTArgs.SizesArray = SizesArrayGbl;
8203 SizeArrayType,
nullptr,
".offload_sizes");
8208 SizesArrayGbl, OffloadSizeAlign,
8213 Info.RTArgs.SizesArray = Buffer;
8221 for (
auto mapFlag : CombinedInfo.
Types)
8223 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
8227 Info.RTArgs.MapTypesArray = MapTypesArrayGbl;
8232 auto *MapNamesArrayGbl =
8234 Info.RTArgs.MapNamesArray = MapNamesArrayGbl;
8235 Info.EmitDebug =
true;
8237 Info.RTArgs.MapNamesArray =
8239 Info.EmitDebug =
false;
8244 if (
Info.separateBeginEndCalls()) {
8245 bool EndMapTypesDiffer =
false;
8247 if (
Type &
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
8248 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT)) {
8249 Type &= ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
8250 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
8251 EndMapTypesDiffer =
true;
8254 if (EndMapTypesDiffer) {
8256 Info.RTArgs.MapTypesArrayEnd = MapTypesArrayGbl;
8261 for (
unsigned I = 0;
I <
Info.NumberOfPtrs; ++
I) {
8269 if (
Info.requiresDevicePointerInfo()) {
8276 DeviceAddrCB(
I,
Info.DevicePtrInfoMap[BPVal].second);
8278 Info.DevicePtrInfoMap[BPVal] = {BP, BP};
8280 DeviceAddrCB(
I, BP);
8292 if (RuntimeSizes.
test(
I)) {
8306 if (
Value *CustomMFunc = CustomMapperCB(
I))
8310 {Builder.getIntN(IndexSize, 0), Builder.getIntN(IndexSize, I)});
8316 Info.NumberOfPtrs == 0)
8361 if (
auto *CI = dyn_cast<ConstantInt>(
Cond)) {
8362 auto CondConstant = CI->getSExtValue();
8394bool OpenMPIRBuilder::checkAndEmitFlushAfterAtomic(
8398 "Unexpected Atomic Ordering.");
8462 assert(
X.Var->getType()->isPointerTy() &&
8463 "OMP Atomic expects a pointer to target memory");
8464 Type *XElemTy =
X.ElemTy;
8467 "OMP atomic read expected a scalar type");
8469 Value *XRead =
nullptr;
8475 XRead = cast<Value>(XLD);
8488 XRead = AtomicLoadRes.first;
8503 checkAndEmitFlushAfterAtomic(Loc, AO, AtomicKind::Read);
8515 assert(
X.Var->getType()->isPointerTy() &&
8516 "OMP Atomic expects a pointer to target memory");
8517 Type *XElemTy =
X.ElemTy;
8520 "OMP atomic write expected a scalar type");
8535 checkAndEmitFlushAfterAtomic(Loc, AO, AtomicKind::Write);
8548 Type *XTy =
X.Var->getType();
8550 "OMP Atomic expects a pointer to target memory");
8551 Type *XElemTy =
X.ElemTy;
8554 "OMP atomic update expected a scalar type");
8557 "OpenMP atomic does not support LT or GT operations");
8561 emitAtomicUpdate(AllocaIP,
X.Var,
X.ElemTy, Expr, AO, RMWOp, UpdateOp,
8562 X.IsVolatile, IsXBinopExpr);
8564 return AtomicResult.takeError();
8565 checkAndEmitFlushAfterAtomic(Loc, AO, AtomicKind::Update);
8570Value *OpenMPIRBuilder::emitRMWOpAsInstruction(
Value *Src1,
Value *Src2,
8607 AtomicUpdateCallbackTy &UpdateOp,
bool VolatileX,
bool IsXBinopExpr) {
8610 bool emitRMWOp =
false;
8618 emitRMWOp = XElemTy;
8621 emitRMWOp = (IsXBinopExpr && XElemTy);
8628 std::pair<Value *, Value *> Res;
8635 Res.second = Res.first;
8637 Res.second = emitRMWOpAsInstruction(Res.first, Expr, RMWOp);
8650 auto AtomicLoadRes = atomicInfo.EmitAtomicLoadLibcall(AO);
8657 X->getName() +
".atomic.cont");
8661 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
8664 PHI->addIncoming(AtomicLoadRes.first, CurBB);
8669 Value *Upd = *CBResult;
8673 auto Result = atomicInfo.EmitAtomicCompareExchangeLibcall(
8674 AtomicLoadRes.second, NewAtomicAddr, AO, Failure);
8679 Res.first = OldExprVal;
8706 X->getName() +
".atomic.cont");
8710 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
8713 PHI->addIncoming(OldVal, CurBB);
8719 X->getName() +
".atomic.fltCast");
8722 X->getName() +
".atomic.ptrCast");
8729 Value *Upd = *CBResult;
8736 Result->setVolatile(VolatileX);
8742 Res.first = OldExprVal;
8762 bool UpdateExpr,
bool IsPostfixUpdate,
bool IsXBinopExpr) {
8767 Type *XTy =
X.Var->getType();
8769 "OMP Atomic expects a pointer to target memory");
8770 Type *XElemTy =
X.ElemTy;
8773 "OMP atomic capture expected a scalar type");
8775 "OpenMP atomic does not support LT or GT operations");
8782 emitAtomicUpdate(AllocaIP,
X.Var,
X.ElemTy, Expr, AO, AtomicOp, UpdateOp,
8783 X.IsVolatile, IsXBinopExpr);
8786 Value *CapturedVal =
8787 (IsPostfixUpdate ? AtomicResult->first : AtomicResult->second);
8790 checkAndEmitFlushAfterAtomic(Loc, AO, AtomicKind::Capture);
8802 IsPostfixUpdate, IsFailOnly, Failure);
8814 assert(
X.Var->getType()->isPointerTy() &&
8815 "OMP atomic expects a pointer to target memory");
8818 assert(V.Var->getType()->isPointerTy() &&
"v.var must be of pointer type");
8819 assert(V.ElemTy ==
X.ElemTy &&
"x and v must be of same type");
8824 if (
Op == OMPAtomicCompareOp::EQ) {
8843 "OldValue and V must be of same type");
8844 if (IsPostfixUpdate) {
8862 CurBBTI,
X.Var->getName() +
".atomic.exit");
8882 Value *CapturedValue =
8890 assert(R.Var->getType()->isPointerTy() &&
8891 "r.var must be of pointer type");
8892 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
8895 Value *ResultCast = R.IsSigned
8901 assert((
Op == OMPAtomicCompareOp::MAX ||
Op == OMPAtomicCompareOp::MIN) &&
8902 "Op should be either max or min at this point");
8903 assert(!IsFailOnly &&
"IsFailOnly is only valid when the comparison is ==");
8943 Value *CapturedValue =
nullptr;
8944 if (IsPostfixUpdate) {
8945 CapturedValue = OldValue;
8977 checkAndEmitFlushAfterAtomic(Loc, AO, AtomicKind::Compare);
9024 bool SubClausesPresent =
9025 (NumTeamsLower || NumTeamsUpper || ThreadLimit || IfExpr);
9028 assert((NumTeamsLower ==
nullptr || NumTeamsUpper !=
nullptr) &&
9029 "if lowerbound is non-null, then upperbound must also be non-null "
9030 "for bounds on num_teams");
9032 if (NumTeamsUpper ==
nullptr)
9035 if (NumTeamsLower ==
nullptr)
9036 NumTeamsLower = NumTeamsUpper;
9040 "argument to if clause must be an integer value");
9045 ConstantInt::get(IfExpr->
getType(), 0));
9054 if (ThreadLimit ==
nullptr)
9060 {Ident, ThreadNum, NumTeamsLower, NumTeamsUpper, ThreadLimit});
9065 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP))
9077 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"gid",
true));
9079 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"tid",
true));
9081 auto HostPostOutlineCB = [
this, Ident,
9082 ToBeDeleted](
Function &OutlinedFn)
mutable {
9087 "there must be a single user for the outlined function");
9092 "Outlined function must have two or three arguments only");
9094 bool HasShared = OutlinedFn.
arg_size() == 3;
9102 assert(StaleCI &&
"Error while outlining - no CallInst user found for the "
9103 "outlined function.");
9110 omp::RuntimeFunction::OMPRTL___kmpc_fork_teams),
9114 I->eraseFromParent();
9129 std::string VarName) {
9138 return MapNamesArrayGlobal;
9143void OpenMPIRBuilder::initializeTypes(
Module &M) {
9146#define OMP_TYPE(VarName, InitValue) VarName = InitValue;
9147#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \
9148 VarName##Ty = ArrayType::get(ElemTy, ArraySize); \
9149 VarName##PtrTy = PointerType::getUnqual(VarName##Ty);
9150#define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) \
9151 VarName = FunctionType::get(ReturnType, {__VA_ARGS__}, IsVarArg); \
9152 VarName##Ptr = PointerType::getUnqual(VarName);
9153#define OMP_STRUCT_TYPE(VarName, StructName, Packed, ...) \
9154 T = StructType::getTypeByName(Ctx, StructName); \
9156 T = StructType::create(Ctx, {__VA_ARGS__}, StructName, Packed); \
9158 VarName##Ptr = PointerType::getUnqual(T);
9159#include "llvm/Frontend/OpenMP/OMPKinds.def"
9170 while (!Worklist.
empty()) {
9174 if (BlockSet.
insert(SuccBB).second)
9186 "omp_offloading_entries");
9210 Fn->
addFnAttr(
"uniform-work-group-size",
"true");
9229 auto &&GetMDInt = [
this](
unsigned V) {
9237 auto &&TargetRegionMetadataEmitter =
9238 [&
C, MD, &OrderedEntries, &GetMDInt, &GetMDString](
9253 GetMDInt(E.getKind()), GetMDInt(EntryInfo.DeviceID),
9254 GetMDInt(EntryInfo.FileID), GetMDString(EntryInfo.ParentName),
9255 GetMDInt(EntryInfo.Line), GetMDInt(EntryInfo.Count),
9256 GetMDInt(E.getOrder())};
9259 OrderedEntries[E.getOrder()] = std::make_pair(&E, EntryInfo);
9268 auto &&DeviceGlobalVarMetadataEmitter =
9269 [&
C, &OrderedEntries, &GetMDInt, &GetMDString, MD](
9279 Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDString(MangledName),
9280 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
9284 OrderedEntries[E.getOrder()] = std::make_pair(&E, varInfo);
9291 DeviceGlobalVarMetadataEmitter);
9293 for (
const auto &E : OrderedEntries) {
9294 assert(E.first &&
"All ordered entries must exist!");
9295 if (
const auto *CE =
9296 dyn_cast<OffloadEntriesInfoManager::OffloadEntryInfoTargetRegion>(
9298 if (!CE->getID() || !CE->getAddress()) {
9310 }
else if (
const auto *CE =
dyn_cast<
9321 if (!CE->getAddress()) {
9326 if (CE->getVarSize() == 0)
9332 "Declaret target link address is set.");
9335 if (!CE->getAddress()) {
9347 if (
auto *
GV = dyn_cast<GlobalValue>(CE->getAddress()))
9348 if ((
GV->hasLocalLinkage() ||
GV->hasHiddenVisibility()) &&
9356 Flags, CE->getLinkage(), CE->getVarName());
9359 Flags, CE->getLinkage());
9380 unsigned FileID,
unsigned Line,
unsigned Count) {
9383 <<
llvm::format(
"_%x_", FileID) << ParentName <<
"_l" << Line;
9390 unsigned NewCount = getTargetRegionEntryInfoCount(EntryInfo);
9393 EntryInfo.
Line, NewCount);
9400 auto FileIDInfo = CallBack();
9403 "getTargetEntryUniqueInfo, error message: " +
9409 std::get<1>(FileIDInfo));
9415 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
9417 !(Remain & 1); Remain = Remain >> 1)
9435 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
9437 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
9444 Flags &= ~omp::OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
9445 Flags |= MemberOfFlag;
9451 bool IsDeclaration,
bool IsExternallyVisible,
9453 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
9454 std::vector<Triple> TargetTriple,
Type *LlvmPtrTy,
9455 std::function<
Constant *()> GlobalInitializer,
9471 if (!IsExternallyVisible)
9473 OS <<
"_decl_tgt_ref_ptr";
9482 auto *
GV = cast<GlobalVariable>(
Ptr);
9486 if (GlobalInitializer)
9487 GV->setInitializer(GlobalInitializer());
9493 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
9494 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
9495 GlobalInitializer, VariableLinkage, LlvmPtrTy, cast<Constant>(
Ptr));
9498 return cast<Constant>(
Ptr);
9507 bool IsDeclaration,
bool IsExternallyVisible,
9509 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
9510 std::vector<Triple> TargetTriple,
9511 std::function<
Constant *()> GlobalInitializer,
9528 VarName = MangledName;
9536 Linkage = (VariableLinkage) ? VariableLinkage() : LlvmVal->
getLinkage();
9552 auto *GvAddrRef = cast<GlobalVariable>(AddrRef);
9553 GvAddrRef->setConstant(
true);
9555 GvAddrRef->setInitializer(
Addr);
9556 GeneratedRefs.push_back(GvAddrRef);
9566 VarName = (
Addr) ?
Addr->getName() :
"";
9570 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
9571 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
9572 LlvmPtrTy, GlobalInitializer, VariableLinkage);
9573 VarName = (
Addr) ?
Addr->getName() :
"";
9594 auto &&GetMDInt = [MN](
unsigned Idx) {
9595 auto *V = cast<ConstantAsMetadata>(MN->getOperand(
Idx));
9596 return cast<ConstantInt>(V->getValue())->getZExtValue();
9599 auto &&GetMDString = [MN](
unsigned Idx) {
9600 auto *V = cast<MDString>(MN->getOperand(
Idx));
9601 return V->getString();
9604 switch (GetMDInt(0)) {
9632 if (HostFilePath.
empty())
9636 if (std::error_code Err = Buf.getError()) {
9638 "OpenMPIRBuilder: " +
9646 if (std::error_code Err =
M.getError()) {
9648 (
"error parsing host file inside of OpenMPIRBuilder: " + Err.message())
9660 return OffloadEntriesTargetRegion.empty() &&
9661 OffloadEntriesDeviceGlobalVar.empty();
9664unsigned OffloadEntriesInfoManager::getTargetRegionEntryInfoCount(
9666 auto It = OffloadEntriesTargetRegionCount.find(
9667 getTargetRegionEntryCountKey(EntryInfo));
9668 if (It == OffloadEntriesTargetRegionCount.end())
9673void OffloadEntriesInfoManager::incrementTargetRegionEntryInfoCount(
9675 OffloadEntriesTargetRegionCount[getTargetRegionEntryCountKey(EntryInfo)] =
9676 EntryInfo.
Count + 1;
9682 OffloadEntriesTargetRegion[EntryInfo] =
9684 OMPTargetRegionEntryTargetRegion);
9685 ++OffloadingEntriesNum;
9691 assert(EntryInfo.
Count == 0 &&
"expected default EntryInfo");
9694 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
9700 if (!hasTargetRegionEntryInfo(EntryInfo)) {
9703 auto &Entry = OffloadEntriesTargetRegion[EntryInfo];
9704 Entry.setAddress(
Addr);
9706 Entry.setFlags(
Flags);
9709 hasTargetRegionEntryInfo(EntryInfo,
true))
9711 assert(!hasTargetRegionEntryInfo(EntryInfo) &&
9712 "Target region entry already registered!");
9714 OffloadEntriesTargetRegion[EntryInfo] = Entry;
9715 ++OffloadingEntriesNum;
9717 incrementTargetRegionEntryInfoCount(EntryInfo);
9724 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
9726 auto It = OffloadEntriesTargetRegion.find(EntryInfo);
9727 if (It == OffloadEntriesTargetRegion.end()) {
9731 if (!IgnoreAddressId && (It->second.getAddress() || It->second.getID()))
9739 for (
const auto &It : OffloadEntriesTargetRegion) {
9740 Action(It.first, It.second);
9746 OffloadEntriesDeviceGlobalVar.try_emplace(
Name, Order,
Flags);
9747 ++OffloadingEntriesNum;
9755 if (!hasDeviceGlobalVarEntryInfo(VarName))
9757 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
9758 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) {
9759 if (Entry.getVarSize() == 0) {
9760 Entry.setVarSize(VarSize);
9761 Entry.setLinkage(Linkage);
9765 Entry.setVarSize(VarSize);
9766 Entry.setLinkage(Linkage);
9767 Entry.setAddress(
Addr);
9769 if (hasDeviceGlobalVarEntryInfo(VarName)) {
9770 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
9771 assert(Entry.isValid() && Entry.getFlags() ==
Flags &&
9772 "Entry not initialized!");
9773 if (Entry.getVarSize() == 0) {
9774 Entry.setVarSize(VarSize);
9775 Entry.setLinkage(Linkage);
9780 OffloadEntriesDeviceGlobalVar.try_emplace(VarName, OffloadingEntriesNum,
9784 OffloadEntriesDeviceGlobalVar.try_emplace(
9785 VarName, OffloadingEntriesNum,
Addr, VarSize,
Flags, Linkage,
"");
9786 ++OffloadingEntriesNum;
9793 for (
const auto &E : OffloadEntriesDeviceGlobalVar)
9794 Action(E.getKey(), E.getValue());
9801void CanonicalLoopInfo::collectControlBlocks(
9808 BBs.
append({getPreheader(), Header,
Cond, Latch, Exit, getAfter()});
9820void CanonicalLoopInfo::setTripCount(
Value *TripCount) {
9824 assert(isa<CmpInst>(CmpI) &&
"First inst must compare IV with TripCount");
9832void CanonicalLoopInfo::mapIndVar(
9842 for (
Use &U : OldIV->
uses()) {
9843 auto *
User = dyn_cast<Instruction>(U.getUser());
9846 if (
User->getParent() == getCond())
9848 if (
User->getParent() == getLatch())
9854 Value *NewIV = Updater(OldIV);
9857 for (
Use *U : ReplacableUses)
9878 "Preheader must terminate with unconditional branch");
9880 "Preheader must jump to header");
9883 assert(isa<BranchInst>(Header->getTerminator()) &&
9884 "Header must terminate with unconditional branch");
9885 assert(Header->getSingleSuccessor() ==
Cond &&
9886 "Header must jump to exiting block");
9889 assert(
Cond->getSinglePredecessor() == Header &&
9890 "Exiting block only reachable from header");
9892 assert(isa<BranchInst>(
Cond->getTerminator()) &&
9893 "Exiting block must terminate with conditional branch");
9895 "Exiting block must have two successors");
9896 assert(cast<BranchInst>(
Cond->getTerminator())->getSuccessor(0) == Body &&
9897 "Exiting block's first successor jump to the body");
9898 assert(cast<BranchInst>(
Cond->getTerminator())->getSuccessor(1) == Exit &&
9899 "Exiting block's second successor must exit the loop");
9903 "Body only reachable from exiting block");
9908 "Latch must terminate with unconditional branch");
9916 assert(isa<BranchInst>(Exit->getTerminator()) &&
9917 "Exit block must terminate with unconditional branch");
9919 "Exit block must jump to after block");
9923 "After block only reachable from exit block");
9927 assert(IndVar &&
"Canonical induction variable not found?");
9929 "Induction variable must be an integer");
9931 "Induction variable must be a PHI in the loop header");
9932 assert(cast<PHINode>(IndVar)->getIncomingBlock(0) == Preheader);
9934 cast<ConstantInt>(cast<PHINode>(IndVar)->getIncomingValue(0))->
isZero());
9935 assert(cast<PHINode>(IndVar)->getIncomingBlock(1) == Latch);
9937 auto *NextIndVar = cast<PHINode>(IndVar)->getIncomingValue(1);
9939 assert(cast<BinaryOperator>(NextIndVar)->
getOpcode() == BinaryOperator::Add);
9940 assert(cast<BinaryOperator>(NextIndVar)->getOperand(0) == IndVar);
9941 assert(cast<ConstantInt>(cast<BinaryOperator>(NextIndVar)->getOperand(1))
9944 Value *TripCount = getTripCount();
9945 assert(TripCount &&
"Loop trip count not found?");
9947 "Trip count and induction variable must have the same type");
9949 auto *CmpI = cast<CmpInst>(&
Cond->front());
9951 "Exit condition must be a signed less-than comparison");
9953 "Exit condition must compare the induction variable");
9955 "Exit condition must compare with the trip count");
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
This file contains the simple types necessary to represent the attributes associated with functions a...
static const Function * getParent(const Value *V)
#define LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE()
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE() pulls the operator overloads used by LLVM_MARK_AS_BITMASK_EN...
#define LLVM_MARK_AS_BITMASK_ENUM(LargestValue)
LLVM_MARK_AS_BITMASK_ENUM lets you opt in an individual enum type so you can perform bitwise operatio...
BlockVerifier::State From
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
Analysis containing CSE Info
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
DenseMap< Block *, BlockRelaxAux > Blocks
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
This header defines various interfaces for pass management in LLVM.
iv Induction Variable Users
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
static cl::opt< unsigned > TileSize("fuse-matrix-tile-size", cl::init(4), cl::Hidden, cl::desc("Tile size for matrix instruction fusion using square-shaped tiles."))
uint64_t IntrinsicInst * II
#define OMP_KERNEL_ARG_VERSION
Provides definitions for Target specific Grid Values.
static OMPScheduleType getOpenMPBaseScheduleType(llvm::omp::ScheduleKind ClauseKind, bool HasChunks, bool HasSimdModifier)
Determine which scheduling algorithm to use, determined from schedule clause arguments.
static void redirectTo(BasicBlock *Source, BasicBlock *Target, DebugLoc DL)
Make Source branch to Target.
Value * createFakeIntVal(IRBuilderBase &Builder, OpenMPIRBuilder::InsertPointTy OuterAllocaIP, llvm::SmallVectorImpl< Instruction * > &ToBeDeleted, OpenMPIRBuilder::InsertPointTy InnerAllocaIP, const Twine &Name="", bool AsPtr=true)
static FunctionCallee getKmpcForDynamicFiniForType(Type *Ty, Module &M, OpenMPIRBuilder &OMPBuilder)
Returns an LLVM function to call for finalizing the dynamic loop using depending on type.
static Expected< Function * > createOutlinedFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, const OpenMPIRBuilder::TargetKernelDefaultAttrs &DefaultAttrs, StringRef FuncName, SmallVectorImpl< Value * > &Inputs, OpenMPIRBuilder::TargetBodyGenCallbackTy &CBFunc, OpenMPIRBuilder::TargetGenArgAccessorsCallbackTy &ArgAccessorFuncCB)
static Function * emitTargetTaskProxyFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, CallInst *StaleCI)
Create an entry point for a target task with the following.
static void updateNVPTXMetadata(Function &Kernel, StringRef Name, int32_t Value, bool Min)
static OMPScheduleType getOpenMPOrderingScheduleType(OMPScheduleType BaseScheduleType, bool HasOrderedClause)
Adds ordering modifier flags to schedule type.
static OMPScheduleType getOpenMPMonotonicityScheduleType(OMPScheduleType ScheduleType, bool HasSimdModifier, bool HasMonotonic, bool HasNonmonotonic, bool HasOrderedClause)
Adds monotonicity modifier flags to schedule type.
static void addSimdMetadata(BasicBlock *Block, MDNode *AccessGroup, LoopInfo &LI)
Attach llvm.access.group metadata to the memref instructions of Block.
static OMPScheduleType computeOpenMPScheduleType(ScheduleKind ClauseKind, bool HasChunks, bool HasSimdModifier, bool HasMonotonicModifier, bool HasNonmonotonicModifier, bool HasOrderedClause)
Determine the schedule type using schedule and ordering clause arguments.
static bool isValidWorkshareLoopScheduleType(OMPScheduleType SchedType)
static Function * getFreshReductionFunc(Module &M)
static void raiseUserConstantDataAllocasToEntryBlock(IRBuilderBase &Builder, Function *Function)
static MDNode * getNVPTXMDNode(Function &Kernel, StringRef Name)
static FunctionCallee getKmpcForDynamicNextForType(Type *Ty, Module &M, OpenMPIRBuilder &OMPBuilder)
Returns an LLVM function to call for updating the next loop using OpenMP dynamic scheduling depending...
static bool isConflictIP(IRBuilder<>::InsertPoint IP1, IRBuilder<>::InsertPoint IP2)
Return whether IP1 and IP2 are ambiguous, i.e.
static void checkReductionInfos(ArrayRef< OpenMPIRBuilder::ReductionInfo > ReductionInfos, bool IsGPU)
static FunctionCallee getKmpcForDynamicInitForType(Type *Ty, Module &M, OpenMPIRBuilder &OMPBuilder)
Returns an LLVM function to call for initializing loop bounds using OpenMP dynamic scheduling dependi...
static cl::opt< double > UnrollThresholdFactor("openmp-ir-builder-unroll-threshold-factor", cl::Hidden, cl::desc("Factor for the unroll threshold to account for code " "simplifications still taking place"), cl::init(1.5))
static int32_t computeHeuristicUnrollFactor(CanonicalLoopInfo *CLI)
Heuristically determine the best-performant unroll factor for CLI.
static Value * emitTaskDependencies(OpenMPIRBuilder &OMPBuilder, const SmallVectorImpl< OpenMPIRBuilder::DependData > &Dependencies)
static void emitTargetCall(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, OpenMPIRBuilder::InsertPointTy AllocaIP, const OpenMPIRBuilder::TargetKernelDefaultAttrs &DefaultAttrs, const OpenMPIRBuilder::TargetKernelRuntimeAttrs &RuntimeAttrs, Value *IfCond, Function *OutlinedFn, Constant *OutlinedFnID, SmallVectorImpl< Value * > &Args, OpenMPIRBuilder::GenMapInfoCallbackTy GenMapInfoCB, SmallVector< llvm::OpenMPIRBuilder::DependData > Dependencies={}, bool HasNoWait=false)
static void workshareLoopTargetCallback(OpenMPIRBuilder *OMPIRBuilder, CanonicalLoopInfo *CLI, Value *Ident, Function &OutlinedFn, Type *ParallelTaskPtr, const SmallVector< Instruction *, 4 > &ToBeDeleted, WorksharingLoopType LoopType)
static Error emitTargetOutlinedFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, bool IsOffloadEntry, TargetRegionEntryInfo &EntryInfo, const OpenMPIRBuilder::TargetKernelDefaultAttrs &DefaultAttrs, Function *&OutlinedFn, Constant *&OutlinedFnID, SmallVectorImpl< Value * > &Inputs, OpenMPIRBuilder::TargetBodyGenCallbackTy &CBFunc, OpenMPIRBuilder::TargetGenArgAccessorsCallbackTy &ArgAccessorFuncCB)
static OpenMPIRBuilder::InsertPointTy getInsertPointAfterInstr(Instruction *I)
static void redirectAllPredecessorsTo(BasicBlock *OldTarget, BasicBlock *NewTarget, DebugLoc DL)
Redirect all edges that branch to OldTarget to NewTarget.
static std::unique_ptr< TargetMachine > createTargetMachine(Function *F, CodeGenOptLevel OptLevel)
Create the TargetMachine object to query the backend for optimization preferences.
static FunctionCallee getKmpcForStaticInitForType(Type *Ty, Module &M, OpenMPIRBuilder &OMPBuilder)
static void addBasicBlockMetadata(BasicBlock *BB, ArrayRef< Metadata * > Properties)
Attach metadata Properties to the basic block described by BB.
static cl::opt< bool > OptimisticAttributes("openmp-ir-builder-optimistic-attributes", cl::Hidden, cl::desc("Use optimistic attributes describing " "'as-if' properties of runtime calls."), cl::init(false))
static FunctionCallee getKmpcForStaticLoopForType(Type *Ty, OpenMPIRBuilder *OMPBuilder, WorksharingLoopType LoopType)
static void createTargetLoopWorkshareCall(OpenMPIRBuilder *OMPBuilder, WorksharingLoopType LoopType, BasicBlock *InsertBlock, Value *Ident, Value *LoopBodyArg, Type *ParallelTaskPtr, Value *TripCount, Function &LoopBodyFn)
static const omp::GV & getGridValue(const Triple &T, Function *Kernel)
static void addLoopMetadata(CanonicalLoopInfo *Loop, ArrayRef< Metadata * > Properties)
Attach loop metadata Properties to the loop described by Loop.
static void removeUnusedBlocksFromParent(ArrayRef< BasicBlock * > BBs)
Determine which blocks in BBs are reachable from outside and remove the ones that are not reachable f...
static void targetParallelCallback(OpenMPIRBuilder *OMPIRBuilder, Function &OutlinedFn, Function *OuterFn, BasicBlock *OuterAllocaBB, Value *Ident, Value *IfCondition, Value *NumThreads, Instruction *PrivTID, AllocaInst *PrivTIDAddr, Value *ThreadID, const SmallVector< Instruction *, 4 > &ToBeDeleted)
static void hostParallelCallback(OpenMPIRBuilder *OMPIRBuilder, Function &OutlinedFn, Function *OuterFn, Value *Ident, Value *IfCondition, Instruction *PrivTID, AllocaInst *PrivTIDAddr, const SmallVector< Instruction *, 4 > &ToBeDeleted)
FunctionAnalysisManager FAM
This file defines the Pass Instrumentation classes that provide instrumentation points into the pass ...
const SmallVectorImpl< MachineOperand > & Cond
Remove Loads Into Fake Uses
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
unsigned unsigned DefaultVal
This file implements the SmallBitVector class.
This file defines the SmallSet class.
static std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
static cl::opt< unsigned > MaxThreads("xcore-max-threads", cl::Optional, cl::desc("Maximum number of threads (for emulation thread-local storage)"), cl::Hidden, cl::value_desc("number"), cl::init(8))
static const uint32_t IV[8]
Class for arbitrary precision integers.
This class represents a conversion between pointers from one address space to another.
an instruction to allocate memory on the stack
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
PointerType * getType() const
Overload to return most specific pointer type.
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
unsigned getAddressSpace() const
Return the address space for the allocation.
std::optional< TypeSize > getAllocationSize(const DataLayout &DL) const
Get allocation size in bytes.
void setAlignment(Align Align)
const Value * getArraySize() const
Get the number of elements allocated.
A container for analyses that lazily runs them and caches their results.
bool registerPass(PassBuilderT &&PassBuilder)
Register an analysis pass with the manager.
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
Class to represent array types.
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
A function analysis which provides an AssumptionCache.
AssumptionCache run(Function &F, FunctionAnalysisManager &)
A cache of @llvm.assume calls within a function.
An instruction that atomically checks whether a specified value is in a memory location,...
static AtomicOrdering getStrongestFailureOrdering(AtomicOrdering SuccessOrdering)
Returns the strongest permitted ordering on failure, given the desired ordering on success.
std::pair< LoadInst *, AllocaInst * > EmitAtomicLoadLibcall(AtomicOrdering AO)
an instruction that atomically reads a memory location, combines it with another value,...
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ FMin
*p = minnum(old, v) minnum matches the behavior of llvm.minnum.
@ UMax
*p = old >unsigned v ? old : v
@ FMax
*p = maxnum(old, v) maxnum matches the behavior of llvm.maxnum.
@ UDecWrap
Decrement one until a minimum value or zero.
AttrBuilder & addAttribute(Attribute::AttrKind Val)
Add an attribute to the builder.
AttrBuilder & removeAttribute(Attribute::AttrKind Val)
Remove an attribute from the builder.
AttributeSet getFnAttrs() const
The function attributes are returned.
AttributeList addFnAttributes(LLVMContext &C, const AttrBuilder &B) const
Add function attribute to the list.
AttributeSet addAttributes(LLVMContext &C, AttributeSet AS) const
Add attributes to the attribute set.
AttributeSet addAttribute(LLVMContext &C, Attribute::AttrKind Kind) const
Add an argument attribute.
static Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
StringRef getValueAsString() const
Return the attribute's value as a string.
LLVM Basic Block Representation.
void replaceSuccessorsPhiUsesWith(BasicBlock *Old, BasicBlock *New)
Update all phi nodes in this basic block's successors to refer to basic block New instead of basic bl...
iterator begin()
Instruction iterator methods.
const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
reverse_iterator rbegin()
const Instruction * getFirstNonPHI() const
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
const Instruction & front() const
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="", bool Before=false)
Split the basic block into two basic blocks at the specified instruction.
const BasicBlock * getUniqueSuccessor() const
Return the successor of this block if it has a unique successor.
const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
InstListType::reverse_iterator reverse_iterator
const BasicBlock * getUniquePredecessor() const
Return the predecessor of this block if it has a unique predecessor block.
const BasicBlock * getSingleSuccessor() const
Return the successor of this block if it has a single successor.
const Function * getParent() const
Return the enclosing method, or null if none.
SymbolTableList< BasicBlock >::iterator eraseFromParent()
Unlink 'this' from the containing function and delete it.
const Instruction * getFirstNonPHIOrDbg(bool SkipPseudoOp=true) const
Returns a pointer to the first instruction in this block that is not a PHINode or a debug intrinsic,...
InstListType::iterator iterator
Instruction iterators...
LLVMContext & getContext() const
Get the context in which this basic block lives.
void moveBefore(BasicBlock *MovePos)
Unlink this basic block from its current function and insert it into the function that MovePos lives ...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
void splice(BasicBlock::iterator ToIt, BasicBlock *FromBB)
Transfer all instructions from FromBB to this basic block at ToIt.
const Instruction & back() const
const Module * getModule() const
Return the module owning the function this basic block belongs to, or nullptr if the function does no...
void removePredecessor(BasicBlock *Pred, bool KeepOneInputPHIs=false)
Update PHI nodes in this BasicBlock before removal of predecessor Pred.
Conditional or Unconditional Branch instruction.
static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
User::op_iterator arg_begin()
Return the iterator pointing to the beginning of the argument list.
Value * getArgOperand(unsigned i) const
User::op_iterator arg_end()
Return the iterator pointing to the end of the argument list.
unsigned arg_size() const
This class represents a function call, abstracting a target machine's calling convention.
Class to represented the control flow structure of an OpenMP canonical loop.
Value * getTripCount() const
Returns the llvm::Value containing the number of loop iterations.
BasicBlock * getHeader() const
The header is the entry for each iteration.
void assertOK() const
Consistency self-check.
Type * getIndVarType() const
Return the type of the induction variable (and the trip count).
BasicBlock * getBody() const
The body block is the single entry for a loop iteration and not controlled by CanonicalLoopInfo.
bool isValid() const
Returns whether this object currently represents the IR of a loop.
OpenMPIRBuilder::InsertPointTy getAfterIP() const
Return the insertion point for user code after the loop.
OpenMPIRBuilder::InsertPointTy getBodyIP() const
Return the insertion point for user code in the body.
BasicBlock * getAfter() const
The after block is intended for clean-up code such as lifetime end markers.
Function * getFunction() const
void invalidate()
Invalidate this loop.
BasicBlock * getLatch() const
Reaching the latch indicates the end of the loop body code.
OpenMPIRBuilder::InsertPointTy getPreheaderIP() const
Return the insertion point for user code before the loop.
BasicBlock * getCond() const
The condition block computes whether there is another loop iteration.
BasicBlock * getExit() const
Reaching the exit indicates no more iterations are being executed.
BasicBlock * getPreheader() const
The preheader ensures that there is only a single edge entering the loop.
Instruction * getIndVar() const
Returns the instruction representing the current logical induction variable.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ ICMP_ULT
unsigned less than
@ ICMP_ULE
unsigned less or equal
static Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static Constant * getString(LLVMContext &Context, StringRef Initializer, bool AddNull=true)
This method constructs a CDS and initializes it with a text string.
static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)
get() constructor - Return a constant with array type with an element count and element type matching...
static Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
static Constant * getPointerBitCastOrAddrSpaceCast(Constant *C, Type *Ty)
Create a BitCast or AddrSpaceCast for a pointer type depending on the address space.
static Constant * getAddrSpaceCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
This is the shared class of boolean and integer constants.
static ConstantInt * getTrue(LLVMContext &Context)
static ConstantInt * getSigned(IntegerType *Ty, int64_t V)
Return a ConstantInt with the specified value for the specified type.
static ConstantInt * getFalse(LLVMContext &Context)
static ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static Constant * get(StructType *T, ArrayRef< Constant * > V)
This is an important base class in LLVM.
static Constant * getAllOnesValue(Type *Ty)
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
DISubprogram * getSubprogram() const
Get the subprogram for this scope.
DISPFlags
Debug info subprogram flags.
Type array for a subprogram.
This class represents an Operation in the Expression.
uint64_t getNumOperands() const
A parsed version of the target data layout string in and methods for querying it.
unsigned getDefaultGlobalsAddressSpace() const
Align getABIIntegerTypeAlignment(unsigned BitWidth) const
Returns the minimum ABI-required alignment for an integer type of the specified bitwidth.
unsigned getAllocaAddrSpace() const
TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
unsigned getPointerSize(unsigned AS=0) const
Layout pointer size in bytes, rounded up to a whole number of bytes.
unsigned getIndexSizeInBits(unsigned AS) const
Size in bits of index used for address calculation in getelementptr.
TypeSize getTypeSizeInBits(Type *Ty) const
Size examples:
TypeSize getTypeStoreSize(Type *Ty) const
Returns the maximum number of bytes that may be overwritten by storing the specified type.
Align getPrefTypeAlign(Type *Ty) const
Returns the preferred stack/global alignment for the specified type.
Analysis pass which computes a DominatorTree.
DominatorTree run(Function &F, FunctionAnalysisManager &)
Run the analysis pass over a function and produce a dominator tree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
Class to represent function types.
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
const BasicBlock & getEntryBlock() const
FunctionType * getFunctionType() const
Returns the FunctionType for me.
void removeFromParent()
removeFromParent - This method unlinks 'this' from the containing module, but does not delete it.
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
uint64_t getFnAttributeAsParsedInteger(StringRef Kind, uint64_t Default=0) const
For a string attribute Kind, parse attribute as an integer.
AttributeList getAttributes() const
Return the attribute list for this Function.
const Function & getFunction() const
void setAttributes(AttributeList Attrs)
Set the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
adds the attribute to the list of attributes for the given arg.
Function::iterator insert(Function::iterator Position, BasicBlock *BB)
Insert BB in the basic block list at Position.
Type * getReturnType() const
Returns the type of the ret val.
void setCallingConv(CallingConv::ID CC)
Argument * getArg(unsigned i) const
bool hasMetadata() const
Return true if this value has any metadata attached to it.
void addMetadata(unsigned KindID, MDNode &MD)
Add a metadata attachment.
LinkageTypes getLinkage() const
void setLinkage(LinkageTypes LT)
Module * getParent()
Get the module that this global value is contained inside of...
void setDSOLocal(bool Local)
PointerType * getType() const
Global values are always pointers.
@ HiddenVisibility
The GV is hidden.
@ ProtectedVisibility
The GV is protected.
void setVisibility(VisibilityTypes V)
LinkageTypes
An enumeration for the kinds of linkage for global values.
@ PrivateLinkage
Like Internal, but omit from symbol table.
@ CommonLinkage
Tentative definitions.
@ InternalLinkage
Rename collisions when linking (static functions).
@ WeakODRLinkage
Same, but only replaced by something equivalent.
@ WeakAnyLinkage
Keep one copy of named function when linking (weak)
@ AppendingLinkage
Special purpose, only applies to global arrays.
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
Type * getValueType() const
InsertPoint - A saved insertion point.
BasicBlock * getBlock() const
bool isSet() const
Returns true if this insert point is set.
BasicBlock::iterator getPoint() const
Common base class shared among various IRBuilders.
Value * CreateNUWMul(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreatePtrDiff(Type *ElemTy, Value *LHS, Value *RHS, const Twine &Name="")
Return the i64 difference between two pointer values, dividing out the size of the pointed-to objects...
Value * CreateICmpULT(Value *LHS, Value *RHS, const Twine &Name="")
AtomicCmpXchgInst * CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New, MaybeAlign Align, AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering, SyncScope::ID SSID=SyncScope::System)
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
AllocaInst * CreateAlloca(Type *Ty, unsigned AddrSpace, Value *ArraySize=nullptr, const Twine &Name="")
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
IntegerType * getIntNTy(unsigned N)
Fetch the type representing an N-bit integer.
Value * CreateICmpSGT(Value *LHS, Value *RHS, const Twine &Name="")
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, const char *Name)
Value * CreateZExtOrTrunc(Value *V, Type *DestTy, const Twine &Name="")
Create a ZExt or Trunc from the integer value V to DestTy.
UnreachableInst * CreateUnreachable()
Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
CallInst * CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue, unsigned Alignment, Value *OffsetValue=nullptr)
Create an assume intrinsic call that represents an alignment assumption on the provided pointer.
Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
BasicBlock::iterator GetInsertPoint() const
Value * CreateStructGEP(Type *Ty, Value *Ptr, unsigned Idx, const Twine &Name="")
IntegerType * getIndexTy(const DataLayout &DL, unsigned AddrSpace)
Fetch the type of an integer that should be used to index GEP operations within AddressSpace.
Value * CreateSExt(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Value * CreateNSWAdd(Value *LHS, Value *RHS, const Twine &Name="")
BasicBlock * GetInsertBlock() const
void SetCurrentDebugLocation(DebugLoc L)
Set location information used by debugging information.
IntegerType * getInt64Ty()
Fetch the type representing a 64-bit integer.
Value * CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="")
Value * CreatePointerBitCastOrAddrSpaceCast(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateUDiv(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateNUWAdd(Value *LHS, Value *RHS, const Twine &Name="")
IntegerType * getInt16Ty()
Fetch the type representing a 16-bit integer.
Value * CreateGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
ConstantInt * getInt64(uint64_t C)
Get a constant 64-bit value.
Value * CreateNeg(Value *V, const Twine &Name="", bool HasNSW=false)
InsertPoint saveIP() const
Returns the current insert point.
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
Value * CreateCmp(CmpInst::Predicate Pred, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
SwitchInst * CreateSwitch(Value *V, BasicBlock *Dest, unsigned NumCases=10, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a switch instruction with the specified value, default dest, and with a hint for the number of...
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
InstTy * Insert(InstTy *I, const Twine &Name="") const
Insert and return the specified instruction.
DebugLoc getCurrentDebugLocation() const
Get location information used by debugging information.
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
ConstantInt * getIntN(unsigned N, uint64_t C)
Get a constant N-bit value, zero extended or truncated from a 64-bit value.
BranchInst * CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a conditional 'br Cond, TrueDest, FalseDest' instruction.
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
LLVMContext & getContext() const
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
ReturnInst * CreateRetVoid()
Create a 'ret void' instruction.
Value * CreateConstInBoundsGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0, unsigned Idx1, const Twine &Name="")
Value * CreateConstInBoundsGEP2_64(Type *Ty, Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name="")
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateExactUDiv(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateIsNotNull(Value *Arg, const Twine &Name="")
Return a boolean value testing if Arg != 0.
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
AtomicRMWInst * CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, Value *Val, MaybeAlign Align, AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
BranchInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
void ClearInsertionPoint()
Clear the insertion point: created instructions will not be inserted into a block.
Value * CreateICmpSLT(Value *LHS, Value *RHS, const Twine &Name="")
ConstantInt * getInt16(uint16_t C)
Get a constant 16-bit value.
Value * CreateICmpUGE(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
void restoreIP(InsertPoint IP)
Sets the current insert point to a previously-saved location.
Value * CreateIsNull(Value *Arg, const Twine &Name="")
Return a boolean value testing if Arg == 0.
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Type * getVoidTy()
Fetch the type representing void.
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)
Value * CreateAShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name="")
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
Value * CreateURem(Value *LHS, Value *RHS, const Twine &Name="")
CallInst * CreateMemCpy(Value *Dst, MaybeAlign DstAlign, Value *Src, MaybeAlign SrcAlign, uint64_t Size, bool isVolatile=false, MDNode *TBAATag=nullptr, MDNode *TBAAStructTag=nullptr, MDNode *ScopeTag=nullptr, MDNode *NoAliasTag=nullptr)
Create and insert a memcpy between the specified pointers.
Value * CreateSExtOrTrunc(Value *V, Type *DestTy, const Twine &Name="")
Create a SExt or Trunc from the integer value V to DestTy.
Value * CreateAddrSpaceCast(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
GlobalVariable * CreateGlobalString(StringRef Str, const Twine &Name="", unsigned AddressSpace=0, Module *M=nullptr, bool AddNull=true)
Make a new global variable with initializer type i8*.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
void removeFromParent()
This method unlinks 'this' from the containing basic block, but does not delete it.
void moveBeforePreserving(Instruction *MovePos)
Perform a moveBefore operation, while signalling that the caller intends to preserve the original ord...
unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY
Return the specified successor. This instruction must be a terminator.
void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
void insertAfter(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately after the specified instruction.
Class to represent integer types.
static IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
Value * getPointerOperand()
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this load instruction.
Align getAlign() const
Return the alignment of the access that is being performed.
Analysis pass that exposes the LoopInfo for a function.
LoopInfo run(Function &F, FunctionAnalysisManager &AM)
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
This class represents a loop nest and can be used to query its properties.
Represents a single loop in the control flow graph.
MDNode * createCallbackEncoding(unsigned CalleeArgNo, ArrayRef< int > Arguments, bool VarArgsArePassed)
Return metadata describing a callback (see llvm::AbstractCallSite).
void replaceOperandWith(unsigned I, Metadata *New)
Replace a specific operand.
static MDTuple * getDistinct(LLVMContext &Context, ArrayRef< Metadata * > MDs)
const MDOperand & getOperand(unsigned I) const
ArrayRef< MDOperand > operands() const
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static MDString * get(LLVMContext &Context, StringRef Str)
This class implements a map that also provides access to all stored values in a deterministic order.
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
A Module instance is used to store all the information related to an LLVM module.
NamedMDNode * getNamedMetadata(StringRef Name) const
Return the first NamedMDNode in the module with the specified name.
LLVMContext & getContext() const
Get the global data context.
Function * getFunction(StringRef Name) const
Look up the specified function in the module symbol table.
StringRef getName() const
Get a short "name" for the module.
const std::string & getTargetTriple() const
Get the target triple which is a string describing the target host.
iterator_range< global_iterator > globals()
const FunctionListType & getFunctionList() const
Get the Module's list of functions (constant).
GlobalVariable * getGlobalVariable(StringRef Name) const
Look up the specified global variable in the module symbol table.
GlobalValue * getNamedValue(StringRef Name) const
Return the global value in the module with the specified name, of arbitrary type.
NamedMDNode * getOrInsertNamedMetadata(StringRef Name)
Return the named MDNode in the module with the specified name.
const GlobalVariable * getNamedGlobal(StringRef Name) const
Return the global variable in the module with the specified name, of arbitrary type.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
iterator_range< op_iterator > operands()
void addOperand(MDNode *M)
Device global variable entries info.
Target region entries info.
Base class of the entries info.
@ OffloadingEntryInfoTargetRegion
Entry is a target region.
@ OffloadingEntryInfoDeviceGlobalVar
Entry is a declare target variable.
OMPTargetDeviceClauseKind
Kind of device clause for declare target variables and functions NOTE: Currently not used as a part o...
@ OMPTargetDeviceClauseAny
The target is marked for all devices.
void registerDeviceGlobalVarEntryInfo(StringRef VarName, Constant *Addr, int64_t VarSize, OMPTargetGlobalVarEntryKind Flags, GlobalValue::LinkageTypes Linkage)
Register device global variable entry.
void initializeDeviceGlobalVarEntryInfo(StringRef Name, OMPTargetGlobalVarEntryKind Flags, unsigned Order)
Initialize device global variable entry.
void actOnDeviceGlobalVarEntriesInfo(const OffloadDeviceGlobalVarEntryInfoActTy &Action)
OMPTargetRegionEntryKind
Kind of the target registry entry.
@ OMPTargetRegionEntryTargetRegion
Mark the entry as target region.
void getTargetRegionEntryFnName(SmallVectorImpl< char > &Name, const TargetRegionEntryInfo &EntryInfo)
bool hasTargetRegionEntryInfo(TargetRegionEntryInfo EntryInfo, bool IgnoreAddressId=false) const
Return true if a target region entry with the provided information exists.
void registerTargetRegionEntryInfo(TargetRegionEntryInfo EntryInfo, Constant *Addr, Constant *ID, OMPTargetRegionEntryKind Flags)
Register target region entry.
void actOnTargetRegionEntriesInfo(const OffloadTargetRegionEntryInfoActTy &Action)
unsigned size() const
Return number of entries defined so far.
void initializeTargetRegionEntryInfo(const TargetRegionEntryInfo &EntryInfo, unsigned Order)
Initialize target region entry.
OMPTargetGlobalVarEntryKind
Kind of the global variable entry..
@ OMPTargetGlobalVarEntryEnter
Mark the entry as a declare target enter.
@ OMPTargetGlobalRegisterRequires
Mark the entry as a register requires global.
@ OMPTargetGlobalVarEntryIndirect
Mark the entry as a declare target indirect global.
@ OMPTargetGlobalVarEntryLink
Mark the entry as a to declare target link.
@ OMPTargetGlobalVarEntryTo
Mark the entry as a to declare target.
bool hasDeviceGlobalVarEntryInfo(StringRef VarName) const
Checks if the variable with the given name has been registered already.
bool empty() const
Return true if a there are no entries defined.
std::optional< bool > IsTargetDevice
Flag to define whether to generate code for the role of the OpenMP host (if set to false) or device (...
void setGridValue(omp::GV G)
StringRef separator() const
int64_t getRequiresFlags() const
Returns requires directive clauses as flags compatible with those expected by libomptarget.
StringRef firstSeparator() const
std::optional< bool > EmitLLVMUsedMetaInfo
Flag for specifying if LLVMUsed information should be emitted.
omp::GV getGridValue() const
void setHasRequiresReverseOffload(bool Value)
bool hasRequiresUnifiedSharedMemory() const
void setHasRequiresUnifiedSharedMemory(bool Value)
bool hasRequiresDynamicAllocators() const
bool openMPOffloadMandatory() const
void setHasRequiresUnifiedAddress(bool Value)
bool isTargetDevice() const
void setHasRequiresDynamicAllocators(bool Value)
void setEmitLLVMUsed(bool Value=true)
bool hasRequiresReverseOffload() const
bool hasRequiresFlags() const
bool hasRequiresUnifiedAddress() const
Struct that keeps the information that should be kept throughout a 'target data' region.
An interface to create LLVM-IR for OpenMP directives.
InsertPointOrErrorTy createOrderedThreadsSimd(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, bool IsThreads)
Generator for '#omp ordered [threads | simd]'.
Constant * getOrCreateIdent(Constant *SrcLocStr, uint32_t SrcLocStrSize, omp::IdentFlag Flags=omp::IdentFlag(0), unsigned Reserve2Flags=0)
Return an ident_t* encoding the source location SrcLocStr and Flags.
FunctionCallee getOrCreateRuntimeFunction(Module &M, omp::RuntimeFunction FnID)
Return the function declaration for the runtime function with FnID.
InsertPointOrErrorTy createCancel(const LocationDescription &Loc, Value *IfCondition, omp::Directive CanceledDirective)
Generator for '#omp cancel'.
ReductionGenCBKind
Enum class for the RedctionGen CallBack type to be used.
CanonicalLoopInfo * collapseLoops(DebugLoc DL, ArrayRef< CanonicalLoopInfo * > Loops, InsertPointTy ComputeIP)
Collapse a loop nest into a single loop.
InsertPointOrErrorTy createTask(const LocationDescription &Loc, InsertPointTy AllocaIP, BodyGenCallbackTy BodyGenCB, bool Tied=true, Value *Final=nullptr, Value *IfCondition=nullptr, SmallVector< DependData > Dependencies={}, bool Mergeable=false, Value *EventHandle=nullptr, Value *Priority=nullptr)
Generator for #omp task
void createTaskyield(const LocationDescription &Loc)
Generator for '#omp taskyield'.
std::function< Error(InsertPointTy CodeGenIP)> FinalizeCallbackTy
Callback type for variable finalization (think destructors).
void emitBranch(BasicBlock *Target)
InsertPointTy createAtomicWrite(const LocationDescription &Loc, AtomicOpValue &X, Value *Expr, AtomicOrdering AO)
Emit atomic write for : X = Expr — Only Scalar data types.
static void writeThreadBoundsForKernel(const Triple &T, Function &Kernel, int32_t LB, int32_t UB)
static TargetRegionEntryInfo getTargetEntryUniqueInfo(FileIdentifierInfoCallbackTy CallBack, StringRef ParentName="")
Creates a unique info for a target entry when provided a filename and line number from.
void emitTaskwaitImpl(const LocationDescription &Loc)
Generate a taskwait runtime call.
Constant * registerTargetRegionFunction(TargetRegionEntryInfo &EntryInfo, Function *OutlinedFunction, StringRef EntryFnName, StringRef EntryFnIDName)
Registers the given function and sets up the attribtues of the function Returns the FunctionID.
GlobalVariable * emitKernelExecutionMode(StringRef KernelName, omp::OMPTgtExecModeFlags Mode)
Emit the kernel execution mode.
void initialize()
Initialize the internal state, this will put structures types and potentially other helpers into the ...
void createTargetDeinit(const LocationDescription &Loc, int32_t TeamsReductionDataSize=0, int32_t TeamsReductionBufferLength=1024)
Create a runtime call for kmpc_target_deinit.
InsertPointOrErrorTy createTaskgroup(const LocationDescription &Loc, InsertPointTy AllocaIP, BodyGenCallbackTy BodyGenCB)
Generator for the taskgroup construct.
void loadOffloadInfoMetadata(Module &M)
Loads all the offload entries information from the host IR metadata.
InsertPointOrErrorTy emitTargetTask(TargetTaskBodyCallbackTy TaskBodyCB, Value *DeviceID, Value *RTLoc, OpenMPIRBuilder::InsertPointTy AllocaIP, const SmallVector< llvm::OpenMPIRBuilder::DependData > &Dependencies, bool HasNoWait)
Generate a target-task for the target construct.
void unrollLoopFull(DebugLoc DL, CanonicalLoopInfo *Loop)
Fully unroll a loop.
void emitFlush(const LocationDescription &Loc)
Generate a flush runtime call.
static std::pair< int32_t, int32_t > readThreadBoundsForKernel(const Triple &T, Function &Kernel)
}
OpenMPIRBuilderConfig Config
The OpenMPIRBuilder Configuration.
CallInst * createOMPInteropDestroy(const LocationDescription &Loc, Value *InteropVar, Value *Device, Value *NumDependences, Value *DependenceAddress, bool HaveNowaitClause)
Create a runtime call for __tgt_interop_destroy.
InsertPointTy createAtomicRead(const LocationDescription &Loc, AtomicOpValue &X, AtomicOpValue &V, AtomicOrdering AO)
Emit atomic Read for : V = X — Only Scalar data types.
Error emitIfClause(Value *Cond, BodyGenCallbackTy ThenGen, BodyGenCallbackTy ElseGen, InsertPointTy AllocaIP={})
Emits code for OpenMP 'if' clause using specified BodyGenCallbackTy Here is the logic: if (Cond) { Th...
std::function< void(EmitMetadataErrorKind, TargetRegionEntryInfo)> EmitMetadataErrorReportFunctionTy
Callback function type.
void emitUsed(StringRef Name, ArrayRef< llvm::WeakTrackingVH > List)
Emit the llvm.used metadata.
InsertPointOrErrorTy createSingle(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, bool IsNowait, ArrayRef< llvm::Value * > CPVars={}, ArrayRef< llvm::Function * > CPFuncs={})
Generator for '#omp single'.
InsertPointOrErrorTy createTeams(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, Value *NumTeamsLower=nullptr, Value *NumTeamsUpper=nullptr, Value *ThreadLimit=nullptr, Value *IfExpr=nullptr)
Generator for #omp teams
std::forward_list< CanonicalLoopInfo > LoopInfos
Collection of owned canonical loop objects that eventually need to be free'd.
void createTaskwait(const LocationDescription &Loc)
Generator for '#omp taskwait'.
CanonicalLoopInfo * createLoopSkeleton(DebugLoc DL, Value *TripCount, Function *F, BasicBlock *PreInsertBefore, BasicBlock *PostInsertBefore, const Twine &Name={})
Create the control flow structure of a canonical OpenMP loop.
std::string createPlatformSpecificName(ArrayRef< StringRef > Parts) const
Get the create a name using the platform specific separators.
FunctionCallee createDispatchNextFunction(unsigned IVSize, bool IVSigned)
Returns __kmpc_dispatch_next_* runtime function for the specified size IVSize and sign IVSigned.
static void getKernelArgsVector(TargetKernelArgs &KernelArgs, IRBuilderBase &Builder, SmallVector< Value * > &ArgsVector)
Create the kernel args vector used by emitTargetKernel.
void unrollLoopHeuristic(DebugLoc DL, CanonicalLoopInfo *Loop)
Fully or partially unroll a loop.
InsertPointOrErrorTy createParallel(const LocationDescription &Loc, InsertPointTy AllocaIP, BodyGenCallbackTy BodyGenCB, PrivatizeCallbackTy PrivCB, FinalizeCallbackTy FiniCB, Value *IfCondition, Value *NumThreads, omp::ProcBindKind ProcBind, bool IsCancellable)
Generator for '#omp parallel'.
omp::OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position)
Get OMP_MAP_MEMBER_OF flag with extra bits reserved based on the position given.
void addAttributes(omp::RuntimeFunction FnID, Function &Fn)
Add attributes known for FnID to Fn.
Module & M
The underlying LLVM-IR module.
StringMap< Constant * > SrcLocStrMap
Map to remember source location strings.
void createMapperAllocas(const LocationDescription &Loc, InsertPointTy AllocaIP, unsigned NumOperands, struct MapperAllocas &MapperAllocas)
Create the allocas instruction used in call to mapper functions.
Constant * getOrCreateSrcLocStr(StringRef LocStr, uint32_t &SrcLocStrSize)
Return the (LLVM-IR) string describing the source location LocStr.
void addOutlineInfo(OutlineInfo &&OI)
Add a new region that will be outlined later.
Error emitTargetRegionFunction(TargetRegionEntryInfo &EntryInfo, FunctionGenCallback &GenerateFunctionCallback, bool IsOffloadEntry, Function *&OutlinedFn, Constant *&OutlinedFnID)
Create a unique name for the entry function using the source location information of the current targ...
FunctionCallee createDispatchFiniFunction(unsigned IVSize, bool IVSigned)
Returns __kmpc_dispatch_fini_* runtime function for the specified size IVSize and sign IVSigned.
void unrollLoopPartial(DebugLoc DL, CanonicalLoopInfo *Loop, int32_t Factor, CanonicalLoopInfo **UnrolledCLI)
Partially unroll a loop.
void emitTaskyieldImpl(const LocationDescription &Loc)
Generate a taskyield runtime call.
void emitMapperCall(const LocationDescription &Loc, Function *MapperFunc, Value *SrcLocInfo, Value *MaptypesArg, Value *MapnamesArg, struct MapperAllocas &MapperAllocas, int64_t DeviceID, unsigned NumOperands)
Create the call for the target mapper function.
InsertPointTy createAtomicCompare(const LocationDescription &Loc, AtomicOpValue &X, AtomicOpValue &V, AtomicOpValue &R, Value *E, Value *D, AtomicOrdering AO, omp::OMPAtomicCompareOp Op, bool IsXBinopExpr, bool IsPostfixUpdate, bool IsFailOnly)
Emit atomic compare for constructs: — Only scalar data types cond-expr-stmt: x = x ordop expr ?...
InsertPointOrErrorTy createAtomicCapture(const LocationDescription &Loc, InsertPointTy AllocaIP, AtomicOpValue &X, AtomicOpValue &V, Value *Expr, AtomicOrdering AO, AtomicRMWInst::BinOp RMWOp, AtomicUpdateCallbackTy &UpdateOp, bool UpdateExpr, bool IsPostfixUpdate, bool IsXBinopExpr)
Emit atomic update for constructs: — Only Scalar data types V = X; X = X BinOp Expr ,...
InsertPointTy createOrderedDepend(const LocationDescription &Loc, InsertPointTy AllocaIP, unsigned NumLoops, ArrayRef< llvm::Value * > StoreValues, const Twine &Name, bool IsDependSource)
Generator for '#omp ordered depend (source | sink)'.
InsertPointTy createCopyinClauseBlocks(InsertPointTy IP, Value *MasterAddr, Value *PrivateAddr, llvm::IntegerType *IntPtrTy, bool BranchtoEnd=true)
Generate conditional branch and relevant BasicBlocks through which private threads copy the 'copyin' ...
void emitOffloadingArrays(InsertPointTy AllocaIP, InsertPointTy CodeGenIP, MapInfosTy &CombinedInfo, TargetDataInfo &Info, bool IsNonContiguous=false, function_ref< void(unsigned int, Value *)> DeviceAddrCB=nullptr, function_ref< Value *(unsigned int)> CustomMapperCB=nullptr)
Emit the arrays used to pass the captures and map information to the offloading runtime library.
SmallVector< FinalizationInfo, 8 > FinalizationStack
The finalization stack made up of finalize callbacks currently in-flight, wrapped into FinalizationIn...
std::vector< CanonicalLoopInfo * > tileLoops(DebugLoc DL, ArrayRef< CanonicalLoopInfo * > Loops, ArrayRef< Value * > TileSizes)
Tile a loop nest.
CallInst * createOMPInteropInit(const LocationDescription &Loc, Value *InteropVar, omp::OMPInteropType InteropType, Value *Device, Value *NumDependences, Value *DependenceAddress, bool HaveNowaitClause)
Create a runtime call for __tgt_interop_init.
void finalize(Function *Fn=nullptr)
Finalize the underlying module, e.g., by outlining regions.
SmallVector< OutlineInfo, 16 > OutlineInfos
Collection of regions that need to be outlined during finalization.
Function * getOrCreateRuntimeFunctionPtr(omp::RuntimeFunction FnID)
InsertPointTy createTargetInit(const LocationDescription &Loc, const llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs)
The omp target interface.
const Triple T
The target triple of the underlying module.
DenseMap< std::pair< Constant *, uint64_t >, Constant * > IdentMap
Map to remember existing ident_t*.
CallInst * createOMPFree(const LocationDescription &Loc, Value *Addr, Value *Allocator, std::string Name="")
Create a runtime call for kmpc_free.
FunctionCallee createForStaticInitFunction(unsigned IVSize, bool IVSigned, bool IsGPUDistribute)
Returns __kmpc_for_static_init_* runtime function for the specified size IVSize and sign IVSigned.
CallInst * createOMPAlloc(const LocationDescription &Loc, Value *Size, Value *Allocator, std::string Name="")
Create a runtime call for kmpc_Alloc.
void emitNonContiguousDescriptor(InsertPointTy AllocaIP, InsertPointTy CodeGenIP, MapInfosTy &CombinedInfo, TargetDataInfo &Info)
Emit an array of struct descriptors to be assigned to the offload args.
InsertPointOrErrorTy createSection(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB)
Generator for '#omp section'.
void emitBlock(BasicBlock *BB, Function *CurFn, bool IsFinished=false)
Value * getOrCreateThreadID(Value *Ident)
Return the current thread ID.
void emitOffloadingArraysAndArgs(InsertPointTy AllocaIP, InsertPointTy CodeGenIP, TargetDataInfo &Info, TargetDataRTArgs &RTArgs, MapInfosTy &CombinedInfo, bool IsNonContiguous=false, bool ForEndCall=false, function_ref< void(unsigned int, Value *)> DeviceAddrCB=nullptr, function_ref< Value *(unsigned int)> CustomMapperCB=nullptr)
Allocates memory for and populates the arrays required for offloading (offload_{baseptrs|ptrs|mappers...
InsertPointOrErrorTy createMaster(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB)
Generator for '#omp master'.
Error emitCancelationCheckImpl(Value *CancelFlag, omp::Directive CanceledDirective, FinalizeCallbackTy ExitCB={})
Generate control flow and cleanup for cancellation.
InsertPointOrErrorTy emitKernelLaunch(const LocationDescription &Loc, Value *OutlinedFnID, EmitFallbackCallbackTy EmitTargetCallFallbackCB, TargetKernelArgs &Args, Value *DeviceID, Value *RTLoc, InsertPointTy AllocaIP)
Generate a target region entry call and host fallback call.
InsertPointOrErrorTy createTarget(const LocationDescription &Loc, bool IsOffloadEntry, OpenMPIRBuilder::InsertPointTy AllocaIP, OpenMPIRBuilder::InsertPointTy CodeGenIP, TargetRegionEntryInfo &EntryInfo, const TargetKernelDefaultAttrs &DefaultAttrs, const TargetKernelRuntimeAttrs &RuntimeAttrs, Value *IfCond, SmallVectorImpl< Value * > &Inputs, GenMapInfoCallbackTy GenMapInfoCB, TargetBodyGenCallbackTy BodyGenCB, TargetGenArgAccessorsCallbackTy ArgAccessorFuncCB, SmallVector< DependData > Dependencies={}, bool HasNowait=false)
Generator for '#omp target'.
StringMap< GlobalVariable *, BumpPtrAllocator > InternalVars
An ordered map of auto-generated variables to their unique names.
GlobalVariable * getOrCreateInternalVariable(Type *Ty, const StringRef &Name, unsigned AddressSpace=0)
Gets (if variable with the given name already exist) or creates internal global variable with the spe...
InsertPointOrErrorTy createReductionsGPU(const LocationDescription &Loc, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, ArrayRef< ReductionInfo > ReductionInfos, bool IsNoWait=false, bool IsTeamsReduction=false, bool HasDistribute=false, ReductionGenCBKind ReductionGenCBKind=ReductionGenCBKind::MLIR, std::optional< omp::GV > GridValue={}, unsigned ReductionBufNum=1024, Value *SrcLocInfo=nullptr)
Design of OpenMP reductions on the GPU.
FunctionCallee createDispatchInitFunction(unsigned IVSize, bool IVSigned)
Returns __kmpc_dispatch_init_* runtime function for the specified size IVSize and sign IVSigned.
Function * emitUserDefinedMapper(function_ref< MapInfosTy &(InsertPointTy CodeGenIP, llvm::Value *PtrPHI, llvm::Value *BeginArg)> PrivAndGenMapInfoCB, llvm::Type *ElemTy, StringRef FuncName, function_ref< bool(unsigned int, Function **)> CustomMapperCB=nullptr)
Emit the user-defined mapper function.
CallInst * createOMPInteropUse(const LocationDescription &Loc, Value *InteropVar, Value *Device, Value *NumDependences, Value *DependenceAddress, bool HaveNowaitClause)
Create a runtime call for __tgt_interop_use.
IRBuilder<>::InsertPoint InsertPointTy
Type used throughout for insertion points.
InsertPointOrErrorTy createReductions(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< ReductionInfo > ReductionInfos, ArrayRef< bool > IsByRef, bool IsNoWait=false)
Generator for '#omp reduction'.
GlobalVariable * createOffloadMapnames(SmallVectorImpl< llvm::Constant * > &Names, std::string VarName)
Create the global variable holding the offload names information.
std::function< Expected< Function * >(StringRef FunctionName)> FunctionGenCallback
Functions used to generate a function with the given name.
static void writeTeamsForKernel(const Triple &T, Function &Kernel, int32_t LB, int32_t UB)
InsertPointOrErrorTy createBarrier(const LocationDescription &Loc, omp::Directive Kind, bool ForceSimpleCall=false, bool CheckCancelFlag=true)
Emitter methods for OpenMP directives.
void setCorrectMemberOfFlag(omp::OpenMPOffloadMappingFlags &Flags, omp::OpenMPOffloadMappingFlags MemberOfFlag)
Given an initial flag set, this function modifies it to contain the passed in MemberOfFlag generated ...
Constant * getOrCreateDefaultSrcLocStr(uint32_t &SrcLocStrSize)
Return the (LLVM-IR) string describing the default source location.
InsertPointOrErrorTy createCritical(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, StringRef CriticalName, Value *HintInst)
Generator for '#omp critical'.
void createOffloadEntry(Constant *ID, Constant *Addr, uint64_t Size, int32_t Flags, GlobalValue::LinkageTypes, StringRef Name="")
Creates offloading entry for the provided entry ID ID, address Addr, size Size, and flags Flags.
static unsigned getOpenMPDefaultSimdAlign(const Triple &TargetTriple, const StringMap< bool > &Features)
Get the default alignment value for given target.
unsigned getFlagMemberOffset()
Get the offset of the OMP_MAP_MEMBER_OF field.
void createOffloadEntriesAndInfoMetadata(EmitMetadataErrorReportFunctionTy &ErrorReportFunction)
void applySimd(CanonicalLoopInfo *Loop, MapVector< Value *, Value * > AlignedVars, Value *IfCond, omp::OrderKind Order, ConstantInt *Simdlen, ConstantInt *Safelen)
Add metadata to simd-ize a loop.
bool isLastFinalizationInfoCancellable(omp::Directive DK)
Return true if the last entry in the finalization stack is of kind DK and cancellable.
InsertPointTy emitTargetKernel(const LocationDescription &Loc, InsertPointTy AllocaIP, Value *&Return, Value *Ident, Value *DeviceID, Value *NumTeams, Value *NumThreads, Value *HostPtr, ArrayRef< Value * > KernelArgs)
Generate a target region entry call.
GlobalVariable * createOffloadMaptypes(SmallVectorImpl< uint64_t > &Mappings, std::string VarName)
Create the global variable holding the offload mappings information.
CallInst * createCachedThreadPrivate(const LocationDescription &Loc, llvm::Value *Pointer, llvm::ConstantInt *Size, const llvm::Twine &Name=Twine(""))
Create a runtime call for kmpc_threadprivate_cached.
IRBuilder Builder
The LLVM-IR Builder used to create IR.
GlobalValue * createGlobalFlag(unsigned Value, StringRef Name)
Create a hidden global flag Name in the module with initial value Value.
InsertPointOrErrorTy applyWorkshareLoop(DebugLoc DL, CanonicalLoopInfo *CLI, InsertPointTy AllocaIP, bool NeedsBarrier, llvm::omp::ScheduleKind SchedKind=llvm::omp::OMP_SCHEDULE_Default, Value *ChunkSize=nullptr, bool HasSimdModifier=false, bool HasMonotonicModifier=false, bool HasNonmonotonicModifier=false, bool HasOrderedClause=false, omp::WorksharingLoopType LoopType=omp::WorksharingLoopType::ForStaticLoop)
Modifies the canonical loop to be a workshare loop.
void emitOffloadingArraysArgument(IRBuilderBase &Builder, OpenMPIRBuilder::TargetDataRTArgs &RTArgs, OpenMPIRBuilder::TargetDataInfo &Info, bool ForEndCall=false)
Emit the arguments to be passed to the runtime library based on the arrays of base pointers,...
InsertPointOrErrorTy createMasked(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, Value *Filter)
Generator for '#omp masked'.
Expected< CanonicalLoopInfo * > createCanonicalLoop(const LocationDescription &Loc, LoopBodyGenCallbackTy BodyGenCB, Value *TripCount, const Twine &Name="loop")
Generator for the control flow structure of an OpenMP canonical loop.
Value * getSizeInBytes(Value *BasePtr)
Computes the size of type in bytes.
FunctionCallee createDispatchDeinitFunction()
Returns __kmpc_dispatch_deinit runtime function.
void registerTargetGlobalVariable(OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind CaptureClause, OffloadEntriesInfoManager::OMPTargetDeviceClauseKind DeviceClause, bool IsDeclaration, bool IsExternallyVisible, TargetRegionEntryInfo EntryInfo, StringRef MangledName, std::vector< GlobalVariable * > &GeneratedRefs, bool OpenMPSIMD, std::vector< Triple > TargetTriple, std::function< Constant *()> GlobalInitializer, std::function< GlobalValue::LinkageTypes()> VariableLinkage, Type *LlvmPtrTy, Constant *Addr)
Registers a target variable for device or host.
InsertPointOrErrorTy createTargetData(const LocationDescription &Loc, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Value *DeviceID, Value *IfCond, TargetDataInfo &Info, GenMapInfoCallbackTy GenMapInfoCB, omp::RuntimeFunction *MapperFunc=nullptr, function_ref< InsertPointOrErrorTy(InsertPointTy CodeGenIP, BodyGenTy BodyGenType)> BodyGenCB=nullptr, function_ref< void(unsigned int, Value *)> DeviceAddrCB=nullptr, function_ref< Value *(unsigned int)> CustomMapperCB=nullptr, Value *SrcLocInfo=nullptr)
Generator for '#omp target data'.
BodyGenTy
Type of BodyGen to use for region codegen.
InsertPointOrErrorTy createAtomicUpdate(const LocationDescription &Loc, InsertPointTy AllocaIP, AtomicOpValue &X, Value *Expr, AtomicOrdering AO, AtomicRMWInst::BinOp RMWOp, AtomicUpdateCallbackTy &UpdateOp, bool IsXBinopExpr)
Emit atomic update for constructs: X = X BinOp Expr ,or X = Expr BinOp X For complex Operations: X = ...
SmallVector< llvm::Function *, 16 > ConstantAllocaRaiseCandidates
A collection of candidate target functions that's constant allocas will attempt to be raised on a cal...
OffloadEntriesInfoManager OffloadInfoManager
Info manager to keep track of target regions.
static std::pair< int32_t, int32_t > readTeamBoundsForKernel(const Triple &T, Function &Kernel)
Read/write a bounds on teams for Kernel.
std::function< std::tuple< std::string, uint64_t >()> FileIdentifierInfoCallbackTy
const std::string ompOffloadInfoName
OMP Offload Info Metadata name string.
Expected< InsertPointTy > InsertPointOrErrorTy
Type used to represent an insertion point or an error value.
InsertPointTy createCopyPrivate(const LocationDescription &Loc, llvm::Value *BufSize, llvm::Value *CpyBuf, llvm::Value *CpyFn, llvm::Value *DidIt)
Generator for __kmpc_copyprivate.
InsertPointOrErrorTy createSections(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< StorableBodyGenCallbackTy > SectionCBs, PrivatizeCallbackTy PrivCB, FinalizeCallbackTy FiniCB, bool IsCancellable, bool IsNowait)
Generator for '#omp sections'.
bool updateToLocation(const LocationDescription &Loc)
Update the internal location to Loc.
void createFlush(const LocationDescription &Loc)
Generator for '#omp flush'.
Constant * getAddrOfDeclareTargetVar(OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind CaptureClause, OffloadEntriesInfoManager::OMPTargetDeviceClauseKind DeviceClause, bool IsDeclaration, bool IsExternallyVisible, TargetRegionEntryInfo EntryInfo, StringRef MangledName, std::vector< GlobalVariable * > &GeneratedRefs, bool OpenMPSIMD, std::vector< Triple > TargetTriple, Type *LlvmPtrTy, std::function< Constant *()> GlobalInitializer, std::function< GlobalValue::LinkageTypes()> VariableLinkage)
Retrieve (or create if non-existent) the address of a declare target variable, used in conjunction wi...
EmitMetadataErrorKind
The kind of errors that can occur when emitting the offload entries and metadata.
@ EMIT_MD_DECLARE_TARGET_ERROR
@ EMIT_MD_GLOBAL_VAR_LINK_ERROR
@ EMIT_MD_TARGET_REGION_ERROR
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
Pseudo-analysis pass that exposes the PassInstrumentation to pass managers.
Class to represent pointers.
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
Analysis pass that exposes the ScalarEvolution for a function.
ScalarEvolution run(Function &F, FunctionAnalysisManager &AM)
The main scalar evolution driver.
A vector that has set insertion semantics.
bool remove_if(UnaryPredicate P)
Remove items from the set vector based on a predicate function.
bool empty() const
Determine if the SetVector is empty or not.
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
bool test(unsigned Idx) const
bool all() const
Returns true if all bits are set.
bool any() const
Returns true if any bit is set.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void append(StringRef RHS)
Append from a StringRef.
StringRef str() const
Explicit conversion to StringRef.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
void setAlignment(Align Align)
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this store instruction.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
ValueTy lookup(StringRef Key) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
StringRef - Represent a constant reference to a string, i.e.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
constexpr bool empty() const
empty - Check if the string is empty.
constexpr size_t size() const
size - Get the string size.
size_t count(char C) const
Return the number of occurrences of C in the string.
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
Class to represent struct types.
static StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
static StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
void addCase(ConstantInt *OnVal, BasicBlock *Dest)
Add an entry to the switch instruction.
Analysis pass providing the TargetTransformInfo.
Result run(const Function &F, FunctionAnalysisManager &)
Analysis pass providing the TargetLibraryInfo.
Target - Wrapper for Target specific information.
TargetMachine * createTargetMachine(StringRef TT, StringRef CPU, StringRef Features, const TargetOptions &Options, std::optional< Reloc::Model > RM, std::optional< CodeModel::Model > CM=std::nullopt, CodeGenOptLevel OL=CodeGenOptLevel::Default, bool JIT=false) const
createTargetMachine - Create a target specific machine implementation for the specified Triple.
Triple - Helper class for working with autoconf configuration names.
bool isPPC() const
Tests whether the target is PowerPC (32- or 64-bit LE or BE).
bool isX86() const
Tests whether the target is x86 (32- or 64-bit).
bool isWasm() const
Tests whether the target is wasm (32- and 64-bit).
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
std::string str() const
Return the twine contents as a std::string.
The instances of the Type class are immutable: once they are created, they are never changed.
unsigned getIntegerBitWidth() const
Type * getStructElementType(unsigned N) const
bool isPointerTy() const
True if this is an instance of PointerType.
static IntegerType * getInt1Ty(LLVMContext &C)
unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
static Type * getVoidTy(LLVMContext &C)
bool isStructTy() const
True if this is an instance of StructType.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
static IntegerType * getInt32Ty(LLVMContext &C)
static IntegerType * getInt64Ty(LLVMContext &C)
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isVoidTy() const
Return true if this is 'void'.
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
This function has undefined behavior.
Produce an estimate of the unrolled cost of the specified loop.
bool canUnroll() const
Whether it is legal to unroll this loop.
uint64_t getRolledLoopSize() const
A Use represents the edge between a Value definition and its users.
void setOperand(unsigned i, Value *Val)
Value * getOperand(unsigned i) const
ValueT lookup(const KeyT &Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
user_iterator user_begin()
void setName(const Twine &Name)
Change the name of the value.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
void replaceUsesWithIf(Value *New, llvm::function_ref< bool(Use &U)> ShouldReplace)
Go through the uses list for this definition and make each use point to "V" if the callback ShouldRep...
User * getUniqueUndroppableUser()
Return true if there is exactly one unique user of this value that cannot be dropped (that user can h...
unsigned getNumUses() const
This method computes the number of uses of this Value.
iterator_range< use_iterator > uses()
StringRef getName() const
Return a constant reference to the value's name.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
iterator insertAfter(iterator where, pointer New)
A raw_ostream that writes to an SmallVector or SmallString.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ C
The default llvm calling convention, compatible with C.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
initializer< Ty > init(const Ty &Val)
void emitOffloadingEntry(Module &M, Constant *Addr, StringRef Name, uint64_t Size, int32_t Flags, int32_t Data, StringRef SectionName)
Create an offloading section struct used to register this global at runtime.
OpenMPOffloadMappingFlags
Values for bit flags used to specify the mapping type for offloading.
@ OMP_MAP_PTR_AND_OBJ
The element being mapped is a pointer-pointee pair; both the pointer and the pointee should be mapped...
@ OMP_MAP_MEMBER_OF
The 16 MSBs of the flags indicate whether the entry is member of some struct/class.
@ OMP_DEVICEID_UNDEF
Device ID if the device was not defined, runtime should get it from environment variables in the spec...
IdentFlag
IDs for all omp runtime library ident_t flag encodings (see their defintion in openmp/runtime/src/kmp...
RuntimeFunction
IDs for all omp runtime library (RTL) functions.
static constexpr GV NVPTXGridValues
For Nvidia GPUs.
WorksharingLoopType
A type of worksharing loop construct.
OMPAtomicCompareOp
Atomic compare operations. Currently OpenMP only supports ==, >, and <.
NodeAddr< PhiNode * > Phi
std::error_code getUniqueID(const Twine Path, UniqueID &Result)
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
BasicBlock * splitBBWithSuffix(IRBuilderBase &Builder, bool CreateBranch, llvm::Twine Suffix=".split")
Like splitBB, but reuses the current block's name for the new name.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Expected< std::unique_ptr< Module > > parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context, ParserCallbacks Callbacks={})
Read the specified bitcode file, returning the module.
detail::zippy< detail::zip_first, T, U, Args... > zip_equal(T &&t, U &&u, Args &&...args)
zip iterator that assumes that all iteratees have the same length.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto successors(const MachineBasicBlock *BB)
testing::Matcher< const detail::ErrorHolder & > Failed()
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
ErrorOr< T > expectedToErrorOrAndEmitErrors(LLVMContext &Ctx, Expected< T > Val)
bool convertUsersOfConstantsToInstructions(ArrayRef< Constant * > Consts, Function *RestrictToFunc=nullptr, bool RemoveDeadConstants=true, bool IncludeSelf=false)
Replace constant expressions users of the given constants with instructions.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
auto reverse(ContainerTy &&C)
TargetTransformInfo::PeelingPreferences gatherPeelingPreferences(Loop *L, ScalarEvolution &SE, const TargetTransformInfo &TTI, std::optional< bool > UserAllowPeeling, std::optional< bool > UserAllowProfileBasedPeeling, bool UnrollingSpecficValues=false)
void spliceBB(IRBuilderBase::InsertPoint IP, BasicBlock *New, bool CreateBranch)
Move the instruction after an InsertPoint to the beginning of another BasicBlock.
void SplitBlockAndInsertIfThenElse(Value *Cond, BasicBlock::iterator SplitBefore, Instruction **ThenTerm, Instruction **ElseTerm, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr)
SplitBlockAndInsertIfThenElse is similar to SplitBlockAndInsertIfThen, but also creates the ElseBlock...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
BasicBlock * splitBB(IRBuilderBase::InsertPoint IP, bool CreateBranch, llvm::Twine Name={})
Split a BasicBlock at an InsertPoint, even if the block is degenerate (missing the terminator).
CodeGenOptLevel
Code generation optimization level.
bool computeUnrollCount(Loop *L, const TargetTransformInfo &TTI, DominatorTree &DT, LoopInfo *LI, AssumptionCache *AC, ScalarEvolution &SE, const SmallPtrSetImpl< const Value * > &EphValues, OptimizationRemarkEmitter *ORE, unsigned TripCount, unsigned MaxTripCount, bool MaxOrZero, unsigned TripMultiple, const UnrollCostEstimator &UCE, TargetTransformInfo::UnrollingPreferences &UP, TargetTransformInfo::PeelingPreferences &PP, bool &UseUpperBound)
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
AtomicOrdering
Atomic ordering for LLVM's memory model.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
BasicBlock * CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap, const Twine &NameSuffix="", Function *F=nullptr, ClonedCodeInfo *CodeInfo=nullptr)
Return a copy of the specified basic block, but without embedding the block into a particular functio...
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
bool MergeBlockIntoPredecessor(BasicBlock *BB, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, MemoryDependenceResults *MemDep=nullptr, bool PredecessorWithTwoSuccessors=false, DominatorTree *DT=nullptr)
Attempts to merge a block into its predecessor, if possible.
DWARFExpression::Operation Op
void remapInstructionsInBlocks(ArrayRef< BasicBlock * > Blocks, ValueToValueMapTy &VMap)
Remaps instructions in Blocks using the mapping in VMap.
TargetTransformInfo::UnrollingPreferences gatherUnrollingPreferences(Loop *L, ScalarEvolution &SE, const TargetTransformInfo &TTI, BlockFrequencyInfo *BFI, ProfileSummaryInfo *PSI, llvm::OptimizationRemarkEmitter &ORE, int OptLevel, std::optional< unsigned > UserThreshold, std::optional< unsigned > UserCount, std::optional< bool > UserAllowPartial, std::optional< bool > UserRuntime, std::optional< bool > UserUpperBound, std::optional< unsigned > UserFullUnrollMaxCount)
Gather the various unrolling parameters based on the defaults, compiler flags, TTI overrides and user...
BasicBlock * SplitBlock(BasicBlock *Old, BasicBlock::iterator SplitPt, DominatorTree *DT, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, const Twine &BBName="", bool Before=false)
Split the specified block at the specified instruction.
auto predecessors(const MachineBasicBlock *BB)
Constant * ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val, ArrayRef< unsigned > Idxs)
ConstantFoldInsertValueInstruction - Attempt to constant fold an insertvalue instruction with the spe...
void DeleteDeadBlocks(ArrayRef< BasicBlock * > BBs, DomTreeUpdater *DTU=nullptr, bool KeepOneInputPHIs=false)
Delete the specified blocks from BB.
This struct is a compact representation of a valid (non-zero power of two) alignment.
static void collectEphemeralValues(const Loop *L, AssumptionCache *AC, SmallPtrSetImpl< const Value * > &EphValues)
Collect a loop's ephemeral values (those used only by an assume or similar intrinsics in the loop).
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
a struct to pack relevant information while generating atomic Ops
A struct to pack the relevant information for an OpenMP depend clause.
Description of a LLVM-IR insertion point (IP) and a debug/source location (filename,...
MapNonContiguousArrayTy Offsets
MapNonContiguousArrayTy Counts
MapNonContiguousArrayTy Strides
This structure contains combined information generated for mappable clauses, including base pointers,...
MapDeviceInfoArrayTy DevicePointers
MapValuesArrayTy BasePointers
MapValuesArrayTy Pointers
StructNonContiguousInfo NonContigInfo
Helper that contains information about regions we need to outline during finalization.
PostOutlineCBTy PostOutlineCB
void collectBlocks(SmallPtrSetImpl< BasicBlock * > &BlockSet, SmallVectorImpl< BasicBlock * > &BlockVector)
Collect all blocks in between EntryBB and ExitBB in both the given vector and set.
SmallVector< Value *, 2 > ExcludeArgsFromAggregate
BasicBlock * OuterAllocaBB
Information about an OpenMP reduction.
EvalKind EvaluationKind
Reduction evaluation kind - scalar, complex or aggregate.
ReductionGenAtomicCBTy AtomicReductionGen
Callback for generating the atomic reduction body, may be null.
ReductionGenCBTy ReductionGen
Callback for generating the reduction body.
Value * Variable
Reduction variable of pointer type.
Value * PrivateVariable
Thread-private partial reduction variable.
ReductionGenClangCBTy ReductionGenClang
Clang callback for generating the reduction body.
Type * ElementType
Reduction element type, must match pointee type of variable.
Container for the arguments used to pass data to the runtime library.
Value * SizesArray
The array of sizes passed to the runtime library.
Value * PointersArray
The array of section pointers passed to the runtime library.
Value * MappersArray
The array of user-defined mappers passed to the runtime library.
Value * BasePointersArray
The array of base pointer passed to the runtime library.
Value * MapTypesArray
The array of map types passed to the runtime library for the beginning of the region or for the entir...
Value * MapNamesArray
The array of original declaration names of mapped pointers sent to the runtime library for debugging.
Data structure that contains the needed information to construct the kernel args vector.
Value * DynCGGroupMem
The size of the dynamic shared memory.
ArrayRef< Value * > NumThreads
The number of threads.
TargetDataRTArgs RTArgs
Arguments passed to the runtime library.
Value * NumIterations
The number of iterations.
unsigned NumTargetItems
Number of arguments passed to the runtime library.
bool HasNoWait
True if the kernel has 'no wait' clause.
ArrayRef< Value * > NumTeams
The number of teams.
Container to pass the default attributes with which a kernel must be launched, used to set kernel att...
omp::OMPTgtExecModeFlags ExecFlags
SmallVector< int32_t, 3 > MaxTeams
Container to pass LLVM IR runtime values or constants related to the number of teams and threads with...
SmallVector< Value *, 3 > MaxTeams
Value * MaxThreads
'parallel' construct 'num_threads' clause value, if present and it is an SPMD kernel.
Value * LoopTripCount
Total number of iterations of the SPMD or Generic-SPMD kernel or null if it is a generic kernel.
SmallVector< Value *, 3 > TargetThreadLimit
SmallVector< Value *, 3 > TeamsThreadLimit
Data structure to contain the information needed to uniquely identify a target entry.
static void getTargetRegionEntryFnName(SmallVectorImpl< char > &Name, StringRef ParentName, unsigned DeviceID, unsigned FileID, unsigned Line, unsigned Count)
static const Target * lookupTarget(StringRef Triple, std::string &Error)
lookupTarget - Lookup a target based on a target triple.
Defines various target-specific GPU grid values that must be consistent between host RTL (plugin),...
unsigned GV_Warp_Size
The default value of maximum number of threads in a worker warp.