60#define DEBUG_TYPE "openmp-ir-builder"
67 cl::desc(
"Use optimistic attributes describing "
68 "'as-if' properties of runtime calls."),
72 "openmp-ir-builder-use-default-max-threads",
cl::Hidden,
83 if (!IP1.isValid() || !IP2.isValid())
90 switch (SchedType & ~OMPScheduleType::MonotonicityMask) {
91 case OMPScheduleType::UnorderedStaticChunked:
92 case OMPScheduleType::UnorderedStatic:
93 case OMPScheduleType::UnorderedDynamicChunked:
94 case OMPScheduleType::UnorderedGuidedChunked:
95 case OMPScheduleType::UnorderedRuntime:
96 case OMPScheduleType::UnorderedAuto:
97 case OMPScheduleType::UnorderedTrapezoidal:
98 case OMPScheduleType::UnorderedGreedy:
99 case OMPScheduleType::UnorderedBalanced:
100 case OMPScheduleType::UnorderedGuidedIterativeChunked:
101 case OMPScheduleType::UnorderedGuidedAnalyticalChunked:
102 case OMPScheduleType::UnorderedSteal:
103 case OMPScheduleType::UnorderedStaticBalancedChunked:
104 case OMPScheduleType::UnorderedGuidedSimd:
105 case OMPScheduleType::UnorderedRuntimeSimd:
106 case OMPScheduleType::OrderedStaticChunked:
107 case OMPScheduleType::OrderedStatic:
108 case OMPScheduleType::OrderedDynamicChunked:
109 case OMPScheduleType::OrderedGuidedChunked:
110 case OMPScheduleType::OrderedRuntime:
111 case OMPScheduleType::OrderedAuto:
112 case OMPScheduleType::OrderdTrapezoidal:
113 case OMPScheduleType::NomergeUnorderedStaticChunked:
114 case OMPScheduleType::NomergeUnorderedStatic:
115 case OMPScheduleType::NomergeUnorderedDynamicChunked:
116 case OMPScheduleType::NomergeUnorderedGuidedChunked:
117 case OMPScheduleType::NomergeUnorderedRuntime:
118 case OMPScheduleType::NomergeUnorderedAuto:
119 case OMPScheduleType::NomergeUnorderedTrapezoidal:
120 case OMPScheduleType::NomergeUnorderedGreedy:
121 case OMPScheduleType::NomergeUnorderedBalanced:
122 case OMPScheduleType::NomergeUnorderedGuidedIterativeChunked:
123 case OMPScheduleType::NomergeUnorderedGuidedAnalyticalChunked:
124 case OMPScheduleType::NomergeUnorderedSteal:
125 case OMPScheduleType::NomergeOrderedStaticChunked:
126 case OMPScheduleType::NomergeOrderedStatic:
127 case OMPScheduleType::NomergeOrderedDynamicChunked:
128 case OMPScheduleType::NomergeOrderedGuidedChunked:
129 case OMPScheduleType::NomergeOrderedRuntime:
130 case OMPScheduleType::NomergeOrderedAuto:
131 case OMPScheduleType::NomergeOrderedTrapezoidal:
132 case OMPScheduleType::OrderedDistributeChunked:
133 case OMPScheduleType::OrderedDistribute:
141 SchedType & OMPScheduleType::MonotonicityMask;
142 if (MonotonicityFlags == OMPScheduleType::MonotonicityMask)
156 Builder.restoreIP(IP);
160 if (Builder.GetInsertPoint() != BB->
end())
170 unsigned Line = FSP->getScopeLine() ? FSP->getScopeLine() : FSP->getLine();
171 Builder.SetCurrentDebugLocation(
177 return T.isAMDGPU() ||
T.isNVPTX() ||
T.isSPIRV();
183 Kernel->getFnAttribute(
"target-features").getValueAsString();
184 if (Features.
count(
"+wavefrontsize64"))
199 bool HasSimdModifier,
bool HasDistScheduleChunks) {
201 switch (ClauseKind) {
202 case OMP_SCHEDULE_Default:
203 case OMP_SCHEDULE_Static:
204 return HasChunks ? OMPScheduleType::BaseStaticChunked
205 : OMPScheduleType::BaseStatic;
206 case OMP_SCHEDULE_Dynamic:
207 return OMPScheduleType::BaseDynamicChunked;
208 case OMP_SCHEDULE_Guided:
209 return HasSimdModifier ? OMPScheduleType::BaseGuidedSimd
210 : OMPScheduleType::BaseGuidedChunked;
211 case OMP_SCHEDULE_Auto:
213 case OMP_SCHEDULE_Runtime:
214 return HasSimdModifier ? OMPScheduleType::BaseRuntimeSimd
215 : OMPScheduleType::BaseRuntime;
216 case OMP_SCHEDULE_Distribute:
217 return HasDistScheduleChunks ? OMPScheduleType::BaseDistributeChunked
218 : OMPScheduleType::BaseDistribute;
226 bool HasOrderedClause) {
227 assert((BaseScheduleType & OMPScheduleType::ModifierMask) ==
228 OMPScheduleType::None &&
229 "Must not have ordering nor monotonicity flags already set");
232 ? OMPScheduleType::ModifierOrdered
233 : OMPScheduleType::ModifierUnordered;
237 if (OrderingScheduleType ==
238 (OMPScheduleType::BaseGuidedSimd | OMPScheduleType::ModifierOrdered))
239 return OMPScheduleType::OrderedGuidedChunked;
240 else if (OrderingScheduleType == (OMPScheduleType::BaseRuntimeSimd |
241 OMPScheduleType::ModifierOrdered))
242 return OMPScheduleType::OrderedRuntime;
244 return OrderingScheduleType;
250 bool HasSimdModifier,
bool HasMonotonic,
251 bool HasNonmonotonic,
bool HasOrderedClause) {
252 assert((ScheduleType & OMPScheduleType::MonotonicityMask) ==
253 OMPScheduleType::None &&
254 "Must not have monotonicity flags already set");
255 assert((!HasMonotonic || !HasNonmonotonic) &&
256 "Monotonic and Nonmonotonic are contradicting each other");
259 return ScheduleType | OMPScheduleType::ModifierMonotonic;
260 }
else if (HasNonmonotonic) {
261 return ScheduleType | OMPScheduleType::ModifierNonmonotonic;
271 if ((BaseScheduleType == OMPScheduleType::BaseStatic) ||
272 (BaseScheduleType == OMPScheduleType::BaseStaticChunked) ||
278 return ScheduleType | OMPScheduleType::ModifierNonmonotonic;
286 bool HasSimdModifier,
bool HasMonotonicModifier,
287 bool HasNonmonotonicModifier,
bool HasOrderedClause,
288 bool HasDistScheduleChunks) {
290 ClauseKind, HasChunks, HasSimdModifier, HasDistScheduleChunks);
294 OrderedSchedule, HasSimdModifier, HasMonotonicModifier,
295 HasNonmonotonicModifier, HasOrderedClause);
303static std::optional<omp::OMPTgtExecModeFlags>
308 if (
Call->getCalledFunction()->getName() ==
"__kmpc_target_init") {
309 TargetInitCall =
Call;
334 std::optional<omp::OMPTgtExecModeFlags> ExecMode =
346 if (
Instruction *Term = Source->getTerminatorOrNull()) {
355 NewBr->setDebugLoc(
DL);
360 assert(New->getFirstInsertionPt() == New->begin() &&
361 "Target BB must not have PHI nodes");
377 New->splice(New->begin(), Old, IP, Old->
end());
381 NewBr->setDebugLoc(
DL);
393 Builder.SetInsertPoint(Old);
397 Builder.SetCurrentDebugLocation(
DebugLoc);
407 New->replaceSuccessorsPhiUsesWith(Old, New);
419 Builder.SetInsertPoint(Old);
422 Builder.SetCurrentDebugLocation(
DebugLoc);
434 Builder.SetInsertPoint(Old);
437 Builder.SetCurrentDebugLocation(
DebugLoc);
454 const Twine &Name =
"",
bool AsPtr =
true,
455 bool Is64Bit =
false) {
456 Builder.restoreIP(OuterAllocaIP);
460 Builder.CreateAlloca(IntTy,
nullptr, Name +
".addr");
464 FakeVal = FakeValAddr;
469 FakeValAddr, Builder.getPtrTy(), Name +
".ascast"));
473 FakeVal = Builder.CreateLoad(IntTy, FakeValAddr, Name +
".val");
478 Builder.restoreIP(InnerAllocaIP);
481 UseFakeVal = Builder.CreateLoad(IntTy, FakeVal, Name +
".use");
484 FakeVal, Is64Bit ? Builder.getInt64(10) : Builder.getInt32(10)));
497enum OpenMPOffloadingRequiresDirFlags {
499 OMP_REQ_UNDEFINED = 0x000,
501 OMP_REQ_NONE = 0x001,
503 OMP_REQ_REVERSE_OFFLOAD = 0x002,
505 OMP_REQ_UNIFIED_ADDRESS = 0x004,
507 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008,
509 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010,
516 DominatorTree *DT =
nullptr,
bool AggregateArgs =
false,
517 BlockFrequencyInfo *BFI =
nullptr,
518 BranchProbabilityInfo *BPI =
nullptr,
519 AssumptionCache *AC =
nullptr,
bool AllowVarArgs =
false,
520 bool AllowAlloca =
false,
521 BasicBlock *AllocationBlock =
nullptr,
523 std::string Suffix =
"",
bool ArgsInZeroAddressSpace =
false)
524 : CodeExtractor(BBs, DT, AggregateArgs, BFI, BPI, AC, AllowVarArgs,
525 AllowAlloca, AllocationBlock, DeallocationBlocks, Suffix,
526 ArgsInZeroAddressSpace),
527 OMPBuilder(OMPBuilder) {}
529 virtual ~OMPCodeExtractor() =
default;
532 OpenMPIRBuilder &OMPBuilder;
535class DeviceSharedMemCodeExtractor :
public OMPCodeExtractor {
537 using OMPCodeExtractor::OMPCodeExtractor;
538 virtual ~DeviceSharedMemCodeExtractor() =
default;
542 allocateVar(IRBuilder<>::InsertPoint AllocaIP,
DebugLoc DL,
Type *VarType,
543 const Twine &Name = Twine(
""),
544 AddrSpaceCastInst **CastedAlloc =
nullptr)
override {
545 return OMPBuilder.createOMPAllocShared({AllocaIP,
DL}, VarType,
Name);
548 virtual Instruction *deallocateVar(IRBuilder<>::InsertPoint DeallocIP,
550 Type *VarType)
override {
551 return OMPBuilder.createOMPFreeShared({DeallocIP,
DL}, Var, VarType);
558 OpenMPIRBuilder &OMPBuilder;
560 DeviceSharedMemOutlineInfo(OpenMPIRBuilder &OMPBuilder)
561 : OMPBuilder(OMPBuilder) {}
562 virtual ~DeviceSharedMemOutlineInfo() =
default;
564 virtual std::unique_ptr<CodeExtractor>
566 bool ArgsInZeroAddressSpace,
567 Twine Suffix = Twine(
""))
override;
573 : RequiresFlags(OMP_REQ_UNDEFINED) {}
577 bool HasRequiresReverseOffload,
bool HasRequiresUnifiedAddress,
578 bool HasRequiresUnifiedSharedMemory,
bool HasRequiresDynamicAllocators)
581 RequiresFlags(OMP_REQ_UNDEFINED) {
582 if (HasRequiresReverseOffload)
583 RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
584 if (HasRequiresUnifiedAddress)
585 RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
586 if (HasRequiresUnifiedSharedMemory)
587 RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
588 if (HasRequiresDynamicAllocators)
589 RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
593 return RequiresFlags & OMP_REQ_REVERSE_OFFLOAD;
597 return RequiresFlags & OMP_REQ_UNIFIED_ADDRESS;
601 return RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY;
605 return RequiresFlags & OMP_REQ_DYNAMIC_ALLOCATORS;
610 :
static_cast<int64_t
>(OMP_REQ_NONE);
615 RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
617 RequiresFlags &= ~OMP_REQ_REVERSE_OFFLOAD;
622 RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
624 RequiresFlags &= ~OMP_REQ_UNIFIED_ADDRESS;
629 RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
631 RequiresFlags &= ~OMP_REQ_UNIFIED_SHARED_MEMORY;
636 RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
638 RequiresFlags &= ~OMP_REQ_DYNAMIC_ALLOCATORS;
651 constexpr size_t MaxDim = 3;
656 Value *DynCGroupMemFallbackFlag =
658 DynCGroupMemFallbackFlag =
Builder.CreateShl(DynCGroupMemFallbackFlag, 2);
663 StrictBlocksFlag =
Builder.CreateShl(StrictBlocksFlag, 6);
664 StrictThreadsFlag =
Builder.CreateShl(StrictThreadsFlag, 7);
666 Value *Flags =
Builder.CreateOr(HasNoWaitFlag, DynCGroupMemFallbackFlag);
667 Flags =
Builder.CreateOr(Flags, StrictBlocksFlag);
668 Flags =
Builder.CreateOr(Flags, StrictThreadsFlag);
674 Value *NumThreads3D =
705 auto FnAttrs = Attrs.getFnAttrs();
706 auto RetAttrs = Attrs.getRetAttrs();
708 for (
size_t ArgNo = 0; ArgNo < Fn.
arg_size(); ++ArgNo)
713 bool Param =
true) ->
void {
714 bool HasSignExt = AS.hasAttribute(Attribute::SExt);
715 bool HasZeroExt = AS.hasAttribute(Attribute::ZExt);
716 if (HasSignExt || HasZeroExt) {
717 assert(AS.getNumAttributes() == 1 &&
718 "Currently not handling extension attr combined with others.");
720 if (
auto AK = TargetLibraryInfo::getExtAttrForI32Param(
T, HasSignExt))
723 TargetLibraryInfo::getExtAttrForI32Return(
T, HasSignExt))
730#define OMP_ATTRS_SET(VarName, AttrSet) AttributeSet VarName = AttrSet;
731#include "llvm/Frontend/OpenMP/OMPKinds.def"
735#define OMP_RTL_ATTRS(Enum, FnAttrSet, RetAttrSet, ArgAttrSets) \
737 FnAttrs = FnAttrs.addAttributes(Ctx, FnAttrSet); \
738 addAttrSet(RetAttrs, RetAttrSet, false); \
739 for (size_t ArgNo = 0; ArgNo < ArgAttrSets.size(); ++ArgNo) \
740 addAttrSet(ArgAttrs[ArgNo], ArgAttrSets[ArgNo]); \
741 Fn.setAttributes(AttributeList::get(Ctx, FnAttrs, RetAttrs, ArgAttrs)); \
743#include "llvm/Frontend/OpenMP/OMPKinds.def"
757#define OMP_RTL(Enum, Str, IsVarArg, ReturnType, ...) \
759 FnTy = FunctionType::get(ReturnType, ArrayRef<Type *>{__VA_ARGS__}, \
761 Fn = M.getFunction(Str); \
763#include "llvm/Frontend/OpenMP/OMPKinds.def"
769#define OMP_RTL(Enum, Str, ...) \
771 Fn = Function::Create(FnTy, GlobalValue::ExternalLinkage, Str, M); \
773#include "llvm/Frontend/OpenMP/OMPKinds.def"
777 if (FnID == OMPRTL___kmpc_fork_call || FnID == OMPRTL___kmpc_fork_teams) {
787 LLVMContext::MD_callback,
789 2, {-1, -1},
true)}));
802 assert(Fn &&
"Failed to create OpenMP runtime function");
813 Builder.SetInsertPoint(FiniBB);
825 FiniBB = OtherFiniBB;
827 Builder.SetInsertPoint(FiniBB->getFirstNonPHIIt());
835 auto EndIt = FiniBB->end();
836 if (FiniBB->size() >= 1)
837 if (
auto Prev = std::prev(EndIt); Prev->isTerminator())
842 FiniBB->replaceAllUsesWith(OtherFiniBB);
843 FiniBB->eraseFromParent();
844 FiniBB = OtherFiniBB;
851 assert(Fn &&
"Failed to create OpenMP runtime function pointer");
874 for (
auto Inst =
Block->getReverseIterator()->begin();
875 Inst !=
Block->getReverseIterator()->end();) {
904 Block.getParent()->getEntryBlock().getTerminator()->getIterator();
925 DeferredOutlines.
push_back(std::move(OI));
929 ParallelRegionBlockSet.
clear();
931 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
941 bool ArgsInZeroAddressSpace =
Config.isTargetDevice();
942 std::unique_ptr<CodeExtractor> Extractor =
943 OI->createCodeExtractor(Blocks, ArgsInZeroAddressSpace,
".omp_par");
947 <<
" Exit: " << OI->ExitBB->getName() <<
"\n");
948 assert(Extractor->isEligible() &&
949 "Expected OpenMP outlining to be possible!");
951 for (
auto *V : OI->ExcludeArgsFromAggregate)
952 Extractor->excludeArgFromAggregate(V);
955 Extractor->extractCodeRegion(CEAC, OI->Inputs, OI->Outputs);
959 if (TargetCpuAttr.isStringAttribute())
962 auto TargetFeaturesAttr = OuterFn->
getFnAttribute(
"target-features");
963 if (TargetFeaturesAttr.isStringAttribute())
964 OutlinedFn->
addFnAttr(TargetFeaturesAttr);
967 LLVM_DEBUG(
dbgs() <<
" Outlined function: " << *OutlinedFn <<
"\n");
969 "OpenMP outlined functions should not return a value!");
974 M.getFunctionList().insertAfter(OuterFn->
getIterator(), OutlinedFn);
981 assert(OI->EntryBB->getUniquePredecessor() == &ArtificialEntry);
988 "Expected instructions to add in the outlined region entry");
995 if (
I.isTerminator()) {
997 if (
Instruction *TI = OI->EntryBB->getTerminatorOrNull())
998 TI->adoptDbgRecords(&ArtificialEntry,
I.getIterator(),
false);
1002 I.moveBeforePreserving(*OI->EntryBB,
1003 OI->EntryBB->getFirstInsertionPt());
1006 OI->EntryBB->moveBefore(&ArtificialEntry);
1013 if (OI->PostOutlineCB)
1014 OI->PostOutlineCB(*OutlinedFn);
1016 if (OI->FixUpNonEntryAllocas)
1046 errs() <<
"Error of kind: " << Kind
1047 <<
" when emitting offload entries and metadata during "
1048 "OMPIRBuilder finalization \n";
1056 if (
Config.isTargetDevice())
1057 applyDeclareTargetGlobalReplacements();
1059 if (
Config.EmitLLVMUsedMetaInfo.value_or(
false)) {
1060 std::vector<WeakTrackingVH> LLVMCompilerUsed = {
1061 M.getGlobalVariable(
"__openmp_nvptx_data_transfer_temporary_storage")};
1062 emitUsed(
"llvm.compiler.used", LLVMCompilerUsed);
1072 assert(Original && Replacement &&
1073 "Null values provided to registerDeclareTargetGlobalReplacement");
1077void OpenMPIRBuilder::applyDeclareTargetGlobalReplacements() {
1083 "A null value was inserted into DeclareTargetGlobalReplacements");
1087 if (!OldGV || !NewGV)
1121 for (
unsigned I = 0, E =
PHI->getNumIncomingValues();
I < E; ++
I) {
1122 if (
PHI->getIncomingValue(
I) != OldGV)
1127 Builder.SetCurrentDebugLocation(
PHI->getDebugLoc());
1129 PHI->setIncomingValue(
I, EdgeLoad);
1135 Builder.SetCurrentDebugLocation(Insn->getDebugLoc());
1151 "Non-default address space declare target global");
1153 unsigned DestAS = ASC->getType()->getPointerAddressSpace();
1154 if (DestAS == 0 && NewGVAS != OldGVAS) {
1155 ASC->replaceAllUsesWith(
Load);
1156 ASC->eraseFromParent();
1161 Insn->replaceUsesOfWith(OldGV,
Load);
1177 ConstantInt::get(I32Ty,
Value), Name);
1190 for (
unsigned I = 0, E =
List.size();
I != E; ++
I)
1194 if (UsedArray.
empty())
1201 GV->setSection(
"llvm.metadata");
1207 auto *Int8Ty =
Builder.getInt8Ty();
1210 ConstantInt::get(Int8Ty, Mode),
Twine(KernelName,
"_exec_mode"));
1218 unsigned Reserve2Flags) {
1220 LocFlags |= OMP_IDENT_FLAG_KMPC;
1227 ConstantInt::get(Int32,
uint32_t(LocFlags)),
1228 ConstantInt::get(Int32, Reserve2Flags),
1229 ConstantInt::get(Int32, SrcLocStrSize), SrcLocStr};
1231 size_t SrcLocStrArgIdx = 4;
1232 if (OpenMPIRBuilder::Ident->getElementType(SrcLocStrArgIdx)
1236 SrcLocStr, OpenMPIRBuilder::Ident->getElementType(SrcLocStrArgIdx));
1243 if (
GV.getValueType() == OpenMPIRBuilder::Ident &&
GV.hasInitializer())
1244 if (
GV.getInitializer() == Initializer)
1249 M, OpenMPIRBuilder::Ident,
1252 M.getDataLayout().getDefaultGlobalsAddressSpace());
1264 SrcLocStrSize = LocStr.
size();
1273 if (
GV.isConstant() &&
GV.hasInitializer() &&
1274 GV.getInitializer() == Initializer)
1277 SrcLocStr =
Builder.CreateGlobalString(
1278 LocStr,
"",
M.getDataLayout().getDefaultGlobalsAddressSpace(),
1286 unsigned Line,
unsigned Column,
1292 Buffer.
append(FunctionName);
1294 Buffer.
append(std::to_string(Line));
1296 Buffer.
append(std::to_string(Column));
1304 StringRef UnknownLoc =
";unknown;unknown;0;0;;";
1315 !DIL->getFilename().empty() ? DIL->getFilename() :
M.getName();
1320 DIL->getColumn(), SrcLocStrSize);
1326 Loc.IP.getNodeParent()->getParent());
1332 "omp_global_thread_num");
1340 "expected one result pointer type per in_reduction item");
1343 if (OrigPtrs.
empty())
1344 return Builder.saveIP();
1363 for (
unsigned Idx = 0; Idx < OrigPtrs.
size(); ++Idx) {
1366 Value *OrigPtr = OrigPtrs[Idx];
1368 OrigPtrTy && OrigPtrTy->getAddressSpace() != 0)
1369 OrigPtr = Builder.CreateAddrSpaceCast(OrigPtr, PtrTy);
1371 Value *
Priv = Builder.CreateCall(GetThData, {Gtid, NullDesc, OrigPtr},
1377 ResPtrTy && ResPtrTy->getAddressSpace() != 0)
1378 Priv = Builder.CreateAddrSpaceCast(
Priv, ResultPtrTys[Idx]);
1380 MapPrivateCB(Idx,
Priv);
1387 bool ForceSimpleCall,
bool CheckCancelFlag) {
1397 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_FOR;
1400 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SECTIONS;
1403 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SINGLE;
1406 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_EXPL;
1409 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL;
1422 bool UseCancelBarrier =
1427 ? OMPRTL___kmpc_cancel_barrier
1428 : OMPRTL___kmpc_barrier),
1431 if (UseCancelBarrier && CheckCancelFlag)
1441 omp::Directive CanceledDirective) {
1446 auto *UI =
Builder.CreateUnreachable();
1454 Builder.SetInsertPoint(ElseTI);
1455 auto ElseIP =
Builder.saveIP();
1463 Builder.SetInsertPoint(ThenTI);
1465 Value *CancelKind =
nullptr;
1466 switch (CanceledDirective) {
1467#define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) \
1468 case DirectiveEnum: \
1469 CancelKind = Builder.getInt32(Value); \
1471#include "llvm/Frontend/OpenMP/OMPKinds.def"
1488 Builder.SetInsertPoint(UI->getParent());
1489 UI->eraseFromParent();
1496 omp::Directive CanceledDirective) {
1501 auto *UI =
Builder.CreateUnreachable();
1504 Value *CancelKind =
nullptr;
1505 switch (CanceledDirective) {
1506#define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) \
1507 case DirectiveEnum: \
1508 CancelKind = Builder.getInt32(Value); \
1510#include "llvm/Frontend/OpenMP/OMPKinds.def"
1527 Builder.SetInsertPoint(UI->getParent());
1528 UI->eraseFromParent();
1541 auto *KernelArgsPtr =
1542 Builder.CreateAlloca(OpenMPIRBuilder::KernelArgs,
nullptr,
"kernel_args");
1547 Builder.CreateStructGEP(OpenMPIRBuilder::KernelArgs, KernelArgsPtr,
I);
1550 M.getDataLayout().getPrefTypeAlign(KernelArgs[
I]->getType()));
1554 NumThreads, HostPtr, KernelArgsPtr};
1581 assert(OutlinedFnID &&
"Invalid outlined function ID!");
1585 Value *Return =
nullptr;
1605 Builder, AllocaIP, Return, RTLoc, DeviceID, Args.NumTeams.front(),
1606 Args.NumThreads.front(), OutlinedFnID, ArgsVector));
1613 Builder.CreateCondBr(
Failed, OffloadFailedBlock, OffloadContBlock);
1615 auto CurFn =
Builder.GetInsertBlock()->getParent();
1622 emitBlock(OffloadContBlock, CurFn,
true);
1627 Value *CancelFlag, omp::Directive CanceledDirective) {
1629 "Unexpected cancellation!");
1649 Builder.CreateCondBr(Cmp, NonCancellationBlock, CancellationBlock,
1658 Builder.SetInsertPoint(CancellationBlock);
1659 Builder.CreateBr(*FiniBBOrErr);
1674 size_t NumArgs = OutlinedFn.
arg_size();
1675 assert((NumArgs == 2 || NumArgs == 3) &&
1676 "expected a 2-3 argument parallel outlined function");
1677 bool UseArgStruct = NumArgs == 3;
1682 {Builder.getInt16Ty(), Builder.getInt32Ty()},
1686 OutlinedFn.
getName() +
".wrapper", OMPIRBuilder->
M);
1688 WrapperFn->addParamAttr(0, Attribute::NoUndef);
1689 WrapperFn->addParamAttr(0, Attribute::ZExt);
1690 WrapperFn->addParamAttr(1, Attribute::NoUndef);
1694 Builder.SetInsertPoint(EntryBB);
1697 Value *AddrAlloca = Builder.CreateAlloca(Builder.getInt32Ty(),
1699 AddrAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1700 AddrAlloca, Builder.getPtrTy(0),
1701 AddrAlloca->
getName() +
".ascast");
1703 Value *ZeroAlloca = Builder.CreateAlloca(Builder.getInt32Ty(),
1705 ZeroAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1706 ZeroAlloca, Builder.getPtrTy(0),
1707 ZeroAlloca->
getName() +
".ascast");
1709 Value *ArgsAlloca =
nullptr;
1711 ArgsAlloca = Builder.CreateAlloca(Builder.getPtrTy(),
1712 nullptr,
"global_args");
1713 ArgsAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1714 ArgsAlloca, Builder.getPtrTy(0),
1715 ArgsAlloca->
getName() +
".ascast");
1719 Builder.CreateStore(WrapperFn->getArg(1), AddrAlloca);
1720 Builder.CreateStore(Builder.getInt32(0), ZeroAlloca);
1724 llvm::omp::RuntimeFunction::OMPRTL___kmpc_get_shared_variables),
1732 Value *StructArg = Builder.CreateLoad(Builder.getPtrTy(), ArgsAlloca);
1733 StructArg = Builder.CreateInBoundsGEP(Builder.getPtrTy(), StructArg,
1734 {Builder.getInt64(0)});
1735 StructArg = Builder.CreateLoad(Builder.getPtrTy(), StructArg,
"structArg");
1736 Args.push_back(StructArg);
1740 Builder.CreateCall(&OutlinedFn, Args);
1741 Builder.CreateRetVoid();
1756 "Expected at least tid and bounded tid as arguments");
1757 unsigned NumCapturedVars = OutlinedFn.
arg_size() - 2;
1765 OutlinedFn.
addFnAttr(Attribute::NoUnwind);
1768 assert(CI &&
"Expected call instruction to outlined function");
1769 CI->
getParent()->setName(
"omp_parallel");
1771 Builder.SetInsertPoint(CI);
1772 Type *PtrTy = OMPIRBuilder->VoidPtr;
1775 OpenMPIRBuilder ::InsertPointTy CurrentIP = Builder.saveIP();
1779 Value *Args = ArgsAlloca;
1783 Args = Builder.CreatePointerCast(ArgsAlloca, PtrTy);
1784 Builder.restoreIP(CurrentIP);
1787 for (
unsigned Idx = 0; Idx < NumCapturedVars; Idx++) {
1789 Value *StoreAddress = Builder.CreateConstInBoundsGEP2_64(
1791 Builder.CreateStore(
V, StoreAddress);
1795 IfCondition ? Builder.CreateSExtOrTrunc(IfCondition, OMPIRBuilder->Int32)
1796 : Builder.getInt32(1);
1797 Value *NumThreadsArg =
1798 NumThreads ? Builder.CreateZExtOrTrunc(NumThreads, OMPIRBuilder->Int32)
1799 : Builder.getInt32(-1);
1809 Value *Parallel60CallArgs[] = {
1814 Builder.getInt32(-1),
1818 Builder.getInt64(NumCapturedVars),
1819 Builder.getInt32(0)};
1827 << *Builder.GetInsertBlock()->getParent() <<
"\n");
1830 Builder.SetInsertPoint(PrivTID);
1832 Builder.CreateStore(Builder.CreateLoad(OMPIRBuilder->Int32, OutlinedAI),
1839 I->eraseFromParent();
1862 if (!
F->hasMetadata(LLVMContext::MD_callback)) {
1870 F->addMetadata(LLVMContext::MD_callback,
1879 OutlinedFn.
addFnAttr(Attribute::NoUnwind);
1882 "Expected at least tid and bounded tid as arguments");
1883 unsigned NumCapturedVars = OutlinedFn.
arg_size() - 2;
1906 if (NumCapturedVars) {
1907 assert(NumCapturedVars == 1 &&
"Expected an aggregate capture argument");
1910 ->getAllocatedType()
1912 "Expected a stack-allocated capture structure");
1918 CI->
getParent()->setName(
"omp_parallel");
1919 Builder.SetInsertPoint(CI);
1922 Value *ForkCallArgs[] = {Ident, Builder.getInt32(NumCapturedVars),
1926 RealArgs.
append(std::begin(ForkCallArgs), std::end(ForkCallArgs));
1928 Value *
Cond = Builder.CreateSExtOrTrunc(IfCondition, OMPIRBuilder->Int32);
1935 auto PtrTy = OMPIRBuilder->VoidPtr;
1936 if (IfCondition && NumCapturedVars == 0) {
1944 << *Builder.GetInsertBlock()->getParent() <<
"\n");
1947 Builder.SetInsertPoint(PrivTID);
1949 Builder.CreateStore(Builder.CreateLoad(OMPIRBuilder->Int32, OutlinedAI),
1956 I->eraseFromParent();
1964 Value *NumThreads, omp::ProcBindKind ProcBind,
bool IsCancellable) {
1973 const bool NeedThreadID = NumThreads ||
Config.isTargetDevice() ||
1974 (ProcBind != OMP_PROC_BIND_default);
1981 bool ArgsInZeroAddressSpace =
Config.isTargetDevice();
1985 if (NumThreads && !
Config.isTargetDevice()) {
1988 Builder.CreateIntCast(NumThreads, Int32,
false)};
1993 if (ProcBind != OMP_PROC_BIND_default) {
1997 ConstantInt::get(Int32,
unsigned(ProcBind),
true)};
2007 BasicBlock *OuterAllocaBlock = OuterAllocIP.getNodeParent();
2019 Builder.CreateAlloca(Int32,
nullptr,
"zero.addr");
2022 if (ArgsInZeroAddressSpace &&
M.getDataLayout().getAllocaAddrSpace() != 0) {
2025 TIDAddrAlloca, PointerType ::get(
M.getContext(), 0),
"tid.addr.ascast");
2029 PointerType ::get(
M.getContext(), 0),
2030 "zero.addr.ascast");
2043 UI->setDebugLoc(
Loc.DL);
2055 if (IP == IP.getNodeParent()->end()) {
2059 IP =
I->getIterator();
2061 assert(IP.getNodeParent()->getTerminator()->getNumSuccessors() == 1 &&
2062 IP.getNodeParent()->getTerminator()->getSuccessor(0) == PRegExitBB &&
2063 "Unexpected insertion point for finalization call!");
2075 Builder.CreateAlloca(Int32,
nullptr,
"tid.addr.local");
2081 Builder.CreateLoad(Int32, ZeroAddr,
"zero.addr.use");
2099 LLVM_DEBUG(
dbgs() <<
"Before body codegen: " << *OuterFn <<
"\n");
2102 assert(BodyGenCB &&
"Expected body generation callback!");
2104 if (
Error Err = BodyGenCB(InnerAllocaIP, CodeGenIP, PRegExitBB))
2107 LLVM_DEBUG(
dbgs() <<
"After body codegen: " << *OuterFn <<
"\n");
2111 bool UsesDeviceSharedMemory =
2113 std::unique_ptr<OutlineInfo> OI =
2114 UsesDeviceSharedMemory
2115 ? std::make_unique<DeviceSharedMemOutlineInfo>(*
this)
2116 : std::make_unique<OutlineInfo>();
2118 if (
Config.isTargetDevice()) {
2120 OI->PostOutlineCB = [=, ToBeDeletedVec =
2121 std::move(ToBeDeleted)](
Function &OutlinedFn) {
2123 IfCondition, NumThreads, PrivTID, PrivTIDAddr,
2124 ThreadID, ToBeDeletedVec);
2128 OI->PostOutlineCB = [=, ToBeDeletedVec =
2129 std::move(ToBeDeleted)](
Function &OutlinedFn) {
2131 PrivTID, PrivTIDAddr, ToBeDeletedVec);
2135 OI->FixUpNonEntryAllocas =
true;
2136 OI->OuterAllocBB = OuterAllocaBlock;
2137 OI->EntryBB = PRegEntryBB;
2138 OI->ExitBB = PRegExitBB;
2139 OI->OuterDeallocBBs.reserve(OuterDeallocBlocks.
size());
2140 copy(OuterDeallocBlocks, OI->OuterDeallocBBs.
end());
2144 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
2156 ".omp_par", ArgsInZeroAddressSpace);
2161 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
2163 Extractor.findInputsOutputs(Inputs, Outputs, SinkingCands,
2168 return GV->getValueType() == OpenMPIRBuilder::Ident;
2173 LLVM_DEBUG(
dbgs() <<
"Before privatization: " << *OuterFn <<
"\n");
2179 if (&V == TIDAddr || &V == ZeroAddr) {
2180 OI->ExcludeArgsFromAggregate.push_back(&V);
2185 for (
Use &U : V.uses())
2187 if (ParallelRegionBlockSet.
count(UserI->getParent()))
2197 if (!V.getType()->isPointerTy()) {
2201 Builder.restoreIP(OuterAllocIP);
2203 if (UsesDeviceSharedMemory) {
2206 V.getName() +
".reloaded");
2207 for (
BasicBlock *DeallocBlock : OuterDeallocBlocks) {
2208 assert(DeallocBlock->getParent() ==
2209 OuterAllocIP.getNodeParent()->getParent() &&
2210 "Dealloc block must be in the allocation's function to reuse "
2211 "its debug location");
2213 Builder.getCurrentDebugLocation()},
2217 Ptr =
Builder.CreateAlloca(V.getType(),
nullptr,
2218 V.getName() +
".reloaded");
2227 Builder.restoreIP(InnerAllocaIP);
2228 Inner =
Builder.CreateLoad(V.getType(), Ptr);
2231 Value *ReplacementValue =
nullptr;
2234 ReplacementValue = PrivTID;
2237 PrivCB(InnerAllocaIP,
Builder.saveIP(), V, *Inner, ReplacementValue);
2242 InnerAllocaIP.getNodeParent()->getTerminator()->getIterator();
2244 assert(ReplacementValue &&
2245 "Expected copy/create callback to set replacement value!");
2246 if (ReplacementValue == &V)
2251 UPtr->set(ReplacementValue);
2274 for (
Value *Output : Outputs)
2278 "OpenMP outlining should not produce live-out values!");
2280 LLVM_DEBUG(
dbgs() <<
"After privatization: " << *OuterFn <<
"\n");
2282 for (
auto *BB : Blocks)
2283 dbgs() <<
" PBR: " << BB->getName() <<
"\n";
2291 assert(FiniInfo.DK == OMPD_parallel &&
2292 "Unexpected finalization stack state!");
2303 Builder.CreateBr(*FiniBBOrErr);
2306 Builder.GetInsertBlock()->getTerminator()->eraseFromParent();
2313 UI->eraseFromParent();
2345 Value *Severity = ConstantInt::get(Int32, IsFatal ? 2 : 1);
2347 Value *Args[] = {Ident, Severity, MessageArg};
2376 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr));
2378 Builder.CreateStore(DepValPtr, Addr);
2381 DependInfo, Entry,
static_cast<unsigned int>(RTLDependInfoFields::Len));
2383 ConstantInt::get(SizeTy,
2388 DependInfo, Entry,
static_cast<unsigned int>(RTLDependInfoFields::Flags));
2390 static_cast<unsigned int>(Dep.
DepKind)),
2403 if (Dependencies.
empty())
2423 Type *DependInfo = OMPBuilder.DependInfo;
2425 Value *DepArray =
nullptr;
2431 Builder.SetInsertPoint(
2432 Builder.GetInsertBlock()->getParent()->getEntryBlock().getTerminator());
2433 DepArray = Builder.CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
2436 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies)) {
2438 Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
2463 Value *DepArray =
nullptr;
2464 Type *DepArrayTy =
nullptr;
2465 Value *NumDeps =
nullptr;
2468 NumDeps = Dependencies.
NumDeps;
2469 }
else if (!Dependencies.
Deps.empty()) {
2471 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
2475 Builder.GetInsertBlock()->getParent()->getEntryBlock();
2477 DepArray =
Builder.CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
2480 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies.
Deps)) {
2482 Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
2496 ConstantInt::get(
Builder.getInt32Ty(), 0),
2498 ConstantInt::get(
Builder.getInt32Ty(), IsNowait)};
2501 omp::RuntimeFunction::OMPRTL___kmpc_omp_taskwait_deps_51),
2511 unsigned ProgramAddressSpace = M.getDataLayout().getProgramAddressSpace();
2523 auto *VoidPtrTy =
PointerType::get(Builder.getContext(), ProgramAddressSpace);
2526 Builder.getVoidTy(), {VoidPtrTy, VoidPtrTy, Builder.getInt32Ty()},
2530 "omp_taskloop_dup", M);
2533 Value *LastprivateFlagArg = DupFunction->
getArg(2);
2534 DestTaskArg->
setName(
"dest_task");
2535 SrcTaskArg->
setName(
"src_task");
2536 LastprivateFlagArg->
setName(
"lastprivate_flag");
2539 Builder.SetInsertPoint(
2542 auto GetTaskContextPtrFromArg = [&](
Value *Arg) ->
Value * {
2543 Type *TaskWithPrivatesTy =
2545 Value *TaskPrivates = Builder.CreateGEP(
2546 TaskWithPrivatesTy, Arg, {Builder.getInt32(0), Builder.getInt32(1)});
2547 Value *ContextPtr = Builder.CreateGEP(
2548 PrivatesTy, TaskPrivates,
2549 {Builder.getInt32(0), Builder.getInt32(PrivatesIndex)});
2553 Value *DestTaskContextPtr = GetTaskContextPtrFromArg(DestTaskArg);
2554 Value *SrcTaskContextPtr = GetTaskContextPtrFromArg(SrcTaskArg);
2556 DestTaskContextPtr->
setName(
"destPtr");
2557 SrcTaskContextPtr->
setName(
"srcPtr");
2561 Expected<IRBuilderBase::InsertPoint> AfterIPOrError =
2562 DupCB(AllocaIP, CodeGenIP, DestTaskContextPtr, SrcTaskContextPtr);
2563 if (!AfterIPOrError)
2565 Builder.restoreIP(*AfterIPOrError);
2575 llvm::function_ref<llvm::Expected<llvm::CanonicalLoopInfo *>()> LoopInfo,
2577 Value *GrainSize,
bool NoGroup,
int Sched,
Value *Final,
bool Mergeable,
2579 Value *TaskContextStructPtrVal,
bool FreeAgent) {
2584 uint32_t SrcLocStrSize;
2598 if (
Error Err = BodyGenCB(TaskloopAllocaIP, TaskloopBodyIP, TaskloopExitBB))
2601 llvm::Expected<llvm::CanonicalLoopInfo *> result = LoopInfo();
2606 llvm::CanonicalLoopInfo *CLI = result.
get();
2607 if (CLI->VirtualCollapse)
2608 CLI->reportUnsupportedVirtualCollapse();
2609 auto OI = std::make_unique<OutlineInfo>();
2610 OI->EntryBB = TaskloopAllocaBB;
2611 OI->OuterAllocBB = AllocaIP.getNodeParent();
2612 OI->ExitBB = TaskloopExitBB;
2613 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2614 copy(DeallocBlocks, OI->OuterDeallocBBs.end());
2617 SmallVector<Instruction *> ToBeDeleted;
2620 Builder, AllocaIP, ToBeDeleted, TaskloopAllocaIP,
"global.tid",
false));
2622 TaskloopAllocaIP,
"lb",
false,
true);
2624 TaskloopAllocaIP,
"ub",
false,
true);
2626 TaskloopAllocaIP,
"step",
false,
true);
2629 OI->Inputs.insert(FakeLB);
2630 OI->Inputs.insert(FakeUB);
2631 OI->Inputs.insert(FakeStep);
2632 if (TaskContextStructPtrVal)
2633 OI->Inputs.insert(TaskContextStructPtrVal);
2634 assert(((TaskContextStructPtrVal && DupCB) ||
2635 (!TaskContextStructPtrVal && !DupCB)) &&
2636 "Task context struct ptr and duplication callback must be both set "
2642 unsigned ProgramAddressSpace =
M.getDataLayout().getProgramAddressSpace();
2646 {FakeLB->getType(), FakeUB->getType(), FakeStep->getType(), PointerTy});
2647 Expected<Value *> TaskDupFnOrErr = createTaskDuplicationFunction(
2650 if (!TaskDupFnOrErr) {
2653 Value *TaskDupFn = *TaskDupFnOrErr;
2655 OI->PostOutlineCB = [
this, Ident, LBVal, UBVal, StepVal, Untied,
2656 TaskloopAllocaBB, CLI, TaskDupFn, ToBeDeleted, IfCond,
2657 GrainSize, NoGroup, Sched, FakeLB, FakeUB, FakeStep,
2658 FakeSharedsTy, Final, Mergeable, Priority,
2660 FreeAgent](
Function &OutlinedFn)
mutable {
2662 assert(OutlinedFn.hasOneUse() &&
2663 "there must be a single user for the outlined function");
2670 Value *CastedLBVal =
2671 Builder.CreateIntCast(LBVal,
Builder.getInt64Ty(),
true,
"lb64");
2672 Value *CastedUBVal =
2673 Builder.CreateIntCast(UBVal,
Builder.getInt64Ty(),
true,
"ub64");
2674 Value *CastedStepVal =
2675 Builder.CreateIntCast(StepVal,
Builder.getInt64Ty(),
true,
"step64");
2677 Builder.SetInsertPoint(StaleCI);
2690 Builder.CreateCall(TaskgroupFn, {Ident, ThreadID});
2715 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
2717 AllocaInst *ArgStructAlloca =
2719 assert(ArgStructAlloca &&
2720 "Unable to find the alloca instruction corresponding to arguments "
2721 "for extracted function");
2722 std::optional<TypeSize> ArgAllocSize =
2725 "Unable to determine size of arguments for extracted function");
2726 Value *SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
2731 CallInst *TaskData =
Builder.CreateCall(
2732 TaskAllocFn, {Ident, ThreadID,
Flags,
2733 TaskSize, SharedsSize,
2738 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
2744 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(0)});
2747 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(1)});
2750 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(2)});
2756 IfCond ?
Builder.CreateIntCast(IfCond,
Builder.getInt32Ty(),
true)
2762 Value *GrainSizeVal =
2763 GrainSize ?
Builder.CreateIntCast(GrainSize,
Builder.getInt64Ty(),
true)
2765 Value *TaskDup = TaskDupFn;
2767 Value *
Args[] = {Ident, ThreadID, TaskData, IfCondVal, Lb, Ub,
2768 Loadstep, NoGroupVal, SchedVal, GrainSizeVal, TaskDup};
2773 Builder.CreateCall(TaskloopFn, Args);
2780 Builder.CreateCall(EndTaskgroupFn, {Ident, ThreadID});
2785 Builder.SetInsertPoint(TaskloopAllocaBB->begin());
2787 LoadInst *SharedsOutlined =
2788 Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
2789 OutlinedFn.getArg(1)->replaceUsesWithIf(
2791 [SharedsOutlined](Use &U) {
return U.getUser() != SharedsOutlined; });
2794 Type *IVTy =
IV->getType();
2800 Value *TaskLB =
nullptr;
2801 Value *TaskUB =
nullptr;
2802 Value *TaskStep =
nullptr;
2803 Value *LoadTaskLB =
nullptr;
2804 Value *LoadTaskUB =
nullptr;
2805 Value *LoadTaskStep =
nullptr;
2806 for (Instruction &
I : *TaskloopAllocaBB) {
2807 if (
I.getOpcode() == Instruction::GetElementPtr) {
2810 switch (CI->getZExtValue()) {
2822 }
else if (
I.getOpcode() == Instruction::Load) {
2824 if (
Load.getPointerOperand() == TaskLB) {
2825 assert(TaskLB !=
nullptr &&
"Expected value for TaskLB");
2827 }
else if (
Load.getPointerOperand() == TaskUB) {
2828 assert(TaskUB !=
nullptr &&
"Expected value for TaskUB");
2830 }
else if (
Load.getPointerOperand() == TaskStep) {
2831 assert(TaskStep !=
nullptr &&
"Expected value for TaskStep");
2837 Builder.SetInsertPoint(CLI->getPreheader()->getTerminator());
2839 assert(LoadTaskLB !=
nullptr &&
"Expected value for LoadTaskLB");
2840 assert(LoadTaskUB !=
nullptr &&
"Expected value for LoadTaskUB");
2841 assert(LoadTaskStep !=
nullptr &&
"Expected value for LoadTaskStep");
2843 Builder.CreateSub(LoadTaskUB, LoadTaskLB), LoadTaskStep);
2844 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One,
"trip_cnt");
2845 Value *CastedTripCount =
Builder.CreateIntCast(TripCount, IVTy,
true);
2846 Value *CastedTaskLB =
Builder.CreateIntCast(LoadTaskLB, IVTy,
true);
2848 CLI->setTripCount(CastedTripCount);
2850 Builder.SetInsertPoint(CLI->getBody()->getFirstInsertionPt());
2852 if (NumOfCollapseLoops > 1) {
2858 Builder.CreateSub(CastedTaskLB, ConstantInt::get(IVTy, 1)));
2861 for (
auto IVUse = CLI->getIndVar()->uses().begin();
2862 IVUse != CLI->getIndVar()->uses().end(); IVUse++) {
2863 User *IVUser = IVUse->getUser();
2865 if (
Op->getOpcode() == Instruction::URem ||
2866 Op->getOpcode() == Instruction::UDiv) {
2871 for (User *User : UsersToReplace) {
2872 User->replaceUsesOfWith(CLI->getIndVar(), IVPlusTaskLB);
2889 assert(CLI->getIndVar()->getNumUses() == 3 &&
2890 "Canonical loop should have exactly three uses of the ind var");
2891 for (User *IVUser : CLI->getIndVar()->users()) {
2893 if (
Mul->getOpcode() == Instruction::Mul) {
2894 for (User *MulUser :
Mul->users()) {
2896 if (
Add->getOpcode() == Instruction::Add) {
2897 Add->setOperand(1, CastedTaskLB);
2906 FakeLB->replaceAllUsesWith(CastedLBVal);
2907 FakeUB->replaceAllUsesWith(CastedUBVal);
2908 FakeStep->replaceAllUsesWith(CastedStepVal);
2910 I->eraseFromParent();
2921 M.getContext(),
M.getDataLayout().getPointerSizeInBits());
2931 bool Mergeable,
Value *EventHandle,
Value *Priority,
bool FreeAgent) {
2962 if (
Error Err = BodyGenCB(TaskAllocaIP, TaskBodyIP, TaskExitBB))
2965 auto OI = std::make_unique<OutlineInfo>();
2966 OI->EntryBB = TaskAllocaBB;
2967 OI->OuterAllocBB = AllocaIP.getNodeParent();
2968 OI->ExitBB = TaskExitBB;
2969 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2970 copy(DeallocBlocks, OI->OuterDeallocBBs.
end());
2975 Builder, AllocaIP, ToBeDeleted, TaskAllocaIP,
"global.tid",
false));
2977 OI->PostOutlineCB = [
this, Ident, Tied, Final, IfCondition, Dependencies,
2978 Affinities, Mergeable, Priority, EventHandle, FreeAgent,
2980 ToBeDeleted](
Function &OutlinedFn)
mutable {
2982 assert(OutlinedFn.hasOneUse() &&
2983 "there must be a single user for the outlined function");
2988 bool HasShareds = StaleCI->
arg_size() > 1;
2989 Builder.SetInsertPoint(StaleCI);
3016 bool UseMergedIf0Path = ConstIfCondition && ConstIfCondition->isZero();
3020 Flags =
Builder.CreateOr(FinalFlag, Flags);
3023 if (Mergeable || UseMergedIf0Path)
3037 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
3046 assert(ArgStructAlloca &&
3047 "Unable to find the alloca instruction corresponding to arguments "
3048 "for extracted function");
3049 std::optional<TypeSize> ArgAllocSize =
3052 "Unable to determine size of arguments for extracted function");
3053 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
3059 TaskAllocFn, {Ident, ThreadID, Flags,
3060 TaskSize, SharedsSize,
3063 if (Affinities.
Count && Affinities.
Info) {
3065 OMPRTL___kmpc_omp_reg_task_with_affinity);
3076 OMPRTL___kmpc_task_allow_completion_event);
3080 Builder.CreatePointerBitCastOrAddrSpaceCast(EventHandle,
3082 EventVal =
Builder.CreatePtrToInt(EventVal,
Builder.getInt64Ty());
3083 Builder.CreateStore(EventVal, EventHandleAddr);
3089 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
3111 VoidPtr, VoidPtr,
Builder.getInt32Ty(), VoidPtr, VoidPtr);
3113 TaskStructType, TaskGEP, {
Zero, ConstantInt::get(Int32Ty, 4)});
3116 Value *CmplrData =
Builder.CreateInBoundsGEP(CmplrStructType,
3118 Builder.CreateStore(Priority, CmplrData);
3121 Value *DepArray =
nullptr;
3122 Value *NumDeps =
nullptr;
3125 NumDeps = Dependencies.
NumDeps;
3126 }
else if (!Dependencies.
Deps.empty()) {
3128 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
3148 if (IfCondition && !UseMergedIf0Path) {
3153 Builder.GetInsertPoint()->getParent()->getTerminator();
3154 Instruction *ThenTI = IfTerminator, *ElseTI =
nullptr;
3155 Builder.SetInsertPoint(IfTerminator);
3158 Builder.SetInsertPoint(ElseTI);
3165 {Ident, ThreadID, NumDeps, DepArray,
3166 ConstantInt::get(
Builder.getInt32Ty(), 0),
3181 Builder.SetInsertPoint(ThenTI);
3189 {Ident, ThreadID, TaskData, NumDeps, DepArray,
3190 ConstantInt::get(
Builder.getInt32Ty(), 0),
3203 LoadInst *Shareds =
Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
3204 OutlinedFn.getArg(1)->replaceUsesWithIf(
3205 Shareds, [Shareds](
Use &U) {
return U.getUser() != Shareds; });
3211 Builder.ClearInsertionPoint();
3213 I->eraseFromParent();
3239 if (
Error Err = BodyGenCB(AllocaIP,
Builder.saveIP(), DeallocBlocks))
3242 Builder.SetInsertPoint(TaskgroupExitBB);
3285 unsigned CaseNumber = 0;
3286 for (
auto SectionCB : SectionCBs) {
3288 M.getContext(),
"omp_section_loop.body.case", CurFn,
Continue);
3290 Builder.SetInsertPoint(CaseBB);
3303 Value *LB = ConstantInt::get(I32Ty, 0);
3304 Value *UB = ConstantInt::get(I32Ty, SectionCBs.
size());
3305 Value *ST = ConstantInt::get(I32Ty, 1);
3307 Loc, LoopBodyGenCB, LB, UB, ST,
true,
false, AllocaIP,
"section_loop");
3312 applyStaticWorkshareLoop(
Loc.DL, *
LoopInfo, AllocaIP,
3313 WorksharingLoopType::ForStaticLoop, !IsNowait);
3319 assert(LoopFini &&
"Bad structure of static workshare loop finalization");
3323 assert(FiniInfo.DK == OMPD_sections &&
3324 "Unexpected finalization stack state!");
3325 if (
Error Err = FiniInfo.mergeFiniBB(
Builder, LoopFini))
3339 if (IP != IP.getNodeParent()->end())
3350 auto *CaseBB =
Loc.IP.getNodeParent();
3351 auto *CondBB = CaseBB->getSinglePredecessor()->getSinglePredecessor();
3352 auto *ExitBB = CondBB->getTerminator()->getSuccessor(1);
3354 IP =
I->getIterator();
3358 Directive OMPD = Directive::OMPD_sections;
3361 return EmitOMPInlinedRegion(OMPD,
nullptr,
nullptr, BodyGenCB, FiniCBWrapper,
3372Value *OpenMPIRBuilder::getGPUThreadID() {
3375 OMPRTL___kmpc_get_hardware_thread_id_in_block),
3379Value *OpenMPIRBuilder::getGPUWarpSize() {
3384Value *OpenMPIRBuilder::getNVPTXWarpID() {
3385 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3386 return Builder.CreateAShr(getGPUThreadID(), LaneIDBits,
"nvptx_warp_id");
3389Value *OpenMPIRBuilder::getNVPTXLaneID() {
3390 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3391 assert(LaneIDBits < 32 &&
"Invalid LaneIDBits size in NVPTX device.");
3392 unsigned LaneIDMask = ~0
u >> (32u - LaneIDBits);
3393 return Builder.CreateAnd(getGPUThreadID(),
Builder.getInt32(LaneIDMask),
3400 uint64_t FromSize =
M.getDataLayout().getTypeStoreSize(FromType);
3401 uint64_t ToSize =
M.getDataLayout().getTypeStoreSize(ToType);
3402 assert(FromSize > 0 &&
"From size must be greater than zero");
3403 assert(ToSize > 0 &&
"To size must be greater than zero");
3404 if (FromType == ToType)
3406 if (FromSize == ToSize)
3407 return Builder.CreateBitCast(From, ToType);
3409 return Builder.CreateIntCast(From, ToType,
true);
3415 Value *ValCastItem =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3416 CastItem,
Builder.getPtrTy(0));
3417 Builder.CreateStore(From, ValCastItem);
3418 return Builder.CreateLoad(ToType, CastItem);
3425 uint64_t Size =
M.getDataLayout().getTypeStoreSize(ElementType);
3426 assert(
Size <= 8 &&
"Unsupported bitwidth in shuffle instruction");
3430 Value *ElemCast = castValueToType(AllocaIP, Element, CastTy);
3432 Builder.CreateIntCast(getGPUWarpSize(),
Builder.getInt16Ty(),
true);
3434 Size <= 4 ? RuntimeFunction::OMPRTL___kmpc_shuffle_int32
3435 : RuntimeFunction::OMPRTL___kmpc_shuffle_int64);
3436 Value *WarpSizeCast =
3438 Value *ShuffleCall =
3443 return castValueToType(AllocaIP, ShuffleCall, ElementType);
3450 uint64_t Size =
M.getDataLayout().getTypeStoreSize(ElemType);
3462 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3463 Value *ElemPtr = DstAddr;
3464 Value *Ptr = SrcAddr;
3465 for (
unsigned IntSize = 8; IntSize >= 1; IntSize /= 2) {
3469 Ptr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3472 Builder.CreateGEP(ElemType, SrcAddr, {ConstantInt::get(IndexTy, 1)});
3473 ElemPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3477 if ((
Size / IntSize) > 1) {
3478 Value *PtrEnd =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3479 SrcAddrGEP,
Builder.getPtrTy());
3496 Builder.CreatePointerBitCastOrAddrSpaceCast(Ptr,
Builder.getPtrTy()));
3498 Builder.CreateICmpSGT(PtrDiff,
Builder.getInt64(IntSize - 1)), ThenBB,
3501 Value *Res = createRuntimeShuffleFunction(
3504 IntType, Ptr,
M.getDataLayout().getPrefTypeAlign(ElemType)),
3506 Builder.CreateAlignedStore(Res, ElemPtr,
3507 M.getDataLayout().getPrefTypeAlign(ElemType));
3509 Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3510 Value *LocalElemPtr =
3511 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3519 Value *Res = createRuntimeShuffleFunction(
3520 AllocaIP,
Builder.CreateLoad(IntType, Ptr), IntType,
Offset);
3521 Builder.CreateStore(Res, ElemPtr);
3522 Ptr =
Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3524 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3530Error OpenMPIRBuilder::emitReductionListCopy(
3535 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3536 Value *RemoteLaneOffset = CopyOptions.RemoteLaneOffset;
3540 for (
auto En :
enumerate(ReductionInfos)) {
3542 Value *SrcElementAddr =
nullptr;
3543 AllocaInst *DestAlloca =
nullptr;
3544 Value *DestElementAddr =
nullptr;
3545 Value *DestElementPtrAddr =
nullptr;
3547 bool ShuffleInElement =
false;
3550 bool UpdateDestListPtr =
false;
3554 ReductionArrayTy, SrcBase,
3555 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3556 SrcElementAddr =
Builder.CreateLoad(
Builder.getPtrTy(), SrcElementPtrAddr);
3560 DestElementPtrAddr =
Builder.CreateInBoundsGEP(
3561 ReductionArrayTy, DestBase,
3562 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3563 bool IsByRefElem = (!IsByRef.
empty() && IsByRef[En.index()]);
3569 Type *DestAllocaType =
3570 IsByRefElem ? RI.ByRefAllocatedType : RI.ElementType;
3571 DestAlloca =
Builder.CreateAlloca(DestAllocaType,
nullptr,
3572 ".omp.reduction.element");
3574 M.getDataLayout().getPrefTypeAlign(DestAllocaType));
3575 DestElementAddr = DestAlloca;
3578 DestElementAddr->
getName() +
".ascast");
3580 ShuffleInElement =
true;
3581 UpdateDestListPtr =
true;
3593 if (ShuffleInElement) {
3594 Type *ShuffleType = RI.ElementType;
3595 Value *ShuffleSrcAddr = SrcElementAddr;
3596 Value *ShuffleDestAddr = DestElementAddr;
3597 AllocaInst *LocalStorage =
nullptr;
3600 assert(RI.ByRefElementType &&
"Expected by-ref element type to be set");
3601 assert(RI.ByRefAllocatedType &&
3602 "Expected by-ref allocated type to be set");
3607 ShuffleType = RI.ByRefElementType;
3609 if (RI.DataPtrPtrGen) {
3612 Builder.saveIP(), ShuffleSrcAddr, ShuffleSrcAddr);
3615 return GenResult.takeError();
3624 LocalStorage =
Builder.CreateAlloca(ShuffleType);
3626 ShuffleDestAddr = LocalStorage;
3631 ShuffleDestAddr = DestElementAddr;
3635 shuffleAndStore(AllocaIP, ShuffleSrcAddr, ShuffleDestAddr, ShuffleType,
3636 RemoteLaneOffset, ReductionArrayTy, IsByRefElem);
3638 if (IsByRefElem && RI.DataPtrPtrGen) {
3640 Value *DestDescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3641 DestAlloca,
Builder.getPtrTy(),
".ascast");
3644 DestDescriptorAddr, LocalStorage, SrcElementAddr,
3645 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
3648 return GenResult.takeError();
3651 switch (RI.EvaluationKind) {
3653 Value *Elem =
Builder.CreateLoad(RI.ElementType, SrcElementAddr);
3655 Builder.CreateStore(Elem, DestElementAddr);
3659 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3660 RI.ElementType, SrcElementAddr, 0, 0,
".realp");
3662 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
3664 RI.ElementType, SrcElementAddr, 0, 1,
".imagp");
3666 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
3668 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3669 RI.ElementType, DestElementAddr, 0, 0,
".realp");
3670 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
3671 RI.ElementType, DestElementAddr, 0, 1,
".imagp");
3672 Builder.CreateStore(SrcReal, DestRealPtr);
3673 Builder.CreateStore(SrcImg, DestImgPtr);
3678 M.getDataLayout().getTypeStoreSize(RI.ElementType));
3680 DestElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3681 SrcElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3693 if (UpdateDestListPtr) {
3694 Value *CastDestAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3695 DestElementAddr,
Builder.getPtrTy(),
3696 DestElementAddr->
getName() +
".ascast");
3697 Builder.CreateStore(CastDestAddr, DestElementPtrAddr);
3704Expected<Function *> OpenMPIRBuilder::emitInterWarpCopyFunction(
3707 IRBuilder<>::InsertPointGuard IPG(
Builder);
3708 LLVMContext &Ctx =
M.getContext();
3710 Builder.getVoidTy(), {Builder.getPtrTy(), Builder.getInt32Ty()},
3714 "_omp_reduction_inter_warp_copy_func", &
M);
3720 Builder.SetInsertPoint(EntryBB);
3738 StringRef TransferMediumName =
3739 "__openmp_nvptx_data_transfer_temporary_storage";
3740 GlobalVariable *TransferMedium =
M.getGlobalVariable(TransferMediumName);
3741 unsigned WarpSize =
Config.getGridValue().GV_Warp_Size;
3743 if (!TransferMedium) {
3744 TransferMedium =
new GlobalVariable(
3752 Value *GPUThreadID = getGPUThreadID();
3754 Value *LaneID = getNVPTXLaneID();
3756 Value *WarpID = getNVPTXWarpID();
3762 AllocaInst *ReduceListAlloca =
Builder.CreateAlloca(
3763 Arg0Type,
nullptr, ReduceListArg->
getName() +
".addr");
3764 AllocaInst *NumWarpsAlloca =
3765 Builder.CreateAlloca(Arg1Type,
nullptr, NumWarpsArg->
getName() +
".addr");
3766 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3767 ReduceListAlloca, Arg0Type, ReduceListAlloca->
getName() +
".ascast");
3768 Value *NumWarpsAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3769 NumWarpsAlloca,
Builder.getPtrTy(0),
3770 NumWarpsAlloca->
getName() +
".ascast");
3771 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
3772 Builder.CreateStore(NumWarpsArg, NumWarpsAddrCast);
3781 for (
auto En :
enumerate(ReductionInfos)) {
3787 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
3788 unsigned RealTySize =
M.getDataLayout().getTypeAllocSize(
3789 IsByRefElem ? RI.ByRefElementType : RI.ElementType);
3790 for (
unsigned TySize = 4; TySize > 0 && RealTySize > 0; TySize /= 2) {
3793 unsigned NumIters = RealTySize / TySize;
3796 Value *Cnt =
nullptr;
3797 Value *CntAddr =
nullptr;
3804 Builder.CreateAlloca(
Builder.getInt32Ty(),
nullptr,
".cnt.addr");
3806 CntAddr =
Builder.CreateAddrSpaceCast(CntAddr,
Builder.getPtrTy(),
3807 CntAddr->
getName() +
".ascast");
3819 Cnt, ConstantInt::get(
Builder.getInt32Ty(), NumIters));
3820 Builder.CreateCondBr(Cmp, BodyBB, ExitBB);
3827 omp::Directive::OMPD_unknown,
3831 return BarrierIP1.takeError();
3837 Value *IsWarpMaster =
Builder.CreateIsNull(LaneID,
"warp_master");
3838 Builder.CreateCondBr(IsWarpMaster, ThenBB, ElseBB);
3842 auto *RedListArrayTy =
3845 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3847 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3848 {ConstantInt::get(IndexTy, 0),
3849 ConstantInt::get(IndexTy, En.index())});
3853 if (IsByRefElem && RI.DataPtrPtrGen) {
3855 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
3858 return GenRes.takeError();
3869 ArrayTy, TransferMedium, {
Builder.getInt64(0), WarpID});
3874 Builder.CreateStore(Elem, MediumPtr,
3886 omp::Directive::OMPD_unknown,
3890 return BarrierIP2.takeError();
3897 Value *NumWarpsVal =
3900 Value *IsActiveThread =
3901 Builder.CreateICmpULT(GPUThreadID, NumWarpsVal,
"is_active_thread");
3902 Builder.CreateCondBr(IsActiveThread, W0ThenBB, W0ElseBB);
3909 ArrayTy, TransferMedium, {
Builder.getInt64(0), GPUThreadID});
3911 Value *TargetElemPtrPtr =
3912 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3913 {ConstantInt::get(IndexTy, 0),
3914 ConstantInt::get(IndexTy, En.index())});
3915 Value *TargetElemPtrVal =
3917 Value *TargetElemPtr = TargetElemPtrVal;
3919 if (IsByRefElem && RI.DataPtrPtrGen) {
3921 RI.DataPtrPtrGen(
Builder.saveIP(), TargetElemPtr, TargetElemPtr);
3924 return GenRes.takeError();
3926 TargetElemPtr =
Builder.CreateLoad(
Builder.getPtrTy(), TargetElemPtr);
3934 Value *SrcMediumValue =
3935 Builder.CreateLoad(CType, SrcMediumPtrVal,
true);
3936 Builder.CreateStore(SrcMediumValue, TargetElemPtr);
3946 Cnt, ConstantInt::get(
Builder.getInt32Ty(), 1));
3947 Builder.CreateStore(Cnt, CntAddr,
false);
3949 auto *CurFn =
Builder.GetInsertBlock()->getParent();
3953 RealTySize %= TySize;
3962Expected<Function *> OpenMPIRBuilder::emitShuffleAndReduceFunction(
3965 LLVMContext &Ctx =
M.getContext();
3966 IRBuilder<>::InsertPointGuard IPG(
Builder);
3967 FunctionType *FuncTy =
3969 {Builder.getPtrTy(), Builder.getInt16Ty(),
3970 Builder.getInt16Ty(), Builder.getInt16Ty()},
3974 "_omp_reduction_shuffle_and_reduce_func", &
M);
3985 Builder.SetInsertPoint(EntryBB);
3997 Type *ReduceListArgType = ReduceListArg->
getType();
4001 ReduceListArgType,
nullptr, ReduceListArg->
getName() +
".addr");
4002 Value *LaneIdAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
4003 LaneIDArg->
getName() +
".addr");
4005 LaneIDArgType,
nullptr, RemoteLaneOffsetArg->
getName() +
".addr");
4006 Value *AlgoVerAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
4007 AlgoVerArg->
getName() +
".addr");
4014 RedListArrayTy,
nullptr,
".omp.reduction.remote_reduce_list");
4016 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4017 ReduceListAlloca, ReduceListArgType,
4018 ReduceListAlloca->
getName() +
".ascast");
4019 Value *LaneIdAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4020 LaneIdAlloca, LaneIDArgPtrType, LaneIdAlloca->
getName() +
".ascast");
4021 Value *RemoteLaneOffsetAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4022 RemoteLaneOffsetAlloca, LaneIDArgPtrType,
4023 RemoteLaneOffsetAlloca->
getName() +
".ascast");
4024 Value *AlgoVerAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4025 AlgoVerAlloca, LaneIDArgPtrType, AlgoVerAlloca->
getName() +
".ascast");
4026 Value *RemoteListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4027 RemoteReductionListAlloca,
Builder.getPtrTy(),
4028 RemoteReductionListAlloca->
getName() +
".ascast");
4030 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
4031 Builder.CreateStore(LaneIDArg, LaneIdAddrCast);
4032 Builder.CreateStore(RemoteLaneOffsetArg, RemoteLaneOffsetAddrCast);
4033 Builder.CreateStore(AlgoVerArg, AlgoVerAddrCast);
4035 Value *ReduceList =
Builder.CreateLoad(ReduceListArgType, ReduceListAddrCast);
4036 Value *LaneId =
Builder.CreateLoad(LaneIDArgType, LaneIdAddrCast);
4037 Value *RemoteLaneOffset =
4038 Builder.CreateLoad(LaneIDArgType, RemoteLaneOffsetAddrCast);
4039 Value *AlgoVer =
Builder.CreateLoad(LaneIDArgType, AlgoVerAddrCast);
4046 Error EmitRedLsCpRes = emitReductionListCopy(
4048 ReduceList, RemoteListAddrCast, IsByRef,
4049 {RemoteLaneOffset,
nullptr,
nullptr});
4052 return EmitRedLsCpRes;
4077 Value *LaneComp =
Builder.CreateICmpULT(LaneId, RemoteLaneOffset);
4082 Value *Algo2AndLaneIdComp =
Builder.CreateAnd(Algo2, LaneIdComp);
4083 Value *RemoteOffsetComp =
4085 Value *CondAlgo2 =
Builder.CreateAnd(Algo2AndLaneIdComp, RemoteOffsetComp);
4086 Value *CA0OrCA1 =
Builder.CreateOr(CondAlgo0, CondAlgo1);
4087 Value *CondReduce =
Builder.CreateOr(CA0OrCA1, CondAlgo2);
4093 Builder.CreateCondBr(CondReduce, ThenBB, ElseBB);
4095 Value *LocalReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4096 ReduceList,
Builder.getPtrTy());
4097 Value *RemoteReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4098 RemoteListAddrCast,
Builder.getPtrTy());
4100 ->addFnAttr(Attribute::NoUnwind);
4111 Value *LaneIdGtOffset =
Builder.CreateICmpUGE(LaneId, RemoteLaneOffset);
4112 Value *CondCopy =
Builder.CreateAnd(Algo1, LaneIdGtOffset);
4117 Builder.CreateCondBr(CondCopy, CpyThenBB, CpyElseBB);
4121 EmitRedLsCpRes = emitReductionListCopy(
4123 RemoteListAddrCast, ReduceList, IsByRef);
4126 return EmitRedLsCpRes;
4141OpenMPIRBuilder::generateReductionDescriptor(
4143 Type *DescriptorType,
4149 Value *DescriptorSize =
4150 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(DescriptorType));
4152 DescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4153 SrcDescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4157 Value *DataPtrField;
4159 DataPtrPtrGen(
Builder.saveIP(), DescriptorAddr, DataPtrField);
4162 return GenResult.takeError();
4165 DataPtr,
Builder.getPtrTy(),
".ascast"),
4171Expected<Value *> OpenMPIRBuilder::createReductionDescriptorCopy(
4173 Value *SrcDescriptorAddr,
Type *DescriptorPtrTy,
const Twine &Name) {
4177 AllocaInst *DescriptorAlloca =
4178 Builder.CreateAlloca(RI.ByRefAllocatedType,
nullptr, Name);
4180 M.getDataLayout().getPrefTypeAlign(RI.ByRefAllocatedType));
4181 Value *DescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4182 DescriptorAlloca, DescriptorPtrTy,
4183 DescriptorAlloca->
getName() +
".ascast");
4188 generateReductionDescriptor(DescriptorAddr, DataPtr, SrcDescriptorAddr,
4189 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
4191 return GenResult.takeError();
4193 return DescriptorAddr;
4196Expected<Function *> OpenMPIRBuilder::emitListToGlobalCopyFunction(
4199 IRBuilder<>::InsertPointGuard IPG(
Builder);
4200 LLVMContext &Ctx =
M.getContext();
4203 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4207 "_omp_reduction_list_to_global_copy_func", &
M);
4214 Builder.SetInsertPoint(EntryBlock);
4225 BufferArg->
getName() +
".addr");
4229 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4230 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4231 BufferArgAlloca,
Builder.getPtrTy(),
4232 BufferArgAlloca->
getName() +
".ascast");
4233 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4234 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4235 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4236 ReduceListArgAlloca,
Builder.getPtrTy(),
4237 ReduceListArgAlloca->
getName() +
".ascast");
4239 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4240 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4241 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4243 Value *LocalReduceList =
4245 Value *BufferArgVal =
4249 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4250 for (
auto En :
enumerate(ReductionInfos)) {
4252 auto *RedListArrayTy =
4256 RedListArrayTy, LocalReduceList,
4257 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4263 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferArgVal, Idxs);
4265 ReductionsBufferTy, BufferVD, 0, En.index());
4267 switch (RI.EvaluationKind) {
4269 Value *TargetElement;
4271 if (IsByRef.
empty() || !IsByRef[En.index()]) {
4272 TargetElement =
Builder.CreateLoad(RI.ElementType, ElemPtr);
4274 if (RI.DataPtrPtrGen) {
4276 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
4279 return GenResult.takeError();
4283 TargetElement =
Builder.CreateLoad(RI.ByRefElementType, ElemPtr);
4286 Builder.CreateStore(TargetElement, GlobVal);
4290 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4291 RI.ElementType, ElemPtr, 0, 0,
".realp");
4293 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
4295 RI.ElementType, ElemPtr, 0, 1,
".imagp");
4297 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
4299 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4300 RI.ElementType, GlobVal, 0, 0,
".realp");
4301 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4302 RI.ElementType, GlobVal, 0, 1,
".imagp");
4303 Builder.CreateStore(SrcReal, DestRealPtr);
4304 Builder.CreateStore(SrcImg, DestImgPtr);
4309 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(RI.ElementType));
4311 GlobVal,
M.getDataLayout().getPrefTypeAlign(RI.ElementType), ElemPtr,
4312 M.getDataLayout().getPrefTypeAlign(RI.ElementType), SizeVal,
false);
4322Expected<Function *> OpenMPIRBuilder::emitListToGlobalReduceFunction(
4325 IRBuilder<>::InsertPointGuard IPG(
Builder);
4326 LLVMContext &Ctx =
M.getContext();
4329 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4333 "_omp_reduction_list_to_global_reduce_func", &
M);
4340 Builder.SetInsertPoint(EntryBlock);
4351 BufferArg->
getName() +
".addr");
4355 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4356 auto *RedListArrayTy =
4361 Value *LocalReduceList =
4362 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4366 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4367 BufferArgAlloca,
Builder.getPtrTy(),
4368 BufferArgAlloca->
getName() +
".ascast");
4369 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4370 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4371 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4372 ReduceListArgAlloca,
Builder.getPtrTy(),
4373 ReduceListArgAlloca->
getName() +
".ascast");
4374 Value *LocalReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4375 LocalReduceList,
Builder.getPtrTy(),
4376 LocalReduceList->
getName() +
".ascast");
4378 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4379 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4380 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4385 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4386 for (
auto En :
enumerate(ReductionInfos)) {
4389 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4390 RedListArrayTy, LocalReduceListAddrCast,
4391 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4393 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4395 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4396 ReductionsBufferTy, BufferVD, 0, En.index());
4398 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4402 Value *SrcElementPtrPtr =
4403 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
4404 {ConstantInt::get(IndexTy, 0),
4405 ConstantInt::get(IndexTy, En.index())});
4406 Value *SrcDescriptorAddr =
4410 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4411 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4415 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4417 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4425 ->addFnAttr(Attribute::NoUnwind);
4430Expected<Function *> OpenMPIRBuilder::emitGlobalToListCopyFunction(
4433 IRBuilder<>::InsertPointGuard IPG(
Builder);
4434 LLVMContext &Ctx =
M.getContext();
4437 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4441 "_omp_reduction_global_to_list_copy_func", &
M);
4448 Builder.SetInsertPoint(EntryBlock);
4459 BufferArg->
getName() +
".addr");
4463 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4464 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4465 BufferArgAlloca,
Builder.getPtrTy(),
4466 BufferArgAlloca->
getName() +
".ascast");
4467 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4468 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4469 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4470 ReduceListArgAlloca,
Builder.getPtrTy(),
4471 ReduceListArgAlloca->
getName() +
".ascast");
4472 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4473 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4474 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4476 Value *LocalReduceList =
4481 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4482 for (
auto En :
enumerate(ReductionInfos)) {
4483 const OpenMPIRBuilder::ReductionInfo &RI = En.value();
4484 auto *RedListArrayTy =
4488 RedListArrayTy, LocalReduceList,
4489 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4494 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4495 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4496 ReductionsBufferTy, BufferVD, 0, En.index());
4502 if (!IsByRef.
empty() && IsByRef[En.index()]) {
4509 return GenResult.takeError();
4515 Value *TargetElement =
Builder.CreateLoad(ElemType, GlobValPtr);
4516 Builder.CreateStore(TargetElement, ElemPtr);
4520 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4529 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4531 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4533 Builder.CreateStore(SrcReal, DestRealPtr);
4534 Builder.CreateStore(SrcImg, DestImgPtr);
4541 ElemPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4542 GlobValPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4553Expected<Function *> OpenMPIRBuilder::emitGlobalToListReduceFunction(
4556 IRBuilder<>::InsertPointGuard IPG(
Builder);
4557 LLVMContext &Ctx =
M.getContext();
4560 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4564 "_omp_reduction_global_to_list_reduce_func", &
M);
4571 Builder.SetInsertPoint(EntryBlock);
4582 BufferArg->
getName() +
".addr");
4586 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4592 Value *LocalReduceList =
4593 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4597 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4598 BufferArgAlloca,
Builder.getPtrTy(),
4599 BufferArgAlloca->
getName() +
".ascast");
4600 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4601 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4602 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4603 ReduceListArgAlloca,
Builder.getPtrTy(),
4604 ReduceListArgAlloca->
getName() +
".ascast");
4605 Value *ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4606 LocalReduceList,
Builder.getPtrTy(),
4607 LocalReduceList->
getName() +
".ascast");
4609 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4610 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4611 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4616 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4617 for (
auto En :
enumerate(ReductionInfos)) {
4620 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4621 RedListArrayTy, ReductionList,
4622 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4625 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4626 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4627 ReductionsBufferTy, BufferVD, 0, En.index());
4629 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4631 Value *ReduceListVal =
4633 Value *SrcElementPtrPtr =
4634 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceListVal,
4635 {ConstantInt::get(IndexTy, 0),
4636 ConstantInt::get(IndexTy, En.index())});
4637 Value *SrcDescriptorAddr =
4641 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4642 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4646 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4648 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4656 ->addFnAttr(Attribute::NoUnwind);
4661std::string OpenMPIRBuilder::getReductionFuncName(StringRef Name)
const {
4662 std::string Suffix =
4664 return (Name + Suffix).str();
4667Expected<Function *> OpenMPIRBuilder::createReductionFunction(
4670 AttributeList FuncAttrs) {
4671 IRBuilder<>::InsertPointGuard IPG(
Builder);
4673 {Builder.getPtrTy(), Builder.getPtrTy()},
4675 std::string
Name = getReductionFuncName(ReducerName);
4684 Builder.SetInsertPoint(EntryBB);
4689 Value *LHSArrayPtr =
nullptr;
4690 Value *RHSArrayPtr =
nullptr;
4697 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
4699 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
4700 Value *LHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4701 LHSAlloca, Arg0Type, LHSAlloca->
getName() +
".ascast");
4702 Value *RHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4703 RHSAlloca, Arg1Type, RHSAlloca->
getName() +
".ascast");
4704 Builder.CreateStore(Arg0, LHSAddrCast);
4705 Builder.CreateStore(Arg1, RHSAddrCast);
4706 LHSArrayPtr =
Builder.CreateLoad(Arg0Type, LHSAddrCast);
4707 RHSArrayPtr =
Builder.CreateLoad(Arg1Type, RHSAddrCast);
4711 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4713 for (
auto En :
enumerate(ReductionInfos)) {
4716 RedArrayTy, RHSArrayPtr,
4717 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4719 Value *RHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4720 RHSI8Ptr, RI.PrivateVariable->getType(),
4721 RHSI8Ptr->
getName() +
".ascast");
4724 RedArrayTy, LHSArrayPtr,
4725 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4727 Value *LHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4728 LHSI8Ptr, RI.Variable->getType(), LHSI8Ptr->
getName() +
".ascast");
4737 if (!IsByRef.
empty() && !IsByRef[En.index()]) {
4738 LHS =
Builder.CreateLoad(RI.ElementType, LHSPtr);
4739 RHS =
Builder.CreateLoad(RI.ElementType, RHSPtr);
4746 return AfterIP.takeError();
4747 if (!
Builder.GetInsertBlock())
4748 return ReductionFunc;
4752 if (!IsByRef.
empty() && !IsByRef[En.index()])
4753 Builder.CreateStore(Reduced, LHSPtr);
4758 for (
auto En :
enumerate(ReductionInfos)) {
4759 unsigned Index = En.index();
4761 Value *LHSFixupPtr, *RHSFixupPtr;
4762 Builder.restoreIP(RI.ReductionGenClang(
4763 Builder.saveIP(), Index, &LHSFixupPtr, &RHSFixupPtr, ReductionFunc));
4768 LHSPtrs[Index], [ReductionFunc](
const Use &U) {
4773 RHSPtrs[Index], [ReductionFunc](
const Use &U) {
4787 return ReductionFunc;
4795 assert(RI.Variable &&
"expected non-null variable");
4796 assert(RI.PrivateVariable &&
"expected non-null private variable");
4797 assert((RI.ReductionGen || RI.ReductionGenClang) &&
4798 "expected non-null reduction generator callback");
4801 RI.Variable->getType() == RI.PrivateVariable->getType() &&
4802 "expected variables and their private equivalents to have the same "
4805 assert(RI.Variable->getType()->isPointerTy() &&
4806 "expected variables to be pointers");
4823 ArrayRef<bool> IsByRef,
bool IsNoWait,
bool IsTeamsReduction,
bool IsSPMD,
4825 Value *SrcLocInfo) {
4840 if (ReductionInfos.
size() == 0)
4854 AttrBuilder AttrBldr(Ctx);
4856 AttrBldr.addAttribute(Attr);
4857 AttrBldr.removeAttribute(Attribute::OptimizeNone);
4858 FuncAttrs = FuncAttrs.addFnAttributes(Ctx, AttrBldr);
4861 Builder.GetInsertBlock()->getParent()->getName(), ReductionInfos, IsByRef,
4863 if (!ReductionResult)
4865 Function *ReductionFunc = *ReductionResult;
4868 if (GridValue.has_value())
4869 Config.setGridValue(GridValue.value());
4884 Builder.getPtrTy(
M.getDataLayout().getProgramAddressSpace());
4886 Value *ReductionList;
4890 Value *ReductionListAlloca =
4891 Builder.CreateAlloca(RedArrayTy,
nullptr,
".omp.reduction.red_list");
4892 ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4893 ReductionListAlloca, PtrTy, ReductionListAlloca->
getName() +
".ascast");
4896 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4897 for (
auto En :
enumerate(ReductionInfos)) {
4900 RedArrayTy, ReductionList,
4901 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4904 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
4909 Builder.CreatePointerBitCastOrAddrSpaceCast(PrivateVar, PtrTy);
4910 Builder.CreateStore(CastElem, ElemPtr);
4913 ReductionInfos, ReductionFunc, FuncAttrs, IsByRef);
4919 emitInterWarpCopyFunction(
Loc, ReductionInfos, FuncAttrs, IsByRef);
4924 Value *RL =
Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList, PtrTy);
4933 unsigned MaxDataSize = 0;
4935 for (
auto En :
enumerate(ReductionInfos)) {
4939 Type *RedTypeArg = (!IsByRef.
empty() && IsByRef[En.index()])
4940 ? En.value().ByRefElementType
4941 : En.value().ElementType;
4942 auto Size =
M.getDataLayout().getTypeStoreSize(RedTypeArg);
4943 if (
Size > MaxDataSize)
4947 Value *ReductionDataSize =
4948 Builder.getInt64(MaxDataSize * ReductionInfos.
size());
4952 Function *CopyScratchToListFunc =
nullptr;
4954 Value *ScratchForCopyBack =
nullptr;
4957 Value *RLForCopyBack = RL;
4959 bool IsAtomicReduction =
4962 if (!IsTeamsReduction) {
4963 Value *SarFuncCast =
4964 Builder.CreatePointerBitCastOrAddrSpaceCast(*SarFunc, FuncPtrTy);
4966 Builder.CreatePointerBitCastOrAddrSpaceCast(WcFunc, FuncPtrTy);
4967 Value *Args[] = {SrcLocInfo, ReductionDataSize, RL, SarFuncCast,
4970 RuntimeFunction::OMPRTL___kmpc_nvptx_parallel_reduce_nowait_v2);
4972 }
else if (IsAtomicReduction) {
4976 RuntimeFunction::OMPRTL___kmpc_is_team_main_thread);
4980 Ctx, ReductionTypeArgs,
"struct._globalized_locals_ty");
4983 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
4988 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
4993 ReductionInfos, ReductionFunc, ReductionsBufferTy, FuncAttrs, IsByRef);
5014 Value *RuntimeRL = RL;
5017 Value *PerThreadScratch;
5023 Value *PerThreadScratchAlloca =
5024 Builder.CreateAlloca(ReductionsBufferTy,
nullptr,
5025 ".omp.reduction.scratch");
5026 PerThreadScratch =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5027 PerThreadScratchAlloca, PtrTy,
5028 PerThreadScratchAlloca->
getName() +
".ascast");
5031 Value *PerThreadRedListAlloca =
5032 Builder.CreateAlloca(RedArrayTy,
nullptr,
5033 ".omp.reduction.per_thread_red_list");
5034 RuntimeRL =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5035 PerThreadRedListAlloca, PtrTy,
5036 PerThreadRedListAlloca->
getName() +
".ascast");
5041 for (
auto En :
enumerate(ReductionInfos)) {
5043 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
5046 ReductionsBufferTy, PerThreadScratch, 0, En.index());
5047 Value *Slot =
Builder.CreateConstInBoundsGEP2_32(RedArrayTy, RuntimeRL,
5050 Value *RuntimeListEntry = FieldPtr;
5052 Value *SrcDescriptor =
5055 AllocaIP, RI, FieldPtr, SrcDescriptor, PtrTy);
5058 RuntimeListEntry = *Descriptor;
5060 Builder.CreateStore(RuntimeListEntry, Slot);
5066 Type *CopyArg0Ty = (*LtGCFunc)->getFunctionType()->getParamType(0);
5067 Type *CopyArg2Ty = (*LtGCFunc)->getFunctionType()->getParamType(2);
5068 ScratchForCopyBack =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5069 PerThreadScratch, CopyArg0Ty);
5071 Builder.CreatePointerBitCastOrAddrSpaceCast(RL, CopyArg2Ty);
5079 *LtGCFunc, {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
5080 CopyScratchToListFunc = *GtLCFunc;
5083 Value *Args3[] = {SrcLocInfo, RuntimeRL, *SarFunc, WcFunc,
5084 *LtGCFunc, *GtLCFunc, *GtLRFunc};
5087 RuntimeFunction::OMPRTL___kmpc_gpu_xteam_reduce_nowait);
5107 if (ScratchForCopyBack) {
5110 CopyScratchToListFunc,
5111 {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
5115 for (
auto En :
enumerate(ReductionInfos)) {
5121 if (IsAtomicReduction) {
5137 Value *LHSPtr, *RHSPtr;
5139 &LHSPtr, &RHSPtr, CurFunc));
5145 RedValue =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5147 if (RHSPtr->
getType() != RHS->getType())
5149 Builder.CreatePointerBitCastOrAddrSpaceCast(RHS, RHSPtr->
getType());
5160 if (IsByRef.
empty() || !IsByRef[En.index()]) {
5162 "red.value." +
Twine(En.index()));
5173 if (!IsByRef.
empty() && !IsByRef[En.index()])
5178 if (ContinuationBlock) {
5179 Builder.CreateBr(ContinuationBlock);
5180 Builder.SetInsertPoint(ContinuationBlock);
5182 Config.setEmitLLVMUsed();
5193 ".omp.reduction.func", &M);
5204 Builder.SetInsertPoint(ReductionFuncBlock);
5206 Value *LHSArrayPtr =
nullptr;
5207 Value *RHSArrayPtr =
nullptr;
5218 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
5220 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
5221 Value *LHSAddrCast =
5222 Builder.CreatePointerBitCastOrAddrSpaceCast(LHSAlloca, Arg0Type);
5223 Value *RHSAddrCast =
5224 Builder.CreatePointerBitCastOrAddrSpaceCast(RHSAlloca, Arg1Type);
5225 Builder.CreateStore(Arg0, LHSAddrCast);
5226 Builder.CreateStore(Arg1, RHSAddrCast);
5227 LHSArrayPtr = Builder.CreateLoad(Arg0Type, LHSAddrCast);
5228 RHSArrayPtr = Builder.CreateLoad(Arg1Type, RHSAddrCast);
5230 LHSArrayPtr = ReductionFunc->
getArg(0);
5231 RHSArrayPtr = ReductionFunc->
getArg(1);
5234 unsigned NumReductions = ReductionInfos.
size();
5237 for (
auto En :
enumerate(ReductionInfos)) {
5239 Value *LHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5240 RedArrayTy, LHSArrayPtr, 0, En.index());
5241 Value *LHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), LHSI8PtrPtr);
5242 Value *LHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5245 Value *RHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5246 RedArrayTy, RHSArrayPtr, 0, En.index());
5247 Value *RHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), RHSI8PtrPtr);
5248 Value *RHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5257 Builder.restoreIP(*AfterIP);
5259 if (!Builder.GetInsertBlock())
5263 if (!IsByRef[En.index()])
5264 Builder.CreateStore(Reduced, LHSPtr);
5266 Builder.CreateRetVoid();
5273 bool IsNoWait,
bool IsTeamsReduction) {
5277 IsByRef, IsNoWait, IsTeamsReduction);
5284 if (ReductionInfos.
size() == 0)
5294 unsigned NumReductions = ReductionInfos.
size();
5296 Builder.SetInsertPoint(AllocaIP.getNodeParent()->getTerminator());
5297 Value *RedArray =
Builder.CreateAlloca(RedArrayTy,
nullptr,
"red.array");
5304 for (
auto En :
enumerate(ReductionInfos)) {
5305 unsigned Index = En.index();
5307 Value *RedArrayElemPtr =
Builder.CreateConstInBoundsGEP2_64(
5308 RedArrayTy, RedArray, 0, Index,
"red.array.elem." +
Twine(Index));
5315 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
5325 ? IdentFlag::OMP_IDENT_FLAG_ATOMIC_REDUCE
5330 unsigned RedArrayByteSize =
DL.getTypeStoreSize(RedArrayTy);
5331 Constant *RedArraySize = ConstantInt::get(IndexTy, RedArrayByteSize);
5333 Value *Lock = getOMPCriticalRegionLock(
".reduction");
5335 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_reduce_nowait
5336 : RuntimeFunction::OMPRTL___kmpc_reduce);
5339 {Ident, ThreadId, NumVariables, RedArraySize,
5340 RedArray, ReductionFunc, Lock},
5351 Builder.CreateSwitch(ReduceCall, ContinuationBlock, 2);
5352 Switch->addCase(
Builder.getInt32(1), NonAtomicRedBlock);
5353 Switch->addCase(
Builder.getInt32(2), AtomicRedBlock);
5358 Builder.SetInsertPoint(NonAtomicRedBlock);
5359 for (
auto En :
enumerate(ReductionInfos)) {
5365 if (!IsByRef[En.index()]) {
5367 "red.value." +
Twine(En.index()));
5369 Value *PrivateRedValue =
5371 "red.private.value." +
Twine(En.index()));
5379 if (!
Builder.GetInsertBlock())
5382 if (!IsByRef[En.index()])
5386 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_end_reduce_nowait
5387 : RuntimeFunction::OMPRTL___kmpc_end_reduce);
5389 Builder.CreateBr(ContinuationBlock);
5394 Builder.SetInsertPoint(AtomicRedBlock);
5395 if (CanGenerateAtomic &&
llvm::none_of(IsByRef, [](
bool P) {
return P; })) {
5402 if (!
Builder.GetInsertBlock())
5405 Builder.CreateBr(ContinuationBlock);
5418 if (!
Builder.GetInsertBlock())
5421 Builder.SetInsertPoint(ContinuationBlock);
5432 Directive OMPD = Directive::OMPD_master;
5437 Value *Args[] = {Ident, ThreadId};
5445 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5457 Directive OMPD = Directive::OMPD_masked;
5463 Value *ArgsEnd[] = {Ident, ThreadId};
5471 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5481 Call->setDoesNotThrow();
5496 bool IsInclusive,
ScanInfo *ScanRedInfo) {
5498 llvm::Error Err = emitScanBasedDirectiveDeclsIR(AllocaIP, ScanVars,
5499 ScanVarsType, ScanRedInfo);
5510 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5513 Type *DestTy = ScanVarsType[i];
5514 Value *Val =
Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5517 Builder.CreateStore(Src, Val);
5522 Builder.GetInsertBlock()->getParent());
5525 IV = ScanRedInfo->
IV;
5528 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5531 Type *DestTy = ScanVarsType[i];
5533 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5535 Builder.CreateStore(Src, ScanVars[i]);
5549 Builder.GetInsertBlock()->getParent());
5554Error OpenMPIRBuilder::emitScanBasedDirectiveDeclsIR(
5558 Builder.restoreIP(AllocaIP);
5560 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5562 Builder.CreateAlloca(Builder.getPtrTy(),
nullptr,
"vla");
5569 Builder.restoreIP(CodeGenIP);
5571 Builder.CreateAdd(ScanRedInfo->
Span, Builder.getInt32(1));
5572 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5574 Value *Allocsize = Builder.CreateTypeSize(
5575 IntPtrTy, M.getDataLayout().getTypeAllocSize(ScanVarsType[i]));
5577 Builder.CreateMalloc(
IntPtrTy, Allocsize, AllocSpan,
nullptr,
"arr");
5578 Builder.CreateStore(Buff, (*(ScanRedInfo->
ScanBuffPtrs))[ScanVars[i]]);
5605Error OpenMPIRBuilder::emitScanBasedDirectiveFinalsIR(
5611 Value *PrivateVar = RedInfo.PrivateVariable;
5612 Value *OrigVar = RedInfo.Variable;
5616 Type *SrcTy = RedInfo.ElementType;
5621 Builder.CreateStore(Src, OrigVar);
5682 llvm::ConstantInt::get(ScanRedInfo->
Span->
getType(), 1));
5683 Builder.SetInsertPoint(InputBB);
5686 Builder.SetInsertPoint(LoopBB);
5702 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5704 Builder.SetInsertPoint(InnerLoopBB);
5708 Value *ReductionVal = RedInfo.PrivateVariable;
5711 Type *DestTy = RedInfo.ElementType;
5714 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5717 Builder.CreateInBoundsGEP(DestTy, Buff, OffsetIval,
"arrayOffset");
5722 RedInfo.ReductionGen(
Builder.saveIP(), LHS, RHS, Result);
5725 Builder.CreateStore(Result, LHSPtr);
5728 IVal, llvm::ConstantInt::get(
Builder.getInt32Ty(), 1));
5730 CmpI =
Builder.CreateICmpUGE(NextIVal, Pow2K);
5731 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5734 Counter, llvm::ConstantInt::get(Counter->
getType(), 1));
5740 Builder.CreateCondBr(Cmp, LoopBB, ExitBB);
5761 Error Err = emitScanBasedDirectiveFinalsIR(ReductionInfos, ScanRedInfo);
5768Error OpenMPIRBuilder::emitScanBasedDirectiveIR(
5780 Error Err = InputLoopGen();
5791 Error Err = ScanLoopGen(Builder);
5798void OpenMPIRBuilder::createScanBBs(ScanInfo *ScanRedInfo) {
5835 Builder.SetInsertPoint(Preheader);
5838 Builder.SetInsertPoint(Header);
5839 PHINode *IndVarPHI =
Builder.CreatePHI(IndVarTy, 2,
"omp_" + Name +
".iv");
5840 IndVarPHI->
addIncoming(ConstantInt::get(IndVarTy, 0), Preheader);
5845 Builder.CreateICmpULT(IndVarPHI, TripCount,
"omp_" + Name +
".cmp");
5846 Builder.CreateCondBr(Cmp, Body, Exit);
5851 Builder.SetInsertPoint(Latch);
5861 bool HasNSW =
Config.hasNoSignedWrap();
5864 unsigned BitWidth = CI->getType()->getIntegerBitWidth();
5866 if (CI->getValue().ugt(SignedMax))
5868 }
else if (IsCollapsed) {
5873 Builder.CreateAdd(IndVarPHI, ConstantInt::get(IndVarTy, 1),
5874 "omp_" + Name +
".next",
true, HasNSW);
5885 CL->Header = Header;
5904 NextBB, NextBB, Name);
5936 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
5945 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
5946 ScanRedInfo->
Span = TripCount;
5952 ScanRedInfo->
IV =
IV;
5953 createScanBBs(ScanRedInfo);
5956 assert(Terminator->getNumSuccessors() == 1);
5957 BasicBlock *ContinueBlock = Terminator->getSuccessor(0);
5960 Builder.GetInsertBlock()->getParent());
5963 Builder.GetInsertBlock()->getParent());
5964 Builder.CreateBr(ContinueBlock);
5970 const auto &&InputLoopGen = [&]() ->
Error {
5973 InclusiveStop, ComputeIP, Name,
true, ScanRedInfo);
5977 Builder.restoreIP((*LoopInfo)->getAfterIP());
5983 InclusiveStop, ComputeIP, Name,
true, ScanRedInfo);
5987 Builder.restoreIP((*LoopInfo)->getAfterIP());
5991 Error Err = emitScanBasedDirectiveIR(InputLoopGen, ScanLoopGen, ScanRedInfo);
5999 bool IsSigned,
bool InclusiveStop,
const Twine &Name) {
6009 assert(IndVarTy == Stop->
getType() &&
"Stop type mismatch");
6010 assert(IndVarTy == Step->
getType() &&
"Step type mismatch");
6030 Incr =
Builder.CreateSelect(IsNeg,
Builder.CreateNeg(Step), Step);
6033 Span =
Builder.CreateSub(UB, LB,
"",
false,
true);
6037 Span =
Builder.CreateSub(Stop, Start,
"",
true);
6042 Value *CountIfLooping;
6043 if (InclusiveStop) {
6044 CountIfLooping =
Builder.CreateAdd(
Builder.CreateUDiv(Span, Incr), One);
6050 CountIfLooping =
Builder.CreateSelect(OneCmp, One, CountIfTwo);
6053 return Builder.CreateSelect(ZeroCmp,
Zero, CountIfLooping,
6054 "omp_" + Name +
".tripcount");
6059 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
6066 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
6071 Config.hasNoSignedWrap());
6072 Value *IndVar =
Builder.CreateAdd(Span, Start,
"",
false,
6073 Config.hasNoSignedWrap());
6075 ScanRedInfo->
IV = IndVar;
6076 return BodyGenCB(
Builder.saveIP(), IndVar);
6082 Builder.getCurrentDebugLocation());
6093 unsigned Bitwidth = Ty->getIntegerBitWidth();
6096 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_4u);
6099 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_8u);
6109 unsigned Bitwidth = Ty->getIntegerBitWidth();
6112 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_4u);
6115 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_8u);
6123 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6125 "Require dedicated allocate IP");
6131 uint32_t SrcLocStrSize;
6135 case WorksharingLoopType::ForStaticLoop:
6136 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6138 case WorksharingLoopType::DistributeStaticLoop:
6139 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6141 case WorksharingLoopType::DistributeForStaticLoop:
6142 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
6149 FunctionCallee StaticInit =
6150 LoopType == WorksharingLoopType::DistributeForStaticLoop
6153 FunctionCallee StaticFini =
6157 Builder.SetInsertPoint(AllocaIP.getNodeParent()->getFirstNonPHIOrAlloca());
6160 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6161 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
6162 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
6163 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
6172 Constant *One = ConstantInt::get(IVTy, 1);
6175 Builder.CreateStore(UpperBound, PUpperBound);
6176 Builder.CreateStore(One, PStride);
6182 (LoopType == WorksharingLoopType::DistributeStaticLoop)
6183 ? OMPScheduleType::OrderedDistribute
6186 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6190 auto BuildInitCall = [LoopType, SrcLoc, ThreadNum, PLastIter, PLowerBound,
6191 PUpperBound, IVTy, PStride, One,
Zero, StaticInit,
6194 PLowerBound, PUpperBound});
6195 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
6196 Value *PDistUpperBound =
6197 Builder.CreateAlloca(IVTy,
nullptr,
"p.distupperbound");
6198 Args.push_back(PDistUpperBound);
6203 BuildInitCall(SchedulingType,
Builder);
6204 if (HasDistSchedule &&
6205 LoopType != WorksharingLoopType::DistributeStaticLoop) {
6206 Constant *DistScheduleSchedType = ConstantInt::get(
6211 BuildInitCall(DistScheduleSchedType,
Builder);
6214 Value *InclusiveUpperBound =
Builder.CreateLoad(IVTy, PUpperBound);
6216 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One);
6217 if (CLI->VirtualCollapse) {
6218 bindCollapsedRange(CLI,
LowerBound, TripCount);
6223 CLI->setTripCount(TripCount);
6230 if (!CLI->VirtualCollapse)
6231 CLI->mapIndVar([&](Instruction *OldIV) ->
Value * {
6235 Config.hasNoSignedWrap());
6246 omp::Directive::OMPD_for,
false,
6249 return BarrierIP.takeError();
6280 Reachable.insert(
Block);
6294OpenMPIRBuilder::applyStaticChunkedWorkshareLoop(
6298 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6299 assert((ChunkSize || DistScheduleChunkSize) &&
"Chunk size is required");
6304 Type *IVTy =
IV->getType();
6306 "Max supported tripcount bitwidth is 64 bits");
6308 :
Type::getInt64Ty(Ctx);
6311 Constant *One = ConstantInt::get(InternalIVTy, 1);
6316 SmallVector<Instruction *> UIs;
6317 for (BasicBlock &BB : *
F)
6318 if (!BB.hasTerminator())
6319 UIs.
push_back(
new UnreachableInst(
F->getContext(), &BB));
6324 LoopInfo &&LI = LIA.
run(*
F,
FAM);
6325 for (Instruction *
I : UIs)
6326 I->eraseFromParent();
6329 if (ChunkSize || DistScheduleChunkSize)
6334 FunctionCallee StaticInit =
6336 FunctionCallee StaticFini =
6342 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6343 Value *PLowerBound =
6344 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.lowerbound");
6345 Value *PUpperBound =
6346 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.upperbound");
6347 Value *PStride =
Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.stride");
6356 ChunkSize ? ChunkSize :
Zero, InternalIVTy,
"chunksize");
6357 Value *CastedDistScheduleChunkSize =
Builder.CreateZExtOrTrunc(
6358 DistScheduleChunkSize ? DistScheduleChunkSize :
Zero, InternalIVTy,
6359 "distschedulechunksize");
6360 Value *CastedTripCount =
6361 Builder.CreateZExt(OrigTripCount, InternalIVTy,
"tripcount");
6364 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6366 ConstantInt::get(I32Type,
static_cast<int>(DistScheduleSchedType));
6368 Value *OrigUpperBound =
Builder.CreateSub(CastedTripCount, One);
6371 Builder.CreateSelect(IsTripCountZero,
Zero, OrigUpperBound);
6372 Builder.CreateStore(UpperBound, PUpperBound);
6373 Builder.CreateStore(One, PStride);
6377 uint32_t SrcLocStrSize;
6380 if (DistScheduleSchedType != OMPScheduleType::None) {
6381 Flag |= OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6386 auto BuildInitCall = [StaticInit, SrcLoc, ThreadNum, PLastIter, PLowerBound,
6387 PUpperBound, PStride, One,
6388 this](
Value *SchedulingType,
Value *ChunkSize,
6391 StaticInit, {SrcLoc, ThreadNum,
6392 SchedulingType, PLastIter,
6393 PLowerBound, PUpperBound,
6397 BuildInitCall(SchedulingType, CastedChunkSize,
Builder);
6398 if (DistScheduleSchedType != OMPScheduleType::None &&
6399 SchedType != OMPScheduleType::OrderedDistributeChunked &&
6400 SchedType != OMPScheduleType::OrderedDistribute) {
6404 BuildInitCall(DistSchedulingType, CastedDistScheduleChunkSize,
Builder);
6408 Value *FirstChunkStart =
6409 Builder.CreateLoad(InternalIVTy, PLowerBound,
"omp_firstchunk.lb");
6410 Value *FirstChunkStop =
6411 Builder.CreateLoad(InternalIVTy, PUpperBound,
"omp_firstchunk.ub");
6412 Value *FirstChunkEnd =
Builder.CreateAdd(FirstChunkStop, One);
6414 Builder.CreateSub(FirstChunkEnd, FirstChunkStart,
"omp_chunk.range");
6415 Value *NextChunkStride =
6416 Builder.CreateLoad(InternalIVTy, PStride,
"omp_dispatch.stride");
6420 Value *DispatchCounter;
6428 DispatchCounter = Counter;
6431 FirstChunkStart, CastedTripCount, NextChunkStride,
6454 Value *ChunkEnd =
Builder.CreateAdd(DispatchCounter, ChunkRange);
6455 Value *IsLastChunk =
6456 Builder.CreateICmpUGE(ChunkEnd, CastedTripCount,
"omp_chunk.is_last");
6457 Value *CountUntilOrigTripCount =
6458 Builder.CreateSub(CastedTripCount, DispatchCounter);
6460 IsLastChunk, CountUntilOrigTripCount, ChunkRange,
"omp_chunk.tripcount");
6461 Value *BackcastedChunkTC =
6462 Builder.CreateTrunc(ChunkTripCount, IVTy,
"omp_chunk.tripcount.trunc");
6463 CLI->setTripCount(BackcastedChunkTC);
6468 Value *BackcastedDispatchCounter =
6469 Builder.CreateTrunc(DispatchCounter, IVTy,
"omp_dispatch.iv.trunc");
6470 CLI->mapIndVar([&](Instruction *) ->
Value * {
6472 return Builder.CreateAdd(
IV, BackcastedDispatchCounter);
6485 return AfterIP.takeError();
6500static FunctionCallee
6503 unsigned Bitwidth = Ty->getIntegerBitWidth();
6506 case WorksharingLoopType::ForStaticLoop:
6509 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_4u);
6512 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_8u);
6514 case WorksharingLoopType::DistributeStaticLoop:
6517 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_4u);
6520 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_8u);
6522 case WorksharingLoopType::DistributeForStaticLoop:
6525 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_4u);
6528 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_8u);
6531 if (Bitwidth != 32 && Bitwidth != 64) {
6543 Function &LoopBodyFn,
bool NoLoop) {
6554 if (LoopType == WorksharingLoopType::DistributeStaticLoop) {
6555 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6556 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6557 Builder.restoreIP(std::prev(InsertBlock->
end()));
6562 M, omp::RuntimeFunction::OMPRTL_omp_get_num_threads);
6563 Builder.restoreIP(std::prev(InsertBlock->
end()));
6567 Builder.CreateZExtOrTrunc(NumThreads, TripCountTy,
"num.threads.cast"));
6568 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6569 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
6570 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6571 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), NoLoop));
6573 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6597 Builder.restoreIP(Preheader->
end());
6600 Builder.CreateBr(CLI->
getExit());
6608 CleanUpInfo.
collectBlocks(RegionBlockSet, BlocksToBeRemoved);
6616 "Expected unique undroppable user of outlined function");
6618 assert(OutlinedFnCallInstruction &&
"Expected outlined function call");
6620 "Expected outlined function call to be located in loop preheader");
6622 if (OutlinedFnCallInstruction->
arg_size() > 1)
6629 LoopBodyArg, TripCount, OutlinedFn, NoLoop);
6631 for (
auto &ToBeDeletedItem : ToBeDeleted)
6632 ToBeDeletedItem->eraseFromParent();
6639 bool NeedsLastIter) {
6640 uint32_t SrcLocStrSize;
6644 if (NeedsLastIter) {
6647 AllocaInst *PLastIter =
6648 Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6652 Builder.CreateStore(ConstantInt::get(I32Type, 0), PLastIter);
6657 Builder.CreateSub(TripCount, ConstantInt::get(TripCount->
getType(), 1));
6660 Builder.CreateStore(
Builder.CreateZExt(IsLast, I32Type), PLastIter);
6665 case WorksharingLoopType::ForStaticLoop:
6666 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6668 case WorksharingLoopType::DistributeStaticLoop:
6669 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6671 case WorksharingLoopType::DistributeForStaticLoop:
6672 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
6677 auto OI = std::make_unique<OutlineInfo>();
6682 SmallVector<Instruction *, 4> ToBeDeleted;
6684 OI->OuterAllocBB = AllocaIP.getNodeParent();
6707 SmallPtrSet<BasicBlock *, 32> ParallelRegionBlockSet;
6709 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
6711 CodeExtractorAnalysisCache CEAC(*OuterFn);
6712 CodeExtractor Extractor(Blocks,
6726 SetVector<Value *> SinkingCands, HoistingCands;
6730 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
6737 for (
auto Use :
Users) {
6739 if (ParallelRegionBlockSet.
count(Inst->getParent())) {
6740 Inst->replaceUsesOfWith(CLI->
getIndVar(), NewLoopCntLoad);
6746 OI->ExcludeArgsFromAggregate.push_back(NewLoopCntLoad);
6753 OI->PostOutlineCB = [=, ToBeDeletedVec =
6754 std::move(ToBeDeleted)](
Function &OutlinedFn) {
6771 return BarrierIP.takeError();
6778 bool NeedsBarrier, omp::ScheduleKind SchedKind,
Value *ChunkSize,
6779 bool HasSimdModifier,
bool HasMonotonicModifier,
6780 bool HasNonmonotonicModifier,
bool HasOrderedClause,
6782 Value *DistScheduleChunkSize,
bool NeedsLastIter) {
6783 if (CLI->VirtualCollapse &&
6784 (
Config.isTargetDevice() ||
6785 (SchedKind != omp::OMP_SCHEDULE_Static &&
6786 SchedKind != omp::OMP_SCHEDULE_Default) ||
6787 ChunkSize || HasOrderedClause || HasDistSchedule ||
6788 DistScheduleChunkSize || LoopType != WorksharingLoopType::ForStaticLoop))
6790 "Virtual collapse requires unchunked static worksharing");
6791 if (
Config.isTargetDevice())
6792 return applyWorkshareLoopTarget(
DL, CLI, AllocaIP, LoopType, NeedsBarrier,
6793 NoLoop, NeedsLastIter);
6795 SchedKind, ChunkSize, HasSimdModifier, HasMonotonicModifier,
6796 HasNonmonotonicModifier, HasOrderedClause, DistScheduleChunkSize);
6798 bool IsOrdered = (EffectiveScheduleType & OMPScheduleType::ModifierOrdered) ==
6799 OMPScheduleType::ModifierOrdered;
6801 if (HasDistSchedule) {
6802 DistScheduleSchedType = DistScheduleChunkSize
6803 ? OMPScheduleType::OrderedDistributeChunked
6804 : OMPScheduleType::OrderedDistribute;
6806 switch (EffectiveScheduleType & ~OMPScheduleType::ModifierMask) {
6807 case OMPScheduleType::BaseStatic:
6808 case OMPScheduleType::BaseDistribute:
6809 assert((!ChunkSize || !DistScheduleChunkSize) &&
6810 "No chunk size with static-chunked schedule");
6811 if (IsOrdered && !HasDistSchedule)
6812 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6813 NeedsBarrier, ChunkSize);
6815 if (DistScheduleChunkSize)
6816 return applyStaticChunkedWorkshareLoop(
6817 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6818 DistScheduleChunkSize, DistScheduleSchedType);
6819 return applyStaticWorkshareLoop(
DL, CLI, AllocaIP, LoopType, NeedsBarrier,
6822 case OMPScheduleType::BaseStaticChunked:
6823 case OMPScheduleType::BaseDistributeChunked:
6824 if (IsOrdered && !HasDistSchedule)
6825 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6826 NeedsBarrier, ChunkSize);
6828 return applyStaticChunkedWorkshareLoop(
6829 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6830 DistScheduleChunkSize, DistScheduleSchedType);
6832 case OMPScheduleType::BaseRuntime:
6833 case OMPScheduleType::BaseAuto:
6834 case OMPScheduleType::BaseGreedy:
6835 case OMPScheduleType::BaseBalanced:
6836 case OMPScheduleType::BaseSteal:
6837 case OMPScheduleType::BaseRuntimeSimd:
6839 "schedule type does not support user-defined chunk sizes");
6841 case OMPScheduleType::BaseGuidedSimd:
6842 case OMPScheduleType::BaseDynamicChunked:
6843 case OMPScheduleType::BaseGuidedChunked:
6844 case OMPScheduleType::BaseGuidedIterativeChunked:
6845 case OMPScheduleType::BaseGuidedAnalyticalChunked:
6846 case OMPScheduleType::BaseStaticBalancedChunked:
6847 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6848 NeedsBarrier, ChunkSize);
6861 unsigned Bitwidth = Ty->getIntegerBitWidth();
6864 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_4u);
6867 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_8u);
6875static FunctionCallee
6877 unsigned Bitwidth = Ty->getIntegerBitWidth();
6880 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_4u);
6883 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_8u);
6890static FunctionCallee
6892 unsigned Bitwidth = Ty->getIntegerBitWidth();
6895 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_4u);
6898 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_8u);
6903OpenMPIRBuilder::applyDynamicWorkshareLoop(
DebugLoc DL, CanonicalLoopInfo *CLI,
6906 bool NeedsBarrier,
Value *Chunk) {
6907 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6909 "Require dedicated allocate IP");
6911 "Require valid schedule type");
6913 bool Ordered = (SchedType & OMPScheduleType::ModifierOrdered) ==
6914 OMPScheduleType::ModifierOrdered;
6919 uint32_t SrcLocStrSize;
6926 Type *IVTy =
IV->getType();
6931 Builder.SetInsertPoint(AllocaIP.getNodeParent()->getFirstNonPHIOrAlloca());
6933 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6934 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
6935 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
6936 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
6945 Constant *One = ConstantInt::get(IVTy, 1);
6946 Builder.CreateStore(One, PLowerBound);
6948 Builder.CreateStore(UpperBound, PUpperBound);
6949 Builder.CreateStore(One, PStride);
6967 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6979 Builder.SetInsertPoint(OuterCond->getFirstInsertionPt());
6982 {SrcLoc, ThreadNum, PLastIter, PLowerBound, PUpperBound, PStride});
6983 Constant *Zero32 = ConstantInt::get(I32Type, 0);
6986 Builder.CreateSub(
Builder.CreateLoad(IVTy, PLowerBound), One,
"lb");
6987 Builder.CreateCondBr(MoreWork, Header, Exit);
6993 PI->setIncomingBlock(0, OuterCond);
6999 Br->setSuccessor(OuterCond);
7004 Builder.SetInsertPoint(
Cond->getFirstInsertionPt());
7005 UpperBound =
Builder.CreateLoad(IVTy, PUpperBound,
"ub");
7008 CI->setOperand(1, UpperBound);
7012 assert(BI->getSuccessor(1) == Exit);
7013 BI->setSuccessor(1, OuterCond);
7027 omp::Directive::OMPD_for,
false,
7030 return BarrierIP.takeError();
7093 "Virtual collapse requires unobserved canonical loop controls");
7102 if (
Loops.front()->getBody()->getUniqueSuccessor() !=
7104 Loops.back()->getAfter()->getSingleSuccessor() != Plan.
Latches.front())
7111 const VirtualRowPlan &Plan,
7115 DebugLoc DL = Builder.getCurrentDebugLocation();
7121 Builder.SetInsertPoint(Entry);
7123 Builder.CreateURem(Begin, TripCounts.
back(),
"omp_collapsed.begin.1");
7125 Builder.CreateUDiv(Begin, TripCounts.
back(),
"omp_collapsed.begin.0");
7128 Value *InitialRemaining =
7129 Builder.CreateAdd(
Count, InnerBegin,
"omp_collapsed.row.remaining");
7130 Builder.CreateBr(OuterHeader);
7133 Builder.SetCurrentDebugLocation(
DL);
7135 Builder.CreatePHI(IVType, 2,
"omp_collapsed.row.remaining.0");
7141 Builder.CreatePHI(IVType, 2,
"omp_collapsed.row.start.1.0");
7142 Start->addIncoming(InnerBegin, Entry);
7143 Start->addIncoming(
Zero, Plan.Latches.front());
7144 Plan.IndVars.back()->setIncomingValue(0, Start);
7149 BasicBlock *InnerHeader = Plan.IndVars.back()->getParent();
7153 Builder.SetInsertPoint(InnerEntry);
7155 Builder.CreateBr(InnerHeader);
7156 InnerBr->setSuccessor(InnerEntry);
7157 Plan.IndVars.back()->setIncomingBlock(0, InnerEntry);
7159 Builder.SetInsertPoint(Plan.Preheaders.back()->getTerminator());
7162 "omp_collapsed.row.is_final");
7164 IsFinalRow, Remaining, TripCounts.
back(),
"omp_collapsed.row.stop");
7165 Plan.InnerCmp->setOperand(1, InnerStop);
7173 "omp_collapsed.row.remaining.next",
7181 Builder.SetInsertPoint(Guard);
7183 Plan.IndVars.front()->setIncomingValue(0, OuterBegin);
7184 Plan.IndVars.front()->setIncomingBlock(0, Entry);
7187CanonicalLoopInfo *OpenMPIRBuilder::createVirtualCollapsedLoop(
7190 Value *CollapsedTripCount) {
7198 BasicBlock *Preheader = Plan.Preheaders.front();
7213 "omp_collapsed.range.begin");
7215 Builder.Insert(BinaryOperator::CreateAdd(CollapsedTripCount,
Zero),
7216 "omp_collapsed.range.count");
7219 Result->VirtualCollapse =
7220 CanonicalLoopInfo::VirtualCollapseInfo{Begin,
Count};
7224 createVirtualRowExecutor(Result, Plan, TripCounts, Begin,
Count, Entry);
7234void OpenMPIRBuilder::bindCollapsedRange(CanonicalLoopInfo *
Loop,
Value *Begin,
7237 Loop->VirtualCollapse->Begin->setOperand(0, Begin);
7238 Loop->VirtualCollapse->Count->setOperand(0,
Count);
7244 assert(
Loops.size() >= 1 &&
"At least one loop required");
7245 size_t NumLoops =
Loops.size();
7249 return Loops.front();
7251 if (
Config.CollapseMapping == CollapseIVMapping::Virtual) {
7252 if (
Loops.size() != 2)
7254 "Virtual collapse requires two constant-count loops");
7257 if (
Loop->VirtualCollapse)
7258 Loop->reportUnsupportedVirtualCollapse();
7262 "Virtual collapse requires two constant-count loops");
7267 Value *CollapsedTripCount =
7269 return createVirtualCollapsedLoop(
DL,
Loops, Plan, TripCounts,
7270 CollapsedTripCount);
7283 Loop->collectControlBlocks(OldControlBBs);
7287 if (ComputeIP.isValid())
7294 Value *CollapsedTripCount =
nullptr;
7297 "All loops to collapse must be valid canonical loops");
7298 Value *OrigTripCount = L->getTripCount();
7299 if (!CollapsedTripCount) {
7300 CollapsedTripCount = OrigTripCount;
7305 CollapsedTripCount =
7306 Builder.CreateNUWMul(CollapsedTripCount, OrigTripCount);
7312 OrigPreheader->
getNextNode(), OrigAfter,
"collapsed",
7319 Builder.restoreIP(Result->getBodyIP());
7321 Value *Leftover = Result->getIndVar();
7323 NewIndVars.
resize(NumLoops);
7324 for (
int i = NumLoops - 1; i >= 1; --i) {
7325 Value *OrigTripCount =
Loops[i]->getTripCount();
7327 Value *NewIndVar =
Builder.CreateURem(Leftover, OrigTripCount);
7328 NewIndVars[i] = NewIndVar;
7330 Leftover =
Builder.CreateUDiv(Leftover, OrigTripCount);
7333 NewIndVars[0] = Leftover;
7342 BasicBlock *ContinueBlock = Result->getBody();
7344 auto ContinueWith = [&ContinueBlock, &ContinuePred,
DL](
BasicBlock *Dest,
7351 ContinueBlock =
nullptr;
7352 ContinuePred = NextSrc;
7359 for (
size_t i = 0; i < NumLoops - 1; ++i)
7360 ContinueWith(
Loops[i]->getBody(),
Loops[i + 1]->getHeader());
7366 for (
size_t i = NumLoops - 1; i > 0; --i)
7367 ContinueWith(
Loops[i]->getAfter(),
Loops[i - 1]->getLatch());
7370 ContinueWith(Result->getLatch(),
nullptr);
7377 for (
size_t i = 0; i < NumLoops; ++i)
7378 Loops[i]->getIndVar()->replaceAllUsesWith(NewIndVars[i]);
7392std::vector<CanonicalLoopInfo *>
7396 "Must pass as many tile sizes as there are loops");
7397 int NumLoops =
Loops.size();
7398 assert(NumLoops >= 1 &&
"At least one loop to tile required");
7410 Loop->collectControlBlocks(OldControlBBs);
7418 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7419 OrigTripCounts.
push_back(L->getTripCount());
7430 for (
int i = 0; i < NumLoops - 1; ++i) {
7443 for (
int i = 0; i < NumLoops; ++i) {
7444 Value *TileSize = TileSizes[i];
7445 Value *OrigTripCount = OrigTripCounts[i];
7448 Value *FloorCompleteTripCount =
Builder.CreateUDiv(OrigTripCount, TileSize);
7449 Value *FloorTripRem =
Builder.CreateURem(OrigTripCount, TileSize);
7458 Value *FloorTripOverflow =
7459 Builder.CreateICmpNE(FloorTripRem, ConstantInt::get(IVType, 0));
7461 FloorTripOverflow =
Builder.CreateZExt(FloorTripOverflow, IVType);
7462 Value *FloorTripCount =
7463 Builder.CreateAdd(FloorCompleteTripCount, FloorTripOverflow,
7464 "omp_floor" +
Twine(i) +
".tripcount",
true);
7467 FloorCompleteCount.
push_back(FloorCompleteTripCount);
7473 std::vector<CanonicalLoopInfo *> Result;
7474 Result.reserve(NumLoops * 2);
7487 auto EmbeddNewLoop =
7488 [
this,
DL,
F, InnerEnter, &Enter, &
Continue, &OutroInsertBefore](
7491 DL, TripCount,
F, InnerEnter, OutroInsertBefore, Name);
7496 Enter = EmbeddedLoop->
getBody();
7498 OutroInsertBefore = EmbeddedLoop->
getLatch();
7499 return EmbeddedLoop;
7503 const Twine &NameBase) {
7506 EmbeddNewLoop(
P.value(), NameBase +
Twine(
P.index()));
7507 Result.push_back(EmbeddedLoop);
7511 EmbeddNewLoops(FloorCount,
"floor");
7517 for (
int i = 0; i < NumLoops; ++i) {
7519 Value *TileSize = TileSizes[i];
7521 Value *FloorIsEpilogue =
7523 Value *TileTripCount =
7524 Builder.CreateSelect(FloorIsEpilogue, FloorRems[i], TileSize);
7530 EmbeddNewLoops(TileCounts,
"tile");
7535 for (std::pair<BasicBlock *, BasicBlock *>
P : InbetweenCode) {
7544 BodyEnter =
nullptr;
7545 BodyEntered = ExitBB;
7557 Builder.restoreIP(Result.back()->getBodyIP());
7558 for (
int i = 0; i < NumLoops; ++i) {
7561 Value *OrigIndVar = OrigIndVars[i];
7612 assert(
Loop->isValid() &&
"Expecting a valid CanonicalLoopInfo");
7616 assert(Latch &&
"A valid CanonicalLoopInfo must have a unique latch");
7624 if (
I.mayReadOrWriteMemory()) {
7628 I.setMetadata(LLVMContext::MD_access_group,
AccessGroup);
7642 Loop->collectControlBlocks(oldControlBBs);
7647 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7648 origTripCounts.
push_back(L->getTripCount());
7657 Builder.SetInsertPoint(TCBlock);
7658 Value *fusedTripCount =
nullptr;
7660 assert(L->isValid() &&
"All loops to fuse must be valid canonical loops");
7661 Value *origTripCount = L->getTripCount();
7662 if (!fusedTripCount) {
7663 fusedTripCount = origTripCount;
7666 Value *condTP =
Builder.CreateICmpSGT(fusedTripCount, origTripCount);
7667 fusedTripCount =
Builder.CreateSelect(condTP, fusedTripCount, origTripCount,
7681 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7682 Loops[i]->getPreheader()->moveBefore(TCBlock);
7683 Loops[i]->getAfter()->moveBefore(TCBlock);
7687 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7699 for (
size_t i = 0; i <
Loops.size(); ++i) {
7701 F->getContext(),
"omp.fused.inner.cond",
F,
Loops[i]->getBody());
7702 Builder.SetInsertPoint(condBlock);
7710 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7711 Builder.SetInsertPoint(condBBs[i]);
7712 Builder.CreateCondBr(condValues[i],
Loops[i]->getBody(), condBBs[i + 1]);
7728 "omp.fused.pre_latch");
7745 assert(
Loop->isValid() &&
"Expecting a valid CanonicalLoopInfo");
7746 if (
Loop->VirtualCollapse)
7769 const Twine &NamePrefix) {
7798 C, NamePrefix +
".if.then",
Cond->getParent(),
Cond->getNextNode());
7800 C, NamePrefix +
".if.else",
Cond->getParent(), CanonicalLoop->
getExit());
7803 Builder.SetInsertPoint(SplitBeforeIt);
7805 Builder.CreateCondBr(IfCond, ThenBlock, ElseBlock);
7808 spliceBB(IP, ThenBlock,
false, Builder.getCurrentDebugLocation());
7811 Builder.SetInsertPoint(ElseBlock);
7817 ExistingBlocks.
reserve(L->getNumBlocks() + 1);
7819 ExistingBlocks.
append(L->block_begin(), L->block_end());
7825 assert(LoopCond && LoopHeader &&
"Invalid loop structure");
7827 if (
Block == L->getLoopPreheader() ||
Block == L->getLoopLatch() ||
7834 if (
Block == ThenBlock)
7835 NewBB->
setName(NamePrefix +
".if.else");
7838 VMap[
Block] = NewBB;
7846 L->getLoopLatch()->splitBasicBlockBefore(
L->getLoopLatch()->begin(),
7847 NamePrefix +
".pre_latch");
7851 L->addBasicBlockToLoop(ThenBlock, LI);
7857 if (TargetTriple.
isX86()) {
7858 if (Features.
lookup(
"avx512f"))
7860 else if (Features.
lookup(
"avx"))
7864 if (TargetTriple.
isPPC())
7866 if (TargetTriple.
isWasm())
7875 Value *IfCond, OrderKind Order,
7877 if (CanonicalLoop->VirtualCollapse)
7878 CanonicalLoop->reportUnsupportedVirtualCollapse();
7887 if (!BB.hasTerminator())
7903 I->eraseFromParent();
7906 if (AlignedVars.
size()) {
7908 for (
auto &AlignedItem : AlignedVars) {
7909 Value *AlignedPtr = AlignedItem.first;
7913 Builder.CreateAlignmentAssumption(
F->getDataLayout(), AlignedPtr,
7921 createIfVersion(CanonicalLoop, IfCond, VMap, LIA, LI, L,
"simd");
7934 Reachable.insert(
Block);
7944 if ((Safelen ==
nullptr) || (Order == OrderKind::OMP_ORDER_concurrent))
7960 if (Simdlen || Safelen) {
7964 ConstantInt *VectorizeWidth = Simdlen ==
nullptr ? Safelen : Simdlen;
7976 assert(Factor >= 0 &&
"Unroll factor must not be negative");
7992 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst}));
7995 addUnrollMetadata(
Loop, LoopMetadata);
8000 if (
Loop->VirtualCollapse)
8001 Loop->reportUnsupportedVirtualCollapse();
8007 *UnrolledCLI =
Loop;
8012 "unrolling only makes sense with a factor of 2 or larger");
8014 Type *IndVarTy =
Loop->getIndVarType();
8021 std::vector<CanonicalLoopInfo *>
LoopNest =
8036 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst})});
8039 (*UnrolledCLI)->assertOK();
8057 Value *Args[] = {Ident, ThreadId, BufSize, CpyBuf, CpyFn, DidItLD};
8076 if (!CPVars.
empty()) {
8081 Directive OMPD = Directive::OMPD_single;
8086 Value *Args[] = {Ident, ThreadId};
8095 if (
Error Err = FiniCB(IP))
8116 EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCBWrapper,
8123 for (
size_t I = 0, E = CPVars.
size();
I < E; ++
I)
8126 ConstantInt::get(Int64, 0), CPVars[
I],
8129 }
else if (!IsNowait) {
8132 omp::Directive::OMPD_unknown,
false,
8150 Directive::OMPD_scope,
nullptr,
nullptr,
8151 BodyGenCB, FiniCB,
false,
true,
8159 omp::Directive::OMPD_unknown,
8175 Directive OMPD = Directive::OMPD_critical;
8180 Value *LockVar = getOMPCriticalRegionLock(CriticalName);
8181 Value *Args[] = {Ident, ThreadId, LockVar};
8198 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
8206 const Twine &Name,
bool IsDependSource) {
8209 [](
Value *SV) {
return SV->getType()->isIntegerTy(64); }) &&
8210 "OpenMP runtime requires depend vec with i64 type");
8223 for (
unsigned I = 0;
I < NumLoops; ++
I) {
8237 Value *Args[] = {Ident, ThreadId, DependBaseAddrGEP};
8255 Directive OMPD = Directive::OMPD_ordered_blockassoc;
8264 Value *Args[] = {Ident, ThreadId};
8274 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
8281 bool HasFinalize,
bool IsCancellable) {
8288 BasicBlock *EntryBB = Builder.GetInsertBlock();
8292 SplitPos->
setDebugLoc(Builder.getCurrentDebugLocation());
8299 emitCommonDirectiveEntry(OMPD, EntryCall, ExitBB, Conditional);
8311 "Unexpected control flow graph state!!");
8313 emitCommonDirectiveExit(OMPD, FinIP, ExitCall, HasFinalize);
8315 return AfterIP.takeError();
8320 "Unexpected Insertion point location!");
8323 auto InsertBB = merged ? ExitPredBB : ExitBB;
8326 Builder.SetInsertPoint(InsertBB);
8332 Directive OMPD,
Value *EntryCall, BasicBlock *ExitBB,
bool Conditional) {
8334 if (!Conditional || !EntryCall)
8340 auto *UI =
new UnreachableInst(
Builder.getContext(), ThenBB);
8350 Builder.CreateCondBr(CallBool, ThenBB, ExitBB);
8354 UI->eraseFromParent();
8362 omp::Directive OMPD,
InsertPointTy FinIP, Instruction *ExitCall,
8370 "Unexpected finalization stack state!");
8373 assert(Fi.DK == OMPD &&
"Unexpected Directive for Finalization call!");
8377 return std::move(Err);
8424 "copyin.not.master.end");
8431 Builder.SetInsertPoint(OMP_Entry);
8434 Value *cmp =
Builder.CreateICmpNE(MasterPtr, PrivatePtr);
8435 Builder.CreateCondBr(cmp, CopyBegin, CopyEnd);
8437 Builder.SetInsertPoint(CopyBegin);
8455 Value *Args[] = {ThreadId,
Size, Allocator};
8478 return Builder.CreateCall(Fn, Args, Name);
8492 Value *Args[] = {ThreadId, Addr, Allocator};
8499 const Twine &Name) {
8507 M.getContext(),
M.getDataLayout().getPrefTypeAlign(Int64)));
8513 const Twine &Name) {
8515 Loc,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)), Name);
8520 const Twine &Name) {
8526 return Builder.CreateCall(Fn, Args, Name);
8531 const Twine &Name) {
8533 Loc, Addr,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)),
8540 Value *DependenceAddress,
bool HaveNowaitClause) {
8550 else if (
Device->getType() != Int32)
8553 if (NumDependences ==
nullptr) {
8554 NumDependences = ConstantInt::get(Int32, 0);
8558 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8560 Ident, ThreadId, InteropVar, InteropTypeVal,
8561 Device, NumDependences, DependenceAddress, HaveNowaitClauseVal};
8570 Value *NumDependences,
Value *DependenceAddress,
bool HaveNowaitClause) {
8580 else if (
Device->getType() != Int32)
8582 if (NumDependences ==
nullptr) {
8583 NumDependences = ConstantInt::get(Int32, 0);
8587 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8589 Ident, ThreadId, InteropVar,
Device,
8590 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8599 Value *NumDependences,
8600 Value *DependenceAddress,
8601 bool HaveNowaitClause) {
8610 else if (
Device->getType() != Int32)
8612 if (NumDependences ==
nullptr) {
8613 NumDependences = ConstantInt::get(Int32, 0);
8617 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8619 Ident, ThreadId, InteropVar,
Device,
8620 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8650 assert(!Attrs.MaxThreads.empty() && !Attrs.MaxTeams.empty() &&
8651 "expected num_threads and num_teams to be specified");
8671 const std::string DebugPrefix =
"_debug__";
8672 if (KernelName.
ends_with(DebugPrefix)) {
8673 KernelName = KernelName.
drop_back(DebugPrefix.length());
8674 Kernel =
M.getFunction(KernelName);
8680 if (Attrs.MinTeams.front() > 1 || Attrs.MaxTeams.front() > 0)
8682 Attrs.MaxTeams.front());
8685 int32_t MaxThreadsVal = Attrs.MaxThreads.front();
8695 Attrs.MinThreads.front());
8700 if (MaxThreadsVal > 0 &&
8703 MaxThreadsVal = int32_t(
8704 std::min<int64_t>(int64_t(MaxThreadsVal) + 64,
8707 if (MaxThreadsVal > 0)
8722 Twine DynamicEnvironmentName = KernelName +
"_dynamic_environment";
8723 Constant *DynamicEnvironmentInitializer =
8727 DynamicEnvironmentInitializer, DynamicEnvironmentName,
8729 DL.getDefaultGlobalsAddressSpace());
8733 DynamicEnvironmentGV->
getType() == DynamicEnvironmentPtr
8734 ? DynamicEnvironmentGV
8736 DynamicEnvironmentPtr);
8739 ConfigurationEnvironment, {
8740 UseGenericStateMachineVal,
8741 MayUseNestedParallelismVal,
8750 KernelEnvironment, {
8751 ConfigurationEnvironmentInitializer,
8755 std::string KernelEnvironmentName =
8756 (KernelName +
"_kernel_environment").str();
8759 KernelEnvironmentInitializer, KernelEnvironmentName,
8761 DL.getDefaultGlobalsAddressSpace());
8764 return KernelEnvironmentGV->
getType() == KernelEnvironmentPtr
8765 ? KernelEnvironmentGV
8767 KernelEnvironmentPtr);
8774 if (!KernelEnvironment)
8782 omp::RuntimeFunction::OMPRTL___kmpc_target_init);
8784 Value *KernelLaunchEnvironment =
8787 KernelLaunchEnvironment =
8788 KernelLaunchEnvironment->
getType() == KernelLaunchEnvParamTy
8789 ? KernelLaunchEnvironment
8790 :
Builder.CreateAddrSpaceCast(KernelLaunchEnvironment,
8791 KernelLaunchEnvParamTy);
8793 Fn, {KernelEnvironment, KernelLaunchEnvironment});
8805 auto *UI =
Builder.CreateUnreachable();
8811 Builder.SetInsertPoint(WorkerExitBB);
8815 Builder.SetInsertPoint(CheckBBTI);
8816 Builder.CreateCondBr(ExecUserCode, UI->getParent(), WorkerExitBB);
8818 CheckBBTI->eraseFromParent();
8819 UI->eraseFromParent();
8827 int32_t TeamsReductionDataSize) {
8832 omp::RuntimeFunction::OMPRTL___kmpc_target_deinit);
8836 if (!TeamsReductionDataSize)
8842 const std::string DebugPrefix =
"_debug__";
8844 KernelName = KernelName.
drop_back(DebugPrefix.length());
8845 auto *KernelEnvironmentGV =
8846 M.getNamedGlobal((KernelName +
"_kernel_environment").str());
8847 assert(KernelEnvironmentGV &&
"Expected kernel environment global\n");
8848 auto *KernelEnvironmentInitializer = KernelEnvironmentGV->getInitializer();
8850 KernelEnvironmentInitializer,
8851 ConstantInt::get(Int32, TeamsReductionDataSize), {0, 7});
8852 KernelEnvironmentGV->setInitializer(NewInitializer);
8857 if (
Kernel.hasFnAttribute(Name)) {
8858 int32_t OldLimit =
Kernel.getFnAttributeAsParsedInteger(Name);
8864std::pair<int32_t, int32_t>
8866 int32_t ThreadLimit =
8867 Kernel.getFnAttributeAsParsedInteger(
"omp_target_thread_limit");
8870 const auto &Attr =
Kernel.getFnAttribute(
"amdgpu-flat-work-group-size");
8871 if (!Attr.isValid() || !Attr.isStringAttribute())
8872 return {0, ThreadLimit};
8873 auto [LBStr, UBStr] = Attr.getValueAsString().split(
',');
8876 return {0, ThreadLimit};
8877 UB = ThreadLimit ? std::min(ThreadLimit, UB) : UB;
8885 return {0, ThreadLimit ? std::min(ThreadLimit, UB) : UB};
8887 return {0, ThreadLimit};
8893 Kernel.addFnAttr(
"omp_target_thread_limit", std::to_string(UB));
8896 Kernel.addFnAttr(
"amdgpu-flat-work-group-size",
8904std::pair<int32_t, int32_t>
8907 return {0,
Kernel.getFnAttributeAsParsedInteger(
"omp_target_num_teams")};
8911 int32_t LB, int32_t UB) {
8919 Kernel.addFnAttr(
"omp_target_num_teams", std::to_string(LB));
8922void OpenMPIRBuilder::setOutlinedTargetRegionFunctionAttributes(
8931 else if (
T.isNVPTX())
8933 else if (
T.isSPIRV())
8939 StringRef EntryFnIDName) {
8940 if (
Config.isTargetDevice()) {
8941 assert(OutlinedFn &&
"The outlined function must exist if embedded");
8945 return new GlobalVariable(
8950Constant *OpenMPIRBuilder::createTargetRegionEntryAddr(
Function *OutlinedFn,
8951 StringRef EntryFnName) {
8955 assert(!
M.getGlobalVariable(EntryFnName,
true) &&
8956 "Named kernel already exists?");
8957 return new GlobalVariable(
8970 if (
Config.isTargetDevice() || !
Config.openMPOffloadMandatory()) {
8974 OutlinedFn = *CBResult;
8976 OutlinedFn =
nullptr;
8982 if (!IsOffloadEntry)
8985 std::string EntryFnIDName =
8987 ? std::string(EntryFnName)
8991 EntryFnName, EntryFnIDName);
8999 setOutlinedTargetRegionFunctionAttributes(OutlinedFn);
9000 auto OutlinedFnID = createOutlinedFunctionID(OutlinedFn, EntryFnIDName);
9001 auto EntryAddr = createTargetRegionEntryAddr(OutlinedFn, EntryFnName);
9003 EntryInfo, EntryAddr, OutlinedFnID,
9005 return OutlinedFnID;
9023 bool IsStandAlone = !BodyGenCB;
9030 MapInfo = &GenMapInfoCB(
Builder.saveIP());
9032 AllocaIP,
Builder.saveIP(), *MapInfo, Info, CustomMapperCB,
9033 true, DeviceAddrCB))
9040 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
9050 SrcLocInfo, DeviceID,
9057 assert(MapperFunc &&
"MapperFunc missing for standalone target data");
9061 if (Info.HasNoWait) {
9071 if (Info.HasNoWait) {
9075 emitBlock(OffloadContBlock, CurFn,
true);
9081 bool RequiresOuterTargetTask = Info.HasNoWait;
9082 if (!RequiresOuterTargetTask)
9083 cantFail(TaskBodyCB(
nullptr,
nullptr,
9087 {}, RTArgs, Info.HasNoWait));
9090 omp::OMPRTL___tgt_target_data_begin_mapper);
9094 for (
auto DeviceMap : Info.DevicePtrInfoMap) {
9098 Builder.CreateStore(LI, DeviceMap.second.second);
9135 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
9144 Value *OffloadingArgs[] = {SrcLocInfo, DeviceID,
9167 return emitIfClause(IfCond, BeginThenGen, BeginElseGen, AllocaIP);
9168 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9183 return emitIfClause(IfCond, EndThenGen, EndElseGen, AllocaIP);
9184 return EndThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9187 return emitIfClause(IfCond, BeginThenGen, EndElseGen, AllocaIP);
9188 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9199 bool IsGPUDistribute) {
9200 assert((IVSize == 32 || IVSize == 64) &&
9201 "IV size is not compatible with the omp runtime");
9203 if (IsGPUDistribute)
9205 ? (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_4
9206 : omp::OMPRTL___kmpc_distribute_static_init_4u)
9207 : (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_8
9208 : omp::OMPRTL___kmpc_distribute_static_init_8u);
9210 Name = IVSize == 32 ? (IVSigned ? omp::OMPRTL___kmpc_for_static_init_4
9211 : omp::OMPRTL___kmpc_for_static_init_4u)
9212 : (IVSigned ? omp::OMPRTL___kmpc_for_static_init_8
9213 : omp::OMPRTL___kmpc_for_static_init_8u);
9220 assert((IVSize == 32 || IVSize == 64) &&
9221 "IV size is not compatible with the omp runtime");
9223 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_4
9224 : omp::OMPRTL___kmpc_dispatch_init_4u)
9225 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_8
9226 : omp::OMPRTL___kmpc_dispatch_init_8u);
9233 assert((IVSize == 32 || IVSize == 64) &&
9234 "IV size is not compatible with the omp runtime");
9236 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_4
9237 : omp::OMPRTL___kmpc_dispatch_next_4u)
9238 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_8
9239 : omp::OMPRTL___kmpc_dispatch_next_8u);
9246 assert((IVSize == 32 || IVSize == 64) &&
9247 "IV size is not compatible with the omp runtime");
9249 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_4
9250 : omp::OMPRTL___kmpc_dispatch_fini_4u)
9251 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_8
9252 : omp::OMPRTL___kmpc_dispatch_fini_8u);
9263 DenseMap<
Value *, std::tuple<Value *, unsigned>> &ValueReplacementMap) {
9271 auto GetUpdatedDIVariable = [&](
DILocalVariable *OldVar,
unsigned arg) {
9275 if (NewVar && (arg == NewVar->
getArg()))
9285 auto UpdateDebugRecord = [&](
auto *DR) {
9288 for (
auto Loc : DR->location_ops()) {
9289 auto Iter = ValueReplacementMap.find(
Loc);
9290 if (Iter != ValueReplacementMap.end()) {
9291 DR->replaceVariableLocationOp(
Loc, std::get<0>(Iter->second));
9292 ArgNo = std::get<1>(Iter->second) + 1;
9296 DR->setVariable(GetUpdatedDIVariable(OldVar, ArgNo));
9301 if (DVR->getNumVariableLocationOps() != 1u) {
9302 DVR->setKillLocation();
9305 Value *
Loc = DVR->getVariableLocationOp(0u);
9312 RequiredBB = &DVR->getFunction()->getEntryBlock();
9314 if (RequiredBB && RequiredBB != CurBB) {
9326 UpdateDebugRecord(&DVR);
9327 MoveDebugRecordToCorrectBlock(&DVR);
9330 for (
auto *DVR : DVRsToDelete)
9331 DVR->getMarker()->MarkedInstr->dropOneDbgRecord(DVR);
9335 Module *M = Func->getParent();
9338 DB.createQualifiedType(dwarf::DW_TAG_pointer_type,
nullptr);
9339 unsigned ArgNo = Func->arg_size();
9341 NewSP,
"dyn_ptr", ArgNo, NewSP->
getFile(), 0, VoidPtrTy,
9342 false, DINode::DIFlags::FlagArtificial);
9344 Argument *LastArg = Func->getArg(Func->arg_size() - 1);
9345 DB.insertDeclare(LastArg, Var, DB.createExpression(),
Loc,
9367 for (
auto &Arg : Inputs)
9368 ParameterTypes.
push_back(Arg->getType()->isPointerTy()
9372 for (
auto &Arg : Inputs)
9373 ParameterTypes.
push_back(Arg->getType());
9381 auto BB = Builder.GetInsertBlock();
9382 auto M = BB->getModule();
9393 if (TargetCpuAttr.isStringAttribute())
9394 Func->addFnAttr(TargetCpuAttr);
9396 auto TargetFeaturesAttr = ParentFn->
getFnAttribute(
"target-features");
9397 if (TargetFeaturesAttr.isStringAttribute())
9398 Func->addFnAttr(TargetFeaturesAttr);
9403 OMPBuilder.
emitUsed(
"llvm.compiler.used", {ExecMode});
9413 Builder.SetCurrentDebugLocation(OutlinedFnLoc);
9417 Builder.SetInsertPoint(EntryBB);
9428 BasicBlock *UserCodeEntryBB = Builder.GetInsertBlock();
9437 splitBB(Builder,
true,
"outlined.body");
9439 CBFunc(Builder.saveIP(), OutlinedBodyBB->
begin(), ExitBB);
9442 Builder.SetInsertPoint(ExitBB);
9450 Builder.SetCurrentDebugLocation(OutlinedFnLoc);
9457 Builder.CreateRetVoid();
9461 auto AllocaIP = Builder.saveIP();
9466 const auto &ArgRange =
make_range(Func->arg_begin(), Func->arg_end() - 1);
9498 if (Instr->getFunction() == Func)
9499 Instr->replaceUsesOfWith(
Input, InputCopy);
9505 for (
auto InArg :
zip(Inputs, ArgRange)) {
9507 Argument &Arg = std::get<1>(InArg);
9508 Value *InputCopy =
nullptr;
9511 Arg,
Input, InputCopy, AllocaIP, Builder.saveIP(), ExitBB->
begin());
9514 Builder.restoreIP(*AfterIP);
9515 ValueReplacementMap[
Input] = std::make_tuple(InputCopy, Arg.
getArgNo());
9535 DeferredReplacement.push_back(std::make_pair(
Input, InputCopy));
9542 ReplaceValue(
Input, InputCopy, Func);
9546 for (
auto Deferred : DeferredReplacement)
9547 ReplaceValue(std::get<0>(Deferred), std::get<1>(Deferred), Func);
9550 ValueReplacementMap);
9558 Value *TaskWithPrivates,
9559 Type *TaskWithPrivatesTy) {
9561 Type *TaskTy = OMPIRBuilder.Task;
9564 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 0);
9565 Value *Shareds = TaskT;
9575 if (TaskWithPrivatesTy != TaskTy)
9576 Shareds = Builder.CreateStructGEP(TaskTy, TaskT, 0);
9593 const size_t NumOffloadingArrays,
const int SharedArgsOperandNo) {
9598 assert((!NumOffloadingArrays || PrivatesTy) &&
9599 "PrivatesTy cannot be nullptr when there are offloadingArrays"
9629 Type *TaskPtrTy = OMPBuilder.TaskPtr;
9630 [[maybe_unused]]
Type *TaskTy = OMPBuilder.Task;
9636 ".omp_target_task_proxy_func", M);
9637 Value *ThreadId = ProxyFn->getArg(0);
9638 Value *TaskWithPrivates = ProxyFn->getArg(1);
9639 ThreadId->
setName(
"thread.id");
9640 TaskWithPrivates->
setName(
"task");
9642 bool HasShareds = SharedArgsOperandNo > 0;
9643 bool HasOffloadingArrays = NumOffloadingArrays > 0;
9647 Builder.SetInsertPoint(EntryBB);
9654 if (HasOffloadingArrays) {
9655 assert(TaskTy != TaskWithPrivatesTy &&
9656 "If there are offloading arrays to pass to the target"
9657 "TaskTy cannot be the same as TaskWithPrivatesTy");
9660 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 1);
9661 for (
unsigned int i = 0; i < NumOffloadingArrays; ++i)
9663 Builder.CreateStructGEP(PrivatesTy, Privates, i));
9667 auto *ArgStructAlloca =
9669 assert(ArgStructAlloca &&
9670 "Unable to find the alloca instruction corresponding to arguments "
9671 "for extracted function");
9673 std::optional<TypeSize> ArgAllocSize =
9675 assert(ArgStructType && ArgAllocSize &&
9676 "Unable to determine size of arguments for extracted function");
9677 uint64_t StructSize = ArgAllocSize->getFixedValue();
9680 Builder.CreateAlloca(ArgStructType,
nullptr,
"structArg");
9682 Value *SharedsSize = Builder.getInt64(StructSize);
9685 OMPBuilder, Builder, TaskWithPrivates, TaskWithPrivatesTy);
9687 Builder.CreateMemCpy(
9688 NewArgStructAlloca, NewArgStructAlloca->
getAlign(), LoadShared,
9690 KernelLaunchArgs.
push_back(NewArgStructAlloca);
9693 Builder.CreateRetVoid();
9699 return GEP->getSourceElementType();
9701 return Alloca->getAllocatedType();
9724 if (OffloadingArraysToPrivatize.
empty())
9725 return OMPIRBuilder.Task;
9728 for (
Value *
V : OffloadingArraysToPrivatize) {
9729 assert(
V->getType()->isPointerTy() &&
9730 "Expected pointer to array to privatize. Got a non-pointer value "
9733 assert(ArrayTy &&
"ArrayType cannot be nullptr");
9739 "struct.task_with_privates");
9754 EntryFnName, Inputs, CBFunc,
9755 ArgAccessorFuncCB, OutlinedFnLoc);
9759 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
9898 auto OI = std::make_unique<OutlineInfo>();
9899 OI->EntryBB = TargetTaskAllocaBB;
9900 OI->OuterAllocBB = AllocaIP.getNodeParent();
9905 Builder, AllocaIP, ToBeDeleted, TargetTaskAllocaIP,
"global.tid",
false));
9908 Builder.restoreIP(TargetTaskBodyIP);
9909 if (
Error Err = TaskBodyCB(DeviceID, RTLoc, TargetTaskAllocaIP))
9927 bool NeedsTargetTask = HasNoWait && DeviceID;
9928 if (NeedsTargetTask) {
9934 OffloadingArraysToPrivatize.
push_back(V);
9935 OI->ExcludeArgsFromAggregate.push_back(V);
9939 OI->PostOutlineCB = [
this, ToBeDeleted, Dependencies, NeedsTargetTask,
9940 DeviceID, OffloadingArraysToPrivatize](
9943 "there must be a single user for the outlined function");
9957 const unsigned int NumStaleCIArgs = StaleCI->
arg_size();
9958 bool HasShareds = NumStaleCIArgs > OffloadingArraysToPrivatize.
size() + 1;
9960 NumStaleCIArgs == (OffloadingArraysToPrivatize.
size() + 2)) &&
9961 "Wrong number of arguments for StaleCI when shareds are present");
9962 int SharedArgOperandNo =
9963 HasShareds ? OffloadingArraysToPrivatize.
size() + 1 : 0;
9969 if (!OffloadingArraysToPrivatize.
empty())
9974 *
this,
Builder, StaleCI, PrivatesTy, TaskWithPrivatesTy,
9975 OffloadingArraysToPrivatize.
size(), SharedArgOperandNo);
9977 LLVM_DEBUG(
dbgs() <<
"Proxy task entry function created: " << *ProxyFn
9980 Builder.SetInsertPoint(StaleCI);
9997 OMPRTL___kmpc_omp_target_task_alloc);
10009 M.getDataLayout().getTypeStoreSize(TaskWithPrivatesTy));
10016 auto *ArgStructAlloca =
10018 assert(ArgStructAlloca &&
10019 "Unable to find the alloca instruction corresponding to arguments "
10020 "for extracted function");
10021 std::optional<TypeSize> ArgAllocSize =
10024 "Unable to determine size of arguments for extracted function");
10025 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
10044 TaskSize, SharedsSize,
10047 if (NeedsTargetTask) {
10048 assert(DeviceID &&
"Expected non-empty device ID.");
10058 *
this,
Builder, TaskData, TaskWithPrivatesTy);
10062 if (!OffloadingArraysToPrivatize.
empty()) {
10064 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskData, 1);
10065 for (
unsigned int i = 0; i < OffloadingArraysToPrivatize.
size(); ++i) {
10066 Value *PtrToPrivatize = OffloadingArraysToPrivatize[i];
10073 "ElementType should match ArrayType");
10076 Value *Dst =
Builder.CreateStructGEP(PrivatesTy, Privates, i);
10079 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(ElementType)));
10083 Value *DepArray =
nullptr;
10084 Value *NumDeps =
nullptr;
10087 NumDeps = Dependencies.
NumDeps;
10088 }
else if (!Dependencies.
Deps.empty()) {
10090 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
10101 if (!NeedsTargetTask) {
10110 ConstantInt::get(
Builder.getInt32Ty(), 0),
10123 }
else if (DepArray) {
10131 {Ident, ThreadID, TaskData, NumDeps, DepArray,
10132 ConstantInt::get(
Builder.getInt32Ty(), 0),
10140 Builder.ClearInsertionPoint();
10143 I->eraseFromParent();
10148 << *(
Builder.GetInsertBlock()) <<
"\n");
10150 << *(
Builder.getModule()) <<
"\n");
10161 CustomMapperCB, IsNonContiguous, DeviceAddrCB))
10184 Builder.restoreIP(IP);
10190 return Builder.saveIP();
10193 bool HasDependencies = !Dependencies.
empty();
10194 bool RequiresOuterTargetTask = HasNoWait || HasDependencies;
10211 if (OutlinedFnID && DeviceID)
10213 EmitTargetCallFallbackCB, KArgs,
10214 DeviceID, RTLoc, TargetTaskAllocaIP);
10222 return EmitTargetCallFallbackCB(OMPBuilder.
Builder.
saveIP());
10229 auto &&EmitTargetCallElse =
10236 if (RequiresOuterTargetTask) {
10243 Dependencies, EmptyRTArgs, HasNoWait);
10245 return EmitTargetCallFallbackCB(Builder.saveIP());
10248 Builder.restoreIP(AfterIP);
10252 auto &&EmitTargetCallThen =
10256 Info.HasNoWait = HasNoWait;
10261 AllocaIP, Builder.saveIP(), Info, RTArgs, MapInfo, CustomMapperCB,
10267 for (
auto [DefaultVal, RuntimeVal] :
10269 NumTeamsC.
push_back(RuntimeVal ? RuntimeVal
10270 : Builder.getInt32(DefaultVal));
10274 auto InitMaxThreadsClause = [&Builder](
Value *
Clause) {
10276 Clause = Builder.CreateIntCast(
Clause, Builder.getInt32Ty(),
10280 auto CombineMaxThreadsClauses = [&Builder](
Value *
Clause,
Value *&Result) {
10283 Result ? Builder.CreateSelect(Builder.CreateICmpULT(Result,
Clause),
10291 Value *MaxThreadsClause =
10293 ? InitMaxThreadsClause(RuntimeAttrs.
MaxThreads.front())
10296 for (
auto [TeamsVal, TargetVal] :
zip_equal(
10298 Value *TeamsThreadLimitClause = InitMaxThreadsClause(TeamsVal);
10299 Value *NumThreads = InitMaxThreadsClause(TargetVal);
10301 CombineMaxThreadsClauses(TeamsThreadLimitClause, NumThreads);
10302 CombineMaxThreadsClauses(MaxThreadsClause, NumThreads);
10304 NumThreadsC.
push_back(NumThreads ? NumThreads : Builder.getInt32(0));
10307 unsigned NumTargetItems = Info.NumberOfPtrs;
10308 Value *RTLoc = RTLocOverride;
10319 Builder.getInt64Ty(),
10321 : Builder.getInt64(0);
10325 DynCGroupMem = Builder.getInt32(0);
10328 NumTargetItems, RTArgs, TripCount, NumTeamsC, NumThreadsC, DynCGroupMem,
10329 HasNoWait,
false,
false,
10330 DynCGroupMemFallback);
10337 if (RequiresOuterTargetTask)
10339 RTLoc, AllocaIP, Dependencies,
10340 KArgs.
RTArgs, Info.HasNoWait);
10343 Builder, OutlinedFnID, EmitTargetCallFallbackCB, KArgs,
10344 RuntimeAttrs.
DeviceID, RTLoc, AllocaIP);
10347 Builder.restoreIP(AfterIP);
10355 return EmitTargetCallElse(AllocaIP, Builder.saveIP(), DeallocBlocks);
10359 return EmitTargetCallThen(AllocaIP, Builder.saveIP(), DeallocBlocks);
10361 return OMPBuilder.
emitIfClause(IfCond, EmitTargetCallThen, EmitTargetCallElse,
10375 bool HasNowait,
Value *DynCGroupMem,
10377 Value *RTLocOverride) {
10382 Builder.restoreIP(CodeGenIP);
10390 *
this,
Builder, IsOffloadEntry, EntryInfo, DefaultAttrs, OutlinedFn,
10391 OutlinedFnID, Inputs, CBFunc, ArgAccessorFuncCB, OutlinedFnLoc))
10397 if (!
Config.isTargetDevice()) {
10399 *
this,
Builder, RTLocOverride, AllocaIP, DeallocBlocks, Info,
10400 DefaultAttrs, RuntimeAttrs, IfCond, OutlinedFn, OutlinedFnID,
10401 Inputs, GenMapInfoCB, CustomMapperCB, Dependencies, HasNowait,
10402 DynCGroupMem, DynCGroupMemFallback))
10418 return OS.
str().str();
10423 return OpenMPIRBuilder::getNameWithSeparators(Parts,
Config.firstSeparator(),
10429 auto &Elem = *
InternalVars.try_emplace(Name,
nullptr).first;
10431 assert(Elem.second->getValueType() == Ty &&
10432 "OMP internal variable has different type than requested");
10445 :
M.getTargetTriple().isAMDGPU()
10447 :
DL.getDefaultGlobalsAddressSpace();
10448 auto Linkage = this->
M.getTargetTriple().isWasm()
10456 const llvm::Align PtrAlign =
DL.getPointerABIAlignment(AddressSpaceVal);
10457 GV->setAlignment(std::max(TypeAlign, PtrAlign));
10461 return Elem.second;
10464Value *OpenMPIRBuilder::getOMPCriticalRegionLock(
StringRef CriticalName) {
10465 std::string Prefix =
Twine(
"gomp_critical_user_", CriticalName).
str();
10466 std::string Name = getNameWithSeparators({Prefix,
"var"},
".",
".");
10477 return SizePtrToInt;
10482 std::string VarName) {
10490 return MaptypesArrayGlobal;
10495 unsigned NumOperands,
10504 ArrI8PtrTy,
nullptr,
".offload_baseptrs");
10508 ArrI64Ty,
nullptr,
".offload_sizes");
10519 int64_t DeviceID,
unsigned NumOperands) {
10525 Value *ArgsBaseGEP =
10527 {Builder.getInt32(0), Builder.getInt32(0)});
10530 {Builder.getInt32(0), Builder.getInt32(0)});
10531 Value *ArgSizesGEP =
10533 {Builder.getInt32(0), Builder.getInt32(0)});
10537 Builder.getInt32(NumOperands),
10538 ArgsBaseGEP, ArgsGEP, ArgSizesGEP,
10539 MaptypesArg, MapnamesArg, NullPtr});
10546 assert((!ForEndCall || Info.separateBeginEndCalls()) &&
10547 "expected region end call to runtime only when end call is separate");
10549 auto VoidPtrTy = UnqualPtrTy;
10550 auto VoidPtrPtrTy = UnqualPtrTy;
10552 auto Int64PtrTy = UnqualPtrTy;
10554 if (!Info.NumberOfPtrs) {
10566 Info.RTArgs.BasePointersArray,
10569 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray,
10573 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
10577 ForEndCall && Info.RTArgs.MapTypesArrayEnd ? Info.RTArgs.MapTypesArrayEnd
10578 : Info.RTArgs.MapTypesArray,
10584 if (!Info.EmitDebug)
10588 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.MapNamesArray,
10593 if (!Info.HasMapper)
10597 Builder.CreatePointerCast(Info.RTArgs.MappersArray, VoidPtrPtrTy);
10618 "struct.descriptor_dim");
10620 enum { OffsetFD = 0, CountFD, StrideFD };
10624 for (
unsigned I = 0, L = 0, E = NonContigInfo.
Dims.
size();
I < E; ++
I) {
10627 if (NonContigInfo.
Dims[
I] == 1)
10632 Builder.CreateAlloca(ArrayTy,
nullptr,
"dims");
10633 Builder.restoreIP(CodeGenIP);
10634 for (
unsigned II = 0, EE = NonContigInfo.
Dims[
I];
II < EE; ++
II) {
10635 unsigned RevIdx = EE -
II - 1;
10639 Value *OffsetLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, OffsetFD);
10641 NonContigInfo.
Offsets[L][RevIdx], OffsetLVal,
10642 M.getDataLayout().getPrefTypeAlign(OffsetLVal->
getType()));
10644 Value *CountLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, CountFD);
10646 NonContigInfo.
Counts[L][RevIdx], CountLVal,
10647 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10649 Value *StrideLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, StrideFD);
10651 NonContigInfo.
Strides[L][RevIdx], StrideLVal,
10652 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10655 Builder.restoreIP(CodeGenIP);
10656 Value *DAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
10657 DimsAddr,
Builder.getPtrTy());
10660 Info.RTArgs.PointersArray, 0,
I);
10662 DAddr,
P,
M.getDataLayout().getPrefTypeAlign(
Builder.getPtrTy()));
10667void OpenMPIRBuilder::emitUDMapperArrayInitOrDel(
10671 StringRef Prefix = IsInit ?
".init" :
".del";
10677 Builder.CreateICmpSGT(
Size, Builder.getInt64(1),
"omp.arrayinit.isarray");
10678 Value *DeleteBit = Builder.CreateAnd(
10681 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10682 OpenMPOffloadMappingFlags::OMP_MAP_DELETE)));
10687 Value *BaseIsBegin = Builder.CreateICmpNE(
Base, Begin);
10688 Cond = Builder.CreateOr(IsArray, BaseIsBegin);
10689 DeleteCond = Builder.CreateIsNull(
10694 DeleteCond =
Builder.CreateIsNotNull(
10710 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10711 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10712 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10713 MapTypeArg =
Builder.CreateOr(
10716 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10717 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT)));
10721 Value *OffloadingArgs[] = {MapperHandle,
Base, Begin,
10722 ArraySize, MapTypeArg, MapName};
10733 bool PreserveMemberOfFlags,
bool PropagatePresentToPointeeStorage,
10734 bool PropagatePresentToNonPointeeStorage) {
10748 MapperFn->
addFnAttr(Attribute::NoInline);
10749 MapperFn->
addFnAttr(Attribute::NoUnwind);
10760 Builder.SetInsertPoint(EntryBB);
10775 Value *PtrBegin = BeginIn;
10781 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
10782 MapType, MapName, ElementSize, HeadBB,
10793 Builder.CreateICmpEQ(PtrBegin, PtrEnd,
"omp.arraymap.isempty");
10794 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
10800 Builder.CreatePHI(PtrBegin->
getType(), 2,
"omp.arraymap.ptrcurrent");
10801 PtrPHI->addIncoming(PtrBegin, HeadBB);
10806 return Info.takeError();
10810 Value *OffloadingArgs[] = {MapperHandle};
10814 Value *ShiftedPreviousSize =
10818 for (
unsigned I = 0;
I < Info->BasePointers.size(); ++
I) {
10819 Value *CurBaseArg = Info->BasePointers[
I];
10820 Value *CurBeginArg = Info->Pointers[
I];
10821 Value *CurSizeArg = Info->Sizes[
I];
10822 Value *CurNameArg = Info->Names.size()
10827 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10830 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10832 constexpr uint64_t MemberOfMask =
10833 static_cast<uint64_t
>(OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
10834 constexpr uint64_t AttachBit =
10835 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10836 OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
10837 constexpr uint64_t PtrAndObjBit =
10838 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10839 OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ);
10897 Value *MemberMapType;
10898 if (PreserveMemberOfFlags || (RawType & AttachBit) ||
10899 Info->HasAttachPtr[
I]) {
10900 if (RawType & MemberOfMask)
10901 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
10903 MemberMapType = OriMapType;
10905 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
10923 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10924 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10925 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10935 Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
10941 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10942 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10943 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10949 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10950 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
10951 Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
10957 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10958 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10964 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10965 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10966 Builder.CreateCondBr(IsFrom, FromBB, EndBB);
10972 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10973 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
10982 CurMapType->
addIncoming(MemberMapType, ToElseBB);
11021 uint64_t ModifierBits =
11022 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11023 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
11024 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
11025 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
11026 bool IsPresentEligibleStorage = !(RawType & (AttachBit | PtrAndObjBit));
11027 bool PropagatePresent =
11028 IsPresentEligibleStorage &&
11029 (Info->HasAttachPtr[
I] ? PropagatePresentToPointeeStorage
11030 : PropagatePresentToNonPointeeStorage);
11031 if (PropagatePresent)
11033 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11034 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
11035 Value *ImportedModifierBits =
11038 CurMapType, ImportedModifierBits,
"omp.maptype.with.modifiers");
11043 Value *FinalMapType =
11044 (RawType & AttachBit) ? CurMapType : CurMapTypeWithModifiers;
11046 Value *OffloadingArgs[] = {MapperHandle, CurBaseArg, CurBeginArg,
11047 CurSizeArg, FinalMapType, CurNameArg};
11049 auto ChildMapperFn = CustomMapperCB(
I);
11050 if (!ChildMapperFn)
11051 return ChildMapperFn.takeError();
11052 if (*ChildMapperFn) {
11068 "omp.arraymap.next");
11069 PtrPHI->addIncoming(PtrNext, LastBB);
11070 Value *IsDone =
Builder.CreateICmpEQ(PtrNext, PtrEnd,
"omp.arraymap.isdone");
11072 Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
11077 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
11078 MapType, MapName, ElementSize, DoneBB,
11091 bool IsNonContiguous,
11095 Info.clearArrayInfo();
11098 if (Info.NumberOfPtrs == 0)
11107 Info.RTArgs.BasePointersArray =
Builder.CreateAlloca(
11108 PointerArrayType,
nullptr,
".offload_baseptrs");
11110 Info.RTArgs.PointersArray =
Builder.CreateAlloca(
11111 PointerArrayType,
nullptr,
".offload_ptrs");
11113 PointerArrayType,
nullptr,
".offload_mappers");
11114 Info.RTArgs.MappersArray = MappersArray;
11121 ConstantInt::get(Int64Ty, 0));
11123 for (
unsigned I = 0, E = CombinedInfo.
Sizes.
size();
I < E; ++
I) {
11124 bool IsNonContigEntry =
11126 (
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11128 OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG) != 0);
11131 if (IsNonContigEntry) {
11133 "Index must be in-bounds for NON_CONTIG Dims array");
11135 assert(DimCount > 0 &&
"NON_CONTIG DimCount must be > 0");
11136 ConstSizes[
I] = ConstantInt::get(Int64Ty, DimCount);
11141 ConstSizes[
I] = CI;
11145 RuntimeSizes.
set(
I);
11148 if (RuntimeSizes.
all()) {
11150 Info.RTArgs.SizesArray =
Builder.CreateAlloca(
11151 SizeArrayType,
nullptr,
".offload_sizes");
11157 auto *SizesArrayGbl =
11162 if (!RuntimeSizes.
any()) {
11163 Info.RTArgs.SizesArray = SizesArrayGbl;
11165 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
11166 Align OffloadSizeAlign =
M.getDataLayout().getABIIntegerTypeAlignment(64);
11169 SizeArrayType,
nullptr,
".offload_sizes");
11173 Buffer,
M.getDataLayout().getPrefTypeAlign(Buffer->
getType()),
11174 SizesArrayGbl, OffloadSizeAlign,
11179 Info.RTArgs.SizesArray = Buffer;
11187 for (
auto mapFlag : CombinedInfo.
Types)
11189 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11193 Info.RTArgs.MapTypesArray = MapTypesArrayGbl;
11199 Info.RTArgs.MapNamesArray = MapNamesArrayGbl;
11200 Info.EmitDebug =
true;
11202 Info.RTArgs.MapNamesArray =
11204 Info.EmitDebug =
false;
11209 if (Info.separateBeginEndCalls()) {
11210 bool EndMapTypesDiffer =
false;
11211 for (uint64_t &
Type : Mapping) {
11212 if (
Type &
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11213 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT)) {
11214 Type &= ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
11215 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
11216 EndMapTypesDiffer =
true;
11219 if (EndMapTypesDiffer) {
11221 Info.RTArgs.MapTypesArrayEnd = MapTypesArrayGbl;
11226 for (
unsigned I = 0;
I < Info.NumberOfPtrs; ++
I) {
11229 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.BasePointersArray,
11231 Builder.CreateAlignedStore(BPVal, BP,
11232 M.getDataLayout().getPrefTypeAlign(PtrTy));
11234 if (Info.requiresDevicePointerInfo()) {
11236 CodeGenIP =
Builder.saveIP();
11238 Info.DevicePtrInfoMap[BPVal] = {BP,
Builder.CreateAlloca(PtrTy)};
11241 DeviceAddrCB(
I, Info.DevicePtrInfoMap[BPVal].second);
11243 Info.DevicePtrInfoMap[BPVal] = {BP, BP};
11245 DeviceAddrCB(
I, BP);
11251 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray, 0,
11254 Builder.CreateAlignedStore(PVal,
P,
11255 M.getDataLayout().getPrefTypeAlign(PtrTy));
11257 if (RuntimeSizes.
test(
I)) {
11259 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
11265 S,
M.getDataLayout().getPrefTypeAlign(PtrTy));
11268 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
11271 auto CustomMFunc = CustomMapperCB(
I);
11273 return CustomMFunc.takeError();
11275 MFunc =
Builder.CreatePointerCast(*CustomMFunc, PtrTy);
11278 PointerArrayType, MappersArray,
11281 MFunc, MAddr,
M.getDataLayout().getPrefTypeAlign(MAddr->
getType()));
11285 Info.NumberOfPtrs == 0)
11302 Builder.ClearInsertionPoint();
11333 auto CondConstant = CI->getSExtValue();
11335 return ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
11337 return ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
11347 Builder.CreateCondBr(
Cond, ThenBlock, ElseBlock);
11350 if (
Error Err = ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks)) {
11360 if (
Error Err = ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks)) {
11371bool OpenMPIRBuilder::checkAndEmitFlushAfterAtomic(
11375 "Unexpected Atomic Ordering.");
11377 bool Flush =
false;
11439 assert(
X.Var->getType()->isPointerTy() &&
11440 "OMP Atomic expects a pointer to target memory");
11441 Type *XElemTy =
X.ElemTy;
11444 "OMP atomic read expected a scalar type");
11446 Value *XRead =
nullptr;
11450 Builder.CreateLoad(XElemTy,
X.Var,
X.IsVolatile,
"omp.atomic.read");
11459 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11462 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11464 XRead = AtomicLoadRes.first;
11471 Builder.CreateLoad(IntCastTy,
X.Var,
X.IsVolatile,
"omp.atomic.load");
11474 XRead =
Builder.CreateBitCast(XLoad, XElemTy,
"atomic.flt.cast");
11476 XRead =
Builder.CreateIntToPtr(XLoad, XElemTy,
"atomic.ptr.cast");
11479 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Read);
11480 Builder.CreateStore(XRead, V.Var, V.IsVolatile);
11491 assert(
X.Var->getType()->isPointerTy() &&
11492 "OMP Atomic expects a pointer to target memory");
11493 Type *XElemTy =
X.ElemTy;
11496 "OMP atomic write expected a scalar type");
11504 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11507 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11515 Builder.CreateBitCast(Expr, IntCastTy,
"atomic.src.int.cast");
11520 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Write);
11527 AtomicUpdateCallbackTy &UpdateOp,
bool IsXBinopExpr,
11528 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11534 Type *XTy =
X.Var->getType();
11536 "OMP Atomic expects a pointer to target memory");
11537 Type *XElemTy =
X.ElemTy;
11540 "OMP atomic update expected a scalar or struct type");
11544 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, RMWOp, UpdateOp,
X.IsVolatile,
11545 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11547 return AtomicResult.takeError();
11548 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Update);
11553Value *OpenMPIRBuilder::emitRMWOpAsInstruction(
Value *Src1,
Value *Src2,
11557 return Builder.CreateAdd(Src1, Src2);
11559 return Builder.CreateSub(Src1, Src2);
11561 return Builder.CreateAnd(Src1, Src2);
11563 return Builder.CreateNeg(Builder.CreateAnd(Src1, Src2));
11565 return Builder.CreateOr(Src1, Src2);
11567 return Builder.CreateXor(Src1, Src2);
11569 return Builder.CreateBinaryIntrinsic(Intrinsic::smax, Src1, Src2);
11571 return Builder.CreateBinaryIntrinsic(Intrinsic::smin, Src1, Src2);
11573 return Builder.CreateBinaryIntrinsic(Intrinsic::umax, Src1, Src2);
11575 return Builder.CreateBinaryIntrinsic(Intrinsic::umin, Src1, Src2);
11577 return Builder.CreateFAdd(Src1, Src2);
11579 return Builder.CreateFSub(Src1, Src2);
11581 return Builder.CreateMaxNum(Src1, Src2);
11583 return Builder.CreateMinNum(Src1, Src2);
11585 return Builder.CreateMaximum(Src1, Src2);
11587 return Builder.CreateMinimum(Src1, Src2);
11616Expected<std::pair<Value *, Value *>> OpenMPIRBuilder::emitAtomicUpdate(
11619 AtomicUpdateCallbackTy &UpdateOp,
bool VolatileX,
bool IsXBinopExpr,
11620 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11622 bool emitRMWOp =
false;
11639 emitRMWOp = XElemTy;
11643 emitRMWOp = (IsXBinopExpr && XElemTy);
11651 std::pair<Value *, Value *> Res;
11653 AtomicRMWInst *RMWInst =
11654 Builder.CreateAtomicRMW(RMWOp,
X, Expr, llvm::MaybeAlign(), AO);
11655 if (IsIgnoreDenormalMode)
11656 RMWInst->
setMetadata(llvm::LLVMContext::MD_atomic_ignore_denormal_mode,
11658 if (
T.isAMDGPU()) {
11659 if (!IsFineGrainedMemory)
11660 RMWInst->
setMetadata(
"amdgpu.no.fine.grained.memory",
11662 if (!IsRemoteMemory)
11666 Res.first = RMWInst;
11671 Res.second = Res.first;
11673 Res.second = emitRMWOpAsInstruction(Res.first, Expr, RMWOp);
11676 Builder.CreateLoad(XElemTy,
X,
X->getName() +
".atomic.load");
11682 OpenMPIRBuilder::AtomicInfo atomicInfo(
11684 OldVal->
getAlign(),
true , AllocaIP,
X);
11685 auto AtomicLoadRes = atomicInfo.EmitAtomicLoadLibcall(AO);
11688 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11695 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11696 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11697 Builder.SetInsertPoint(ContBB);
11699 PHI->addIncoming(AtomicLoadRes.first, CurBB);
11701 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11704 Value *Upd = *CBResult;
11705 Builder.CreateStore(Upd, NewAtomicAddr);
11708 auto Result = atomicInfo.EmitAtomicCompareExchangeLibcall(
11709 AtomicLoadRes.second, NewAtomicAddr, AO, Failure);
11710 LoadInst *PHILoad =
Builder.CreateLoad(XElemTy,
Result.first);
11711 PHI->addIncoming(PHILoad,
Builder.GetInsertBlock());
11714 Res.first = OldExprVal;
11717 if (UnreachableInst *ExitTI =
11720 Builder.SetInsertPoint(ExitBB);
11722 Builder.SetInsertPoint(ExitTI);
11725 IntegerType *IntCastTy =
11728 Builder.CreateLoad(IntCastTy,
X,
X->getName() +
".atomic.load");
11738 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11745 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11746 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11747 Builder.SetInsertPoint(ContBB);
11749 PHI->addIncoming(OldVal, CurBB);
11754 OldExprVal =
Builder.CreateBitCast(
PHI, XElemTy,
11755 X->getName() +
".atomic.fltCast");
11757 OldExprVal =
Builder.CreateIntToPtr(
PHI, XElemTy,
11758 X->getName() +
".atomic.ptrCast");
11762 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11765 Value *Upd = *CBResult;
11766 Builder.CreateStore(Upd, NewAtomicAddr);
11767 LoadInst *DesiredVal =
Builder.CreateLoad(IntCastTy, NewAtomicAddr);
11771 X,
PHI, DesiredVal, llvm::MaybeAlign(), AO, Failure);
11772 Result->setVolatile(VolatileX);
11773 Value *PreviousVal =
Builder.CreateExtractValue(Result, 0);
11774 Value *SuccessFailureVal =
Builder.CreateExtractValue(Result, 1);
11775 PHI->addIncoming(PreviousVal,
Builder.GetInsertBlock());
11776 Builder.CreateCondBr(SuccessFailureVal, ExitBB, ContBB);
11778 Res.first = OldExprVal;
11782 if (UnreachableInst *ExitTI =
11785 Builder.SetInsertPoint(ExitBB);
11787 Builder.SetInsertPoint(ExitTI);
11798 bool UpdateExpr,
bool IsPostfixUpdate,
bool IsXBinopExpr,
11799 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11804 Type *XTy =
X.Var->getType();
11806 "OMP Atomic expects a pointer to target memory");
11807 Type *XElemTy =
X.ElemTy;
11810 "OMP atomic capture expected a scalar or struct type");
11817 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, AtomicOp, UpdateOp,
X.IsVolatile,
11818 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11821 Value *CapturedVal =
11822 (IsPostfixUpdate ? AtomicResult->first : AtomicResult->second);
11823 Builder.CreateStore(CapturedVal, V.Var, V.IsVolatile);
11825 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Capture);
11833 bool IsFailOnly,
bool IsWeak) {
11837 IsPostfixUpdate, IsFailOnly, Failure, IsWeak);
11849 assert(
X.Var->getType()->isPointerTy() &&
11850 "OMP atomic expects a pointer to target memory");
11853 assert(V.Var->getType()->isPointerTy() &&
"v.var must be of pointer type");
11854 assert(V.ElemTy ==
X.ElemTy &&
"x and v must be of same type");
11857 bool IsInteger = E->getType()->isIntegerTy();
11859 if (
Op == OMPAtomicCompareOp::EQ) {
11862 Value *OldValue =
nullptr;
11863 Value *SuccessOrFail =
nullptr;
11901 X.Var->getName() +
".atomic.load");
11907 Value *EIsNaN =
Builder.CreateFCmpUNO(E, E,
"atomic.e.isnan");
11908 Value *XIsNaN =
Builder.CreateFCmpUNO(XFP, XFP,
"atomic.x.isnan");
11909 Value *EitherNaN =
Builder.CreateOr(EIsNaN, XIsNaN,
"atomic.either.nan");
11914 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11918 M.getContext(),
X.Var->getName() +
".atomic.nan",
F, ExitBB);
11920 M.getContext(),
X.Var->getName() +
".atomic.notnan",
F, ExitBB);
11922 M.getContext(),
X.Var->getName() +
".atomic.zero",
F, ExitBB);
11924 M.getContext(),
X.Var->getName() +
".atomic.normal",
F, ExitBB);
11928 Builder.SetInsertPoint(CurBB);
11929 Builder.CreateCondBr(EitherNaN, NaNBB, NotNaNBB);
11932 Builder.SetInsertPoint(NaNBB);
11936 Builder.SetInsertPoint(NotNaNBB);
11939 X.Var->getName() +
".atomic.xiszero");
11941 "atomic.e.iszero");
11942 Value *BothZero =
Builder.CreateAnd(XIsZero, EIsZero,
"atomic.both.zero");
11943 Builder.CreateCondBr(BothZero, ZeroBB, NormalBB);
11946 Builder.SetInsertPoint(ZeroBB);
11948 X.Var, XCurr, DBCast,
MaybeAlign(), AO, Failure);
11950 Value *OldZero =
Builder.CreateExtractValue(ResZero, 0);
11951 Value *OkZero =
Builder.CreateExtractValue(ResZero, 1);
11955 Builder.SetInsertPoint(NormalBB);
11957 X.Var, EBCast, DBCast,
MaybeAlign(), AO, Failure);
11959 Value *OldNormal =
Builder.CreateExtractValue(ResNormal, 0);
11960 Value *OkNormal =
Builder.CreateExtractValue(ResNormal, 1);
11966 Builder.CreatePHI(IntCastTy, 3,
X.Var->getName() +
".atomic.old");
11971 X.Var->getName() +
".atomic.ok");
11978 Builder.SetInsertPoint(ExitBB);
11983 OldValue =
Builder.CreateBitCast(OldIntPHI,
X.ElemTy,
11984 X.Var->getName() +
".atomic.old.fp");
11985 SuccessOrFail = SuccessPHI;
11993 Result =
Builder.CreateAtomicCmpXchg(
X.Var, EBCast, DBCast,
11999 Result->setWeak(IsWeak);
12002 OldValue =
Builder.CreateExtractValue(Result, 0);
12004 OldValue =
Builder.CreateBitCast(OldValue,
X.ElemTy);
12006 "OldValue and V must be of same type");
12007 if (IsPostfixUpdate) {
12008 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
12010 SuccessOrFail =
Builder.CreateExtractValue(Result, 1);
12014 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
12016 CurBBTI,
X.Var->getName() +
".atomic.exit");
12022 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
12024 Builder.SetInsertPoint(ContBB);
12025 Builder.CreateStore(OldValue, V.Var);
12031 Builder.SetInsertPoint(ExitBB);
12033 Builder.SetInsertPoint(ExitTI);
12036 Value *CapturedValue =
12037 Builder.CreateSelect(SuccessOrFail, E, OldValue);
12038 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
12044 assert(R.Var->getType()->isPointerTy() &&
12045 "r.var must be of pointer type");
12046 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
12048 Value *SuccessFailureVal =
12049 Builder.CreateExtractValue(Result, 1);
12050 Value *ResultCast =
12051 R.IsSigned ?
Builder.CreateSExt(SuccessFailureVal, R.ElemTy)
12052 :
Builder.CreateZExt(SuccessFailureVal, R.ElemTy);
12053 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
12062 "OldValue and V must be of same type");
12063 if (IsPostfixUpdate) {
12064 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
12069 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
12071 CurBBTI,
X.Var->getName() +
".atomic.exit");
12077 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
12079 Builder.SetInsertPoint(ContBB);
12080 Builder.CreateStore(OldValue, V.Var);
12086 Builder.SetInsertPoint(ExitBB);
12088 Builder.SetInsertPoint(ExitTI);
12091 Value *CapturedValue =
12092 Builder.CreateSelect(SuccessOrFail, E, OldValue);
12093 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
12099 assert(R.Var->getType()->isPointerTy() &&
12100 "r.var must be of pointer type");
12101 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
12103 Value *ResultCast = R.IsSigned
12104 ?
Builder.CreateSExt(SuccessOrFail, R.ElemTy)
12105 :
Builder.CreateZExt(SuccessOrFail, R.ElemTy);
12106 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
12110 assert((
Op == OMPAtomicCompareOp::MAX ||
Op == OMPAtomicCompareOp::MIN) &&
12111 "Op should be either max or min at this point");
12112 assert(!IsFailOnly &&
"IsFailOnly is only valid when the comparison is ==");
12123 if (IsXBinopExpr) {
12152 Value *CapturedValue =
nullptr;
12153 if (IsPostfixUpdate) {
12154 CapturedValue = OldValue;
12179 Value *NonAtomicCmp =
Builder.CreateCmp(Pred, OldValue, E);
12180 CapturedValue =
Builder.CreateSelect(NonAtomicCmp, E, OldValue);
12182 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
12186 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Compare);
12206 if (&OuterAllocaBB ==
Builder.GetInsertBlock()) {
12233 bool SubClausesPresent =
12234 (NumTeamsLower || NumTeamsUpper || ThreadLimit || IfExpr);
12236 if (!
Config.isTargetDevice() && SubClausesPresent) {
12237 assert((NumTeamsLower ==
nullptr || NumTeamsUpper !=
nullptr) &&
12238 "if lowerbound is non-null, then upperbound must also be non-null "
12239 "for bounds on num_teams");
12241 if (NumTeamsUpper ==
nullptr)
12242 NumTeamsUpper =
Builder.getInt32(0);
12244 if (NumTeamsLower ==
nullptr)
12245 NumTeamsLower = NumTeamsUpper;
12249 "argument to if clause must be an integer value");
12253 IfExpr =
Builder.CreateICmpNE(IfExpr,
12254 ConstantInt::get(IfExpr->
getType(), 0));
12255 NumTeamsUpper =
Builder.CreateSelect(
12256 IfExpr, NumTeamsUpper,
Builder.getInt32(1),
"numTeamsUpper");
12259 NumTeamsLower =
Builder.CreateSelect(
12260 IfExpr, NumTeamsLower,
Builder.getInt32(1),
"numTeamsLower");
12263 if (ThreadLimit ==
nullptr)
12264 ThreadLimit =
Builder.getInt32(0);
12268 Value *NumTeamsLowerInt32 =
12270 Value *NumTeamsUpperInt32 =
12272 Value *ThreadLimitInt32 =
12279 {Ident, ThreadNum, NumTeamsLowerInt32, NumTeamsUpperInt32,
12280 ThreadLimitInt32});
12285 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
12288 auto OI = std::make_unique<OutlineInfo>();
12289 OI->EntryBB = AllocaBB;
12290 OI->ExitBB = ExitBB;
12291 OI->OuterAllocBB = &OuterAllocaBB;
12297 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"gid",
true));
12299 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"tid",
true));
12301 auto HostPostOutlineCB = [
this, Ident,
12302 ToBeDeleted](
Function &OutlinedFn)
mutable {
12307 "there must be a single user for the outlined function");
12312 "Outlined function must have two or three arguments only");
12314 bool HasShared = OutlinedFn.
arg_size() == 3;
12322 assert(StaleCI &&
"Error while outlining - no CallInst user found for the "
12323 "outlined function.");
12324 Builder.SetInsertPoint(StaleCI);
12331 omp::RuntimeFunction::OMPRTL___kmpc_fork_teams),
12334 Builder.ClearInsertionPoint();
12336 I->eraseFromParent();
12339 if (!
Config.isTargetDevice())
12340 OI->PostOutlineCB = HostPostOutlineCB;
12344 Builder.SetInsertPoint(ExitBB);
12355 BasicBlock *OuterAllocaBB = OuterAllocIP.getNodeParent();
12357 if (OuterAllocaBB ==
Builder.GetInsertBlock()) {
12372 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
12377 if (
Config.isTargetDevice()) {
12378 auto OI = std::make_unique<OutlineInfo>();
12379 OI->OuterAllocBB = OuterAllocIP.getNodeParent();
12380 OI->EntryBB = AllocaBB;
12381 OI->ExitBB = ExitBB;
12382 OI->OuterDeallocBBs.reserve(OuterDeallocBlocks.
size());
12383 copy(OuterDeallocBlocks, OI->OuterDeallocBBs.
end());
12387 Builder.SetInsertPoint(ExitBB);
12394 std::string VarName) {
12403 return MapNamesArrayGlobal;
12408void OpenMPIRBuilder::initializeTypes(
Module &M) {
12412 unsigned ProgramAS = M.getDataLayout().getProgramAddressSpace();
12413#define OMP_TYPE(VarName, InitValue) VarName = InitValue;
12414#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \
12415 VarName##Ty = ArrayType::get(ElemTy, ArraySize); \
12416 VarName##PtrTy = PointerType::get(Ctx, DefaultTargetAS);
12417#define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) \
12418 VarName = FunctionType::get(ReturnType, {__VA_ARGS__}, IsVarArg); \
12419 VarName##Ptr = PointerType::get(Ctx, ProgramAS);
12420#define OMP_STRUCT_TYPE(VarName, StructName, Packed, ...) \
12421 T = StructType::getTypeByName(Ctx, StructName); \
12423 T = StructType::create(Ctx, {__VA_ARGS__}, StructName, Packed); \
12425 VarName##Ptr = PointerType::get(Ctx, DefaultTargetAS);
12426#include "llvm/Frontend/OpenMP/OMPKinds.def"
12437 while (!Worklist.
empty()) {
12441 if (
BlockSet.insert(SuccBB).second)
12446std::unique_ptr<CodeExtractor>
12448 bool ArgsInZeroAddressSpace,
12450 return std::make_unique<CodeExtractor>(
12460 Suffix.
str(), ArgsInZeroAddressSpace);
12463std::unique_ptr<CodeExtractor> DeviceSharedMemOutlineInfo::createCodeExtractor(
12465 return std::make_unique<DeviceSharedMemCodeExtractor>(
12466 OMPBuilder, Blocks,
nullptr,
12474 OuterDeallocBBs.empty()
12477 Suffix.
str(), ArgsInZeroAddressSpace);
12481 uint64_t
Size, int32_t Flags,
12487 Name.empty() ? Addr->
getName() : Name,
Size, Flags, 0);
12499 Fn->
addFnAttr(
"uniform-work-group-size");
12500 Fn->
addFnAttr(Attribute::MustProgress);
12518 auto &&GetMDInt = [
this](
unsigned V) {
12525 NamedMDNode *MD =
M.getOrInsertNamedMetadata(
"omp_offload.info");
12526 auto &&TargetRegionMetadataEmitter =
12527 [&
C, MD, &OrderedEntries, &GetMDInt, &GetMDString](
12542 GetMDInt(E.getKind()), GetMDInt(EntryInfo.DeviceID),
12543 GetMDInt(EntryInfo.FileID), GetMDString(EntryInfo.ParentName),
12544 GetMDInt(EntryInfo.Line), GetMDInt(EntryInfo.Count),
12545 GetMDInt(E.getOrder())};
12548 OrderedEntries[E.getOrder()] = std::make_pair(&E, EntryInfo);
12557 auto &&DeviceGlobalVarMetadataEmitter =
12558 [&
C, &OrderedEntries, &GetMDInt, &GetMDString, MD](
12568 Metadata *
Ops[] = {GetMDInt(E.getKind()), GetMDString(MangledName),
12569 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
12573 OrderedEntries[E.getOrder()] = std::make_pair(&E, varInfo);
12580 DeviceGlobalVarMetadataEmitter);
12582 for (
const auto &E : OrderedEntries) {
12583 assert(E.first &&
"All ordered entries must exist!");
12584 if (
const auto *CE =
12587 if (!CE->getID() || !CE->getAddress()) {
12591 if (!
M.getNamedValue(FnName))
12599 }
else if (
const auto *CE =
dyn_cast<
12608 if (
Config.isTargetDevice() &&
Config.hasRequiresUnifiedSharedMemory())
12610 if (!CE->getAddress()) {
12615 if (CE->getVarSize() == 0)
12619 assert(((
Config.isTargetDevice() && !CE->getAddress()) ||
12620 (!
Config.isTargetDevice() && CE->getAddress())) &&
12621 "Declaret target link address is set.");
12622 if (
Config.isTargetDevice())
12624 if (!CE->getAddress()) {
12631 if (!CE->getAddress()) {
12644 if ((
GV->hasLocalLinkage() ||
GV->hasHiddenVisibility()) &&
12648 OMPTargetGlobalVarEntryIndirectVTable))
12657 Flags, CE->getLinkage(), CE->getVarName());
12660 Flags, CE->getLinkage());
12671 if (
Config.hasRequiresFlags() && !
Config.isTargetDevice())
12677 Config.getRequiresFlags());
12687 OS <<
"_" <<
Count;
12692 unsigned NewCount = getTargetRegionEntryInfoCount(EntryInfo);
12695 EntryInfo.
Line, NewCount);
12703 auto FileIDInfo = CallBack();
12704 uint64_t FileID = 0;
12706 ID =
Status->getUniqueID();
12707 FileID =
Status->getUniqueID().getFile();
12711 FileID =
hash_value(std::get<0>(FileIDInfo));
12715 std::get<1>(FileIDInfo));
12720 for (uint64_t Remain =
12721 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12723 !(Remain & 1); Remain = Remain >> 1)
12741 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12743 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12750 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12756 Flags &=
~omp::OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
12757 Flags |= MemberOfFlag;
12763 bool IsDeclaration,
bool IsExternallyVisible,
12765 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12766 std::vector<Triple> TargetTriple,
Type *LlvmPtrTy,
12767 std::function<
Constant *()> GlobalInitializer,
12778 Config.hasRequiresUnifiedSharedMemory())) {
12783 if (!IsExternallyVisible)
12785 OS <<
"_decl_tgt_ref_ptr";
12788 Value *Ptr =
M.getNamedValue(PtrName);
12797 if (!
Config.isTargetDevice()) {
12798 if (GlobalInitializer)
12799 GV->setInitializer(GlobalInitializer());
12805 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12806 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12807 GlobalInitializer, VariableLinkage, LlvmPtrTy,
cast<Constant>(Ptr));
12819 bool IsDeclaration,
bool IsExternallyVisible,
12821 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12822 std::vector<Triple> TargetTriple,
12823 std::function<
Constant *()> GlobalInitializer,
12827 (TargetTriple.empty() && !
Config.isTargetDevice()))
12838 !
Config.hasRequiresUnifiedSharedMemory()) {
12840 VarName = MangledName;
12843 if (!IsDeclaration)
12845 M.getDataLayout().getTypeSizeInBits(LlvmVal->
getValueType()), 8);
12848 Linkage = (VariableLinkage) ? VariableLinkage() : LlvmVal->
getLinkage();
12852 if (
Config.isTargetDevice() &&
12861 if (!
M.getNamedValue(RefName)) {
12865 GvAddrRef->setConstant(
true);
12867 GvAddrRef->setInitializer(Addr);
12868 GeneratedRefs.push_back(GvAddrRef);
12877 if (
Config.isTargetDevice()) {
12878 VarName = (Addr) ? Addr->
getName() :
"";
12882 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12883 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12884 LlvmPtrTy, GlobalInitializer, VariableLinkage);
12885 VarName = (Addr) ? Addr->
getName() :
"";
12887 VarSize =
M.getDataLayout().getPointerSize();
12906 auto &&GetMDInt = [MN](
unsigned Idx) {
12911 auto &&GetMDString = [MN](
unsigned Idx) {
12913 return V->getString();
12916 switch (GetMDInt(0)) {
12920 case OffloadEntriesInfoManager::OffloadEntryInfo::
12921 OffloadingEntryInfoTargetRegion: {
12931 case OffloadEntriesInfoManager::OffloadEntryInfo::
12932 OffloadingEntryInfoDeviceGlobalVar:
12945 if (HostFilePath.
empty())
12949 if (std::error_code Err = Buf.getError()) {
12951 "OpenMPIRBuilder: " +
12959 if (std::error_code Err =
M.getError()) {
12961 (
"error parsing host file inside of OpenMPIRBuilder: " + Err.message())
12975 "expected a valid insertion block for creating an iterator loop");
12979 if (SplitIP == CurBB->
end())
12981 SplitIP = Terminator->getIterator();
12985 Builder.getCurrentDebugLocation(),
"omp.it.cont");
12997 T->eraseFromParent();
13012 bool ReachesLatch =
false;
13015 while (!Worklist.
empty()) {
13020 "iterator bodygen must leave at most one unterminated block",
13026 if (Succ == Latch) {
13027 ReachesLatch =
true;
13032 "iterator bodygen must not branch out of the loop body",
13034 if (Visited.
insert(Succ).second)
13040 Builder.SetInsertPoint(OpenBB);
13042 }
else if (!ReachesLatch) {
13052 return ContBB->
begin();
13062 for (
const auto &
ParamAttr : ParamAttrs) {
13105 return std::string(Out.str());
13113 unsigned VecRegSize;
13115 ISADataTy ISAData[] = {
13134 for (
char Mask :
Masked) {
13135 for (
const ISADataTy &
Data : ISAData) {
13138 Out <<
"_ZGV" <<
Data.ISA << Mask;
13140 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
13154template <
typename T>
13157 StringRef MangledName,
bool OutputBecomesInput,
13161 Out << Prefix << ISA << LMask << VLEN;
13162 if (OutputBecomesInput)
13164 Out << ParSeq <<
'_' << MangledName;
13173 bool OutputBecomesInput,
13178 OutputBecomesInput, Fn);
13180 OutputBecomesInput, Fn);
13184 OutputBecomesInput, Fn);
13186 OutputBecomesInput, Fn);
13190 OutputBecomesInput, Fn);
13192 OutputBecomesInput, Fn);
13197 OutputBecomesInput, Fn);
13208 char ISA,
unsigned NarrowestDataSize,
bool OutputBecomesInput) {
13209 assert((ISA ==
'n' || ISA ==
's') &&
"Expected ISA either 's' or 'n'.");
13221 OutputBecomesInput, Fn);
13228 OutputBecomesInput, Fn);
13230 OutputBecomesInput, Fn);
13234 OutputBecomesInput, Fn);
13238 OutputBecomesInput, Fn);
13247 OutputBecomesInput, Fn);
13254 MangledName, OutputBecomesInput, Fn);
13256 MangledName, OutputBecomesInput, Fn);
13260 MangledName, OutputBecomesInput, Fn);
13264 MangledName, OutputBecomesInput, Fn);
13274 return OffloadEntriesTargetRegion.empty() &&
13275 OffloadEntriesDeviceGlobalVar.empty();
13278unsigned OffloadEntriesInfoManager::getTargetRegionEntryInfoCount(
13280 auto It = OffloadEntriesTargetRegionCount.find(
13281 getTargetRegionEntryCountKey(EntryInfo));
13282 if (It == OffloadEntriesTargetRegionCount.end())
13287void OffloadEntriesInfoManager::incrementTargetRegionEntryInfoCount(
13289 OffloadEntriesTargetRegionCount[getTargetRegionEntryCountKey(EntryInfo)] =
13290 EntryInfo.
Count + 1;
13296 OffloadEntriesTargetRegion[EntryInfo] =
13299 ++OffloadingEntriesNum;
13305 assert(EntryInfo.
Count == 0 &&
"expected default EntryInfo");
13308 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
13312 if (OMPBuilder->Config.isTargetDevice()) {
13317 auto &Entry = OffloadEntriesTargetRegion[EntryInfo];
13318 Entry.setAddress(Addr);
13320 Entry.setFlags(Flags);
13326 "Target region entry already registered!");
13328 OffloadEntriesTargetRegion[EntryInfo] = Entry;
13329 ++OffloadingEntriesNum;
13331 incrementTargetRegionEntryInfoCount(EntryInfo);
13338 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
13340 auto It = OffloadEntriesTargetRegion.find(EntryInfo);
13341 if (It == OffloadEntriesTargetRegion.end()) {
13345 if (!IgnoreAddressId && (It->second.getAddress() || It->second.getID()))
13353 for (
const auto &It : OffloadEntriesTargetRegion) {
13354 Action(It.first, It.second);
13360 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
13361 ++OffloadingEntriesNum;
13367 if (OMPBuilder->Config.isTargetDevice()) {
13371 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
13373 if (Entry.getVarSize() == 0) {
13374 Entry.setVarSize(VarSize);
13375 Entry.setLinkage(Linkage);
13379 Entry.setVarSize(VarSize);
13380 Entry.setLinkage(Linkage);
13381 Entry.setAddress(Addr);
13384 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
13385 assert(Entry.isValid() && Entry.getFlags() == Flags &&
13386 "Entry not initialized!");
13387 if (Entry.getVarSize() == 0) {
13388 Entry.setVarSize(VarSize);
13389 Entry.setLinkage(Linkage);
13396 OffloadEntriesDeviceGlobalVar.try_emplace(VarName, OffloadingEntriesNum,
13397 Addr, VarSize, Flags, Linkage,
13400 OffloadEntriesDeviceGlobalVar.try_emplace(
13401 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage,
"");
13402 ++OffloadingEntriesNum;
13409 for (
const auto &E : OffloadEntriesDeviceGlobalVar)
13410 Action(E.getKey(), E.getValue());
13417void CanonicalLoopInfo::reportUnsupportedVirtualCollapse()
const {
13419 assert(VirtualCollapse &&
"Requires Virtual collapse state");
13421 "virtual collapse must be the final structural loop transformation");
13424void CanonicalLoopInfo::collectControlBlocks(
13426 if (VirtualCollapse)
13427 reportUnsupportedVirtualCollapse();
13433 BBs.
append({getPreheader(), Header,
Cond, Latch, Exit, getAfter()});
13436BasicBlock *CanonicalLoopInfo::getVirtualCollapseInit()
const {
13437 return VirtualCollapse ? VirtualCollapse->Count->getParent() :
nullptr;
13442 if (VirtualCollapse)
13443 return getVirtualCollapseInit()->getSinglePredecessor();
13452void CanonicalLoopInfo::setTripCount(
Value *TripCount) {
13464void CanonicalLoopInfo::mapIndVar(
13474 for (
Use &U : OldIV->
uses()) {
13478 if (
User->getParent() == getCond())
13480 if (
User->getParent() == getLatch())
13486 Value *NewIV = Updater(OldIV);
13489 for (Use *U : ReplacableUses)
13503 bool IsVirtual = VirtualCollapse.has_value();
13509 IndVarEntry = Guard->getSuccessor(0);
13512 assert(Guard->getSuccessor(1) == Exit);
13513 assert(VirtualCollapse->Begin->getParent() ==
Init);
13515 {VirtualCollapse->Begin, VirtualCollapse->Count}) {
13517 assert(Copy->getOpcode() == Instruction::Add &&
Zero &&
Zero->isZero() &&
13518 "Virtual range copies must add zero");
13522 NonEmpty->getOperand(0) == VirtualCollapse->Count &&
13524 "Collapsed guard must skip empty ranges with zero count");
13536 "Preheader must terminate with unconditional branch");
13539 "Preheader must jump to collapsed initialization");
13542 "Preheader must jump to header");
13546 "Header must terminate with unconditional branch");
13547 assert(Header->getSingleSuccessor() == Cond &&
13548 "Header must jump to exiting block");
13551 assert(Cond->getSinglePredecessor() == Header &&
13552 "Exiting block only reachable from header");
13555 "Exiting block must terminate with conditional branch");
13557 "Exiting block's first successor jump to the body");
13559 "Exiting block's second successor must exit the loop");
13563 "Body only reachable from exiting block");
13568 "Latch must terminate with unconditional branch");
13569 assert(Latch->getSingleSuccessor() == Header &&
"Latch must jump to header");
13572 assert(Latch->getSinglePredecessor() !=
nullptr);
13577 "Exit block must terminate with unconditional branch");
13578 assert(Exit->getSingleSuccessor() == After &&
13579 "Exit block must jump to after block");
13583 "After block only reachable from exit block");
13587 assert(IndVar &&
"Canonical induction variable not found?");
13589 "Induction variable must be an integer");
13591 "Induction variable must be a PHI in the loop header");
13598 auto *NextIndVar =
cast<PHINode>(IndVar)->getIncomingValue(1);
13607 assert(TripCount &&
"Loop trip count not found?");
13609 "Trip count and induction variable must have the same type");
13613 "Exit condition must be a signed less-than comparison");
13615 "Exit condition must compare the induction variable");
13617 "Exit condition must compare with the trip count");
13626 VirtualCollapse.reset();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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")))
Expand Atomic instructions
This file contains the simple types necessary to represent the attributes associated with functions a...
static const Function * getParent(const Value *V)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
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
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
uint64_t IntrinsicInst * II
#define OMP_KERNEL_ARG_VERSION
Provides definitions for Target specific Grid Values.
static Value * removeASCastIfPresent(Value *V)
static void createTargetLoopWorkshareCall(OpenMPIRBuilder *OMPBuilder, WorksharingLoopType LoopType, BasicBlock *InsertBlock, Value *Ident, Value *LoopBodyArg, Value *TripCount, Function &LoopBodyFn, bool NoLoop)
Value * createFakeIntVal(IRBuilderBase &Builder, OpenMPIRBuilder::InsertPointTy OuterAllocaIP, llvm::SmallVectorImpl< Instruction * > &ToBeDeleted, OpenMPIRBuilder::InsertPointTy InnerAllocaIP, const Twine &Name="", bool AsPtr=true, bool Is64Bit=false)
static Function * createTargetParallelWrapper(OpenMPIRBuilder *OMPIRBuilder, Function &OutlinedFn)
Create wrapper function used to gather the outlined function's argument structure from a shared buffe...
static void redirectTo(BasicBlock *Source, BasicBlock *Target, DebugLoc DL)
Make Source branch to Target.
static FunctionCallee getKmpcDistForStaticInitForType(Type *Ty, Module &M, OpenMPIRBuilder &OMPBuilder)
static void applyParallelAccessesMetadata(CanonicalLoopInfo *CLI, LLVMContext &Ctx, Loop *Loop, LoopInfo &LoopInfo, SmallVector< Metadata * > &LoopMDList)
static Expected< Function * > createOutlinedFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, const OpenMPIRBuilder::TargetKernelDefaultAttrs &DefaultAttrs, StringRef FuncName, SmallVectorImpl< Value * > &Inputs, OpenMPIRBuilder::TargetBodyGenCallbackTy &CBFunc, OpenMPIRBuilder::TargetGenArgAccessorsCallbackTy &ArgAccessorFuncCB, DebugLoc OutlinedFnLoc)
static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, char ISA, StringRef ParSeq, StringRef MangledName, bool OutputBecomesInput, llvm::Function *Fn)
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 void FixupDebugInfoForOutlinedFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, Function *Func, DenseMap< Value *, std::tuple< Value *, unsigned > > &ValueReplacementMap)
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 std::string mangleVectorParameters(ArrayRef< llvm::OpenMPIRBuilder::DeclareSimdAttrTy > ParamAttrs)
Mangle the parameter part of the vector function name according to their OpenMP classification.
static bool isGenericKernel(Function &Fn)
static void workshareLoopTargetCallback(OpenMPIRBuilder *OMPIRBuilder, CanonicalLoopInfo *CLI, Value *Ident, Function &OutlinedFn, const SmallVector< Instruction *, 4 > &ToBeDeleted, WorksharingLoopType LoopType, bool NoLoop)
static bool isValidWorkshareLoopScheduleType(OMPScheduleType SchedType)
static bool isAtomicableReductionSet(ArrayRef< OpenMPIRBuilder::ReductionInfo > ReductionInfos)
static llvm::CallInst * emitNoUnwindRuntimeCall(IRBuilder<> &Builder, llvm::FunctionCallee Callee, ArrayRef< llvm::Value * > Args, const llvm::Twine &Name)
static Error populateReductionFunction(Function *ReductionFunc, ArrayRef< OpenMPIRBuilder::ReductionInfo > ReductionInfos, IRBuilder<> &Builder, ArrayRef< bool > IsByRef, bool IsGPU)
static Function * getFreshReductionFunc(Module &M)
static void raiseUserConstantDataAllocasToEntryBlock(IRBuilderBase &Builder, Function *Function)
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 Type * getOffloadingArrayType(Value *V)
static OMPScheduleType getOpenMPBaseScheduleType(llvm::omp::ScheduleKind ClauseKind, bool HasChunks, bool HasSimdModifier, bool HasDistScheduleChunks)
Determine which scheduling algorithm to use, determined from schedule clause arguments.
static OMPScheduleType computeOpenMPScheduleType(ScheduleKind ClauseKind, bool HasChunks, bool HasSimdModifier, bool HasMonotonicModifier, bool HasNonmonotonicModifier, bool HasOrderedClause, bool HasDistScheduleChunks)
Determine the schedule type using schedule and ordering clause arguments.
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 std::optional< omp::OMPTgtExecModeFlags > getTargetKernelExecMode(Function &Kernel)
Given a function, if it represents the entry point of a target kernel, this returns the execution mod...
static StructType * createTaskWithPrivatesTy(OpenMPIRBuilder &OMPIRBuilder, ArrayRef< Value * > OffloadingArraysToPrivatize)
static cl::opt< bool > UseDefaultMaxThreads("openmp-ir-builder-use-default-max-threads", cl::Hidden, cl::desc("Use a default max threads if none is provided."), cl::init(true))
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, DebugLoc OutlinedFnLoc)
static Value * emitTaskDependencies(OpenMPIRBuilder &OMPBuilder, const SmallVectorImpl< OpenMPIRBuilder::DependData > &Dependencies)
static void updateNVPTXAttr(Function &Kernel, StringRef Name, int32_t Value, bool Min)
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 void hoistNonEntryAllocasToEntryBlock(llvm::BasicBlock &Block)
static FunctionCallee getKmpcForStaticInitForType(Type *Ty, Module &M, OpenMPIRBuilder &OMPBuilder)
static void addAccessGroupMetadata(BasicBlock *Block, MDNode *AccessGroup, LoopInfo &LI)
Attach llvm.access.group metadata to the memref instructions of Block.
static void addBasicBlockMetadata(BasicBlock *BB, ArrayRef< Metadata * > Properties)
Attach metadata Properties to the basic block described by BB.
static void restoreIPandDebugLoc(llvm::IRBuilderBase &Builder, llvm::IRBuilderBase::InsertPoint IP)
This is a wrapper over IRBuilderBase::restoreIP that also restores a current debug location when the ...
static LoadInst * loadSharedDataFromTaskDescriptor(OpenMPIRBuilder &OMPIRBuilder, IRBuilderBase &Builder, Value *TaskWithPrivates, Type *TaskWithPrivatesTy)
Given a task descriptor, TaskWithPrivates, return the pointer to the block of pointers containing sha...
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 bool hasGridValue(const Triple &T)
static FunctionCallee getKmpcForStaticLoopForType(Type *Ty, OpenMPIRBuilder *OMPBuilder, WorksharingLoopType LoopType)
static const omp::GV & getGridValue(const Triple &T, Function *Kernel)
static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, StringRef Prefix, char ISA, StringRef ParSeq, StringRef MangledName, bool OutputBecomesInput, llvm::Function *Fn)
static Error emitTargetCall(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, Value *RTLocOverride, OpenMPIRBuilder::InsertPointTy AllocaIP, ArrayRef< BasicBlock * > DeallocBlocks, OpenMPIRBuilder::TargetDataInfo &Info, const OpenMPIRBuilder::TargetKernelDefaultAttrs &DefaultAttrs, const OpenMPIRBuilder::TargetKernelRuntimeAttrs &RuntimeAttrs, Value *IfCond, Function *OutlinedFn, Constant *OutlinedFnID, SmallVectorImpl< Value * > &Args, OpenMPIRBuilder::GenMapInfoCallbackTy GenMapInfoCB, OpenMPIRBuilder::CustomMapperCallbackTy CustomMapperCB, const OpenMPIRBuilder::DependenciesInfo &Dependencies, bool HasNoWait, Value *DynCGroupMem, OMPDynGroupprivateFallbackType DynCGroupMemFallback)
static Function * emitTargetTaskProxyFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, CallInst *StaleCI, StructType *PrivatesTy, StructType *TaskWithPrivatesTy, const size_t NumOffloadingArrays, const int SharedArgsOperandNo)
Create an entry point for a target task with the following.
static void addLoopMetadata(CanonicalLoopInfo *Loop, ArrayRef< Metadata * > Properties)
Attach loop metadata Properties to the loop described by Loop.
static AtomicOrdering TransformReleaseAcquireRelease(AtomicOrdering AO)
static void removeUnusedBlocksFromParent(ArrayRef< BasicBlock * > BBs)
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 ...
SmallVector< MachineOperand, 4 > 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_>.
SmallPtrSet< BasicBlock *, 0 > BlockSet
This file implements the SmallBitVector class.
This file defines the SmallSet class.
static SymbolRef::Type getType(const Symbol *Sym)
Defines the virtual file system interface vfs::FileSystem.
static const uint32_t IV[8]
Class for arbitrary precision integers.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
An arbitrary precision integer that knows its signedness.
static APSInt getUnsigned(uint64_t X)
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.
LLVM_ABI std::optional< TypeSize > getAllocationSize(const DataLayout &DL) const
Get allocation size in bytes.
LLVM_ABI bool isArrayAllocation() const
Return true if there is an allocation size parameter to the allocation instruction that is not 1.
void setAlignment(Align Align)
const Value * getArraySize() const
Get the number of elements allocated.
bool registerPass(PassBuilderT &&PassBuilder)
Register an analysis pass with the manager.
This class represents an incoming formal argument to a Function.
unsigned getArgNo() const
Return the index of this formal argument in its containing function.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & back() const
Get the last element.
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
Class to represent array types.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
An instruction that atomically checks whether a specified value is in a memory location,...
void setWeak(bool IsWeak)
static AtomicOrdering getStrongestFailureOrdering(AtomicOrdering SuccessOrdering)
Returns the strongest permitted ordering on failure, given the desired ordering on success.
LLVM_ABI std::pair< LoadInst *, AllocaInst * > EmitAtomicLoadLibcall(AtomicOrdering AO)
LLVM_ABI void EmitAtomicStoreLibcall(AtomicOrdering AO, Value *Source)
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.
@ FMinimum
*p = minimum(old, v) minimum matches the behavior of llvm.minimum.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ FMaximum
*p = maximum(old, v) maximum matches the behavior of llvm.maximum.
@ 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
@ FMaximumNum
*p = maximumnum(old, v) maximumnum matches the behavior of llvm.maximumnum.
@ FMax
*p = maxnum(old, v) maxnum matches the behavior of llvm.maxnum.
@ UDecWrap
Decrement one until a minimum value or zero.
@ FMinimumNum
*p = minimumnum(old, v) minimumnum matches the behavior of llvm.minimumnum.
This class holds the attributes for a particular argument, parameter, function, or return value.
LLVM_ABI AttributeSet addAttributes(LLVMContext &C, AttributeSet AS) const
Add attributes to the attribute set.
LLVM_ABI AttributeSet addAttribute(LLVMContext &C, Attribute::AttrKind Kind) const
Add an argument attribute.
static LLVM_ABI Attribute getWithAlignment(LLVMContext &Context, Align Alignment)
Return a uniquified Attribute object that has the specific alignment set.
LLVM Basic Block Representation.
LLVM_ABI 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.
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
reverse_iterator rbegin()
bool hasTerminator() const LLVM_READONLY
Returns whether the block has a terminator.
const Instruction & back() const
LLVM_ABI BasicBlock * splitBasicBlockBefore(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction and insert the new basic blo...
LLVM_ABI InstListType::const_iterator getFirstNonPHIIt() const
Returns an iterator to the first instruction in this block that is not a PHINode instruction.
LLVM_ABI void insertDbgRecordBefore(DbgRecord *DR, InstListType::iterator Here)
Insert a DbgRecord into a block at the position given by Here.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
LLVM_ABI const BasicBlock * getUniqueSuccessor() const
Return the successor of this block if it has a unique successor.
LLVM_ABI const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
const Instruction & front() const
InstListType::reverse_iterator reverse_iterator
LLVM_ABI const BasicBlock * getUniquePredecessor() const
Return the predecessor of this block if it has a unique predecessor block.
const Instruction * getTerminatorOrNull() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
LLVM_ABI const BasicBlock * getSingleSuccessor() const
Return the successor of this block if it has a single successor.
LLVM_ABI InstListType::const_iterator getFirstNonPHIOrPseudoProbe() const
Returns an iterator to the first instruction in this block that is not a PHINode or a pseudo operatio...
LLVM_ABI void insertInto(Function *Parent, BasicBlock *InsertBefore=nullptr)
Insert unlinked basic block into a function.
LLVM_ABI SymbolTableList< BasicBlock >::iterator eraseFromParent()
Unlink 'this' from the containing function and delete it.
InstListType::iterator iterator
Instruction iterators...
LLVM_ABI 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; assumes that the block is well-formed.
void splice(BasicBlock::iterator ToIt, BasicBlock *FromBB)
Transfer all instructions from FromBB to this basic block at ToIt.
LLVM_ABI void removePredecessor(BasicBlock *Pred, bool KeepOneInputPHIs=false)
Update PHI nodes in this BasicBlock before removal of predecessor Pred.
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.
LLVM_ABI 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.
void setLastIter(Value *IterVar)
Sets the last iteration variable for this 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
LLVM_ABI 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.
LLVM_ABI 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.
This class is the base class for the comparison instructions.
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 LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
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 LLVM_ABI Constant * getString(LLVMContext &Context, StringRef Initializer, bool AddNull=true, bool ByteString=false)
This method constructs a CDS and initializes it with a text string.
static LLVM_ABI Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
static LLVM_ABI Constant * getPointerBitCastOrAddrSpaceCast(Constant *C, Type *Ty)
Create a BitCast or AddrSpaceCast for a pointer type depending on the address space.
static LLVM_ABI Constant * getAddrSpaceCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static LLVM_ABI ConstantFP * getZero(Type *Ty, bool Negative=false)
This is the shared class of boolean and integer constants.
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static LLVM_ABI Constant * get(StructType *T, ArrayRef< Constant * > V)
This is an important base class in LLVM.
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
DILocalScope * getScope() const
Get the local scope for this variable.
DINodeArray getAnnotations() const
Subprogram description. Uses SubclassData1.
uint32_t getAlignInBits() const
StringRef getName() const
A parsed version of the target data layout string in and methods for querying it.
TypeSize getTypeStoreSize(Type *Ty) const
Returns the maximum number of bytes that may be overwritten by storing the specified type.
Record of a variable value-assignment, aka a non instruction representation of the dbg....
Analysis pass which computes a DominatorTree.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
Represents either an error or a value T.
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.
reference get()
Returns a reference to the stored T value.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
Class to represent function types.
Type * getParamType(unsigned i) const
Parameter type accessors.
static LLVM_ABI 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.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
DISubprogram * getSubprogram() const
Get the attached subprogram.
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 GlobalObject has any metadata attached to it.
LLVM_ABI 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
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
Common base class shared among various IRBuilders.
InsertPoint saveIP() const
Returns the current insert point.
BasicBlock::iterator InsertPoint
InsertPoint - A saved insertion point.
void restoreIP(InsertPoint IP)
Sets the current insert point to a previously-saved location.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI void removeFromParent()
This method unlinks 'this' from the containing basic block, but does not delete it.
LLVM_ABI 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.
LLVM_ABI void moveBefore(InstListType::iterator InsertPos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
LLVM_ABI 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.
LLVM_ABI BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY
Return the specified successor. This instruction must be a terminator.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
user_iterator user_begin()
LLVM_ABI void moveBeforePreserving(InstListType::iterator MovePos)
Perform a moveBefore operation, while signalling that the caller intends to preserve the original ord...
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI void insertAfter(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately after the specified instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
static LLVM_ABI 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.
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.
LLVM_ABI LoopInfo run(Function &F, FunctionAnalysisManager &AM)
ArrayRef< BlockT * > getBlocks() const
Get a list of the basic blocks which make up this loop.
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.
LLVM_ABI MDNode * createCallbackEncoding(unsigned CalleeArgNo, ArrayRef< int > Arguments, bool VarArgsArePassed)
Return metadata describing a callback (see llvm::AbstractCallSite).
LLVM_ABI void replaceOperandWith(unsigned I, Metadata *New)
Replace a specific operand.
static MDTuple * getDistinct(LLVMContext &Context, ArrayRef< Metadata * > MDs)
ArrayRef< MDOperand > operands() const
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
This class implements a map that also provides access to all stored values in a deterministic order.
A Module instance is used to store all the information related to an LLVM module.
LLVMContext & getContext() const
Get the global data context.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
iterator_range< op_iterator > operands()
LLVM_ABI void addOperand(MDNode *M)
Device global variable entries info.
Target region entries info.
Base class of the entries info.
Class that manages information about offload code regions and data.
function_ref< void(StringRef, const OffloadEntryInfoDeviceGlobalVar &)> OffloadDeviceGlobalVarEntryInfoActTy
Applies action Action on all registered entries.
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.
LLVM_ABI void registerDeviceGlobalVarEntryInfo(StringRef VarName, Constant *Addr, int64_t VarSize, OMPTargetGlobalVarEntryKind Flags, GlobalValue::LinkageTypes Linkage)
Register device global variable entry.
LLVM_ABI void initializeDeviceGlobalVarEntryInfo(StringRef Name, OMPTargetGlobalVarEntryKind Flags, unsigned Order)
Initialize device global variable entry.
LLVM_ABI void actOnDeviceGlobalVarEntriesInfo(const OffloadDeviceGlobalVarEntryInfoActTy &Action)
OMPTargetRegionEntryKind
Kind of the target registry entry.
@ OMPTargetRegionEntryTargetRegion
Mark the entry as target region.
LLVM_ABI void getTargetRegionEntryFnName(SmallVectorImpl< char > &Name, const TargetRegionEntryInfo &EntryInfo)
LLVM_ABI bool hasTargetRegionEntryInfo(TargetRegionEntryInfo EntryInfo, bool IgnoreAddressId=false) const
Return true if a target region entry with the provided information exists.
LLVM_ABI void registerTargetRegionEntryInfo(TargetRegionEntryInfo EntryInfo, Constant *Addr, Constant *ID, OMPTargetRegionEntryKind Flags)
Register target region entry.
LLVM_ABI void actOnTargetRegionEntriesInfo(const OffloadTargetRegionEntryInfoActTy &Action)
LLVM_ABI 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.
@ OMPTargetGlobalVarEntryIndirectVTable
Mark the entry as a declare target indirect vtable.
function_ref< void(const TargetRegionEntryInfo &EntryInfo, const OffloadEntryInfoTargetRegion &)> OffloadTargetRegionEntryInfoActTy
brief Applies action Action on all registered entries.
bool hasDeviceGlobalVarEntryInfo(StringRef VarName) const
Checks if the variable with the given name has been registered already.
LLVM_ABI 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 (...
std::optional< bool > IsGPU
Flag for specifying if the compilation is done for an accelerator.
LLVM_ABI int64_t getRequiresFlags() const
Returns requires directive clauses as flags compatible with those expected by libomptarget.
std::optional< bool > OpenMPOffloadMandatory
Flag for specifying if offloading is mandatory.
LLVM_ABI void setHasRequiresReverseOffload(bool Value)
LLVM_ABI OpenMPIRBuilderConfig()
LLVM_ABI bool hasRequiresUnifiedSharedMemory() const
LLVM_ABI void setHasRequiresUnifiedSharedMemory(bool Value)
unsigned getDefaultTargetAS() const
LLVM_ABI bool hasRequiresDynamicAllocators() const
LLVM_ABI void setHasRequiresUnifiedAddress(bool Value)
bool isTargetDevice() const
LLVM_ABI void setHasRequiresDynamicAllocators(bool Value)
LLVM_ABI bool hasRequiresReverseOffload() const
bool hasRequiresFlags() const
LLVM_ABI 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.
LLVM_ABI InsertPointOrErrorTy createOrderedThreadsSimd(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, bool IsThreads)
Generator for 'omp ordered [threads | simd]'.
LLVM_ABI void emitAArch64DeclareSimdFunction(llvm::Function *Fn, unsigned VLENVal, llvm::ArrayRef< DeclareSimdAttrTy > ParamAttrs, DeclareSimdBranch Branch, char ISA, unsigned NarrowestDataSize, bool OutputBecomesInput)
Emit AArch64 vector-function ABI attributes for a declare simd function.
LLVM_ABI 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.
LLVM_ABI void registerDeclareTargetGlobalReplacement(GlobalValue *Original, GlobalValue *Replacement)
Register a module-scope replacement of a declare target global variable.
LLVM_ABI FunctionCallee getOrCreateRuntimeFunction(Module &M, omp::RuntimeFunction FnID)
Return the function declaration for the runtime function with FnID.
LLVM_ABI InsertPointOrErrorTy createCancel(const LocationDescription &Loc, Value *IfCondition, omp::Directive CanceledDirective)
Generator for 'omp cancel'.
std::function< Expected< Function * >(StringRef FunctionName)> FunctionGenCallback
Functions used to generate a function with the given name.
LLVM_ABI CallInst * createOMPAllocShared(const LocationDescription &Loc, Value *Size, const Twine &Name=Twine(""))
Create a runtime call for kmpc_alloc_shared.
ReductionGenCBKind
Enum class for the RedctionGen CallBack type to be used.
LLVM_ABI CanonicalLoopInfo * collapseLoops(DebugLoc DL, ArrayRef< CanonicalLoopInfo * > Loops, InsertPointTy ComputeIP)
Collapse a loop nest using Config.CollapseMapping.
LLVM_ABI void createTaskyield(const LocationDescription &Loc)
Generator for 'omp taskyield'.
std::function< Error(InsertPointTy CodeGenIP)> FinalizeCallbackTy
Callback type for variable finalization (think destructors).
LLVM_ABI void emitBranch(BasicBlock *Target)
LLVM_ABI Error emitCancelationCheckImpl(Value *CancelFlag, omp::Directive CanceledDirective)
Generate control flow and cleanup for cancellation.
static LLVM_ABI void writeThreadBoundsForKernel(const Triple &T, Function &Kernel, int32_t LB, int32_t UB)
LLVM_ABI void emitTaskwaitImpl(const LocationDescription &Loc)
Generate a taskwait runtime call.
LLVM_ABI 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.
LLVM_ABI GlobalVariable * emitKernelExecutionMode(StringRef KernelName, omp::OMPTgtExecModeFlags Mode)
Emit the kernel execution mode.
LLVM_ABI void initialize()
Initialize the internal state, this will put structures types and potentially other helpers into the ...
LLVM_ABI 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, bool IsWeak=false)
LLVM_ABI InsertPointTy createAtomicWrite(const LocationDescription &Loc, AtomicOpValue &X, Value *Expr, AtomicOrdering AO, InsertPointTy AllocaIP)
Emit atomic write for : X = Expr — Only Scalar data types.
LLVM_ABI void loadOffloadInfoMetadata(Module &M)
Loads all the offload entries information from the host IR metadata.
function_ref< MapInfosTy &(InsertPointTy CodeGenIP)> GenMapInfoCallbackTy
Callback type for creating the map infos for the kernel parameters.
LLVM_ABI Error emitOffloadingArrays(InsertPointTy AllocaIP, InsertPointTy CodeGenIP, MapInfosTy &CombinedInfo, TargetDataInfo &Info, CustomMapperCallbackTy CustomMapperCB, bool IsNonContiguous=false, function_ref< void(unsigned int, Value *)> DeviceAddrCB=nullptr)
Emit the arrays used to pass the captures and map information to the offloading runtime library.
LLVM_ABI void unrollLoopFull(DebugLoc DL, CanonicalLoopInfo *Loop)
Fully unroll a loop.
function_ref< Error(InsertPointTy CodeGenIP, Value *IndVar)> LoopBodyGenCallbackTy
Callback type for loop body code generation.
LLVM_ABI InsertPointOrErrorTy emitScanReduction(const LocationDescription &Loc, ArrayRef< llvm::OpenMPIRBuilder::ReductionInfo > ReductionInfos, ScanInfo *ScanRedInfo)
This function performs the scan reduction of the values updated in the input phase.
LLVM_ABI void emitFlush(const LocationDescription &Loc)
Generate a flush runtime call.
LLVM_ABI InsertPointOrErrorTy createScope(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, bool IsNowait)
Generator for 'omp scope'.
static LLVM_ABI std::pair< int32_t, int32_t > readThreadBoundsForKernel(const Triple &T, Function &Kernel)
}
OpenMPIRBuilderConfig Config
The OpenMPIRBuilder Configuration.
LLVM_ABI CallInst * createOMPInteropDestroy(const LocationDescription &Loc, Value *InteropVar, Value *Device, Value *NumDependences, Value *DependenceAddress, bool HaveNowaitClause)
Create a runtime call for __tgt_interop_destroy.
LLVM_ABI void emitUsed(StringRef Name, ArrayRef< llvm::WeakTrackingVH > List)
Emit the llvm.used metadata.
LLVM_ABI InsertPointOrErrorTy createSingle(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, bool IsNowait, ArrayRef< llvm::Value * > CPVars={}, ArrayRef< llvm::Function * > CPFuncs={})
Generator for 'omp single'.
LLVM_ABI InsertPointOrErrorTy createTarget(const LocationDescription &Loc, bool IsOffloadEntry, OpenMPIRBuilder::InsertPointTy AllocaIP, OpenMPIRBuilder::InsertPointTy CodeGenIP, ArrayRef< BasicBlock * > DeallocBlocks, TargetDataInfo &Info, TargetRegionEntryInfo &EntryInfo, const TargetKernelDefaultAttrs &DefaultAttrs, const TargetKernelRuntimeAttrs &RuntimeAttrs, Value *IfCond, SmallVectorImpl< Value * > &Inputs, GenMapInfoCallbackTy GenMapInfoCB, TargetBodyGenCallbackTy BodyGenCB, TargetGenArgAccessorsCallbackTy ArgAccessorFuncCB, CustomMapperCallbackTy CustomMapperCB, const DependenciesInfo &Dependencies={}, bool HasNowait=false, Value *DynCGroupMem=nullptr, omp::OMPDynGroupprivateFallbackType DynCGroupMemFallback=omp::OMPDynGroupprivateFallbackType::Abort, DebugLoc OutlinedFnLoc={}, Value *RTLocOverride=nullptr)
Generator for 'omp target'.
LLVM_ABI 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.
LLVM_ABI llvm::StructType * getKmpTaskAffinityInfoTy()
Return the LLVM struct type matching runtime kmp_task_affinity_info_t.
LLVM_ABI Constant * emitKernelEnvironment(const LocationDescription &Loc, const llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs)
The omp target interface.
LLVM_ABI std::string createPlatformSpecificName(ArrayRef< StringRef > Parts) const
Get the create a name using the platform specific separators.
LLVM_ABI FunctionCallee createDispatchNextFunction(unsigned IVSize, bool IVSigned)
Returns __kmpc_dispatch_next_* runtime function for the specified size IVSize and sign IVSigned.
static LLVM_ABI void getKernelArgsVector(TargetKernelArgs &KernelArgs, IRBuilderBase &Builder, SmallVector< Value * > &ArgsVector)
Create the kernel args vector used by emitTargetKernel.
LLVM_ABI void unrollLoopHeuristic(DebugLoc DL, CanonicalLoopInfo *Loop)
Fully or partially unroll a loop.
LLVM_ABI omp::OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position)
Get OMP_MAP_MEMBER_OF flag with extra bits reserved based on the position given.
LLVM_ABI void addAttributes(omp::RuntimeFunction FnID, Function &Fn)
Add attributes known for FnID to Fn.
LLVM_ABI Expected< Function * > emitUserDefinedMapper(function_ref< MapInfosOrErrorTy(InsertPointTy CodeGenIP, llvm::Value *PtrPHI, llvm::Value *BeginArg)> PrivAndGenMapInfoCB, llvm::Type *ElemTy, StringRef FuncName, CustomMapperCallbackTy CustomMapperCB, bool PreserveMemberOfFlags=false, bool PropagatePresentToPointeeStorage=false, bool PropagatePresentToNonPointeeStorage=false)
Emit the user-defined mapper function.
Module & M
The underlying LLVM-IR module.
StringMap< Constant * > SrcLocStrMap
Map to remember source location strings.
LLVM_ABI void createMapperAllocas(const LocationDescription &Loc, InsertPointTy AllocaIP, unsigned NumOperands, struct MapperAllocas &MapperAllocas)
Create the allocas instruction used in call to mapper functions.
SmallVector< DeclareTargetGlobalReplacement, 8 > DeclareTargetGlobalReplacements
Collection of declare target globals to rewrite uses of during device module finalizaiton.
LLVM_ABI Constant * getOrCreateSrcLocStr(StringRef LocStr, uint32_t &SrcLocStrSize)
Return the (LLVM-IR) string describing the source location LocStr.
LLVM_ABI 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...
LLVM_ABI InsertPointOrErrorTy createIteratorLoop(LocationDescription Loc, llvm::Value *TripCount, IteratorBodyGenTy BodyGen, llvm::StringRef Name="iterator")
Create a canonical iterator loop at the current insertion point.
LLVM_ABI Expected< SmallVector< llvm::CanonicalLoopInfo * > > createCanonicalScanLoops(const LocationDescription &Loc, LoopBodyGenCallbackTy BodyGenCB, Value *Start, Value *Stop, Value *Step, bool IsSigned, bool InclusiveStop, InsertPointTy ComputeIP, const Twine &Name, ScanInfo *ScanRedInfo)
Generator for the control flow structure of an OpenMP canonical loops if the parent directive has an ...
LLVM_ABI FunctionCallee createDispatchFiniFunction(unsigned IVSize, bool IVSigned)
Returns __kmpc_dispatch_fini_* runtime function for the specified size IVSize and sign IVSigned.
function_ref< InsertPointOrErrorTy( InsertPointTy AllocaIP, InsertPointTy CodeGenIP, ArrayRef< BasicBlock * > DeallocBlocks)> TargetBodyGenCallbackTy
LLVM_ABI void unrollLoopPartial(DebugLoc DL, CanonicalLoopInfo *Loop, int32_t Factor, CanonicalLoopInfo **UnrolledCLI)
Partially unroll a loop.
function_ref< Error(Value *DeviceID, Value *RTLoc, IRBuilderBase::InsertPoint TargetTaskAllocaIP)> TargetTaskBodyCallbackTy
Callback type for generating the bodies of device directives that require outer target tasks (e....
Expected< MapInfosTy & > MapInfosOrErrorTy
bool HandleFPNegZero
Emit atomic compare for constructs: — Only scalar data types cond-expr-stmt: x = x ordop expr ?
LLVM_ABI void emitTaskyieldImpl(const LocationDescription &Loc)
Generate a taskyield runtime call.
LLVM_ABI 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.
LLVM_ABI InsertPointOrErrorTy createDistribute(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< BasicBlock * > DeallocBlocks, BodyGenCallbackTy BodyGenCB)
Generator for #omp distribute
function_ref< Expected< Function * >(unsigned int)> CustomMapperCallbackTy
LLVM_ABI 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)'.
LLVM_ABI 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' ...
function_ref< InsertPointOrErrorTy( InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Value &Original, Value &Inner, Value *&ReplVal)> PrivatizeCallbackTy
Callback type for variable privatization (think copy & default constructor).
LLVM_ABI bool isFinalized()
Check whether the finalize function has already run.
SmallVector< FinalizationInfo, 8 > FinalizationStack
The finalization stack made up of finalize callbacks currently in-flight, wrapped into FinalizationIn...
LLVM_ABI std::vector< CanonicalLoopInfo * > tileLoops(DebugLoc DL, ArrayRef< CanonicalLoopInfo * > Loops, ArrayRef< Value * > TileSizes)
Tile a loop nest.
LLVM_ABI 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.
LLVM_ABI Error emitIfClause(Value *Cond, BodyGenCallbackTy ThenGen, BodyGenCallbackTy ElseGen, InsertPointTy AllocaIP={}, ArrayRef< BasicBlock * > DeallocBlocks={})
Emits code for OpenMP 'if' clause using specified BodyGenCallbackTy Here is the logic: if (Cond) { Th...
LLVM_ABI void finalize(Function *Fn=nullptr)
Finalize the underlying module, e.g., by outlining regions.
LLVM_ABI Function * getOrCreateRuntimeFunctionPtr(omp::RuntimeFunction FnID)
void addOutlineInfo(std::unique_ptr< OutlineInfo > &&OI)
Add a new region that will be outlined later.
LLVM_ABI InsertPointTy createTargetInit(const LocationDescription &Loc, const llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs)
Create a runtime call for kmpc_target_init.
LLVM_ABI InsertPointOrErrorTy createReductions(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< ReductionInfo > ReductionInfos, ArrayRef< bool > IsByRef, bool IsNoWait=false, bool IsTeamsReduction=false)
Generator for 'omp reduction'.
const Triple T
The target triple of the underlying module.
DenseMap< std::pair< Constant *, uint64_t >, Constant * > IdentMap
Map to remember existing ident_t*.
LLVM_ABI CallInst * createOMPFree(const LocationDescription &Loc, Value *Addr, Value *Allocator, std::string Name="")
Create a runtime call for kmpc_free.
LLVM_ABI InsertPointOrErrorTy createReductionsGPU(const LocationDescription &Loc, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, ArrayRef< ReductionInfo > ReductionInfos, ArrayRef< bool > IsByRef, bool IsNoWait=false, bool IsTeamsReduction=false, bool IsSPMD=false, ReductionGenCBKind ReductionGenCBKind=ReductionGenCBKind::MLIR, std::optional< omp::GV > GridValue={}, Value *SrcLocInfo=nullptr)
Design of OpenMP reductions on the GPU.
LLVM_ABI FunctionCallee createForStaticInitFunction(unsigned IVSize, bool IVSigned, bool IsGPUDistribute)
Returns __kmpc_for_static_init_* runtime function for the specified size IVSize and sign IVSigned.
LLVM_ABI CallInst * createOMPAlloc(const LocationDescription &Loc, Value *Size, Value *Allocator, std::string Name="")
Create a runtime call for kmpc_alloc.
LLVM_ABI void emitNonContiguousDescriptor(InsertPointTy AllocaIP, InsertPointTy CodeGenIP, MapInfosTy &CombinedInfo, TargetDataInfo &Info)
Emit an array of struct descriptors to be assigned to the offload args.
LLVM_ABI InsertPointOrErrorTy createSection(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB)
Generator for 'omp section'.
LLVM_ABI InsertPointOrErrorTy createTaskgroup(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< BasicBlock * > DeallocBlocks, BodyGenCallbackTy BodyGenCB)
Generator for the taskgroup construct.
LLVM_ABI InsertPointOrErrorTy createParallel(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< BasicBlock * > DeallocBlocks, BodyGenCallbackTy BodyGenCB, PrivatizeCallbackTy PrivCB, FinalizeCallbackTy FiniCB, Value *IfCondition, Value *NumThreads, omp::ProcBindKind ProcBind, bool IsCancellable)
Generator for 'omp parallel'.
function_ref< InsertPointOrErrorTy(InsertPointTy)> EmitFallbackCallbackTy
Callback function type for functions emitting the host fallback code that is executed when the kernel...
static LLVM_ABI TargetRegionEntryInfo getTargetEntryUniqueInfo(FileIdentifierInfoCallbackTy CallBack, vfs::FileSystem &VFS, StringRef ParentName="")
Creates a unique info for a target entry when provided a filename and line number from.
LLVM_ABI void emitTaskDependency(IRBuilderBase &Builder, Value *Entry, const DependData &Dep)
Store one kmp_depend_info entry at the given Entry pointer.
LLVM_ABI void emitBlock(BasicBlock *BB, Function *CurFn, bool IsFinished=false)
LLVM_ABI Value * getOrCreateThreadID(Value *Ident)
Return the current thread ID.
LLVM_ABI InsertPointOrErrorTy createMaster(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB)
Generator for 'omp master'.
LLVM_ABI InsertPointOrErrorTy createTargetData(const LocationDescription &Loc, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, ArrayRef< BasicBlock * > DeallocBlocks, Value *DeviceID, Value *IfCond, TargetDataInfo &Info, GenMapInfoCallbackTy GenMapInfoCB, CustomMapperCallbackTy CustomMapperCB, omp::RuntimeFunction *MapperFunc=nullptr, function_ref< InsertPointOrErrorTy(InsertPointTy CodeGenIP, BodyGenTy BodyGenType)> BodyGenCB=nullptr, function_ref< void(unsigned int, Value *)> DeviceAddrCB=nullptr, Value *SrcLocInfo=nullptr)
Generator for 'omp target data'.
LLVM_ABI CallInst * createRuntimeFunctionCall(FunctionCallee Callee, ArrayRef< Value * > Args, StringRef Name="")
LLVM_ABI 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.
StringMap< GlobalVariable *, BumpPtrAllocator > InternalVars
An ordered map of auto-generated variables to their unique names.
LLVM_ABI InsertPointOrErrorTy createCancellationPoint(const LocationDescription &Loc, omp::Directive CanceledDirective)
Generator for 'omp cancellation point'.
LLVM_ABI CallInst * createOMPAlignedAlloc(const LocationDescription &Loc, Value *Align, Value *Size, Value *Allocator, std::string Name="")
Create a runtime call for kmpc_align_alloc.
LLVM_ABI FunctionCallee createDispatchInitFunction(unsigned IVSize, bool IVSigned)
Returns __kmpc_dispatch_init_* runtime function for the specified size IVSize and sign IVSigned.
LLVM_ABI InsertPointOrErrorTy createScan(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< llvm::Value * > ScanVars, ArrayRef< llvm::Type * > ScanVarsType, bool IsInclusive, ScanInfo *ScanRedInfo)
This directive split and directs the control flow to input phase blocks or scan phase blocks based on...
LLVM_ABI CallInst * createOMPFreeShared(const LocationDescription &Loc, Value *Addr, Value *Size, const Twine &Name=Twine(""))
Create a runtime call for kmpc_free_shared.
LLVM_ABI 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.
LLVM_ABI GlobalVariable * getOrCreateInternalVariable(Type *Ty, const StringRef &Name, std::optional< unsigned > AddressSpace={})
Gets (if variable with the given name already exist) or creates internal global variable with the spe...
LLVM_ABI GlobalVariable * createOffloadMapnames(SmallVectorImpl< llvm::Constant * > &Names, std::string VarName)
Create the global variable holding the offload names information.
LLVM_ABI InsertPointOrErrorTy createTask(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< BasicBlock * > DeallocBlocks, BodyGenCallbackTy BodyGenCB, bool Tied=true, Value *Final=nullptr, Value *IfCondition=nullptr, const DependenciesInfo &Dependencies={}, const AffinityData &Affinities={}, bool Mergeable=false, Value *EventHandle=nullptr, Value *Priority=nullptr, bool FreeAgent=false)
Generator for #omp taskloop
std::forward_list< ScanInfo > ScanInfos
Collection of owned ScanInfo objects that eventually need to be free'd.
static LLVM_ABI void writeTeamsForKernel(const Triple &T, Function &Kernel, int32_t LB, int32_t UB)
LLVM_ABI Value * calculateCanonicalLoopTripCount(const LocationDescription &Loc, Value *Start, Value *Stop, Value *Step, bool IsSigned, bool InclusiveStop, const Twine &Name="loop")
Calculate the trip count of a canonical loop.
LLVM_ABI InsertPointOrErrorTy createBarrier(const LocationDescription &Loc, omp::Directive Kind, bool ForceSimpleCall=false, bool CheckCancelFlag=true)
Emitter methods for OpenMP directives.
LLVM_ABI void setCorrectMemberOfFlag(omp::OpenMPOffloadMappingFlags &Flags, omp::OpenMPOffloadMappingFlags MemberOfFlag)
Given an initial flag set, this function modifies it to contain the passed in MemberOfFlag generated ...
LLVM_ABI Error emitOffloadingArraysAndArgs(InsertPointTy AllocaIP, InsertPointTy CodeGenIP, TargetDataInfo &Info, TargetDataRTArgs &RTArgs, MapInfosTy &CombinedInfo, CustomMapperCallbackTy CustomMapperCB, bool IsNonContiguous=false, bool ForEndCall=false, function_ref< void(unsigned int, Value *)> DeviceAddrCB=nullptr)
Allocates memory for and populates the arrays required for offloading (offload_{baseptrs|ptrs|mappers...
LLVM_ABI Constant * getOrCreateDefaultSrcLocStr(uint32_t &SrcLocStrSize)
Return the (LLVM-IR) string describing the default source location.
LLVM_ABI InsertPointOrErrorTy createCritical(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, StringRef CriticalName, Value *HintInst)
Generator for 'omp critical'.
LLVM_ABI void createError(const LocationDescription &Loc, bool IsFatal, Value *Message)
Generate a call to the runtime to emit the diagnostic of an OpenMP error directive with at(execution)...
LLVM_ABI 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 LLVM_ABI unsigned getOpenMPDefaultSimdAlign(const Triple &TargetTriple, const StringMap< bool > &Features)
Get the default alignment value for given target.
LLVM_ABI unsigned getFlagMemberOffset()
Get the offset of the OMP_MAP_MEMBER_OF field.
LLVM_ABI 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, bool IsIgnoreDenormalMode=false, bool IsFineGrainedMemory=false, bool IsRemoteMemory=false)
Emit atomic update for constructs: — Only Scalar data types V = X; X = X BinOp Expr ,...
LLVM_ABI CanonicalLoopInfo * createLoopSkeleton(DebugLoc DL, Value *TripCount, Function *F, BasicBlock *PreInsertBefore, BasicBlock *PostInsertBefore, const Twine &Name={}, bool IsCollapsed=false)
Create the control flow structure of a canonical OpenMP loop.
LLVM_ABI void createOffloadEntriesAndInfoMetadata(EmitMetadataErrorReportFunctionTy &ErrorReportFunction)
LLVM_ABI void applySimd(CanonicalLoopInfo *Loop, MapVector< Value *, Value * > AlignedVars, Value *IfCond, omp::OrderKind Order, ConstantInt *Simdlen, ConstantInt *Safelen)
Add metadata to simd-ize a loop.
SmallVector< std::unique_ptr< OutlineInfo >, 16 > OutlineInfos
Collection of regions that need to be outlined during finalization.
LLVM_ABI InsertPointOrErrorTy createAtomicUpdate(const LocationDescription &Loc, InsertPointTy AllocaIP, AtomicOpValue &X, Value *Expr, AtomicOrdering AO, AtomicRMWInst::BinOp RMWOp, AtomicUpdateCallbackTy &UpdateOp, bool IsXBinopExpr, bool IsIgnoreDenormalMode=false, bool IsFineGrainedMemory=false, bool IsRemoteMemory=false)
Emit atomic update for constructs: X = X BinOp Expr ,or X = Expr BinOp X For complex Operations: X = ...
std::function< std::tuple< std::string, uint64_t >()> FileIdentifierInfoCallbackTy
bool isLastFinalizationInfoCancellable(omp::Directive DK)
Return true if the last entry in the finalization stack is of kind DK and cancellable.
LLVM_ABI 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.
LLVM_ABI GlobalVariable * createOffloadMaptypes(SmallVectorImpl< uint64_t > &Mappings, std::string VarName)
Create the global variable holding the offload mappings information.
LLVM_ABI ~OpenMPIRBuilder()
LLVM_ABI 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.
LLVM_ABI GlobalValue * createGlobalFlag(unsigned Value, StringRef Name)
Create a hidden global flag Name in the module with initial value Value.
LLVM_ABI 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,...
LLVM_ABI InsertPointOrErrorTy createMasked(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, Value *Filter)
Generator for 'omp masked'.
LLVM_ABI 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.
function_ref< Expected< InsertPointTy >( InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Value *DestPtr, Value *SrcPtr)> TaskDupCallbackTy
Callback type for task duplication function code generation.
LLVM_ABI Value * getSizeInBytes(Value *BasePtr)
Computes the size of type in bytes.
llvm::function_ref< llvm::Error( InsertPointTy BodyIP, llvm::Value *LinearIV)> IteratorBodyGenTy
LLVM_ABI FunctionCallee createDispatchDeinitFunction()
Returns __kmpc_dispatch_deinit runtime function.
LLVM_ABI 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.
LLVM_ABI void createTargetDeinit(const LocationDescription &Loc, int32_t TeamsReductionDataSize=0)
Create a runtime call for kmpc_target_deinit.
BodyGenTy
Type of BodyGen to use for region codegen.
LLVM_ABI CanonicalLoopInfo * fuseLoops(DebugLoc DL, ArrayRef< CanonicalLoopInfo * > Loops)
Fuse a sequence of loops.
LLVM_ABI void emitX86DeclareSimdFunction(llvm::Function *Fn, unsigned NumElements, const llvm::APSInt &VLENVal, llvm::ArrayRef< DeclareSimdAttrTy > ParamAttrs, DeclareSimdBranch Branch)
Emit x86 vector-function ABI attributes for a declare simd function.
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 LLVM_ABI std::pair< int32_t, int32_t > readTeamBoundsForKernel(const Triple &T, Function &Kernel)
Read/write a bounds on teams for Kernel.
const std::string ompOffloadInfoName
OMP Offload Info Metadata name string.
LLVM_ABI 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, bool NoLoop=false, bool HasDistSchedule=false, Value *DistScheduleChunkSize=nullptr, bool NeedsLastIter=false)
Modifies the canonical loop to be a workshare loop.
Expected< InsertPointTy > InsertPointOrErrorTy
Type used to represent an insertion point or an error value.
LLVM_ABI InsertPointTy createCopyPrivate(const LocationDescription &Loc, llvm::Value *BufSize, llvm::Value *CpyBuf, llvm::Value *CpyFn, llvm::Value *DidIt)
Generator for __kmpc_copyprivate.
LLVM_ABI InsertPointOrErrorTy createSections(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< StorableBodyGenCallbackTy > SectionCBs, PrivatizeCallbackTy PrivCB, FinalizeCallbackTy FiniCB, bool IsCancellable, bool IsNowait)
Generator for 'omp sections'.
std::function< void(EmitMetadataErrorKind, TargetRegionEntryInfo)> EmitMetadataErrorReportFunctionTy
Callback function type.
function_ref< InsertPointOrErrorTy( Argument &Arg, Value *Input, Value *&RetVal, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, ArrayRef< InsertPointTy > DeallocIPs)> TargetGenArgAccessorsCallbackTy
LLVM_ABI Expected< ScanInfo * > scanInfoInitialize()
Creates a ScanInfo object, allocates and returns the pointer.
LLVM_ABI InsertPointOrErrorTy emitTargetTask(TargetTaskBodyCallbackTy TaskBodyCB, Value *DeviceID, Value *RTLoc, OpenMPIRBuilder::InsertPointTy AllocaIP, const DependenciesInfo &Dependencies, const TargetDataRTArgs &RTArgs, bool HasNoWait)
Generate a target-task for the target construct.
LLVM_ABI InsertPointTy createAtomicRead(const LocationDescription &Loc, AtomicOpValue &X, AtomicOpValue &V, AtomicOrdering AO, InsertPointTy AllocaIP)
Emit atomic Read for : V = X — Only Scalar data types.
function_ref< Error(InsertPointTy AllocaIP, InsertPointTy CodeGenIP, ArrayRef< BasicBlock * > DeallocBlocks)> BodyGenCallbackTy
Callback type for body (=inner region) code generation.
bool updateToLocation(const LocationDescription &Loc)
Update the internal location to Loc.
LLVM_ABI void createFlush(const LocationDescription &Loc)
Generator for 'omp flush'.
LLVM_ABI 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...
LLVM_ABI void createTaskwait(const LocationDescription &Loc, DependenciesInfo Dependencies={}, bool IsNowait=false)
Generator for 'omp taskwait'.
origPtr *with the address space normalization required by the runtime entry point *The NULL descriptor makes the runtime walk the enclosing taskgroups to *find the matching task_reduction registration for the item The lookups *are emitted at p Loc
EmitMetadataErrorKind
The kind of errors that can occur when emitting the offload entries and metadata.
@ EMIT_MD_DECLARE_TARGET_ERROR
@ EMIT_MD_GLOBAL_VAR_INDIRECT_ERROR
@ EMIT_MD_GLOBAL_VAR_LINK_ERROR
@ EMIT_MD_TARGET_REGION_ERROR
unsigned getOpcode() const
Return the opcode for this Instruction or ConstantExpr.
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(LLVMContext &C)
This constructs an opaque pointer to an object in the default address space (address space zero).
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
ScanInfo holds the information to assist in lowering of Scan reduction.
llvm::SmallDenseMap< llvm::Value *, llvm::Value * > * ScanBuffPtrs
Maps the private reduction variable to the pointer of the temporary buffer.
llvm::BasicBlock * OMPScanLoopExit
Exit block of loop body.
llvm::Value * IV
Keeps track of value of iteration variable for input/scan loop to be used for Scan directive lowering...
llvm::BasicBlock * OMPAfterScanBlock
Dominates the body of the loop before scan directive.
llvm::BasicBlock * OMPScanInit
Block before loop body where scan initializations are done.
llvm::BasicBlock * OMPBeforeScanBlock
Dominates the body of the loop before scan directive.
llvm::BasicBlock * OMPScanFinish
Block after loop body where scan finalizations are done.
llvm::Value * Span
Stores the span of canonical loop being lowered to be used for temporary buffer allocation or Finaliz...
bool OMPFirstScanLoop
If true, it indicates Input phase is lowered; else it indicates ScanPhase is lowered.
llvm::BasicBlock * OMPScanDispatch
Controls the flow to before or after scan blocks.
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
Returns true if bit Idx is set.
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.
bool contains(ConstPtrType Ptr) const
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...
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...
Represent a constant reference to a string, i.e.
std::string str() const
Get the contents as an std::string.
constexpr bool empty() const
Check if the string is empty.
constexpr size_t size() const
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 LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
static LLVM_ABI StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Type * getElementType(unsigned N) const
LLVM_ABI void addCase(ConstantInt *OnVal, BasicBlock *Dest)
Add an entry to the switch instruction.
Target - Wrapper for Target specific information.
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).
bool isSystemZ() const
Tests whether the target is SystemZ.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM_ABI 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.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
LLVM_ABI unsigned getIntegerBitWidth() const
LLVM_ABI Type * getStructElementType(unsigned N) const
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isPointerTy() const
True if this is an instance of PointerType.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
bool isStructTy() const
True if this is an instance of StructType.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
bool isVoidTy() const
Return true if this is 'void'.
Unconditional Branch instruction.
static UncondBrInst * Create(BasicBlock *Target, InsertPosition InsertBefore=nullptr)
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
This function has undefined behavior.
A Use represents the edge between a Value definition and its users.
void setOperand(unsigned i, Value *Val)
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
LLVM_ABI bool hasNUses(unsigned N) const
Return true if this Value has exactly N uses.
LLVM_ABI User * getUniqueUndroppableUser()
Return true if there is exactly one unique user of this value that cannot be dropped (that user can h...
LLVM_ABI bool 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...
iterator_range< use_iterator > uses()
LLVM_ABI 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.
A raw_ostream that writes to an SmallVector or SmallString.
The virtual file system interface.
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(const Twine &Name, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatile=false, bool IsText=true)
This is a convenience method that opens a file, gets its content and then closes the file.
virtual llvm::ErrorOr< Status > status(const Twine &Path)=0
Get the status of the entry at Path, if one exists.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ SPIR_KERNEL
Used for SPIR kernel functions.
@ PTX_Kernel
Call to a PTX kernel. Passes all arguments in parameter space.
@ BasicBlock
Various leaf nodes.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
Flag
These should be considered private to the implementation of the MCInstrDesc class.
constexpr StringLiteral MaxNTID("nvvm.maxntid")
constexpr StringLiteral MaxClusterRank("nvvm.maxclusterrank")
initializer< Ty > init(const Ty &Val)
@ User
could "use" a pointer
LLVM_ABI GlobalVariable * emitOffloadingEntry(Module &M, object::OffloadKind Kind, Constant *Addr, StringRef Name, uint64_t Size, uint32_t Flags, uint64_t Data, Constant *AuxAddr=nullptr)
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.
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.
constexpr const GV & getAMDGPUGridValues()
constexpr unsigned DefaultPartialUnrollFactor
Unroll factor for a partial unroll without an explicit factor, when the unrolled loop must be materia...
static constexpr GV SPIRVGridValues
For generic SPIR-V GPUs.
OMPDynGroupprivateFallbackType
The fallback types for the dyn_groupprivate clause.
static constexpr GV NVPTXGridValues
For Nvidia GPUs.
@ OMP_TGT_EXEC_MODE_SPMD_NO_LOOP
@ OMP_TGT_EXEC_MODE_GENERIC
Function * Kernel
Summary of a kernel (=entry point for target offloading).
WorksharingLoopType
A type of worksharing loop construct.
OMPAtomicCompareOp
Atomic compare operations. Currently OpenMP only supports ==, >, and <.
EnumSet< Property > Properties
NodeAddr< PhiNode * > Phi
friend class Instruction
Iterator for Instructions in a `BasicBlock.
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.
LLVM_ABI 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.
hash_code hash_value(const FixedPointSemantics &Val)
LLVM_ABI 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.
@ LLVM_MARK_AS_BITMASK_ENUM
LLVM_ABI BasicBlock * CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap, const Twine &NameSuffix="", Function *F=nullptr, ClonedCodeInfo *CodeInfo=nullptr, bool MapAtoms=true)
Return a copy of the specified basic block, but without embedding the block into a particular functio...
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
unsigned getPointerAddressSpace(const Type *T)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto successors(const MachineBasicBlock *BB)
@ Load
The value being inserted comes from a load (InsertElement only).
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
testing::Matcher< const detail::ErrorHolder & > Failed()
constexpr from_range_t from_range
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE()
LLVM_ABI BasicBlock * splitBB(IRBuilderBase::InsertPoint IP, bool CreateBranch, DebugLoc DL, llvm::Twine Name={})
Split a BasicBlock at an InsertPoint, even if the block is degenerate (missing the terminator).
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...
std::string utostr(uint64_t X, bool isNeg=false)
ErrorOr< T > expectedToErrorOrAndEmitErrors(LLVMContext &Ctx, Expected< T > Val)
bool isa_and_nonnull(const Y &Val)
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto dyn_cast_or_null(const Y &Val)
LLVM_ABI 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)
LLVM_ABI 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...
LLVM_ABI 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.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
LLVM_ABI 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).
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
LLVM_ABI 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.
@ Mul
Product of integers.
LLVM_ABI BasicBlock * SplitBlock(BasicBlock *Old, BasicBlock::iterator SplitPt, DominatorTree *DT, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, const Twine &BBName="")
Split the specified block at the specified instruction.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
DWARFExpression::Operation Op
LLVM_ABI void remapInstructionsInBlocks(ArrayRef< BasicBlock * > Blocks, ValueToValueMapTy &VMap)
Remaps instructions in Blocks using the mapping in VMap.
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
constexpr unsigned BitWidth
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
LLVM_ABI void spliceBB(IRBuilderBase::InsertPoint IP, BasicBlock *New, bool CreateBranch, DebugLoc DL)
Move the instruction after an InsertPoint to the beginning of another BasicBlock.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
auto predecessors(const MachineBasicBlock *BB)
auto filter_to_vector(ContainerTy &&C, PredicateFn &&Pred)
Filter a range to a SmallVector with the element types deduced.
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
LLVM_ABI Constant * ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val, ArrayRef< unsigned > Idxs)
Attempt to constant fold an insertvalue instruction with the specified operands and indices.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI void DeleteDeadBlocks(ArrayRef< BasicBlock * > BBs, DomTreeUpdater *DTU=nullptr, bool KeepOneInputPHIs=false)
Delete the specified blocks from BB.
bool to_integer(StringRef S, N &Num, unsigned Base=0)
Convert the string S to an integer of the specified type using the radix Base. If Base is 0,...
@ End
Run the machine verifier once, at the end of the pipeline.
static auto filterDbgVars(iterator_range< simple_ilist< DbgRecord >::iterator > R)
Filter the DbgRecord range to DbgVariableRecord types only and downcast.
Physical handles captured before the source descriptors are invalidated.
SmallVector< PHINode *, 4 > IndVars
SmallVector< BasicBlock *, 4 > Preheaders
SmallVector< BasicBlock *, 4 > Latches
This struct is a compact representation of a valid (non-zero power of two) alignment.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
A struct to pack the relevant information for an OpenMP affinity clause.
a struct to pack relevant information while generating atomic Ops
A struct to pack the relevant information for an OpenMP depend clause.
omp::RTLDependenceKindTy DepKind
A struct to pack static and dynamic dependency information for a task.
SmallVector< DependData > Deps
LLVM_ABI Error mergeFiniBB(IRBuilderBase &Builder, BasicBlock *ExistingFiniBB)
For cases where there is an unavoidable existing finalization block (e.g.
LLVM_ABI Expected< BasicBlock * > getFiniBB(IRBuilderBase &Builder)
The basic block to which control should be transferred to implement the FiniCB.
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.
void collectBlocks(SmallPtrSetImpl< BasicBlock * > &BlockSet, SmallVectorImpl< BasicBlock * > &BlockVector)
Collect all blocks in between EntryBB and ExitBB in both the given vector and set.
BasicBlock * OuterAllocBB
virtual std::unique_ptr< CodeExtractor > createCodeExtractor(ArrayRef< BasicBlock * > Blocks, bool ArgsInZeroAddressSpace, Twine Suffix=Twine(""))
Create a CodeExtractor instance based on the information stored in this structure,...
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.
ReductionGenDataPtrPtrCBTy DataPtrPtrGen
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 * MapTypesArrayEnd
The array of map types passed to the runtime library for the end of the region, or nullptr if there a...
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.
bool StrictBlocks
True if the kernel strictly requires the number of blocks and threads above to run.
ArrayRef< Value * > NumThreads
The number of threads.
TargetDataRTArgs RTArgs
Arguments passed to the runtime library.
Value * NumIterations
The number of iterations.
Value * DynCGroupMem
The size of the dynamic shared memory.
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.
omp::OMPDynGroupprivateFallbackType DynCGroupMemFallback
The fallback mechanism for the shared memory.
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...
Value * DeviceID
Device ID value used in the kernel launch.
SmallVector< Value *, 3 > MaxTeams
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
SmallVector< Value * > MaxThreads
'parallel' construct 'num_threads' clause value, if present and it is an SPMD kernel.
Data structure to contain the information needed to uniquely identify a target entry.
static LLVM_ABI void getTargetRegionEntryFnName(SmallVectorImpl< char > &Name, StringRef ParentName, unsigned DeviceID, unsigned FileID, unsigned Line, unsigned Count)
static constexpr const char * KernelNamePrefix
The prefix used for kernel names.
Defines various target-specific GPU grid values that must be consistent between host RTL (plugin),...