69#define DEBUG_TYPE "openmp-ir-builder"
76 cl::desc(
"Use optimistic attributes describing "
77 "'as-if' properties of runtime calls."),
81 "openmp-ir-builder-unroll-threshold-factor",
cl::Hidden,
82 cl::desc(
"Factor for the unroll threshold to account for code "
83 "simplifications still taking place"),
87 "openmp-ir-builder-use-default-max-threads",
cl::Hidden,
98 if (!IP1.isSet() || !IP2.isSet())
100 return IP1.getBlock() == IP2.getBlock() && IP1.getPoint() == IP2.getPoint();
105 switch (SchedType & ~OMPScheduleType::MonotonicityMask) {
106 case OMPScheduleType::UnorderedStaticChunked:
107 case OMPScheduleType::UnorderedStatic:
108 case OMPScheduleType::UnorderedDynamicChunked:
109 case OMPScheduleType::UnorderedGuidedChunked:
110 case OMPScheduleType::UnorderedRuntime:
111 case OMPScheduleType::UnorderedAuto:
112 case OMPScheduleType::UnorderedTrapezoidal:
113 case OMPScheduleType::UnorderedGreedy:
114 case OMPScheduleType::UnorderedBalanced:
115 case OMPScheduleType::UnorderedGuidedIterativeChunked:
116 case OMPScheduleType::UnorderedGuidedAnalyticalChunked:
117 case OMPScheduleType::UnorderedSteal:
118 case OMPScheduleType::UnorderedStaticBalancedChunked:
119 case OMPScheduleType::UnorderedGuidedSimd:
120 case OMPScheduleType::UnorderedRuntimeSimd:
121 case OMPScheduleType::OrderedStaticChunked:
122 case OMPScheduleType::OrderedStatic:
123 case OMPScheduleType::OrderedDynamicChunked:
124 case OMPScheduleType::OrderedGuidedChunked:
125 case OMPScheduleType::OrderedRuntime:
126 case OMPScheduleType::OrderedAuto:
127 case OMPScheduleType::OrderdTrapezoidal:
128 case OMPScheduleType::NomergeUnorderedStaticChunked:
129 case OMPScheduleType::NomergeUnorderedStatic:
130 case OMPScheduleType::NomergeUnorderedDynamicChunked:
131 case OMPScheduleType::NomergeUnorderedGuidedChunked:
132 case OMPScheduleType::NomergeUnorderedRuntime:
133 case OMPScheduleType::NomergeUnorderedAuto:
134 case OMPScheduleType::NomergeUnorderedTrapezoidal:
135 case OMPScheduleType::NomergeUnorderedGreedy:
136 case OMPScheduleType::NomergeUnorderedBalanced:
137 case OMPScheduleType::NomergeUnorderedGuidedIterativeChunked:
138 case OMPScheduleType::NomergeUnorderedGuidedAnalyticalChunked:
139 case OMPScheduleType::NomergeUnorderedSteal:
140 case OMPScheduleType::NomergeOrderedStaticChunked:
141 case OMPScheduleType::NomergeOrderedStatic:
142 case OMPScheduleType::NomergeOrderedDynamicChunked:
143 case OMPScheduleType::NomergeOrderedGuidedChunked:
144 case OMPScheduleType::NomergeOrderedRuntime:
145 case OMPScheduleType::NomergeOrderedAuto:
146 case OMPScheduleType::NomergeOrderedTrapezoidal:
147 case OMPScheduleType::OrderedDistributeChunked:
148 case OMPScheduleType::OrderedDistribute:
156 SchedType & OMPScheduleType::MonotonicityMask;
157 if (MonotonicityFlags == OMPScheduleType::MonotonicityMask)
171 Builder.restoreIP(IP);
175 if (Builder.GetInsertPoint() != BB->
end())
185 unsigned Line = FSP->getScopeLine() ? FSP->getScopeLine() : FSP->getLine();
186 Builder.SetCurrentDebugLocation(
192 return T.isAMDGPU() ||
T.isNVPTX() ||
T.isSPIRV();
198 Kernel->getFnAttribute(
"target-features").getValueAsString();
199 if (Features.
count(
"+wavefrontsize64"))
214 bool HasSimdModifier,
bool HasDistScheduleChunks) {
216 switch (ClauseKind) {
217 case OMP_SCHEDULE_Default:
218 case OMP_SCHEDULE_Static:
219 return HasChunks ? OMPScheduleType::BaseStaticChunked
220 : OMPScheduleType::BaseStatic;
221 case OMP_SCHEDULE_Dynamic:
222 return OMPScheduleType::BaseDynamicChunked;
223 case OMP_SCHEDULE_Guided:
224 return HasSimdModifier ? OMPScheduleType::BaseGuidedSimd
225 : OMPScheduleType::BaseGuidedChunked;
226 case OMP_SCHEDULE_Auto:
228 case OMP_SCHEDULE_Runtime:
229 return HasSimdModifier ? OMPScheduleType::BaseRuntimeSimd
230 : OMPScheduleType::BaseRuntime;
231 case OMP_SCHEDULE_Distribute:
232 return HasDistScheduleChunks ? OMPScheduleType::BaseDistributeChunked
233 : OMPScheduleType::BaseDistribute;
241 bool HasOrderedClause) {
242 assert((BaseScheduleType & OMPScheduleType::ModifierMask) ==
243 OMPScheduleType::None &&
244 "Must not have ordering nor monotonicity flags already set");
247 ? OMPScheduleType::ModifierOrdered
248 : OMPScheduleType::ModifierUnordered;
252 if (OrderingScheduleType ==
253 (OMPScheduleType::BaseGuidedSimd | OMPScheduleType::ModifierOrdered))
254 return OMPScheduleType::OrderedGuidedChunked;
255 else if (OrderingScheduleType == (OMPScheduleType::BaseRuntimeSimd |
256 OMPScheduleType::ModifierOrdered))
257 return OMPScheduleType::OrderedRuntime;
259 return OrderingScheduleType;
265 bool HasSimdModifier,
bool HasMonotonic,
266 bool HasNonmonotonic,
bool HasOrderedClause) {
267 assert((ScheduleType & OMPScheduleType::MonotonicityMask) ==
268 OMPScheduleType::None &&
269 "Must not have monotonicity flags already set");
270 assert((!HasMonotonic || !HasNonmonotonic) &&
271 "Monotonic and Nonmonotonic are contradicting each other");
274 return ScheduleType | OMPScheduleType::ModifierMonotonic;
275 }
else if (HasNonmonotonic) {
276 return ScheduleType | OMPScheduleType::ModifierNonmonotonic;
286 if ((BaseScheduleType == OMPScheduleType::BaseStatic) ||
287 (BaseScheduleType == OMPScheduleType::BaseStaticChunked) ||
293 return ScheduleType | OMPScheduleType::ModifierNonmonotonic;
301 bool HasSimdModifier,
bool HasMonotonicModifier,
302 bool HasNonmonotonicModifier,
bool HasOrderedClause,
303 bool HasDistScheduleChunks) {
305 ClauseKind, HasChunks, HasSimdModifier, HasDistScheduleChunks);
309 OrderedSchedule, HasSimdModifier, HasMonotonicModifier,
310 HasNonmonotonicModifier, HasOrderedClause);
318static std::optional<omp::OMPTgtExecModeFlags>
323 if (
Call->getCalledFunction()->getName() ==
"__kmpc_target_init") {
324 TargetInitCall =
Call;
349 std::optional<omp::OMPTgtExecModeFlags> ExecMode =
361 if (
Instruction *Term = Source->getTerminatorOrNull()) {
370 NewBr->setDebugLoc(
DL);
375 assert(New->getFirstInsertionPt() == New->begin() &&
376 "Target BB must not have PHI nodes");
392 New->splice(New->begin(), Old, IP.
getPoint(), Old->
end());
396 NewBr->setDebugLoc(
DL);
408 Builder.SetInsertPoint(Old);
412 Builder.SetCurrentDebugLocation(
DebugLoc);
422 New->replaceSuccessorsPhiUsesWith(Old, New);
431 Builder.SetInsertPoint(Builder.GetInsertBlock()->getTerminator());
433 Builder.SetInsertPoint(Builder.GetInsertBlock());
436 Builder.SetCurrentDebugLocation(
DebugLoc);
445 Builder.SetInsertPoint(Builder.GetInsertBlock()->getTerminator());
447 Builder.SetInsertPoint(Builder.GetInsertBlock());
450 Builder.SetCurrentDebugLocation(
DebugLoc);
467 const Twine &Name =
"",
bool AsPtr =
true,
468 bool Is64Bit =
false) {
469 Builder.restoreIP(OuterAllocaIP);
473 Builder.CreateAlloca(IntTy,
nullptr, Name +
".addr");
477 FakeVal = FakeValAddr;
482 FakeValAddr, Builder.getPtrTy(), Name +
".ascast"));
486 FakeVal = Builder.CreateLoad(IntTy, FakeValAddr, Name +
".val");
491 Builder.restoreIP(InnerAllocaIP);
494 UseFakeVal = Builder.CreateLoad(IntTy, FakeVal, Name +
".use");
497 FakeVal, Is64Bit ? Builder.getInt64(10) : Builder.getInt32(10)));
510enum OpenMPOffloadingRequiresDirFlags {
512 OMP_REQ_UNDEFINED = 0x000,
514 OMP_REQ_NONE = 0x001,
516 OMP_REQ_REVERSE_OFFLOAD = 0x002,
518 OMP_REQ_UNIFIED_ADDRESS = 0x004,
520 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008,
522 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010,
529 DominatorTree *DT =
nullptr,
bool AggregateArgs =
false,
530 BlockFrequencyInfo *BFI =
nullptr,
531 BranchProbabilityInfo *BPI =
nullptr,
532 AssumptionCache *AC =
nullptr,
bool AllowVarArgs =
false,
533 bool AllowAlloca =
false,
534 BasicBlock *AllocationBlock =
nullptr,
536 std::string Suffix =
"",
bool ArgsInZeroAddressSpace =
false)
537 : CodeExtractor(BBs, DT, AggregateArgs, BFI, BPI, AC, AllowVarArgs,
538 AllowAlloca, AllocationBlock, DeallocationBlocks, Suffix,
539 ArgsInZeroAddressSpace),
540 OMPBuilder(OMPBuilder) {}
542 virtual ~OMPCodeExtractor() =
default;
545 OpenMPIRBuilder &OMPBuilder;
548class DeviceSharedMemCodeExtractor :
public OMPCodeExtractor {
550 using OMPCodeExtractor::OMPCodeExtractor;
551 virtual ~DeviceSharedMemCodeExtractor() =
default;
555 allocateVar(IRBuilder<>::InsertPoint AllocaIP,
DebugLoc DL,
Type *VarType,
556 const Twine &Name = Twine(
""),
557 AddrSpaceCastInst **CastedAlloc =
nullptr)
override {
558 return OMPBuilder.createOMPAllocShared({AllocaIP,
DL}, VarType,
Name);
561 virtual Instruction *deallocateVar(IRBuilder<>::InsertPoint DeallocIP,
563 Type *VarType)
override {
564 return OMPBuilder.createOMPFreeShared({DeallocIP,
DL}, Var, VarType);
571 OpenMPIRBuilder &OMPBuilder;
573 DeviceSharedMemOutlineInfo(OpenMPIRBuilder &OMPBuilder)
574 : OMPBuilder(OMPBuilder) {}
575 virtual ~DeviceSharedMemOutlineInfo() =
default;
577 virtual std::unique_ptr<CodeExtractor>
579 bool ArgsInZeroAddressSpace,
580 Twine Suffix = Twine(
""))
override;
586 : RequiresFlags(OMP_REQ_UNDEFINED) {}
590 bool HasRequiresReverseOffload,
bool HasRequiresUnifiedAddress,
591 bool HasRequiresUnifiedSharedMemory,
bool HasRequiresDynamicAllocators)
594 RequiresFlags(OMP_REQ_UNDEFINED) {
595 if (HasRequiresReverseOffload)
596 RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
597 if (HasRequiresUnifiedAddress)
598 RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
599 if (HasRequiresUnifiedSharedMemory)
600 RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
601 if (HasRequiresDynamicAllocators)
602 RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
606 return RequiresFlags & OMP_REQ_REVERSE_OFFLOAD;
610 return RequiresFlags & OMP_REQ_UNIFIED_ADDRESS;
614 return RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY;
618 return RequiresFlags & OMP_REQ_DYNAMIC_ALLOCATORS;
623 :
static_cast<int64_t
>(OMP_REQ_NONE);
628 RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
630 RequiresFlags &= ~OMP_REQ_REVERSE_OFFLOAD;
635 RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
637 RequiresFlags &= ~OMP_REQ_UNIFIED_ADDRESS;
642 RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
644 RequiresFlags &= ~OMP_REQ_UNIFIED_SHARED_MEMORY;
649 RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
651 RequiresFlags &= ~OMP_REQ_DYNAMIC_ALLOCATORS;
664 constexpr size_t MaxDim = 3;
669 Value *DynCGroupMemFallbackFlag =
671 DynCGroupMemFallbackFlag =
Builder.CreateShl(DynCGroupMemFallbackFlag, 2);
676 StrictBlocksFlag =
Builder.CreateShl(StrictBlocksFlag, 6);
677 StrictThreadsFlag =
Builder.CreateShl(StrictThreadsFlag, 7);
679 Value *Flags =
Builder.CreateOr(HasNoWaitFlag, DynCGroupMemFallbackFlag);
680 Flags =
Builder.CreateOr(Flags, StrictBlocksFlag);
681 Flags =
Builder.CreateOr(Flags, StrictThreadsFlag);
687 Value *NumThreads3D =
718 auto FnAttrs = Attrs.getFnAttrs();
719 auto RetAttrs = Attrs.getRetAttrs();
721 for (
size_t ArgNo = 0; ArgNo < Fn.
arg_size(); ++ArgNo)
726 bool Param =
true) ->
void {
727 bool HasSignExt = AS.hasAttribute(Attribute::SExt);
728 bool HasZeroExt = AS.hasAttribute(Attribute::ZExt);
729 if (HasSignExt || HasZeroExt) {
730 assert(AS.getNumAttributes() == 1 &&
731 "Currently not handling extension attr combined with others.");
733 if (
auto AK = TargetLibraryInfo::getExtAttrForI32Param(
T, HasSignExt))
736 TargetLibraryInfo::getExtAttrForI32Return(
T, HasSignExt))
743#define OMP_ATTRS_SET(VarName, AttrSet) AttributeSet VarName = AttrSet;
744#include "llvm/Frontend/OpenMP/OMPKinds.def"
748#define OMP_RTL_ATTRS(Enum, FnAttrSet, RetAttrSet, ArgAttrSets) \
750 FnAttrs = FnAttrs.addAttributes(Ctx, FnAttrSet); \
751 addAttrSet(RetAttrs, RetAttrSet, false); \
752 for (size_t ArgNo = 0; ArgNo < ArgAttrSets.size(); ++ArgNo) \
753 addAttrSet(ArgAttrs[ArgNo], ArgAttrSets[ArgNo]); \
754 Fn.setAttributes(AttributeList::get(Ctx, FnAttrs, RetAttrs, ArgAttrs)); \
756#include "llvm/Frontend/OpenMP/OMPKinds.def"
770#define OMP_RTL(Enum, Str, IsVarArg, ReturnType, ...) \
772 FnTy = FunctionType::get(ReturnType, ArrayRef<Type *>{__VA_ARGS__}, \
774 Fn = M.getFunction(Str); \
776#include "llvm/Frontend/OpenMP/OMPKinds.def"
782#define OMP_RTL(Enum, Str, ...) \
784 Fn = Function::Create(FnTy, GlobalValue::ExternalLinkage, Str, M); \
786#include "llvm/Frontend/OpenMP/OMPKinds.def"
790 if (FnID == OMPRTL___kmpc_fork_call || FnID == OMPRTL___kmpc_fork_teams) {
800 LLVMContext::MD_callback,
802 2, {-1, -1},
true)}));
815 assert(Fn &&
"Failed to create OpenMP runtime function");
826 Builder.SetInsertPoint(FiniBB);
838 FiniBB = OtherFiniBB;
840 Builder.SetInsertPoint(FiniBB->getFirstNonPHIIt());
848 auto EndIt = FiniBB->end();
849 if (FiniBB->size() >= 1)
850 if (
auto Prev = std::prev(EndIt); Prev->isTerminator())
855 FiniBB->replaceAllUsesWith(OtherFiniBB);
856 FiniBB->eraseFromParent();
857 FiniBB = OtherFiniBB;
864 assert(Fn &&
"Failed to create OpenMP runtime function pointer");
887 for (
auto Inst =
Block->getReverseIterator()->begin();
888 Inst !=
Block->getReverseIterator()->end();) {
917 Block.getParent()->getEntryBlock().getTerminator()->getIterator();
938 DeferredOutlines.
push_back(std::move(OI));
942 ParallelRegionBlockSet.
clear();
944 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
954 bool ArgsInZeroAddressSpace =
Config.isTargetDevice();
955 std::unique_ptr<CodeExtractor> Extractor =
956 OI->createCodeExtractor(Blocks, ArgsInZeroAddressSpace,
".omp_par");
960 <<
" Exit: " << OI->ExitBB->getName() <<
"\n");
961 assert(Extractor->isEligible() &&
962 "Expected OpenMP outlining to be possible!");
964 for (
auto *V : OI->ExcludeArgsFromAggregate)
965 Extractor->excludeArgFromAggregate(V);
968 Extractor->extractCodeRegion(CEAC, OI->Inputs, OI->Outputs);
972 if (TargetCpuAttr.isStringAttribute())
975 auto TargetFeaturesAttr = OuterFn->
getFnAttribute(
"target-features");
976 if (TargetFeaturesAttr.isStringAttribute())
977 OutlinedFn->
addFnAttr(TargetFeaturesAttr);
980 LLVM_DEBUG(
dbgs() <<
" Outlined function: " << *OutlinedFn <<
"\n");
982 "OpenMP outlined functions should not return a value!");
987 M.getFunctionList().insertAfter(OuterFn->
getIterator(), OutlinedFn);
994 assert(OI->EntryBB->getUniquePredecessor() == &ArtificialEntry);
1001 "Expected instructions to add in the outlined region entry");
1003 End = ArtificialEntry.
rend();
1008 if (
I.isTerminator()) {
1010 if (
Instruction *TI = OI->EntryBB->getTerminatorOrNull())
1011 TI->adoptDbgRecords(&ArtificialEntry,
I.getIterator(),
false);
1015 I.moveBeforePreserving(*OI->EntryBB,
1016 OI->EntryBB->getFirstInsertionPt());
1019 OI->EntryBB->moveBefore(&ArtificialEntry);
1026 if (OI->PostOutlineCB)
1027 OI->PostOutlineCB(*OutlinedFn);
1029 if (OI->FixUpNonEntryAllocas)
1061 errs() <<
"Error of kind: " << Kind
1062 <<
" when emitting offload entries and metadata during "
1063 "OMPIRBuilder finalization \n";
1071 if (
Config.isTargetDevice())
1072 applyDeclareTargetGlobalReplacements();
1074 if (
Config.EmitLLVMUsedMetaInfo.value_or(
false)) {
1075 std::vector<WeakTrackingVH> LLVMCompilerUsed = {
1076 M.getGlobalVariable(
"__openmp_nvptx_data_transfer_temporary_storage")};
1077 emitUsed(
"llvm.compiler.used", LLVMCompilerUsed);
1087 assert(Original && Replacement &&
1088 "Null values provided to registerDeclareTargetGlobalReplacement");
1092void OpenMPIRBuilder::applyDeclareTargetGlobalReplacements() {
1098 "A null value was inserted into DeclareTargetGlobalReplacements");
1102 if (!OldGV || !NewGV)
1136 for (
unsigned I = 0, E =
PHI->getNumIncomingValues();
I < E; ++
I) {
1137 if (
PHI->getIncomingValue(
I) != OldGV)
1142 Builder.SetCurrentDebugLocation(
PHI->getDebugLoc());
1144 PHI->setIncomingValue(
I, EdgeLoad);
1150 Builder.SetCurrentDebugLocation(Insn->getDebugLoc());
1166 "Non-default address space declare target global");
1168 unsigned DestAS = ASC->getType()->getPointerAddressSpace();
1169 if (DestAS == 0 && NewGVAS != OldGVAS) {
1170 ASC->replaceAllUsesWith(
Load);
1171 ASC->eraseFromParent();
1176 Insn->replaceUsesOfWith(OldGV,
Load);
1192 ConstantInt::get(I32Ty,
Value), Name);
1205 for (
unsigned I = 0, E =
List.size();
I != E; ++
I)
1209 if (UsedArray.
empty())
1216 GV->setSection(
"llvm.metadata");
1222 auto *Int8Ty =
Builder.getInt8Ty();
1225 ConstantInt::get(Int8Ty, Mode),
Twine(KernelName,
"_exec_mode"));
1233 unsigned Reserve2Flags) {
1235 LocFlags |= OMP_IDENT_FLAG_KMPC;
1242 ConstantInt::get(Int32,
uint32_t(LocFlags)),
1243 ConstantInt::get(Int32, Reserve2Flags),
1244 ConstantInt::get(Int32, SrcLocStrSize), SrcLocStr};
1246 size_t SrcLocStrArgIdx = 4;
1247 if (OpenMPIRBuilder::Ident->getElementType(SrcLocStrArgIdx)
1251 SrcLocStr, OpenMPIRBuilder::Ident->getElementType(SrcLocStrArgIdx));
1258 if (
GV.getValueType() == OpenMPIRBuilder::Ident &&
GV.hasInitializer())
1259 if (
GV.getInitializer() == Initializer)
1264 M, OpenMPIRBuilder::Ident,
1267 M.getDataLayout().getDefaultGlobalsAddressSpace());
1279 SrcLocStrSize = LocStr.
size();
1288 if (
GV.isConstant() &&
GV.hasInitializer() &&
1289 GV.getInitializer() == Initializer)
1292 SrcLocStr =
Builder.CreateGlobalString(
1293 LocStr,
"",
M.getDataLayout().getDefaultGlobalsAddressSpace(),
1301 unsigned Line,
unsigned Column,
1307 Buffer.
append(FunctionName);
1309 Buffer.
append(std::to_string(Line));
1311 Buffer.
append(std::to_string(Column));
1319 StringRef UnknownLoc =
";unknown;unknown;0;0;;";
1330 !DIL->getFilename().empty() ? DIL->getFilename() :
M.getName();
1335 DIL->getColumn(), SrcLocStrSize);
1341 Loc.IP.getBlock()->getParent());
1347 "omp_global_thread_num");
1355 "expected one result pointer type per in_reduction item");
1358 if (OrigPtrs.
empty())
1359 return Builder.saveIP();
1378 for (
unsigned Idx = 0; Idx < OrigPtrs.
size(); ++Idx) {
1381 Value *OrigPtr = OrigPtrs[Idx];
1383 OrigPtrTy && OrigPtrTy->getAddressSpace() != 0)
1384 OrigPtr = Builder.CreateAddrSpaceCast(OrigPtr, PtrTy);
1386 Value *
Priv = Builder.CreateCall(GetThData, {Gtid, NullDesc, OrigPtr},
1392 ResPtrTy && ResPtrTy->getAddressSpace() != 0)
1393 Priv = Builder.CreateAddrSpaceCast(
Priv, ResultPtrTys[Idx]);
1395 MapPrivateCB(Idx,
Priv);
1402 bool ForceSimpleCall,
bool CheckCancelFlag) {
1412 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_FOR;
1415 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SECTIONS;
1418 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SINGLE;
1421 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_EXPL;
1424 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL;
1437 bool UseCancelBarrier =
1442 ? OMPRTL___kmpc_cancel_barrier
1443 : OMPRTL___kmpc_barrier),
1446 if (UseCancelBarrier && CheckCancelFlag)
1456 omp::Directive CanceledDirective) {
1461 auto *UI =
Builder.CreateUnreachable();
1469 Builder.SetInsertPoint(ElseTI);
1470 auto ElseIP =
Builder.saveIP();
1478 Builder.SetInsertPoint(ThenTI);
1480 Value *CancelKind =
nullptr;
1481 switch (CanceledDirective) {
1482#define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) \
1483 case DirectiveEnum: \
1484 CancelKind = Builder.getInt32(Value); \
1486#include "llvm/Frontend/OpenMP/OMPKinds.def"
1503 Builder.SetInsertPoint(UI->getParent());
1504 UI->eraseFromParent();
1511 omp::Directive CanceledDirective) {
1516 auto *UI =
Builder.CreateUnreachable();
1519 Value *CancelKind =
nullptr;
1520 switch (CanceledDirective) {
1521#define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) \
1522 case DirectiveEnum: \
1523 CancelKind = Builder.getInt32(Value); \
1525#include "llvm/Frontend/OpenMP/OMPKinds.def"
1542 Builder.SetInsertPoint(UI->getParent());
1543 UI->eraseFromParent();
1556 auto *KernelArgsPtr =
1557 Builder.CreateAlloca(OpenMPIRBuilder::KernelArgs,
nullptr,
"kernel_args");
1562 Builder.CreateStructGEP(OpenMPIRBuilder::KernelArgs, KernelArgsPtr,
I);
1565 M.getDataLayout().getPrefTypeAlign(KernelArgs[
I]->getType()));
1569 NumThreads, HostPtr, KernelArgsPtr};
1596 assert(OutlinedFnID &&
"Invalid outlined function ID!");
1600 Value *Return =
nullptr;
1620 Builder, AllocaIP, Return, RTLoc, DeviceID, Args.NumTeams.front(),
1621 Args.NumThreads.front(), OutlinedFnID, ArgsVector));
1628 Builder.CreateCondBr(
Failed, OffloadFailedBlock, OffloadContBlock);
1630 auto CurFn =
Builder.GetInsertBlock()->getParent();
1637 emitBlock(OffloadContBlock, CurFn,
true);
1642 Value *CancelFlag, omp::Directive CanceledDirective) {
1644 "Unexpected cancellation!");
1664 Builder.CreateCondBr(Cmp, NonCancellationBlock, CancellationBlock,
1673 Builder.SetInsertPoint(CancellationBlock);
1674 Builder.CreateBr(*FiniBBOrErr);
1677 Builder.SetInsertPoint(NonCancellationBlock, NonCancellationBlock->
begin());
1689 size_t NumArgs = OutlinedFn.
arg_size();
1690 assert((NumArgs == 2 || NumArgs == 3) &&
1691 "expected a 2-3 argument parallel outlined function");
1692 bool UseArgStruct = NumArgs == 3;
1697 {Builder.getInt16Ty(), Builder.getInt32Ty()},
1701 OutlinedFn.
getName() +
".wrapper", OMPIRBuilder->
M);
1703 WrapperFn->addParamAttr(0, Attribute::NoUndef);
1704 WrapperFn->addParamAttr(0, Attribute::ZExt);
1705 WrapperFn->addParamAttr(1, Attribute::NoUndef);
1709 Builder.SetInsertPoint(EntryBB);
1712 Value *AddrAlloca = Builder.CreateAlloca(Builder.getInt32Ty(),
1714 AddrAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1715 AddrAlloca, Builder.getPtrTy(0),
1716 AddrAlloca->
getName() +
".ascast");
1718 Value *ZeroAlloca = Builder.CreateAlloca(Builder.getInt32Ty(),
1720 ZeroAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1721 ZeroAlloca, Builder.getPtrTy(0),
1722 ZeroAlloca->
getName() +
".ascast");
1724 Value *ArgsAlloca =
nullptr;
1726 ArgsAlloca = Builder.CreateAlloca(Builder.getPtrTy(),
1727 nullptr,
"global_args");
1728 ArgsAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1729 ArgsAlloca, Builder.getPtrTy(0),
1730 ArgsAlloca->
getName() +
".ascast");
1734 Builder.CreateStore(WrapperFn->getArg(1), AddrAlloca);
1735 Builder.CreateStore(Builder.getInt32(0), ZeroAlloca);
1739 llvm::omp::RuntimeFunction::OMPRTL___kmpc_get_shared_variables),
1747 Value *StructArg = Builder.CreateLoad(Builder.getPtrTy(), ArgsAlloca);
1748 StructArg = Builder.CreateInBoundsGEP(Builder.getPtrTy(), StructArg,
1749 {Builder.getInt64(0)});
1750 StructArg = Builder.CreateLoad(Builder.getPtrTy(), StructArg,
"structArg");
1751 Args.push_back(StructArg);
1755 Builder.CreateCall(&OutlinedFn, Args);
1756 Builder.CreateRetVoid();
1771 "Expected at least tid and bounded tid as arguments");
1772 unsigned NumCapturedVars = OutlinedFn.
arg_size() - 2;
1780 OutlinedFn.
addFnAttr(Attribute::NoUnwind);
1783 assert(CI &&
"Expected call instruction to outlined function");
1784 CI->
getParent()->setName(
"omp_parallel");
1786 Builder.SetInsertPoint(CI);
1787 Type *PtrTy = OMPIRBuilder->VoidPtr;
1790 OpenMPIRBuilder ::InsertPointTy CurrentIP = Builder.saveIP();
1794 Value *Args = ArgsAlloca;
1798 Args = Builder.CreatePointerCast(ArgsAlloca, PtrTy);
1799 Builder.restoreIP(CurrentIP);
1802 for (
unsigned Idx = 0; Idx < NumCapturedVars; Idx++) {
1804 Value *StoreAddress = Builder.CreateConstInBoundsGEP2_64(
1806 Builder.CreateStore(V, StoreAddress);
1810 IfCondition ? Builder.CreateSExtOrTrunc(IfCondition, OMPIRBuilder->Int32)
1811 : Builder.getInt32(1);
1812 Value *NumThreadsArg =
1813 NumThreads ? Builder.CreateZExtOrTrunc(NumThreads, OMPIRBuilder->Int32)
1814 : Builder.getInt32(-1);
1824 Value *Parallel60CallArgs[] = {
1829 Builder.getInt32(-1),
1833 Builder.getInt64(NumCapturedVars),
1834 Builder.getInt32(0)};
1842 << *Builder.GetInsertBlock()->getParent() <<
"\n");
1845 Builder.SetInsertPoint(PrivTID);
1847 Builder.CreateStore(Builder.CreateLoad(OMPIRBuilder->Int32, OutlinedAI),
1854 I->eraseFromParent();
1877 if (!
F->hasMetadata(LLVMContext::MD_callback)) {
1885 F->addMetadata(LLVMContext::MD_callback,
1894 OutlinedFn.
addFnAttr(Attribute::NoUnwind);
1897 "Expected at least tid and bounded tid as arguments");
1898 unsigned NumCapturedVars = OutlinedFn.
arg_size() - 2;
1901 CI->
getParent()->setName(
"omp_parallel");
1902 Builder.SetInsertPoint(CI);
1905 Value *ForkCallArgs[] = {Ident, Builder.getInt32(NumCapturedVars),
1909 RealArgs.
append(std::begin(ForkCallArgs), std::end(ForkCallArgs));
1911 Value *
Cond = Builder.CreateSExtOrTrunc(IfCondition, OMPIRBuilder->Int32);
1918 auto PtrTy = OMPIRBuilder->VoidPtr;
1919 if (IfCondition && NumCapturedVars == 0) {
1927 << *Builder.GetInsertBlock()->getParent() <<
"\n");
1930 Builder.SetInsertPoint(PrivTID);
1932 Builder.CreateStore(Builder.CreateLoad(OMPIRBuilder->Int32, OutlinedAI),
1939 I->eraseFromParent();
1947 Value *NumThreads, omp::ProcBindKind ProcBind,
bool IsCancellable) {
1956 const bool NeedThreadID = NumThreads ||
Config.isTargetDevice() ||
1957 (ProcBind != OMP_PROC_BIND_default);
1964 bool ArgsInZeroAddressSpace =
Config.isTargetDevice();
1968 if (NumThreads && !
Config.isTargetDevice()) {
1971 Builder.CreateIntCast(NumThreads, Int32,
false)};
1976 if (ProcBind != OMP_PROC_BIND_default) {
1980 ConstantInt::get(Int32,
unsigned(ProcBind),
true)};
2002 Builder.CreateAlloca(Int32,
nullptr,
"zero.addr");
2005 if (ArgsInZeroAddressSpace &&
M.getDataLayout().getAllocaAddrSpace() != 0) {
2008 TIDAddrAlloca, PointerType ::get(
M.getContext(), 0),
"tid.addr.ascast");
2012 PointerType ::get(
M.getContext(), 0),
2013 "zero.addr.ascast");
2037 if (IP.getBlock()->end() == IP.getPoint()) {
2043 assert(IP.getBlock()->getTerminator()->getNumSuccessors() == 1 &&
2044 IP.getBlock()->getTerminator()->getSuccessor(0) == PRegExitBB &&
2045 "Unexpected insertion point for finalization call!");
2057 Builder.CreateAlloca(Int32,
nullptr,
"tid.addr.local");
2063 Builder.CreateLoad(Int32, ZeroAddr,
"zero.addr.use");
2081 LLVM_DEBUG(
dbgs() <<
"Before body codegen: " << *OuterFn <<
"\n");
2084 assert(BodyGenCB &&
"Expected body generation callback!");
2086 if (
Error Err = BodyGenCB(InnerAllocaIP, CodeGenIP, PRegExitBB))
2089 LLVM_DEBUG(
dbgs() <<
"After body codegen: " << *OuterFn <<
"\n");
2093 bool UsesDeviceSharedMemory =
2095 std::unique_ptr<OutlineInfo> OI =
2096 UsesDeviceSharedMemory
2097 ? std::make_unique<DeviceSharedMemOutlineInfo>(*
this)
2098 : std::make_unique<OutlineInfo>();
2100 if (
Config.isTargetDevice()) {
2102 OI->PostOutlineCB = [=, ToBeDeletedVec =
2103 std::move(ToBeDeleted)](
Function &OutlinedFn) {
2105 IfCondition, NumThreads, PrivTID, PrivTIDAddr,
2106 ThreadID, ToBeDeletedVec);
2110 OI->PostOutlineCB = [=, ToBeDeletedVec =
2111 std::move(ToBeDeleted)](
Function &OutlinedFn) {
2113 PrivTID, PrivTIDAddr, ToBeDeletedVec);
2117 OI->FixUpNonEntryAllocas =
true;
2118 OI->OuterAllocBB = OuterAllocaBlock;
2119 OI->EntryBB = PRegEntryBB;
2120 OI->ExitBB = PRegExitBB;
2121 OI->OuterDeallocBBs.reserve(OuterDeallocBlocks.
size());
2122 copy(OuterDeallocBlocks, OI->OuterDeallocBBs.
end());
2126 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
2138 ".omp_par", ArgsInZeroAddressSpace);
2143 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
2145 Extractor.findInputsOutputs(Inputs, Outputs, SinkingCands,
2150 return GV->getValueType() == OpenMPIRBuilder::Ident;
2155 LLVM_DEBUG(
dbgs() <<
"Before privatization: " << *OuterFn <<
"\n");
2161 if (&V == TIDAddr || &V == ZeroAddr) {
2162 OI->ExcludeArgsFromAggregate.push_back(&V);
2167 for (
Use &U : V.uses())
2169 if (ParallelRegionBlockSet.
count(UserI->getParent()))
2179 if (!V.getType()->isPointerTy()) {
2183 Builder.restoreIP(OuterAllocIP);
2185 if (UsesDeviceSharedMemory) {
2188 V.getName() +
".reloaded");
2189 for (
BasicBlock *DeallocBlock : OuterDeallocBlocks) {
2190 assert(DeallocBlock->getParent() ==
2192 "Dealloc block must be in the allocation's function to reuse "
2193 "its debug location");
2195 {
InsertPointTy(DeallocBlock, DeallocBlock->getFirstInsertionPt()),
2196 Builder.getCurrentDebugLocation()},
2200 Ptr =
Builder.CreateAlloca(V.getType(),
nullptr,
2201 V.getName() +
".reloaded");
2206 Builder.SetInsertPoint(InsertBB,
2211 Builder.restoreIP(InnerAllocaIP);
2212 Inner =
Builder.CreateLoad(V.getType(), Ptr);
2215 Value *ReplacementValue =
nullptr;
2218 ReplacementValue = PrivTID;
2221 PrivCB(InnerAllocaIP,
Builder.saveIP(), V, *Inner, ReplacementValue);
2229 assert(ReplacementValue &&
2230 "Expected copy/create callback to set replacement value!");
2231 if (ReplacementValue == &V)
2236 UPtr->set(ReplacementValue);
2261 for (
Value *Output : Outputs)
2265 "OpenMP outlining should not produce live-out values!");
2267 LLVM_DEBUG(
dbgs() <<
"After privatization: " << *OuterFn <<
"\n");
2269 for (
auto *BB : Blocks)
2270 dbgs() <<
" PBR: " << BB->getName() <<
"\n";
2278 assert(FiniInfo.DK == OMPD_parallel &&
2279 "Unexpected finalization stack state!");
2290 Builder.CreateBr(*FiniBBOrErr);
2294 Term->eraseFromParent();
2300 InsertPointTy AfterIP(UI->getParent(), UI->getParent()->end());
2301 UI->eraseFromParent();
2333 Value *Severity = ConstantInt::get(Int32, IsFatal ? 2 : 1);
2335 Value *Args[] = {Ident, Severity, MessageArg};
2364 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr));
2366 Builder.CreateStore(DepValPtr, Addr);
2369 DependInfo, Entry,
static_cast<unsigned int>(RTLDependInfoFields::Len));
2371 ConstantInt::get(SizeTy,
2376 DependInfo, Entry,
static_cast<unsigned int>(RTLDependInfoFields::Flags));
2378 static_cast<unsigned int>(Dep.
DepKind)),
2391 if (Dependencies.
empty())
2411 Type *DependInfo = OMPBuilder.DependInfo;
2413 Value *DepArray =
nullptr;
2419 Builder.SetInsertPoint(
2420 Builder.GetInsertBlock()->getParent()->getEntryBlock().getTerminator());
2421 DepArray = Builder.CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
2424 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies)) {
2426 Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
2450 Value *DepArray =
nullptr;
2451 Type *DepArrayTy =
nullptr;
2452 Value *NumDeps =
nullptr;
2455 NumDeps = Dependencies.
NumDeps;
2456 }
else if (!Dependencies.
Deps.empty()) {
2458 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
2462 Builder.GetInsertBlock()->getParent()->getEntryBlock();
2464 DepArray =
Builder.CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
2467 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies.
Deps)) {
2469 Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
2483 ConstantInt::get(
Builder.getInt32Ty(), 0),
2485 ConstantInt::get(
Builder.getInt32Ty(),
false)};
2488 omp::RuntimeFunction::OMPRTL___kmpc_omp_taskwait_deps_51),
2498 unsigned ProgramAddressSpace = M.getDataLayout().getProgramAddressSpace();
2510 auto *VoidPtrTy =
PointerType::get(Builder.getContext(), ProgramAddressSpace);
2513 Builder.getVoidTy(), {VoidPtrTy, VoidPtrTy, Builder.getInt32Ty()},
2517 "omp_taskloop_dup", M);
2520 Value *LastprivateFlagArg = DupFunction->
getArg(2);
2521 DestTaskArg->
setName(
"dest_task");
2522 SrcTaskArg->
setName(
"src_task");
2523 LastprivateFlagArg->
setName(
"lastprivate_flag");
2526 Builder.SetInsertPoint(
2529 auto GetTaskContextPtrFromArg = [&](
Value *Arg) ->
Value * {
2530 Type *TaskWithPrivatesTy =
2532 Value *TaskPrivates = Builder.CreateGEP(
2533 TaskWithPrivatesTy, Arg, {Builder.getInt32(0), Builder.getInt32(1)});
2534 Value *ContextPtr = Builder.CreateGEP(
2535 PrivatesTy, TaskPrivates,
2536 {Builder.getInt32(0), Builder.getInt32(PrivatesIndex)});
2540 Value *DestTaskContextPtr = GetTaskContextPtrFromArg(DestTaskArg);
2541 Value *SrcTaskContextPtr = GetTaskContextPtrFromArg(SrcTaskArg);
2543 DestTaskContextPtr->
setName(
"destPtr");
2544 SrcTaskContextPtr->
setName(
"srcPtr");
2549 Expected<IRBuilderBase::InsertPoint> AfterIPOrError =
2550 DupCB(AllocaIP, CodeGenIP, DestTaskContextPtr, SrcTaskContextPtr);
2551 if (!AfterIPOrError)
2553 Builder.restoreIP(*AfterIPOrError);
2563 llvm::function_ref<llvm::Expected<llvm::CanonicalLoopInfo *>()> LoopInfo,
2565 Value *GrainSize,
bool NoGroup,
int Sched,
Value *Final,
bool Mergeable,
2567 Value *TaskContextStructPtrVal,
bool FreeAgent) {
2572 uint32_t SrcLocStrSize;
2588 if (
Error Err = BodyGenCB(TaskloopAllocaIP, TaskloopBodyIP, TaskloopExitBB))
2591 llvm::Expected<llvm::CanonicalLoopInfo *> result = LoopInfo();
2596 llvm::CanonicalLoopInfo *CLI = result.
get();
2597 auto OI = std::make_unique<OutlineInfo>();
2598 OI->EntryBB = TaskloopAllocaBB;
2599 OI->OuterAllocBB = AllocaIP.getBlock();
2600 OI->ExitBB = TaskloopExitBB;
2601 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2602 copy(DeallocBlocks, OI->OuterDeallocBBs.end());
2605 SmallVector<Instruction *> ToBeDeleted;
2608 Builder, AllocaIP, ToBeDeleted, TaskloopAllocaIP,
"global.tid",
false));
2610 TaskloopAllocaIP,
"lb",
false,
true);
2612 TaskloopAllocaIP,
"ub",
false,
true);
2614 TaskloopAllocaIP,
"step",
false,
true);
2617 OI->Inputs.insert(FakeLB);
2618 OI->Inputs.insert(FakeUB);
2619 OI->Inputs.insert(FakeStep);
2620 if (TaskContextStructPtrVal)
2621 OI->Inputs.insert(TaskContextStructPtrVal);
2622 assert(((TaskContextStructPtrVal && DupCB) ||
2623 (!TaskContextStructPtrVal && !DupCB)) &&
2624 "Task context struct ptr and duplication callback must be both set "
2630 unsigned ProgramAddressSpace =
M.getDataLayout().getProgramAddressSpace();
2634 {FakeLB->getType(), FakeUB->getType(), FakeStep->getType(), PointerTy});
2635 Expected<Value *> TaskDupFnOrErr = createTaskDuplicationFunction(
2638 if (!TaskDupFnOrErr) {
2641 Value *TaskDupFn = *TaskDupFnOrErr;
2643 OI->PostOutlineCB = [
this, Ident, LBVal, UBVal, StepVal, Untied,
2644 TaskloopAllocaBB, CLI, TaskDupFn, ToBeDeleted, IfCond,
2645 GrainSize, NoGroup, Sched, FakeLB, FakeUB, FakeStep,
2646 FakeSharedsTy, Final, Mergeable, Priority,
2648 FreeAgent](
Function &OutlinedFn)
mutable {
2650 assert(OutlinedFn.hasOneUse() &&
2651 "there must be a single user for the outlined function");
2658 Value *CastedLBVal =
2659 Builder.CreateIntCast(LBVal,
Builder.getInt64Ty(),
true,
"lb64");
2660 Value *CastedUBVal =
2661 Builder.CreateIntCast(UBVal,
Builder.getInt64Ty(),
true,
"ub64");
2662 Value *CastedStepVal =
2663 Builder.CreateIntCast(StepVal,
Builder.getInt64Ty(),
true,
"step64");
2665 Builder.SetInsertPoint(StaleCI);
2678 Builder.CreateCall(TaskgroupFn, {Ident, ThreadID});
2703 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
2705 AllocaInst *ArgStructAlloca =
2707 assert(ArgStructAlloca &&
2708 "Unable to find the alloca instruction corresponding to arguments "
2709 "for extracted function");
2710 std::optional<TypeSize> ArgAllocSize =
2713 "Unable to determine size of arguments for extracted function");
2714 Value *SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
2719 CallInst *TaskData =
Builder.CreateCall(
2720 TaskAllocFn, {Ident, ThreadID,
Flags,
2721 TaskSize, SharedsSize,
2726 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
2732 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(0)});
2735 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(1)});
2738 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(2)});
2744 IfCond ?
Builder.CreateIntCast(IfCond,
Builder.getInt32Ty(),
true)
2750 Value *GrainSizeVal =
2751 GrainSize ?
Builder.CreateIntCast(GrainSize,
Builder.getInt64Ty(),
true)
2753 Value *TaskDup = TaskDupFn;
2755 Value *
Args[] = {Ident, ThreadID, TaskData, IfCondVal, Lb, Ub,
2756 Loadstep, NoGroupVal, SchedVal, GrainSizeVal, TaskDup};
2761 Builder.CreateCall(TaskloopFn, Args);
2768 Builder.CreateCall(EndTaskgroupFn, {Ident, ThreadID});
2773 Builder.SetInsertPoint(TaskloopAllocaBB, TaskloopAllocaBB->begin());
2775 LoadInst *SharedsOutlined =
2776 Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
2777 OutlinedFn.getArg(1)->replaceUsesWithIf(
2779 [SharedsOutlined](Use &U) {
return U.getUser() != SharedsOutlined; });
2782 Type *IVTy =
IV->getType();
2788 Value *TaskLB =
nullptr;
2789 Value *TaskUB =
nullptr;
2790 Value *TaskStep =
nullptr;
2791 Value *LoadTaskLB =
nullptr;
2792 Value *LoadTaskUB =
nullptr;
2793 Value *LoadTaskStep =
nullptr;
2794 for (Instruction &
I : *TaskloopAllocaBB) {
2795 if (
I.getOpcode() == Instruction::GetElementPtr) {
2798 switch (CI->getZExtValue()) {
2810 }
else if (
I.getOpcode() == Instruction::Load) {
2812 if (
Load.getPointerOperand() == TaskLB) {
2813 assert(TaskLB !=
nullptr &&
"Expected value for TaskLB");
2815 }
else if (
Load.getPointerOperand() == TaskUB) {
2816 assert(TaskUB !=
nullptr &&
"Expected value for TaskUB");
2818 }
else if (
Load.getPointerOperand() == TaskStep) {
2819 assert(TaskStep !=
nullptr &&
"Expected value for TaskStep");
2825 Builder.SetInsertPoint(CLI->getPreheader()->getTerminator());
2827 assert(LoadTaskLB !=
nullptr &&
"Expected value for LoadTaskLB");
2828 assert(LoadTaskUB !=
nullptr &&
"Expected value for LoadTaskUB");
2829 assert(LoadTaskStep !=
nullptr &&
"Expected value for LoadTaskStep");
2831 Builder.CreateSub(LoadTaskUB, LoadTaskLB), LoadTaskStep);
2832 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One,
"trip_cnt");
2833 Value *CastedTripCount =
Builder.CreateIntCast(TripCount, IVTy,
true);
2834 Value *CastedTaskLB =
Builder.CreateIntCast(LoadTaskLB, IVTy,
true);
2836 CLI->setTripCount(CastedTripCount);
2838 Builder.SetInsertPoint(CLI->getBody(),
2839 CLI->getBody()->getFirstInsertionPt());
2841 if (NumOfCollapseLoops > 1) {
2847 Builder.CreateSub(CastedTaskLB, ConstantInt::get(IVTy, 1)));
2850 for (
auto IVUse = CLI->getIndVar()->uses().begin();
2851 IVUse != CLI->getIndVar()->uses().end(); IVUse++) {
2852 User *IVUser = IVUse->getUser();
2854 if (
Op->getOpcode() == Instruction::URem ||
2855 Op->getOpcode() == Instruction::UDiv) {
2860 for (User *User : UsersToReplace) {
2861 User->replaceUsesOfWith(CLI->getIndVar(), IVPlusTaskLB);
2878 assert(CLI->getIndVar()->getNumUses() == 3 &&
2879 "Canonical loop should have exactly three uses of the ind var");
2880 for (User *IVUser : CLI->getIndVar()->users()) {
2882 if (
Mul->getOpcode() == Instruction::Mul) {
2883 for (User *MulUser :
Mul->users()) {
2885 if (
Add->getOpcode() == Instruction::Add) {
2886 Add->setOperand(1, CastedTaskLB);
2895 FakeLB->replaceAllUsesWith(CastedLBVal);
2896 FakeUB->replaceAllUsesWith(CastedUBVal);
2897 FakeStep->replaceAllUsesWith(CastedStepVal);
2899 I->eraseFromParent();
2904 Builder.SetInsertPoint(TaskloopExitBB, TaskloopExitBB->
begin());
2910 M.getContext(),
M.getDataLayout().getPointerSizeInBits());
2920 bool Mergeable,
Value *EventHandle,
Value *Priority,
bool FreeAgent) {
2952 if (
Error Err = BodyGenCB(TaskAllocaIP, TaskBodyIP, TaskExitBB))
2955 auto OI = std::make_unique<OutlineInfo>();
2956 OI->EntryBB = TaskAllocaBB;
2957 OI->OuterAllocBB = AllocaIP.
getBlock();
2958 OI->ExitBB = TaskExitBB;
2959 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2960 copy(DeallocBlocks, OI->OuterDeallocBBs.
end());
2965 Builder, AllocaIP, ToBeDeleted, TaskAllocaIP,
"global.tid",
false));
2967 OI->PostOutlineCB = [
this, Ident, Tied, Final, IfCondition, Dependencies,
2968 Affinities, Mergeable, Priority, EventHandle, FreeAgent,
2970 ToBeDeleted](
Function &OutlinedFn)
mutable {
2972 assert(OutlinedFn.hasOneUse() &&
2973 "there must be a single user for the outlined function");
2978 bool HasShareds = StaleCI->
arg_size() > 1;
2979 Builder.SetInsertPoint(StaleCI);
3006 bool UseMergedIf0Path = ConstIfCondition && ConstIfCondition->isZero();
3010 Flags =
Builder.CreateOr(FinalFlag, Flags);
3013 if (Mergeable || UseMergedIf0Path)
3027 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
3036 assert(ArgStructAlloca &&
3037 "Unable to find the alloca instruction corresponding to arguments "
3038 "for extracted function");
3039 std::optional<TypeSize> ArgAllocSize =
3042 "Unable to determine size of arguments for extracted function");
3043 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
3049 TaskAllocFn, {Ident, ThreadID, Flags,
3050 TaskSize, SharedsSize,
3053 if (Affinities.
Count && Affinities.
Info) {
3055 OMPRTL___kmpc_omp_reg_task_with_affinity);
3066 OMPRTL___kmpc_task_allow_completion_event);
3070 Builder.CreatePointerBitCastOrAddrSpaceCast(EventHandle,
3072 EventVal =
Builder.CreatePtrToInt(EventVal,
Builder.getInt64Ty());
3073 Builder.CreateStore(EventVal, EventHandleAddr);
3079 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
3094 Constant *Zero = ConstantInt::get(Int32Ty, 0);
3098 Builder.CreateInBoundsGEP(TaskPtr, TaskData, {Zero, Zero});
3101 VoidPtr, VoidPtr,
Builder.getInt32Ty(), VoidPtr, VoidPtr);
3103 TaskStructType, TaskGEP, {Zero, ConstantInt::get(Int32Ty, 4)});
3106 Value *CmplrData =
Builder.CreateInBoundsGEP(CmplrStructType,
3107 PriorityData, {Zero, Zero});
3108 Builder.CreateStore(Priority, CmplrData);
3111 Value *DepArray =
nullptr;
3112 Value *NumDeps =
nullptr;
3115 NumDeps = Dependencies.
NumDeps;
3116 }
else if (!Dependencies.
Deps.empty()) {
3118 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
3138 if (IfCondition && !UseMergedIf0Path) {
3143 Builder.GetInsertPoint()->getParent()->getTerminator();
3144 Instruction *ThenTI = IfTerminator, *ElseTI =
nullptr;
3145 Builder.SetInsertPoint(IfTerminator);
3148 Builder.SetInsertPoint(ElseTI);
3155 {Ident, ThreadID, NumDeps, DepArray,
3156 ConstantInt::get(
Builder.getInt32Ty(), 0),
3171 Builder.SetInsertPoint(ThenTI);
3179 {Ident, ThreadID, TaskData, NumDeps, DepArray,
3180 ConstantInt::get(
Builder.getInt32Ty(), 0),
3191 Builder.SetInsertPoint(TaskAllocaBB, TaskAllocaBB->
begin());
3193 LoadInst *Shareds =
Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
3194 OutlinedFn.getArg(1)->replaceUsesWithIf(
3195 Shareds, [Shareds](
Use &U) {
return U.getUser() != Shareds; });
3201 Builder.ClearInsertionPoint();
3203 I->eraseFromParent();
3207 Builder.SetInsertPoint(TaskExitBB, TaskExitBB->
begin());
3229 if (
Error Err = BodyGenCB(AllocaIP,
Builder.saveIP(), DeallocBlocks))
3232 Builder.SetInsertPoint(TaskgroupExitBB);
3275 unsigned CaseNumber = 0;
3276 for (
auto SectionCB : SectionCBs) {
3278 M.getContext(),
"omp_section_loop.body.case", CurFn,
Continue);
3280 Builder.SetInsertPoint(CaseBB);
3295 Value *LB = ConstantInt::get(I32Ty, 0);
3296 Value *UB = ConstantInt::get(I32Ty, SectionCBs.
size());
3297 Value *ST = ConstantInt::get(I32Ty, 1);
3299 Loc, LoopBodyGenCB, LB, UB, ST,
true,
false, AllocaIP,
"section_loop");
3304 applyStaticWorkshareLoop(
Loc.DL, *
LoopInfo, AllocaIP,
3305 WorksharingLoopType::ForStaticLoop, !IsNowait);
3311 assert(LoopFini &&
"Bad structure of static workshare loop finalization");
3315 assert(FiniInfo.DK == OMPD_sections &&
3316 "Unexpected finalization stack state!");
3317 if (
Error Err = FiniInfo.mergeFiniBB(
Builder, LoopFini))
3331 if (IP.getBlock()->end() != IP.getPoint())
3342 auto *CaseBB =
Loc.IP.getBlock();
3343 auto *CondBB = CaseBB->getSinglePredecessor()->getSinglePredecessor();
3344 auto *ExitBB = CondBB->getTerminator()->getSuccessor(1);
3350 Directive OMPD = Directive::OMPD_sections;
3353 return EmitOMPInlinedRegion(OMPD,
nullptr,
nullptr, BodyGenCB, FiniCBWrapper,
3364Value *OpenMPIRBuilder::getGPUThreadID() {
3367 OMPRTL___kmpc_get_hardware_thread_id_in_block),
3371Value *OpenMPIRBuilder::getGPUWarpSize() {
3376Value *OpenMPIRBuilder::getNVPTXWarpID() {
3377 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3378 return Builder.CreateAShr(getGPUThreadID(), LaneIDBits,
"nvptx_warp_id");
3381Value *OpenMPIRBuilder::getNVPTXLaneID() {
3382 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3383 assert(LaneIDBits < 32 &&
"Invalid LaneIDBits size in NVPTX device.");
3384 unsigned LaneIDMask = ~0
u >> (32u - LaneIDBits);
3385 return Builder.CreateAnd(getGPUThreadID(),
Builder.getInt32(LaneIDMask),
3392 uint64_t FromSize =
M.getDataLayout().getTypeStoreSize(FromType);
3393 uint64_t ToSize =
M.getDataLayout().getTypeStoreSize(ToType);
3394 assert(FromSize > 0 &&
"From size must be greater than zero");
3395 assert(ToSize > 0 &&
"To size must be greater than zero");
3396 if (FromType == ToType)
3398 if (FromSize == ToSize)
3399 return Builder.CreateBitCast(From, ToType);
3401 return Builder.CreateIntCast(From, ToType,
true);
3407 Value *ValCastItem =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3408 CastItem,
Builder.getPtrTy(0));
3409 Builder.CreateStore(From, ValCastItem);
3410 return Builder.CreateLoad(ToType, CastItem);
3417 uint64_t Size =
M.getDataLayout().getTypeStoreSize(ElementType);
3418 assert(
Size <= 8 &&
"Unsupported bitwidth in shuffle instruction");
3422 Value *ElemCast = castValueToType(AllocaIP, Element, CastTy);
3424 Builder.CreateIntCast(getGPUWarpSize(),
Builder.getInt16Ty(),
true);
3426 Size <= 4 ? RuntimeFunction::OMPRTL___kmpc_shuffle_int32
3427 : RuntimeFunction::OMPRTL___kmpc_shuffle_int64);
3428 Value *WarpSizeCast =
3430 Value *ShuffleCall =
3435 return castValueToType(AllocaIP, ShuffleCall, ElementType);
3442 uint64_t Size =
M.getDataLayout().getTypeStoreSize(ElemType);
3454 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3455 Value *ElemPtr = DstAddr;
3456 Value *Ptr = SrcAddr;
3457 for (
unsigned IntSize = 8; IntSize >= 1; IntSize /= 2) {
3461 Ptr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3464 Builder.CreateGEP(ElemType, SrcAddr, {ConstantInt::get(IndexTy, 1)});
3465 ElemPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3469 if ((
Size / IntSize) > 1) {
3470 Value *PtrEnd =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3471 SrcAddrGEP,
Builder.getPtrTy());
3488 Builder.CreatePointerBitCastOrAddrSpaceCast(Ptr,
Builder.getPtrTy()));
3490 Builder.CreateICmpSGT(PtrDiff,
Builder.getInt64(IntSize - 1)), ThenBB,
3493 Value *Res = createRuntimeShuffleFunction(
3496 IntType, Ptr,
M.getDataLayout().getPrefTypeAlign(ElemType)),
3498 Builder.CreateAlignedStore(Res, ElemPtr,
3499 M.getDataLayout().getPrefTypeAlign(ElemType));
3501 Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3502 Value *LocalElemPtr =
3503 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3511 Value *Res = createRuntimeShuffleFunction(
3512 AllocaIP,
Builder.CreateLoad(IntType, Ptr), IntType,
Offset);
3513 Builder.CreateStore(Res, ElemPtr);
3514 Ptr =
Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3516 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3522Error OpenMPIRBuilder::emitReductionListCopy(
3527 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3528 Value *RemoteLaneOffset = CopyOptions.RemoteLaneOffset;
3532 for (
auto En :
enumerate(ReductionInfos)) {
3534 Value *SrcElementAddr =
nullptr;
3535 AllocaInst *DestAlloca =
nullptr;
3536 Value *DestElementAddr =
nullptr;
3537 Value *DestElementPtrAddr =
nullptr;
3539 bool ShuffleInElement =
false;
3542 bool UpdateDestListPtr =
false;
3546 ReductionArrayTy, SrcBase,
3547 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3548 SrcElementAddr =
Builder.CreateLoad(
Builder.getPtrTy(), SrcElementPtrAddr);
3552 DestElementPtrAddr =
Builder.CreateInBoundsGEP(
3553 ReductionArrayTy, DestBase,
3554 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3555 bool IsByRefElem = (!IsByRef.
empty() && IsByRef[En.index()]);
3561 Type *DestAllocaType =
3562 IsByRefElem ? RI.ByRefAllocatedType : RI.ElementType;
3563 DestAlloca =
Builder.CreateAlloca(DestAllocaType,
nullptr,
3564 ".omp.reduction.element");
3566 M.getDataLayout().getPrefTypeAlign(DestAllocaType));
3567 DestElementAddr = DestAlloca;
3570 DestElementAddr->
getName() +
".ascast");
3572 ShuffleInElement =
true;
3573 UpdateDestListPtr =
true;
3585 if (ShuffleInElement) {
3586 Type *ShuffleType = RI.ElementType;
3587 Value *ShuffleSrcAddr = SrcElementAddr;
3588 Value *ShuffleDestAddr = DestElementAddr;
3589 AllocaInst *LocalStorage =
nullptr;
3592 assert(RI.ByRefElementType &&
"Expected by-ref element type to be set");
3593 assert(RI.ByRefAllocatedType &&
3594 "Expected by-ref allocated type to be set");
3599 ShuffleType = RI.ByRefElementType;
3601 if (RI.DataPtrPtrGen) {
3604 Builder.saveIP(), ShuffleSrcAddr, ShuffleSrcAddr);
3607 return GenResult.takeError();
3616 LocalStorage =
Builder.CreateAlloca(ShuffleType);
3618 ShuffleDestAddr = LocalStorage;
3623 ShuffleDestAddr = DestElementAddr;
3627 shuffleAndStore(AllocaIP, ShuffleSrcAddr, ShuffleDestAddr, ShuffleType,
3628 RemoteLaneOffset, ReductionArrayTy, IsByRefElem);
3630 if (IsByRefElem && RI.DataPtrPtrGen) {
3632 Value *DestDescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3633 DestAlloca,
Builder.getPtrTy(),
".ascast");
3636 DestDescriptorAddr, LocalStorage, SrcElementAddr,
3637 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
3640 return GenResult.takeError();
3643 switch (RI.EvaluationKind) {
3645 Value *Elem =
Builder.CreateLoad(RI.ElementType, SrcElementAddr);
3647 Builder.CreateStore(Elem, DestElementAddr);
3651 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3652 RI.ElementType, SrcElementAddr, 0, 0,
".realp");
3654 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
3656 RI.ElementType, SrcElementAddr, 0, 1,
".imagp");
3658 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
3660 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3661 RI.ElementType, DestElementAddr, 0, 0,
".realp");
3662 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
3663 RI.ElementType, DestElementAddr, 0, 1,
".imagp");
3664 Builder.CreateStore(SrcReal, DestRealPtr);
3665 Builder.CreateStore(SrcImg, DestImgPtr);
3670 M.getDataLayout().getTypeStoreSize(RI.ElementType));
3672 DestElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3673 SrcElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3685 if (UpdateDestListPtr) {
3686 Value *CastDestAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3687 DestElementAddr,
Builder.getPtrTy(),
3688 DestElementAddr->
getName() +
".ascast");
3689 Builder.CreateStore(CastDestAddr, DestElementPtrAddr);
3696Expected<Function *> OpenMPIRBuilder::emitInterWarpCopyFunction(
3699 IRBuilder<>::InsertPointGuard IPG(
Builder);
3700 LLVMContext &Ctx =
M.getContext();
3702 Builder.getVoidTy(), {Builder.getPtrTy(), Builder.getInt32Ty()},
3706 "_omp_reduction_inter_warp_copy_func", &
M);
3712 Builder.SetInsertPoint(EntryBB);
3730 StringRef TransferMediumName =
3731 "__openmp_nvptx_data_transfer_temporary_storage";
3732 GlobalVariable *TransferMedium =
M.getGlobalVariable(TransferMediumName);
3733 unsigned WarpSize =
Config.getGridValue().GV_Warp_Size;
3735 if (!TransferMedium) {
3736 TransferMedium =
new GlobalVariable(
3744 Value *GPUThreadID = getGPUThreadID();
3746 Value *LaneID = getNVPTXLaneID();
3748 Value *WarpID = getNVPTXWarpID();
3752 Builder.GetInsertBlock()->getFirstInsertionPt());
3756 AllocaInst *ReduceListAlloca =
Builder.CreateAlloca(
3757 Arg0Type,
nullptr, ReduceListArg->
getName() +
".addr");
3758 AllocaInst *NumWarpsAlloca =
3759 Builder.CreateAlloca(Arg1Type,
nullptr, NumWarpsArg->
getName() +
".addr");
3760 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3761 ReduceListAlloca, Arg0Type, ReduceListAlloca->
getName() +
".ascast");
3762 Value *NumWarpsAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3763 NumWarpsAlloca,
Builder.getPtrTy(0),
3764 NumWarpsAlloca->
getName() +
".ascast");
3765 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
3766 Builder.CreateStore(NumWarpsArg, NumWarpsAddrCast);
3775 for (
auto En :
enumerate(ReductionInfos)) {
3781 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
3782 unsigned RealTySize =
M.getDataLayout().getTypeAllocSize(
3783 IsByRefElem ? RI.ByRefElementType : RI.ElementType);
3784 for (
unsigned TySize = 4; TySize > 0 && RealTySize > 0; TySize /= 2) {
3787 unsigned NumIters = RealTySize / TySize;
3790 Value *Cnt =
nullptr;
3791 Value *CntAddr =
nullptr;
3798 Builder.CreateAlloca(
Builder.getInt32Ty(),
nullptr,
".cnt.addr");
3800 CntAddr =
Builder.CreateAddrSpaceCast(CntAddr,
Builder.getPtrTy(),
3801 CntAddr->
getName() +
".ascast");
3813 Cnt, ConstantInt::get(
Builder.getInt32Ty(), NumIters));
3814 Builder.CreateCondBr(Cmp, BodyBB, ExitBB);
3821 omp::Directive::OMPD_unknown,
3825 return BarrierIP1.takeError();
3831 Value *IsWarpMaster =
Builder.CreateIsNull(LaneID,
"warp_master");
3832 Builder.CreateCondBr(IsWarpMaster, ThenBB, ElseBB);
3836 auto *RedListArrayTy =
3839 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3841 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3842 {ConstantInt::get(IndexTy, 0),
3843 ConstantInt::get(IndexTy, En.index())});
3847 if (IsByRefElem && RI.DataPtrPtrGen) {
3849 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
3852 return GenRes.takeError();
3863 ArrayTy, TransferMedium, {
Builder.getInt64(0), WarpID});
3868 Builder.CreateStore(Elem, MediumPtr,
3880 omp::Directive::OMPD_unknown,
3884 return BarrierIP2.takeError();
3891 Value *NumWarpsVal =
3894 Value *IsActiveThread =
3895 Builder.CreateICmpULT(GPUThreadID, NumWarpsVal,
"is_active_thread");
3896 Builder.CreateCondBr(IsActiveThread, W0ThenBB, W0ElseBB);
3903 ArrayTy, TransferMedium, {
Builder.getInt64(0), GPUThreadID});
3905 Value *TargetElemPtrPtr =
3906 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3907 {ConstantInt::get(IndexTy, 0),
3908 ConstantInt::get(IndexTy, En.index())});
3909 Value *TargetElemPtrVal =
3911 Value *TargetElemPtr = TargetElemPtrVal;
3913 if (IsByRefElem && RI.DataPtrPtrGen) {
3915 RI.DataPtrPtrGen(
Builder.saveIP(), TargetElemPtr, TargetElemPtr);
3918 return GenRes.takeError();
3920 TargetElemPtr =
Builder.CreateLoad(
Builder.getPtrTy(), TargetElemPtr);
3928 Value *SrcMediumValue =
3929 Builder.CreateLoad(CType, SrcMediumPtrVal,
true);
3930 Builder.CreateStore(SrcMediumValue, TargetElemPtr);
3940 Cnt, ConstantInt::get(
Builder.getInt32Ty(), 1));
3941 Builder.CreateStore(Cnt, CntAddr,
false);
3943 auto *CurFn =
Builder.GetInsertBlock()->getParent();
3947 RealTySize %= TySize;
3956Expected<Function *> OpenMPIRBuilder::emitShuffleAndReduceFunction(
3959 LLVMContext &Ctx =
M.getContext();
3960 IRBuilder<>::InsertPointGuard IPG(
Builder);
3961 FunctionType *FuncTy =
3963 {Builder.getPtrTy(), Builder.getInt16Ty(),
3964 Builder.getInt16Ty(), Builder.getInt16Ty()},
3968 "_omp_reduction_shuffle_and_reduce_func", &
M);
3979 Builder.SetInsertPoint(EntryBB);
3991 Type *ReduceListArgType = ReduceListArg->
getType();
3995 ReduceListArgType,
nullptr, ReduceListArg->
getName() +
".addr");
3996 Value *LaneIdAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
3997 LaneIDArg->
getName() +
".addr");
3999 LaneIDArgType,
nullptr, RemoteLaneOffsetArg->
getName() +
".addr");
4000 Value *AlgoVerAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
4001 AlgoVerArg->
getName() +
".addr");
4008 RedListArrayTy,
nullptr,
".omp.reduction.remote_reduce_list");
4010 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4011 ReduceListAlloca, ReduceListArgType,
4012 ReduceListAlloca->
getName() +
".ascast");
4013 Value *LaneIdAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4014 LaneIdAlloca, LaneIDArgPtrType, LaneIdAlloca->
getName() +
".ascast");
4015 Value *RemoteLaneOffsetAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4016 RemoteLaneOffsetAlloca, LaneIDArgPtrType,
4017 RemoteLaneOffsetAlloca->
getName() +
".ascast");
4018 Value *AlgoVerAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4019 AlgoVerAlloca, LaneIDArgPtrType, AlgoVerAlloca->
getName() +
".ascast");
4020 Value *RemoteListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4021 RemoteReductionListAlloca,
Builder.getPtrTy(),
4022 RemoteReductionListAlloca->
getName() +
".ascast");
4024 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
4025 Builder.CreateStore(LaneIDArg, LaneIdAddrCast);
4026 Builder.CreateStore(RemoteLaneOffsetArg, RemoteLaneOffsetAddrCast);
4027 Builder.CreateStore(AlgoVerArg, AlgoVerAddrCast);
4029 Value *ReduceList =
Builder.CreateLoad(ReduceListArgType, ReduceListAddrCast);
4030 Value *LaneId =
Builder.CreateLoad(LaneIDArgType, LaneIdAddrCast);
4031 Value *RemoteLaneOffset =
4032 Builder.CreateLoad(LaneIDArgType, RemoteLaneOffsetAddrCast);
4033 Value *AlgoVer =
Builder.CreateLoad(LaneIDArgType, AlgoVerAddrCast);
4040 Error EmitRedLsCpRes = emitReductionListCopy(
4042 ReduceList, RemoteListAddrCast, IsByRef,
4043 {RemoteLaneOffset,
nullptr,
nullptr});
4046 return EmitRedLsCpRes;
4071 Value *LaneComp =
Builder.CreateICmpULT(LaneId, RemoteLaneOffset);
4076 Value *Algo2AndLaneIdComp =
Builder.CreateAnd(Algo2, LaneIdComp);
4077 Value *RemoteOffsetComp =
4079 Value *CondAlgo2 =
Builder.CreateAnd(Algo2AndLaneIdComp, RemoteOffsetComp);
4080 Value *CA0OrCA1 =
Builder.CreateOr(CondAlgo0, CondAlgo1);
4081 Value *CondReduce =
Builder.CreateOr(CA0OrCA1, CondAlgo2);
4087 Builder.CreateCondBr(CondReduce, ThenBB, ElseBB);
4089 Value *LocalReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4090 ReduceList,
Builder.getPtrTy());
4091 Value *RemoteReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4092 RemoteListAddrCast,
Builder.getPtrTy());
4094 ->addFnAttr(Attribute::NoUnwind);
4105 Value *LaneIdGtOffset =
Builder.CreateICmpUGE(LaneId, RemoteLaneOffset);
4106 Value *CondCopy =
Builder.CreateAnd(Algo1, LaneIdGtOffset);
4111 Builder.CreateCondBr(CondCopy, CpyThenBB, CpyElseBB);
4115 EmitRedLsCpRes = emitReductionListCopy(
4117 RemoteListAddrCast, ReduceList, IsByRef);
4120 return EmitRedLsCpRes;
4135OpenMPIRBuilder::generateReductionDescriptor(
4137 Type *DescriptorType,
4143 Value *DescriptorSize =
4144 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(DescriptorType));
4146 DescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4147 SrcDescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4151 Value *DataPtrField;
4153 DataPtrPtrGen(
Builder.saveIP(), DescriptorAddr, DataPtrField);
4156 return GenResult.takeError();
4159 DataPtr,
Builder.getPtrTy(),
".ascast"),
4165Expected<Value *> OpenMPIRBuilder::createReductionDescriptorCopy(
4167 Value *SrcDescriptorAddr,
Type *DescriptorPtrTy,
const Twine &Name) {
4171 AllocaInst *DescriptorAlloca =
4172 Builder.CreateAlloca(RI.ByRefAllocatedType,
nullptr, Name);
4174 M.getDataLayout().getPrefTypeAlign(RI.ByRefAllocatedType));
4175 Value *DescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4176 DescriptorAlloca, DescriptorPtrTy,
4177 DescriptorAlloca->
getName() +
".ascast");
4182 generateReductionDescriptor(DescriptorAddr, DataPtr, SrcDescriptorAddr,
4183 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
4185 return GenResult.takeError();
4187 return DescriptorAddr;
4190Expected<Function *> OpenMPIRBuilder::emitListToGlobalCopyFunction(
4193 IRBuilder<>::InsertPointGuard IPG(
Builder);
4194 LLVMContext &Ctx =
M.getContext();
4197 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4201 "_omp_reduction_list_to_global_copy_func", &
M);
4208 Builder.SetInsertPoint(EntryBlock);
4219 BufferArg->
getName() +
".addr");
4223 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4224 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4225 BufferArgAlloca,
Builder.getPtrTy(),
4226 BufferArgAlloca->
getName() +
".ascast");
4227 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4228 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4229 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4230 ReduceListArgAlloca,
Builder.getPtrTy(),
4231 ReduceListArgAlloca->
getName() +
".ascast");
4233 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4234 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4235 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4237 Value *LocalReduceList =
4239 Value *BufferArgVal =
4243 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4244 for (
auto En :
enumerate(ReductionInfos)) {
4246 auto *RedListArrayTy =
4250 RedListArrayTy, LocalReduceList,
4251 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4257 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferArgVal, Idxs);
4259 ReductionsBufferTy, BufferVD, 0, En.index());
4261 switch (RI.EvaluationKind) {
4263 Value *TargetElement;
4265 if (IsByRef.
empty() || !IsByRef[En.index()]) {
4266 TargetElement =
Builder.CreateLoad(RI.ElementType, ElemPtr);
4268 if (RI.DataPtrPtrGen) {
4270 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
4273 return GenResult.takeError();
4277 TargetElement =
Builder.CreateLoad(RI.ByRefElementType, ElemPtr);
4280 Builder.CreateStore(TargetElement, GlobVal);
4284 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4285 RI.ElementType, ElemPtr, 0, 0,
".realp");
4287 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
4289 RI.ElementType, ElemPtr, 0, 1,
".imagp");
4291 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
4293 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4294 RI.ElementType, GlobVal, 0, 0,
".realp");
4295 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4296 RI.ElementType, GlobVal, 0, 1,
".imagp");
4297 Builder.CreateStore(SrcReal, DestRealPtr);
4298 Builder.CreateStore(SrcImg, DestImgPtr);
4303 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(RI.ElementType));
4305 GlobVal,
M.getDataLayout().getPrefTypeAlign(RI.ElementType), ElemPtr,
4306 M.getDataLayout().getPrefTypeAlign(RI.ElementType), SizeVal,
false);
4316Expected<Function *> OpenMPIRBuilder::emitListToGlobalReduceFunction(
4319 IRBuilder<>::InsertPointGuard IPG(
Builder);
4320 LLVMContext &Ctx =
M.getContext();
4323 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4327 "_omp_reduction_list_to_global_reduce_func", &
M);
4334 Builder.SetInsertPoint(EntryBlock);
4345 BufferArg->
getName() +
".addr");
4349 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4350 auto *RedListArrayTy =
4355 Value *LocalReduceList =
4356 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4360 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4361 BufferArgAlloca,
Builder.getPtrTy(),
4362 BufferArgAlloca->
getName() +
".ascast");
4363 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4364 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4365 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4366 ReduceListArgAlloca,
Builder.getPtrTy(),
4367 ReduceListArgAlloca->
getName() +
".ascast");
4368 Value *LocalReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4369 LocalReduceList,
Builder.getPtrTy(),
4370 LocalReduceList->
getName() +
".ascast");
4372 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4373 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4374 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4379 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4380 for (
auto En :
enumerate(ReductionInfos)) {
4383 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4384 RedListArrayTy, LocalReduceListAddrCast,
4385 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4387 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4389 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4390 ReductionsBufferTy, BufferVD, 0, En.index());
4392 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4396 Value *SrcElementPtrPtr =
4397 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
4398 {ConstantInt::get(IndexTy, 0),
4399 ConstantInt::get(IndexTy, En.index())});
4400 Value *SrcDescriptorAddr =
4404 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4405 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4409 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4411 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4419 ->addFnAttr(Attribute::NoUnwind);
4424Expected<Function *> OpenMPIRBuilder::emitGlobalToListCopyFunction(
4427 IRBuilder<>::InsertPointGuard IPG(
Builder);
4428 LLVMContext &Ctx =
M.getContext();
4431 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4435 "_omp_reduction_global_to_list_copy_func", &
M);
4442 Builder.SetInsertPoint(EntryBlock);
4453 BufferArg->
getName() +
".addr");
4457 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4458 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4459 BufferArgAlloca,
Builder.getPtrTy(),
4460 BufferArgAlloca->
getName() +
".ascast");
4461 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4462 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4463 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4464 ReduceListArgAlloca,
Builder.getPtrTy(),
4465 ReduceListArgAlloca->
getName() +
".ascast");
4466 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4467 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4468 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4470 Value *LocalReduceList =
4475 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4476 for (
auto En :
enumerate(ReductionInfos)) {
4477 const OpenMPIRBuilder::ReductionInfo &RI = En.value();
4478 auto *RedListArrayTy =
4482 RedListArrayTy, LocalReduceList,
4483 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4488 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4489 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4490 ReductionsBufferTy, BufferVD, 0, En.index());
4496 if (!IsByRef.
empty() && IsByRef[En.index()]) {
4503 return GenResult.takeError();
4509 Value *TargetElement =
Builder.CreateLoad(ElemType, GlobValPtr);
4510 Builder.CreateStore(TargetElement, ElemPtr);
4514 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4523 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4525 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4527 Builder.CreateStore(SrcReal, DestRealPtr);
4528 Builder.CreateStore(SrcImg, DestImgPtr);
4535 ElemPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4536 GlobValPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4547Expected<Function *> OpenMPIRBuilder::emitGlobalToListReduceFunction(
4550 IRBuilder<>::InsertPointGuard IPG(
Builder);
4551 LLVMContext &Ctx =
M.getContext();
4554 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4558 "_omp_reduction_global_to_list_reduce_func", &
M);
4565 Builder.SetInsertPoint(EntryBlock);
4576 BufferArg->
getName() +
".addr");
4580 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4586 Value *LocalReduceList =
4587 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4591 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4592 BufferArgAlloca,
Builder.getPtrTy(),
4593 BufferArgAlloca->
getName() +
".ascast");
4594 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4595 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4596 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4597 ReduceListArgAlloca,
Builder.getPtrTy(),
4598 ReduceListArgAlloca->
getName() +
".ascast");
4599 Value *ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4600 LocalReduceList,
Builder.getPtrTy(),
4601 LocalReduceList->
getName() +
".ascast");
4603 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4604 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4605 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4610 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4611 for (
auto En :
enumerate(ReductionInfos)) {
4614 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4615 RedListArrayTy, ReductionList,
4616 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4619 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4620 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4621 ReductionsBufferTy, BufferVD, 0, En.index());
4623 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4625 Value *ReduceListVal =
4627 Value *SrcElementPtrPtr =
4628 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceListVal,
4629 {ConstantInt::get(IndexTy, 0),
4630 ConstantInt::get(IndexTy, En.index())});
4631 Value *SrcDescriptorAddr =
4635 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4636 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4640 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4642 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4650 ->addFnAttr(Attribute::NoUnwind);
4655std::string OpenMPIRBuilder::getReductionFuncName(StringRef Name)
const {
4656 std::string Suffix =
4658 return (Name + Suffix).str();
4661Expected<Function *> OpenMPIRBuilder::createReductionFunction(
4664 AttributeList FuncAttrs) {
4665 IRBuilder<>::InsertPointGuard IPG(
Builder);
4667 {Builder.getPtrTy(), Builder.getPtrTy()},
4669 std::string
Name = getReductionFuncName(ReducerName);
4678 Builder.SetInsertPoint(EntryBB);
4683 Value *LHSArrayPtr =
nullptr;
4684 Value *RHSArrayPtr =
nullptr;
4691 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
4693 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
4694 Value *LHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4695 LHSAlloca, Arg0Type, LHSAlloca->
getName() +
".ascast");
4696 Value *RHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4697 RHSAlloca, Arg1Type, RHSAlloca->
getName() +
".ascast");
4698 Builder.CreateStore(Arg0, LHSAddrCast);
4699 Builder.CreateStore(Arg1, RHSAddrCast);
4700 LHSArrayPtr =
Builder.CreateLoad(Arg0Type, LHSAddrCast);
4701 RHSArrayPtr =
Builder.CreateLoad(Arg1Type, RHSAddrCast);
4705 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4707 for (
auto En :
enumerate(ReductionInfos)) {
4710 RedArrayTy, RHSArrayPtr,
4711 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4713 Value *RHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4714 RHSI8Ptr, RI.PrivateVariable->getType(),
4715 RHSI8Ptr->
getName() +
".ascast");
4718 RedArrayTy, LHSArrayPtr,
4719 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4721 Value *LHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4722 LHSI8Ptr, RI.Variable->getType(), LHSI8Ptr->
getName() +
".ascast");
4731 if (!IsByRef.
empty() && !IsByRef[En.index()]) {
4732 LHS =
Builder.CreateLoad(RI.ElementType, LHSPtr);
4733 RHS =
Builder.CreateLoad(RI.ElementType, RHSPtr);
4740 return AfterIP.takeError();
4741 if (!
Builder.GetInsertBlock())
4742 return ReductionFunc;
4746 if (!IsByRef.
empty() && !IsByRef[En.index()])
4747 Builder.CreateStore(Reduced, LHSPtr);
4752 for (
auto En :
enumerate(ReductionInfos)) {
4753 unsigned Index = En.index();
4755 Value *LHSFixupPtr, *RHSFixupPtr;
4756 Builder.restoreIP(RI.ReductionGenClang(
4757 Builder.saveIP(), Index, &LHSFixupPtr, &RHSFixupPtr, ReductionFunc));
4762 LHSPtrs[Index], [ReductionFunc](
const Use &U) {
4767 RHSPtrs[Index], [ReductionFunc](
const Use &U) {
4781 return ReductionFunc;
4789 assert(RI.Variable &&
"expected non-null variable");
4790 assert(RI.PrivateVariable &&
"expected non-null private variable");
4791 assert((RI.ReductionGen || RI.ReductionGenClang) &&
4792 "expected non-null reduction generator callback");
4795 RI.Variable->getType() == RI.PrivateVariable->getType() &&
4796 "expected variables and their private equivalents to have the same "
4799 assert(RI.Variable->getType()->isPointerTy() &&
4800 "expected variables to be pointers");
4817 ArrayRef<bool> IsByRef,
bool IsNoWait,
bool IsTeamsReduction,
bool IsSPMD,
4819 Value *SrcLocInfo) {
4833 if (ReductionInfos.
size() == 0)
4843 Builder.SetInsertPoint(InsertBlock, InsertBlock->
end());
4848 AttrBuilder AttrBldr(Ctx);
4850 AttrBldr.addAttribute(Attr);
4851 AttrBldr.removeAttribute(Attribute::OptimizeNone);
4852 FuncAttrs = FuncAttrs.addFnAttributes(Ctx, AttrBldr);
4856 Builder.GetInsertBlock()->getParent()->getName(), ReductionInfos, IsByRef,
4858 if (!ReductionResult)
4860 Function *ReductionFunc = *ReductionResult;
4864 if (GridValue.has_value())
4865 Config.setGridValue(GridValue.value());
4880 Builder.getPtrTy(
M.getDataLayout().getProgramAddressSpace());
4884 Value *ReductionListAlloca =
4885 Builder.CreateAlloca(RedArrayTy,
nullptr,
".omp.reduction.red_list");
4886 Value *ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4887 ReductionListAlloca, PtrTy, ReductionListAlloca->
getName() +
".ascast");
4890 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4891 for (
auto En :
enumerate(ReductionInfos)) {
4894 RedArrayTy, ReductionList,
4895 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4898 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
4903 Builder.CreatePointerBitCastOrAddrSpaceCast(PrivateVar, PtrTy);
4904 Builder.CreateStore(CastElem, ElemPtr);
4908 ReductionInfos, ReductionFunc, FuncAttrs, IsByRef);
4914 emitInterWarpCopyFunction(
Loc, ReductionInfos, FuncAttrs, IsByRef);
4920 Value *RL =
Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList, PtrTy);
4929 unsigned MaxDataSize = 0;
4931 for (
auto En :
enumerate(ReductionInfos)) {
4935 Type *RedTypeArg = (!IsByRef.
empty() && IsByRef[En.index()])
4936 ? En.value().ByRefElementType
4937 : En.value().ElementType;
4938 auto Size =
M.getDataLayout().getTypeStoreSize(RedTypeArg);
4939 if (
Size > MaxDataSize)
4943 Value *ReductionDataSize =
4944 Builder.getInt64(MaxDataSize * ReductionInfos.
size());
4948 Function *CopyScratchToListFunc =
nullptr;
4950 Value *ScratchForCopyBack =
nullptr;
4953 Value *RLForCopyBack = RL;
4955 bool IsAtomicReduction =
4958 if (!IsTeamsReduction) {
4959 Value *SarFuncCast =
4960 Builder.CreatePointerBitCastOrAddrSpaceCast(*SarFunc, FuncPtrTy);
4962 Builder.CreatePointerBitCastOrAddrSpaceCast(WcFunc, FuncPtrTy);
4963 Value *Args[] = {SrcLocInfo, ReductionDataSize, RL, SarFuncCast,
4966 RuntimeFunction::OMPRTL___kmpc_nvptx_parallel_reduce_nowait_v2);
4968 }
else if (IsAtomicReduction) {
4972 RuntimeFunction::OMPRTL___kmpc_is_team_main_thread);
4977 Ctx, ReductionTypeArgs,
"struct._globalized_locals_ty");
4980 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
4985 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
4990 ReductionInfos, ReductionFunc, ReductionsBufferTy, FuncAttrs, IsByRef);
5013 Value *RuntimeRL = RL;
5020 ReductionsBufferTy,
nullptr,
".omp.reduction.scratch");
5021 Value *PerThreadScratch =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5022 PerThreadScratchAlloca, PtrTy,
5023 PerThreadScratchAlloca->
getName() +
".ascast");
5026 Value *PerThreadRedListAlloca =
5027 Builder.CreateAlloca(RedArrayTy,
nullptr,
5028 ".omp.reduction.per_thread_red_list");
5029 RuntimeRL =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5030 PerThreadRedListAlloca, PtrTy,
5031 PerThreadRedListAlloca->
getName() +
".ascast");
5036 for (
auto En :
enumerate(ReductionInfos)) {
5038 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
5041 ReductionsBufferTy, PerThreadScratch, 0, En.index());
5042 Value *Slot =
Builder.CreateConstInBoundsGEP2_32(RedArrayTy, RuntimeRL,
5045 Value *RuntimeListEntry = FieldPtr;
5047 Value *SrcDescriptor =
5050 AllocaIP, RI, FieldPtr, SrcDescriptor, PtrTy);
5053 RuntimeListEntry = *Descriptor;
5055 Builder.CreateStore(RuntimeListEntry, Slot);
5061 Type *CopyArg0Ty = (*LtGCFunc)->getFunctionType()->getParamType(0);
5062 Type *CopyArg2Ty = (*LtGCFunc)->getFunctionType()->getParamType(2);
5063 ScratchForCopyBack =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5064 PerThreadScratch, CopyArg0Ty);
5066 Builder.CreatePointerBitCastOrAddrSpaceCast(RL, CopyArg2Ty);
5074 *LtGCFunc, {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
5075 CopyScratchToListFunc = *GtLCFunc;
5078 Value *Args3[] = {SrcLocInfo, RuntimeRL, *SarFunc, WcFunc,
5079 *LtGCFunc, *GtLCFunc, *GtLRFunc};
5082 RuntimeFunction::OMPRTL___kmpc_gpu_xteam_reduce_nowait);
5102 if (ScratchForCopyBack) {
5105 CopyScratchToListFunc,
5106 {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
5110 for (
auto En :
enumerate(ReductionInfos)) {
5116 if (IsAtomicReduction) {
5132 Value *LHSPtr, *RHSPtr;
5134 &LHSPtr, &RHSPtr, CurFunc));
5140 RedValue =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5142 if (RHSPtr->
getType() != RHS->getType())
5144 Builder.CreatePointerBitCastOrAddrSpaceCast(RHS, RHSPtr->
getType());
5155 if (IsByRef.
empty() || !IsByRef[En.index()]) {
5157 "red.value." +
Twine(En.index()));
5168 if (!IsByRef.
empty() && !IsByRef[En.index()])
5173 if (ContinuationBlock) {
5174 Builder.CreateBr(ContinuationBlock);
5175 Builder.SetInsertPoint(ContinuationBlock);
5177 Config.setEmitLLVMUsed();
5188 ".omp.reduction.func", &M);
5199 Builder.SetInsertPoint(ReductionFuncBlock);
5201 Value *LHSArrayPtr =
nullptr;
5202 Value *RHSArrayPtr =
nullptr;
5213 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
5215 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
5216 Value *LHSAddrCast =
5217 Builder.CreatePointerBitCastOrAddrSpaceCast(LHSAlloca, Arg0Type);
5218 Value *RHSAddrCast =
5219 Builder.CreatePointerBitCastOrAddrSpaceCast(RHSAlloca, Arg1Type);
5220 Builder.CreateStore(Arg0, LHSAddrCast);
5221 Builder.CreateStore(Arg1, RHSAddrCast);
5222 LHSArrayPtr = Builder.CreateLoad(Arg0Type, LHSAddrCast);
5223 RHSArrayPtr = Builder.CreateLoad(Arg1Type, RHSAddrCast);
5225 LHSArrayPtr = ReductionFunc->
getArg(0);
5226 RHSArrayPtr = ReductionFunc->
getArg(1);
5229 unsigned NumReductions = ReductionInfos.
size();
5232 for (
auto En :
enumerate(ReductionInfos)) {
5234 Value *LHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5235 RedArrayTy, LHSArrayPtr, 0, En.index());
5236 Value *LHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), LHSI8PtrPtr);
5237 Value *LHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5240 Value *RHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5241 RedArrayTy, RHSArrayPtr, 0, En.index());
5242 Value *RHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), RHSI8PtrPtr);
5243 Value *RHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5252 Builder.restoreIP(*AfterIP);
5254 if (!Builder.GetInsertBlock())
5258 if (!IsByRef[En.index()])
5259 Builder.CreateStore(Reduced, LHSPtr);
5261 Builder.CreateRetVoid();
5268 bool IsNoWait,
bool IsTeamsReduction) {
5272 IsByRef, IsNoWait, IsTeamsReduction);
5279 if (ReductionInfos.
size() == 0)
5289 unsigned NumReductions = ReductionInfos.
size();
5292 Value *RedArray =
Builder.CreateAlloca(RedArrayTy,
nullptr,
"red.array");
5294 Builder.SetInsertPoint(InsertBlock, InsertBlock->
end());
5299 for (
auto En :
enumerate(ReductionInfos)) {
5300 unsigned Index = En.index();
5302 Value *RedArrayElemPtr =
Builder.CreateConstInBoundsGEP2_64(
5303 RedArrayTy, RedArray, 0, Index,
"red.array.elem." +
Twine(Index));
5310 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
5320 ? IdentFlag::OMP_IDENT_FLAG_ATOMIC_REDUCE
5325 unsigned RedArrayByteSize =
DL.getTypeStoreSize(RedArrayTy);
5326 Constant *RedArraySize = ConstantInt::get(IndexTy, RedArrayByteSize);
5328 Value *Lock = getOMPCriticalRegionLock(
".reduction");
5330 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_reduce_nowait
5331 : RuntimeFunction::OMPRTL___kmpc_reduce);
5334 {Ident, ThreadId, NumVariables, RedArraySize,
5335 RedArray, ReductionFunc, Lock},
5346 Builder.CreateSwitch(ReduceCall, ContinuationBlock, 2);
5347 Switch->addCase(
Builder.getInt32(1), NonAtomicRedBlock);
5348 Switch->addCase(
Builder.getInt32(2), AtomicRedBlock);
5353 Builder.SetInsertPoint(NonAtomicRedBlock);
5354 for (
auto En :
enumerate(ReductionInfos)) {
5360 if (!IsByRef[En.index()]) {
5362 "red.value." +
Twine(En.index()));
5364 Value *PrivateRedValue =
5366 "red.private.value." +
Twine(En.index()));
5374 if (!
Builder.GetInsertBlock())
5377 if (!IsByRef[En.index()])
5381 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_end_reduce_nowait
5382 : RuntimeFunction::OMPRTL___kmpc_end_reduce);
5384 Builder.CreateBr(ContinuationBlock);
5389 Builder.SetInsertPoint(AtomicRedBlock);
5390 if (CanGenerateAtomic &&
llvm::none_of(IsByRef, [](
bool P) {
return P; })) {
5397 if (!
Builder.GetInsertBlock())
5400 Builder.CreateBr(ContinuationBlock);
5413 if (!
Builder.GetInsertBlock())
5416 Builder.SetInsertPoint(ContinuationBlock);
5427 Directive OMPD = Directive::OMPD_master;
5432 Value *Args[] = {Ident, ThreadId};
5440 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5452 Directive OMPD = Directive::OMPD_masked;
5458 Value *ArgsEnd[] = {Ident, ThreadId};
5466 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5476 Call->setDoesNotThrow();
5491 bool IsInclusive,
ScanInfo *ScanRedInfo) {
5493 llvm::Error Err = emitScanBasedDirectiveDeclsIR(AllocaIP, ScanVars,
5494 ScanVarsType, ScanRedInfo);
5505 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5508 Type *DestTy = ScanVarsType[i];
5509 Value *Val =
Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5512 Builder.CreateStore(Src, Val);
5517 Builder.GetInsertBlock()->getParent());
5520 IV = ScanRedInfo->
IV;
5523 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5526 Type *DestTy = ScanVarsType[i];
5528 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5530 Builder.CreateStore(Src, ScanVars[i]);
5544 Builder.GetInsertBlock()->getParent());
5549Error OpenMPIRBuilder::emitScanBasedDirectiveDeclsIR(
5553 Builder.restoreIP(AllocaIP);
5555 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5557 Builder.CreateAlloca(Builder.getPtrTy(),
nullptr,
"vla");
5564 Builder.restoreIP(CodeGenIP);
5566 Builder.CreateAdd(ScanRedInfo->
Span, Builder.getInt32(1));
5567 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5569 Value *Allocsize = Builder.CreateTypeSize(
5570 IntPtrTy, M.getDataLayout().getTypeAllocSize(ScanVarsType[i]));
5572 Builder.CreateMalloc(
IntPtrTy, Allocsize, AllocSpan,
nullptr,
"arr");
5573 Builder.CreateStore(Buff, (*(ScanRedInfo->
ScanBuffPtrs))[ScanVars[i]]);
5600Error OpenMPIRBuilder::emitScanBasedDirectiveFinalsIR(
5606 Value *PrivateVar = RedInfo.PrivateVariable;
5607 Value *OrigVar = RedInfo.Variable;
5611 Type *SrcTy = RedInfo.ElementType;
5616 Builder.CreateStore(Src, OrigVar);
5664 Builder.GetInsertBlock()->getModule(),
5671 Builder.GetInsertBlock()->getModule(),
5677 llvm::ConstantInt::get(ScanRedInfo->
Span->
getType(), 1));
5678 Builder.SetInsertPoint(InputBB);
5681 Builder.SetInsertPoint(LoopBB);
5697 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5699 Builder.SetInsertPoint(InnerLoopBB);
5703 Value *ReductionVal = RedInfo.PrivateVariable;
5706 Type *DestTy = RedInfo.ElementType;
5709 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5712 Builder.CreateInBoundsGEP(DestTy, Buff, OffsetIval,
"arrayOffset");
5717 RedInfo.ReductionGen(
Builder.saveIP(), LHS, RHS, Result);
5720 Builder.CreateStore(Result, LHSPtr);
5723 IVal, llvm::ConstantInt::get(
Builder.getInt32Ty(), 1));
5725 CmpI =
Builder.CreateICmpUGE(NextIVal, Pow2K);
5726 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5729 Counter, llvm::ConstantInt::get(Counter->
getType(), 1));
5735 Builder.CreateCondBr(Cmp, LoopBB, ExitBB);
5756 Error Err = emitScanBasedDirectiveFinalsIR(ReductionInfos, ScanRedInfo);
5763Error OpenMPIRBuilder::emitScanBasedDirectiveIR(
5775 Error Err = InputLoopGen();
5786 Error Err = ScanLoopGen(Builder);
5793void OpenMPIRBuilder::createScanBBs(ScanInfo *ScanRedInfo) {
5830 Builder.SetInsertPoint(Preheader);
5833 Builder.SetInsertPoint(Header);
5834 PHINode *IndVarPHI =
Builder.CreatePHI(IndVarTy, 2,
"omp_" + Name +
".iv");
5835 IndVarPHI->
addIncoming(ConstantInt::get(IndVarTy, 0), Preheader);
5840 Builder.CreateICmpULT(IndVarPHI, TripCount,
"omp_" + Name +
".cmp");
5841 Builder.CreateCondBr(Cmp, Body, Exit);
5846 Builder.SetInsertPoint(Latch);
5856 bool HasNSW =
Config.hasNoSignedWrap();
5859 unsigned BitWidth = CI->getType()->getIntegerBitWidth();
5861 if (CI->getValue().ugt(SignedMax))
5863 }
else if (IsCollapsed) {
5868 Builder.CreateAdd(IndVarPHI, ConstantInt::get(IndVarTy, 1),
5869 "omp_" + Name +
".next",
true, HasNSW);
5880 CL->Header = Header;
5899 NextBB, NextBB, Name);
5931 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
5940 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
5941 ScanRedInfo->
Span = TripCount;
5947 ScanRedInfo->
IV =
IV;
5948 createScanBBs(ScanRedInfo);
5951 assert(Terminator->getNumSuccessors() == 1);
5952 BasicBlock *ContinueBlock = Terminator->getSuccessor(0);
5955 Builder.GetInsertBlock()->getParent());
5958 Builder.GetInsertBlock()->getParent());
5959 Builder.CreateBr(ContinueBlock);
5965 const auto &&InputLoopGen = [&]() ->
Error {
5968 InclusiveStop, ComputeIP, Name,
true, ScanRedInfo);
5972 Builder.restoreIP((*LoopInfo)->getAfterIP());
5978 InclusiveStop, ComputeIP, Name,
true, ScanRedInfo);
5982 Builder.restoreIP((*LoopInfo)->getAfterIP());
5986 Error Err = emitScanBasedDirectiveIR(InputLoopGen, ScanLoopGen, ScanRedInfo);
5994 bool IsSigned,
bool InclusiveStop,
const Twine &Name) {
6004 assert(IndVarTy == Stop->
getType() &&
"Stop type mismatch");
6005 assert(IndVarTy == Step->
getType() &&
"Step type mismatch");
6009 ConstantInt *Zero = ConstantInt::get(IndVarTy, 0);
6025 Incr =
Builder.CreateSelect(IsNeg,
Builder.CreateNeg(Step), Step);
6028 Span =
Builder.CreateSub(UB, LB,
"",
false,
true);
6032 Span =
Builder.CreateSub(Stop, Start,
"",
true);
6037 Value *CountIfLooping;
6038 if (InclusiveStop) {
6039 CountIfLooping =
Builder.CreateAdd(
Builder.CreateUDiv(Span, Incr), One);
6045 CountIfLooping =
Builder.CreateSelect(OneCmp, One, CountIfTwo);
6048 return Builder.CreateSelect(ZeroCmp, Zero, CountIfLooping,
6049 "omp_" + Name +
".tripcount");
6054 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
6061 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
6066 Config.hasNoSignedWrap());
6067 Value *IndVar =
Builder.CreateAdd(Span, Start,
"",
false,
6068 Config.hasNoSignedWrap());
6070 ScanRedInfo->
IV = IndVar;
6071 return BodyGenCB(
Builder.saveIP(), IndVar);
6077 Builder.getCurrentDebugLocation());
6088 unsigned Bitwidth = Ty->getIntegerBitWidth();
6091 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_4u);
6094 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_8u);
6104 unsigned Bitwidth = Ty->getIntegerBitWidth();
6107 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_4u);
6110 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_8u);
6118 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6120 "Require dedicated allocate IP");
6126 uint32_t SrcLocStrSize;
6130 case WorksharingLoopType::ForStaticLoop:
6131 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6133 case WorksharingLoopType::DistributeStaticLoop:
6134 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6136 case WorksharingLoopType::DistributeForStaticLoop:
6137 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
6144 Type *IVTy =
IV->getType();
6145 FunctionCallee StaticInit =
6146 LoopType == WorksharingLoopType::DistributeForStaticLoop
6149 FunctionCallee StaticFini =
6153 Builder.SetInsertPoint(AllocaIP.getBlock()->getFirstNonPHIOrDbgOrAlloca());
6156 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6157 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
6158 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
6159 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
6168 Constant *One = ConstantInt::get(IVTy, 1);
6169 Builder.CreateStore(Zero, PLowerBound);
6171 Builder.CreateStore(UpperBound, PUpperBound);
6172 Builder.CreateStore(One, PStride);
6178 (LoopType == WorksharingLoopType::DistributeStaticLoop)
6179 ? OMPScheduleType::OrderedDistribute
6182 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6186 auto BuildInitCall = [LoopType, SrcLoc, ThreadNum, PLastIter, PLowerBound,
6187 PUpperBound, IVTy, PStride, One,
Zero, StaticInit,
6190 PLowerBound, PUpperBound});
6191 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
6192 Value *PDistUpperBound =
6193 Builder.CreateAlloca(IVTy,
nullptr,
"p.distupperbound");
6194 Args.push_back(PDistUpperBound);
6199 BuildInitCall(SchedulingType,
Builder);
6200 if (HasDistSchedule &&
6201 LoopType != WorksharingLoopType::DistributeStaticLoop) {
6202 Constant *DistScheduleSchedType = ConstantInt::get(
6207 BuildInitCall(DistScheduleSchedType,
Builder);
6210 Value *InclusiveUpperBound =
Builder.CreateLoad(IVTy, PUpperBound);
6212 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One);
6213 CLI->setTripCount(TripCount);
6219 CLI->mapIndVar([&](Instruction *OldIV) ->
Value * {
6224 Config.hasNoSignedWrap());
6236 omp::Directive::OMPD_for,
false,
6239 return BarrierIP.takeError();
6266 Reachable.insert(
Block);
6280OpenMPIRBuilder::applyStaticChunkedWorkshareLoop(
6284 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6285 assert((ChunkSize || DistScheduleChunkSize) &&
"Chunk size is required");
6290 Type *IVTy =
IV->getType();
6292 "Max supported tripcount bitwidth is 64 bits");
6294 :
Type::getInt64Ty(Ctx);
6297 Constant *One = ConstantInt::get(InternalIVTy, 1);
6302 SmallVector<Instruction *> UIs;
6303 for (BasicBlock &BB : *
F)
6304 if (!BB.hasTerminator())
6305 UIs.
push_back(
new UnreachableInst(
F->getContext(), &BB));
6310 LoopInfo &&LI = LIA.
run(*
F,
FAM);
6311 for (Instruction *
I : UIs)
6312 I->eraseFromParent();
6315 if (ChunkSize || DistScheduleChunkSize)
6320 FunctionCallee StaticInit =
6322 FunctionCallee StaticFini =
6328 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6329 Value *PLowerBound =
6330 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.lowerbound");
6331 Value *PUpperBound =
6332 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.upperbound");
6333 Value *PStride =
Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.stride");
6342 ChunkSize ? ChunkSize : Zero, InternalIVTy,
"chunksize");
6343 Value *CastedDistScheduleChunkSize =
Builder.CreateZExtOrTrunc(
6344 DistScheduleChunkSize ? DistScheduleChunkSize : Zero, InternalIVTy,
6345 "distschedulechunksize");
6346 Value *CastedTripCount =
6347 Builder.CreateZExt(OrigTripCount, InternalIVTy,
"tripcount");
6350 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6352 ConstantInt::get(I32Type,
static_cast<int>(DistScheduleSchedType));
6353 Builder.CreateStore(Zero, PLowerBound);
6354 Value *OrigUpperBound =
Builder.CreateSub(CastedTripCount, One);
6355 Value *IsTripCountZero =
Builder.CreateICmpEQ(CastedTripCount, Zero);
6357 Builder.CreateSelect(IsTripCountZero, Zero, OrigUpperBound);
6358 Builder.CreateStore(UpperBound, PUpperBound);
6359 Builder.CreateStore(One, PStride);
6363 uint32_t SrcLocStrSize;
6366 if (DistScheduleSchedType != OMPScheduleType::None) {
6367 Flag |= OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6372 auto BuildInitCall = [StaticInit, SrcLoc, ThreadNum, PLastIter, PLowerBound,
6373 PUpperBound, PStride, One,
6374 this](
Value *SchedulingType,
Value *ChunkSize,
6377 StaticInit, {SrcLoc, ThreadNum,
6378 SchedulingType, PLastIter,
6379 PLowerBound, PUpperBound,
6383 BuildInitCall(SchedulingType, CastedChunkSize,
Builder);
6384 if (DistScheduleSchedType != OMPScheduleType::None &&
6385 SchedType != OMPScheduleType::OrderedDistributeChunked &&
6386 SchedType != OMPScheduleType::OrderedDistribute) {
6390 BuildInitCall(DistSchedulingType, CastedDistScheduleChunkSize,
Builder);
6394 Value *FirstChunkStart =
6395 Builder.CreateLoad(InternalIVTy, PLowerBound,
"omp_firstchunk.lb");
6396 Value *FirstChunkStop =
6397 Builder.CreateLoad(InternalIVTy, PUpperBound,
"omp_firstchunk.ub");
6398 Value *FirstChunkEnd =
Builder.CreateAdd(FirstChunkStop, One);
6400 Builder.CreateSub(FirstChunkEnd, FirstChunkStart,
"omp_chunk.range");
6401 Value *NextChunkStride =
6402 Builder.CreateLoad(InternalIVTy, PStride,
"omp_dispatch.stride");
6406 Value *DispatchCounter;
6414 DispatchCounter = Counter;
6417 FirstChunkStart, CastedTripCount, NextChunkStride,
6440 Value *ChunkEnd =
Builder.CreateAdd(DispatchCounter, ChunkRange);
6441 Value *IsLastChunk =
6442 Builder.CreateICmpUGE(ChunkEnd, CastedTripCount,
"omp_chunk.is_last");
6443 Value *CountUntilOrigTripCount =
6444 Builder.CreateSub(CastedTripCount, DispatchCounter);
6446 IsLastChunk, CountUntilOrigTripCount, ChunkRange,
"omp_chunk.tripcount");
6447 Value *BackcastedChunkTC =
6448 Builder.CreateTrunc(ChunkTripCount, IVTy,
"omp_chunk.tripcount.trunc");
6449 CLI->setTripCount(BackcastedChunkTC);
6454 Value *BackcastedDispatchCounter =
6455 Builder.CreateTrunc(DispatchCounter, IVTy,
"omp_dispatch.iv.trunc");
6456 CLI->mapIndVar([&](Instruction *) ->
Value * {
6458 return Builder.CreateAdd(
IV, BackcastedDispatchCounter);
6471 return AfterIP.takeError();
6486static FunctionCallee
6489 unsigned Bitwidth = Ty->getIntegerBitWidth();
6492 case WorksharingLoopType::ForStaticLoop:
6495 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_4u);
6498 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_8u);
6500 case WorksharingLoopType::DistributeStaticLoop:
6503 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_4u);
6506 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_8u);
6508 case WorksharingLoopType::DistributeForStaticLoop:
6511 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_4u);
6514 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_8u);
6517 if (Bitwidth != 32 && Bitwidth != 64) {
6529 Function &LoopBodyFn,
bool NoLoop) {
6540 if (LoopType == WorksharingLoopType::DistributeStaticLoop) {
6541 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6542 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6543 Builder.restoreIP({InsertBlock, std::prev(InsertBlock->
end())});
6548 M, omp::RuntimeFunction::OMPRTL_omp_get_num_threads);
6549 Builder.restoreIP({InsertBlock, std::prev(InsertBlock->
end())});
6553 Builder.CreateZExtOrTrunc(NumThreads, TripCountTy,
"num.threads.cast"));
6554 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6555 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
6556 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6557 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), NoLoop));
6559 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6583 Builder.restoreIP({Preheader, Preheader->
end()});
6586 Builder.CreateBr(CLI->
getExit());
6594 CleanUpInfo.
collectBlocks(RegionBlockSet, BlocksToBeRemoved);
6602 "Expected unique undroppable user of outlined function");
6604 assert(OutlinedFnCallInstruction &&
"Expected outlined function call");
6606 "Expected outlined function call to be located in loop preheader");
6608 if (OutlinedFnCallInstruction->
arg_size() > 1)
6615 LoopBodyArg, TripCount, OutlinedFn, NoLoop);
6617 for (
auto &ToBeDeletedItem : ToBeDeleted)
6618 ToBeDeletedItem->eraseFromParent();
6625 uint32_t SrcLocStrSize;
6629 case WorksharingLoopType::ForStaticLoop:
6630 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6632 case WorksharingLoopType::DistributeStaticLoop:
6633 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6635 case WorksharingLoopType::DistributeForStaticLoop:
6636 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
6641 auto OI = std::make_unique<OutlineInfo>();
6646 SmallVector<Instruction *, 4> ToBeDeleted;
6648 OI->OuterAllocBB = AllocaIP.getBlock();
6671 SmallPtrSet<BasicBlock *, 32> ParallelRegionBlockSet;
6673 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
6675 CodeExtractorAnalysisCache CEAC(*OuterFn);
6676 CodeExtractor Extractor(Blocks,
6690 SetVector<Value *> SinkingCands, HoistingCands;
6694 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
6701 for (
auto Use :
Users) {
6703 if (ParallelRegionBlockSet.
count(Inst->getParent())) {
6704 Inst->replaceUsesOfWith(CLI->
getIndVar(), NewLoopCntLoad);
6710 OI->ExcludeArgsFromAggregate.push_back(NewLoopCntLoad);
6717 OI->PostOutlineCB = [=, ToBeDeletedVec =
6718 std::move(ToBeDeleted)](
Function &OutlinedFn) {
6728 bool NeedsBarrier, omp::ScheduleKind SchedKind,
Value *ChunkSize,
6729 bool HasSimdModifier,
bool HasMonotonicModifier,
6730 bool HasNonmonotonicModifier,
bool HasOrderedClause,
6732 Value *DistScheduleChunkSize) {
6733 if (
Config.isTargetDevice())
6734 return applyWorkshareLoopTarget(
DL, CLI, AllocaIP, LoopType, NoLoop);
6736 SchedKind, ChunkSize, HasSimdModifier, HasMonotonicModifier,
6737 HasNonmonotonicModifier, HasOrderedClause, DistScheduleChunkSize);
6739 bool IsOrdered = (EffectiveScheduleType & OMPScheduleType::ModifierOrdered) ==
6740 OMPScheduleType::ModifierOrdered;
6742 if (HasDistSchedule) {
6743 DistScheduleSchedType = DistScheduleChunkSize
6744 ? OMPScheduleType::OrderedDistributeChunked
6745 : OMPScheduleType::OrderedDistribute;
6747 switch (EffectiveScheduleType & ~OMPScheduleType::ModifierMask) {
6748 case OMPScheduleType::BaseStatic:
6749 case OMPScheduleType::BaseDistribute:
6750 assert((!ChunkSize || !DistScheduleChunkSize) &&
6751 "No chunk size with static-chunked schedule");
6752 if (IsOrdered && !HasDistSchedule)
6753 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6754 NeedsBarrier, ChunkSize);
6756 if (DistScheduleChunkSize)
6757 return applyStaticChunkedWorkshareLoop(
6758 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6759 DistScheduleChunkSize, DistScheduleSchedType);
6760 return applyStaticWorkshareLoop(
DL, CLI, AllocaIP, LoopType, NeedsBarrier,
6763 case OMPScheduleType::BaseStaticChunked:
6764 case OMPScheduleType::BaseDistributeChunked:
6765 if (IsOrdered && !HasDistSchedule)
6766 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6767 NeedsBarrier, ChunkSize);
6769 return applyStaticChunkedWorkshareLoop(
6770 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6771 DistScheduleChunkSize, DistScheduleSchedType);
6773 case OMPScheduleType::BaseRuntime:
6774 case OMPScheduleType::BaseAuto:
6775 case OMPScheduleType::BaseGreedy:
6776 case OMPScheduleType::BaseBalanced:
6777 case OMPScheduleType::BaseSteal:
6778 case OMPScheduleType::BaseRuntimeSimd:
6780 "schedule type does not support user-defined chunk sizes");
6782 case OMPScheduleType::BaseGuidedSimd:
6783 case OMPScheduleType::BaseDynamicChunked:
6784 case OMPScheduleType::BaseGuidedChunked:
6785 case OMPScheduleType::BaseGuidedIterativeChunked:
6786 case OMPScheduleType::BaseGuidedAnalyticalChunked:
6787 case OMPScheduleType::BaseStaticBalancedChunked:
6788 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6789 NeedsBarrier, ChunkSize);
6802 unsigned Bitwidth = Ty->getIntegerBitWidth();
6805 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_4u);
6808 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_8u);
6816static FunctionCallee
6818 unsigned Bitwidth = Ty->getIntegerBitWidth();
6821 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_4u);
6824 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_8u);
6831static FunctionCallee
6833 unsigned Bitwidth = Ty->getIntegerBitWidth();
6836 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_4u);
6839 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_8u);
6844OpenMPIRBuilder::applyDynamicWorkshareLoop(
DebugLoc DL, CanonicalLoopInfo *CLI,
6847 bool NeedsBarrier,
Value *Chunk) {
6848 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6850 "Require dedicated allocate IP");
6852 "Require valid schedule type");
6854 bool Ordered = (SchedType & OMPScheduleType::ModifierOrdered) ==
6855 OMPScheduleType::ModifierOrdered;
6860 uint32_t SrcLocStrSize;
6867 Type *IVTy =
IV->getType();
6872 Builder.SetInsertPoint(AllocaIP.getBlock()->getFirstNonPHIOrDbgOrAlloca());
6874 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6875 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
6876 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
6877 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
6886 Constant *One = ConstantInt::get(IVTy, 1);
6887 Builder.CreateStore(One, PLowerBound);
6889 Builder.CreateStore(UpperBound, PUpperBound);
6890 Builder.CreateStore(One, PStride);
6908 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6920 Builder.SetInsertPoint(OuterCond, OuterCond->getFirstInsertionPt());
6923 {SrcLoc, ThreadNum, PLastIter, PLowerBound, PUpperBound, PStride});
6924 Constant *Zero32 = ConstantInt::get(I32Type, 0);
6927 Builder.CreateSub(
Builder.CreateLoad(IVTy, PLowerBound), One,
"lb");
6928 Builder.CreateCondBr(MoreWork, Header, Exit);
6934 PI->setIncomingBlock(0, OuterCond);
6940 Br->setSuccessor(OuterCond);
6946 UpperBound =
Builder.CreateLoad(IVTy, PUpperBound,
"ub");
6949 CI->setOperand(1, UpperBound);
6953 assert(BI->getSuccessor(1) == Exit);
6954 BI->setSuccessor(1, OuterCond);
6968 omp::Directive::OMPD_for,
false,
6971 return BarrierIP.takeError();
7023 assert(
Loops.size() >= 1 &&
"At least one loop required");
7024 size_t NumLoops =
Loops.size();
7028 return Loops.front();
7040 Loop->collectControlBlocks(OldControlBBs);
7044 if (ComputeIP.
isSet())
7051 Value *CollapsedTripCount =
nullptr;
7054 "All loops to collapse must be valid canonical loops");
7055 Value *OrigTripCount = L->getTripCount();
7056 if (!CollapsedTripCount) {
7057 CollapsedTripCount = OrigTripCount;
7062 CollapsedTripCount =
7063 Builder.CreateNUWMul(CollapsedTripCount, OrigTripCount);
7069 OrigPreheader->
getNextNode(), OrigAfter,
"collapsed",
7076 Builder.restoreIP(Result->getBodyIP());
7078 Value *Leftover = Result->getIndVar();
7080 NewIndVars.
resize(NumLoops);
7081 for (
int i = NumLoops - 1; i >= 1; --i) {
7082 Value *OrigTripCount =
Loops[i]->getTripCount();
7084 Value *NewIndVar =
Builder.CreateURem(Leftover, OrigTripCount);
7085 NewIndVars[i] = NewIndVar;
7087 Leftover =
Builder.CreateUDiv(Leftover, OrigTripCount);
7090 NewIndVars[0] = Leftover;
7099 BasicBlock *ContinueBlock = Result->getBody();
7101 auto ContinueWith = [&ContinueBlock, &ContinuePred,
DL](
BasicBlock *Dest,
7108 ContinueBlock =
nullptr;
7109 ContinuePred = NextSrc;
7116 for (
size_t i = 0; i < NumLoops - 1; ++i)
7117 ContinueWith(
Loops[i]->getBody(),
Loops[i + 1]->getHeader());
7123 for (
size_t i = NumLoops - 1; i > 0; --i)
7124 ContinueWith(
Loops[i]->getAfter(),
Loops[i - 1]->getLatch());
7127 ContinueWith(Result->getLatch(),
nullptr);
7134 for (
size_t i = 0; i < NumLoops; ++i)
7135 Loops[i]->getIndVar()->replaceAllUsesWith(NewIndVars[i]);
7149std::vector<CanonicalLoopInfo *>
7153 "Must pass as many tile sizes as there are loops");
7154 int NumLoops =
Loops.size();
7155 assert(NumLoops >= 1 &&
"At least one loop to tile required");
7167 Loop->collectControlBlocks(OldControlBBs);
7175 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7176 OrigTripCounts.
push_back(L->getTripCount());
7187 for (
int i = 0; i < NumLoops - 1; ++i) {
7200 for (
int i = 0; i < NumLoops; ++i) {
7202 Value *OrigTripCount = OrigTripCounts[i];
7215 Value *FloorTripOverflow =
7216 Builder.CreateICmpNE(FloorTripRem, ConstantInt::get(IVType, 0));
7218 FloorTripOverflow =
Builder.CreateZExt(FloorTripOverflow, IVType);
7219 Value *FloorTripCount =
7220 Builder.CreateAdd(FloorCompleteTripCount, FloorTripOverflow,
7221 "omp_floor" +
Twine(i) +
".tripcount",
true);
7224 FloorCompleteCount.
push_back(FloorCompleteTripCount);
7230 std::vector<CanonicalLoopInfo *> Result;
7231 Result.reserve(NumLoops * 2);
7244 auto EmbeddNewLoop =
7245 [
this,
DL,
F, InnerEnter, &Enter, &
Continue, &OutroInsertBefore](
7248 DL, TripCount,
F, InnerEnter, OutroInsertBefore, Name);
7253 Enter = EmbeddedLoop->
getBody();
7255 OutroInsertBefore = EmbeddedLoop->
getLatch();
7256 return EmbeddedLoop;
7260 const Twine &NameBase) {
7263 EmbeddNewLoop(
P.value(), NameBase +
Twine(
P.index()));
7264 Result.push_back(EmbeddedLoop);
7268 EmbeddNewLoops(FloorCount,
"floor");
7274 for (
int i = 0; i < NumLoops; ++i) {
7278 Value *FloorIsEpilogue =
7280 Value *TileTripCount =
7287 EmbeddNewLoops(TileCounts,
"tile");
7292 for (std::pair<BasicBlock *, BasicBlock *>
P : InbetweenCode) {
7301 BodyEnter =
nullptr;
7302 BodyEntered = ExitBB;
7314 Builder.restoreIP(Result.back()->getBodyIP());
7315 for (
int i = 0; i < NumLoops; ++i) {
7318 Value *OrigIndVar = OrigIndVars[i];
7369 assert(
Loop->isValid() &&
"Expecting a valid CanonicalLoopInfo");
7373 assert(Latch &&
"A valid CanonicalLoopInfo must have a unique latch");
7381 if (
I.mayReadOrWriteMemory()) {
7385 I.setMetadata(LLVMContext::MD_access_group,
AccessGroup);
7399 Loop->collectControlBlocks(oldControlBBs);
7404 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7405 origTripCounts.
push_back(L->getTripCount());
7414 Builder.SetInsertPoint(TCBlock);
7415 Value *fusedTripCount =
nullptr;
7417 assert(L->isValid() &&
"All loops to fuse must be valid canonical loops");
7418 Value *origTripCount = L->getTripCount();
7419 if (!fusedTripCount) {
7420 fusedTripCount = origTripCount;
7423 Value *condTP =
Builder.CreateICmpSGT(fusedTripCount, origTripCount);
7424 fusedTripCount =
Builder.CreateSelect(condTP, fusedTripCount, origTripCount,
7438 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7439 Loops[i]->getPreheader()->moveBefore(TCBlock);
7440 Loops[i]->getAfter()->moveBefore(TCBlock);
7444 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7456 for (
size_t i = 0; i <
Loops.size(); ++i) {
7458 F->getContext(),
"omp.fused.inner.cond",
F,
Loops[i]->getBody());
7459 Builder.SetInsertPoint(condBlock);
7467 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7468 Builder.SetInsertPoint(condBBs[i]);
7469 Builder.CreateCondBr(condValues[i],
Loops[i]->getBody(), condBBs[i + 1]);
7485 "omp.fused.pre_latch");
7518 const Twine &NamePrefix) {
7547 C, NamePrefix +
".if.then",
Cond->getParent(),
Cond->getNextNode());
7549 C, NamePrefix +
".if.else",
Cond->getParent(), CanonicalLoop->
getExit());
7552 Builder.SetInsertPoint(SplitBeforeIt);
7554 Builder.CreateCondBr(IfCond, ThenBlock, ElseBlock);
7557 spliceBB(IP, ThenBlock,
false, Builder.getCurrentDebugLocation());
7560 Builder.SetInsertPoint(ElseBlock);
7566 ExistingBlocks.
reserve(L->getNumBlocks() + 1);
7568 ExistingBlocks.
append(L->block_begin(), L->block_end());
7574 assert(LoopCond && LoopHeader &&
"Invalid loop structure");
7576 if (
Block == L->getLoopPreheader() ||
Block == L->getLoopLatch() ||
7583 if (
Block == ThenBlock)
7584 NewBB->
setName(NamePrefix +
".if.else");
7587 VMap[
Block] = NewBB;
7595 L->getLoopLatch()->splitBasicBlockBefore(
L->getLoopLatch()->begin(),
7596 NamePrefix +
".pre_latch");
7600 L->addBasicBlockToLoop(ThenBlock, LI);
7606 if (TargetTriple.
isX86()) {
7607 if (Features.
lookup(
"avx512f"))
7609 else if (Features.
lookup(
"avx"))
7613 if (TargetTriple.
isPPC())
7615 if (TargetTriple.
isWasm())
7624 Value *IfCond, OrderKind Order,
7634 if (!BB.hasTerminator())
7650 I->eraseFromParent();
7653 if (AlignedVars.
size()) {
7655 for (
auto &AlignedItem : AlignedVars) {
7656 Value *AlignedPtr = AlignedItem.first;
7660 Builder.CreateAlignmentAssumption(
F->getDataLayout(), AlignedPtr,
7668 createIfVersion(CanonicalLoop, IfCond, VMap, LIA, LI, L,
"simd");
7681 Reachable.insert(
Block);
7691 if ((Safelen ==
nullptr) || (Order == OrderKind::OMP_ORDER_concurrent))
7707 if (Simdlen || Safelen) {
7711 ConstantInt *VectorizeWidth = Simdlen ==
nullptr ? Safelen : Simdlen;
7737static std::unique_ptr<TargetMachine>
7741 StringRef CPU =
F->getFnAttribute(
"target-cpu").getValueAsString();
7742 StringRef Features =
F->getFnAttribute(
"target-features").getValueAsString();
7753 std::nullopt, OptLevel));
7771 if (!BB.hasTerminator())
7784 [&](
const Function &
F) {
return TM->getTargetTransformInfo(
F); });
7785 FAM.registerPass([&]() {
return TIRA; });
7799 I->eraseFromParent();
7802 assert(L &&
"Expecting CanonicalLoopInfo to be recognized as a loop");
7807 nullptr, ORE,
static_cast<int>(OptLevel),
7827 <<
" Threshold=" << UP.
Threshold <<
"\n"
7830 <<
" PartialOptSizeThreshold="
7850 Ptr =
Load->getPointerOperand();
7852 Ptr =
Store->getPointerOperand();
7859 if (Alloca->getParent() == &
F->getEntryBlock())
7879 int MaxTripCount = 0;
7880 bool MaxOrZero =
false;
7881 unsigned TripMultiple = 0;
7885 MaxTripCount, MaxOrZero, TripMultiple, UCE, UP, PP);
7886 LLVM_DEBUG(
dbgs() <<
"Suggesting unroll factor of " << Factor <<
"\n");
7897 assert(Factor >= 0 &&
"Unroll factor must not be negative");
7913 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst}));
7926 *UnrolledCLI =
Loop;
7931 "unrolling only makes sense with a factor of 2 or larger");
7933 Type *IndVarTy =
Loop->getIndVarType();
7940 std::vector<CanonicalLoopInfo *>
LoopNest =
7955 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst})});
7958 (*UnrolledCLI)->assertOK();
7976 Value *Args[] = {Ident, ThreadId, BufSize, CpyBuf, CpyFn, DidItLD};
7995 if (!CPVars.
empty()) {
8000 Directive OMPD = Directive::OMPD_single;
8005 Value *Args[] = {Ident, ThreadId};
8014 if (
Error Err = FiniCB(IP))
8035 EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCBWrapper,
8042 for (
size_t I = 0, E = CPVars.
size();
I < E; ++
I)
8045 ConstantInt::get(Int64, 0), CPVars[
I],
8048 }
else if (!IsNowait) {
8051 omp::Directive::OMPD_unknown,
false,
8069 Directive::OMPD_scope,
nullptr,
nullptr,
8070 BodyGenCB, FiniCB,
false,
true,
8078 omp::Directive::OMPD_unknown,
8094 Directive OMPD = Directive::OMPD_critical;
8099 Value *LockVar = getOMPCriticalRegionLock(CriticalName);
8100 Value *Args[] = {Ident, ThreadId, LockVar};
8117 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
8125 const Twine &Name,
bool IsDependSource) {
8128 [](
Value *SV) {
return SV->getType()->isIntegerTy(64); }) &&
8129 "OpenMP runtime requires depend vec with i64 type");
8142 for (
unsigned I = 0;
I < NumLoops; ++
I) {
8156 Value *Args[] = {Ident, ThreadId, DependBaseAddrGEP};
8174 Directive OMPD = Directive::OMPD_ordered_blockassoc;
8183 Value *Args[] = {Ident, ThreadId};
8193 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
8200 bool HasFinalize,
bool IsCancellable) {
8207 BasicBlock *EntryBB = Builder.GetInsertBlock();
8216 emitCommonDirectiveEntry(OMPD, EntryCall, ExitBB, Conditional);
8228 "Unexpected control flow graph state!!");
8230 emitCommonDirectiveExit(OMPD, FinIP, ExitCall, HasFinalize);
8232 return AfterIP.takeError();
8237 "Unexpected Insertion point location!");
8240 auto InsertBB = merged ? ExitPredBB : ExitBB;
8243 Builder.SetInsertPoint(InsertBB);
8245 return Builder.saveIP();
8249 Directive OMPD,
Value *EntryCall, BasicBlock *ExitBB,
bool Conditional) {
8251 if (!Conditional || !EntryCall)
8257 auto *UI =
new UnreachableInst(
Builder.getContext(), ThenBB);
8267 Builder.CreateCondBr(CallBool, ThenBB, ExitBB);
8271 UI->eraseFromParent();
8279 omp::Directive OMPD,
InsertPointTy FinIP, Instruction *ExitCall,
8287 "Unexpected finalization stack state!");
8290 assert(Fi.DK == OMPD &&
"Unexpected Directive for Finalization call!");
8292 if (
Error Err = Fi.mergeFiniBB(
Builder, FinIP.getBlock()))
8293 return std::move(Err);
8297 Builder.SetInsertPoint(FinIP.getBlock()->getTerminator());
8307 return IRBuilder<>::InsertPoint(ExitCall->
getParent(),
8341 "copyin.not.master.end");
8348 Builder.SetInsertPoint(OMP_Entry);
8351 Value *cmp =
Builder.CreateICmpNE(MasterPtr, PrivatePtr);
8352 Builder.CreateCondBr(cmp, CopyBegin, CopyEnd);
8354 Builder.SetInsertPoint(CopyBegin);
8372 Value *Args[] = {ThreadId,
Size, Allocator};
8395 return Builder.CreateCall(Fn, Args, Name);
8409 Value *Args[] = {ThreadId, Addr, Allocator};
8416 const Twine &Name) {
8424 M.getContext(),
M.getDataLayout().getPrefTypeAlign(Int64)));
8430 const Twine &Name) {
8432 Loc,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)), Name);
8437 const Twine &Name) {
8443 return Builder.CreateCall(Fn, Args, Name);
8448 const Twine &Name) {
8450 Loc, Addr,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)),
8457 Value *DependenceAddress,
bool HaveNowaitClause) {
8467 else if (
Device->getType() != Int32)
8470 if (NumDependences ==
nullptr) {
8471 NumDependences = ConstantInt::get(Int32, 0);
8475 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8477 Ident, ThreadId, InteropVar, InteropTypeVal,
8478 Device, NumDependences, DependenceAddress, HaveNowaitClauseVal};
8487 Value *NumDependences,
Value *DependenceAddress,
bool HaveNowaitClause) {
8497 else if (
Device->getType() != Int32)
8499 if (NumDependences ==
nullptr) {
8500 NumDependences = ConstantInt::get(Int32, 0);
8504 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8506 Ident, ThreadId, InteropVar,
Device,
8507 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8516 Value *NumDependences,
8517 Value *DependenceAddress,
8518 bool HaveNowaitClause) {
8527 else if (
Device->getType() != Int32)
8529 if (NumDependences ==
nullptr) {
8530 NumDependences = ConstantInt::get(Int32, 0);
8534 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8536 Ident, ThreadId, InteropVar,
Device,
8537 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8567 assert(!Attrs.MaxThreads.empty() && !Attrs.MaxTeams.empty() &&
8568 "expected num_threads and num_teams to be specified");
8588 const std::string DebugPrefix =
"_debug__";
8589 if (KernelName.
ends_with(DebugPrefix)) {
8590 KernelName = KernelName.
drop_back(DebugPrefix.length());
8591 Kernel =
M.getFunction(KernelName);
8597 if (Attrs.MinTeams.front() > 1 || Attrs.MaxTeams.front() > 0)
8599 Attrs.MaxTeams.front());
8603 int32_t MaxThreadsVal = Attrs.MaxThreads.front();
8608 Attrs.MinThreads.front());
8610 MaxThreadsVal = Attrs.MinThreads.front();
8619 MaxThreadsVal = int32_t(
8620 std::min<int64_t>(int64_t(MaxThreadsVal) + 64,
8623 if (MaxThreadsVal > 0)
8636 omp::RuntimeFunction::OMPRTL___kmpc_target_init);
8639 Twine DynamicEnvironmentName = KernelName +
"_dynamic_environment";
8640 Constant *DynamicEnvironmentInitializer =
8644 DynamicEnvironmentInitializer, DynamicEnvironmentName,
8646 DL.getDefaultGlobalsAddressSpace());
8650 DynamicEnvironmentGV->
getType() == DynamicEnvironmentPtr
8651 ? DynamicEnvironmentGV
8653 DynamicEnvironmentPtr);
8656 ConfigurationEnvironment, {
8657 UseGenericStateMachineVal,
8658 MayUseNestedParallelismVal,
8667 KernelEnvironment, {
8668 ConfigurationEnvironmentInitializer,
8672 std::string KernelEnvironmentName =
8673 (KernelName +
"_kernel_environment").str();
8676 KernelEnvironmentInitializer, KernelEnvironmentName,
8678 DL.getDefaultGlobalsAddressSpace());
8682 KernelEnvironmentGV->
getType() == KernelEnvironmentPtr
8683 ? KernelEnvironmentGV
8685 KernelEnvironmentPtr);
8686 Value *KernelLaunchEnvironment =
8689 KernelLaunchEnvironment =
8690 KernelLaunchEnvironment->
getType() == KernelLaunchEnvParamTy
8691 ? KernelLaunchEnvironment
8692 :
Builder.CreateAddrSpaceCast(KernelLaunchEnvironment,
8693 KernelLaunchEnvParamTy);
8695 Fn, {KernelEnvironment, KernelLaunchEnvironment});
8707 auto *UI =
Builder.CreateUnreachable();
8713 Builder.SetInsertPoint(WorkerExitBB);
8717 Builder.SetInsertPoint(CheckBBTI);
8718 Builder.CreateCondBr(ExecUserCode, UI->getParent(), WorkerExitBB);
8720 CheckBBTI->eraseFromParent();
8721 UI->eraseFromParent();
8729 int32_t TeamsReductionDataSize) {
8734 omp::RuntimeFunction::OMPRTL___kmpc_target_deinit);
8738 if (!TeamsReductionDataSize)
8744 const std::string DebugPrefix =
"_debug__";
8746 KernelName = KernelName.
drop_back(DebugPrefix.length());
8747 auto *KernelEnvironmentGV =
8748 M.getNamedGlobal((KernelName +
"_kernel_environment").str());
8749 assert(KernelEnvironmentGV &&
"Expected kernel environment global\n");
8750 auto *KernelEnvironmentInitializer = KernelEnvironmentGV->getInitializer();
8752 KernelEnvironmentInitializer,
8753 ConstantInt::get(Int32, TeamsReductionDataSize), {0, 7});
8754 KernelEnvironmentGV->setInitializer(NewInitializer);
8759 if (
Kernel.hasFnAttribute(Name)) {
8760 int32_t OldLimit =
Kernel.getFnAttributeAsParsedInteger(Name);
8766std::pair<int32_t, int32_t>
8768 int32_t ThreadLimit =
8769 Kernel.getFnAttributeAsParsedInteger(
"omp_target_thread_limit");
8772 const auto &Attr =
Kernel.getFnAttribute(
"amdgpu-flat-work-group-size");
8773 if (!Attr.isValid() || !Attr.isStringAttribute())
8774 return {0, ThreadLimit};
8775 auto [LBStr, UBStr] = Attr.getValueAsString().split(
',');
8778 return {0, ThreadLimit};
8779 UB = ThreadLimit ? std::min(ThreadLimit, UB) : UB;
8787 return {0, ThreadLimit ? std::min(ThreadLimit, UB) : UB};
8789 return {0, ThreadLimit};
8795 Kernel.addFnAttr(
"omp_target_thread_limit", std::to_string(UB));
8798 Kernel.addFnAttr(
"amdgpu-flat-work-group-size",
8806std::pair<int32_t, int32_t>
8809 return {0,
Kernel.getFnAttributeAsParsedInteger(
"omp_target_num_teams")};
8813 int32_t LB, int32_t UB) {
8821 Kernel.addFnAttr(
"omp_target_num_teams", std::to_string(LB));
8824void OpenMPIRBuilder::setOutlinedTargetRegionFunctionAttributes(
8833 else if (
T.isNVPTX())
8835 else if (
T.isSPIRV())
8841 StringRef EntryFnIDName) {
8842 if (
Config.isTargetDevice()) {
8843 assert(OutlinedFn &&
"The outlined function must exist if embedded");
8847 return new GlobalVariable(
8852Constant *OpenMPIRBuilder::createTargetRegionEntryAddr(
Function *OutlinedFn,
8853 StringRef EntryFnName) {
8857 assert(!
M.getGlobalVariable(EntryFnName,
true) &&
8858 "Named kernel already exists?");
8859 return new GlobalVariable(
8872 if (
Config.isTargetDevice() || !
Config.openMPOffloadMandatory()) {
8876 OutlinedFn = *CBResult;
8878 OutlinedFn =
nullptr;
8884 if (!IsOffloadEntry)
8887 std::string EntryFnIDName =
8889 ? std::string(EntryFnName)
8893 EntryFnName, EntryFnIDName);
8901 setOutlinedTargetRegionFunctionAttributes(OutlinedFn);
8902 auto OutlinedFnID = createOutlinedFunctionID(OutlinedFn, EntryFnIDName);
8903 auto EntryAddr = createTargetRegionEntryAddr(OutlinedFn, EntryFnName);
8905 EntryInfo, EntryAddr, OutlinedFnID,
8907 return OutlinedFnID;
8925 bool IsStandAlone = !BodyGenCB;
8932 MapInfo = &GenMapInfoCB(
Builder.saveIP());
8934 AllocaIP,
Builder.saveIP(), *MapInfo, Info, CustomMapperCB,
8935 true, DeviceAddrCB))
8942 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
8952 SrcLocInfo, DeviceID,
8959 assert(MapperFunc &&
"MapperFunc missing for standalone target data");
8963 if (Info.HasNoWait) {
8973 if (Info.HasNoWait) {
8977 emitBlock(OffloadContBlock, CurFn,
true);
8983 bool RequiresOuterTargetTask = Info.HasNoWait;
8984 if (!RequiresOuterTargetTask)
8985 cantFail(TaskBodyCB(
nullptr,
nullptr,
8989 {}, RTArgs, Info.HasNoWait));
8992 omp::OMPRTL___tgt_target_data_begin_mapper);
8996 for (
auto DeviceMap : Info.DevicePtrInfoMap) {
9000 Builder.CreateStore(LI, DeviceMap.second.second);
9037 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
9046 Value *OffloadingArgs[] = {SrcLocInfo, DeviceID,
9069 return emitIfClause(IfCond, BeginThenGen, BeginElseGen, AllocaIP);
9070 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9085 return emitIfClause(IfCond, EndThenGen, EndElseGen, AllocaIP);
9086 return EndThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9089 return emitIfClause(IfCond, BeginThenGen, EndElseGen, AllocaIP);
9090 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9101 bool IsGPUDistribute) {
9102 assert((IVSize == 32 || IVSize == 64) &&
9103 "IV size is not compatible with the omp runtime");
9105 if (IsGPUDistribute)
9107 ? (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_4
9108 : omp::OMPRTL___kmpc_distribute_static_init_4u)
9109 : (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_8
9110 : omp::OMPRTL___kmpc_distribute_static_init_8u);
9112 Name = IVSize == 32 ? (IVSigned ? omp::OMPRTL___kmpc_for_static_init_4
9113 : omp::OMPRTL___kmpc_for_static_init_4u)
9114 : (IVSigned ? omp::OMPRTL___kmpc_for_static_init_8
9115 : omp::OMPRTL___kmpc_for_static_init_8u);
9122 assert((IVSize == 32 || IVSize == 64) &&
9123 "IV size is not compatible with the omp runtime");
9125 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_4
9126 : omp::OMPRTL___kmpc_dispatch_init_4u)
9127 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_8
9128 : omp::OMPRTL___kmpc_dispatch_init_8u);
9135 assert((IVSize == 32 || IVSize == 64) &&
9136 "IV size is not compatible with the omp runtime");
9138 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_4
9139 : omp::OMPRTL___kmpc_dispatch_next_4u)
9140 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_8
9141 : omp::OMPRTL___kmpc_dispatch_next_8u);
9148 assert((IVSize == 32 || IVSize == 64) &&
9149 "IV size is not compatible with the omp runtime");
9151 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_4
9152 : omp::OMPRTL___kmpc_dispatch_fini_4u)
9153 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_8
9154 : omp::OMPRTL___kmpc_dispatch_fini_8u);
9165 DenseMap<
Value *, std::tuple<Value *, unsigned>> &ValueReplacementMap) {
9173 auto GetUpdatedDIVariable = [&](
DILocalVariable *OldVar,
unsigned arg) {
9177 if (NewVar && (arg == NewVar->
getArg()))
9187 auto UpdateDebugRecord = [&](
auto *DR) {
9190 for (
auto Loc : DR->location_ops()) {
9191 auto Iter = ValueReplacementMap.find(
Loc);
9192 if (Iter != ValueReplacementMap.end()) {
9193 DR->replaceVariableLocationOp(
Loc, std::get<0>(Iter->second));
9194 ArgNo = std::get<1>(Iter->second) + 1;
9198 DR->setVariable(GetUpdatedDIVariable(OldVar, ArgNo));
9203 if (DVR->getNumVariableLocationOps() != 1u) {
9204 DVR->setKillLocation();
9207 Value *
Loc = DVR->getVariableLocationOp(0u);
9214 RequiredBB = &DVR->getFunction()->getEntryBlock();
9216 if (RequiredBB && RequiredBB != CurBB) {
9228 "Unexpected debug intrinsic");
9230 UpdateDebugRecord(&DVR);
9231 MoveDebugRecordToCorrectBlock(&DVR);
9234 for (
auto *DVR : DVRsToDelete)
9235 DVR->getMarker()->MarkedInstr->dropOneDbgRecord(DVR);
9239 Module *M = Func->getParent();
9242 DB.createQualifiedType(dwarf::DW_TAG_pointer_type,
nullptr);
9243 unsigned ArgNo = Func->arg_size();
9245 NewSP,
"dyn_ptr", ArgNo, NewSP->
getFile(), 0, VoidPtrTy,
9246 false, DINode::DIFlags::FlagArtificial);
9248 Argument *LastArg = Func->getArg(Func->arg_size() - 1);
9249 DB.insertDeclare(LastArg, Var, DB.createExpression(),
Loc,
9271 for (
auto &Arg : Inputs)
9272 ParameterTypes.
push_back(Arg->getType()->isPointerTy()
9276 for (
auto &Arg : Inputs)
9277 ParameterTypes.
push_back(Arg->getType());
9285 auto BB = Builder.GetInsertBlock();
9286 auto M = BB->getModule();
9297 if (TargetCpuAttr.isStringAttribute())
9298 Func->addFnAttr(TargetCpuAttr);
9300 auto TargetFeaturesAttr = ParentFn->
getFnAttribute(
"target-features");
9301 if (TargetFeaturesAttr.isStringAttribute())
9302 Func->addFnAttr(TargetFeaturesAttr);
9307 OMPBuilder.
emitUsed(
"llvm.compiler.used", {ExecMode});
9317 Builder.SetCurrentDebugLocation(OutlinedFnLoc);
9321 Builder.SetInsertPoint(EntryBB);
9327 BasicBlock *UserCodeEntryBB = Builder.GetInsertBlock();
9337 splitBB(Builder,
true,
"outlined.body");
9344 Builder.SetInsertPoint(ExitBB);
9352 Builder.SetCurrentDebugLocation(OutlinedFnLoc);
9359 Builder.CreateRetVoid();
9363 auto AllocaIP = Builder.saveIP();
9368 const auto &ArgRange =
make_range(Func->arg_begin(), Func->arg_end() - 1);
9400 if (Instr->getFunction() == Func)
9401 Instr->replaceUsesOfWith(
Input, InputCopy);
9407 for (
auto InArg :
zip(Inputs, ArgRange)) {
9409 Argument &Arg = std::get<1>(InArg);
9410 Value *InputCopy =
nullptr;
9413 Arg,
Input, InputCopy, AllocaIP, Builder.saveIP(),
9417 Builder.restoreIP(*AfterIP);
9418 ValueReplacementMap[
Input] = std::make_tuple(InputCopy, Arg.
getArgNo());
9438 DeferredReplacement.push_back(std::make_pair(
Input, InputCopy));
9445 ReplaceValue(
Input, InputCopy, Func);
9449 for (
auto Deferred : DeferredReplacement)
9450 ReplaceValue(std::get<0>(Deferred), std::get<1>(Deferred), Func);
9453 ValueReplacementMap);
9461 Value *TaskWithPrivates,
9462 Type *TaskWithPrivatesTy) {
9464 Type *TaskTy = OMPIRBuilder.Task;
9467 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 0);
9468 Value *Shareds = TaskT;
9478 if (TaskWithPrivatesTy != TaskTy)
9479 Shareds = Builder.CreateStructGEP(TaskTy, TaskT, 0);
9496 const size_t NumOffloadingArrays,
const int SharedArgsOperandNo) {
9501 assert((!NumOffloadingArrays || PrivatesTy) &&
9502 "PrivatesTy cannot be nullptr when there are offloadingArrays"
9535 Type *TaskPtrTy = OMPBuilder.TaskPtr;
9536 [[maybe_unused]]
Type *TaskTy = OMPBuilder.Task;
9542 ".omp_target_task_proxy_func", M);
9543 Value *ThreadId = ProxyFn->getArg(0);
9544 Value *TaskWithPrivates = ProxyFn->getArg(1);
9545 ThreadId->
setName(
"thread.id");
9546 TaskWithPrivates->
setName(
"task");
9548 bool HasShareds = SharedArgsOperandNo > 0;
9549 bool HasOffloadingArrays = NumOffloadingArrays > 0;
9553 Builder.SetInsertPoint(EntryBB);
9560 if (HasOffloadingArrays) {
9561 assert(TaskTy != TaskWithPrivatesTy &&
9562 "If there are offloading arrays to pass to the target"
9563 "TaskTy cannot be the same as TaskWithPrivatesTy");
9566 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 1);
9567 for (
unsigned int i = 0; i < NumOffloadingArrays; ++i)
9569 Builder.CreateStructGEP(PrivatesTy, Privates, i));
9573 auto *ArgStructAlloca =
9575 assert(ArgStructAlloca &&
9576 "Unable to find the alloca instruction corresponding to arguments "
9577 "for extracted function");
9579 std::optional<TypeSize> ArgAllocSize =
9581 assert(ArgStructType && ArgAllocSize &&
9582 "Unable to determine size of arguments for extracted function");
9583 uint64_t StructSize = ArgAllocSize->getFixedValue();
9586 Builder.CreateAlloca(ArgStructType,
nullptr,
"structArg");
9588 Value *SharedsSize = Builder.getInt64(StructSize);
9591 OMPBuilder, Builder, TaskWithPrivates, TaskWithPrivatesTy);
9593 Builder.CreateMemCpy(
9594 NewArgStructAlloca, NewArgStructAlloca->
getAlign(), LoadShared,
9596 KernelLaunchArgs.
push_back(NewArgStructAlloca);
9599 Builder.CreateRetVoid();
9605 return GEP->getSourceElementType();
9607 return Alloca->getAllocatedType();
9630 if (OffloadingArraysToPrivatize.
empty())
9631 return OMPIRBuilder.Task;
9634 for (
Value *V : OffloadingArraysToPrivatize) {
9635 assert(V->getType()->isPointerTy() &&
9636 "Expected pointer to array to privatize. Got a non-pointer value "
9639 assert(ArrayTy &&
"ArrayType cannot be nullptr");
9645 "struct.task_with_privates");
9660 EntryFnName, Inputs, CBFunc,
9661 ArgAccessorFuncCB, OutlinedFnLoc);
9665 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
9802 TargetTaskAllocaBB->
begin());
9805 auto OI = std::make_unique<OutlineInfo>();
9806 OI->EntryBB = TargetTaskAllocaBB;
9807 OI->OuterAllocBB = AllocaIP.
getBlock();
9812 Builder, AllocaIP, ToBeDeleted, TargetTaskAllocaIP,
"global.tid",
false));
9815 Builder.restoreIP(TargetTaskBodyIP);
9816 if (
Error Err = TaskBodyCB(DeviceID, RTLoc, TargetTaskAllocaIP))
9834 bool NeedsTargetTask = HasNoWait && DeviceID;
9835 if (NeedsTargetTask) {
9841 OffloadingArraysToPrivatize.
push_back(V);
9842 OI->ExcludeArgsFromAggregate.push_back(V);
9846 OI->PostOutlineCB = [
this, ToBeDeleted, Dependencies, NeedsTargetTask,
9847 DeviceID, OffloadingArraysToPrivatize](
9850 "there must be a single user for the outlined function");
9864 const unsigned int NumStaleCIArgs = StaleCI->
arg_size();
9865 bool HasShareds = NumStaleCIArgs > OffloadingArraysToPrivatize.
size() + 1;
9867 NumStaleCIArgs == (OffloadingArraysToPrivatize.
size() + 2)) &&
9868 "Wrong number of arguments for StaleCI when shareds are present");
9869 int SharedArgOperandNo =
9870 HasShareds ? OffloadingArraysToPrivatize.
size() + 1 : 0;
9876 if (!OffloadingArraysToPrivatize.
empty())
9881 *
this,
Builder, StaleCI, PrivatesTy, TaskWithPrivatesTy,
9882 OffloadingArraysToPrivatize.
size(), SharedArgOperandNo);
9884 LLVM_DEBUG(
dbgs() <<
"Proxy task entry function created: " << *ProxyFn
9887 Builder.SetInsertPoint(StaleCI);
9904 OMPRTL___kmpc_omp_target_task_alloc);
9916 M.getDataLayout().getTypeStoreSize(TaskWithPrivatesTy));
9923 auto *ArgStructAlloca =
9925 assert(ArgStructAlloca &&
9926 "Unable to find the alloca instruction corresponding to arguments "
9927 "for extracted function");
9928 std::optional<TypeSize> ArgAllocSize =
9931 "Unable to determine size of arguments for extracted function");
9932 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
9951 TaskSize, SharedsSize,
9954 if (NeedsTargetTask) {
9955 assert(DeviceID &&
"Expected non-empty device ID.");
9965 *
this,
Builder, TaskData, TaskWithPrivatesTy);
9969 if (!OffloadingArraysToPrivatize.
empty()) {
9971 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskData, 1);
9972 for (
unsigned int i = 0; i < OffloadingArraysToPrivatize.
size(); ++i) {
9973 Value *PtrToPrivatize = OffloadingArraysToPrivatize[i];
9980 "ElementType should match ArrayType");
9983 Value *Dst =
Builder.CreateStructGEP(PrivatesTy, Privates, i);
9986 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(ElementType)));
9990 Value *DepArray =
nullptr;
9991 Value *NumDeps =
nullptr;
9994 NumDeps = Dependencies.
NumDeps;
9995 }
else if (!Dependencies.
Deps.empty()) {
9997 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
10008 if (!NeedsTargetTask) {
10017 ConstantInt::get(
Builder.getInt32Ty(), 0),
10030 }
else if (DepArray) {
10038 {Ident, ThreadID, TaskData, NumDeps, DepArray,
10039 ConstantInt::get(
Builder.getInt32Ty(), 0),
10047 Builder.ClearInsertionPoint();
10050 I->eraseFromParent();
10055 << *(
Builder.GetInsertBlock()) <<
"\n");
10057 << *(
Builder.GetInsertBlock()->getParent()->getParent())
10069 CustomMapperCB, IsNonContiguous, DeviceAddrCB))
10092 Builder.restoreIP(IP);
10098 return Builder.saveIP();
10101 bool HasDependencies = !Dependencies.
empty();
10102 bool RequiresOuterTargetTask = HasNoWait || HasDependencies;
10119 if (OutlinedFnID && DeviceID)
10121 EmitTargetCallFallbackCB, KArgs,
10122 DeviceID, RTLoc, TargetTaskAllocaIP);
10130 return EmitTargetCallFallbackCB(OMPBuilder.
Builder.
saveIP());
10137 auto &&EmitTargetCallElse =
10144 if (RequiresOuterTargetTask) {
10151 Dependencies, EmptyRTArgs, HasNoWait);
10153 return EmitTargetCallFallbackCB(Builder.saveIP());
10156 Builder.restoreIP(AfterIP);
10160 auto &&EmitTargetCallThen =
10164 Info.HasNoWait = HasNoWait;
10169 AllocaIP, Builder.saveIP(), Info, RTArgs, MapInfo, CustomMapperCB,
10175 for (
auto [DefaultVal, RuntimeVal] :
10177 NumTeamsC.
push_back(RuntimeVal ? RuntimeVal
10178 : Builder.getInt32(DefaultVal));
10182 auto InitMaxThreadsClause = [&Builder](
Value *
Clause) {
10184 Clause = Builder.CreateIntCast(
Clause, Builder.getInt32Ty(),
10188 auto CombineMaxThreadsClauses = [&Builder](
Value *
Clause,
Value *&Result) {
10191 Result ? Builder.CreateSelect(Builder.CreateICmpULT(Result,
Clause),
10199 Value *MaxThreadsClause =
10201 ? InitMaxThreadsClause(RuntimeAttrs.
MaxThreads.front())
10204 for (
auto [TeamsVal, TargetVal] :
zip_equal(
10206 Value *TeamsThreadLimitClause = InitMaxThreadsClause(TeamsVal);
10207 Value *NumThreads = InitMaxThreadsClause(TargetVal);
10209 CombineMaxThreadsClauses(TeamsThreadLimitClause, NumThreads);
10210 CombineMaxThreadsClauses(MaxThreadsClause, NumThreads);
10212 NumThreadsC.
push_back(NumThreads ? NumThreads : Builder.getInt32(0));
10215 unsigned NumTargetItems = Info.NumberOfPtrs;
10223 Builder.getInt64Ty(),
10225 : Builder.getInt64(0);
10229 DynCGroupMem = Builder.getInt32(0);
10232 NumTargetItems, RTArgs, TripCount, NumTeamsC, NumThreadsC, DynCGroupMem,
10233 HasNoWait,
false,
false,
10234 DynCGroupMemFallback);
10241 if (RequiresOuterTargetTask)
10243 RTLoc, AllocaIP, Dependencies,
10244 KArgs.
RTArgs, Info.HasNoWait);
10247 Builder, OutlinedFnID, EmitTargetCallFallbackCB, KArgs,
10248 RuntimeAttrs.
DeviceID, RTLoc, AllocaIP);
10251 Builder.restoreIP(AfterIP);
10258 if (!OutlinedFnID) {
10259 cantFail(EmitTargetCallElse(AllocaIP, Builder.saveIP(), DeallocBlocks));
10265 cantFail(EmitTargetCallThen(AllocaIP, Builder.saveIP(), DeallocBlocks));
10270 EmitTargetCallElse, AllocaIP));
10283 bool HasNowait,
Value *DynCGroupMem,
10290 Builder.restoreIP(CodeGenIP);
10298 *
this,
Builder, IsOffloadEntry, EntryInfo, DefaultAttrs, OutlinedFn,
10299 OutlinedFnID, Inputs, CBFunc, ArgAccessorFuncCB, OutlinedFnLoc))
10305 if (!
Config.isTargetDevice())
10307 RuntimeAttrs, IfCond, OutlinedFn, OutlinedFnID, Inputs,
10308 GenMapInfoCB, CustomMapperCB, Dependencies, HasNowait,
10309 DynCGroupMem, DynCGroupMemFallback);
10323 return OS.
str().str();
10328 return OpenMPIRBuilder::getNameWithSeparators(Parts,
Config.firstSeparator(),
10334 auto &Elem = *
InternalVars.try_emplace(Name,
nullptr).first;
10336 assert(Elem.second->getValueType() == Ty &&
10337 "OMP internal variable has different type than requested");
10350 :
M.getTargetTriple().isAMDGPU()
10352 :
DL.getDefaultGlobalsAddressSpace();
10353 auto Linkage = this->
M.getTargetTriple().isWasm()
10361 const llvm::Align PtrAlign =
DL.getPointerABIAlignment(AddressSpaceVal);
10362 GV->setAlignment(std::max(TypeAlign, PtrAlign));
10366 return Elem.second;
10369Value *OpenMPIRBuilder::getOMPCriticalRegionLock(
StringRef CriticalName) {
10370 std::string Prefix =
Twine(
"gomp_critical_user_", CriticalName).
str();
10371 std::string Name = getNameWithSeparators({Prefix,
"var"},
".",
".");
10382 return SizePtrToInt;
10387 std::string VarName) {
10395 return MaptypesArrayGlobal;
10400 unsigned NumOperands,
10409 ArrI8PtrTy,
nullptr,
".offload_baseptrs");
10413 ArrI64Ty,
nullptr,
".offload_sizes");
10424 int64_t DeviceID,
unsigned NumOperands) {
10430 Value *ArgsBaseGEP =
10432 {Builder.getInt32(0), Builder.getInt32(0)});
10435 {Builder.getInt32(0), Builder.getInt32(0)});
10436 Value *ArgSizesGEP =
10438 {Builder.getInt32(0), Builder.getInt32(0)});
10442 Builder.getInt32(NumOperands),
10443 ArgsBaseGEP, ArgsGEP, ArgSizesGEP,
10444 MaptypesArg, MapnamesArg, NullPtr});
10451 assert((!ForEndCall || Info.separateBeginEndCalls()) &&
10452 "expected region end call to runtime only when end call is separate");
10454 auto VoidPtrTy = UnqualPtrTy;
10455 auto VoidPtrPtrTy = UnqualPtrTy;
10457 auto Int64PtrTy = UnqualPtrTy;
10459 if (!Info.NumberOfPtrs) {
10471 Info.RTArgs.BasePointersArray,
10474 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray,
10478 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
10482 ForEndCall && Info.RTArgs.MapTypesArrayEnd ? Info.RTArgs.MapTypesArrayEnd
10483 : Info.RTArgs.MapTypesArray,
10489 if (!Info.EmitDebug)
10493 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.MapNamesArray,
10498 if (!Info.HasMapper)
10502 Builder.CreatePointerCast(Info.RTArgs.MappersArray, VoidPtrPtrTy);
10523 "struct.descriptor_dim");
10525 enum { OffsetFD = 0, CountFD, StrideFD };
10529 for (
unsigned I = 0, L = 0, E = NonContigInfo.
Dims.
size();
I < E; ++
I) {
10532 if (NonContigInfo.
Dims[
I] == 1)
10537 Builder.CreateAlloca(ArrayTy,
nullptr,
"dims");
10538 Builder.restoreIP(CodeGenIP);
10539 for (
unsigned II = 0, EE = NonContigInfo.
Dims[
I];
II < EE; ++
II) {
10540 unsigned RevIdx = EE -
II - 1;
10544 Value *OffsetLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, OffsetFD);
10546 NonContigInfo.
Offsets[L][RevIdx], OffsetLVal,
10547 M.getDataLayout().getPrefTypeAlign(OffsetLVal->
getType()));
10549 Value *CountLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, CountFD);
10551 NonContigInfo.
Counts[L][RevIdx], CountLVal,
10552 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10554 Value *StrideLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, StrideFD);
10556 NonContigInfo.
Strides[L][RevIdx], StrideLVal,
10557 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10560 Builder.restoreIP(CodeGenIP);
10561 Value *DAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
10562 DimsAddr,
Builder.getPtrTy());
10565 Info.RTArgs.PointersArray, 0,
I);
10567 DAddr,
P,
M.getDataLayout().getPrefTypeAlign(
Builder.getPtrTy()));
10572void OpenMPIRBuilder::emitUDMapperArrayInitOrDel(
10576 StringRef Prefix = IsInit ?
".init" :
".del";
10582 Builder.CreateICmpSGT(
Size, Builder.getInt64(1),
"omp.arrayinit.isarray");
10583 Value *DeleteBit = Builder.CreateAnd(
10586 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10587 OpenMPOffloadMappingFlags::OMP_MAP_DELETE)));
10592 Value *BaseIsBegin = Builder.CreateICmpNE(
Base, Begin);
10593 Cond = Builder.CreateOr(IsArray, BaseIsBegin);
10594 DeleteCond = Builder.CreateIsNull(
10599 DeleteCond =
Builder.CreateIsNotNull(
10615 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10616 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10617 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10618 MapTypeArg =
Builder.CreateOr(
10621 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10622 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT)));
10626 Value *OffloadingArgs[] = {MapperHandle,
Base, Begin,
10627 ArraySize, MapTypeArg, MapName};
10638 bool PreserveMemberOfFlags,
bool PropagatePresentToPointee) {
10654 MapperFn->
addFnAttr(Attribute::NoInline);
10655 MapperFn->
addFnAttr(Attribute::NoUnwind);
10666 Builder.SetInsertPoint(EntryBB);
10681 Value *PtrBegin = BeginIn;
10687 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
10688 MapType, MapName, ElementSize, HeadBB,
10699 Builder.CreateICmpEQ(PtrBegin, PtrEnd,
"omp.arraymap.isempty");
10700 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
10706 Builder.CreatePHI(PtrBegin->
getType(), 2,
"omp.arraymap.ptrcurrent");
10707 PtrPHI->addIncoming(PtrBegin, HeadBB);
10712 return Info.takeError();
10716 Value *OffloadingArgs[] = {MapperHandle};
10720 Value *ShiftedPreviousSize =
10724 for (
unsigned I = 0;
I < Info->BasePointers.size(); ++
I) {
10725 Value *CurBaseArg = Info->BasePointers[
I];
10726 Value *CurBeginArg = Info->Pointers[
I];
10727 Value *CurSizeArg = Info->Sizes[
I];
10728 Value *CurNameArg = Info->Names.size()
10733 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10736 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10738 constexpr uint64_t MemberOfMask =
10739 static_cast<uint64_t
>(OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
10740 constexpr uint64_t AttachBit =
10741 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10742 OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
10800 Value *MemberMapType;
10801 if (PreserveMemberOfFlags || (RawType & AttachBit) ||
10802 Info->HasAttachPtr[
I]) {
10803 if (RawType & MemberOfMask)
10804 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
10806 MemberMapType = OriMapType;
10808 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
10826 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10827 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10828 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10838 Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
10844 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10845 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10846 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10852 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10853 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
10854 Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
10860 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10861 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10867 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10868 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10869 Builder.CreateCondBr(IsFrom, FromBB, EndBB);
10875 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10876 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
10885 CurMapType->
addIncoming(MemberMapType, ToElseBB);
10922 uint64_t ModifierBits =
10923 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10924 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
10925 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
10926 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
10927 if (PropagatePresentToPointee && Info->HasAttachPtr[
I])
10929 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10930 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
10931 Value *ImportedModifierBits =
10934 CurMapType, ImportedModifierBits,
"omp.maptype.with.modifiers");
10939 Value *FinalMapType =
10940 (RawType & AttachBit) ? CurMapType : CurMapTypeWithModifiers;
10942 Value *OffloadingArgs[] = {MapperHandle, CurBaseArg, CurBeginArg,
10943 CurSizeArg, FinalMapType, CurNameArg};
10945 auto ChildMapperFn = CustomMapperCB(
I);
10946 if (!ChildMapperFn)
10947 return ChildMapperFn.takeError();
10948 if (*ChildMapperFn) {
10964 "omp.arraymap.next");
10965 PtrPHI->addIncoming(PtrNext, LastBB);
10966 Value *IsDone =
Builder.CreateICmpEQ(PtrNext, PtrEnd,
"omp.arraymap.isdone");
10968 Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
10973 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
10974 MapType, MapName, ElementSize, DoneBB,
10987 bool IsNonContiguous,
10991 Info.clearArrayInfo();
10994 if (Info.NumberOfPtrs == 0)
11003 Info.RTArgs.BasePointersArray =
Builder.CreateAlloca(
11004 PointerArrayType,
nullptr,
".offload_baseptrs");
11006 Info.RTArgs.PointersArray =
Builder.CreateAlloca(
11007 PointerArrayType,
nullptr,
".offload_ptrs");
11009 PointerArrayType,
nullptr,
".offload_mappers");
11010 Info.RTArgs.MappersArray = MappersArray;
11017 ConstantInt::get(Int64Ty, 0));
11019 for (
unsigned I = 0, E = CombinedInfo.
Sizes.
size();
I < E; ++
I) {
11020 bool IsNonContigEntry =
11022 (
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11024 OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG) != 0);
11027 if (IsNonContigEntry) {
11029 "Index must be in-bounds for NON_CONTIG Dims array");
11031 assert(DimCount > 0 &&
"NON_CONTIG DimCount must be > 0");
11032 ConstSizes[
I] = ConstantInt::get(Int64Ty, DimCount);
11037 ConstSizes[
I] = CI;
11041 RuntimeSizes.
set(
I);
11044 if (RuntimeSizes.
all()) {
11046 Info.RTArgs.SizesArray =
Builder.CreateAlloca(
11047 SizeArrayType,
nullptr,
".offload_sizes");
11053 auto *SizesArrayGbl =
11058 if (!RuntimeSizes.
any()) {
11059 Info.RTArgs.SizesArray = SizesArrayGbl;
11061 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
11062 Align OffloadSizeAlign =
M.getDataLayout().getABIIntegerTypeAlignment(64);
11065 SizeArrayType,
nullptr,
".offload_sizes");
11069 Buffer,
M.getDataLayout().getPrefTypeAlign(Buffer->
getType()),
11070 SizesArrayGbl, OffloadSizeAlign,
11075 Info.RTArgs.SizesArray = Buffer;
11083 for (
auto mapFlag : CombinedInfo.
Types)
11085 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11089 Info.RTArgs.MapTypesArray = MapTypesArrayGbl;
11095 Info.RTArgs.MapNamesArray = MapNamesArrayGbl;
11096 Info.EmitDebug =
true;
11098 Info.RTArgs.MapNamesArray =
11100 Info.EmitDebug =
false;
11105 if (Info.separateBeginEndCalls()) {
11106 bool EndMapTypesDiffer =
false;
11107 for (uint64_t &
Type : Mapping) {
11108 if (
Type &
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11109 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT)) {
11110 Type &= ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
11111 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
11112 EndMapTypesDiffer =
true;
11115 if (EndMapTypesDiffer) {
11117 Info.RTArgs.MapTypesArrayEnd = MapTypesArrayGbl;
11122 for (
unsigned I = 0;
I < Info.NumberOfPtrs; ++
I) {
11125 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.BasePointersArray,
11127 Builder.CreateAlignedStore(BPVal, BP,
11128 M.getDataLayout().getPrefTypeAlign(PtrTy));
11130 if (Info.requiresDevicePointerInfo()) {
11132 CodeGenIP =
Builder.saveIP();
11134 Info.DevicePtrInfoMap[BPVal] = {BP,
Builder.CreateAlloca(PtrTy)};
11137 DeviceAddrCB(
I, Info.DevicePtrInfoMap[BPVal].second);
11139 Info.DevicePtrInfoMap[BPVal] = {BP, BP};
11141 DeviceAddrCB(
I, BP);
11147 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray, 0,
11150 Builder.CreateAlignedStore(PVal,
P,
11151 M.getDataLayout().getPrefTypeAlign(PtrTy));
11153 if (RuntimeSizes.
test(
I)) {
11155 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
11161 S,
M.getDataLayout().getPrefTypeAlign(PtrTy));
11164 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
11167 auto CustomMFunc = CustomMapperCB(
I);
11169 return CustomMFunc.takeError();
11171 MFunc =
Builder.CreatePointerCast(*CustomMFunc, PtrTy);
11174 PointerArrayType, MappersArray,
11177 MFunc, MAddr,
M.getDataLayout().getPrefTypeAlign(MAddr->
getType()));
11181 Info.NumberOfPtrs == 0)
11198 Builder.ClearInsertionPoint();
11229 auto CondConstant = CI->getSExtValue();
11231 return ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
11233 return ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
11243 Builder.CreateCondBr(
Cond, ThenBlock, ElseBlock);
11246 if (
Error Err = ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks))
11252 if (
Error Err = ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks))
11261bool OpenMPIRBuilder::checkAndEmitFlushAfterAtomic(
11265 "Unexpected Atomic Ordering.");
11267 bool Flush =
false;
11329 assert(
X.Var->getType()->isPointerTy() &&
11330 "OMP Atomic expects a pointer to target memory");
11331 Type *XElemTy =
X.ElemTy;
11334 "OMP atomic read expected a scalar type");
11336 Value *XRead =
nullptr;
11340 Builder.CreateLoad(XElemTy,
X.Var,
X.IsVolatile,
"omp.atomic.read");
11349 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11352 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11354 XRead = AtomicLoadRes.first;
11361 Builder.CreateLoad(IntCastTy,
X.Var,
X.IsVolatile,
"omp.atomic.load");
11364 XRead =
Builder.CreateBitCast(XLoad, XElemTy,
"atomic.flt.cast");
11366 XRead =
Builder.CreateIntToPtr(XLoad, XElemTy,
"atomic.ptr.cast");
11369 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Read);
11370 Builder.CreateStore(XRead, V.Var, V.IsVolatile);
11381 assert(
X.Var->getType()->isPointerTy() &&
11382 "OMP Atomic expects a pointer to target memory");
11383 Type *XElemTy =
X.ElemTy;
11386 "OMP atomic write expected a scalar type");
11394 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11397 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11405 Builder.CreateBitCast(Expr, IntCastTy,
"atomic.src.int.cast");
11410 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Write);
11417 AtomicUpdateCallbackTy &UpdateOp,
bool IsXBinopExpr,
11418 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11424 Type *XTy =
X.Var->getType();
11426 "OMP Atomic expects a pointer to target memory");
11427 Type *XElemTy =
X.ElemTy;
11430 "OMP atomic update expected a scalar or struct type");
11433 "OpenMP atomic does not support LT or GT operations");
11437 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, RMWOp, UpdateOp,
X.IsVolatile,
11438 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11440 return AtomicResult.takeError();
11441 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Update);
11446Value *OpenMPIRBuilder::emitRMWOpAsInstruction(
Value *Src1,
Value *Src2,
11450 return Builder.CreateAdd(Src1, Src2);
11452 return Builder.CreateSub(Src1, Src2);
11454 return Builder.CreateAnd(Src1, Src2);
11456 return Builder.CreateNeg(Builder.CreateAnd(Src1, Src2));
11458 return Builder.CreateOr(Src1, Src2);
11460 return Builder.CreateXor(Src1, Src2);
11499Expected<std::pair<Value *, Value *>> OpenMPIRBuilder::emitAtomicUpdate(
11502 AtomicUpdateCallbackTy &UpdateOp,
bool VolatileX,
bool IsXBinopExpr,
11503 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11505 bool emitRMWOp =
false;
11513 emitRMWOp = XElemTy;
11516 emitRMWOp = (IsXBinopExpr && XElemTy);
11523 std::pair<Value *, Value *> Res;
11525 AtomicRMWInst *RMWInst =
11526 Builder.CreateAtomicRMW(RMWOp,
X, Expr, llvm::MaybeAlign(), AO);
11527 if (IsIgnoreDenormalMode)
11528 RMWInst->
setMetadata(llvm::LLVMContext::MD_atomic_ignore_denormal_mode,
11530 if (
T.isAMDGPU()) {
11531 if (!IsFineGrainedMemory)
11532 RMWInst->
setMetadata(
"amdgpu.no.fine.grained.memory",
11534 if (!IsRemoteMemory)
11538 Res.first = RMWInst;
11543 Res.second = Res.first;
11545 Res.second = emitRMWOpAsInstruction(Res.first, Expr, RMWOp);
11548 Builder.CreateLoad(XElemTy,
X,
X->getName() +
".atomic.load");
11554 OpenMPIRBuilder::AtomicInfo atomicInfo(
11556 OldVal->
getAlign(),
true , AllocaIP,
X);
11557 auto AtomicLoadRes = atomicInfo.EmitAtomicLoadLibcall(AO);
11560 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11567 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11568 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11569 Builder.SetInsertPoint(ContBB);
11571 PHI->addIncoming(AtomicLoadRes.first, CurBB);
11573 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11576 Value *Upd = *CBResult;
11577 Builder.CreateStore(Upd, NewAtomicAddr);
11580 auto Result = atomicInfo.EmitAtomicCompareExchangeLibcall(
11581 AtomicLoadRes.second, NewAtomicAddr, AO, Failure);
11582 LoadInst *PHILoad =
Builder.CreateLoad(XElemTy,
Result.first);
11583 PHI->addIncoming(PHILoad,
Builder.GetInsertBlock());
11586 Res.first = OldExprVal;
11589 if (UnreachableInst *ExitTI =
11592 Builder.SetInsertPoint(ExitBB);
11594 Builder.SetInsertPoint(ExitTI);
11597 IntegerType *IntCastTy =
11600 Builder.CreateLoad(IntCastTy,
X,
X->getName() +
".atomic.load");
11610 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11617 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11618 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11619 Builder.SetInsertPoint(ContBB);
11621 PHI->addIncoming(OldVal, CurBB);
11626 OldExprVal =
Builder.CreateBitCast(
PHI, XElemTy,
11627 X->getName() +
".atomic.fltCast");
11629 OldExprVal =
Builder.CreateIntToPtr(
PHI, XElemTy,
11630 X->getName() +
".atomic.ptrCast");
11634 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11637 Value *Upd = *CBResult;
11638 Builder.CreateStore(Upd, NewAtomicAddr);
11639 LoadInst *DesiredVal =
Builder.CreateLoad(IntCastTy, NewAtomicAddr);
11643 X,
PHI, DesiredVal, llvm::MaybeAlign(), AO, Failure);
11644 Result->setVolatile(VolatileX);
11645 Value *PreviousVal =
Builder.CreateExtractValue(Result, 0);
11646 Value *SuccessFailureVal =
Builder.CreateExtractValue(Result, 1);
11647 PHI->addIncoming(PreviousVal,
Builder.GetInsertBlock());
11648 Builder.CreateCondBr(SuccessFailureVal, ExitBB, ContBB);
11650 Res.first = OldExprVal;
11654 if (UnreachableInst *ExitTI =
11657 Builder.SetInsertPoint(ExitBB);
11659 Builder.SetInsertPoint(ExitTI);
11670 bool UpdateExpr,
bool IsPostfixUpdate,
bool IsXBinopExpr,
11671 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11676 Type *XTy =
X.Var->getType();
11678 "OMP Atomic expects a pointer to target memory");
11679 Type *XElemTy =
X.ElemTy;
11682 "OMP atomic capture expected a scalar or struct type");
11684 "OpenMP atomic does not support LT or GT operations");
11691 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, AtomicOp, UpdateOp,
X.IsVolatile,
11692 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11695 Value *CapturedVal =
11696 (IsPostfixUpdate ? AtomicResult->first : AtomicResult->second);
11697 Builder.CreateStore(CapturedVal, V.Var, V.IsVolatile);
11699 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Capture);
11707 bool IsFailOnly,
bool IsWeak) {
11711 IsPostfixUpdate, IsFailOnly, Failure, IsWeak);
11723 assert(
X.Var->getType()->isPointerTy() &&
11724 "OMP atomic expects a pointer to target memory");
11727 assert(V.Var->getType()->isPointerTy() &&
"v.var must be of pointer type");
11728 assert(V.ElemTy ==
X.ElemTy &&
"x and v must be of same type");
11731 bool IsInteger = E->getType()->isIntegerTy();
11733 if (
Op == OMPAtomicCompareOp::EQ) {
11736 Value *OldValue =
nullptr;
11737 Value *SuccessOrFail =
nullptr;
11775 X.Var->getName() +
".atomic.load");
11781 Value *EIsNaN =
Builder.CreateFCmpUNO(E, E,
"atomic.e.isnan");
11782 Value *XIsNaN =
Builder.CreateFCmpUNO(XFP, XFP,
"atomic.x.isnan");
11783 Value *EitherNaN =
Builder.CreateOr(EIsNaN, XIsNaN,
"atomic.either.nan");
11788 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11792 M.getContext(),
X.Var->getName() +
".atomic.nan",
F, ExitBB);
11794 M.getContext(),
X.Var->getName() +
".atomic.notnan",
F, ExitBB);
11796 M.getContext(),
X.Var->getName() +
".atomic.zero",
F, ExitBB);
11798 M.getContext(),
X.Var->getName() +
".atomic.normal",
F, ExitBB);
11802 Builder.SetInsertPoint(CurBB);
11803 Builder.CreateCondBr(EitherNaN, NaNBB, NotNaNBB);
11806 Builder.SetInsertPoint(NaNBB);
11810 Builder.SetInsertPoint(NotNaNBB);
11813 X.Var->getName() +
".atomic.xiszero");
11815 "atomic.e.iszero");
11816 Value *BothZero =
Builder.CreateAnd(XIsZero, EIsZero,
"atomic.both.zero");
11817 Builder.CreateCondBr(BothZero, ZeroBB, NormalBB);
11820 Builder.SetInsertPoint(ZeroBB);
11822 X.Var, XCurr, DBCast,
MaybeAlign(), AO, Failure);
11824 Value *OldZero =
Builder.CreateExtractValue(ResZero, 0);
11825 Value *OkZero =
Builder.CreateExtractValue(ResZero, 1);
11829 Builder.SetInsertPoint(NormalBB);
11831 X.Var, EBCast, DBCast,
MaybeAlign(), AO, Failure);
11833 Value *OldNormal =
Builder.CreateExtractValue(ResNormal, 0);
11834 Value *OkNormal =
Builder.CreateExtractValue(ResNormal, 1);
11840 Builder.CreatePHI(IntCastTy, 3,
X.Var->getName() +
".atomic.old");
11845 X.Var->getName() +
".atomic.ok");
11852 Builder.SetInsertPoint(ExitBB);
11857 OldValue =
Builder.CreateBitCast(OldIntPHI,
X.ElemTy,
11858 X.Var->getName() +
".atomic.old.fp");
11859 SuccessOrFail = SuccessPHI;
11867 Result =
Builder.CreateAtomicCmpXchg(
X.Var, EBCast, DBCast,
11873 Result->setWeak(IsWeak);
11876 OldValue =
Builder.CreateExtractValue(Result, 0);
11878 OldValue =
Builder.CreateBitCast(OldValue,
X.ElemTy);
11880 "OldValue and V must be of same type");
11881 if (IsPostfixUpdate) {
11882 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
11884 SuccessOrFail =
Builder.CreateExtractValue(Result, 1);
11888 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11890 CurBBTI,
X.Var->getName() +
".atomic.exit");
11896 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
11898 Builder.SetInsertPoint(ContBB);
11899 Builder.CreateStore(OldValue, V.Var);
11905 Builder.SetInsertPoint(ExitBB);
11907 Builder.SetInsertPoint(ExitTI);
11910 Value *CapturedValue =
11911 Builder.CreateSelect(SuccessOrFail, E, OldValue);
11912 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
11918 assert(R.Var->getType()->isPointerTy() &&
11919 "r.var must be of pointer type");
11920 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
11922 Value *SuccessFailureVal =
11923 Builder.CreateExtractValue(Result, 1);
11924 Value *ResultCast =
11925 R.IsSigned ?
Builder.CreateSExt(SuccessFailureVal, R.ElemTy)
11926 :
Builder.CreateZExt(SuccessFailureVal, R.ElemTy);
11927 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
11936 "OldValue and V must be of same type");
11937 if (IsPostfixUpdate) {
11938 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
11943 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11945 CurBBTI,
X.Var->getName() +
".atomic.exit");
11951 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
11953 Builder.SetInsertPoint(ContBB);
11954 Builder.CreateStore(OldValue, V.Var);
11960 Builder.SetInsertPoint(ExitBB);
11962 Builder.SetInsertPoint(ExitTI);
11965 Value *CapturedValue =
11966 Builder.CreateSelect(SuccessOrFail, E, OldValue);
11967 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
11973 assert(R.Var->getType()->isPointerTy() &&
11974 "r.var must be of pointer type");
11975 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
11977 Value *ResultCast = R.IsSigned
11978 ?
Builder.CreateSExt(SuccessOrFail, R.ElemTy)
11979 :
Builder.CreateZExt(SuccessOrFail, R.ElemTy);
11980 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
11984 assert((
Op == OMPAtomicCompareOp::MAX ||
Op == OMPAtomicCompareOp::MIN) &&
11985 "Op should be either max or min at this point");
11986 assert(!IsFailOnly &&
"IsFailOnly is only valid when the comparison is ==");
11997 if (IsXBinopExpr) {
12026 Value *CapturedValue =
nullptr;
12027 if (IsPostfixUpdate) {
12028 CapturedValue = OldValue;
12053 Value *NonAtomicCmp =
Builder.CreateCmp(Pred, OldValue, E);
12054 CapturedValue =
Builder.CreateSelect(NonAtomicCmp, E, OldValue);
12056 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
12060 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Compare);
12080 if (&OuterAllocaBB ==
Builder.GetInsertBlock()) {
12107 bool SubClausesPresent =
12108 (NumTeamsLower || NumTeamsUpper || ThreadLimit || IfExpr);
12110 if (!
Config.isTargetDevice() && SubClausesPresent) {
12111 assert((NumTeamsLower ==
nullptr || NumTeamsUpper !=
nullptr) &&
12112 "if lowerbound is non-null, then upperbound must also be non-null "
12113 "for bounds on num_teams");
12115 if (NumTeamsUpper ==
nullptr)
12116 NumTeamsUpper =
Builder.getInt32(0);
12118 if (NumTeamsLower ==
nullptr)
12119 NumTeamsLower = NumTeamsUpper;
12123 "argument to if clause must be an integer value");
12127 IfExpr =
Builder.CreateICmpNE(IfExpr,
12128 ConstantInt::get(IfExpr->
getType(), 0));
12129 NumTeamsUpper =
Builder.CreateSelect(
12130 IfExpr, NumTeamsUpper,
Builder.getInt32(1),
"numTeamsUpper");
12133 NumTeamsLower =
Builder.CreateSelect(
12134 IfExpr, NumTeamsLower,
Builder.getInt32(1),
"numTeamsLower");
12137 if (ThreadLimit ==
nullptr)
12138 ThreadLimit =
Builder.getInt32(0);
12142 Value *NumTeamsLowerInt32 =
12144 Value *NumTeamsUpperInt32 =
12146 Value *ThreadLimitInt32 =
12153 {Ident, ThreadNum, NumTeamsLowerInt32, NumTeamsUpperInt32,
12154 ThreadLimitInt32});
12159 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
12162 auto OI = std::make_unique<OutlineInfo>();
12163 OI->EntryBB = AllocaBB;
12164 OI->ExitBB = ExitBB;
12165 OI->OuterAllocBB = &OuterAllocaBB;
12171 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"gid",
true));
12173 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"tid",
true));
12175 auto HostPostOutlineCB = [
this, Ident,
12176 ToBeDeleted](
Function &OutlinedFn)
mutable {
12181 "there must be a single user for the outlined function");
12186 "Outlined function must have two or three arguments only");
12188 bool HasShared = OutlinedFn.
arg_size() == 3;
12196 assert(StaleCI &&
"Error while outlining - no CallInst user found for the "
12197 "outlined function.");
12198 Builder.SetInsertPoint(StaleCI);
12205 omp::RuntimeFunction::OMPRTL___kmpc_fork_teams),
12208 Builder.ClearInsertionPoint();
12210 I->eraseFromParent();
12213 if (!
Config.isTargetDevice())
12214 OI->PostOutlineCB = HostPostOutlineCB;
12218 Builder.SetInsertPoint(ExitBB);
12231 if (OuterAllocaBB ==
Builder.GetInsertBlock()) {
12246 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
12251 if (
Config.isTargetDevice()) {
12252 auto OI = std::make_unique<OutlineInfo>();
12253 OI->OuterAllocBB = OuterAllocIP.
getBlock();
12254 OI->EntryBB = AllocaBB;
12255 OI->ExitBB = ExitBB;
12256 OI->OuterDeallocBBs.reserve(OuterDeallocBlocks.
size());
12257 copy(OuterDeallocBlocks, OI->OuterDeallocBBs.
end());
12261 Builder.SetInsertPoint(ExitBB);
12268 std::string VarName) {
12277 return MapNamesArrayGlobal;
12282void OpenMPIRBuilder::initializeTypes(
Module &M) {
12286 unsigned ProgramAS = M.getDataLayout().getProgramAddressSpace();
12287#define OMP_TYPE(VarName, InitValue) VarName = InitValue;
12288#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \
12289 VarName##Ty = ArrayType::get(ElemTy, ArraySize); \
12290 VarName##PtrTy = PointerType::get(Ctx, DefaultTargetAS);
12291#define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) \
12292 VarName = FunctionType::get(ReturnType, {__VA_ARGS__}, IsVarArg); \
12293 VarName##Ptr = PointerType::get(Ctx, ProgramAS);
12294#define OMP_STRUCT_TYPE(VarName, StructName, Packed, ...) \
12295 T = StructType::getTypeByName(Ctx, StructName); \
12297 T = StructType::create(Ctx, {__VA_ARGS__}, StructName, Packed); \
12299 VarName##Ptr = PointerType::get(Ctx, DefaultTargetAS);
12300#include "llvm/Frontend/OpenMP/OMPKinds.def"
12311 while (!Worklist.
empty()) {
12315 if (
BlockSet.insert(SuccBB).second)
12320std::unique_ptr<CodeExtractor>
12322 bool ArgsInZeroAddressSpace,
12324 return std::make_unique<CodeExtractor>(
12334 Suffix.
str(), ArgsInZeroAddressSpace);
12337std::unique_ptr<CodeExtractor> DeviceSharedMemOutlineInfo::createCodeExtractor(
12339 return std::make_unique<DeviceSharedMemCodeExtractor>(
12340 OMPBuilder, Blocks,
nullptr,
12348 OuterDeallocBBs.empty()
12351 Suffix.
str(), ArgsInZeroAddressSpace);
12355 uint64_t
Size, int32_t Flags,
12361 Name.empty() ? Addr->
getName() : Name,
Size, Flags, 0);
12373 Fn->
addFnAttr(
"uniform-work-group-size");
12374 Fn->
addFnAttr(Attribute::MustProgress);
12392 auto &&GetMDInt = [
this](
unsigned V) {
12399 NamedMDNode *MD =
M.getOrInsertNamedMetadata(
"omp_offload.info");
12400 auto &&TargetRegionMetadataEmitter =
12401 [&
C, MD, &OrderedEntries, &GetMDInt, &GetMDString](
12416 GetMDInt(E.getKind()), GetMDInt(EntryInfo.DeviceID),
12417 GetMDInt(EntryInfo.FileID), GetMDString(EntryInfo.ParentName),
12418 GetMDInt(EntryInfo.Line), GetMDInt(EntryInfo.Count),
12419 GetMDInt(E.getOrder())};
12422 OrderedEntries[E.getOrder()] = std::make_pair(&E, EntryInfo);
12431 auto &&DeviceGlobalVarMetadataEmitter =
12432 [&
C, &OrderedEntries, &GetMDInt, &GetMDString, MD](
12442 Metadata *
Ops[] = {GetMDInt(E.getKind()), GetMDString(MangledName),
12443 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
12447 OrderedEntries[E.getOrder()] = std::make_pair(&E, varInfo);
12454 DeviceGlobalVarMetadataEmitter);
12456 for (
const auto &E : OrderedEntries) {
12457 assert(E.first &&
"All ordered entries must exist!");
12458 if (
const auto *CE =
12461 if (!CE->getID() || !CE->getAddress()) {
12465 if (!
M.getNamedValue(FnName))
12473 }
else if (
const auto *CE =
dyn_cast<
12482 if (
Config.isTargetDevice() &&
Config.hasRequiresUnifiedSharedMemory())
12484 if (!CE->getAddress()) {
12489 if (CE->getVarSize() == 0)
12493 assert(((
Config.isTargetDevice() && !CE->getAddress()) ||
12494 (!
Config.isTargetDevice() && CE->getAddress())) &&
12495 "Declaret target link address is set.");
12496 if (
Config.isTargetDevice())
12498 if (!CE->getAddress()) {
12505 if (!CE->getAddress()) {
12518 if ((
GV->hasLocalLinkage() ||
GV->hasHiddenVisibility()) &&
12522 OMPTargetGlobalVarEntryIndirectVTable))
12531 Flags, CE->getLinkage(), CE->getVarName());
12534 Flags, CE->getLinkage());
12545 if (
Config.hasRequiresFlags() && !
Config.isTargetDevice())
12551 Config.getRequiresFlags());
12561 OS <<
"_" <<
Count;
12566 unsigned NewCount = getTargetRegionEntryInfoCount(EntryInfo);
12569 EntryInfo.
Line, NewCount);
12577 auto FileIDInfo = CallBack();
12578 uint64_t FileID = 0;
12580 ID =
Status->getUniqueID();
12581 FileID =
Status->getUniqueID().getFile();
12585 FileID =
hash_value(std::get<0>(FileIDInfo));
12589 std::get<1>(FileIDInfo));
12594 for (uint64_t Remain =
12595 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12597 !(Remain & 1); Remain = Remain >> 1)
12615 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12617 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12624 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12630 Flags &=
~omp::OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
12631 Flags |= MemberOfFlag;
12637 bool IsDeclaration,
bool IsExternallyVisible,
12639 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12640 std::vector<Triple> TargetTriple,
Type *LlvmPtrTy,
12641 std::function<
Constant *()> GlobalInitializer,
12652 Config.hasRequiresUnifiedSharedMemory())) {
12657 if (!IsExternallyVisible)
12659 OS <<
"_decl_tgt_ref_ptr";
12662 Value *Ptr =
M.getNamedValue(PtrName);
12671 if (!
Config.isTargetDevice()) {
12672 if (GlobalInitializer)
12673 GV->setInitializer(GlobalInitializer());
12679 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12680 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12681 GlobalInitializer, VariableLinkage, LlvmPtrTy,
cast<Constant>(Ptr));
12693 bool IsDeclaration,
bool IsExternallyVisible,
12695 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12696 std::vector<Triple> TargetTriple,
12697 std::function<
Constant *()> GlobalInitializer,
12701 (TargetTriple.empty() && !
Config.isTargetDevice()))
12712 !
Config.hasRequiresUnifiedSharedMemory()) {
12714 VarName = MangledName;
12717 if (!IsDeclaration)
12719 M.getDataLayout().getTypeSizeInBits(LlvmVal->
getValueType()), 8);
12722 Linkage = (VariableLinkage) ? VariableLinkage() : LlvmVal->
getLinkage();
12726 if (
Config.isTargetDevice() &&
12735 if (!
M.getNamedValue(RefName)) {
12739 GvAddrRef->setConstant(
true);
12741 GvAddrRef->setInitializer(Addr);
12742 GeneratedRefs.push_back(GvAddrRef);
12751 if (
Config.isTargetDevice()) {
12752 VarName = (Addr) ? Addr->
getName() :
"";
12756 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12757 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12758 LlvmPtrTy, GlobalInitializer, VariableLinkage);
12759 VarName = (Addr) ? Addr->
getName() :
"";
12761 VarSize =
M.getDataLayout().getPointerSize();
12780 auto &&GetMDInt = [MN](
unsigned Idx) {
12785 auto &&GetMDString = [MN](
unsigned Idx) {
12787 return V->getString();
12790 switch (GetMDInt(0)) {
12794 case OffloadEntriesInfoManager::OffloadEntryInfo::
12795 OffloadingEntryInfoTargetRegion: {
12805 case OffloadEntriesInfoManager::OffloadEntryInfo::
12806 OffloadingEntryInfoDeviceGlobalVar:
12819 if (HostFilePath.
empty())
12823 if (std::error_code Err = Buf.getError()) {
12825 "OpenMPIRBuilder: " +
12833 if (std::error_code Err =
M.getError()) {
12835 (
"error parsing host file inside of OpenMPIRBuilder: " + Err.message())
12849 "expected a valid insertion block for creating an iterator loop");
12859 Builder.getCurrentDebugLocation(),
"omp.it.cont");
12871 T->eraseFromParent();
12880 if (!BodyBr || BodyBr->getSuccessor() != CLI->
getLatch()) {
12882 "iterator bodygen must terminate the canonical body with an "
12883 "unconditional branch to the loop latch",
12907 for (
const auto &
ParamAttr : ParamAttrs) {
12950 return std::string(Out.str());
12958 unsigned VecRegSize;
12960 ISADataTy ISAData[] = {
12979 for (
char Mask :
Masked) {
12980 for (
const ISADataTy &
Data : ISAData) {
12983 Out <<
"_ZGV" <<
Data.ISA << Mask;
12985 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
12999template <
typename T>
13002 StringRef MangledName,
bool OutputBecomesInput,
13006 Out << Prefix << ISA << LMask << VLEN;
13007 if (OutputBecomesInput)
13009 Out << ParSeq <<
'_' << MangledName;
13018 bool OutputBecomesInput,
13023 OutputBecomesInput, Fn);
13025 OutputBecomesInput, Fn);
13029 OutputBecomesInput, Fn);
13031 OutputBecomesInput, Fn);
13035 OutputBecomesInput, Fn);
13037 OutputBecomesInput, Fn);
13042 OutputBecomesInput, Fn);
13053 char ISA,
unsigned NarrowestDataSize,
bool OutputBecomesInput) {
13054 assert((ISA ==
'n' || ISA ==
's') &&
"Expected ISA either 's' or 'n'.");
13066 OutputBecomesInput, Fn);
13073 OutputBecomesInput, Fn);
13075 OutputBecomesInput, Fn);
13079 OutputBecomesInput, Fn);
13083 OutputBecomesInput, Fn);
13092 OutputBecomesInput, Fn);
13099 MangledName, OutputBecomesInput, Fn);
13101 MangledName, OutputBecomesInput, Fn);
13105 MangledName, OutputBecomesInput, Fn);
13109 MangledName, OutputBecomesInput, Fn);
13119 return OffloadEntriesTargetRegion.empty() &&
13120 OffloadEntriesDeviceGlobalVar.empty();
13123unsigned OffloadEntriesInfoManager::getTargetRegionEntryInfoCount(
13125 auto It = OffloadEntriesTargetRegionCount.find(
13126 getTargetRegionEntryCountKey(EntryInfo));
13127 if (It == OffloadEntriesTargetRegionCount.end())
13132void OffloadEntriesInfoManager::incrementTargetRegionEntryInfoCount(
13134 OffloadEntriesTargetRegionCount[getTargetRegionEntryCountKey(EntryInfo)] =
13135 EntryInfo.
Count + 1;
13141 OffloadEntriesTargetRegion[EntryInfo] =
13144 ++OffloadingEntriesNum;
13150 assert(EntryInfo.
Count == 0 &&
"expected default EntryInfo");
13153 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
13157 if (OMPBuilder->Config.isTargetDevice()) {
13162 auto &Entry = OffloadEntriesTargetRegion[EntryInfo];
13163 Entry.setAddress(Addr);
13165 Entry.setFlags(Flags);
13171 "Target region entry already registered!");
13173 OffloadEntriesTargetRegion[EntryInfo] = Entry;
13174 ++OffloadingEntriesNum;
13176 incrementTargetRegionEntryInfoCount(EntryInfo);
13183 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
13185 auto It = OffloadEntriesTargetRegion.find(EntryInfo);
13186 if (It == OffloadEntriesTargetRegion.end()) {
13190 if (!IgnoreAddressId && (It->second.getAddress() || It->second.getID()))
13198 for (
const auto &It : OffloadEntriesTargetRegion) {
13199 Action(It.first, It.second);
13205 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
13206 ++OffloadingEntriesNum;
13212 if (OMPBuilder->Config.isTargetDevice()) {
13216 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
13218 if (Entry.getVarSize() == 0) {
13219 Entry.setVarSize(VarSize);
13220 Entry.setLinkage(Linkage);
13224 Entry.setVarSize(VarSize);
13225 Entry.setLinkage(Linkage);
13226 Entry.setAddress(Addr);
13229 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
13230 assert(Entry.isValid() && Entry.getFlags() == Flags &&
13231 "Entry not initialized!");
13232 if (Entry.getVarSize() == 0) {
13233 Entry.setVarSize(VarSize);
13234 Entry.setLinkage(Linkage);
13241 OffloadEntriesDeviceGlobalVar.try_emplace(VarName, OffloadingEntriesNum,
13242 Addr, VarSize, Flags, Linkage,
13245 OffloadEntriesDeviceGlobalVar.try_emplace(
13246 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage,
"");
13247 ++OffloadingEntriesNum;
13254 for (
const auto &E : OffloadEntriesDeviceGlobalVar)
13255 Action(E.getKey(), E.getValue());
13262void CanonicalLoopInfo::collectControlBlocks(
13269 BBs.
append({getPreheader(), Header,
Cond, Latch, Exit, getAfter()});
13281void CanonicalLoopInfo::setTripCount(
Value *TripCount) {
13293void CanonicalLoopInfo::mapIndVar(
13303 for (
Use &U : OldIV->
uses()) {
13307 if (
User->getParent() == getCond())
13309 if (
User->getParent() == getLatch())
13315 Value *NewIV = Updater(OldIV);
13318 for (Use *U : ReplacableUses)
13339 "Preheader must terminate with unconditional branch");
13341 "Preheader must jump to header");
13345 "Header must terminate with unconditional branch");
13346 assert(Header->getSingleSuccessor() == Cond &&
13347 "Header must jump to exiting block");
13350 assert(Cond->getSinglePredecessor() == Header &&
13351 "Exiting block only reachable from header");
13354 "Exiting block must terminate with conditional branch");
13356 "Exiting block's first successor jump to the body");
13358 "Exiting block's second successor must exit the loop");
13362 "Body only reachable from exiting block");
13367 "Latch must terminate with unconditional branch");
13368 assert(Latch->getSingleSuccessor() == Header &&
"Latch must jump to header");
13371 assert(Latch->getSinglePredecessor() !=
nullptr);
13376 "Exit block must terminate with unconditional branch");
13377 assert(Exit->getSingleSuccessor() == After &&
13378 "Exit block must jump to after block");
13382 "After block only reachable from exit block");
13386 assert(IndVar &&
"Canonical induction variable not found?");
13388 "Induction variable must be an integer");
13390 "Induction variable must be a PHI in the loop header");
13396 auto *NextIndVar =
cast<PHINode>(IndVar)->getIncomingValue(1);
13404 assert(TripCount &&
"Loop trip count not found?");
13406 "Trip count and induction variable must have the same type");
13410 "Exit condition must be a signed less-than comparison");
13412 "Exit condition must compare the induction variable");
13414 "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 Expected< Function * > createOutlinedFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, const OpenMPIRBuilder::TargetKernelDefaultAttrs &DefaultAttrs, StringRef FuncName, SmallVectorImpl< Value * > &Inputs, OpenMPIRBuilder::TargetBodyGenCallbackTy &CBFunc, OpenMPIRBuilder::TargetGenArgAccessorsCallbackTy &ArgAccessorFuncCB, DebugLoc OutlinedFnLoc)
static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, char ISA, StringRef ParSeq, StringRef MangledName, bool OutputBecomesInput, llvm::Function *Fn)
static FunctionCallee getKmpcForDynamicFiniForType(Type *Ty, Module &M, OpenMPIRBuilder &OMPBuilder)
Returns an LLVM function to call for finalizing the dynamic loop using depending on type.
static void FixupDebugInfoForOutlinedFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, Function *Func, DenseMap< Value *, std::tuple< Value *, unsigned > > &ValueReplacementMap)
static OMPScheduleType getOpenMPOrderingScheduleType(OMPScheduleType BaseScheduleType, bool HasOrderedClause)
Adds ordering modifier flags to schedule type.
static OMPScheduleType getOpenMPMonotonicityScheduleType(OMPScheduleType ScheduleType, bool HasSimdModifier, bool HasMonotonic, bool HasNonmonotonic, bool HasOrderedClause)
Adds monotonicity modifier flags to schedule type.
static std::string mangleVectorParameters(ArrayRef< llvm::OpenMPIRBuilder::DeclareSimdAttrTy > ParamAttrs)
Mangle the parameter part of the vector function name according to their OpenMP classification.
static bool isGenericKernel(Function &Fn)
static void workshareLoopTargetCallback(OpenMPIRBuilder *OMPIRBuilder, CanonicalLoopInfo *CLI, Value *Ident, Function &OutlinedFn, const SmallVector< Instruction *, 4 > &ToBeDeleted, WorksharingLoopType LoopType, bool NoLoop)
static bool isValidWorkshareLoopScheduleType(OMPScheduleType SchedType)
static bool isAtomicableReductionSet(ArrayRef< OpenMPIRBuilder::ReductionInfo > ReductionInfos)
static llvm::CallInst * emitNoUnwindRuntimeCall(IRBuilder<> &Builder, llvm::FunctionCallee Callee, ArrayRef< llvm::Value * > Args, const llvm::Twine &Name)
static Error populateReductionFunction(Function *ReductionFunc, ArrayRef< OpenMPIRBuilder::ReductionInfo > ReductionInfos, IRBuilder<> &Builder, ArrayRef< bool > IsByRef, bool IsGPU)
static Function * getFreshReductionFunc(Module &M)
static void raiseUserConstantDataAllocasToEntryBlock(IRBuilderBase &Builder, Function *Function)
static FunctionCallee getKmpcForDynamicNextForType(Type *Ty, Module &M, OpenMPIRBuilder &OMPBuilder)
Returns an LLVM function to call for updating the next loop using OpenMP dynamic scheduling depending...
static bool isConflictIP(IRBuilder<>::InsertPoint IP1, IRBuilder<>::InsertPoint IP2)
Return whether IP1 and IP2 are ambiguous, i.e.
static void checkReductionInfos(ArrayRef< OpenMPIRBuilder::ReductionInfo > ReductionInfos, bool IsGPU)
static Type * getOffloadingArrayType(Value *V)
static OMPScheduleType getOpenMPBaseScheduleType(llvm::omp::ScheduleKind ClauseKind, bool HasChunks, bool HasSimdModifier, bool HasDistScheduleChunks)
Determine which scheduling algorithm to use, determined from schedule clause arguments.
static OMPScheduleType computeOpenMPScheduleType(ScheduleKind ClauseKind, bool HasChunks, bool HasSimdModifier, bool HasMonotonicModifier, bool HasNonmonotonicModifier, bool HasOrderedClause, bool HasDistScheduleChunks)
Determine the schedule type using schedule and ordering clause arguments.
static FunctionCallee getKmpcForDynamicInitForType(Type *Ty, Module &M, OpenMPIRBuilder &OMPBuilder)
Returns an LLVM function to call for initializing loop bounds using OpenMP dynamic scheduling dependi...
static std::optional< omp::OMPTgtExecModeFlags > getTargetKernelExecMode(Function &Kernel)
Given a function, if it represents the entry point of a target kernel, this returns the execution mod...
static StructType * createTaskWithPrivatesTy(OpenMPIRBuilder &OMPIRBuilder, ArrayRef< Value * > OffloadingArraysToPrivatize)
static cl::opt< 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 Error emitTargetOutlinedFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, bool IsOffloadEntry, TargetRegionEntryInfo &EntryInfo, const OpenMPIRBuilder::TargetKernelDefaultAttrs &DefaultAttrs, Function *&OutlinedFn, Constant *&OutlinedFnID, SmallVectorImpl< Value * > &Inputs, OpenMPIRBuilder::TargetBodyGenCallbackTy &CBFunc, OpenMPIRBuilder::TargetGenArgAccessorsCallbackTy &ArgAccessorFuncCB, DebugLoc OutlinedFnLoc)
static 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 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 * getPointerBitCastOrAddrSpaceCast(Constant *C, Type *Ty)
Create a BitCast or AddrSpaceCast for a pointer type depending on the address space.
static LLVM_ABI Constant * getAddrSpaceCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static LLVM_ABI ConstantFP * getZero(Type *Ty, bool Negative=false)
This is the shared class of boolean and integer constants.
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static LLVM_ABI Constant * get(StructType *T, ArrayRef< Constant * > V)
This is an important base class in LLVM.
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
DILocalScope * getScope() const
Get the local scope for this variable.
DINodeArray getAnnotations() const
Subprogram description. Uses SubclassData1.
uint32_t getAlignInBits() const
StringRef getName() const
A parsed version of the target data layout string in and methods for querying it.
TypeSize getTypeStoreSize(Type *Ty) const
Returns the maximum number of bytes that may be overwritten by storing the specified type.
Record of a variable value-assignment, aka a non instruction representation of the dbg....
Analysis pass which computes a DominatorTree.
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.
user_iterator user_begin()
LLVM_ABI void moveBeforePreserving(InstListType::iterator MovePos)
Perform a moveBefore operation, while signalling that the caller intends to preserve the original ord...
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI void insertAfter(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately after the specified instruction.
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 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
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 createTarget(const LocationDescription &Loc, bool IsOffloadEntry, OpenMPIRBuilder::InsertPointTy AllocaIP, OpenMPIRBuilder::InsertPointTy CodeGenIP, ArrayRef< BasicBlock * > DeallocBlocks, TargetDataInfo &Info, TargetRegionEntryInfo &EntryInfo, const TargetKernelDefaultAttrs &DefaultAttrs, const TargetKernelRuntimeAttrs &RuntimeAttrs, Value *IfCond, SmallVectorImpl< Value * > &Inputs, GenMapInfoCallbackTy GenMapInfoCB, TargetBodyGenCallbackTy BodyGenCB, TargetGenArgAccessorsCallbackTy ArgAccessorFuncCB, CustomMapperCallbackTy CustomMapperCB, const DependenciesInfo &Dependencies={}, bool HasNowait=false, Value *DynCGroupMem=nullptr, omp::OMPDynGroupprivateFallbackType DynCGroupMemFallback=omp::OMPDynGroupprivateFallbackType::Abort, DebugLoc OutlinedFnLoc={})
Generator for 'omp target'.
LLVM_ABI InsertPointOrErrorTy createTargetData(const LocationDescription &Loc, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, ArrayRef< BasicBlock * > DeallocBlocks, Value *DeviceID, Value *IfCond, TargetDataInfo &Info, GenMapInfoCallbackTy GenMapInfoCB, CustomMapperCallbackTy CustomMapperCB, omp::RuntimeFunction *MapperFunc=nullptr, function_ref< InsertPointOrErrorTy(InsertPointTy CodeGenIP, BodyGenTy BodyGenType)> BodyGenCB=nullptr, function_ref< void(unsigned int, Value *)> DeviceAddrCB=nullptr, Value *SrcLocInfo=nullptr)
Generator for 'omp target data'.
LLVM_ABI CallInst * createRuntimeFunctionCall(FunctionCallee Callee, ArrayRef< Value * > Args, StringRef Name="")
LLVM_ABI InsertPointOrErrorTy emitKernelLaunch(const LocationDescription &Loc, Value *OutlinedFnID, EmitFallbackCallbackTy EmitTargetCallFallbackCB, TargetKernelArgs &Args, Value *DeviceID, Value *RTLoc, InsertPointTy AllocaIP)
Generate a target region entry call and host fallback call.
StringMap< GlobalVariable *, BumpPtrAllocator > InternalVars
An ordered map of auto-generated variables to their unique names.
LLVM_ABI InsertPointOrErrorTy createCancellationPoint(const LocationDescription &Loc, omp::Directive CanceledDirective)
Generator for 'omp cancellation point'.
LLVM_ABI CallInst * createOMPAlignedAlloc(const LocationDescription &Loc, Value *Align, Value *Size, Value *Allocator, std::string Name="")
Create a runtime call for kmpc_align_alloc.
LLVM_ABI FunctionCallee createDispatchInitFunction(unsigned IVSize, bool IVSigned)
Returns __kmpc_dispatch_init_* runtime function for the specified size IVSize and sign IVSigned.
LLVM_ABI InsertPointOrErrorTy createScan(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< llvm::Value * > ScanVars, ArrayRef< llvm::Type * > ScanVarsType, bool IsInclusive, ScanInfo *ScanRedInfo)
This directive split and directs the control flow to input phase blocks or scan phase blocks based on...
LLVM_ABI CallInst * createOMPFreeShared(const LocationDescription &Loc, Value *Addr, Value *Size, const Twine &Name=Twine(""))
Create a runtime call for kmpc_free_shared.
LLVM_ABI CallInst * createOMPInteropUse(const LocationDescription &Loc, Value *InteropVar, Value *Device, Value *NumDependences, Value *DependenceAddress, bool HaveNowaitClause)
Create a runtime call for __tgt_interop_use.
IRBuilder<>::InsertPoint InsertPointTy
Type used throughout for insertion points.
LLVM_ABI GlobalVariable * getOrCreateInternalVariable(Type *Ty, const StringRef &Name, std::optional< unsigned > AddressSpace={})
Gets (if variable with the given name already exist) or creates internal global variable with the spe...
LLVM_ABI GlobalVariable * createOffloadMapnames(SmallVectorImpl< llvm::Constant * > &Names, std::string VarName)
Create the global variable holding the offload names information.
LLVM_ABI InsertPointOrErrorTy createTask(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< BasicBlock * > DeallocBlocks, BodyGenCallbackTy BodyGenCB, bool Tied=true, Value *Final=nullptr, Value *IfCondition=nullptr, const DependenciesInfo &Dependencies={}, const AffinityData &Affinities={}, bool Mergeable=false, Value *EventHandle=nullptr, Value *Priority=nullptr, bool FreeAgent=false)
Generator for #omp taskloop
std::forward_list< ScanInfo > ScanInfos
Collection of owned ScanInfo objects that eventually need to be free'd.
static LLVM_ABI void writeTeamsForKernel(const Triple &T, Function &Kernel, int32_t LB, int32_t UB)
LLVM_ABI Value * calculateCanonicalLoopTripCount(const LocationDescription &Loc, Value *Start, Value *Stop, Value *Step, bool IsSigned, bool InclusiveStop, const Twine &Name="loop")
Calculate the trip count of a canonical loop.
LLVM_ABI InsertPointOrErrorTy createBarrier(const LocationDescription &Loc, omp::Directive Kind, bool ForceSimpleCall=false, bool CheckCancelFlag=true)
Emitter methods for OpenMP directives.
LLVM_ABI void setCorrectMemberOfFlag(omp::OpenMPOffloadMappingFlags &Flags, omp::OpenMPOffloadMappingFlags MemberOfFlag)
Given an initial flag set, this function modifies it to contain the passed in MemberOfFlag generated ...
LLVM_ABI Error emitOffloadingArraysAndArgs(InsertPointTy AllocaIP, InsertPointTy CodeGenIP, TargetDataInfo &Info, TargetDataRTArgs &RTArgs, MapInfosTy &CombinedInfo, CustomMapperCallbackTy CustomMapperCB, bool IsNonContiguous=false, bool ForEndCall=false, function_ref< void(unsigned int, Value *)> DeviceAddrCB=nullptr)
Allocates memory for and populates the arrays required for offloading (offload_{baseptrs|ptrs|mappers...
LLVM_ABI Constant * getOrCreateDefaultSrcLocStr(uint32_t &SrcLocStrSize)
Return the (LLVM-IR) string describing the default source location.
LLVM_ABI InsertPointOrErrorTy createCritical(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, StringRef CriticalName, Value *HintInst)
Generator for 'omp critical'.
LLVM_ABI void createError(const LocationDescription &Loc, bool IsFatal, Value *Message)
Generate a call to the runtime to emit the diagnostic of an OpenMP error directive with at(execution)...
LLVM_ABI void createOffloadEntry(Constant *ID, Constant *Addr, uint64_t Size, int32_t Flags, GlobalValue::LinkageTypes, StringRef Name="")
Creates offloading entry for the provided entry ID ID, address Addr, size Size, and flags Flags.
static LLVM_ABI unsigned getOpenMPDefaultSimdAlign(const Triple &TargetTriple, const StringMap< bool > &Features)
Get the default alignment value for given target.
LLVM_ABI unsigned getFlagMemberOffset()
Get the offset of the OMP_MAP_MEMBER_OF field.
LLVM_ABI InsertPointOrErrorTy 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).
bool isSystemZ() const
Tests whether the target is SystemZ.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
LLVM_ABI unsigned getIntegerBitWidth() const
LLVM_ABI Type * getStructElementType(unsigned N) const
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isPointerTy() const
True if this is an instance of PointerType.
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.
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.
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.
EnumSet< Property, Property_enumSize > Properties
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.
bool StrictBlocks
True if the kernel strictly requires the number of blocks and threads above to run.
ArrayRef< Value * > NumThreads
The number of threads.
TargetDataRTArgs RTArgs
Arguments passed to the runtime library.
Value * NumIterations
The number of iterations.
Value * DynCGroupMem
The size of the dynamic shared memory.
unsigned NumTargetItems
Number of arguments passed to the runtime library.
bool HasNoWait
True if the kernel has 'no wait' clause.
ArrayRef< Value * > NumTeams
The number of teams.
omp::OMPDynGroupprivateFallbackType DynCGroupMemFallback
The fallback mechanism for the shared memory.
Container to pass the default attributes with which a kernel must be launched, used to set kernel att...
omp::OMPTgtExecModeFlags ExecFlags
SmallVector< int32_t, 3 > MaxTeams
Container to pass LLVM IR runtime values or constants related to the number of teams and threads with...
Value * DeviceID
Device ID value used in the kernel launch.
SmallVector< Value *, 3 > MaxTeams
Value * LoopTripCount
Total number of iterations of the SPMD or Generic-SPMD kernel or null if it is a generic kernel.
SmallVector< Value *, 3 > TargetThreadLimit
SmallVector< Value *, 3 > TeamsThreadLimit
SmallVector< Value * > MaxThreads
'parallel' construct 'num_threads' clause value, if present and it is an SPMD kernel.
Data structure to contain the information needed to uniquely identify a target entry.
static LLVM_ABI void getTargetRegionEntryFnName(SmallVectorImpl< char > &Name, StringRef ParentName, unsigned DeviceID, unsigned FileID, unsigned Line, unsigned Count)
static constexpr const char * KernelNamePrefix
The prefix used for kernel names.
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),...