70#define DEBUG_TYPE "openmp-ir-builder"
77 cl::desc(
"Use optimistic attributes describing "
78 "'as-if' properties of runtime calls."),
82 "openmp-ir-builder-unroll-threshold-factor",
cl::Hidden,
83 cl::desc(
"Factor for the unroll threshold to account for code "
84 "simplifications still taking place"),
88 "openmp-ir-builder-use-default-max-threads",
cl::Hidden,
99 if (!IP1.isSet() || !IP2.isSet())
101 return IP1.getBlock() == IP2.getBlock() && IP1.getPoint() == IP2.getPoint();
106 switch (SchedType & ~OMPScheduleType::MonotonicityMask) {
107 case OMPScheduleType::UnorderedStaticChunked:
108 case OMPScheduleType::UnorderedStatic:
109 case OMPScheduleType::UnorderedDynamicChunked:
110 case OMPScheduleType::UnorderedGuidedChunked:
111 case OMPScheduleType::UnorderedRuntime:
112 case OMPScheduleType::UnorderedAuto:
113 case OMPScheduleType::UnorderedTrapezoidal:
114 case OMPScheduleType::UnorderedGreedy:
115 case OMPScheduleType::UnorderedBalanced:
116 case OMPScheduleType::UnorderedGuidedIterativeChunked:
117 case OMPScheduleType::UnorderedGuidedAnalyticalChunked:
118 case OMPScheduleType::UnorderedSteal:
119 case OMPScheduleType::UnorderedStaticBalancedChunked:
120 case OMPScheduleType::UnorderedGuidedSimd:
121 case OMPScheduleType::UnorderedRuntimeSimd:
122 case OMPScheduleType::OrderedStaticChunked:
123 case OMPScheduleType::OrderedStatic:
124 case OMPScheduleType::OrderedDynamicChunked:
125 case OMPScheduleType::OrderedGuidedChunked:
126 case OMPScheduleType::OrderedRuntime:
127 case OMPScheduleType::OrderedAuto:
128 case OMPScheduleType::OrderdTrapezoidal:
129 case OMPScheduleType::NomergeUnorderedStaticChunked:
130 case OMPScheduleType::NomergeUnorderedStatic:
131 case OMPScheduleType::NomergeUnorderedDynamicChunked:
132 case OMPScheduleType::NomergeUnorderedGuidedChunked:
133 case OMPScheduleType::NomergeUnorderedRuntime:
134 case OMPScheduleType::NomergeUnorderedAuto:
135 case OMPScheduleType::NomergeUnorderedTrapezoidal:
136 case OMPScheduleType::NomergeUnorderedGreedy:
137 case OMPScheduleType::NomergeUnorderedBalanced:
138 case OMPScheduleType::NomergeUnorderedGuidedIterativeChunked:
139 case OMPScheduleType::NomergeUnorderedGuidedAnalyticalChunked:
140 case OMPScheduleType::NomergeUnorderedSteal:
141 case OMPScheduleType::NomergeOrderedStaticChunked:
142 case OMPScheduleType::NomergeOrderedStatic:
143 case OMPScheduleType::NomergeOrderedDynamicChunked:
144 case OMPScheduleType::NomergeOrderedGuidedChunked:
145 case OMPScheduleType::NomergeOrderedRuntime:
146 case OMPScheduleType::NomergeOrderedAuto:
147 case OMPScheduleType::NomergeOrderedTrapezoidal:
148 case OMPScheduleType::OrderedDistributeChunked:
149 case OMPScheduleType::OrderedDistribute:
157 SchedType & OMPScheduleType::MonotonicityMask;
158 if (MonotonicityFlags == OMPScheduleType::MonotonicityMask)
172 Builder.restoreIP(IP);
176 if (Builder.GetInsertPoint() != BB->
end())
186 unsigned Line = FSP->getScopeLine() ? FSP->getScopeLine() : FSP->getLine();
187 Builder.SetCurrentDebugLocation(
193 return T.isAMDGPU() ||
T.isNVPTX() ||
T.isSPIRV();
199 Kernel->getFnAttribute(
"target-features").getValueAsString();
200 if (Features.
count(
"+wavefrontsize64"))
215 bool HasSimdModifier,
bool HasDistScheduleChunks) {
217 switch (ClauseKind) {
218 case OMP_SCHEDULE_Default:
219 case OMP_SCHEDULE_Static:
220 return HasChunks ? OMPScheduleType::BaseStaticChunked
221 : OMPScheduleType::BaseStatic;
222 case OMP_SCHEDULE_Dynamic:
223 return OMPScheduleType::BaseDynamicChunked;
224 case OMP_SCHEDULE_Guided:
225 return HasSimdModifier ? OMPScheduleType::BaseGuidedSimd
226 : OMPScheduleType::BaseGuidedChunked;
227 case OMP_SCHEDULE_Auto:
229 case OMP_SCHEDULE_Runtime:
230 return HasSimdModifier ? OMPScheduleType::BaseRuntimeSimd
231 : OMPScheduleType::BaseRuntime;
232 case OMP_SCHEDULE_Distribute:
233 return HasDistScheduleChunks ? OMPScheduleType::BaseDistributeChunked
234 : OMPScheduleType::BaseDistribute;
242 bool HasOrderedClause) {
243 assert((BaseScheduleType & OMPScheduleType::ModifierMask) ==
244 OMPScheduleType::None &&
245 "Must not have ordering nor monotonicity flags already set");
248 ? OMPScheduleType::ModifierOrdered
249 : OMPScheduleType::ModifierUnordered;
250 OMPScheduleType OrderingScheduleType = BaseScheduleType | OrderingModifier;
253 if (OrderingScheduleType ==
254 (OMPScheduleType::BaseGuidedSimd | OMPScheduleType::ModifierOrdered))
255 return OMPScheduleType::OrderedGuidedChunked;
256 else if (OrderingScheduleType == (OMPScheduleType::BaseRuntimeSimd |
257 OMPScheduleType::ModifierOrdered))
258 return OMPScheduleType::OrderedRuntime;
260 return OrderingScheduleType;
266 bool HasSimdModifier,
bool HasMonotonic,
267 bool HasNonmonotonic,
bool HasOrderedClause) {
268 assert((ScheduleType & OMPScheduleType::MonotonicityMask) ==
269 OMPScheduleType::None &&
270 "Must not have monotonicity flags already set");
271 assert((!HasMonotonic || !HasNonmonotonic) &&
272 "Monotonic and Nonmonotonic are contradicting each other");
275 return ScheduleType | OMPScheduleType::ModifierMonotonic;
276 }
else if (HasNonmonotonic) {
277 return ScheduleType | OMPScheduleType::ModifierNonmonotonic;
287 if ((BaseScheduleType == OMPScheduleType::BaseStatic) ||
288 (BaseScheduleType == OMPScheduleType::BaseStaticChunked) ||
294 return ScheduleType | OMPScheduleType::ModifierNonmonotonic;
302 bool HasSimdModifier,
bool HasMonotonicModifier,
303 bool HasNonmonotonicModifier,
bool HasOrderedClause,
304 bool HasDistScheduleChunks) {
306 ClauseKind, HasChunks, HasSimdModifier, HasDistScheduleChunks);
310 OrderedSchedule, HasSimdModifier, HasMonotonicModifier,
311 HasNonmonotonicModifier, HasOrderedClause);
319static std::optional<omp::OMPTgtExecModeFlags>
324 if (
Call->getCalledFunction()->getName() ==
"__kmpc_target_init") {
325 TargetInitCall =
Call;
350 std::optional<omp::OMPTgtExecModeFlags> ExecMode =
362 if (
Instruction *Term = Source->getTerminatorOrNull()) {
371 NewBr->setDebugLoc(
DL);
376 assert(New->getFirstInsertionPt() == New->begin() &&
377 "Target BB must not have PHI nodes");
393 New->splice(New->begin(), Old, IP.
getPoint(), Old->
end());
397 NewBr->setDebugLoc(
DL);
409 Builder.SetInsertPoint(Old);
413 Builder.SetCurrentDebugLocation(
DebugLoc);
423 New->replaceSuccessorsPhiUsesWith(Old, New);
432 Builder.SetInsertPoint(Builder.GetInsertBlock()->getTerminator());
434 Builder.SetInsertPoint(Builder.GetInsertBlock());
437 Builder.SetCurrentDebugLocation(
DebugLoc);
446 Builder.SetInsertPoint(Builder.GetInsertBlock()->getTerminator());
448 Builder.SetInsertPoint(Builder.GetInsertBlock());
451 Builder.SetCurrentDebugLocation(
DebugLoc);
468 const Twine &Name =
"",
bool AsPtr =
true,
469 bool Is64Bit =
false) {
470 Builder.restoreIP(OuterAllocaIP);
474 Builder.CreateAlloca(IntTy,
nullptr, Name +
".addr");
478 FakeVal = FakeValAddr;
480 FakeVal = Builder.CreateLoad(IntTy, FakeValAddr, Name +
".val");
485 Builder.restoreIP(InnerAllocaIP);
488 UseFakeVal = Builder.CreateLoad(IntTy, FakeVal, Name +
".use");
491 FakeVal, Is64Bit ? Builder.getInt64(10) : Builder.getInt32(10)));
504enum OpenMPOffloadingRequiresDirFlags {
506 OMP_REQ_UNDEFINED = 0x000,
508 OMP_REQ_NONE = 0x001,
510 OMP_REQ_REVERSE_OFFLOAD = 0x002,
512 OMP_REQ_UNIFIED_ADDRESS = 0x004,
514 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008,
516 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010,
523 DominatorTree *DT =
nullptr,
bool AggregateArgs =
false,
524 BlockFrequencyInfo *BFI =
nullptr,
525 BranchProbabilityInfo *BPI =
nullptr,
526 AssumptionCache *AC =
nullptr,
bool AllowVarArgs =
false,
527 bool AllowAlloca =
false,
528 BasicBlock *AllocationBlock =
nullptr,
530 std::string Suffix =
"",
bool ArgsInZeroAddressSpace =
false)
531 : CodeExtractor(BBs, DT, AggregateArgs, BFI, BPI, AC, AllowVarArgs,
532 AllowAlloca, AllocationBlock, DeallocationBlocks, Suffix,
533 ArgsInZeroAddressSpace),
534 OMPBuilder(OMPBuilder) {}
536 virtual ~OMPCodeExtractor() =
default;
539 OpenMPIRBuilder &OMPBuilder;
542class DeviceSharedMemCodeExtractor :
public OMPCodeExtractor {
544 using OMPCodeExtractor::OMPCodeExtractor;
545 virtual ~DeviceSharedMemCodeExtractor() =
default;
549 allocateVar(IRBuilder<>::InsertPoint AllocaIP,
Type *VarType,
550 const Twine &Name = Twine(
""),
551 AddrSpaceCastInst **CastedAlloc =
nullptr)
override {
552 return OMPBuilder.createOMPAllocShared(AllocaIP, VarType, Name);
555 virtual Instruction *deallocateVar(IRBuilder<>::InsertPoint DeallocIP,
557 return OMPBuilder.createOMPFreeShared(DeallocIP, Var, VarType);
564 OpenMPIRBuilder &OMPBuilder;
566 DeviceSharedMemOutlineInfo(OpenMPIRBuilder &OMPBuilder)
567 : OMPBuilder(OMPBuilder) {}
568 virtual ~DeviceSharedMemOutlineInfo() =
default;
570 virtual std::unique_ptr<CodeExtractor>
572 bool ArgsInZeroAddressSpace,
573 Twine Suffix = Twine(
""))
override;
579 : RequiresFlags(OMP_REQ_UNDEFINED) {}
583 bool HasRequiresReverseOffload,
bool HasRequiresUnifiedAddress,
584 bool HasRequiresUnifiedSharedMemory,
bool HasRequiresDynamicAllocators)
587 RequiresFlags(OMP_REQ_UNDEFINED) {
588 if (HasRequiresReverseOffload)
589 RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
590 if (HasRequiresUnifiedAddress)
591 RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
592 if (HasRequiresUnifiedSharedMemory)
593 RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
594 if (HasRequiresDynamicAllocators)
595 RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
599 return RequiresFlags & OMP_REQ_REVERSE_OFFLOAD;
603 return RequiresFlags & OMP_REQ_UNIFIED_ADDRESS;
607 return RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY;
611 return RequiresFlags & OMP_REQ_DYNAMIC_ALLOCATORS;
616 :
static_cast<int64_t
>(OMP_REQ_NONE);
621 RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
623 RequiresFlags &= ~OMP_REQ_REVERSE_OFFLOAD;
628 RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
630 RequiresFlags &= ~OMP_REQ_UNIFIED_ADDRESS;
635 RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
637 RequiresFlags &= ~OMP_REQ_UNIFIED_SHARED_MEMORY;
642 RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
644 RequiresFlags &= ~OMP_REQ_DYNAMIC_ALLOCATORS;
657 constexpr size_t MaxDim = 3;
662 Value *DynCGroupMemFallbackFlag =
664 DynCGroupMemFallbackFlag =
Builder.CreateShl(DynCGroupMemFallbackFlag, 2);
667 StrictFlag =
Builder.CreateShl(StrictFlag, 6);
669 Value *Flags =
Builder.CreateOr(HasNoWaitFlag, DynCGroupMemFallbackFlag);
670 Flags =
Builder.CreateOr(Flags, StrictFlag);
676 Value *NumThreads3D =
707 auto FnAttrs = Attrs.getFnAttrs();
708 auto RetAttrs = Attrs.getRetAttrs();
710 for (
size_t ArgNo = 0; ArgNo < Fn.
arg_size(); ++ArgNo)
715 bool Param =
true) ->
void {
716 bool HasSignExt = AS.hasAttribute(Attribute::SExt);
717 bool HasZeroExt = AS.hasAttribute(Attribute::ZExt);
718 if (HasSignExt || HasZeroExt) {
719 assert(AS.getNumAttributes() == 1 &&
720 "Currently not handling extension attr combined with others.");
722 if (
auto AK = TargetLibraryInfo::getExtAttrForI32Param(
T, HasSignExt))
725 TargetLibraryInfo::getExtAttrForI32Return(
T, HasSignExt))
732#define OMP_ATTRS_SET(VarName, AttrSet) AttributeSet VarName = AttrSet;
733#include "llvm/Frontend/OpenMP/OMPKinds.def"
737#define OMP_RTL_ATTRS(Enum, FnAttrSet, RetAttrSet, ArgAttrSets) \
739 FnAttrs = FnAttrs.addAttributes(Ctx, FnAttrSet); \
740 addAttrSet(RetAttrs, RetAttrSet, false); \
741 for (size_t ArgNo = 0; ArgNo < ArgAttrSets.size(); ++ArgNo) \
742 addAttrSet(ArgAttrs[ArgNo], ArgAttrSets[ArgNo]); \
743 Fn.setAttributes(AttributeList::get(Ctx, FnAttrs, RetAttrs, ArgAttrs)); \
745#include "llvm/Frontend/OpenMP/OMPKinds.def"
759#define OMP_RTL(Enum, Str, IsVarArg, ReturnType, ...) \
761 FnTy = FunctionType::get(ReturnType, ArrayRef<Type *>{__VA_ARGS__}, \
763 Fn = M.getFunction(Str); \
765#include "llvm/Frontend/OpenMP/OMPKinds.def"
771#define OMP_RTL(Enum, Str, ...) \
773 Fn = Function::Create(FnTy, GlobalValue::ExternalLinkage, Str, M); \
775#include "llvm/Frontend/OpenMP/OMPKinds.def"
779 if (FnID == OMPRTL___kmpc_fork_call || FnID == OMPRTL___kmpc_fork_teams) {
789 LLVMContext::MD_callback,
791 2, {-1, -1},
true)}));
804 assert(Fn &&
"Failed to create OpenMP runtime function");
815 Builder.SetInsertPoint(FiniBB);
827 FiniBB = OtherFiniBB;
829 Builder.SetInsertPoint(FiniBB->getFirstNonPHIIt());
837 auto EndIt = FiniBB->end();
838 if (FiniBB->size() >= 1)
839 if (
auto Prev = std::prev(EndIt); Prev->isTerminator())
844 FiniBB->replaceAllUsesWith(OtherFiniBB);
845 FiniBB->eraseFromParent();
846 FiniBB = OtherFiniBB;
853 assert(Fn &&
"Failed to create OpenMP runtime function pointer");
876 for (
auto Inst =
Block->getReverseIterator()->begin();
877 Inst !=
Block->getReverseIterator()->end();) {
906 Block.getParent()->getEntryBlock().getTerminator()->getIterator();
927 DeferredOutlines.
push_back(std::move(OI));
931 ParallelRegionBlockSet.
clear();
933 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
943 bool ArgsInZeroAddressSpace =
Config.isTargetDevice();
944 std::unique_ptr<CodeExtractor> Extractor =
945 OI->createCodeExtractor(Blocks, ArgsInZeroAddressSpace,
".omp_par");
949 <<
" Exit: " << OI->ExitBB->getName() <<
"\n");
950 assert(Extractor->isEligible() &&
951 "Expected OpenMP outlining to be possible!");
953 for (
auto *V : OI->ExcludeArgsFromAggregate)
954 Extractor->excludeArgFromAggregate(V);
957 Extractor->extractCodeRegion(CEAC, OI->Inputs, OI->Outputs);
961 if (TargetCpuAttr.isStringAttribute())
964 auto TargetFeaturesAttr = OuterFn->
getFnAttribute(
"target-features");
965 if (TargetFeaturesAttr.isStringAttribute())
966 OutlinedFn->
addFnAttr(TargetFeaturesAttr);
969 LLVM_DEBUG(
dbgs() <<
" Outlined function: " << *OutlinedFn <<
"\n");
971 "OpenMP outlined functions should not return a value!");
976 M.getFunctionList().insertAfter(OuterFn->
getIterator(), OutlinedFn);
983 assert(OI->EntryBB->getUniquePredecessor() == &ArtificialEntry);
990 "Expected instructions to add in the outlined region entry");
992 End = ArtificialEntry.
rend();
997 if (
I.isTerminator()) {
999 if (
Instruction *TI = OI->EntryBB->getTerminatorOrNull())
1000 TI->adoptDbgRecords(&ArtificialEntry,
I.getIterator(),
false);
1004 I.moveBeforePreserving(*OI->EntryBB,
1005 OI->EntryBB->getFirstInsertionPt());
1008 OI->EntryBB->moveBefore(&ArtificialEntry);
1015 if (OI->PostOutlineCB)
1016 OI->PostOutlineCB(*OutlinedFn);
1018 if (OI->FixUpNonEntryAllocas)
1050 errs() <<
"Error of kind: " << Kind
1051 <<
" when emitting offload entries and metadata during "
1052 "OMPIRBuilder finalization \n";
1060 if (
Config.isTargetDevice())
1061 applyDeclareTargetGlobalReplacements();
1063 if (
Config.EmitLLVMUsedMetaInfo.value_or(
false)) {
1064 std::vector<WeakTrackingVH> LLVMCompilerUsed = {
1065 M.getGlobalVariable(
"__openmp_nvptx_data_transfer_temporary_storage")};
1066 emitUsed(
"llvm.compiler.used", LLVMCompilerUsed);
1076 assert(Original && Replacement &&
1077 "Null values provided to registerDeclareTargetGlobalReplacement");
1081void OpenMPIRBuilder::applyDeclareTargetGlobalReplacements() {
1087 "A null value was inserted into DeclareTargetGlobalReplacements");
1091 if (!OldGV || !NewGV)
1125 for (
unsigned I = 0, E =
PHI->getNumIncomingValues();
I < E; ++
I) {
1126 if (
PHI->getIncomingValue(
I) != OldGV)
1131 Builder.SetCurrentDebugLocation(
PHI->getDebugLoc());
1133 PHI->setIncomingValue(
I, EdgeLoad);
1139 Builder.SetCurrentDebugLocation(Insn->getDebugLoc());
1155 "Non-default address space declare target global");
1157 unsigned DestAS = ASC->getType()->getPointerAddressSpace();
1158 if (DestAS == 0 && NewGVAS != OldGVAS) {
1159 ASC->replaceAllUsesWith(
Load);
1160 ASC->eraseFromParent();
1165 Insn->replaceUsesOfWith(OldGV,
Load);
1181 ConstantInt::get(I32Ty,
Value), Name);
1194 for (
unsigned I = 0, E =
List.size();
I != E; ++
I)
1198 if (UsedArray.
empty())
1205 GV->setSection(
"llvm.metadata");
1211 auto *Int8Ty =
Builder.getInt8Ty();
1214 ConstantInt::get(Int8Ty, Mode),
Twine(KernelName,
"_exec_mode"));
1222 unsigned Reserve2Flags) {
1224 LocFlags |= OMP_IDENT_FLAG_KMPC;
1231 ConstantInt::get(Int32,
uint32_t(LocFlags)),
1232 ConstantInt::get(Int32, Reserve2Flags),
1233 ConstantInt::get(Int32, SrcLocStrSize), SrcLocStr};
1235 size_t SrcLocStrArgIdx = 4;
1236 if (OpenMPIRBuilder::Ident->getElementType(SrcLocStrArgIdx)
1240 SrcLocStr, OpenMPIRBuilder::Ident->getElementType(SrcLocStrArgIdx));
1247 if (
GV.getValueType() == OpenMPIRBuilder::Ident &&
GV.hasInitializer())
1248 if (
GV.getInitializer() == Initializer)
1253 M, OpenMPIRBuilder::Ident,
1256 M.getDataLayout().getDefaultGlobalsAddressSpace());
1268 SrcLocStrSize = LocStr.
size();
1277 if (
GV.isConstant() &&
GV.hasInitializer() &&
1278 GV.getInitializer() == Initializer)
1281 SrcLocStr =
Builder.CreateGlobalString(
1282 LocStr,
"",
M.getDataLayout().getDefaultGlobalsAddressSpace(),
1290 unsigned Line,
unsigned Column,
1296 Buffer.
append(FunctionName);
1298 Buffer.
append(std::to_string(Line));
1300 Buffer.
append(std::to_string(Column));
1308 StringRef UnknownLoc =
";unknown;unknown;0;0;;";
1319 !DIL->getFilename().empty() ? DIL->getFilename() :
M.getName();
1324 DIL->getColumn(), SrcLocStrSize);
1330 Loc.IP.getBlock()->getParent());
1336 "omp_global_thread_num");
1344 "expected one result pointer type per in_reduction item");
1347 if (OrigPtrs.
empty())
1348 return Builder.saveIP();
1367 for (
unsigned Idx = 0; Idx < OrigPtrs.
size(); ++Idx) {
1370 Value *OrigPtr = OrigPtrs[Idx];
1372 OrigPtrTy && OrigPtrTy->getAddressSpace() != 0)
1373 OrigPtr = Builder.CreateAddrSpaceCast(OrigPtr, PtrTy);
1375 Value *
Priv = Builder.CreateCall(GetThData, {Gtid, NullDesc, OrigPtr},
1381 ResPtrTy && ResPtrTy->getAddressSpace() != 0)
1382 Priv = Builder.CreateAddrSpaceCast(
Priv, ResultPtrTys[Idx]);
1384 MapPrivateCB(Idx,
Priv);
1391 bool ForceSimpleCall,
bool CheckCancelFlag) {
1401 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_FOR;
1404 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SECTIONS;
1407 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SINGLE;
1410 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_EXPL;
1413 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL;
1426 bool UseCancelBarrier =
1431 ? OMPRTL___kmpc_cancel_barrier
1432 : OMPRTL___kmpc_barrier),
1435 if (UseCancelBarrier && CheckCancelFlag)
1445 omp::Directive CanceledDirective) {
1450 auto *UI =
Builder.CreateUnreachable();
1458 Builder.SetInsertPoint(ElseTI);
1459 auto ElseIP =
Builder.saveIP();
1467 Builder.SetInsertPoint(ThenTI);
1469 Value *CancelKind =
nullptr;
1470 switch (CanceledDirective) {
1471#define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) \
1472 case DirectiveEnum: \
1473 CancelKind = Builder.getInt32(Value); \
1475#include "llvm/Frontend/OpenMP/OMPKinds.def"
1492 Builder.SetInsertPoint(UI->getParent());
1493 UI->eraseFromParent();
1500 omp::Directive CanceledDirective) {
1505 auto *UI =
Builder.CreateUnreachable();
1508 Value *CancelKind =
nullptr;
1509 switch (CanceledDirective) {
1510#define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) \
1511 case DirectiveEnum: \
1512 CancelKind = Builder.getInt32(Value); \
1514#include "llvm/Frontend/OpenMP/OMPKinds.def"
1531 Builder.SetInsertPoint(UI->getParent());
1532 UI->eraseFromParent();
1545 auto *KernelArgsPtr =
1546 Builder.CreateAlloca(OpenMPIRBuilder::KernelArgs,
nullptr,
"kernel_args");
1551 Builder.CreateStructGEP(OpenMPIRBuilder::KernelArgs, KernelArgsPtr,
I);
1554 M.getDataLayout().getPrefTypeAlign(KernelArgs[
I]->getType()));
1558 NumThreads, HostPtr, KernelArgsPtr};
1585 assert(OutlinedFnID &&
"Invalid outlined function ID!");
1589 Value *Return =
nullptr;
1609 Builder, AllocaIP, Return, RTLoc, DeviceID, Args.NumTeams.front(),
1610 Args.NumThreads.front(), OutlinedFnID, ArgsVector));
1617 Builder.CreateCondBr(
Failed, OffloadFailedBlock, OffloadContBlock);
1619 auto CurFn =
Builder.GetInsertBlock()->getParent();
1626 emitBlock(OffloadContBlock, CurFn,
true);
1631 Value *CancelFlag, omp::Directive CanceledDirective) {
1633 "Unexpected cancellation!");
1653 Builder.CreateCondBr(Cmp, NonCancellationBlock, CancellationBlock,
1662 Builder.SetInsertPoint(CancellationBlock);
1663 Builder.CreateBr(*FiniBBOrErr);
1666 Builder.SetInsertPoint(NonCancellationBlock, NonCancellationBlock->
begin());
1678 size_t NumArgs = OutlinedFn.
arg_size();
1679 assert((NumArgs == 2 || NumArgs == 3) &&
1680 "expected a 2-3 argument parallel outlined function");
1681 bool UseArgStruct = NumArgs == 3;
1686 {Builder.getInt16Ty(), Builder.getInt32Ty()},
1690 OutlinedFn.
getName() +
".wrapper", OMPIRBuilder->
M);
1692 WrapperFn->addParamAttr(0, Attribute::NoUndef);
1693 WrapperFn->addParamAttr(0, Attribute::ZExt);
1694 WrapperFn->addParamAttr(1, Attribute::NoUndef);
1698 Builder.SetInsertPoint(EntryBB);
1701 Value *AddrAlloca = Builder.CreateAlloca(Builder.getInt32Ty(),
1703 AddrAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1704 AddrAlloca, Builder.getPtrTy(0),
1705 AddrAlloca->
getName() +
".ascast");
1707 Value *ZeroAlloca = Builder.CreateAlloca(Builder.getInt32Ty(),
1709 ZeroAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1710 ZeroAlloca, Builder.getPtrTy(0),
1711 ZeroAlloca->
getName() +
".ascast");
1713 Value *ArgsAlloca =
nullptr;
1715 ArgsAlloca = Builder.CreateAlloca(Builder.getPtrTy(),
1716 nullptr,
"global_args");
1717 ArgsAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1718 ArgsAlloca, Builder.getPtrTy(0),
1719 ArgsAlloca->
getName() +
".ascast");
1723 Builder.CreateStore(WrapperFn->getArg(1), AddrAlloca);
1724 Builder.CreateStore(Builder.getInt32(0), ZeroAlloca);
1728 llvm::omp::RuntimeFunction::OMPRTL___kmpc_get_shared_variables),
1736 Value *StructArg = Builder.CreateLoad(Builder.getPtrTy(), ArgsAlloca);
1737 StructArg = Builder.CreateInBoundsGEP(Builder.getPtrTy(), StructArg,
1738 {Builder.getInt64(0)});
1739 StructArg = Builder.CreateLoad(Builder.getPtrTy(), StructArg,
"structArg");
1740 Args.push_back(StructArg);
1744 Builder.CreateCall(&OutlinedFn, Args);
1745 Builder.CreateRetVoid();
1760 "Expected at least tid and bounded tid as arguments");
1761 unsigned NumCapturedVars = OutlinedFn.
arg_size() - 2;
1769 OutlinedFn.
addFnAttr(Attribute::NoUnwind);
1772 assert(CI &&
"Expected call instruction to outlined function");
1773 CI->
getParent()->setName(
"omp_parallel");
1775 Builder.SetInsertPoint(CI);
1776 Type *PtrTy = OMPIRBuilder->VoidPtr;
1779 OpenMPIRBuilder ::InsertPointTy CurrentIP = Builder.saveIP();
1783 Value *Args = ArgsAlloca;
1787 Args = Builder.CreatePointerCast(ArgsAlloca, PtrTy);
1788 Builder.restoreIP(CurrentIP);
1791 for (
unsigned Idx = 0; Idx < NumCapturedVars; Idx++) {
1793 Value *StoreAddress = Builder.CreateConstInBoundsGEP2_64(
1795 Builder.CreateStore(V, StoreAddress);
1799 IfCondition ? Builder.CreateSExtOrTrunc(IfCondition, OMPIRBuilder->Int32)
1800 : Builder.getInt32(1);
1801 Value *NumThreadsArg =
1802 NumThreads ? Builder.CreateZExtOrTrunc(NumThreads, OMPIRBuilder->Int32)
1803 : Builder.getInt32(-1);
1813 Value *Parallel60CallArgs[] = {
1818 Builder.getInt32(-1),
1822 Builder.getInt64(NumCapturedVars),
1823 Builder.getInt32(0)};
1831 << *Builder.GetInsertBlock()->getParent() <<
"\n");
1834 Builder.SetInsertPoint(PrivTID);
1836 Builder.CreateStore(Builder.CreateLoad(OMPIRBuilder->Int32, OutlinedAI),
1843 I->eraseFromParent();
1866 if (!
F->hasMetadata(LLVMContext::MD_callback)) {
1874 F->addMetadata(LLVMContext::MD_callback,
1883 OutlinedFn.
addFnAttr(Attribute::NoUnwind);
1886 "Expected at least tid and bounded tid as arguments");
1887 unsigned NumCapturedVars = OutlinedFn.
arg_size() - 2;
1890 CI->
getParent()->setName(
"omp_parallel");
1891 Builder.SetInsertPoint(CI);
1894 Value *ForkCallArgs[] = {Ident, Builder.getInt32(NumCapturedVars),
1898 RealArgs.
append(std::begin(ForkCallArgs), std::end(ForkCallArgs));
1900 Value *
Cond = Builder.CreateSExtOrTrunc(IfCondition, OMPIRBuilder->Int32);
1907 auto PtrTy = OMPIRBuilder->VoidPtr;
1908 if (IfCondition && NumCapturedVars == 0) {
1916 << *Builder.GetInsertBlock()->getParent() <<
"\n");
1919 Builder.SetInsertPoint(PrivTID);
1921 Builder.CreateStore(Builder.CreateLoad(OMPIRBuilder->Int32, OutlinedAI),
1928 I->eraseFromParent();
1936 Value *NumThreads, omp::ProcBindKind ProcBind,
bool IsCancellable) {
1945 const bool NeedThreadID = NumThreads ||
Config.isTargetDevice() ||
1946 (ProcBind != OMP_PROC_BIND_default);
1953 bool ArgsInZeroAddressSpace =
Config.isTargetDevice();
1957 if (NumThreads && !
Config.isTargetDevice()) {
1960 Builder.CreateIntCast(NumThreads, Int32,
false)};
1965 if (ProcBind != OMP_PROC_BIND_default) {
1969 ConstantInt::get(Int32,
unsigned(ProcBind),
true)};
1991 Builder.CreateAlloca(Int32,
nullptr,
"zero.addr");
1994 if (ArgsInZeroAddressSpace &&
M.getDataLayout().getAllocaAddrSpace() != 0) {
1997 TIDAddrAlloca, PointerType ::get(
M.getContext(), 0),
"tid.addr.ascast");
2001 PointerType ::get(
M.getContext(), 0),
2002 "zero.addr.ascast");
2026 if (IP.getBlock()->end() == IP.getPoint()) {
2032 assert(IP.getBlock()->getTerminator()->getNumSuccessors() == 1 &&
2033 IP.getBlock()->getTerminator()->getSuccessor(0) == PRegExitBB &&
2034 "Unexpected insertion point for finalization call!");
2046 Builder.CreateAlloca(Int32,
nullptr,
"tid.addr.local");
2052 Builder.CreateLoad(Int32, ZeroAddr,
"zero.addr.use");
2070 LLVM_DEBUG(
dbgs() <<
"Before body codegen: " << *OuterFn <<
"\n");
2073 assert(BodyGenCB &&
"Expected body generation callback!");
2075 if (
Error Err = BodyGenCB(InnerAllocaIP, CodeGenIP, PRegExitBB))
2078 LLVM_DEBUG(
dbgs() <<
"After body codegen: " << *OuterFn <<
"\n");
2082 bool UsesDeviceSharedMemory =
2084 std::unique_ptr<OutlineInfo> OI =
2085 UsesDeviceSharedMemory
2086 ? std::make_unique<DeviceSharedMemOutlineInfo>(*
this)
2087 : std::make_unique<OutlineInfo>();
2089 if (
Config.isTargetDevice()) {
2091 OI->PostOutlineCB = [=, ToBeDeletedVec =
2092 std::move(ToBeDeleted)](
Function &OutlinedFn) {
2094 IfCondition, NumThreads, PrivTID, PrivTIDAddr,
2095 ThreadID, ToBeDeletedVec);
2099 OI->PostOutlineCB = [=, ToBeDeletedVec =
2100 std::move(ToBeDeleted)](
Function &OutlinedFn) {
2102 PrivTID, PrivTIDAddr, ToBeDeletedVec);
2106 OI->FixUpNonEntryAllocas =
true;
2107 OI->OuterAllocBB = OuterAllocaBlock;
2108 OI->EntryBB = PRegEntryBB;
2109 OI->ExitBB = PRegExitBB;
2110 OI->OuterDeallocBBs.reserve(OuterDeallocBlocks.
size());
2111 copy(OuterDeallocBlocks, OI->OuterDeallocBBs.
end());
2115 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
2127 ".omp_par", ArgsInZeroAddressSpace);
2132 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
2134 Extractor.findInputsOutputs(Inputs, Outputs, SinkingCands,
2139 return GV->getValueType() == OpenMPIRBuilder::Ident;
2144 LLVM_DEBUG(
dbgs() <<
"Before privatization: " << *OuterFn <<
"\n");
2150 if (&V == TIDAddr || &V == ZeroAddr) {
2151 OI->ExcludeArgsFromAggregate.push_back(&V);
2156 for (
Use &U : V.uses())
2158 if (ParallelRegionBlockSet.
count(UserI->getParent()))
2168 if (!V.getType()->isPointerTy()) {
2172 Builder.restoreIP(OuterAllocIP);
2174 if (UsesDeviceSharedMemory) {
2177 V.getName() +
".reloaded");
2178 for (
BasicBlock *DeallocBlock : OuterDeallocBlocks)
2180 InsertPointTy(DeallocBlock, DeallocBlock->getFirstInsertionPt()),
2183 Ptr =
Builder.CreateAlloca(V.getType(),
nullptr,
2184 V.getName() +
".reloaded");
2189 Builder.SetInsertPoint(InsertBB,
2194 Builder.restoreIP(InnerAllocaIP);
2195 Inner =
Builder.CreateLoad(V.getType(), Ptr);
2198 Value *ReplacementValue =
nullptr;
2201 ReplacementValue = PrivTID;
2204 PrivCB(InnerAllocaIP,
Builder.saveIP(), V, *Inner, ReplacementValue);
2212 assert(ReplacementValue &&
2213 "Expected copy/create callback to set replacement value!");
2214 if (ReplacementValue == &V)
2219 UPtr->set(ReplacementValue);
2244 for (
Value *Output : Outputs)
2248 "OpenMP outlining should not produce live-out values!");
2250 LLVM_DEBUG(
dbgs() <<
"After privatization: " << *OuterFn <<
"\n");
2252 for (
auto *BB : Blocks)
2253 dbgs() <<
" PBR: " << BB->getName() <<
"\n";
2261 assert(FiniInfo.DK == OMPD_parallel &&
2262 "Unexpected finalization stack state!");
2273 Builder.CreateBr(*FiniBBOrErr);
2277 Term->eraseFromParent();
2283 InsertPointTy AfterIP(UI->getParent(), UI->getParent()->end());
2284 UI->eraseFromParent();
2316 Value *Severity = ConstantInt::get(Int32, IsFatal ? 2 : 1);
2318 Value *Args[] = {Ident, Severity, MessageArg};
2347 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr));
2349 Builder.CreateStore(DepValPtr, Addr);
2352 DependInfo, Entry,
static_cast<unsigned int>(RTLDependInfoFields::Len));
2354 ConstantInt::get(SizeTy,
2359 DependInfo, Entry,
static_cast<unsigned int>(RTLDependInfoFields::Flags));
2361 static_cast<unsigned int>(Dep.
DepKind)),
2374 if (Dependencies.
empty())
2394 Type *DependInfo = OMPBuilder.DependInfo;
2396 Value *DepArray =
nullptr;
2398 Builder.SetInsertPoint(
2402 DepArray = Builder.CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
2404 Builder.restoreIP(OldIP);
2406 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies)) {
2408 Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
2432 Value *DepArray =
nullptr;
2433 Type *DepArrayTy =
nullptr;
2434 Value *NumDeps =
nullptr;
2437 NumDeps = Dependencies.
NumDeps;
2438 }
else if (!Dependencies.
Deps.empty()) {
2441 Builder.GetInsertBlock()->getParent()->getEntryBlock();
2445 DepArray =
Builder.CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
2446 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
2449 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies.
Deps)) {
2451 Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
2465 ConstantInt::get(
Builder.getInt32Ty(), 0),
2467 ConstantInt::get(
Builder.getInt32Ty(),
false)};
2470 omp::RuntimeFunction::OMPRTL___kmpc_omp_taskwait_deps_51),
2480 unsigned ProgramAddressSpace = M.getDataLayout().getProgramAddressSpace();
2492 auto *VoidPtrTy =
PointerType::get(Builder.getContext(), ProgramAddressSpace);
2495 Builder.getVoidTy(), {VoidPtrTy, VoidPtrTy, Builder.getInt32Ty()},
2499 "omp_taskloop_dup", M);
2502 Value *LastprivateFlagArg = DupFunction->
getArg(2);
2503 DestTaskArg->
setName(
"dest_task");
2504 SrcTaskArg->
setName(
"src_task");
2505 LastprivateFlagArg->
setName(
"lastprivate_flag");
2508 Builder.SetInsertPoint(
2511 auto GetTaskContextPtrFromArg = [&](
Value *Arg) ->
Value * {
2512 Type *TaskWithPrivatesTy =
2514 Value *TaskPrivates = Builder.CreateGEP(
2515 TaskWithPrivatesTy, Arg, {Builder.getInt32(0), Builder.getInt32(1)});
2516 Value *ContextPtr = Builder.CreateGEP(
2517 PrivatesTy, TaskPrivates,
2518 {Builder.getInt32(0), Builder.getInt32(PrivatesIndex)});
2522 Value *DestTaskContextPtr = GetTaskContextPtrFromArg(DestTaskArg);
2523 Value *SrcTaskContextPtr = GetTaskContextPtrFromArg(SrcTaskArg);
2525 DestTaskContextPtr->
setName(
"destPtr");
2526 SrcTaskContextPtr->
setName(
"srcPtr");
2531 Expected<IRBuilderBase::InsertPoint> AfterIPOrError =
2532 DupCB(AllocaIP, CodeGenIP, DestTaskContextPtr, SrcTaskContextPtr);
2533 if (!AfterIPOrError)
2535 Builder.restoreIP(*AfterIPOrError);
2545 llvm::function_ref<llvm::Expected<llvm::CanonicalLoopInfo *>()> LoopInfo,
2547 Value *GrainSize,
bool NoGroup,
int Sched,
Value *Final,
bool Mergeable,
2549 Value *TaskContextStructPtrVal) {
2554 uint32_t SrcLocStrSize;
2570 if (
Error Err = BodyGenCB(TaskloopAllocaIP, TaskloopBodyIP, TaskloopExitBB))
2573 llvm::Expected<llvm::CanonicalLoopInfo *> result = LoopInfo();
2578 llvm::CanonicalLoopInfo *CLI = result.
get();
2579 auto OI = std::make_unique<OutlineInfo>();
2580 OI->EntryBB = TaskloopAllocaBB;
2581 OI->OuterAllocBB = AllocaIP.getBlock();
2582 OI->ExitBB = TaskloopExitBB;
2583 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2584 copy(DeallocBlocks, OI->OuterDeallocBBs.end());
2587 SmallVector<Instruction *> ToBeDeleted;
2590 Builder, AllocaIP, ToBeDeleted, TaskloopAllocaIP,
"global.tid",
false));
2592 TaskloopAllocaIP,
"lb",
false,
true);
2594 TaskloopAllocaIP,
"ub",
false,
true);
2596 TaskloopAllocaIP,
"step",
false,
true);
2599 OI->Inputs.insert(FakeLB);
2600 OI->Inputs.insert(FakeUB);
2601 OI->Inputs.insert(FakeStep);
2602 if (TaskContextStructPtrVal)
2603 OI->Inputs.insert(TaskContextStructPtrVal);
2604 assert(((TaskContextStructPtrVal && DupCB) ||
2605 (!TaskContextStructPtrVal && !DupCB)) &&
2606 "Task context struct ptr and duplication callback must be both set "
2612 unsigned ProgramAddressSpace =
M.getDataLayout().getProgramAddressSpace();
2616 {FakeLB->getType(), FakeUB->getType(), FakeStep->getType(), PointerTy});
2617 Expected<Value *> TaskDupFnOrErr = createTaskDuplicationFunction(
2620 if (!TaskDupFnOrErr) {
2623 Value *TaskDupFn = *TaskDupFnOrErr;
2625 OI->PostOutlineCB = [
this, Ident, LBVal, UBVal, StepVal, Untied,
2626 TaskloopAllocaBB, CLI, TaskDupFn, ToBeDeleted, IfCond,
2627 GrainSize, NoGroup, Sched, FakeLB, FakeUB, FakeStep,
2628 FakeSharedsTy, Final, Mergeable, Priority,
2629 NumOfCollapseLoops](
Function &OutlinedFn)
mutable {
2631 assert(OutlinedFn.hasOneUse() &&
2632 "there must be a single user for the outlined function");
2639 Value *CastedLBVal =
2640 Builder.CreateIntCast(LBVal,
Builder.getInt64Ty(),
true,
"lb64");
2641 Value *CastedUBVal =
2642 Builder.CreateIntCast(UBVal,
Builder.getInt64Ty(),
true,
"ub64");
2643 Value *CastedStepVal =
2644 Builder.CreateIntCast(StepVal,
Builder.getInt64Ty(),
true,
"step64");
2646 Builder.SetInsertPoint(StaleCI);
2659 Builder.CreateCall(TaskgroupFn, {Ident, ThreadID});
2680 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
2682 AllocaInst *ArgStructAlloca =
2684 assert(ArgStructAlloca &&
2685 "Unable to find the alloca instruction corresponding to arguments "
2686 "for extracted function");
2687 std::optional<TypeSize> ArgAllocSize =
2690 "Unable to determine size of arguments for extracted function");
2691 Value *SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
2696 CallInst *TaskData =
Builder.CreateCall(
2697 TaskAllocFn, {Ident, ThreadID,
Flags,
2698 TaskSize, SharedsSize,
2703 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
2704 Builder.CreateMemCpy(TaskShareds, Alignment, Shareds, Alignment,
2709 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(0)});
2712 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(1)});
2715 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(2)});
2721 IfCond ?
Builder.CreateIntCast(IfCond,
Builder.getInt32Ty(),
true)
2727 Value *GrainSizeVal =
2728 GrainSize ?
Builder.CreateIntCast(GrainSize,
Builder.getInt64Ty(),
true)
2730 Value *TaskDup = TaskDupFn;
2732 Value *
Args[] = {Ident, ThreadID, TaskData, IfCondVal, Lb, Ub,
2733 Loadstep, NoGroupVal, SchedVal, GrainSizeVal, TaskDup};
2738 Builder.CreateCall(TaskloopFn, Args);
2745 Builder.CreateCall(EndTaskgroupFn, {Ident, ThreadID});
2750 Builder.SetInsertPoint(TaskloopAllocaBB, TaskloopAllocaBB->begin());
2752 LoadInst *SharedsOutlined =
2753 Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
2754 OutlinedFn.getArg(1)->replaceUsesWithIf(
2756 [SharedsOutlined](Use &U) {
return U.getUser() != SharedsOutlined; });
2759 Type *IVTy =
IV->getType();
2765 Value *TaskLB =
nullptr;
2766 Value *TaskUB =
nullptr;
2767 Value *TaskStep =
nullptr;
2768 Value *LoadTaskLB =
nullptr;
2769 Value *LoadTaskUB =
nullptr;
2770 Value *LoadTaskStep =
nullptr;
2771 for (Instruction &
I : *TaskloopAllocaBB) {
2772 if (
I.getOpcode() == Instruction::GetElementPtr) {
2775 switch (CI->getZExtValue()) {
2787 }
else if (
I.getOpcode() == Instruction::Load) {
2789 if (
Load.getPointerOperand() == TaskLB) {
2790 assert(TaskLB !=
nullptr &&
"Expected value for TaskLB");
2792 }
else if (
Load.getPointerOperand() == TaskUB) {
2793 assert(TaskUB !=
nullptr &&
"Expected value for TaskUB");
2795 }
else if (
Load.getPointerOperand() == TaskStep) {
2796 assert(TaskStep !=
nullptr &&
"Expected value for TaskStep");
2802 Builder.SetInsertPoint(CLI->getPreheader()->getTerminator());
2804 assert(LoadTaskLB !=
nullptr &&
"Expected value for LoadTaskLB");
2805 assert(LoadTaskUB !=
nullptr &&
"Expected value for LoadTaskUB");
2806 assert(LoadTaskStep !=
nullptr &&
"Expected value for LoadTaskStep");
2808 Builder.CreateSub(LoadTaskUB, LoadTaskLB), LoadTaskStep);
2809 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One,
"trip_cnt");
2810 Value *CastedTripCount =
Builder.CreateIntCast(TripCount, IVTy,
true);
2811 Value *CastedTaskLB =
Builder.CreateIntCast(LoadTaskLB, IVTy,
true);
2813 CLI->setTripCount(CastedTripCount);
2815 Builder.SetInsertPoint(CLI->getBody(),
2816 CLI->getBody()->getFirstInsertionPt());
2818 if (NumOfCollapseLoops > 1) {
2824 Builder.CreateSub(CastedTaskLB, ConstantInt::get(IVTy, 1)));
2827 for (
auto IVUse = CLI->getIndVar()->uses().begin();
2828 IVUse != CLI->getIndVar()->uses().end(); IVUse++) {
2829 User *IVUser = IVUse->getUser();
2831 if (
Op->getOpcode() == Instruction::URem ||
2832 Op->getOpcode() == Instruction::UDiv) {
2837 for (User *User : UsersToReplace) {
2838 User->replaceUsesOfWith(CLI->getIndVar(), IVPlusTaskLB);
2855 assert(CLI->getIndVar()->getNumUses() == 3 &&
2856 "Canonical loop should have exactly three uses of the ind var");
2857 for (User *IVUser : CLI->getIndVar()->users()) {
2859 if (
Mul->getOpcode() == Instruction::Mul) {
2860 for (User *MulUser :
Mul->users()) {
2862 if (
Add->getOpcode() == Instruction::Add) {
2863 Add->setOperand(1, CastedTaskLB);
2872 FakeLB->replaceAllUsesWith(CastedLBVal);
2873 FakeUB->replaceAllUsesWith(CastedUBVal);
2874 FakeStep->replaceAllUsesWith(CastedStepVal);
2876 I->eraseFromParent();
2881 Builder.SetInsertPoint(TaskloopExitBB, TaskloopExitBB->
begin());
2887 M.getContext(),
M.getDataLayout().getPointerSizeInBits());
2897 bool Mergeable,
Value *EventHandle,
Value *Priority) {
2929 if (
Error Err = BodyGenCB(TaskAllocaIP, TaskBodyIP, TaskExitBB))
2932 auto OI = std::make_unique<OutlineInfo>();
2933 OI->EntryBB = TaskAllocaBB;
2934 OI->OuterAllocBB = AllocaIP.
getBlock();
2935 OI->ExitBB = TaskExitBB;
2936 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2937 copy(DeallocBlocks, OI->OuterDeallocBBs.
end());
2942 Builder, AllocaIP, ToBeDeleted, TaskAllocaIP,
"global.tid",
false));
2944 OI->PostOutlineCB = [
this, Ident, Tied, Final, IfCondition, Dependencies,
2945 Affinities, Mergeable, Priority, EventHandle,
2947 ToBeDeleted](
Function &OutlinedFn)
mutable {
2949 assert(OutlinedFn.hasOneUse() &&
2950 "there must be a single user for the outlined function");
2955 bool HasShareds = StaleCI->
arg_size() > 1;
2956 Builder.SetInsertPoint(StaleCI);
2981 bool UseMergedIf0Path = ConstIfCondition && ConstIfCondition->isZero();
2985 Flags =
Builder.CreateOr(FinalFlag, Flags);
2988 if (Mergeable || UseMergedIf0Path)
3000 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
3009 assert(ArgStructAlloca &&
3010 "Unable to find the alloca instruction corresponding to arguments "
3011 "for extracted function");
3012 std::optional<TypeSize> ArgAllocSize =
3015 "Unable to determine size of arguments for extracted function");
3016 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
3022 TaskAllocFn, {Ident, ThreadID, Flags,
3023 TaskSize, SharedsSize,
3026 if (Affinities.
Count && Affinities.
Info) {
3028 OMPRTL___kmpc_omp_reg_task_with_affinity);
3039 OMPRTL___kmpc_task_allow_completion_event);
3043 Builder.CreatePointerBitCastOrAddrSpaceCast(EventHandle,
3045 EventVal =
Builder.CreatePtrToInt(EventVal,
Builder.getInt64Ty());
3046 Builder.CreateStore(EventVal, EventHandleAddr);
3052 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
3053 Builder.CreateMemCpy(TaskShareds, Alignment, Shareds, Alignment,
3067 Constant *Zero = ConstantInt::get(Int32Ty, 0);
3071 Builder.CreateInBoundsGEP(TaskPtr, TaskData, {Zero, Zero});
3074 VoidPtr, VoidPtr,
Builder.getInt32Ty(), VoidPtr, VoidPtr);
3076 TaskStructType, TaskGEP, {Zero, ConstantInt::get(Int32Ty, 4)});
3079 Value *CmplrData =
Builder.CreateInBoundsGEP(CmplrStructType,
3080 PriorityData, {Zero, Zero});
3081 Builder.CreateStore(Priority, CmplrData);
3084 Value *DepArray =
nullptr;
3085 Value *NumDeps =
nullptr;
3088 NumDeps = Dependencies.
NumDeps;
3089 }
else if (!Dependencies.
Deps.empty()) {
3091 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
3111 if (IfCondition && !UseMergedIf0Path) {
3116 Builder.GetInsertPoint()->getParent()->getTerminator();
3117 Instruction *ThenTI = IfTerminator, *ElseTI =
nullptr;
3118 Builder.SetInsertPoint(IfTerminator);
3121 Builder.SetInsertPoint(ElseTI);
3128 {Ident, ThreadID, NumDeps, DepArray,
3129 ConstantInt::get(
Builder.getInt32Ty(), 0),
3144 Builder.SetInsertPoint(ThenTI);
3152 {Ident, ThreadID, TaskData, NumDeps, DepArray,
3153 ConstantInt::get(
Builder.getInt32Ty(), 0),
3164 Builder.SetInsertPoint(TaskAllocaBB, TaskAllocaBB->
begin());
3166 LoadInst *Shareds =
Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
3167 OutlinedFn.getArg(1)->replaceUsesWithIf(
3168 Shareds, [Shareds](
Use &U) {
return U.getUser() != Shareds; });
3172 I->eraseFromParent();
3176 Builder.SetInsertPoint(TaskExitBB, TaskExitBB->
begin());
3198 if (
Error Err = BodyGenCB(AllocaIP,
Builder.saveIP(), DeallocBlocks))
3201 Builder.SetInsertPoint(TaskgroupExitBB);
3244 unsigned CaseNumber = 0;
3245 for (
auto SectionCB : SectionCBs) {
3247 M.getContext(),
"omp_section_loop.body.case", CurFn,
Continue);
3249 Builder.SetInsertPoint(CaseBB);
3264 Value *LB = ConstantInt::get(I32Ty, 0);
3265 Value *UB = ConstantInt::get(I32Ty, SectionCBs.
size());
3266 Value *ST = ConstantInt::get(I32Ty, 1);
3268 Loc, LoopBodyGenCB, LB, UB, ST,
true,
false, AllocaIP,
"section_loop");
3273 applyStaticWorkshareLoop(
Loc.DL, *
LoopInfo, AllocaIP,
3274 WorksharingLoopType::ForStaticLoop, !IsNowait);
3280 assert(LoopFini &&
"Bad structure of static workshare loop finalization");
3284 assert(FiniInfo.DK == OMPD_sections &&
3285 "Unexpected finalization stack state!");
3286 if (
Error Err = FiniInfo.mergeFiniBB(
Builder, LoopFini))
3300 if (IP.getBlock()->end() != IP.getPoint())
3311 auto *CaseBB =
Loc.IP.getBlock();
3312 auto *CondBB = CaseBB->getSinglePredecessor()->getSinglePredecessor();
3313 auto *ExitBB = CondBB->getTerminator()->getSuccessor(1);
3319 Directive OMPD = Directive::OMPD_sections;
3322 return EmitOMPInlinedRegion(OMPD,
nullptr,
nullptr, BodyGenCB, FiniCBWrapper,
3333Value *OpenMPIRBuilder::getGPUThreadID() {
3336 OMPRTL___kmpc_get_hardware_thread_id_in_block),
3340Value *OpenMPIRBuilder::getGPUWarpSize() {
3345Value *OpenMPIRBuilder::getNVPTXWarpID() {
3346 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3347 return Builder.CreateAShr(getGPUThreadID(), LaneIDBits,
"nvptx_warp_id");
3350Value *OpenMPIRBuilder::getNVPTXLaneID() {
3351 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3352 assert(LaneIDBits < 32 &&
"Invalid LaneIDBits size in NVPTX device.");
3353 unsigned LaneIDMask = ~0
u >> (32u - LaneIDBits);
3354 return Builder.CreateAnd(getGPUThreadID(),
Builder.getInt32(LaneIDMask),
3361 uint64_t FromSize =
M.getDataLayout().getTypeStoreSize(FromType);
3362 uint64_t ToSize =
M.getDataLayout().getTypeStoreSize(ToType);
3363 assert(FromSize > 0 &&
"From size must be greater than zero");
3364 assert(ToSize > 0 &&
"To size must be greater than zero");
3365 if (FromType == ToType)
3367 if (FromSize == ToSize)
3368 return Builder.CreateBitCast(From, ToType);
3370 return Builder.CreateIntCast(From, ToType,
true);
3376 Value *ValCastItem =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3377 CastItem,
Builder.getPtrTy(0));
3378 Builder.CreateStore(From, ValCastItem);
3379 return Builder.CreateLoad(ToType, CastItem);
3386 uint64_t
Size =
M.getDataLayout().getTypeStoreSize(ElementType);
3387 assert(
Size <= 8 &&
"Unsupported bitwidth in shuffle instruction");
3391 Value *ElemCast = castValueToType(AllocaIP, Element, CastTy);
3393 Builder.CreateIntCast(getGPUWarpSize(),
Builder.getInt16Ty(),
true);
3395 Size <= 4 ? RuntimeFunction::OMPRTL___kmpc_shuffle_int32
3396 : RuntimeFunction::OMPRTL___kmpc_shuffle_int64);
3397 Value *WarpSizeCast =
3399 Value *ShuffleCall =
3404 return castValueToType(AllocaIP, ShuffleCall, ElementType);
3411 uint64_t
Size =
M.getDataLayout().getTypeStoreSize(ElemType);
3423 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3424 Value *ElemPtr = DstAddr;
3425 Value *Ptr = SrcAddr;
3426 for (
unsigned IntSize = 8; IntSize >= 1; IntSize /= 2) {
3430 Ptr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3433 Builder.CreateGEP(ElemType, SrcAddr, {ConstantInt::get(IndexTy, 1)});
3434 ElemPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3438 if ((
Size / IntSize) > 1) {
3439 Value *PtrEnd =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3440 SrcAddrGEP,
Builder.getPtrTy());
3457 Builder.CreatePointerBitCastOrAddrSpaceCast(Ptr,
Builder.getPtrTy()));
3459 Builder.CreateICmpSGT(PtrDiff,
Builder.getInt64(IntSize - 1)), ThenBB,
3462 Value *Res = createRuntimeShuffleFunction(
3465 IntType, Ptr,
M.getDataLayout().getPrefTypeAlign(ElemType)),
3467 Builder.CreateAlignedStore(Res, ElemPtr,
3468 M.getDataLayout().getPrefTypeAlign(ElemType));
3470 Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3471 Value *LocalElemPtr =
3472 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3480 Value *Res = createRuntimeShuffleFunction(
3481 AllocaIP,
Builder.CreateLoad(IntType, Ptr), IntType,
Offset);
3482 Builder.CreateStore(Res, ElemPtr);
3483 Ptr =
Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3485 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3491Error OpenMPIRBuilder::emitReductionListCopy(
3496 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3497 Value *RemoteLaneOffset = CopyOptions.RemoteLaneOffset;
3501 for (
auto En :
enumerate(ReductionInfos)) {
3503 Value *SrcElementAddr =
nullptr;
3504 AllocaInst *DestAlloca =
nullptr;
3505 Value *DestElementAddr =
nullptr;
3506 Value *DestElementPtrAddr =
nullptr;
3508 bool ShuffleInElement =
false;
3511 bool UpdateDestListPtr =
false;
3515 ReductionArrayTy, SrcBase,
3516 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3517 SrcElementAddr =
Builder.CreateLoad(
Builder.getPtrTy(), SrcElementPtrAddr);
3521 DestElementPtrAddr =
Builder.CreateInBoundsGEP(
3522 ReductionArrayTy, DestBase,
3523 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3524 bool IsByRefElem = (!IsByRef.
empty() && IsByRef[En.index()]);
3530 Type *DestAllocaType =
3531 IsByRefElem ? RI.ByRefAllocatedType : RI.ElementType;
3532 DestAlloca =
Builder.CreateAlloca(DestAllocaType,
nullptr,
3533 ".omp.reduction.element");
3535 M.getDataLayout().getPrefTypeAlign(DestAllocaType));
3536 DestElementAddr = DestAlloca;
3539 DestElementAddr->
getName() +
".ascast");
3541 ShuffleInElement =
true;
3542 UpdateDestListPtr =
true;
3554 if (ShuffleInElement) {
3555 Type *ShuffleType = RI.ElementType;
3556 Value *ShuffleSrcAddr = SrcElementAddr;
3557 Value *ShuffleDestAddr = DestElementAddr;
3558 AllocaInst *LocalStorage =
nullptr;
3561 assert(RI.ByRefElementType &&
"Expected by-ref element type to be set");
3562 assert(RI.ByRefAllocatedType &&
3563 "Expected by-ref allocated type to be set");
3568 ShuffleType = RI.ByRefElementType;
3570 if (RI.DataPtrPtrGen) {
3573 Builder.saveIP(), ShuffleSrcAddr, ShuffleSrcAddr);
3576 return GenResult.takeError();
3585 LocalStorage =
Builder.CreateAlloca(ShuffleType);
3587 ShuffleDestAddr = LocalStorage;
3592 ShuffleDestAddr = DestElementAddr;
3596 shuffleAndStore(AllocaIP, ShuffleSrcAddr, ShuffleDestAddr, ShuffleType,
3597 RemoteLaneOffset, ReductionArrayTy, IsByRefElem);
3599 if (IsByRefElem && RI.DataPtrPtrGen) {
3601 Value *DestDescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3602 DestAlloca,
Builder.getPtrTy(),
".ascast");
3605 DestDescriptorAddr, LocalStorage, SrcElementAddr,
3606 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
3609 return GenResult.takeError();
3612 switch (RI.EvaluationKind) {
3614 Value *Elem =
Builder.CreateLoad(RI.ElementType, SrcElementAddr);
3616 Builder.CreateStore(Elem, DestElementAddr);
3620 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3621 RI.ElementType, SrcElementAddr, 0, 0,
".realp");
3623 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
3625 RI.ElementType, SrcElementAddr, 0, 1,
".imagp");
3627 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
3629 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3630 RI.ElementType, DestElementAddr, 0, 0,
".realp");
3631 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
3632 RI.ElementType, DestElementAddr, 0, 1,
".imagp");
3633 Builder.CreateStore(SrcReal, DestRealPtr);
3634 Builder.CreateStore(SrcImg, DestImgPtr);
3639 M.getDataLayout().getTypeStoreSize(RI.ElementType));
3641 DestElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3642 SrcElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3654 if (UpdateDestListPtr) {
3655 Value *CastDestAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3656 DestElementAddr,
Builder.getPtrTy(),
3657 DestElementAddr->
getName() +
".ascast");
3658 Builder.CreateStore(CastDestAddr, DestElementPtrAddr);
3665Expected<Function *> OpenMPIRBuilder::emitInterWarpCopyFunction(
3668 IRBuilder<>::InsertPointGuard IPG(
Builder);
3669 LLVMContext &Ctx =
M.getContext();
3671 Builder.getVoidTy(), {Builder.getPtrTy(), Builder.getInt32Ty()},
3675 "_omp_reduction_inter_warp_copy_func", &
M);
3681 Builder.SetInsertPoint(EntryBB);
3699 StringRef TransferMediumName =
3700 "__openmp_nvptx_data_transfer_temporary_storage";
3701 GlobalVariable *TransferMedium =
M.getGlobalVariable(TransferMediumName);
3702 unsigned WarpSize =
Config.getGridValue().GV_Warp_Size;
3704 if (!TransferMedium) {
3705 TransferMedium =
new GlobalVariable(
3713 Value *GPUThreadID = getGPUThreadID();
3715 Value *LaneID = getNVPTXLaneID();
3717 Value *WarpID = getNVPTXWarpID();
3721 Builder.GetInsertBlock()->getFirstInsertionPt());
3725 AllocaInst *ReduceListAlloca =
Builder.CreateAlloca(
3726 Arg0Type,
nullptr, ReduceListArg->
getName() +
".addr");
3727 AllocaInst *NumWarpsAlloca =
3728 Builder.CreateAlloca(Arg1Type,
nullptr, NumWarpsArg->
getName() +
".addr");
3729 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3730 ReduceListAlloca, Arg0Type, ReduceListAlloca->
getName() +
".ascast");
3731 Value *NumWarpsAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3732 NumWarpsAlloca,
Builder.getPtrTy(0),
3733 NumWarpsAlloca->
getName() +
".ascast");
3734 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
3735 Builder.CreateStore(NumWarpsArg, NumWarpsAddrCast);
3744 for (
auto En :
enumerate(ReductionInfos)) {
3750 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
3751 unsigned RealTySize =
M.getDataLayout().getTypeAllocSize(
3752 IsByRefElem ? RI.ByRefElementType : RI.ElementType);
3753 for (
unsigned TySize = 4; TySize > 0 && RealTySize > 0; TySize /= 2) {
3756 unsigned NumIters = RealTySize / TySize;
3759 Value *Cnt =
nullptr;
3760 Value *CntAddr =
nullptr;
3767 Builder.CreateAlloca(
Builder.getInt32Ty(),
nullptr,
".cnt.addr");
3769 CntAddr =
Builder.CreateAddrSpaceCast(CntAddr,
Builder.getPtrTy(),
3770 CntAddr->
getName() +
".ascast");
3782 Cnt, ConstantInt::get(
Builder.getInt32Ty(), NumIters));
3783 Builder.CreateCondBr(Cmp, BodyBB, ExitBB);
3790 omp::Directive::OMPD_unknown,
3794 return BarrierIP1.takeError();
3800 Value *IsWarpMaster =
Builder.CreateIsNull(LaneID,
"warp_master");
3801 Builder.CreateCondBr(IsWarpMaster, ThenBB, ElseBB);
3805 auto *RedListArrayTy =
3808 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3810 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3811 {ConstantInt::get(IndexTy, 0),
3812 ConstantInt::get(IndexTy, En.index())});
3816 if (IsByRefElem && RI.DataPtrPtrGen) {
3818 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
3821 return GenRes.takeError();
3832 ArrayTy, TransferMedium, {
Builder.getInt64(0), WarpID});
3837 Builder.CreateStore(Elem, MediumPtr,
3849 omp::Directive::OMPD_unknown,
3853 return BarrierIP2.takeError();
3860 Value *NumWarpsVal =
3863 Value *IsActiveThread =
3864 Builder.CreateICmpULT(GPUThreadID, NumWarpsVal,
"is_active_thread");
3865 Builder.CreateCondBr(IsActiveThread, W0ThenBB, W0ElseBB);
3872 ArrayTy, TransferMedium, {
Builder.getInt64(0), GPUThreadID});
3874 Value *TargetElemPtrPtr =
3875 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3876 {ConstantInt::get(IndexTy, 0),
3877 ConstantInt::get(IndexTy, En.index())});
3878 Value *TargetElemPtrVal =
3880 Value *TargetElemPtr = TargetElemPtrVal;
3882 if (IsByRefElem && RI.DataPtrPtrGen) {
3884 RI.DataPtrPtrGen(
Builder.saveIP(), TargetElemPtr, TargetElemPtr);
3887 return GenRes.takeError();
3889 TargetElemPtr =
Builder.CreateLoad(
Builder.getPtrTy(), TargetElemPtr);
3897 Value *SrcMediumValue =
3898 Builder.CreateLoad(CType, SrcMediumPtrVal,
true);
3899 Builder.CreateStore(SrcMediumValue, TargetElemPtr);
3909 Cnt, ConstantInt::get(
Builder.getInt32Ty(), 1));
3910 Builder.CreateStore(Cnt, CntAddr,
false);
3912 auto *CurFn =
Builder.GetInsertBlock()->getParent();
3916 RealTySize %= TySize;
3925Expected<Function *> OpenMPIRBuilder::emitShuffleAndReduceFunction(
3928 LLVMContext &Ctx =
M.getContext();
3929 IRBuilder<>::InsertPointGuard IPG(
Builder);
3930 FunctionType *FuncTy =
3932 {Builder.getPtrTy(), Builder.getInt16Ty(),
3933 Builder.getInt16Ty(), Builder.getInt16Ty()},
3937 "_omp_reduction_shuffle_and_reduce_func", &
M);
3948 Builder.SetInsertPoint(EntryBB);
3960 Type *ReduceListArgType = ReduceListArg->
getType();
3964 ReduceListArgType,
nullptr, ReduceListArg->
getName() +
".addr");
3965 Value *LaneIdAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
3966 LaneIDArg->
getName() +
".addr");
3968 LaneIDArgType,
nullptr, RemoteLaneOffsetArg->
getName() +
".addr");
3969 Value *AlgoVerAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
3970 AlgoVerArg->
getName() +
".addr");
3977 RedListArrayTy,
nullptr,
".omp.reduction.remote_reduce_list");
3979 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3980 ReduceListAlloca, ReduceListArgType,
3981 ReduceListAlloca->
getName() +
".ascast");
3982 Value *LaneIdAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3983 LaneIdAlloca, LaneIDArgPtrType, LaneIdAlloca->
getName() +
".ascast");
3984 Value *RemoteLaneOffsetAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3985 RemoteLaneOffsetAlloca, LaneIDArgPtrType,
3986 RemoteLaneOffsetAlloca->
getName() +
".ascast");
3987 Value *AlgoVerAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3988 AlgoVerAlloca, LaneIDArgPtrType, AlgoVerAlloca->
getName() +
".ascast");
3989 Value *RemoteListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3990 RemoteReductionListAlloca,
Builder.getPtrTy(),
3991 RemoteReductionListAlloca->
getName() +
".ascast");
3993 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
3994 Builder.CreateStore(LaneIDArg, LaneIdAddrCast);
3995 Builder.CreateStore(RemoteLaneOffsetArg, RemoteLaneOffsetAddrCast);
3996 Builder.CreateStore(AlgoVerArg, AlgoVerAddrCast);
3998 Value *ReduceList =
Builder.CreateLoad(ReduceListArgType, ReduceListAddrCast);
3999 Value *LaneId =
Builder.CreateLoad(LaneIDArgType, LaneIdAddrCast);
4000 Value *RemoteLaneOffset =
4001 Builder.CreateLoad(LaneIDArgType, RemoteLaneOffsetAddrCast);
4002 Value *AlgoVer =
Builder.CreateLoad(LaneIDArgType, AlgoVerAddrCast);
4009 Error EmitRedLsCpRes = emitReductionListCopy(
4011 ReduceList, RemoteListAddrCast, IsByRef,
4012 {RemoteLaneOffset,
nullptr,
nullptr});
4015 return EmitRedLsCpRes;
4040 Value *LaneComp =
Builder.CreateICmpULT(LaneId, RemoteLaneOffset);
4045 Value *Algo2AndLaneIdComp =
Builder.CreateAnd(Algo2, LaneIdComp);
4046 Value *RemoteOffsetComp =
4048 Value *CondAlgo2 =
Builder.CreateAnd(Algo2AndLaneIdComp, RemoteOffsetComp);
4049 Value *CA0OrCA1 =
Builder.CreateOr(CondAlgo0, CondAlgo1);
4050 Value *CondReduce =
Builder.CreateOr(CA0OrCA1, CondAlgo2);
4056 Builder.CreateCondBr(CondReduce, ThenBB, ElseBB);
4058 Value *LocalReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4059 ReduceList,
Builder.getPtrTy());
4060 Value *RemoteReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4061 RemoteListAddrCast,
Builder.getPtrTy());
4063 ->addFnAttr(Attribute::NoUnwind);
4074 Value *LaneIdGtOffset =
Builder.CreateICmpUGE(LaneId, RemoteLaneOffset);
4075 Value *CondCopy =
Builder.CreateAnd(Algo1, LaneIdGtOffset);
4080 Builder.CreateCondBr(CondCopy, CpyThenBB, CpyElseBB);
4084 EmitRedLsCpRes = emitReductionListCopy(
4086 RemoteListAddrCast, ReduceList, IsByRef);
4089 return EmitRedLsCpRes;
4104OpenMPIRBuilder::generateReductionDescriptor(
4106 Type *DescriptorType,
4112 Value *DescriptorSize =
4113 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(DescriptorType));
4115 DescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4116 SrcDescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4120 Value *DataPtrField;
4122 DataPtrPtrGen(
Builder.saveIP(), DescriptorAddr, DataPtrField);
4125 return GenResult.takeError();
4128 DataPtr,
Builder.getPtrTy(),
".ascast"),
4134Expected<Value *> OpenMPIRBuilder::createReductionDescriptorCopy(
4136 Value *SrcDescriptorAddr,
Type *DescriptorPtrTy,
const Twine &Name) {
4140 AllocaInst *DescriptorAlloca =
4141 Builder.CreateAlloca(RI.ByRefAllocatedType,
nullptr, Name);
4143 M.getDataLayout().getPrefTypeAlign(RI.ByRefAllocatedType));
4144 Value *DescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4145 DescriptorAlloca, DescriptorPtrTy,
4146 DescriptorAlloca->
getName() +
".ascast");
4151 generateReductionDescriptor(DescriptorAddr, DataPtr, SrcDescriptorAddr,
4152 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
4154 return GenResult.takeError();
4156 return DescriptorAddr;
4159Expected<Function *> OpenMPIRBuilder::emitListToGlobalCopyFunction(
4162 IRBuilder<>::InsertPointGuard IPG(
Builder);
4163 LLVMContext &Ctx =
M.getContext();
4166 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4170 "_omp_reduction_list_to_global_copy_func", &
M);
4177 Builder.SetInsertPoint(EntryBlock);
4188 BufferArg->
getName() +
".addr");
4192 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4193 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4194 BufferArgAlloca,
Builder.getPtrTy(),
4195 BufferArgAlloca->
getName() +
".ascast");
4196 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4197 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4198 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4199 ReduceListArgAlloca,
Builder.getPtrTy(),
4200 ReduceListArgAlloca->
getName() +
".ascast");
4202 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4203 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4204 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4206 Value *LocalReduceList =
4208 Value *BufferArgVal =
4212 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4213 for (
auto En :
enumerate(ReductionInfos)) {
4215 auto *RedListArrayTy =
4219 RedListArrayTy, LocalReduceList,
4220 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4226 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferArgVal, Idxs);
4228 ReductionsBufferTy, BufferVD, 0, En.index());
4230 switch (RI.EvaluationKind) {
4232 Value *TargetElement;
4234 if (IsByRef.
empty() || !IsByRef[En.index()]) {
4235 TargetElement =
Builder.CreateLoad(RI.ElementType, ElemPtr);
4237 if (RI.DataPtrPtrGen) {
4239 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
4242 return GenResult.takeError();
4246 TargetElement =
Builder.CreateLoad(RI.ByRefElementType, ElemPtr);
4249 Builder.CreateStore(TargetElement, GlobVal);
4253 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4254 RI.ElementType, ElemPtr, 0, 0,
".realp");
4256 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
4258 RI.ElementType, ElemPtr, 0, 1,
".imagp");
4260 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
4262 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4263 RI.ElementType, GlobVal, 0, 0,
".realp");
4264 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4265 RI.ElementType, GlobVal, 0, 1,
".imagp");
4266 Builder.CreateStore(SrcReal, DestRealPtr);
4267 Builder.CreateStore(SrcImg, DestImgPtr);
4272 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(RI.ElementType));
4274 GlobVal,
M.getDataLayout().getPrefTypeAlign(RI.ElementType), ElemPtr,
4275 M.getDataLayout().getPrefTypeAlign(RI.ElementType), SizeVal,
false);
4285Expected<Function *> OpenMPIRBuilder::emitListToGlobalReduceFunction(
4288 IRBuilder<>::InsertPointGuard IPG(
Builder);
4289 LLVMContext &Ctx =
M.getContext();
4292 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4296 "_omp_reduction_list_to_global_reduce_func", &
M);
4303 Builder.SetInsertPoint(EntryBlock);
4314 BufferArg->
getName() +
".addr");
4318 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4319 auto *RedListArrayTy =
4324 Value *LocalReduceList =
4325 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4329 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4330 BufferArgAlloca,
Builder.getPtrTy(),
4331 BufferArgAlloca->
getName() +
".ascast");
4332 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4333 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4334 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4335 ReduceListArgAlloca,
Builder.getPtrTy(),
4336 ReduceListArgAlloca->
getName() +
".ascast");
4337 Value *LocalReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4338 LocalReduceList,
Builder.getPtrTy(),
4339 LocalReduceList->
getName() +
".ascast");
4341 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4342 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4343 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4348 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4349 for (
auto En :
enumerate(ReductionInfos)) {
4352 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4353 RedListArrayTy, LocalReduceListAddrCast,
4354 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4356 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4358 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4359 ReductionsBufferTy, BufferVD, 0, En.index());
4361 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4365 Value *SrcElementPtrPtr =
4366 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
4367 {ConstantInt::get(IndexTy, 0),
4368 ConstantInt::get(IndexTy, En.index())});
4369 Value *SrcDescriptorAddr =
4373 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4374 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4378 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4380 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4388 ->addFnAttr(Attribute::NoUnwind);
4393Expected<Function *> OpenMPIRBuilder::emitGlobalToListCopyFunction(
4396 IRBuilder<>::InsertPointGuard IPG(
Builder);
4397 LLVMContext &Ctx =
M.getContext();
4400 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4404 "_omp_reduction_global_to_list_copy_func", &
M);
4411 Builder.SetInsertPoint(EntryBlock);
4422 BufferArg->
getName() +
".addr");
4426 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4427 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4428 BufferArgAlloca,
Builder.getPtrTy(),
4429 BufferArgAlloca->
getName() +
".ascast");
4430 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4431 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4432 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4433 ReduceListArgAlloca,
Builder.getPtrTy(),
4434 ReduceListArgAlloca->
getName() +
".ascast");
4435 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4436 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4437 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4439 Value *LocalReduceList =
4444 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4445 for (
auto En :
enumerate(ReductionInfos)) {
4446 const OpenMPIRBuilder::ReductionInfo &RI = En.value();
4447 auto *RedListArrayTy =
4451 RedListArrayTy, LocalReduceList,
4452 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4457 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4458 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4459 ReductionsBufferTy, BufferVD, 0, En.index());
4465 if (!IsByRef.
empty() && IsByRef[En.index()]) {
4472 return GenResult.takeError();
4478 Value *TargetElement =
Builder.CreateLoad(ElemType, GlobValPtr);
4479 Builder.CreateStore(TargetElement, ElemPtr);
4483 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4492 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4494 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4496 Builder.CreateStore(SrcReal, DestRealPtr);
4497 Builder.CreateStore(SrcImg, DestImgPtr);
4504 ElemPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4505 GlobValPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4516Expected<Function *> OpenMPIRBuilder::emitGlobalToListReduceFunction(
4519 IRBuilder<>::InsertPointGuard IPG(
Builder);
4520 LLVMContext &Ctx =
M.getContext();
4523 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4527 "_omp_reduction_global_to_list_reduce_func", &
M);
4534 Builder.SetInsertPoint(EntryBlock);
4545 BufferArg->
getName() +
".addr");
4549 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4555 Value *LocalReduceList =
4556 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4560 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4561 BufferArgAlloca,
Builder.getPtrTy(),
4562 BufferArgAlloca->
getName() +
".ascast");
4563 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4564 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4565 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4566 ReduceListArgAlloca,
Builder.getPtrTy(),
4567 ReduceListArgAlloca->
getName() +
".ascast");
4568 Value *ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4569 LocalReduceList,
Builder.getPtrTy(),
4570 LocalReduceList->
getName() +
".ascast");
4572 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4573 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4574 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4579 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4580 for (
auto En :
enumerate(ReductionInfos)) {
4583 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4584 RedListArrayTy, ReductionList,
4585 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4588 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4589 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4590 ReductionsBufferTy, BufferVD, 0, En.index());
4592 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4594 Value *ReduceListVal =
4596 Value *SrcElementPtrPtr =
4597 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceListVal,
4598 {ConstantInt::get(IndexTy, 0),
4599 ConstantInt::get(IndexTy, En.index())});
4600 Value *SrcDescriptorAddr =
4604 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4605 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4609 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4611 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4619 ->addFnAttr(Attribute::NoUnwind);
4624std::string OpenMPIRBuilder::getReductionFuncName(StringRef Name)
const {
4625 std::string Suffix =
4627 return (Name + Suffix).str();
4630Expected<Function *> OpenMPIRBuilder::createReductionFunction(
4633 AttributeList FuncAttrs) {
4634 IRBuilder<>::InsertPointGuard IPG(
Builder);
4636 {Builder.getPtrTy(), Builder.getPtrTy()},
4638 std::string
Name = getReductionFuncName(ReducerName);
4647 Builder.SetInsertPoint(EntryBB);
4652 Value *LHSArrayPtr =
nullptr;
4653 Value *RHSArrayPtr =
nullptr;
4660 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
4662 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
4663 Value *LHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4664 LHSAlloca, Arg0Type, LHSAlloca->
getName() +
".ascast");
4665 Value *RHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4666 RHSAlloca, Arg1Type, RHSAlloca->
getName() +
".ascast");
4667 Builder.CreateStore(Arg0, LHSAddrCast);
4668 Builder.CreateStore(Arg1, RHSAddrCast);
4669 LHSArrayPtr =
Builder.CreateLoad(Arg0Type, LHSAddrCast);
4670 RHSArrayPtr =
Builder.CreateLoad(Arg1Type, RHSAddrCast);
4674 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4676 for (
auto En :
enumerate(ReductionInfos)) {
4679 RedArrayTy, RHSArrayPtr,
4680 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4682 Value *RHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4683 RHSI8Ptr, RI.PrivateVariable->getType(),
4684 RHSI8Ptr->
getName() +
".ascast");
4687 RedArrayTy, LHSArrayPtr,
4688 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4690 Value *LHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4691 LHSI8Ptr, RI.Variable->getType(), LHSI8Ptr->
getName() +
".ascast");
4700 if (!IsByRef.
empty() && !IsByRef[En.index()]) {
4701 LHS =
Builder.CreateLoad(RI.ElementType, LHSPtr);
4702 RHS =
Builder.CreateLoad(RI.ElementType, RHSPtr);
4709 return AfterIP.takeError();
4710 if (!
Builder.GetInsertBlock())
4711 return ReductionFunc;
4715 if (!IsByRef.
empty() && !IsByRef[En.index()])
4716 Builder.CreateStore(Reduced, LHSPtr);
4721 for (
auto En :
enumerate(ReductionInfos)) {
4722 unsigned Index = En.index();
4724 Value *LHSFixupPtr, *RHSFixupPtr;
4725 Builder.restoreIP(RI.ReductionGenClang(
4726 Builder.saveIP(), Index, &LHSFixupPtr, &RHSFixupPtr, ReductionFunc));
4731 LHSPtrs[Index], [ReductionFunc](
const Use &U) {
4736 RHSPtrs[Index], [ReductionFunc](
const Use &U) {
4750 return ReductionFunc;
4758 assert(RI.Variable &&
"expected non-null variable");
4759 assert(RI.PrivateVariable &&
"expected non-null private variable");
4760 assert((RI.ReductionGen || RI.ReductionGenClang) &&
4761 "expected non-null reduction generator callback");
4764 RI.Variable->getType() == RI.PrivateVariable->getType() &&
4765 "expected variables and their private equivalents to have the same "
4768 assert(RI.Variable->getType()->isPointerTy() &&
4769 "expected variables to be pointers");
4786 ArrayRef<bool> IsByRef,
bool IsNoWait,
bool IsTeamsReduction,
bool IsSPMD,
4788 Value *SrcLocInfo) {
4802 if (ReductionInfos.
size() == 0)
4812 Builder.SetInsertPoint(InsertBlock, InsertBlock->
end());
4816 AttributeList FuncAttrs;
4817 AttrBuilder AttrBldr(Ctx);
4819 AttrBldr.addAttribute(Attr);
4820 AttrBldr.removeAttribute(Attribute::OptimizeNone);
4821 FuncAttrs = FuncAttrs.addFnAttributes(Ctx, AttrBldr);
4825 Builder.GetInsertBlock()->getParent()->getName(), ReductionInfos, IsByRef,
4827 if (!ReductionResult)
4829 Function *ReductionFunc = *ReductionResult;
4833 if (GridValue.has_value())
4834 Config.setGridValue(GridValue.value());
4849 Builder.getPtrTy(
M.getDataLayout().getProgramAddressSpace());
4853 Value *ReductionListAlloca =
4854 Builder.CreateAlloca(RedArrayTy,
nullptr,
".omp.reduction.red_list");
4855 Value *ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4856 ReductionListAlloca, PtrTy, ReductionListAlloca->
getName() +
".ascast");
4859 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4860 for (
auto En :
enumerate(ReductionInfos)) {
4863 RedArrayTy, ReductionList,
4864 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4867 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
4872 Builder.CreatePointerBitCastOrAddrSpaceCast(PrivateVar, PtrTy);
4873 Builder.CreateStore(CastElem, ElemPtr);
4877 ReductionInfos, ReductionFunc, FuncAttrs, IsByRef);
4883 emitInterWarpCopyFunction(
Loc, ReductionInfos, FuncAttrs, IsByRef);
4889 Value *RL =
Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList, PtrTy);
4898 unsigned MaxDataSize = 0;
4900 for (
auto En :
enumerate(ReductionInfos)) {
4904 Type *RedTypeArg = (!IsByRef.
empty() && IsByRef[En.index()])
4905 ? En.value().ByRefElementType
4906 : En.value().ElementType;
4907 auto Size =
M.getDataLayout().getTypeStoreSize(RedTypeArg);
4908 if (
Size > MaxDataSize)
4912 Value *ReductionDataSize =
4913 Builder.getInt64(MaxDataSize * ReductionInfos.
size());
4917 Function *CopyScratchToListFunc =
nullptr;
4919 Value *ScratchForCopyBack =
nullptr;
4922 Value *RLForCopyBack = RL;
4924 bool IsAtomicReduction =
4927 if (!IsTeamsReduction) {
4928 Value *SarFuncCast =
4929 Builder.CreatePointerBitCastOrAddrSpaceCast(*SarFunc, FuncPtrTy);
4931 Builder.CreatePointerBitCastOrAddrSpaceCast(WcFunc, FuncPtrTy);
4932 Value *Args[] = {SrcLocInfo, ReductionDataSize, RL, SarFuncCast,
4935 RuntimeFunction::OMPRTL___kmpc_nvptx_parallel_reduce_nowait_v2);
4937 }
else if (IsAtomicReduction) {
4941 RuntimeFunction::OMPRTL___kmpc_is_team_main_thread);
4946 Ctx, ReductionTypeArgs,
"struct._globalized_locals_ty");
4949 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
4954 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
4959 ReductionInfos, ReductionFunc, ReductionsBufferTy, FuncAttrs, IsByRef);
4982 Value *RuntimeRL = RL;
4989 ReductionsBufferTy,
nullptr,
".omp.reduction.scratch");
4990 Value *PerThreadScratch =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4991 PerThreadScratchAlloca, PtrTy,
4992 PerThreadScratchAlloca->
getName() +
".ascast");
4995 Value *PerThreadRedListAlloca =
4996 Builder.CreateAlloca(RedArrayTy,
nullptr,
4997 ".omp.reduction.per_thread_red_list");
4998 RuntimeRL =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4999 PerThreadRedListAlloca, PtrTy,
5000 PerThreadRedListAlloca->
getName() +
".ascast");
5005 for (
auto En :
enumerate(ReductionInfos)) {
5007 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
5010 ReductionsBufferTy, PerThreadScratch, 0, En.index());
5011 Value *Slot =
Builder.CreateConstInBoundsGEP2_32(RedArrayTy, RuntimeRL,
5014 Value *RuntimeListEntry = FieldPtr;
5016 Value *SrcDescriptor =
5019 AllocaIP, RI, FieldPtr, SrcDescriptor, PtrTy);
5022 RuntimeListEntry = *Descriptor;
5024 Builder.CreateStore(RuntimeListEntry, Slot);
5030 Type *CopyArg0Ty = (*LtGCFunc)->getFunctionType()->getParamType(0);
5031 Type *CopyArg2Ty = (*LtGCFunc)->getFunctionType()->getParamType(2);
5032 ScratchForCopyBack =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5033 PerThreadScratch, CopyArg0Ty);
5035 Builder.CreatePointerBitCastOrAddrSpaceCast(RL, CopyArg2Ty);
5043 *LtGCFunc, {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
5044 CopyScratchToListFunc = *GtLCFunc;
5047 Value *Args3[] = {SrcLocInfo, RuntimeRL, *SarFunc, WcFunc,
5048 *LtGCFunc, *GtLCFunc, *GtLRFunc};
5051 RuntimeFunction::OMPRTL___kmpc_gpu_xteam_reduce_nowait);
5071 if (ScratchForCopyBack) {
5074 CopyScratchToListFunc,
5075 {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
5079 for (
auto En :
enumerate(ReductionInfos)) {
5085 if (IsAtomicReduction) {
5101 Value *LHSPtr, *RHSPtr;
5103 &LHSPtr, &RHSPtr, CurFunc));
5109 RedValue =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5111 if (RHSPtr->
getType() != RHS->getType())
5113 Builder.CreatePointerBitCastOrAddrSpaceCast(RHS, RHSPtr->
getType());
5124 if (IsByRef.
empty() || !IsByRef[En.index()]) {
5126 "red.value." +
Twine(En.index()));
5137 if (!IsByRef.
empty() && !IsByRef[En.index()])
5142 if (ContinuationBlock) {
5143 Builder.CreateBr(ContinuationBlock);
5144 Builder.SetInsertPoint(ContinuationBlock);
5146 Config.setEmitLLVMUsed();
5157 ".omp.reduction.func", &M);
5168 Builder.SetInsertPoint(ReductionFuncBlock);
5170 Value *LHSArrayPtr =
nullptr;
5171 Value *RHSArrayPtr =
nullptr;
5182 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
5184 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
5185 Value *LHSAddrCast =
5186 Builder.CreatePointerBitCastOrAddrSpaceCast(LHSAlloca, Arg0Type);
5187 Value *RHSAddrCast =
5188 Builder.CreatePointerBitCastOrAddrSpaceCast(RHSAlloca, Arg1Type);
5189 Builder.CreateStore(Arg0, LHSAddrCast);
5190 Builder.CreateStore(Arg1, RHSAddrCast);
5191 LHSArrayPtr = Builder.CreateLoad(Arg0Type, LHSAddrCast);
5192 RHSArrayPtr = Builder.CreateLoad(Arg1Type, RHSAddrCast);
5194 LHSArrayPtr = ReductionFunc->
getArg(0);
5195 RHSArrayPtr = ReductionFunc->
getArg(1);
5198 unsigned NumReductions = ReductionInfos.
size();
5201 for (
auto En :
enumerate(ReductionInfos)) {
5203 Value *LHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5204 RedArrayTy, LHSArrayPtr, 0, En.index());
5205 Value *LHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), LHSI8PtrPtr);
5206 Value *LHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5209 Value *RHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5210 RedArrayTy, RHSArrayPtr, 0, En.index());
5211 Value *RHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), RHSI8PtrPtr);
5212 Value *RHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5221 Builder.restoreIP(*AfterIP);
5223 if (!Builder.GetInsertBlock())
5227 if (!IsByRef[En.index()])
5228 Builder.CreateStore(Reduced, LHSPtr);
5230 Builder.CreateRetVoid();
5237 bool IsNoWait,
bool IsTeamsReduction) {
5241 IsByRef, IsNoWait, IsTeamsReduction);
5248 if (ReductionInfos.
size() == 0)
5258 unsigned NumReductions = ReductionInfos.
size();
5261 Value *RedArray =
Builder.CreateAlloca(RedArrayTy,
nullptr,
"red.array");
5263 Builder.SetInsertPoint(InsertBlock, InsertBlock->
end());
5265 for (
auto En :
enumerate(ReductionInfos)) {
5266 unsigned Index = En.index();
5268 Value *RedArrayElemPtr =
Builder.CreateConstInBoundsGEP2_64(
5269 RedArrayTy, RedArray, 0, Index,
"red.array.elem." +
Twine(Index));
5276 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
5286 ? IdentFlag::OMP_IDENT_FLAG_ATOMIC_REDUCE
5291 unsigned RedArrayByteSize =
DL.getTypeStoreSize(RedArrayTy);
5292 Constant *RedArraySize = ConstantInt::get(IndexTy, RedArrayByteSize);
5294 Value *Lock = getOMPCriticalRegionLock(
".reduction");
5296 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_reduce_nowait
5297 : RuntimeFunction::OMPRTL___kmpc_reduce);
5300 {Ident, ThreadId, NumVariables, RedArraySize,
5301 RedArray, ReductionFunc, Lock},
5312 Builder.CreateSwitch(ReduceCall, ContinuationBlock, 2);
5313 Switch->addCase(
Builder.getInt32(1), NonAtomicRedBlock);
5314 Switch->addCase(
Builder.getInt32(2), AtomicRedBlock);
5319 Builder.SetInsertPoint(NonAtomicRedBlock);
5320 for (
auto En :
enumerate(ReductionInfos)) {
5326 if (!IsByRef[En.index()]) {
5328 "red.value." +
Twine(En.index()));
5330 Value *PrivateRedValue =
5332 "red.private.value." +
Twine(En.index()));
5340 if (!
Builder.GetInsertBlock())
5343 if (!IsByRef[En.index()])
5347 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_end_reduce_nowait
5348 : RuntimeFunction::OMPRTL___kmpc_end_reduce);
5350 Builder.CreateBr(ContinuationBlock);
5355 Builder.SetInsertPoint(AtomicRedBlock);
5356 if (CanGenerateAtomic &&
llvm::none_of(IsByRef, [](
bool P) {
return P; })) {
5363 if (!
Builder.GetInsertBlock())
5366 Builder.CreateBr(ContinuationBlock);
5379 if (!
Builder.GetInsertBlock())
5382 Builder.SetInsertPoint(ContinuationBlock);
5393 Directive OMPD = Directive::OMPD_master;
5398 Value *Args[] = {Ident, ThreadId};
5406 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5417 Directive OMPD = Directive::OMPD_masked;
5423 Value *ArgsEnd[] = {Ident, ThreadId};
5431 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5441 Call->setDoesNotThrow();
5456 bool IsInclusive,
ScanInfo *ScanRedInfo) {
5458 llvm::Error Err = emitScanBasedDirectiveDeclsIR(AllocaIP, ScanVars,
5459 ScanVarsType, ScanRedInfo);
5470 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5473 Type *DestTy = ScanVarsType[i];
5474 Value *Val =
Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5477 Builder.CreateStore(Src, Val);
5482 Builder.GetInsertBlock()->getParent());
5485 IV = ScanRedInfo->
IV;
5488 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5491 Type *DestTy = ScanVarsType[i];
5493 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5495 Builder.CreateStore(Src, ScanVars[i]);
5509 Builder.GetInsertBlock()->getParent());
5514Error OpenMPIRBuilder::emitScanBasedDirectiveDeclsIR(
5518 Builder.restoreIP(AllocaIP);
5520 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5522 Builder.CreateAlloca(Builder.getPtrTy(),
nullptr,
"vla");
5529 Builder.restoreIP(CodeGenIP);
5531 Builder.CreateAdd(ScanRedInfo->
Span, Builder.getInt32(1));
5532 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5536 Value *Buff = Builder.CreateMalloc(
IntPtrTy, ScanVarsType[i], Allocsize,
5537 AllocSpan,
nullptr,
"arr");
5538 Builder.CreateStore(Buff, (*(ScanRedInfo->
ScanBuffPtrs))[ScanVars[i]]);
5556 Builder.SetInsertPoint(
Builder.GetInsertBlock()->getTerminator());
5565Error OpenMPIRBuilder::emitScanBasedDirectiveFinalsIR(
5571 Value *PrivateVar = RedInfo.PrivateVariable;
5572 Value *OrigVar = RedInfo.Variable;
5576 Type *SrcTy = RedInfo.ElementType;
5581 Builder.CreateStore(Src, OrigVar);
5604 Builder.SetInsertPoint(
Builder.GetInsertBlock()->getTerminator());
5629 Builder.GetInsertBlock()->getModule(),
5636 Builder.GetInsertBlock()->getModule(),
5642 llvm::ConstantInt::get(ScanRedInfo->
Span->
getType(), 1));
5643 Builder.SetInsertPoint(InputBB);
5646 Builder.SetInsertPoint(LoopBB);
5662 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5664 Builder.SetInsertPoint(InnerLoopBB);
5668 Value *ReductionVal = RedInfo.PrivateVariable;
5671 Type *DestTy = RedInfo.ElementType;
5674 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5677 Builder.CreateInBoundsGEP(DestTy, Buff, OffsetIval,
"arrayOffset");
5682 RedInfo.ReductionGen(
Builder.saveIP(), LHS, RHS, Result);
5685 Builder.CreateStore(Result, LHSPtr);
5688 IVal, llvm::ConstantInt::get(
Builder.getInt32Ty(), 1));
5690 CmpI =
Builder.CreateICmpUGE(NextIVal, Pow2K);
5691 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5694 Counter, llvm::ConstantInt::get(Counter->
getType(), 1));
5700 Builder.CreateCondBr(Cmp, LoopBB, ExitBB);
5721 Error Err = emitScanBasedDirectiveFinalsIR(ReductionInfos, ScanRedInfo);
5728Error OpenMPIRBuilder::emitScanBasedDirectiveIR(
5740 Error Err = InputLoopGen();
5751 Error Err = ScanLoopGen(Builder.saveIP());
5758void OpenMPIRBuilder::createScanBBs(ScanInfo *ScanRedInfo) {
5795 Builder.SetInsertPoint(Preheader);
5798 Builder.SetInsertPoint(Header);
5799 PHINode *IndVarPHI =
Builder.CreatePHI(IndVarTy, 2,
"omp_" + Name +
".iv");
5800 IndVarPHI->
addIncoming(ConstantInt::get(IndVarTy, 0), Preheader);
5805 Builder.CreateICmpULT(IndVarPHI, TripCount,
"omp_" + Name +
".cmp");
5806 Builder.CreateCondBr(Cmp, Body, Exit);
5811 Builder.SetInsertPoint(Latch);
5821 bool HasNSW =
Config.hasNoSignedWrap();
5824 unsigned BitWidth = CI->getType()->getIntegerBitWidth();
5826 if (CI->getValue().ugt(SignedMax))
5828 }
else if (IsCollapsed) {
5833 Builder.CreateAdd(IndVarPHI, ConstantInt::get(IndVarTy, 1),
5834 "omp_" + Name +
".next",
true, HasNSW);
5845 CL->Header = Header;
5864 NextBB, NextBB, Name);
5896 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
5905 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
5906 ScanRedInfo->
Span = TripCount;
5912 ScanRedInfo->
IV =
IV;
5913 createScanBBs(ScanRedInfo);
5916 assert(Terminator->getNumSuccessors() == 1);
5917 BasicBlock *ContinueBlock = Terminator->getSuccessor(0);
5920 Builder.GetInsertBlock()->getParent());
5923 Builder.GetInsertBlock()->getParent());
5924 Builder.CreateBr(ContinueBlock);
5930 const auto &&InputLoopGen = [&]() ->
Error {
5932 Builder.saveIP(), BodyGen, Start, Stop, Step, IsSigned, InclusiveStop,
5933 ComputeIP, Name,
true, ScanRedInfo);
5937 Builder.restoreIP((*LoopInfo)->getAfterIP());
5943 InclusiveStop, ComputeIP, Name,
true, ScanRedInfo);
5947 Builder.restoreIP((*LoopInfo)->getAfterIP());
5951 Error Err = emitScanBasedDirectiveIR(InputLoopGen, ScanLoopGen, ScanRedInfo);
5959 bool IsSigned,
bool InclusiveStop,
const Twine &Name) {
5969 assert(IndVarTy == Stop->
getType() &&
"Stop type mismatch");
5970 assert(IndVarTy == Step->
getType() &&
"Step type mismatch");
5974 ConstantInt *Zero = ConstantInt::get(IndVarTy, 0);
5990 Incr =
Builder.CreateSelect(IsNeg,
Builder.CreateNeg(Step), Step);
5993 Span =
Builder.CreateSub(UB, LB,
"",
false,
true);
5997 Span =
Builder.CreateSub(Stop, Start,
"",
true);
6002 Value *CountIfLooping;
6003 if (InclusiveStop) {
6004 CountIfLooping =
Builder.CreateAdd(
Builder.CreateUDiv(Span, Incr), One);
6010 CountIfLooping =
Builder.CreateSelect(OneCmp, One, CountIfTwo);
6013 return Builder.CreateSelect(ZeroCmp, Zero, CountIfLooping,
6014 "omp_" + Name +
".tripcount");
6019 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
6026 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
6031 Config.hasNoSignedWrap());
6032 Value *IndVar =
Builder.CreateAdd(Span, Start,
"",
false,
6033 Config.hasNoSignedWrap());
6035 ScanRedInfo->
IV = IndVar;
6036 return BodyGenCB(
Builder.saveIP(), IndVar);
6042 Builder.getCurrentDebugLocation());
6053 unsigned Bitwidth = Ty->getIntegerBitWidth();
6056 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_4u);
6059 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_8u);
6069 unsigned Bitwidth = Ty->getIntegerBitWidth();
6072 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_4u);
6075 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_8u);
6083 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6085 "Require dedicated allocate IP");
6091 uint32_t SrcLocStrSize;
6095 case WorksharingLoopType::ForStaticLoop:
6096 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6098 case WorksharingLoopType::DistributeStaticLoop:
6099 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6101 case WorksharingLoopType::DistributeForStaticLoop:
6102 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
6109 Type *IVTy =
IV->getType();
6110 FunctionCallee StaticInit =
6111 LoopType == WorksharingLoopType::DistributeForStaticLoop
6114 FunctionCallee StaticFini =
6118 Builder.SetInsertPoint(AllocaIP.getBlock()->getFirstNonPHIOrDbgOrAlloca());
6121 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6122 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
6123 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
6124 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
6133 Constant *One = ConstantInt::get(IVTy, 1);
6134 Builder.CreateStore(Zero, PLowerBound);
6136 Builder.CreateStore(UpperBound, PUpperBound);
6137 Builder.CreateStore(One, PStride);
6143 (LoopType == WorksharingLoopType::DistributeStaticLoop)
6144 ? OMPScheduleType::OrderedDistribute
6147 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6151 auto BuildInitCall = [LoopType, SrcLoc, ThreadNum, PLastIter, PLowerBound,
6152 PUpperBound, IVTy, PStride, One,
Zero, StaticInit,
6155 PLowerBound, PUpperBound});
6156 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
6157 Value *PDistUpperBound =
6158 Builder.CreateAlloca(IVTy,
nullptr,
"p.distupperbound");
6159 Args.push_back(PDistUpperBound);
6164 BuildInitCall(SchedulingType,
Builder);
6165 if (HasDistSchedule &&
6166 LoopType != WorksharingLoopType::DistributeStaticLoop) {
6167 Constant *DistScheduleSchedType = ConstantInt::get(
6172 BuildInitCall(DistScheduleSchedType,
Builder);
6174 Value *LowerBound =
Builder.CreateLoad(IVTy, PLowerBound);
6175 Value *InclusiveUpperBound =
Builder.CreateLoad(IVTy, PUpperBound);
6176 Value *TripCountMinusOne =
Builder.CreateSub(InclusiveUpperBound, LowerBound);
6177 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One);
6178 CLI->setTripCount(TripCount);
6184 CLI->mapIndVar([&](Instruction *OldIV) ->
Value * {
6188 return Builder.CreateAdd(OldIV, LowerBound,
"",
false,
6189 Config.hasNoSignedWrap());
6201 omp::Directive::OMPD_for,
false,
6204 return BarrierIP.takeError();
6231 Reachable.insert(
Block);
6241 Ctx, {
MDString::get(Ctx,
"llvm.loop.parallel_accesses"), AccessGroup}));
6245OpenMPIRBuilder::applyStaticChunkedWorkshareLoop(
6249 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6250 assert((ChunkSize || DistScheduleChunkSize) &&
"Chunk size is required");
6255 Type *IVTy =
IV->getType();
6257 "Max supported tripcount bitwidth is 64 bits");
6259 :
Type::getInt64Ty(Ctx);
6262 Constant *One = ConstantInt::get(InternalIVTy, 1);
6267 SmallVector<Instruction *> UIs;
6268 for (BasicBlock &BB : *
F)
6269 if (!BB.hasTerminator())
6270 UIs.
push_back(
new UnreachableInst(
F->getContext(), &BB));
6275 LoopInfo &&LI = LIA.
run(*
F,
FAM);
6276 for (Instruction *
I : UIs)
6277 I->eraseFromParent();
6280 if (ChunkSize || DistScheduleChunkSize)
6285 FunctionCallee StaticInit =
6287 FunctionCallee StaticFini =
6293 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6294 Value *PLowerBound =
6295 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.lowerbound");
6296 Value *PUpperBound =
6297 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.upperbound");
6298 Value *PStride =
Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.stride");
6307 ChunkSize ? ChunkSize : Zero, InternalIVTy,
"chunksize");
6308 Value *CastedDistScheduleChunkSize =
Builder.CreateZExtOrTrunc(
6309 DistScheduleChunkSize ? DistScheduleChunkSize : Zero, InternalIVTy,
6310 "distschedulechunksize");
6311 Value *CastedTripCount =
6312 Builder.CreateZExt(OrigTripCount, InternalIVTy,
"tripcount");
6315 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6317 ConstantInt::get(I32Type,
static_cast<int>(DistScheduleSchedType));
6318 Builder.CreateStore(Zero, PLowerBound);
6319 Value *OrigUpperBound =
Builder.CreateSub(CastedTripCount, One);
6320 Value *IsTripCountZero =
Builder.CreateICmpEQ(CastedTripCount, Zero);
6322 Builder.CreateSelect(IsTripCountZero, Zero, OrigUpperBound);
6323 Builder.CreateStore(UpperBound, PUpperBound);
6324 Builder.CreateStore(One, PStride);
6328 uint32_t SrcLocStrSize;
6331 if (DistScheduleSchedType != OMPScheduleType::None) {
6332 Flag |= OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6337 auto BuildInitCall = [StaticInit, SrcLoc, ThreadNum, PLastIter, PLowerBound,
6338 PUpperBound, PStride, One,
6339 this](
Value *SchedulingType,
Value *ChunkSize,
6342 StaticInit, {SrcLoc, ThreadNum,
6343 SchedulingType, PLastIter,
6344 PLowerBound, PUpperBound,
6348 BuildInitCall(SchedulingType, CastedChunkSize,
Builder);
6349 if (DistScheduleSchedType != OMPScheduleType::None &&
6350 SchedType != OMPScheduleType::OrderedDistributeChunked &&
6351 SchedType != OMPScheduleType::OrderedDistribute) {
6355 BuildInitCall(DistSchedulingType, CastedDistScheduleChunkSize,
Builder);
6359 Value *FirstChunkStart =
6360 Builder.CreateLoad(InternalIVTy, PLowerBound,
"omp_firstchunk.lb");
6361 Value *FirstChunkStop =
6362 Builder.CreateLoad(InternalIVTy, PUpperBound,
"omp_firstchunk.ub");
6363 Value *FirstChunkEnd =
Builder.CreateAdd(FirstChunkStop, One);
6365 Builder.CreateSub(FirstChunkEnd, FirstChunkStart,
"omp_chunk.range");
6366 Value *NextChunkStride =
6367 Builder.CreateLoad(InternalIVTy, PStride,
"omp_dispatch.stride");
6371 Value *DispatchCounter;
6379 DispatchCounter = Counter;
6382 FirstChunkStart, CastedTripCount, NextChunkStride,
6405 Value *ChunkEnd =
Builder.CreateAdd(DispatchCounter, ChunkRange);
6406 Value *IsLastChunk =
6407 Builder.CreateICmpUGE(ChunkEnd, CastedTripCount,
"omp_chunk.is_last");
6408 Value *CountUntilOrigTripCount =
6409 Builder.CreateSub(CastedTripCount, DispatchCounter);
6411 IsLastChunk, CountUntilOrigTripCount, ChunkRange,
"omp_chunk.tripcount");
6412 Value *BackcastedChunkTC =
6413 Builder.CreateTrunc(ChunkTripCount, IVTy,
"omp_chunk.tripcount.trunc");
6414 CLI->setTripCount(BackcastedChunkTC);
6419 Value *BackcastedDispatchCounter =
6420 Builder.CreateTrunc(DispatchCounter, IVTy,
"omp_dispatch.iv.trunc");
6421 CLI->mapIndVar([&](Instruction *) ->
Value * {
6423 return Builder.CreateAdd(
IV, BackcastedDispatchCounter);
6436 return AfterIP.takeError();
6451static FunctionCallee
6454 unsigned Bitwidth = Ty->getIntegerBitWidth();
6457 case WorksharingLoopType::ForStaticLoop:
6460 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_4u);
6463 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_8u);
6465 case WorksharingLoopType::DistributeStaticLoop:
6468 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_4u);
6471 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_8u);
6473 case WorksharingLoopType::DistributeForStaticLoop:
6476 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_4u);
6479 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_8u);
6482 if (Bitwidth != 32 && Bitwidth != 64) {
6494 Function &LoopBodyFn,
bool NoLoop) {
6505 if (LoopType == WorksharingLoopType::DistributeStaticLoop) {
6506 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6507 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6508 Builder.restoreIP({InsertBlock, std::prev(InsertBlock->
end())});
6513 M, omp::RuntimeFunction::OMPRTL_omp_get_num_threads);
6514 Builder.restoreIP({InsertBlock, std::prev(InsertBlock->
end())});
6518 Builder.CreateZExtOrTrunc(NumThreads, TripCountTy,
"num.threads.cast"));
6519 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6520 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
6521 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6522 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), NoLoop));
6524 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6548 Builder.restoreIP({Preheader, Preheader->
end()});
6551 Builder.CreateBr(CLI->
getExit());
6559 CleanUpInfo.
collectBlocks(RegionBlockSet, BlocksToBeRemoved);
6567 "Expected unique undroppable user of outlined function");
6569 assert(OutlinedFnCallInstruction &&
"Expected outlined function call");
6571 "Expected outlined function call to be located in loop preheader");
6573 if (OutlinedFnCallInstruction->
arg_size() > 1)
6580 LoopBodyArg, TripCount, OutlinedFn, NoLoop);
6582 for (
auto &ToBeDeletedItem : ToBeDeleted)
6583 ToBeDeletedItem->eraseFromParent();
6590 uint32_t SrcLocStrSize;
6594 case WorksharingLoopType::ForStaticLoop:
6595 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6597 case WorksharingLoopType::DistributeStaticLoop:
6598 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6600 case WorksharingLoopType::DistributeForStaticLoop:
6601 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
6606 auto OI = std::make_unique<OutlineInfo>();
6611 SmallVector<Instruction *, 4> ToBeDeleted;
6613 OI->OuterAllocBB = AllocaIP.getBlock();
6636 SmallPtrSet<BasicBlock *, 32> ParallelRegionBlockSet;
6638 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
6640 CodeExtractorAnalysisCache CEAC(*OuterFn);
6641 CodeExtractor Extractor(Blocks,
6655 SetVector<Value *> SinkingCands, HoistingCands;
6659 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
6666 for (
auto Use :
Users) {
6668 if (ParallelRegionBlockSet.
count(Inst->getParent())) {
6669 Inst->replaceUsesOfWith(CLI->
getIndVar(), NewLoopCntLoad);
6675 OI->ExcludeArgsFromAggregate.push_back(NewLoopCntLoad);
6682 OI->PostOutlineCB = [=, ToBeDeletedVec =
6683 std::move(ToBeDeleted)](
Function &OutlinedFn) {
6693 bool NeedsBarrier, omp::ScheduleKind SchedKind,
Value *ChunkSize,
6694 bool HasSimdModifier,
bool HasMonotonicModifier,
6695 bool HasNonmonotonicModifier,
bool HasOrderedClause,
6697 Value *DistScheduleChunkSize) {
6698 if (
Config.isTargetDevice())
6699 return applyWorkshareLoopTarget(
DL, CLI, AllocaIP, LoopType, NoLoop);
6701 SchedKind, ChunkSize, HasSimdModifier, HasMonotonicModifier,
6702 HasNonmonotonicModifier, HasOrderedClause, DistScheduleChunkSize);
6704 bool IsOrdered = (EffectiveScheduleType & OMPScheduleType::ModifierOrdered) ==
6705 OMPScheduleType::ModifierOrdered;
6707 if (HasDistSchedule) {
6708 DistScheduleSchedType = DistScheduleChunkSize
6709 ? OMPScheduleType::OrderedDistributeChunked
6710 : OMPScheduleType::OrderedDistribute;
6712 switch (EffectiveScheduleType & ~OMPScheduleType::ModifierMask) {
6713 case OMPScheduleType::BaseStatic:
6714 case OMPScheduleType::BaseDistribute:
6715 assert((!ChunkSize || !DistScheduleChunkSize) &&
6716 "No chunk size with static-chunked schedule");
6717 if (IsOrdered && !HasDistSchedule)
6718 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6719 NeedsBarrier, ChunkSize);
6721 if (DistScheduleChunkSize)
6722 return applyStaticChunkedWorkshareLoop(
6723 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6724 DistScheduleChunkSize, DistScheduleSchedType);
6725 return applyStaticWorkshareLoop(
DL, CLI, AllocaIP, LoopType, NeedsBarrier,
6728 case OMPScheduleType::BaseStaticChunked:
6729 case OMPScheduleType::BaseDistributeChunked:
6730 if (IsOrdered && !HasDistSchedule)
6731 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6732 NeedsBarrier, ChunkSize);
6734 return applyStaticChunkedWorkshareLoop(
6735 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6736 DistScheduleChunkSize, DistScheduleSchedType);
6738 case OMPScheduleType::BaseRuntime:
6739 case OMPScheduleType::BaseAuto:
6740 case OMPScheduleType::BaseGreedy:
6741 case OMPScheduleType::BaseBalanced:
6742 case OMPScheduleType::BaseSteal:
6743 case OMPScheduleType::BaseRuntimeSimd:
6745 "schedule type does not support user-defined chunk sizes");
6747 case OMPScheduleType::BaseGuidedSimd:
6748 case OMPScheduleType::BaseDynamicChunked:
6749 case OMPScheduleType::BaseGuidedChunked:
6750 case OMPScheduleType::BaseGuidedIterativeChunked:
6751 case OMPScheduleType::BaseGuidedAnalyticalChunked:
6752 case OMPScheduleType::BaseStaticBalancedChunked:
6753 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6754 NeedsBarrier, ChunkSize);
6767 unsigned Bitwidth = Ty->getIntegerBitWidth();
6770 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_4u);
6773 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_8u);
6781static FunctionCallee
6783 unsigned Bitwidth = Ty->getIntegerBitWidth();
6786 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_4u);
6789 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_8u);
6796static FunctionCallee
6798 unsigned Bitwidth = Ty->getIntegerBitWidth();
6801 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_4u);
6804 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_8u);
6809OpenMPIRBuilder::applyDynamicWorkshareLoop(
DebugLoc DL, CanonicalLoopInfo *CLI,
6812 bool NeedsBarrier,
Value *Chunk) {
6813 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6815 "Require dedicated allocate IP");
6817 "Require valid schedule type");
6819 bool Ordered = (SchedType & OMPScheduleType::ModifierOrdered) ==
6820 OMPScheduleType::ModifierOrdered;
6825 uint32_t SrcLocStrSize;
6832 Type *IVTy =
IV->getType();
6837 Builder.SetInsertPoint(AllocaIP.getBlock()->getFirstNonPHIOrDbgOrAlloca());
6839 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6840 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
6841 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
6842 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
6851 Constant *One = ConstantInt::get(IVTy, 1);
6852 Builder.CreateStore(One, PLowerBound);
6854 Builder.CreateStore(UpperBound, PUpperBound);
6855 Builder.CreateStore(One, PStride);
6873 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6885 Builder.SetInsertPoint(OuterCond, OuterCond->getFirstInsertionPt());
6888 {SrcLoc, ThreadNum, PLastIter, PLowerBound, PUpperBound, PStride});
6889 Constant *Zero32 = ConstantInt::get(I32Type, 0);
6892 Builder.CreateSub(
Builder.CreateLoad(IVTy, PLowerBound), One,
"lb");
6893 Builder.CreateCondBr(MoreWork, Header, Exit);
6899 PI->setIncomingBlock(0, OuterCond);
6900 PI->setIncomingValue(0, LowerBound);
6905 Br->setSuccessor(OuterCond);
6911 UpperBound =
Builder.CreateLoad(IVTy, PUpperBound,
"ub");
6914 CI->setOperand(1, UpperBound);
6918 assert(BI->getSuccessor(1) == Exit);
6919 BI->setSuccessor(1, OuterCond);
6933 omp::Directive::OMPD_for,
false,
6936 return BarrierIP.takeError();
6988 assert(
Loops.size() >= 1 &&
"At least one loop required");
6989 size_t NumLoops =
Loops.size();
6993 return Loops.front();
7005 Loop->collectControlBlocks(OldControlBBs);
7009 if (ComputeIP.
isSet())
7016 Value *CollapsedTripCount =
nullptr;
7019 "All loops to collapse must be valid canonical loops");
7020 Value *OrigTripCount = L->getTripCount();
7021 if (!CollapsedTripCount) {
7022 CollapsedTripCount = OrigTripCount;
7027 CollapsedTripCount =
7028 Builder.CreateNUWMul(CollapsedTripCount, OrigTripCount);
7034 OrigPreheader->
getNextNode(), OrigAfter,
"collapsed",
7041 Builder.restoreIP(Result->getBodyIP());
7043 Value *Leftover = Result->getIndVar();
7045 NewIndVars.
resize(NumLoops);
7046 for (
int i = NumLoops - 1; i >= 1; --i) {
7047 Value *OrigTripCount =
Loops[i]->getTripCount();
7049 Value *NewIndVar =
Builder.CreateURem(Leftover, OrigTripCount);
7050 NewIndVars[i] = NewIndVar;
7052 Leftover =
Builder.CreateUDiv(Leftover, OrigTripCount);
7055 NewIndVars[0] = Leftover;
7064 BasicBlock *ContinueBlock = Result->getBody();
7066 auto ContinueWith = [&ContinueBlock, &ContinuePred,
DL](
BasicBlock *Dest,
7073 ContinueBlock =
nullptr;
7074 ContinuePred = NextSrc;
7081 for (
size_t i = 0; i < NumLoops - 1; ++i)
7082 ContinueWith(
Loops[i]->getBody(),
Loops[i + 1]->getHeader());
7088 for (
size_t i = NumLoops - 1; i > 0; --i)
7089 ContinueWith(
Loops[i]->getAfter(),
Loops[i - 1]->getLatch());
7092 ContinueWith(Result->getLatch(),
nullptr);
7099 for (
size_t i = 0; i < NumLoops; ++i)
7100 Loops[i]->getIndVar()->replaceAllUsesWith(NewIndVars[i]);
7114std::vector<CanonicalLoopInfo *>
7118 "Must pass as many tile sizes as there are loops");
7119 int NumLoops =
Loops.size();
7120 assert(NumLoops >= 1 &&
"At least one loop to tile required");
7132 Loop->collectControlBlocks(OldControlBBs);
7140 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7141 OrigTripCounts.
push_back(L->getTripCount());
7152 for (
int i = 0; i < NumLoops - 1; ++i) {
7165 for (
int i = 0; i < NumLoops; ++i) {
7167 Value *OrigTripCount = OrigTripCounts[i];
7180 Value *FloorTripOverflow =
7181 Builder.CreateICmpNE(FloorTripRem, ConstantInt::get(IVType, 0));
7183 FloorTripOverflow =
Builder.CreateZExt(FloorTripOverflow, IVType);
7184 Value *FloorTripCount =
7185 Builder.CreateAdd(FloorCompleteTripCount, FloorTripOverflow,
7186 "omp_floor" +
Twine(i) +
".tripcount",
true);
7189 FloorCompleteCount.
push_back(FloorCompleteTripCount);
7195 std::vector<CanonicalLoopInfo *> Result;
7196 Result.reserve(NumLoops * 2);
7209 auto EmbeddNewLoop =
7210 [
this,
DL,
F, InnerEnter, &Enter, &
Continue, &OutroInsertBefore](
7213 DL, TripCount,
F, InnerEnter, OutroInsertBefore, Name);
7218 Enter = EmbeddedLoop->
getBody();
7220 OutroInsertBefore = EmbeddedLoop->
getLatch();
7221 return EmbeddedLoop;
7225 const Twine &NameBase) {
7228 EmbeddNewLoop(
P.value(), NameBase +
Twine(
P.index()));
7229 Result.push_back(EmbeddedLoop);
7233 EmbeddNewLoops(FloorCount,
"floor");
7239 for (
int i = 0; i < NumLoops; ++i) {
7243 Value *FloorIsEpilogue =
7245 Value *TileTripCount =
7252 EmbeddNewLoops(TileCounts,
"tile");
7257 for (std::pair<BasicBlock *, BasicBlock *>
P : InbetweenCode) {
7266 BodyEnter =
nullptr;
7267 BodyEntered = ExitBB;
7279 Builder.restoreIP(Result.back()->getBodyIP());
7280 for (
int i = 0; i < NumLoops; ++i) {
7283 Value *OrigIndVar = OrigIndVars[i];
7311 if (Properties.
empty())
7334 assert(
Loop->isValid() &&
"Expecting a valid CanonicalLoopInfo");
7338 assert(Latch &&
"A valid CanonicalLoopInfo must have a unique latch");
7346 if (
I.mayReadOrWriteMemory()) {
7350 I.setMetadata(LLVMContext::MD_access_group, AccessGroup);
7364 Loop->collectControlBlocks(oldControlBBs);
7369 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7370 origTripCounts.
push_back(L->getTripCount());
7379 Builder.SetInsertPoint(TCBlock);
7380 Value *fusedTripCount =
nullptr;
7382 assert(L->isValid() &&
"All loops to fuse must be valid canonical loops");
7383 Value *origTripCount = L->getTripCount();
7384 if (!fusedTripCount) {
7385 fusedTripCount = origTripCount;
7388 Value *condTP =
Builder.CreateICmpSGT(fusedTripCount, origTripCount);
7389 fusedTripCount =
Builder.CreateSelect(condTP, fusedTripCount, origTripCount,
7403 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7404 Loops[i]->getPreheader()->moveBefore(TCBlock);
7405 Loops[i]->getAfter()->moveBefore(TCBlock);
7409 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7421 for (
size_t i = 0; i <
Loops.size(); ++i) {
7423 F->getContext(),
"omp.fused.inner.cond",
F,
Loops[i]->getBody());
7424 Builder.SetInsertPoint(condBlock);
7432 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7433 Builder.SetInsertPoint(condBBs[i]);
7434 Builder.CreateCondBr(condValues[i],
Loops[i]->getBody(), condBBs[i + 1]);
7450 "omp.fused.pre_latch");
7483 const Twine &NamePrefix) {
7512 C, NamePrefix +
".if.then",
Cond->getParent(),
Cond->getNextNode());
7514 C, NamePrefix +
".if.else",
Cond->getParent(), CanonicalLoop->
getExit());
7517 Builder.SetInsertPoint(SplitBeforeIt);
7519 Builder.CreateCondBr(IfCond, ThenBlock, ElseBlock);
7522 spliceBB(IP, ThenBlock,
false, Builder.getCurrentDebugLocation());
7525 Builder.SetInsertPoint(ElseBlock);
7531 ExistingBlocks.
reserve(L->getNumBlocks() + 1);
7533 ExistingBlocks.
append(L->block_begin(), L->block_end());
7539 assert(LoopCond && LoopHeader &&
"Invalid loop structure");
7541 if (
Block == L->getLoopPreheader() ||
Block == L->getLoopLatch() ||
7548 if (
Block == ThenBlock)
7549 NewBB->
setName(NamePrefix +
".if.else");
7552 VMap[
Block] = NewBB;
7560 L->getLoopLatch()->splitBasicBlockBefore(
L->getLoopLatch()->begin(),
7561 NamePrefix +
".pre_latch");
7565 L->addBasicBlockToLoop(ThenBlock, LI);
7571 if (TargetTriple.
isX86()) {
7572 if (Features.
lookup(
"avx512f"))
7574 else if (Features.
lookup(
"avx"))
7578 if (TargetTriple.
isPPC())
7580 if (TargetTriple.
isWasm())
7587 Value *IfCond, OrderKind Order,
7597 if (!BB.hasTerminator())
7613 I->eraseFromParent();
7616 if (AlignedVars.
size()) {
7618 for (
auto &AlignedItem : AlignedVars) {
7619 Value *AlignedPtr = AlignedItem.first;
7620 Value *Alignment = AlignedItem.second;
7623 Builder.CreateAlignmentAssumption(
F->getDataLayout(), AlignedPtr,
7631 createIfVersion(CanonicalLoop, IfCond, VMap, LIA, LI, L,
"simd");
7644 Reachable.insert(
Block);
7654 if ((Safelen ==
nullptr) || (Order == OrderKind::OMP_ORDER_concurrent))
7670 if (Simdlen || Safelen) {
7674 ConstantInt *VectorizeWidth = Simdlen ==
nullptr ? Safelen : Simdlen;
7700static std::unique_ptr<TargetMachine>
7704 StringRef CPU =
F->getFnAttribute(
"target-cpu").getValueAsString();
7705 StringRef Features =
F->getFnAttribute(
"target-features").getValueAsString();
7716 std::nullopt, OptLevel));
7734 if (!BB.hasTerminator())
7747 [&](
const Function &
F) {
return TM->getTargetTransformInfo(
F); });
7748 FAM.registerPass([&]() {
return TIRA; });
7762 I->eraseFromParent();
7765 assert(L &&
"Expecting CanonicalLoopInfo to be recognized as a loop");
7770 nullptr, ORE,
static_cast<int>(OptLevel),
7790 <<
" Threshold=" << UP.
Threshold <<
"\n"
7793 <<
" PartialOptSizeThreshold="
7813 Ptr =
Load->getPointerOperand();
7815 Ptr =
Store->getPointerOperand();
7822 if (Alloca->getParent() == &
F->getEntryBlock())
7842 int MaxTripCount = 0;
7843 bool MaxOrZero =
false;
7844 unsigned TripMultiple = 0;
7848 MaxTripCount, MaxOrZero, TripMultiple, UCE, UP, PP);
7849 LLVM_DEBUG(
dbgs() <<
"Suggesting unroll factor of " << Factor <<
"\n");
7860 assert(Factor >= 0 &&
"Unroll factor must not be negative");
7876 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst}));
7889 *UnrolledCLI =
Loop;
7894 "unrolling only makes sense with a factor of 2 or larger");
7896 Type *IndVarTy =
Loop->getIndVarType();
7903 std::vector<CanonicalLoopInfo *>
LoopNest =
7918 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst})});
7921 (*UnrolledCLI)->assertOK();
7939 Value *Args[] = {Ident, ThreadId, BufSize, CpyBuf, CpyFn, DidItLD};
7958 if (!CPVars.
empty()) {
7963 Directive OMPD = Directive::OMPD_single;
7968 Value *Args[] = {Ident, ThreadId};
7977 if (
Error Err = FiniCB(IP))
7998 EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCBWrapper,
8005 for (
size_t I = 0, E = CPVars.
size();
I < E; ++
I)
8008 ConstantInt::get(Int64, 0), CPVars[
I],
8011 }
else if (!IsNowait) {
8014 omp::Directive::OMPD_unknown,
false,
8032 Directive::OMPD_scope,
nullptr,
nullptr,
8033 BodyGenCB, FiniCB,
false,
true,
8041 omp::Directive::OMPD_unknown,
8057 Directive OMPD = Directive::OMPD_critical;
8062 Value *LockVar = getOMPCriticalRegionLock(CriticalName);
8063 Value *Args[] = {Ident, ThreadId, LockVar};
8080 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
8088 const Twine &Name,
bool IsDependSource) {
8092 "OpenMP runtime requires depend vec with i64 type");
8105 for (
unsigned I = 0;
I < NumLoops; ++
I) {
8119 Value *Args[] = {Ident, ThreadId, DependBaseAddrGEP};
8137 Directive OMPD = Directive::OMPD_ordered_blockassoc;
8146 Value *Args[] = {Ident, ThreadId};
8156 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
8163 bool HasFinalize,
bool IsCancellable) {
8170 BasicBlock *EntryBB = Builder.GetInsertBlock();
8179 emitCommonDirectiveEntry(OMPD, EntryCall, ExitBB, Conditional);
8191 "Unexpected control flow graph state!!");
8193 emitCommonDirectiveExit(OMPD, FinIP, ExitCall, HasFinalize);
8195 return AfterIP.takeError();
8200 "Unexpected Insertion point location!");
8203 auto InsertBB = merged ? ExitPredBB : ExitBB;
8206 Builder.SetInsertPoint(InsertBB);
8208 return Builder.saveIP();
8212 Directive OMPD,
Value *EntryCall, BasicBlock *ExitBB,
bool Conditional) {
8214 if (!Conditional || !EntryCall)
8220 auto *UI =
new UnreachableInst(
Builder.getContext(), ThenBB);
8230 Builder.CreateCondBr(CallBool, ThenBB, ExitBB);
8234 UI->eraseFromParent();
8242 omp::Directive OMPD,
InsertPointTy FinIP, Instruction *ExitCall,
8250 "Unexpected finalization stack state!");
8253 assert(Fi.DK == OMPD &&
"Unexpected Directive for Finalization call!");
8255 if (
Error Err = Fi.mergeFiniBB(
Builder, FinIP.getBlock()))
8256 return std::move(Err);
8260 Builder.SetInsertPoint(FinIP.getBlock()->getTerminator());
8270 return IRBuilder<>::InsertPoint(ExitCall->
getParent(),
8304 "copyin.not.master.end");
8311 Builder.SetInsertPoint(OMP_Entry);
8314 Value *cmp =
Builder.CreateICmpNE(MasterPtr, PrivatePtr);
8315 Builder.CreateCondBr(cmp, CopyBegin, CopyEnd);
8317 Builder.SetInsertPoint(CopyBegin);
8335 Value *Args[] = {ThreadId,
Size, Allocator};
8358 return Builder.CreateCall(Fn, Args, Name);
8372 Value *Args[] = {ThreadId, Addr, Allocator};
8379 const Twine &Name) {
8387 M.getContext(),
M.getDataLayout().getPrefTypeAlign(Int64)));
8393 const Twine &Name) {
8395 Loc,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)), Name);
8400 const Twine &Name) {
8406 return Builder.CreateCall(Fn, Args, Name);
8411 const Twine &Name) {
8413 Loc, Addr,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)),
8420 Value *DependenceAddress,
bool HaveNowaitClause) {
8430 else if (
Device->getType() != Int32)
8432 Constant *InteropTypeVal = ConstantInt::get(Int32, (
int)InteropType);
8433 if (NumDependences ==
nullptr) {
8434 NumDependences = ConstantInt::get(Int32, 0);
8438 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8440 Ident, ThreadId, InteropVar, InteropTypeVal,
8441 Device, NumDependences, DependenceAddress, HaveNowaitClauseVal};
8450 Value *NumDependences,
Value *DependenceAddress,
bool HaveNowaitClause) {
8460 else if (
Device->getType() != Int32)
8462 if (NumDependences ==
nullptr) {
8463 NumDependences = ConstantInt::get(Int32, 0);
8467 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8469 Ident, ThreadId, InteropVar,
Device,
8470 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8479 Value *NumDependences,
8480 Value *DependenceAddress,
8481 bool HaveNowaitClause) {
8490 else if (
Device->getType() != Int32)
8492 if (NumDependences ==
nullptr) {
8493 NumDependences = ConstantInt::get(Int32, 0);
8497 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8499 Ident, ThreadId, InteropVar,
Device,
8500 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8530 assert(!Attrs.MaxThreads.empty() && !Attrs.MaxTeams.empty() &&
8531 "expected num_threads and num_teams to be specified");
8551 const std::string DebugPrefix =
"_debug__";
8552 if (KernelName.
ends_with(DebugPrefix)) {
8553 KernelName = KernelName.
drop_back(DebugPrefix.length());
8554 Kernel =
M.getFunction(KernelName);
8560 if (Attrs.MinTeams > 1 || Attrs.MaxTeams.front() > 0)
8565 int32_t MaxThreadsVal = Attrs.MaxThreads.front();
8572 MaxThreadsVal = Attrs.MinThreads;
8576 if (MaxThreadsVal > 0)
8587 omp::RuntimeFunction::OMPRTL___kmpc_target_init);
8590 Twine DynamicEnvironmentName = KernelName +
"_dynamic_environment";
8591 Constant *DynamicEnvironmentInitializer =
8595 DynamicEnvironmentInitializer, DynamicEnvironmentName,
8597 DL.getDefaultGlobalsAddressSpace());
8601 DynamicEnvironmentGV->
getType() == DynamicEnvironmentPtr
8602 ? DynamicEnvironmentGV
8604 DynamicEnvironmentPtr);
8607 ConfigurationEnvironment, {
8608 UseGenericStateMachineVal,
8609 MayUseNestedParallelismVal,
8618 KernelEnvironment, {
8619 ConfigurationEnvironmentInitializer,
8623 std::string KernelEnvironmentName =
8624 (KernelName +
"_kernel_environment").str();
8627 KernelEnvironmentInitializer, KernelEnvironmentName,
8629 DL.getDefaultGlobalsAddressSpace());
8633 KernelEnvironmentGV->
getType() == KernelEnvironmentPtr
8634 ? KernelEnvironmentGV
8636 KernelEnvironmentPtr);
8637 Value *KernelLaunchEnvironment =
8640 KernelLaunchEnvironment =
8641 KernelLaunchEnvironment->
getType() == KernelLaunchEnvParamTy
8642 ? KernelLaunchEnvironment
8643 :
Builder.CreateAddrSpaceCast(KernelLaunchEnvironment,
8644 KernelLaunchEnvParamTy);
8646 Fn, {KernelEnvironment, KernelLaunchEnvironment});
8658 auto *UI =
Builder.CreateUnreachable();
8664 Builder.SetInsertPoint(WorkerExitBB);
8668 Builder.SetInsertPoint(CheckBBTI);
8669 Builder.CreateCondBr(ExecUserCode, UI->getParent(), WorkerExitBB);
8671 CheckBBTI->eraseFromParent();
8672 UI->eraseFromParent();
8680 int32_t TeamsReductionDataSize) {
8685 omp::RuntimeFunction::OMPRTL___kmpc_target_deinit);
8689 if (!TeamsReductionDataSize)
8695 const std::string DebugPrefix =
"_debug__";
8697 KernelName = KernelName.
drop_back(DebugPrefix.length());
8698 auto *KernelEnvironmentGV =
8699 M.getNamedGlobal((KernelName +
"_kernel_environment").str());
8700 assert(KernelEnvironmentGV &&
"Expected kernel environment global\n");
8701 auto *KernelEnvironmentInitializer = KernelEnvironmentGV->getInitializer();
8703 KernelEnvironmentInitializer,
8704 ConstantInt::get(Int32, TeamsReductionDataSize), {0, 7});
8705 KernelEnvironmentGV->setInitializer(NewInitializer);
8710 if (
Kernel.hasFnAttribute(Name)) {
8711 int32_t OldLimit =
Kernel.getFnAttributeAsParsedInteger(Name);
8717std::pair<int32_t, int32_t>
8719 int32_t ThreadLimit =
8720 Kernel.getFnAttributeAsParsedInteger(
"omp_target_thread_limit");
8723 const auto &Attr =
Kernel.getFnAttribute(
"amdgpu-flat-work-group-size");
8724 if (!Attr.isValid() || !Attr.isStringAttribute())
8725 return {0, ThreadLimit};
8726 auto [LBStr, UBStr] = Attr.getValueAsString().split(
',');
8729 return {0, ThreadLimit};
8730 UB = ThreadLimit ? std::min(ThreadLimit, UB) : UB;
8738 return {0, ThreadLimit ? std::min(ThreadLimit, UB) : UB};
8740 return {0, ThreadLimit};
8746 Kernel.addFnAttr(
"omp_target_thread_limit", std::to_string(UB));
8749 Kernel.addFnAttr(
"amdgpu-flat-work-group-size",
8757std::pair<int32_t, int32_t>
8760 return {0,
Kernel.getFnAttributeAsParsedInteger(
"omp_target_num_teams")};
8764 int32_t LB, int32_t UB) {
8772 Kernel.addFnAttr(
"omp_target_num_teams", std::to_string(LB));
8775void OpenMPIRBuilder::setOutlinedTargetRegionFunctionAttributes(
8784 else if (
T.isNVPTX())
8786 else if (
T.isSPIRV())
8792 StringRef EntryFnIDName) {
8793 if (
Config.isTargetDevice()) {
8794 assert(OutlinedFn &&
"The outlined function must exist if embedded");
8798 return new GlobalVariable(
8803Constant *OpenMPIRBuilder::createTargetRegionEntryAddr(
Function *OutlinedFn,
8804 StringRef EntryFnName) {
8808 assert(!
M.getGlobalVariable(EntryFnName,
true) &&
8809 "Named kernel already exists?");
8810 return new GlobalVariable(
8823 if (
Config.isTargetDevice() || !
Config.openMPOffloadMandatory()) {
8827 OutlinedFn = *CBResult;
8829 OutlinedFn =
nullptr;
8835 if (!IsOffloadEntry)
8838 std::string EntryFnIDName =
8840 ? std::string(EntryFnName)
8844 EntryFnName, EntryFnIDName);
8852 setOutlinedTargetRegionFunctionAttributes(OutlinedFn);
8853 auto OutlinedFnID = createOutlinedFunctionID(OutlinedFn, EntryFnIDName);
8854 auto EntryAddr = createTargetRegionEntryAddr(OutlinedFn, EntryFnName);
8856 EntryInfo, EntryAddr, OutlinedFnID,
8858 return OutlinedFnID;
8876 bool IsStandAlone = !BodyGenCB;
8883 MapInfo = &GenMapInfoCB(
Builder.saveIP());
8885 AllocaIP,
Builder.saveIP(), *MapInfo, Info, CustomMapperCB,
8886 true, DeviceAddrCB))
8893 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
8903 SrcLocInfo, DeviceID,
8910 assert(MapperFunc &&
"MapperFunc missing for standalone target data");
8914 if (Info.HasNoWait) {
8924 if (Info.HasNoWait) {
8928 emitBlock(OffloadContBlock, CurFn,
true);
8934 bool RequiresOuterTargetTask = Info.HasNoWait;
8935 if (!RequiresOuterTargetTask)
8936 cantFail(TaskBodyCB(
nullptr,
nullptr,
8940 {}, RTArgs, Info.HasNoWait));
8943 omp::OMPRTL___tgt_target_data_begin_mapper);
8947 for (
auto DeviceMap : Info.DevicePtrInfoMap) {
8951 Builder.CreateStore(LI, DeviceMap.second.second);
8988 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
8997 Value *OffloadingArgs[] = {SrcLocInfo, DeviceID,
9020 return emitIfClause(IfCond, BeginThenGen, BeginElseGen, AllocaIP);
9021 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9036 return emitIfClause(IfCond, EndThenGen, EndElseGen, AllocaIP);
9037 return EndThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9040 return emitIfClause(IfCond, BeginThenGen, EndElseGen, AllocaIP);
9041 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9052 bool IsGPUDistribute) {
9053 assert((IVSize == 32 || IVSize == 64) &&
9054 "IV size is not compatible with the omp runtime");
9056 if (IsGPUDistribute)
9058 ? (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_4
9059 : omp::OMPRTL___kmpc_distribute_static_init_4u)
9060 : (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_8
9061 : omp::OMPRTL___kmpc_distribute_static_init_8u);
9063 Name = IVSize == 32 ? (IVSigned ? omp::OMPRTL___kmpc_for_static_init_4
9064 : omp::OMPRTL___kmpc_for_static_init_4u)
9065 : (IVSigned ? omp::OMPRTL___kmpc_for_static_init_8
9066 : omp::OMPRTL___kmpc_for_static_init_8u);
9073 assert((IVSize == 32 || IVSize == 64) &&
9074 "IV size is not compatible with the omp runtime");
9076 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_4
9077 : omp::OMPRTL___kmpc_dispatch_init_4u)
9078 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_8
9079 : omp::OMPRTL___kmpc_dispatch_init_8u);
9086 assert((IVSize == 32 || IVSize == 64) &&
9087 "IV size is not compatible with the omp runtime");
9089 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_4
9090 : omp::OMPRTL___kmpc_dispatch_next_4u)
9091 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_8
9092 : omp::OMPRTL___kmpc_dispatch_next_8u);
9099 assert((IVSize == 32 || IVSize == 64) &&
9100 "IV size is not compatible with the omp runtime");
9102 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_4
9103 : omp::OMPRTL___kmpc_dispatch_fini_4u)
9104 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_8
9105 : omp::OMPRTL___kmpc_dispatch_fini_8u);
9116 DenseMap<
Value *, std::tuple<Value *, unsigned>> &ValueReplacementMap) {
9124 auto GetUpdatedDIVariable = [&](
DILocalVariable *OldVar,
unsigned arg) {
9128 if (NewVar && (arg == NewVar->
getArg()))
9138 auto UpdateDebugRecord = [&](
auto *DR) {
9141 for (
auto Loc : DR->location_ops()) {
9142 auto Iter = ValueReplacementMap.find(
Loc);
9143 if (Iter != ValueReplacementMap.end()) {
9144 DR->replaceVariableLocationOp(
Loc, std::get<0>(Iter->second));
9145 ArgNo = std::get<1>(Iter->second) + 1;
9149 DR->setVariable(GetUpdatedDIVariable(OldVar, ArgNo));
9154 if (DVR->getNumVariableLocationOps() != 1u) {
9155 DVR->setKillLocation();
9158 Value *
Loc = DVR->getVariableLocationOp(0u);
9165 RequiredBB = &DVR->getFunction()->getEntryBlock();
9167 if (RequiredBB && RequiredBB != CurBB) {
9179 "Unexpected debug intrinsic");
9181 UpdateDebugRecord(&DVR);
9182 MoveDebugRecordToCorrectBlock(&DVR);
9185 for (
auto *DVR : DVRsToDelete)
9186 DVR->getMarker()->MarkedInstr->dropOneDbgRecord(DVR);
9190 Module *M = Func->getParent();
9193 DB.createQualifiedType(dwarf::DW_TAG_pointer_type,
nullptr);
9194 unsigned ArgNo = Func->arg_size();
9196 NewSP,
"dyn_ptr", ArgNo, NewSP->
getFile(), 0, VoidPtrTy,
9197 false, DINode::DIFlags::FlagArtificial);
9199 Argument *LastArg = Func->getArg(Func->arg_size() - 1);
9200 DB.insertDeclare(LastArg, Var, DB.createExpression(),
Loc,
9221 for (
auto &Arg : Inputs)
9222 ParameterTypes.
push_back(Arg->getType()->isPointerTy()
9226 for (
auto &Arg : Inputs)
9227 ParameterTypes.
push_back(Arg->getType());
9235 auto BB = Builder.GetInsertBlock();
9236 auto M = BB->getModule();
9247 if (TargetCpuAttr.isStringAttribute())
9248 Func->addFnAttr(TargetCpuAttr);
9250 auto TargetFeaturesAttr = ParentFn->
getFnAttribute(
"target-features");
9251 if (TargetFeaturesAttr.isStringAttribute())
9252 Func->addFnAttr(TargetFeaturesAttr);
9257 OMPBuilder.
emitUsed(
"llvm.compiler.used", {ExecMode});
9268 Builder.SetInsertPoint(EntryBB);
9274 BasicBlock *UserCodeEntryBB = Builder.GetInsertBlock();
9284 splitBB(Builder,
true,
"outlined.body");
9291 Builder.SetInsertPoint(ExitBB);
9298 Builder.CreateRetVoid();
9302 auto AllocaIP = Builder.saveIP();
9307 const auto &ArgRange =
make_range(Func->arg_begin(), Func->arg_end() - 1);
9339 if (Instr->getFunction() == Func)
9340 Instr->replaceUsesOfWith(
Input, InputCopy);
9346 for (
auto InArg :
zip(Inputs, ArgRange)) {
9348 Argument &Arg = std::get<1>(InArg);
9349 Value *InputCopy =
nullptr;
9352 Arg,
Input, InputCopy, AllocaIP, Builder.saveIP(),
9356 Builder.restoreIP(*AfterIP);
9357 ValueReplacementMap[
Input] = std::make_tuple(InputCopy, Arg.
getArgNo());
9377 DeferredReplacement.push_back(std::make_pair(
Input, InputCopy));
9384 ReplaceValue(
Input, InputCopy, Func);
9388 for (
auto Deferred : DeferredReplacement)
9389 ReplaceValue(std::get<0>(Deferred), std::get<1>(Deferred), Func);
9392 ValueReplacementMap);
9400 Value *TaskWithPrivates,
9401 Type *TaskWithPrivatesTy) {
9403 Type *TaskTy = OMPIRBuilder.Task;
9406 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 0);
9407 Value *Shareds = TaskT;
9417 if (TaskWithPrivatesTy != TaskTy)
9418 Shareds = Builder.CreateStructGEP(TaskTy, TaskT, 0);
9435 const size_t NumOffloadingArrays,
const int SharedArgsOperandNo) {
9440 assert((!NumOffloadingArrays || PrivatesTy) &&
9441 "PrivatesTy cannot be nullptr when there are offloadingArrays"
9474 Type *TaskPtrTy = OMPBuilder.TaskPtr;
9475 [[maybe_unused]]
Type *TaskTy = OMPBuilder.Task;
9481 ".omp_target_task_proxy_func",
9482 Builder.GetInsertBlock()->getModule());
9483 Value *ThreadId = ProxyFn->getArg(0);
9484 Value *TaskWithPrivates = ProxyFn->getArg(1);
9485 ThreadId->
setName(
"thread.id");
9486 TaskWithPrivates->
setName(
"task");
9488 bool HasShareds = SharedArgsOperandNo > 0;
9489 bool HasOffloadingArrays = NumOffloadingArrays > 0;
9492 Builder.SetInsertPoint(EntryBB);
9498 if (HasOffloadingArrays) {
9499 assert(TaskTy != TaskWithPrivatesTy &&
9500 "If there are offloading arrays to pass to the target"
9501 "TaskTy cannot be the same as TaskWithPrivatesTy");
9504 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 1);
9505 for (
unsigned int i = 0; i < NumOffloadingArrays; ++i)
9507 Builder.CreateStructGEP(PrivatesTy, Privates, i));
9511 auto *ArgStructAlloca =
9513 assert(ArgStructAlloca &&
9514 "Unable to find the alloca instruction corresponding to arguments "
9515 "for extracted function");
9517 std::optional<TypeSize> ArgAllocSize =
9519 assert(ArgStructType && ArgAllocSize &&
9520 "Unable to determine size of arguments for extracted function");
9521 uint64_t StructSize = ArgAllocSize->getFixedValue();
9524 Builder.CreateAlloca(ArgStructType,
nullptr,
"structArg");
9526 Value *SharedsSize = Builder.getInt64(StructSize);
9529 OMPBuilder, Builder, TaskWithPrivates, TaskWithPrivatesTy);
9531 Builder.CreateMemCpy(
9532 NewArgStructAlloca, NewArgStructAlloca->
getAlign(), LoadShared,
9534 KernelLaunchArgs.
push_back(NewArgStructAlloca);
9537 Builder.CreateRetVoid();
9543 return GEP->getSourceElementType();
9545 return Alloca->getAllocatedType();
9568 if (OffloadingArraysToPrivatize.
empty())
9569 return OMPIRBuilder.Task;
9572 for (
Value *V : OffloadingArraysToPrivatize) {
9573 assert(V->getType()->isPointerTy() &&
9574 "Expected pointer to array to privatize. Got a non-pointer value "
9577 assert(ArrayTy &&
"ArrayType cannot be nullptr");
9583 "struct.task_with_privates");
9597 EntryFnName, Inputs, CBFunc,
9602 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
9739 TargetTaskAllocaBB->
begin());
9742 auto OI = std::make_unique<OutlineInfo>();
9743 OI->EntryBB = TargetTaskAllocaBB;
9744 OI->OuterAllocBB = AllocaIP.
getBlock();
9749 Builder, AllocaIP, ToBeDeleted, TargetTaskAllocaIP,
"global.tid",
false));
9752 Builder.restoreIP(TargetTaskBodyIP);
9753 if (
Error Err = TaskBodyCB(DeviceID, RTLoc, TargetTaskAllocaIP))
9771 bool NeedsTargetTask = HasNoWait && DeviceID;
9772 if (NeedsTargetTask) {
9778 OffloadingArraysToPrivatize.
push_back(V);
9779 OI->ExcludeArgsFromAggregate.push_back(V);
9783 OI->PostOutlineCB = [
this, ToBeDeleted, Dependencies, NeedsTargetTask,
9784 DeviceID, OffloadingArraysToPrivatize](
9787 "there must be a single user for the outlined function");
9801 const unsigned int NumStaleCIArgs = StaleCI->
arg_size();
9802 bool HasShareds = NumStaleCIArgs > OffloadingArraysToPrivatize.
size() + 1;
9804 NumStaleCIArgs == (OffloadingArraysToPrivatize.
size() + 2)) &&
9805 "Wrong number of arguments for StaleCI when shareds are present");
9806 int SharedArgOperandNo =
9807 HasShareds ? OffloadingArraysToPrivatize.
size() + 1 : 0;
9813 if (!OffloadingArraysToPrivatize.
empty())
9818 *
this,
Builder, StaleCI, PrivatesTy, TaskWithPrivatesTy,
9819 OffloadingArraysToPrivatize.
size(), SharedArgOperandNo);
9821 LLVM_DEBUG(
dbgs() <<
"Proxy task entry function created: " << *ProxyFn
9824 Builder.SetInsertPoint(StaleCI);
9841 OMPRTL___kmpc_omp_target_task_alloc);
9853 M.getDataLayout().getTypeStoreSize(TaskWithPrivatesTy));
9860 auto *ArgStructAlloca =
9862 assert(ArgStructAlloca &&
9863 "Unable to find the alloca instruction corresponding to arguments "
9864 "for extracted function");
9865 std::optional<TypeSize> ArgAllocSize =
9868 "Unable to determine size of arguments for extracted function");
9869 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
9888 TaskSize, SharedsSize,
9891 if (NeedsTargetTask) {
9892 assert(DeviceID &&
"Expected non-empty device ID.");
9902 *
this,
Builder, TaskData, TaskWithPrivatesTy);
9903 Builder.CreateMemCpy(TaskShareds, Alignment, Shareds, Alignment,
9906 if (!OffloadingArraysToPrivatize.
empty()) {
9908 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskData, 1);
9909 for (
unsigned int i = 0; i < OffloadingArraysToPrivatize.
size(); ++i) {
9910 Value *PtrToPrivatize = OffloadingArraysToPrivatize[i];
9917 "ElementType should match ArrayType");
9920 Value *Dst =
Builder.CreateStructGEP(PrivatesTy, Privates, i);
9922 Dst, Alignment, PtrToPrivatize, Alignment,
9923 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(ElementType)));
9927 Value *DepArray =
nullptr;
9928 Value *NumDeps =
nullptr;
9931 NumDeps = Dependencies.
NumDeps;
9932 }
else if (!Dependencies.
Deps.empty()) {
9934 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
9945 if (!NeedsTargetTask) {
9954 ConstantInt::get(
Builder.getInt32Ty(), 0),
9967 }
else if (DepArray) {
9975 {Ident, ThreadID, TaskData, NumDeps, DepArray,
9976 ConstantInt::get(
Builder.getInt32Ty(), 0),
9986 I->eraseFromParent();
9991 << *(
Builder.GetInsertBlock()) <<
"\n");
9993 << *(
Builder.GetInsertBlock()->getParent()->getParent())
10005 CustomMapperCB, IsNonContiguous, DeviceAddrCB))
10028 Builder.restoreIP(IP);
10034 return Builder.saveIP();
10037 bool HasDependencies = !Dependencies.
empty();
10038 bool RequiresOuterTargetTask = HasNoWait || HasDependencies;
10055 if (OutlinedFnID && DeviceID)
10057 EmitTargetCallFallbackCB, KArgs,
10058 DeviceID, RTLoc, TargetTaskAllocaIP);
10066 return EmitTargetCallFallbackCB(OMPBuilder.
Builder.
saveIP());
10073 auto &&EmitTargetCallElse =
10080 if (RequiresOuterTargetTask) {
10087 Dependencies, EmptyRTArgs, HasNoWait);
10089 return EmitTargetCallFallbackCB(Builder.saveIP());
10092 Builder.restoreIP(AfterIP);
10096 auto &&EmitTargetCallThen =
10100 Info.HasNoWait = HasNoWait;
10105 AllocaIP, Builder.saveIP(), Info, RTArgs, MapInfo, CustomMapperCB,
10111 for (
auto [DefaultVal, RuntimeVal] :
10113 NumTeamsC.
push_back(RuntimeVal ? RuntimeVal
10114 : Builder.getInt32(DefaultVal));
10118 auto InitMaxThreadsClause = [&Builder](
Value *
Clause) {
10120 Clause = Builder.CreateIntCast(
Clause, Builder.getInt32Ty(),
10124 auto CombineMaxThreadsClauses = [&Builder](
Value *
Clause,
Value *&Result) {
10127 Result ? Builder.CreateSelect(Builder.CreateICmpULT(Result,
Clause),
10135 Value *MaxThreadsClause =
10137 ? InitMaxThreadsClause(RuntimeAttrs.
MaxThreads)
10140 for (
auto [TeamsVal, TargetVal] :
zip_equal(
10142 Value *TeamsThreadLimitClause = InitMaxThreadsClause(TeamsVal);
10143 Value *NumThreads = InitMaxThreadsClause(TargetVal);
10145 CombineMaxThreadsClauses(TeamsThreadLimitClause, NumThreads);
10146 CombineMaxThreadsClauses(MaxThreadsClause, NumThreads);
10148 NumThreadsC.
push_back(NumThreads ? NumThreads : Builder.getInt32(0));
10151 unsigned NumTargetItems = Info.NumberOfPtrs;
10159 Builder.getInt64Ty(),
10161 : Builder.getInt64(0);
10165 DynCGroupMem = Builder.getInt32(0);
10168 NumTargetItems, RTArgs, TripCount, NumTeamsC, NumThreadsC, DynCGroupMem,
10169 HasNoWait,
false, DynCGroupMemFallback);
10176 if (RequiresOuterTargetTask)
10178 RTLoc, AllocaIP, Dependencies,
10179 KArgs.
RTArgs, Info.HasNoWait);
10182 Builder, OutlinedFnID, EmitTargetCallFallbackCB, KArgs,
10183 RuntimeAttrs.
DeviceID, RTLoc, AllocaIP);
10186 Builder.restoreIP(AfterIP);
10193 if (!OutlinedFnID) {
10194 cantFail(EmitTargetCallElse(AllocaIP, Builder.saveIP(), DeallocBlocks));
10200 cantFail(EmitTargetCallThen(AllocaIP, Builder.saveIP(), DeallocBlocks));
10205 EmitTargetCallElse, AllocaIP));
10218 bool HasNowait,
Value *DynCGroupMem,
10224 Builder.restoreIP(CodeGenIP);
10232 *
this,
Builder, IsOffloadEntry, EntryInfo, DefaultAttrs, OutlinedFn,
10233 OutlinedFnID, Inputs, CBFunc, ArgAccessorFuncCB))
10239 if (!
Config.isTargetDevice())
10241 RuntimeAttrs, IfCond, OutlinedFn, OutlinedFnID, Inputs,
10242 GenMapInfoCB, CustomMapperCB, Dependencies, HasNowait,
10243 DynCGroupMem, DynCGroupMemFallback);
10257 return OS.
str().str();
10262 return OpenMPIRBuilder::getNameWithSeparators(Parts,
Config.firstSeparator(),
10268 auto &Elem = *
InternalVars.try_emplace(Name,
nullptr).first;
10270 assert(Elem.second->getValueType() == Ty &&
10271 "OMP internal variable has different type than requested");
10284 :
M.getTargetTriple().isAMDGPU()
10286 :
DL.getDefaultGlobalsAddressSpace();
10287 auto Linkage = this->
M.getTargetTriple().isWasm()
10295 const llvm::Align PtrAlign =
DL.getPointerABIAlignment(AddressSpaceVal);
10296 GV->setAlignment(std::max(TypeAlign, PtrAlign));
10300 return Elem.second;
10303Value *OpenMPIRBuilder::getOMPCriticalRegionLock(
StringRef CriticalName) {
10304 std::string Prefix =
Twine(
"gomp_critical_user_", CriticalName).
str();
10305 std::string Name = getNameWithSeparators({Prefix,
"var"},
".",
".");
10316 return SizePtrToInt;
10321 std::string VarName) {
10329 return MaptypesArrayGlobal;
10334 unsigned NumOperands,
10343 ArrI8PtrTy,
nullptr,
".offload_baseptrs");
10347 ArrI64Ty,
nullptr,
".offload_sizes");
10358 int64_t DeviceID,
unsigned NumOperands) {
10364 Value *ArgsBaseGEP =
10366 {Builder.getInt32(0), Builder.getInt32(0)});
10369 {Builder.getInt32(0), Builder.getInt32(0)});
10370 Value *ArgSizesGEP =
10372 {Builder.getInt32(0), Builder.getInt32(0)});
10376 Builder.getInt32(NumOperands),
10377 ArgsBaseGEP, ArgsGEP, ArgSizesGEP,
10378 MaptypesArg, MapnamesArg, NullPtr});
10385 assert((!ForEndCall || Info.separateBeginEndCalls()) &&
10386 "expected region end call to runtime only when end call is separate");
10388 auto VoidPtrTy = UnqualPtrTy;
10389 auto VoidPtrPtrTy = UnqualPtrTy;
10391 auto Int64PtrTy = UnqualPtrTy;
10393 if (!Info.NumberOfPtrs) {
10405 Info.RTArgs.BasePointersArray,
10408 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray,
10412 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
10416 ForEndCall && Info.RTArgs.MapTypesArrayEnd ? Info.RTArgs.MapTypesArrayEnd
10417 : Info.RTArgs.MapTypesArray,
10423 if (!Info.EmitDebug)
10427 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.MapNamesArray,
10432 if (!Info.HasMapper)
10436 Builder.CreatePointerCast(Info.RTArgs.MappersArray, VoidPtrPtrTy);
10457 "struct.descriptor_dim");
10459 enum { OffsetFD = 0, CountFD, StrideFD };
10463 for (
unsigned I = 0, L = 0, E = NonContigInfo.
Dims.
size();
I < E; ++
I) {
10466 if (NonContigInfo.
Dims[
I] == 1)
10471 Builder.CreateAlloca(ArrayTy,
nullptr,
"dims");
10472 Builder.restoreIP(CodeGenIP);
10473 for (
unsigned II = 0, EE = NonContigInfo.
Dims[
I];
II < EE; ++
II) {
10474 unsigned RevIdx = EE -
II - 1;
10478 Value *OffsetLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, OffsetFD);
10480 NonContigInfo.
Offsets[L][RevIdx], OffsetLVal,
10481 M.getDataLayout().getPrefTypeAlign(OffsetLVal->
getType()));
10483 Value *CountLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, CountFD);
10485 NonContigInfo.
Counts[L][RevIdx], CountLVal,
10486 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10488 Value *StrideLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, StrideFD);
10490 NonContigInfo.
Strides[L][RevIdx], StrideLVal,
10491 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10494 Builder.restoreIP(CodeGenIP);
10495 Value *DAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
10496 DimsAddr,
Builder.getPtrTy());
10499 Info.RTArgs.PointersArray, 0,
I);
10501 DAddr,
P,
M.getDataLayout().getPrefTypeAlign(
Builder.getPtrTy()));
10506void OpenMPIRBuilder::emitUDMapperArrayInitOrDel(
10510 StringRef Prefix = IsInit ?
".init" :
".del";
10516 Builder.CreateICmpSGT(
Size, Builder.getInt64(1),
"omp.arrayinit.isarray");
10517 Value *DeleteBit = Builder.CreateAnd(
10520 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10521 OpenMPOffloadMappingFlags::OMP_MAP_DELETE)));
10526 Value *BaseIsBegin = Builder.CreateICmpNE(
Base, Begin);
10527 Cond = Builder.CreateOr(IsArray, BaseIsBegin);
10528 DeleteCond = Builder.CreateIsNull(
10533 DeleteCond =
Builder.CreateIsNotNull(
10549 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10550 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10551 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10552 MapTypeArg =
Builder.CreateOr(
10555 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10556 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT)));
10560 Value *OffloadingArgs[] = {MapperHandle,
Base, Begin,
10561 ArraySize, MapTypeArg, MapName};
10572 bool PreserveMemberOfFlags,
bool PropagatePresentToPointee) {
10588 MapperFn->
addFnAttr(Attribute::NoInline);
10589 MapperFn->
addFnAttr(Attribute::NoUnwind);
10599 auto SavedIP =
Builder.saveIP();
10600 Builder.SetInsertPoint(EntryBB);
10612 TypeSize ElementSize =
M.getDataLayout().getTypeStoreSize(ElemTy);
10614 Value *PtrBegin = BeginIn;
10620 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
10621 MapType, MapName, ElementSize, HeadBB,
10632 Builder.CreateICmpEQ(PtrBegin, PtrEnd,
"omp.arraymap.isempty");
10633 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
10639 Builder.CreatePHI(PtrBegin->
getType(), 2,
"omp.arraymap.ptrcurrent");
10640 PtrPHI->addIncoming(PtrBegin, HeadBB);
10645 return Info.takeError();
10649 Value *OffloadingArgs[] = {MapperHandle};
10653 Value *ShiftedPreviousSize =
10657 for (
unsigned I = 0;
I < Info->BasePointers.size(); ++
I) {
10658 Value *CurBaseArg = Info->BasePointers[
I];
10659 Value *CurBeginArg = Info->Pointers[
I];
10660 Value *CurSizeArg = Info->Sizes[
I];
10661 Value *CurNameArg = Info->Names.size()
10666 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10669 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10672 static_cast<uint64_t>(OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
10674 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10675 OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
10733 Value *MemberMapType;
10734 if (PreserveMemberOfFlags || (RawType & AttachBit) ||
10735 Info->HasAttachPtr[
I]) {
10736 if (RawType & MemberOfMask)
10737 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
10739 MemberMapType = OriMapType;
10741 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
10759 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10760 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10761 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10771 Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
10777 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10778 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10779 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10785 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10786 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
10787 Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
10793 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10794 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10800 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10801 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10802 Builder.CreateCondBr(IsFrom, FromBB, EndBB);
10808 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10809 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
10818 CurMapType->
addIncoming(MemberMapType, ToElseBB);
10856 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10857 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
10858 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
10859 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
10860 if (PropagatePresentToPointee && Info->HasAttachPtr[
I])
10862 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10863 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
10864 Value *ImportedModifierBits =
10867 CurMapType, ImportedModifierBits,
"omp.maptype.with.modifiers");
10872 Value *FinalMapType =
10873 (RawType & AttachBit) ? CurMapType : CurMapTypeWithModifiers;
10875 Value *OffloadingArgs[] = {MapperHandle, CurBaseArg, CurBeginArg,
10876 CurSizeArg, FinalMapType, CurNameArg};
10878 auto ChildMapperFn = CustomMapperCB(
I);
10879 if (!ChildMapperFn)
10880 return ChildMapperFn.takeError();
10881 if (*ChildMapperFn) {
10896 Value *PtrNext =
Builder.CreateConstGEP1_32(ElemTy, PtrPHI, 1,
10897 "omp.arraymap.next");
10898 PtrPHI->addIncoming(PtrNext, LastBB);
10899 Value *IsDone =
Builder.CreateICmpEQ(PtrNext, PtrEnd,
"omp.arraymap.isdone");
10901 Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
10906 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
10907 MapType, MapName, ElementSize, DoneBB,
10921 bool IsNonContiguous,
10925 Info.clearArrayInfo();
10928 if (Info.NumberOfPtrs == 0)
10937 Info.RTArgs.BasePointersArray =
Builder.CreateAlloca(
10938 PointerArrayType,
nullptr,
".offload_baseptrs");
10940 Info.RTArgs.PointersArray =
Builder.CreateAlloca(
10941 PointerArrayType,
nullptr,
".offload_ptrs");
10943 PointerArrayType,
nullptr,
".offload_mappers");
10944 Info.RTArgs.MappersArray = MappersArray;
10951 ConstantInt::get(Int64Ty, 0));
10953 for (
unsigned I = 0, E = CombinedInfo.
Sizes.
size();
I < E; ++
I) {
10954 bool IsNonContigEntry =
10956 (
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10958 OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG) != 0);
10961 if (IsNonContigEntry) {
10963 "Index must be in-bounds for NON_CONTIG Dims array");
10965 assert(DimCount > 0 &&
"NON_CONTIG DimCount must be > 0");
10966 ConstSizes[
I] = ConstantInt::get(Int64Ty, DimCount);
10971 ConstSizes[
I] = CI;
10975 RuntimeSizes.
set(
I);
10978 if (RuntimeSizes.
all()) {
10980 Info.RTArgs.SizesArray =
Builder.CreateAlloca(
10981 SizeArrayType,
nullptr,
".offload_sizes");
10987 auto *SizesArrayGbl =
10992 if (!RuntimeSizes.
any()) {
10993 Info.RTArgs.SizesArray = SizesArrayGbl;
10995 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
10996 Align OffloadSizeAlign =
M.getDataLayout().getABIIntegerTypeAlignment(64);
10999 SizeArrayType,
nullptr,
".offload_sizes");
11003 Buffer,
M.getDataLayout().getPrefTypeAlign(Buffer->
getType()),
11004 SizesArrayGbl, OffloadSizeAlign,
11009 Info.RTArgs.SizesArray = Buffer;
11017 for (
auto mapFlag : CombinedInfo.
Types)
11019 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11023 Info.RTArgs.MapTypesArray = MapTypesArrayGbl;
11029 Info.RTArgs.MapNamesArray = MapNamesArrayGbl;
11030 Info.EmitDebug =
true;
11032 Info.RTArgs.MapNamesArray =
11034 Info.EmitDebug =
false;
11039 if (Info.separateBeginEndCalls()) {
11040 bool EndMapTypesDiffer =
false;
11042 if (
Type &
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11043 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT)) {
11044 Type &= ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
11045 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
11046 EndMapTypesDiffer =
true;
11049 if (EndMapTypesDiffer) {
11051 Info.RTArgs.MapTypesArrayEnd = MapTypesArrayGbl;
11056 for (
unsigned I = 0;
I < Info.NumberOfPtrs; ++
I) {
11059 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.BasePointersArray,
11061 Builder.CreateAlignedStore(BPVal, BP,
11062 M.getDataLayout().getPrefTypeAlign(PtrTy));
11064 if (Info.requiresDevicePointerInfo()) {
11066 CodeGenIP =
Builder.saveIP();
11068 Info.DevicePtrInfoMap[BPVal] = {BP,
Builder.CreateAlloca(PtrTy)};
11071 DeviceAddrCB(
I, Info.DevicePtrInfoMap[BPVal].second);
11073 Info.DevicePtrInfoMap[BPVal] = {BP, BP};
11075 DeviceAddrCB(
I, BP);
11081 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray, 0,
11084 Builder.CreateAlignedStore(PVal,
P,
11085 M.getDataLayout().getPrefTypeAlign(PtrTy));
11087 if (RuntimeSizes.
test(
I)) {
11089 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
11095 S,
M.getDataLayout().getPrefTypeAlign(PtrTy));
11098 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
11101 auto CustomMFunc = CustomMapperCB(
I);
11103 return CustomMFunc.takeError();
11105 MFunc =
Builder.CreatePointerCast(*CustomMFunc, PtrTy);
11108 PointerArrayType, MappersArray,
11111 MFunc, MAddr,
M.getDataLayout().getPrefTypeAlign(MAddr->
getType()));
11115 Info.NumberOfPtrs == 0)
11132 Builder.ClearInsertionPoint();
11163 auto CondConstant = CI->getSExtValue();
11165 return ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
11167 return ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
11177 Builder.CreateCondBr(
Cond, ThenBlock, ElseBlock);
11180 if (
Error Err = ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks))
11186 if (
Error Err = ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks))
11195bool OpenMPIRBuilder::checkAndEmitFlushAfterAtomic(
11199 "Unexpected Atomic Ordering.");
11201 bool Flush =
false;
11263 assert(
X.Var->getType()->isPointerTy() &&
11264 "OMP Atomic expects a pointer to target memory");
11265 Type *XElemTy =
X.ElemTy;
11268 "OMP atomic read expected a scalar type");
11270 Value *XRead =
nullptr;
11274 Builder.CreateLoad(XElemTy,
X.Var,
X.IsVolatile,
"omp.atomic.read");
11283 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11286 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11288 XRead = AtomicLoadRes.first;
11295 Builder.CreateLoad(IntCastTy,
X.Var,
X.IsVolatile,
"omp.atomic.load");
11298 XRead =
Builder.CreateBitCast(XLoad, XElemTy,
"atomic.flt.cast");
11300 XRead =
Builder.CreateIntToPtr(XLoad, XElemTy,
"atomic.ptr.cast");
11303 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Read);
11304 Builder.CreateStore(XRead, V.Var, V.IsVolatile);
11315 assert(
X.Var->getType()->isPointerTy() &&
11316 "OMP Atomic expects a pointer to target memory");
11317 Type *XElemTy =
X.ElemTy;
11320 "OMP atomic write expected a scalar type");
11328 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11331 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11339 Builder.CreateBitCast(Expr, IntCastTy,
"atomic.src.int.cast");
11344 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Write);
11351 AtomicUpdateCallbackTy &UpdateOp,
bool IsXBinopExpr,
11352 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11358 Type *XTy =
X.Var->getType();
11360 "OMP Atomic expects a pointer to target memory");
11361 Type *XElemTy =
X.ElemTy;
11364 "OMP atomic update expected a scalar or struct type");
11367 "OpenMP atomic does not support LT or GT operations");
11371 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, RMWOp, UpdateOp,
X.IsVolatile,
11372 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11374 return AtomicResult.takeError();
11375 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Update);
11380Value *OpenMPIRBuilder::emitRMWOpAsInstruction(
Value *Src1,
Value *Src2,
11384 return Builder.CreateAdd(Src1, Src2);
11386 return Builder.CreateSub(Src1, Src2);
11388 return Builder.CreateAnd(Src1, Src2);
11390 return Builder.CreateNeg(Builder.CreateAnd(Src1, Src2));
11392 return Builder.CreateOr(Src1, Src2);
11394 return Builder.CreateXor(Src1, Src2);
11433Expected<std::pair<Value *, Value *>> OpenMPIRBuilder::emitAtomicUpdate(
11436 AtomicUpdateCallbackTy &UpdateOp,
bool VolatileX,
bool IsXBinopExpr,
11437 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11439 bool emitRMWOp =
false;
11447 emitRMWOp = XElemTy;
11450 emitRMWOp = (IsXBinopExpr && XElemTy);
11457 std::pair<Value *, Value *> Res;
11459 AtomicRMWInst *RMWInst =
11460 Builder.CreateAtomicRMW(RMWOp,
X, Expr, llvm::MaybeAlign(), AO);
11461 if (
T.isAMDGPU()) {
11462 if (IsIgnoreDenormalMode)
11463 RMWInst->
setMetadata(
"amdgpu.ignore.denormal.mode",
11465 if (!IsFineGrainedMemory)
11466 RMWInst->
setMetadata(
"amdgpu.no.fine.grained.memory",
11468 if (!IsRemoteMemory)
11472 Res.first = RMWInst;
11477 Res.second = Res.first;
11479 Res.second = emitRMWOpAsInstruction(Res.first, Expr, RMWOp);
11482 Builder.CreateLoad(XElemTy,
X,
X->getName() +
".atomic.load");
11488 OpenMPIRBuilder::AtomicInfo atomicInfo(
11490 OldVal->
getAlign(),
true , AllocaIP,
X);
11491 auto AtomicLoadRes = atomicInfo.EmitAtomicLoadLibcall(AO);
11494 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11501 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11502 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11503 Builder.SetInsertPoint(ContBB);
11505 PHI->addIncoming(AtomicLoadRes.first, CurBB);
11507 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11510 Value *Upd = *CBResult;
11511 Builder.CreateStore(Upd, NewAtomicAddr);
11514 auto Result = atomicInfo.EmitAtomicCompareExchangeLibcall(
11515 AtomicLoadRes.second, NewAtomicAddr, AO, Failure);
11516 LoadInst *PHILoad =
Builder.CreateLoad(XElemTy,
Result.first);
11517 PHI->addIncoming(PHILoad,
Builder.GetInsertBlock());
11520 Res.first = OldExprVal;
11523 if (UnreachableInst *ExitTI =
11526 Builder.SetInsertPoint(ExitBB);
11528 Builder.SetInsertPoint(ExitTI);
11531 IntegerType *IntCastTy =
11534 Builder.CreateLoad(IntCastTy,
X,
X->getName() +
".atomic.load");
11544 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11551 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11552 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11553 Builder.SetInsertPoint(ContBB);
11555 PHI->addIncoming(OldVal, CurBB);
11560 OldExprVal =
Builder.CreateBitCast(
PHI, XElemTy,
11561 X->getName() +
".atomic.fltCast");
11563 OldExprVal =
Builder.CreateIntToPtr(
PHI, XElemTy,
11564 X->getName() +
".atomic.ptrCast");
11568 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11571 Value *Upd = *CBResult;
11572 Builder.CreateStore(Upd, NewAtomicAddr);
11573 LoadInst *DesiredVal =
Builder.CreateLoad(IntCastTy, NewAtomicAddr);
11577 X,
PHI, DesiredVal, llvm::MaybeAlign(), AO, Failure);
11578 Result->setVolatile(VolatileX);
11579 Value *PreviousVal =
Builder.CreateExtractValue(Result, 0);
11580 Value *SuccessFailureVal =
Builder.CreateExtractValue(Result, 1);
11581 PHI->addIncoming(PreviousVal,
Builder.GetInsertBlock());
11582 Builder.CreateCondBr(SuccessFailureVal, ExitBB, ContBB);
11584 Res.first = OldExprVal;
11588 if (UnreachableInst *ExitTI =
11591 Builder.SetInsertPoint(ExitBB);
11593 Builder.SetInsertPoint(ExitTI);
11604 bool UpdateExpr,
bool IsPostfixUpdate,
bool IsXBinopExpr,
11605 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11610 Type *XTy =
X.Var->getType();
11612 "OMP Atomic expects a pointer to target memory");
11613 Type *XElemTy =
X.ElemTy;
11616 "OMP atomic capture expected a scalar or struct type");
11618 "OpenMP atomic does not support LT or GT operations");
11625 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, AtomicOp, UpdateOp,
X.IsVolatile,
11626 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11629 Value *CapturedVal =
11630 (IsPostfixUpdate ? AtomicResult->first : AtomicResult->second);
11631 Builder.CreateStore(CapturedVal, V.Var, V.IsVolatile);
11633 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Capture);
11641 bool IsFailOnly,
bool IsWeak) {
11645 IsPostfixUpdate, IsFailOnly, Failure, IsWeak);
11657 assert(
X.Var->getType()->isPointerTy() &&
11658 "OMP atomic expects a pointer to target memory");
11661 assert(V.Var->getType()->isPointerTy() &&
"v.var must be of pointer type");
11662 assert(V.ElemTy ==
X.ElemTy &&
"x and v must be of same type");
11665 bool IsInteger = E->getType()->isIntegerTy();
11667 if (
Op == OMPAtomicCompareOp::EQ) {
11670 Value *OldValue =
nullptr;
11671 Value *SuccessOrFail =
nullptr;
11709 X.Var->getName() +
".atomic.load");
11715 Value *EIsNaN =
Builder.CreateFCmpUNO(E, E,
"atomic.e.isnan");
11716 Value *XIsNaN =
Builder.CreateFCmpUNO(XFP, XFP,
"atomic.x.isnan");
11717 Value *EitherNaN =
Builder.CreateOr(EIsNaN, XIsNaN,
"atomic.either.nan");
11722 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11726 M.getContext(),
X.Var->getName() +
".atomic.nan",
F, ExitBB);
11728 M.getContext(),
X.Var->getName() +
".atomic.notnan",
F, ExitBB);
11730 M.getContext(),
X.Var->getName() +
".atomic.zero",
F, ExitBB);
11732 M.getContext(),
X.Var->getName() +
".atomic.normal",
F, ExitBB);
11736 Builder.SetInsertPoint(CurBB);
11737 Builder.CreateCondBr(EitherNaN, NaNBB, NotNaNBB);
11740 Builder.SetInsertPoint(NaNBB);
11744 Builder.SetInsertPoint(NotNaNBB);
11747 X.Var->getName() +
".atomic.xiszero");
11749 "atomic.e.iszero");
11750 Value *BothZero =
Builder.CreateAnd(XIsZero, EIsZero,
"atomic.both.zero");
11751 Builder.CreateCondBr(BothZero, ZeroBB, NormalBB);
11754 Builder.SetInsertPoint(ZeroBB);
11756 X.Var, XCurr, DBCast,
MaybeAlign(), AO, Failure);
11758 Value *OldZero =
Builder.CreateExtractValue(ResZero, 0);
11759 Value *OkZero =
Builder.CreateExtractValue(ResZero, 1);
11763 Builder.SetInsertPoint(NormalBB);
11765 X.Var, EBCast, DBCast,
MaybeAlign(), AO, Failure);
11767 Value *OldNormal =
Builder.CreateExtractValue(ResNormal, 0);
11768 Value *OkNormal =
Builder.CreateExtractValue(ResNormal, 1);
11774 Builder.CreatePHI(IntCastTy, 3,
X.Var->getName() +
".atomic.old");
11779 X.Var->getName() +
".atomic.ok");
11786 Builder.SetInsertPoint(ExitBB);
11791 OldValue =
Builder.CreateBitCast(OldIntPHI,
X.ElemTy,
11792 X.Var->getName() +
".atomic.old.fp");
11793 SuccessOrFail = SuccessPHI;
11801 Result =
Builder.CreateAtomicCmpXchg(
X.Var, EBCast, DBCast,
11807 Result->setWeak(IsWeak);
11810 OldValue =
Builder.CreateExtractValue(Result, 0);
11812 OldValue =
Builder.CreateBitCast(OldValue,
X.ElemTy);
11814 "OldValue and V must be of same type");
11815 if (IsPostfixUpdate) {
11816 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
11818 SuccessOrFail =
Builder.CreateExtractValue(Result, 1);
11822 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11824 CurBBTI,
X.Var->getName() +
".atomic.exit");
11830 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
11832 Builder.SetInsertPoint(ContBB);
11833 Builder.CreateStore(OldValue, V.Var);
11839 Builder.SetInsertPoint(ExitBB);
11841 Builder.SetInsertPoint(ExitTI);
11844 Value *CapturedValue =
11845 Builder.CreateSelect(SuccessOrFail, E, OldValue);
11846 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
11852 assert(R.Var->getType()->isPointerTy() &&
11853 "r.var must be of pointer type");
11854 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
11856 Value *SuccessFailureVal =
11857 Builder.CreateExtractValue(Result, 1);
11858 Value *ResultCast =
11859 R.IsSigned ?
Builder.CreateSExt(SuccessFailureVal, R.ElemTy)
11860 :
Builder.CreateZExt(SuccessFailureVal, R.ElemTy);
11861 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
11870 "OldValue and V must be of same type");
11871 if (IsPostfixUpdate) {
11872 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
11877 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11879 CurBBTI,
X.Var->getName() +
".atomic.exit");
11885 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
11887 Builder.SetInsertPoint(ContBB);
11888 Builder.CreateStore(OldValue, V.Var);
11894 Builder.SetInsertPoint(ExitBB);
11896 Builder.SetInsertPoint(ExitTI);
11899 Value *CapturedValue =
11900 Builder.CreateSelect(SuccessOrFail, E, OldValue);
11901 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
11907 assert(R.Var->getType()->isPointerTy() &&
11908 "r.var must be of pointer type");
11909 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
11911 Value *ResultCast = R.IsSigned
11912 ?
Builder.CreateSExt(SuccessOrFail, R.ElemTy)
11913 :
Builder.CreateZExt(SuccessOrFail, R.ElemTy);
11914 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
11918 assert((
Op == OMPAtomicCompareOp::MAX ||
Op == OMPAtomicCompareOp::MIN) &&
11919 "Op should be either max or min at this point");
11920 assert(!IsFailOnly &&
"IsFailOnly is only valid when the comparison is ==");
11931 if (IsXBinopExpr) {
11960 Value *CapturedValue =
nullptr;
11961 if (IsPostfixUpdate) {
11962 CapturedValue = OldValue;
11987 Value *NonAtomicCmp =
Builder.CreateCmp(Pred, OldValue, E);
11988 CapturedValue =
Builder.CreateSelect(NonAtomicCmp, E, OldValue);
11990 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
11994 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Compare);
12014 if (&OuterAllocaBB ==
Builder.GetInsertBlock()) {
12041 bool SubClausesPresent =
12042 (NumTeamsLower || NumTeamsUpper || ThreadLimit || IfExpr);
12044 if (!
Config.isTargetDevice() && SubClausesPresent) {
12045 assert((NumTeamsLower ==
nullptr || NumTeamsUpper !=
nullptr) &&
12046 "if lowerbound is non-null, then upperbound must also be non-null "
12047 "for bounds on num_teams");
12049 if (NumTeamsUpper ==
nullptr)
12050 NumTeamsUpper =
Builder.getInt32(0);
12052 if (NumTeamsLower ==
nullptr)
12053 NumTeamsLower = NumTeamsUpper;
12057 "argument to if clause must be an integer value");
12061 IfExpr =
Builder.CreateICmpNE(IfExpr,
12062 ConstantInt::get(IfExpr->
getType(), 0));
12063 NumTeamsUpper =
Builder.CreateSelect(
12064 IfExpr, NumTeamsUpper,
Builder.getInt32(1),
"numTeamsUpper");
12067 NumTeamsLower =
Builder.CreateSelect(
12068 IfExpr, NumTeamsLower,
Builder.getInt32(1),
"numTeamsLower");
12071 if (ThreadLimit ==
nullptr)
12072 ThreadLimit =
Builder.getInt32(0);
12076 Value *NumTeamsLowerInt32 =
12078 Value *NumTeamsUpperInt32 =
12080 Value *ThreadLimitInt32 =
12087 {Ident, ThreadNum, NumTeamsLowerInt32, NumTeamsUpperInt32,
12088 ThreadLimitInt32});
12093 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
12096 auto OI = std::make_unique<OutlineInfo>();
12097 OI->EntryBB = AllocaBB;
12098 OI->ExitBB = ExitBB;
12099 OI->OuterAllocBB = &OuterAllocaBB;
12105 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"gid",
true));
12107 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"tid",
true));
12109 auto HostPostOutlineCB = [
this, Ident,
12110 ToBeDeleted](
Function &OutlinedFn)
mutable {
12115 "there must be a single user for the outlined function");
12120 "Outlined function must have two or three arguments only");
12122 bool HasShared = OutlinedFn.
arg_size() == 3;
12130 assert(StaleCI &&
"Error while outlining - no CallInst user found for the "
12131 "outlined function.");
12132 Builder.SetInsertPoint(StaleCI);
12139 omp::RuntimeFunction::OMPRTL___kmpc_fork_teams),
12143 I->eraseFromParent();
12146 if (!
Config.isTargetDevice())
12147 OI->PostOutlineCB = HostPostOutlineCB;
12151 Builder.SetInsertPoint(ExitBB);
12164 if (OuterAllocaBB ==
Builder.GetInsertBlock()) {
12179 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
12184 if (
Config.isTargetDevice()) {
12185 auto OI = std::make_unique<OutlineInfo>();
12186 OI->OuterAllocBB = OuterAllocIP.
getBlock();
12187 OI->EntryBB = AllocaBB;
12188 OI->ExitBB = ExitBB;
12189 OI->OuterDeallocBBs.reserve(OuterDeallocBlocks.
size());
12190 copy(OuterDeallocBlocks, OI->OuterDeallocBBs.
end());
12194 Builder.SetInsertPoint(ExitBB);
12201 std::string VarName) {
12210 return MapNamesArrayGlobal;
12215void OpenMPIRBuilder::initializeTypes(
Module &M) {
12219 unsigned ProgramAS = M.getDataLayout().getProgramAddressSpace();
12220#define OMP_TYPE(VarName, InitValue) VarName = InitValue;
12221#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \
12222 VarName##Ty = ArrayType::get(ElemTy, ArraySize); \
12223 VarName##PtrTy = PointerType::get(Ctx, DefaultTargetAS);
12224#define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) \
12225 VarName = FunctionType::get(ReturnType, {__VA_ARGS__}, IsVarArg); \
12226 VarName##Ptr = PointerType::get(Ctx, ProgramAS);
12227#define OMP_STRUCT_TYPE(VarName, StructName, Packed, ...) \
12228 T = StructType::getTypeByName(Ctx, StructName); \
12230 T = StructType::create(Ctx, {__VA_ARGS__}, StructName, Packed); \
12232 VarName##Ptr = PointerType::get(Ctx, DefaultTargetAS);
12233#include "llvm/Frontend/OpenMP/OMPKinds.def"
12244 while (!Worklist.
empty()) {
12248 if (
BlockSet.insert(SuccBB).second)
12253std::unique_ptr<CodeExtractor>
12255 bool ArgsInZeroAddressSpace,
12257 return std::make_unique<CodeExtractor>(
12267 Suffix.
str(), ArgsInZeroAddressSpace);
12270std::unique_ptr<CodeExtractor> DeviceSharedMemOutlineInfo::createCodeExtractor(
12272 return std::make_unique<DeviceSharedMemCodeExtractor>(
12273 OMPBuilder, Blocks,
nullptr,
12281 OuterDeallocBBs.empty()
12284 Suffix.
str(), ArgsInZeroAddressSpace);
12294 Name.empty() ? Addr->
getName() : Name,
Size, Flags, 0);
12306 Fn->
addFnAttr(
"uniform-work-group-size");
12307 Fn->
addFnAttr(Attribute::MustProgress);
12325 auto &&GetMDInt = [
this](
unsigned V) {
12332 NamedMDNode *MD =
M.getOrInsertNamedMetadata(
"omp_offload.info");
12333 auto &&TargetRegionMetadataEmitter =
12334 [&
C, MD, &OrderedEntries, &GetMDInt, &GetMDString](
12349 GetMDInt(E.getKind()), GetMDInt(EntryInfo.DeviceID),
12350 GetMDInt(EntryInfo.FileID), GetMDString(EntryInfo.ParentName),
12351 GetMDInt(EntryInfo.Line), GetMDInt(EntryInfo.Count),
12352 GetMDInt(E.getOrder())};
12355 OrderedEntries[E.getOrder()] = std::make_pair(&E, EntryInfo);
12364 auto &&DeviceGlobalVarMetadataEmitter =
12365 [&
C, &OrderedEntries, &GetMDInt, &GetMDString, MD](
12375 Metadata *
Ops[] = {GetMDInt(E.getKind()), GetMDString(MangledName),
12376 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
12380 OrderedEntries[E.getOrder()] = std::make_pair(&E, varInfo);
12387 DeviceGlobalVarMetadataEmitter);
12389 for (
const auto &E : OrderedEntries) {
12390 assert(E.first &&
"All ordered entries must exist!");
12391 if (
const auto *CE =
12394 if (!CE->getID() || !CE->getAddress()) {
12398 if (!
M.getNamedValue(FnName))
12406 }
else if (
const auto *CE =
dyn_cast<
12415 if (
Config.isTargetDevice() &&
Config.hasRequiresUnifiedSharedMemory())
12417 if (!CE->getAddress()) {
12422 if (CE->getVarSize() == 0)
12426 assert(((
Config.isTargetDevice() && !CE->getAddress()) ||
12427 (!
Config.isTargetDevice() && CE->getAddress())) &&
12428 "Declaret target link address is set.");
12429 if (
Config.isTargetDevice())
12431 if (!CE->getAddress()) {
12438 if (!CE->getAddress()) {
12451 if ((
GV->hasLocalLinkage() ||
GV->hasHiddenVisibility()) &&
12455 OMPTargetGlobalVarEntryIndirectVTable))
12464 Flags, CE->getLinkage(), CE->getVarName());
12467 Flags, CE->getLinkage());
12478 if (
Config.hasRequiresFlags() && !
Config.isTargetDevice())
12484 Config.getRequiresFlags());
12494 OS <<
"_" <<
Count;
12499 unsigned NewCount = getTargetRegionEntryInfoCount(EntryInfo);
12502 EntryInfo.
Line, NewCount);
12510 auto FileIDInfo = CallBack();
12513 ID =
Status->getUniqueID();
12514 FileID =
Status->getUniqueID().getFile();
12518 FileID =
hash_value(std::get<0>(FileIDInfo));
12522 std::get<1>(FileIDInfo));
12528 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12530 !(Remain & 1); Remain = Remain >> 1)
12548 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12550 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12557 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12563 Flags &=
~omp::OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
12564 Flags |= MemberOfFlag;
12570 bool IsDeclaration,
bool IsExternallyVisible,
12572 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12573 std::vector<Triple> TargetTriple,
Type *LlvmPtrTy,
12574 std::function<
Constant *()> GlobalInitializer,
12585 Config.hasRequiresUnifiedSharedMemory())) {
12590 if (!IsExternallyVisible)
12592 OS <<
"_decl_tgt_ref_ptr";
12595 Value *Ptr =
M.getNamedValue(PtrName);
12604 if (!
Config.isTargetDevice()) {
12605 if (GlobalInitializer)
12606 GV->setInitializer(GlobalInitializer());
12612 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12613 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12614 GlobalInitializer, VariableLinkage, LlvmPtrTy,
cast<Constant>(Ptr));
12626 bool IsDeclaration,
bool IsExternallyVisible,
12628 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12629 std::vector<Triple> TargetTriple,
12630 std::function<
Constant *()> GlobalInitializer,
12634 (TargetTriple.empty() && !
Config.isTargetDevice()))
12645 !
Config.hasRequiresUnifiedSharedMemory()) {
12647 VarName = MangledName;
12650 if (!IsDeclaration)
12652 M.getDataLayout().getTypeSizeInBits(LlvmVal->
getValueType()), 8);
12655 Linkage = (VariableLinkage) ? VariableLinkage() : LlvmVal->
getLinkage();
12659 if (
Config.isTargetDevice() &&
12668 if (!
M.getNamedValue(RefName)) {
12672 GvAddrRef->setConstant(
true);
12674 GvAddrRef->setInitializer(Addr);
12675 GeneratedRefs.push_back(GvAddrRef);
12684 if (
Config.isTargetDevice()) {
12685 VarName = (Addr) ? Addr->
getName() :
"";
12689 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12690 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12691 LlvmPtrTy, GlobalInitializer, VariableLinkage);
12692 VarName = (Addr) ? Addr->
getName() :
"";
12694 VarSize =
M.getDataLayout().getPointerSize();
12713 auto &&GetMDInt = [MN](
unsigned Idx) {
12718 auto &&GetMDString = [MN](
unsigned Idx) {
12720 return V->getString();
12723 switch (GetMDInt(0)) {
12727 case OffloadEntriesInfoManager::OffloadEntryInfo::
12728 OffloadingEntryInfoTargetRegion: {
12738 case OffloadEntriesInfoManager::OffloadEntryInfo::
12739 OffloadingEntryInfoDeviceGlobalVar:
12752 if (HostFilePath.
empty())
12756 if (std::error_code Err = Buf.getError()) {
12758 "OpenMPIRBuilder: " +
12766 if (std::error_code Err =
M.getError()) {
12768 (
"error parsing host file inside of OpenMPIRBuilder: " + Err.message())
12782 "expected a valid insertion block for creating an iterator loop");
12792 Builder.getCurrentDebugLocation(),
"omp.it.cont");
12804 T->eraseFromParent();
12813 if (!BodyBr || BodyBr->getSuccessor() != CLI->
getLatch()) {
12815 "iterator bodygen must terminate the canonical body with an "
12816 "unconditional branch to the loop latch",
12840 for (
const auto &
ParamAttr : ParamAttrs) {
12883 return std::string(Out.
str());
12891 unsigned VecRegSize;
12893 ISADataTy ISAData[] = {
12912 for (
char Mask :
Masked) {
12913 for (
const ISADataTy &
Data : ISAData) {
12916 Out <<
"_ZGV" <<
Data.ISA << Mask;
12918 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
12932template <
typename T>
12935 StringRef MangledName,
bool OutputBecomesInput,
12939 Out << Prefix << ISA << LMask << VLEN;
12940 if (OutputBecomesInput)
12942 Out << ParSeq <<
'_' << MangledName;
12951 bool OutputBecomesInput,
12956 OutputBecomesInput, Fn);
12958 OutputBecomesInput, Fn);
12962 OutputBecomesInput, Fn);
12964 OutputBecomesInput, Fn);
12968 OutputBecomesInput, Fn);
12970 OutputBecomesInput, Fn);
12975 OutputBecomesInput, Fn);
12986 char ISA,
unsigned NarrowestDataSize,
bool OutputBecomesInput) {
12987 assert((ISA ==
'n' || ISA ==
's') &&
"Expected ISA either 's' or 'n'.");
12999 OutputBecomesInput, Fn);
13006 OutputBecomesInput, Fn);
13008 OutputBecomesInput, Fn);
13012 OutputBecomesInput, Fn);
13016 OutputBecomesInput, Fn);
13025 OutputBecomesInput, Fn);
13032 MangledName, OutputBecomesInput, Fn);
13034 MangledName, OutputBecomesInput, Fn);
13038 MangledName, OutputBecomesInput, Fn);
13042 MangledName, OutputBecomesInput, Fn);
13052 return OffloadEntriesTargetRegion.empty() &&
13053 OffloadEntriesDeviceGlobalVar.empty();
13056unsigned OffloadEntriesInfoManager::getTargetRegionEntryInfoCount(
13058 auto It = OffloadEntriesTargetRegionCount.find(
13059 getTargetRegionEntryCountKey(EntryInfo));
13060 if (It == OffloadEntriesTargetRegionCount.end())
13065void OffloadEntriesInfoManager::incrementTargetRegionEntryInfoCount(
13067 OffloadEntriesTargetRegionCount[getTargetRegionEntryCountKey(EntryInfo)] =
13068 EntryInfo.
Count + 1;
13074 OffloadEntriesTargetRegion[EntryInfo] =
13077 ++OffloadingEntriesNum;
13083 assert(EntryInfo.
Count == 0 &&
"expected default EntryInfo");
13086 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
13090 if (OMPBuilder->Config.isTargetDevice()) {
13095 auto &Entry = OffloadEntriesTargetRegion[EntryInfo];
13096 Entry.setAddress(Addr);
13098 Entry.setFlags(Flags);
13104 "Target region entry already registered!");
13106 OffloadEntriesTargetRegion[EntryInfo] = Entry;
13107 ++OffloadingEntriesNum;
13109 incrementTargetRegionEntryInfoCount(EntryInfo);
13116 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
13118 auto It = OffloadEntriesTargetRegion.find(EntryInfo);
13119 if (It == OffloadEntriesTargetRegion.end()) {
13123 if (!IgnoreAddressId && (It->second.getAddress() || It->second.getID()))
13131 for (
const auto &It : OffloadEntriesTargetRegion) {
13132 Action(It.first, It.second);
13138 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
13139 ++OffloadingEntriesNum;
13145 if (OMPBuilder->Config.isTargetDevice()) {
13149 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
13151 if (Entry.getVarSize() == 0) {
13152 Entry.setVarSize(VarSize);
13153 Entry.setLinkage(Linkage);
13157 Entry.setVarSize(VarSize);
13158 Entry.setLinkage(Linkage);
13159 Entry.setAddress(Addr);
13162 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
13163 assert(Entry.isValid() && Entry.getFlags() == Flags &&
13164 "Entry not initialized!");
13165 if (Entry.getVarSize() == 0) {
13166 Entry.setVarSize(VarSize);
13167 Entry.setLinkage(Linkage);
13174 OffloadEntriesDeviceGlobalVar.try_emplace(VarName, OffloadingEntriesNum,
13175 Addr, VarSize, Flags, Linkage,
13178 OffloadEntriesDeviceGlobalVar.try_emplace(
13179 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage,
"");
13180 ++OffloadingEntriesNum;
13187 for (
const auto &E : OffloadEntriesDeviceGlobalVar)
13188 Action(E.getKey(), E.getValue());
13195void CanonicalLoopInfo::collectControlBlocks(
13202 BBs.
append({getPreheader(), Header,
Cond, Latch, Exit, getAfter()});
13214void CanonicalLoopInfo::setTripCount(
Value *TripCount) {
13226void CanonicalLoopInfo::mapIndVar(
13236 for (
Use &U : OldIV->
uses()) {
13240 if (
User->getParent() == getCond())
13242 if (
User->getParent() == getLatch())
13248 Value *NewIV = Updater(OldIV);
13251 for (Use *U : ReplacableUses)
13272 "Preheader must terminate with unconditional branch");
13274 "Preheader must jump to header");
13278 "Header must terminate with unconditional branch");
13279 assert(Header->getSingleSuccessor() == Cond &&
13280 "Header must jump to exiting block");
13283 assert(Cond->getSinglePredecessor() == Header &&
13284 "Exiting block only reachable from header");
13287 "Exiting block must terminate with conditional branch");
13289 "Exiting block's first successor jump to the body");
13291 "Exiting block's second successor must exit the loop");
13295 "Body only reachable from exiting block");
13300 "Latch must terminate with unconditional branch");
13301 assert(Latch->getSingleSuccessor() == Header &&
"Latch must jump to header");
13304 assert(Latch->getSinglePredecessor() !=
nullptr);
13309 "Exit block must terminate with unconditional branch");
13310 assert(Exit->getSingleSuccessor() == After &&
13311 "Exit block must jump to after block");
13315 "After block only reachable from exit block");
13319 assert(IndVar &&
"Canonical induction variable not found?");
13321 "Induction variable must be an integer");
13323 "Induction variable must be a PHI in the loop header");
13329 auto *NextIndVar =
cast<PHINode>(IndVar)->getIncomingValue(1);
13337 assert(TripCount &&
"Loop trip count not found?");
13339 "Trip count and induction variable must have the same type");
13343 "Exit condition must be a signed less-than comparison");
13345 "Exit condition must compare the induction variable");
13347 "Exit condition must compare with the trip count");
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)
static cl::opt< unsigned > TileSize("fuse-matrix-tile-size", cl::init(4), cl::Hidden, cl::desc("Tile size for matrix instruction fusion using square-shaped tiles."))
uint64_t IntrinsicInst * II
#define OMP_KERNEL_ARG_VERSION
Provides definitions for Target specific Grid Values.
static 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 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 Expected< Function * > createOutlinedFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, const OpenMPIRBuilder::TargetKernelDefaultAttrs &DefaultAttrs, StringRef FuncName, SmallVectorImpl< Value * > &Inputs, OpenMPIRBuilder::TargetBodyGenCallbackTy &CBFunc, OpenMPIRBuilder::TargetGenArgAccessorsCallbackTy &ArgAccessorFuncCB)
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< double > UnrollThresholdFactor("openmp-ir-builder-unroll-threshold-factor", cl::Hidden, cl::desc("Factor for the unroll threshold to account for code " "simplifications still taking place"), cl::init(1.5))
static 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 int32_t computeHeuristicUnrollFactor(CanonicalLoopInfo *CLI)
Heuristically determine the best-performant unroll factor for CLI.
static void emitTargetCall(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, 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 Value * emitTaskDependencies(OpenMPIRBuilder &OMPBuilder, const SmallVectorImpl< OpenMPIRBuilder::DependData > &Dependencies)
static Error emitTargetOutlinedFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, bool IsOffloadEntry, TargetRegionEntryInfo &EntryInfo, const OpenMPIRBuilder::TargetKernelDefaultAttrs &DefaultAttrs, Function *&OutlinedFn, Constant *&OutlinedFnID, SmallVectorImpl< Value * > &Inputs, OpenMPIRBuilder::TargetBodyGenCallbackTy &CBFunc, OpenMPIRBuilder::TargetGenArgAccessorsCallbackTy &ArgAccessorFuncCB)
static 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 std::unique_ptr< TargetMachine > createTargetMachine(Function *F, CodeGenOptLevel OptLevel)
Create the TargetMachine object to query the backend for optimization preferences.
static FunctionCallee getKmpcForStaticInitForType(Type *Ty, Module &M, OpenMPIRBuilder &OMPBuilder)
static void 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 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 ...
const SmallVectorImpl< MachineOperand > & Cond
Remove Loads Into Fake Uses
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
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 cl::opt< unsigned > MaxThreads("xcore-max-threads", cl::Optional, cl::desc("Maximum number of threads (for emulation thread-local storage)"), cl::Hidden, cl::value_desc("number"), cl::init(8))
static const uint32_t IV[8]
Class for arbitrary precision integers.
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),...
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.
A function analysis which provides an AssumptionCache.
LLVM_ABI AssumptionCache run(Function &F, FunctionAnalysisManager &)
A cache of @llvm.assume calls within a function.
An instruction that atomically checks whether a specified value is in a memory location,...
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 InstListType::const_iterator getFirstNonPHIOrDbg(bool SkipPseudoOp=true) const
Returns a pointer to the first instruction in this block that is not a PHINode or a debug intrinsic,...
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 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.
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 * getTruncOrBitCast(Constant *C, Type *Ty)
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 * getSizeOf(Type *Ty)
getSizeOf constant expr - computes the (alloc) size of a type (in address-units, not bits) in a targe...
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.
LLVM_ABI DominatorTree run(Function &F, FunctionAnalysisManager &)
Run the analysis pass over a function and produce a dominator tree.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
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.
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
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.
InsertPoint - A saved insertion point.
BasicBlock * getBlock() const
bool isSet() const
Returns true if this insert point is set.
BasicBlock::iterator getPoint() const
Common base class shared among various IRBuilders.
InsertPoint saveIP() const
Returns the current insert 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 const DebugLoc & getStableDebugLoc() const
Fetch the debug location for this node, unless this is a debug intrinsic, in which case fetch the deb...
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 const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
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.
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.
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 into a single loop.
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 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 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 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)
Generator for 'omp target'.
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.
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
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)
Generator for #omp taskloop
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)
The omp target interface.
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.
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 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)
Modifies the canonical loop to be a workshare loop.
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 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 PropagatePresentToPointee=false)
Emit the user-defined mapper function.
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.
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 void createTaskwait(const LocationDescription &Loc, DependenciesInfo Dependencies={})
Generator for 'omp taskwait'.
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...
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...
Analysis pass that exposes the ScalarEvolution for a function.
LLVM_ABI ScalarEvolution run(Function &F, FunctionAnalysisManager &AM)
The main scalar evolution driver.
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.
Analysis pass providing the TargetTransformInfo.
LLVM_ABI Result run(const Function &F, FunctionAnalysisManager &)
TargetTransformInfo Result
Analysis pass providing the TargetLibraryInfo.
Target - Wrapper for Target specific information.
TargetMachine * createTargetMachine(const Triple &TT, StringRef CPU, StringRef Features, const TargetOptions &Options, std::optional< Reloc::Model > RM, std::optional< CodeModel::Model > CM=std::nullopt, CodeGenOptLevel OL=CodeGenOptLevel::Default, bool JIT=false) const
createTargetMachine - Create a target specific machine implementation for the specified Triple.
Triple - Helper class for working with autoconf configuration names.
bool isPPC() const
Tests whether the target is PowerPC (32- or 64-bit LE or BE).
bool isX86() const
Tests whether the target is x86 (32- or 64-bit).
bool isWasm() const
Tests whether the target is wasm (32- and 64-bit).
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
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.
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 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.
Produce an estimate of the unrolled cost of the specified loop.
LLVM_ABI bool canUnroll(OptimizationRemarkEmitter *ORE=nullptr, const Loop *L=nullptr) const
Whether it is legal to unroll this loop.
uint64_t getRolledLoopSize() const
A Use represents the edge between a Value definition and its users.
void setOperand(unsigned i, Value *Val)
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
user_iterator user_begin()
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 const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
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.
StringRef str() const
Return a StringRef for the vector contents.
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()
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 <.
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.
LLVM_ABI unsigned computeUnrollCount(Loop *L, const TargetTransformInfo &TTI, DominatorTree &DT, LoopInfo *LI, AssumptionCache *AC, ScalarEvolution &SE, const SmallPtrSetImpl< const Value * > &EphValues, OptimizationRemarkEmitter *ORE, unsigned TripCount, unsigned MaxTripCount, bool MaxOrZero, unsigned TripMultiple, const UnrollCostEstimator &UCE, TargetTransformInfo::UnrollingPreferences &UP, TargetTransformInfo::PeelingPreferences &PP)
bool 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).
@ Store
The extracted value is stored (ExtractElement 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...
LLVM_ABI TargetTransformInfo::UnrollingPreferences gatherUnrollingPreferences(Loop *L, ScalarEvolution &SE, const TargetTransformInfo &TTI, BlockFrequencyInfo *BFI, ProfileSummaryInfo *PSI, llvm::OptimizationRemarkEmitter &ORE, int OptLevel, std::optional< unsigned > UserThreshold, std::optional< bool > UserAllowPartial, std::optional< bool > UserRuntime, std::optional< bool > UserUpperBound, std::optional< unsigned > UserFullUnrollMaxCount)
Gather the various unrolling parameters based on the defaults, compiler flags, TTI overrides and user...
std::string utostr(uint64_t X, bool isNeg=false)
ErrorOr< T > expectedToErrorOrAndEmitErrors(LLVMContext &Ctx, Expected< T > Val)
bool isa_and_nonnull(const Y &Val)
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 TargetTransformInfo::PeelingPreferences gatherPeelingPreferences(Loop *L, ScalarEvolution &SE, const TargetTransformInfo &TTI, std::optional< bool > UserAllowPeeling, std::optional< bool > UserAllowProfileBasedPeeling, bool UnrollingSpecficValues=false)
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)
CodeGenOptLevel
Code generation optimization level.
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.
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,...
static auto filterDbgVars(iterator_range< simple_ilist< DbgRecord >::iterator > R)
Filter the DbgRecord range to DbgVariableRecord types only and downcast.
This struct is a compact representation of a valid (non-zero power of two) alignment.
static LLVM_ABI void collectEphemeralValues(const Loop *L, AssumptionCache *AC, SmallPtrSetImpl< const Value * > &EphValues)
Collect a loop's ephemeral values (those used only by an assume or similar intrinsics in the loop).
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
A struct to pack 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.
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 StrictBlocksAndThreads
True if the kernel strictly requires the number of blocks and threads above to run.
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 * MaxThreads
'parallel' construct 'num_threads' clause value, if present and it is an SPMD kernel.
Value * LoopTripCount
Total number of iterations of the SPMD or Generic-SPMD kernel or null if it is a generic kernel.
SmallVector< Value *, 3 > TargetThreadLimit
SmallVector< Value *, 3 > TeamsThreadLimit
Data structure to contain the information needed to uniquely identify a target entry.
static 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.
static LLVM_ABI const Target * lookupTarget(const Triple &TheTriple, std::string &Error)
lookupTarget - Lookup a target based on a target triple.
Defines various target-specific GPU grid values that must be consistent between host RTL (plugin),...