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());
8602 int32_t MaxThreadsVal = Attrs.MaxThreads.front();
8612 Attrs.MinThreads.front());
8617 if (MaxThreadsVal > 0 &&
8620 MaxThreadsVal = int32_t(
8621 std::min<int64_t>(int64_t(MaxThreadsVal) + 64,
8624 if (MaxThreadsVal > 0)
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());
8681 return KernelEnvironmentGV->
getType() == KernelEnvironmentPtr
8682 ? KernelEnvironmentGV
8684 KernelEnvironmentPtr);
8691 if (!KernelEnvironment)
8699 omp::RuntimeFunction::OMPRTL___kmpc_target_init);
8701 Value *KernelLaunchEnvironment =
8704 KernelLaunchEnvironment =
8705 KernelLaunchEnvironment->
getType() == KernelLaunchEnvParamTy
8706 ? KernelLaunchEnvironment
8707 :
Builder.CreateAddrSpaceCast(KernelLaunchEnvironment,
8708 KernelLaunchEnvParamTy);
8710 Fn, {KernelEnvironment, KernelLaunchEnvironment});
8722 auto *UI =
Builder.CreateUnreachable();
8728 Builder.SetInsertPoint(WorkerExitBB);
8732 Builder.SetInsertPoint(CheckBBTI);
8733 Builder.CreateCondBr(ExecUserCode, UI->getParent(), WorkerExitBB);
8735 CheckBBTI->eraseFromParent();
8736 UI->eraseFromParent();
8744 int32_t TeamsReductionDataSize) {
8749 omp::RuntimeFunction::OMPRTL___kmpc_target_deinit);
8753 if (!TeamsReductionDataSize)
8759 const std::string DebugPrefix =
"_debug__";
8761 KernelName = KernelName.
drop_back(DebugPrefix.length());
8762 auto *KernelEnvironmentGV =
8763 M.getNamedGlobal((KernelName +
"_kernel_environment").str());
8764 assert(KernelEnvironmentGV &&
"Expected kernel environment global\n");
8765 auto *KernelEnvironmentInitializer = KernelEnvironmentGV->getInitializer();
8767 KernelEnvironmentInitializer,
8768 ConstantInt::get(Int32, TeamsReductionDataSize), {0, 7});
8769 KernelEnvironmentGV->setInitializer(NewInitializer);
8774 if (
Kernel.hasFnAttribute(Name)) {
8775 int32_t OldLimit =
Kernel.getFnAttributeAsParsedInteger(Name);
8781std::pair<int32_t, int32_t>
8783 int32_t ThreadLimit =
8784 Kernel.getFnAttributeAsParsedInteger(
"omp_target_thread_limit");
8787 const auto &Attr =
Kernel.getFnAttribute(
"amdgpu-flat-work-group-size");
8788 if (!Attr.isValid() || !Attr.isStringAttribute())
8789 return {0, ThreadLimit};
8790 auto [LBStr, UBStr] = Attr.getValueAsString().split(
',');
8793 return {0, ThreadLimit};
8794 UB = ThreadLimit ? std::min(ThreadLimit, UB) : UB;
8802 return {0, ThreadLimit ? std::min(ThreadLimit, UB) : UB};
8804 return {0, ThreadLimit};
8810 Kernel.addFnAttr(
"omp_target_thread_limit", std::to_string(UB));
8813 Kernel.addFnAttr(
"amdgpu-flat-work-group-size",
8821std::pair<int32_t, int32_t>
8824 return {0,
Kernel.getFnAttributeAsParsedInteger(
"omp_target_num_teams")};
8828 int32_t LB, int32_t UB) {
8836 Kernel.addFnAttr(
"omp_target_num_teams", std::to_string(LB));
8839void OpenMPIRBuilder::setOutlinedTargetRegionFunctionAttributes(
8848 else if (
T.isNVPTX())
8850 else if (
T.isSPIRV())
8856 StringRef EntryFnIDName) {
8857 if (
Config.isTargetDevice()) {
8858 assert(OutlinedFn &&
"The outlined function must exist if embedded");
8862 return new GlobalVariable(
8867Constant *OpenMPIRBuilder::createTargetRegionEntryAddr(
Function *OutlinedFn,
8868 StringRef EntryFnName) {
8872 assert(!
M.getGlobalVariable(EntryFnName,
true) &&
8873 "Named kernel already exists?");
8874 return new GlobalVariable(
8887 if (
Config.isTargetDevice() || !
Config.openMPOffloadMandatory()) {
8891 OutlinedFn = *CBResult;
8893 OutlinedFn =
nullptr;
8899 if (!IsOffloadEntry)
8902 std::string EntryFnIDName =
8904 ? std::string(EntryFnName)
8908 EntryFnName, EntryFnIDName);
8916 setOutlinedTargetRegionFunctionAttributes(OutlinedFn);
8917 auto OutlinedFnID = createOutlinedFunctionID(OutlinedFn, EntryFnIDName);
8918 auto EntryAddr = createTargetRegionEntryAddr(OutlinedFn, EntryFnName);
8920 EntryInfo, EntryAddr, OutlinedFnID,
8922 return OutlinedFnID;
8940 bool IsStandAlone = !BodyGenCB;
8947 MapInfo = &GenMapInfoCB(
Builder.saveIP());
8949 AllocaIP,
Builder.saveIP(), *MapInfo, Info, CustomMapperCB,
8950 true, DeviceAddrCB))
8957 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
8967 SrcLocInfo, DeviceID,
8974 assert(MapperFunc &&
"MapperFunc missing for standalone target data");
8978 if (Info.HasNoWait) {
8988 if (Info.HasNoWait) {
8992 emitBlock(OffloadContBlock, CurFn,
true);
8998 bool RequiresOuterTargetTask = Info.HasNoWait;
8999 if (!RequiresOuterTargetTask)
9000 cantFail(TaskBodyCB(
nullptr,
nullptr,
9004 {}, RTArgs, Info.HasNoWait));
9007 omp::OMPRTL___tgt_target_data_begin_mapper);
9011 for (
auto DeviceMap : Info.DevicePtrInfoMap) {
9015 Builder.CreateStore(LI, DeviceMap.second.second);
9052 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
9061 Value *OffloadingArgs[] = {SrcLocInfo, DeviceID,
9084 return emitIfClause(IfCond, BeginThenGen, BeginElseGen, AllocaIP);
9085 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9100 return emitIfClause(IfCond, EndThenGen, EndElseGen, AllocaIP);
9101 return EndThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9104 return emitIfClause(IfCond, BeginThenGen, EndElseGen, AllocaIP);
9105 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9116 bool IsGPUDistribute) {
9117 assert((IVSize == 32 || IVSize == 64) &&
9118 "IV size is not compatible with the omp runtime");
9120 if (IsGPUDistribute)
9122 ? (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_4
9123 : omp::OMPRTL___kmpc_distribute_static_init_4u)
9124 : (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_8
9125 : omp::OMPRTL___kmpc_distribute_static_init_8u);
9127 Name = IVSize == 32 ? (IVSigned ? omp::OMPRTL___kmpc_for_static_init_4
9128 : omp::OMPRTL___kmpc_for_static_init_4u)
9129 : (IVSigned ? omp::OMPRTL___kmpc_for_static_init_8
9130 : omp::OMPRTL___kmpc_for_static_init_8u);
9137 assert((IVSize == 32 || IVSize == 64) &&
9138 "IV size is not compatible with the omp runtime");
9140 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_4
9141 : omp::OMPRTL___kmpc_dispatch_init_4u)
9142 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_8
9143 : omp::OMPRTL___kmpc_dispatch_init_8u);
9150 assert((IVSize == 32 || IVSize == 64) &&
9151 "IV size is not compatible with the omp runtime");
9153 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_4
9154 : omp::OMPRTL___kmpc_dispatch_next_4u)
9155 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_8
9156 : omp::OMPRTL___kmpc_dispatch_next_8u);
9163 assert((IVSize == 32 || IVSize == 64) &&
9164 "IV size is not compatible with the omp runtime");
9166 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_4
9167 : omp::OMPRTL___kmpc_dispatch_fini_4u)
9168 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_8
9169 : omp::OMPRTL___kmpc_dispatch_fini_8u);
9180 DenseMap<
Value *, std::tuple<Value *, unsigned>> &ValueReplacementMap) {
9188 auto GetUpdatedDIVariable = [&](
DILocalVariable *OldVar,
unsigned arg) {
9192 if (NewVar && (arg == NewVar->
getArg()))
9202 auto UpdateDebugRecord = [&](
auto *DR) {
9205 for (
auto Loc : DR->location_ops()) {
9206 auto Iter = ValueReplacementMap.find(
Loc);
9207 if (Iter != ValueReplacementMap.end()) {
9208 DR->replaceVariableLocationOp(
Loc, std::get<0>(Iter->second));
9209 ArgNo = std::get<1>(Iter->second) + 1;
9213 DR->setVariable(GetUpdatedDIVariable(OldVar, ArgNo));
9218 if (DVR->getNumVariableLocationOps() != 1u) {
9219 DVR->setKillLocation();
9222 Value *
Loc = DVR->getVariableLocationOp(0u);
9229 RequiredBB = &DVR->getFunction()->getEntryBlock();
9231 if (RequiredBB && RequiredBB != CurBB) {
9243 "Unexpected debug intrinsic");
9245 UpdateDebugRecord(&DVR);
9246 MoveDebugRecordToCorrectBlock(&DVR);
9249 for (
auto *DVR : DVRsToDelete)
9250 DVR->getMarker()->MarkedInstr->dropOneDbgRecord(DVR);
9254 Module *M = Func->getParent();
9257 DB.createQualifiedType(dwarf::DW_TAG_pointer_type,
nullptr);
9258 unsigned ArgNo = Func->arg_size();
9260 NewSP,
"dyn_ptr", ArgNo, NewSP->
getFile(), 0, VoidPtrTy,
9261 false, DINode::DIFlags::FlagArtificial);
9263 Argument *LastArg = Func->getArg(Func->arg_size() - 1);
9264 DB.insertDeclare(LastArg, Var, DB.createExpression(),
Loc,
9286 for (
auto &Arg : Inputs)
9287 ParameterTypes.
push_back(Arg->getType()->isPointerTy()
9291 for (
auto &Arg : Inputs)
9292 ParameterTypes.
push_back(Arg->getType());
9300 auto BB = Builder.GetInsertBlock();
9301 auto M = BB->getModule();
9312 if (TargetCpuAttr.isStringAttribute())
9313 Func->addFnAttr(TargetCpuAttr);
9315 auto TargetFeaturesAttr = ParentFn->
getFnAttribute(
"target-features");
9316 if (TargetFeaturesAttr.isStringAttribute())
9317 Func->addFnAttr(TargetFeaturesAttr);
9322 OMPBuilder.
emitUsed(
"llvm.compiler.used", {ExecMode});
9332 Builder.SetCurrentDebugLocation(OutlinedFnLoc);
9336 Builder.SetInsertPoint(EntryBB);
9347 BasicBlock *UserCodeEntryBB = Builder.GetInsertBlock();
9357 splitBB(Builder,
true,
"outlined.body");
9364 Builder.SetInsertPoint(ExitBB);
9372 Builder.SetCurrentDebugLocation(OutlinedFnLoc);
9379 Builder.CreateRetVoid();
9383 auto AllocaIP = Builder.saveIP();
9388 const auto &ArgRange =
make_range(Func->arg_begin(), Func->arg_end() - 1);
9420 if (Instr->getFunction() == Func)
9421 Instr->replaceUsesOfWith(
Input, InputCopy);
9427 for (
auto InArg :
zip(Inputs, ArgRange)) {
9429 Argument &Arg = std::get<1>(InArg);
9430 Value *InputCopy =
nullptr;
9433 Arg,
Input, InputCopy, AllocaIP, Builder.saveIP(),
9437 Builder.restoreIP(*AfterIP);
9438 ValueReplacementMap[
Input] = std::make_tuple(InputCopy, Arg.
getArgNo());
9458 DeferredReplacement.push_back(std::make_pair(
Input, InputCopy));
9465 ReplaceValue(
Input, InputCopy, Func);
9469 for (
auto Deferred : DeferredReplacement)
9470 ReplaceValue(std::get<0>(Deferred), std::get<1>(Deferred), Func);
9473 ValueReplacementMap);
9481 Value *TaskWithPrivates,
9482 Type *TaskWithPrivatesTy) {
9484 Type *TaskTy = OMPIRBuilder.Task;
9487 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 0);
9488 Value *Shareds = TaskT;
9498 if (TaskWithPrivatesTy != TaskTy)
9499 Shareds = Builder.CreateStructGEP(TaskTy, TaskT, 0);
9516 const size_t NumOffloadingArrays,
const int SharedArgsOperandNo) {
9521 assert((!NumOffloadingArrays || PrivatesTy) &&
9522 "PrivatesTy cannot be nullptr when there are offloadingArrays"
9555 Type *TaskPtrTy = OMPBuilder.TaskPtr;
9556 [[maybe_unused]]
Type *TaskTy = OMPBuilder.Task;
9562 ".omp_target_task_proxy_func", M);
9563 Value *ThreadId = ProxyFn->getArg(0);
9564 Value *TaskWithPrivates = ProxyFn->getArg(1);
9565 ThreadId->
setName(
"thread.id");
9566 TaskWithPrivates->
setName(
"task");
9568 bool HasShareds = SharedArgsOperandNo > 0;
9569 bool HasOffloadingArrays = NumOffloadingArrays > 0;
9573 Builder.SetInsertPoint(EntryBB);
9580 if (HasOffloadingArrays) {
9581 assert(TaskTy != TaskWithPrivatesTy &&
9582 "If there are offloading arrays to pass to the target"
9583 "TaskTy cannot be the same as TaskWithPrivatesTy");
9586 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 1);
9587 for (
unsigned int i = 0; i < NumOffloadingArrays; ++i)
9589 Builder.CreateStructGEP(PrivatesTy, Privates, i));
9593 auto *ArgStructAlloca =
9595 assert(ArgStructAlloca &&
9596 "Unable to find the alloca instruction corresponding to arguments "
9597 "for extracted function");
9599 std::optional<TypeSize> ArgAllocSize =
9601 assert(ArgStructType && ArgAllocSize &&
9602 "Unable to determine size of arguments for extracted function");
9603 uint64_t StructSize = ArgAllocSize->getFixedValue();
9606 Builder.CreateAlloca(ArgStructType,
nullptr,
"structArg");
9608 Value *SharedsSize = Builder.getInt64(StructSize);
9611 OMPBuilder, Builder, TaskWithPrivates, TaskWithPrivatesTy);
9613 Builder.CreateMemCpy(
9614 NewArgStructAlloca, NewArgStructAlloca->
getAlign(), LoadShared,
9616 KernelLaunchArgs.
push_back(NewArgStructAlloca);
9619 Builder.CreateRetVoid();
9625 return GEP->getSourceElementType();
9627 return Alloca->getAllocatedType();
9650 if (OffloadingArraysToPrivatize.
empty())
9651 return OMPIRBuilder.Task;
9654 for (
Value *V : OffloadingArraysToPrivatize) {
9655 assert(V->getType()->isPointerTy() &&
9656 "Expected pointer to array to privatize. Got a non-pointer value "
9659 assert(ArrayTy &&
"ArrayType cannot be nullptr");
9665 "struct.task_with_privates");
9680 EntryFnName, Inputs, CBFunc,
9681 ArgAccessorFuncCB, OutlinedFnLoc);
9685 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
9822 TargetTaskAllocaBB->
begin());
9825 auto OI = std::make_unique<OutlineInfo>();
9826 OI->EntryBB = TargetTaskAllocaBB;
9827 OI->OuterAllocBB = AllocaIP.
getBlock();
9832 Builder, AllocaIP, ToBeDeleted, TargetTaskAllocaIP,
"global.tid",
false));
9835 Builder.restoreIP(TargetTaskBodyIP);
9836 if (
Error Err = TaskBodyCB(DeviceID, RTLoc, TargetTaskAllocaIP))
9854 bool NeedsTargetTask = HasNoWait && DeviceID;
9855 if (NeedsTargetTask) {
9861 OffloadingArraysToPrivatize.
push_back(V);
9862 OI->ExcludeArgsFromAggregate.push_back(V);
9866 OI->PostOutlineCB = [
this, ToBeDeleted, Dependencies, NeedsTargetTask,
9867 DeviceID, OffloadingArraysToPrivatize](
9870 "there must be a single user for the outlined function");
9884 const unsigned int NumStaleCIArgs = StaleCI->
arg_size();
9885 bool HasShareds = NumStaleCIArgs > OffloadingArraysToPrivatize.
size() + 1;
9887 NumStaleCIArgs == (OffloadingArraysToPrivatize.
size() + 2)) &&
9888 "Wrong number of arguments for StaleCI when shareds are present");
9889 int SharedArgOperandNo =
9890 HasShareds ? OffloadingArraysToPrivatize.
size() + 1 : 0;
9896 if (!OffloadingArraysToPrivatize.
empty())
9901 *
this,
Builder, StaleCI, PrivatesTy, TaskWithPrivatesTy,
9902 OffloadingArraysToPrivatize.
size(), SharedArgOperandNo);
9904 LLVM_DEBUG(
dbgs() <<
"Proxy task entry function created: " << *ProxyFn
9907 Builder.SetInsertPoint(StaleCI);
9924 OMPRTL___kmpc_omp_target_task_alloc);
9936 M.getDataLayout().getTypeStoreSize(TaskWithPrivatesTy));
9943 auto *ArgStructAlloca =
9945 assert(ArgStructAlloca &&
9946 "Unable to find the alloca instruction corresponding to arguments "
9947 "for extracted function");
9948 std::optional<TypeSize> ArgAllocSize =
9951 "Unable to determine size of arguments for extracted function");
9952 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
9971 TaskSize, SharedsSize,
9974 if (NeedsTargetTask) {
9975 assert(DeviceID &&
"Expected non-empty device ID.");
9985 *
this,
Builder, TaskData, TaskWithPrivatesTy);
9989 if (!OffloadingArraysToPrivatize.
empty()) {
9991 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskData, 1);
9992 for (
unsigned int i = 0; i < OffloadingArraysToPrivatize.
size(); ++i) {
9993 Value *PtrToPrivatize = OffloadingArraysToPrivatize[i];
10000 "ElementType should match ArrayType");
10003 Value *Dst =
Builder.CreateStructGEP(PrivatesTy, Privates, i);
10006 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(ElementType)));
10010 Value *DepArray =
nullptr;
10011 Value *NumDeps =
nullptr;
10014 NumDeps = Dependencies.
NumDeps;
10015 }
else if (!Dependencies.
Deps.empty()) {
10017 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
10028 if (!NeedsTargetTask) {
10037 ConstantInt::get(
Builder.getInt32Ty(), 0),
10050 }
else if (DepArray) {
10058 {Ident, ThreadID, TaskData, NumDeps, DepArray,
10059 ConstantInt::get(
Builder.getInt32Ty(), 0),
10067 Builder.ClearInsertionPoint();
10070 I->eraseFromParent();
10075 << *(
Builder.GetInsertBlock()) <<
"\n");
10077 << *(
Builder.GetInsertBlock()->getParent()->getParent())
10089 CustomMapperCB, IsNonContiguous, DeviceAddrCB))
10112 Builder.restoreIP(IP);
10118 return Builder.saveIP();
10121 bool HasDependencies = !Dependencies.
empty();
10122 bool RequiresOuterTargetTask = HasNoWait || HasDependencies;
10139 if (OutlinedFnID && DeviceID)
10141 EmitTargetCallFallbackCB, KArgs,
10142 DeviceID, RTLoc, TargetTaskAllocaIP);
10150 return EmitTargetCallFallbackCB(OMPBuilder.
Builder.
saveIP());
10157 auto &&EmitTargetCallElse =
10164 if (RequiresOuterTargetTask) {
10171 Dependencies, EmptyRTArgs, HasNoWait);
10173 return EmitTargetCallFallbackCB(Builder.saveIP());
10176 Builder.restoreIP(AfterIP);
10180 auto &&EmitTargetCallThen =
10184 Info.HasNoWait = HasNoWait;
10189 AllocaIP, Builder.saveIP(), Info, RTArgs, MapInfo, CustomMapperCB,
10195 for (
auto [DefaultVal, RuntimeVal] :
10197 NumTeamsC.
push_back(RuntimeVal ? RuntimeVal
10198 : Builder.getInt32(DefaultVal));
10202 auto InitMaxThreadsClause = [&Builder](
Value *
Clause) {
10204 Clause = Builder.CreateIntCast(
Clause, Builder.getInt32Ty(),
10208 auto CombineMaxThreadsClauses = [&Builder](
Value *
Clause,
Value *&Result) {
10211 Result ? Builder.CreateSelect(Builder.CreateICmpULT(Result,
Clause),
10219 Value *MaxThreadsClause =
10221 ? InitMaxThreadsClause(RuntimeAttrs.
MaxThreads.front())
10224 for (
auto [TeamsVal, TargetVal] :
zip_equal(
10226 Value *TeamsThreadLimitClause = InitMaxThreadsClause(TeamsVal);
10227 Value *NumThreads = InitMaxThreadsClause(TargetVal);
10229 CombineMaxThreadsClauses(TeamsThreadLimitClause, NumThreads);
10230 CombineMaxThreadsClauses(MaxThreadsClause, NumThreads);
10232 NumThreadsC.
push_back(NumThreads ? NumThreads : Builder.getInt32(0));
10235 unsigned NumTargetItems = Info.NumberOfPtrs;
10236 Value *RTLoc = RTLocOverride;
10247 Builder.getInt64Ty(),
10249 : Builder.getInt64(0);
10253 DynCGroupMem = Builder.getInt32(0);
10256 NumTargetItems, RTArgs, TripCount, NumTeamsC, NumThreadsC, DynCGroupMem,
10257 HasNoWait,
false,
false,
10258 DynCGroupMemFallback);
10265 if (RequiresOuterTargetTask)
10267 RTLoc, AllocaIP, Dependencies,
10268 KArgs.
RTArgs, Info.HasNoWait);
10271 Builder, OutlinedFnID, EmitTargetCallFallbackCB, KArgs,
10272 RuntimeAttrs.
DeviceID, RTLoc, AllocaIP);
10275 Builder.restoreIP(AfterIP);
10282 if (!OutlinedFnID) {
10283 cantFail(EmitTargetCallElse(AllocaIP, Builder.saveIP(), DeallocBlocks));
10289 cantFail(EmitTargetCallThen(AllocaIP, Builder.saveIP(), DeallocBlocks));
10294 EmitTargetCallElse, AllocaIP));
10307 bool HasNowait,
Value *DynCGroupMem,
10309 Value *RTLocOverride) {
10314 Builder.restoreIP(CodeGenIP);
10322 *
this,
Builder, IsOffloadEntry, EntryInfo, DefaultAttrs, OutlinedFn,
10323 OutlinedFnID, Inputs, CBFunc, ArgAccessorFuncCB, OutlinedFnLoc))
10329 if (!
Config.isTargetDevice())
10331 DefaultAttrs, RuntimeAttrs, IfCond, OutlinedFn, OutlinedFnID,
10332 Inputs, GenMapInfoCB, CustomMapperCB, Dependencies,
10333 HasNowait, DynCGroupMem, DynCGroupMemFallback);
10347 return OS.
str().str();
10352 return OpenMPIRBuilder::getNameWithSeparators(Parts,
Config.firstSeparator(),
10358 auto &Elem = *
InternalVars.try_emplace(Name,
nullptr).first;
10360 assert(Elem.second->getValueType() == Ty &&
10361 "OMP internal variable has different type than requested");
10374 :
M.getTargetTriple().isAMDGPU()
10376 :
DL.getDefaultGlobalsAddressSpace();
10377 auto Linkage = this->
M.getTargetTriple().isWasm()
10385 const llvm::Align PtrAlign =
DL.getPointerABIAlignment(AddressSpaceVal);
10386 GV->setAlignment(std::max(TypeAlign, PtrAlign));
10390 return Elem.second;
10393Value *OpenMPIRBuilder::getOMPCriticalRegionLock(
StringRef CriticalName) {
10394 std::string Prefix =
Twine(
"gomp_critical_user_", CriticalName).
str();
10395 std::string Name = getNameWithSeparators({Prefix,
"var"},
".",
".");
10406 return SizePtrToInt;
10411 std::string VarName) {
10419 return MaptypesArrayGlobal;
10424 unsigned NumOperands,
10433 ArrI8PtrTy,
nullptr,
".offload_baseptrs");
10437 ArrI64Ty,
nullptr,
".offload_sizes");
10448 int64_t DeviceID,
unsigned NumOperands) {
10454 Value *ArgsBaseGEP =
10456 {Builder.getInt32(0), Builder.getInt32(0)});
10459 {Builder.getInt32(0), Builder.getInt32(0)});
10460 Value *ArgSizesGEP =
10462 {Builder.getInt32(0), Builder.getInt32(0)});
10466 Builder.getInt32(NumOperands),
10467 ArgsBaseGEP, ArgsGEP, ArgSizesGEP,
10468 MaptypesArg, MapnamesArg, NullPtr});
10475 assert((!ForEndCall || Info.separateBeginEndCalls()) &&
10476 "expected region end call to runtime only when end call is separate");
10478 auto VoidPtrTy = UnqualPtrTy;
10479 auto VoidPtrPtrTy = UnqualPtrTy;
10481 auto Int64PtrTy = UnqualPtrTy;
10483 if (!Info.NumberOfPtrs) {
10495 Info.RTArgs.BasePointersArray,
10498 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray,
10502 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
10506 ForEndCall && Info.RTArgs.MapTypesArrayEnd ? Info.RTArgs.MapTypesArrayEnd
10507 : Info.RTArgs.MapTypesArray,
10513 if (!Info.EmitDebug)
10517 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.MapNamesArray,
10522 if (!Info.HasMapper)
10526 Builder.CreatePointerCast(Info.RTArgs.MappersArray, VoidPtrPtrTy);
10547 "struct.descriptor_dim");
10549 enum { OffsetFD = 0, CountFD, StrideFD };
10553 for (
unsigned I = 0, L = 0, E = NonContigInfo.
Dims.
size();
I < E; ++
I) {
10556 if (NonContigInfo.
Dims[
I] == 1)
10561 Builder.CreateAlloca(ArrayTy,
nullptr,
"dims");
10562 Builder.restoreIP(CodeGenIP);
10563 for (
unsigned II = 0, EE = NonContigInfo.
Dims[
I];
II < EE; ++
II) {
10564 unsigned RevIdx = EE -
II - 1;
10568 Value *OffsetLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, OffsetFD);
10570 NonContigInfo.
Offsets[L][RevIdx], OffsetLVal,
10571 M.getDataLayout().getPrefTypeAlign(OffsetLVal->
getType()));
10573 Value *CountLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, CountFD);
10575 NonContigInfo.
Counts[L][RevIdx], CountLVal,
10576 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10578 Value *StrideLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, StrideFD);
10580 NonContigInfo.
Strides[L][RevIdx], StrideLVal,
10581 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10584 Builder.restoreIP(CodeGenIP);
10585 Value *DAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
10586 DimsAddr,
Builder.getPtrTy());
10589 Info.RTArgs.PointersArray, 0,
I);
10591 DAddr,
P,
M.getDataLayout().getPrefTypeAlign(
Builder.getPtrTy()));
10596void OpenMPIRBuilder::emitUDMapperArrayInitOrDel(
10600 StringRef Prefix = IsInit ?
".init" :
".del";
10606 Builder.CreateICmpSGT(
Size, Builder.getInt64(1),
"omp.arrayinit.isarray");
10607 Value *DeleteBit = Builder.CreateAnd(
10610 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10611 OpenMPOffloadMappingFlags::OMP_MAP_DELETE)));
10616 Value *BaseIsBegin = Builder.CreateICmpNE(
Base, Begin);
10617 Cond = Builder.CreateOr(IsArray, BaseIsBegin);
10618 DeleteCond = Builder.CreateIsNull(
10623 DeleteCond =
Builder.CreateIsNotNull(
10639 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10640 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10641 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10642 MapTypeArg =
Builder.CreateOr(
10645 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10646 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT)));
10650 Value *OffloadingArgs[] = {MapperHandle,
Base, Begin,
10651 ArraySize, MapTypeArg, MapName};
10662 bool PreserveMemberOfFlags,
bool PropagatePresentToPointee) {
10678 MapperFn->
addFnAttr(Attribute::NoInline);
10679 MapperFn->
addFnAttr(Attribute::NoUnwind);
10690 Builder.SetInsertPoint(EntryBB);
10705 Value *PtrBegin = BeginIn;
10711 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
10712 MapType, MapName, ElementSize, HeadBB,
10723 Builder.CreateICmpEQ(PtrBegin, PtrEnd,
"omp.arraymap.isempty");
10724 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
10730 Builder.CreatePHI(PtrBegin->
getType(), 2,
"omp.arraymap.ptrcurrent");
10731 PtrPHI->addIncoming(PtrBegin, HeadBB);
10736 return Info.takeError();
10740 Value *OffloadingArgs[] = {MapperHandle};
10744 Value *ShiftedPreviousSize =
10748 for (
unsigned I = 0;
I < Info->BasePointers.size(); ++
I) {
10749 Value *CurBaseArg = Info->BasePointers[
I];
10750 Value *CurBeginArg = Info->Pointers[
I];
10751 Value *CurSizeArg = Info->Sizes[
I];
10752 Value *CurNameArg = Info->Names.size()
10757 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10760 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10762 constexpr uint64_t MemberOfMask =
10763 static_cast<uint64_t
>(OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
10764 constexpr uint64_t AttachBit =
10765 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10766 OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
10824 Value *MemberMapType;
10825 if (PreserveMemberOfFlags || (RawType & AttachBit) ||
10826 Info->HasAttachPtr[
I]) {
10827 if (RawType & MemberOfMask)
10828 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
10830 MemberMapType = OriMapType;
10832 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
10850 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10851 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10852 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10862 Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
10868 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10869 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10870 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10876 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10877 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
10878 Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
10884 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10885 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10891 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10892 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10893 Builder.CreateCondBr(IsFrom, FromBB, EndBB);
10899 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10900 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
10909 CurMapType->
addIncoming(MemberMapType, ToElseBB);
10946 uint64_t ModifierBits =
10947 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10948 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
10949 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
10950 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
10951 if (PropagatePresentToPointee && Info->HasAttachPtr[
I])
10953 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10954 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
10955 Value *ImportedModifierBits =
10958 CurMapType, ImportedModifierBits,
"omp.maptype.with.modifiers");
10963 Value *FinalMapType =
10964 (RawType & AttachBit) ? CurMapType : CurMapTypeWithModifiers;
10966 Value *OffloadingArgs[] = {MapperHandle, CurBaseArg, CurBeginArg,
10967 CurSizeArg, FinalMapType, CurNameArg};
10969 auto ChildMapperFn = CustomMapperCB(
I);
10970 if (!ChildMapperFn)
10971 return ChildMapperFn.takeError();
10972 if (*ChildMapperFn) {
10988 "omp.arraymap.next");
10989 PtrPHI->addIncoming(PtrNext, LastBB);
10990 Value *IsDone =
Builder.CreateICmpEQ(PtrNext, PtrEnd,
"omp.arraymap.isdone");
10992 Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
10997 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
10998 MapType, MapName, ElementSize, DoneBB,
11011 bool IsNonContiguous,
11015 Info.clearArrayInfo();
11018 if (Info.NumberOfPtrs == 0)
11027 Info.RTArgs.BasePointersArray =
Builder.CreateAlloca(
11028 PointerArrayType,
nullptr,
".offload_baseptrs");
11030 Info.RTArgs.PointersArray =
Builder.CreateAlloca(
11031 PointerArrayType,
nullptr,
".offload_ptrs");
11033 PointerArrayType,
nullptr,
".offload_mappers");
11034 Info.RTArgs.MappersArray = MappersArray;
11041 ConstantInt::get(Int64Ty, 0));
11043 for (
unsigned I = 0, E = CombinedInfo.
Sizes.
size();
I < E; ++
I) {
11044 bool IsNonContigEntry =
11046 (
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11048 OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG) != 0);
11051 if (IsNonContigEntry) {
11053 "Index must be in-bounds for NON_CONTIG Dims array");
11055 assert(DimCount > 0 &&
"NON_CONTIG DimCount must be > 0");
11056 ConstSizes[
I] = ConstantInt::get(Int64Ty, DimCount);
11061 ConstSizes[
I] = CI;
11065 RuntimeSizes.
set(
I);
11068 if (RuntimeSizes.
all()) {
11070 Info.RTArgs.SizesArray =
Builder.CreateAlloca(
11071 SizeArrayType,
nullptr,
".offload_sizes");
11077 auto *SizesArrayGbl =
11082 if (!RuntimeSizes.
any()) {
11083 Info.RTArgs.SizesArray = SizesArrayGbl;
11085 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
11086 Align OffloadSizeAlign =
M.getDataLayout().getABIIntegerTypeAlignment(64);
11089 SizeArrayType,
nullptr,
".offload_sizes");
11093 Buffer,
M.getDataLayout().getPrefTypeAlign(Buffer->
getType()),
11094 SizesArrayGbl, OffloadSizeAlign,
11099 Info.RTArgs.SizesArray = Buffer;
11107 for (
auto mapFlag : CombinedInfo.
Types)
11109 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11113 Info.RTArgs.MapTypesArray = MapTypesArrayGbl;
11119 Info.RTArgs.MapNamesArray = MapNamesArrayGbl;
11120 Info.EmitDebug =
true;
11122 Info.RTArgs.MapNamesArray =
11124 Info.EmitDebug =
false;
11129 if (Info.separateBeginEndCalls()) {
11130 bool EndMapTypesDiffer =
false;
11131 for (uint64_t &
Type : Mapping) {
11132 if (
Type &
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11133 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT)) {
11134 Type &= ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
11135 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
11136 EndMapTypesDiffer =
true;
11139 if (EndMapTypesDiffer) {
11141 Info.RTArgs.MapTypesArrayEnd = MapTypesArrayGbl;
11146 for (
unsigned I = 0;
I < Info.NumberOfPtrs; ++
I) {
11149 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.BasePointersArray,
11151 Builder.CreateAlignedStore(BPVal, BP,
11152 M.getDataLayout().getPrefTypeAlign(PtrTy));
11154 if (Info.requiresDevicePointerInfo()) {
11156 CodeGenIP =
Builder.saveIP();
11158 Info.DevicePtrInfoMap[BPVal] = {BP,
Builder.CreateAlloca(PtrTy)};
11161 DeviceAddrCB(
I, Info.DevicePtrInfoMap[BPVal].second);
11163 Info.DevicePtrInfoMap[BPVal] = {BP, BP};
11165 DeviceAddrCB(
I, BP);
11171 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray, 0,
11174 Builder.CreateAlignedStore(PVal,
P,
11175 M.getDataLayout().getPrefTypeAlign(PtrTy));
11177 if (RuntimeSizes.
test(
I)) {
11179 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
11185 S,
M.getDataLayout().getPrefTypeAlign(PtrTy));
11188 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
11191 auto CustomMFunc = CustomMapperCB(
I);
11193 return CustomMFunc.takeError();
11195 MFunc =
Builder.CreatePointerCast(*CustomMFunc, PtrTy);
11198 PointerArrayType, MappersArray,
11201 MFunc, MAddr,
M.getDataLayout().getPrefTypeAlign(MAddr->
getType()));
11205 Info.NumberOfPtrs == 0)
11222 Builder.ClearInsertionPoint();
11253 auto CondConstant = CI->getSExtValue();
11255 return ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
11257 return ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
11267 Builder.CreateCondBr(
Cond, ThenBlock, ElseBlock);
11270 if (
Error Err = ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks))
11276 if (
Error Err = ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks))
11285bool OpenMPIRBuilder::checkAndEmitFlushAfterAtomic(
11289 "Unexpected Atomic Ordering.");
11291 bool Flush =
false;
11353 assert(
X.Var->getType()->isPointerTy() &&
11354 "OMP Atomic expects a pointer to target memory");
11355 Type *XElemTy =
X.ElemTy;
11358 "OMP atomic read expected a scalar type");
11360 Value *XRead =
nullptr;
11364 Builder.CreateLoad(XElemTy,
X.Var,
X.IsVolatile,
"omp.atomic.read");
11373 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11376 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11378 XRead = AtomicLoadRes.first;
11385 Builder.CreateLoad(IntCastTy,
X.Var,
X.IsVolatile,
"omp.atomic.load");
11388 XRead =
Builder.CreateBitCast(XLoad, XElemTy,
"atomic.flt.cast");
11390 XRead =
Builder.CreateIntToPtr(XLoad, XElemTy,
"atomic.ptr.cast");
11393 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Read);
11394 Builder.CreateStore(XRead, V.Var, V.IsVolatile);
11405 assert(
X.Var->getType()->isPointerTy() &&
11406 "OMP Atomic expects a pointer to target memory");
11407 Type *XElemTy =
X.ElemTy;
11410 "OMP atomic write expected a scalar type");
11418 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11421 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11429 Builder.CreateBitCast(Expr, IntCastTy,
"atomic.src.int.cast");
11434 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Write);
11441 AtomicUpdateCallbackTy &UpdateOp,
bool IsXBinopExpr,
11442 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11448 Type *XTy =
X.Var->getType();
11450 "OMP Atomic expects a pointer to target memory");
11451 Type *XElemTy =
X.ElemTy;
11454 "OMP atomic update expected a scalar or struct type");
11457 "OpenMP atomic does not support LT or GT operations");
11461 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, RMWOp, UpdateOp,
X.IsVolatile,
11462 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11464 return AtomicResult.takeError();
11465 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Update);
11470Value *OpenMPIRBuilder::emitRMWOpAsInstruction(
Value *Src1,
Value *Src2,
11474 return Builder.CreateAdd(Src1, Src2);
11476 return Builder.CreateSub(Src1, Src2);
11478 return Builder.CreateAnd(Src1, Src2);
11480 return Builder.CreateNeg(Builder.CreateAnd(Src1, Src2));
11482 return Builder.CreateOr(Src1, Src2);
11484 return Builder.CreateXor(Src1, Src2);
11523Expected<std::pair<Value *, Value *>> OpenMPIRBuilder::emitAtomicUpdate(
11526 AtomicUpdateCallbackTy &UpdateOp,
bool VolatileX,
bool IsXBinopExpr,
11527 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11529 bool emitRMWOp =
false;
11537 emitRMWOp = XElemTy;
11540 emitRMWOp = (IsXBinopExpr && XElemTy);
11547 std::pair<Value *, Value *> Res;
11549 AtomicRMWInst *RMWInst =
11550 Builder.CreateAtomicRMW(RMWOp,
X, Expr, llvm::MaybeAlign(), AO);
11551 if (IsIgnoreDenormalMode)
11552 RMWInst->
setMetadata(llvm::LLVMContext::MD_atomic_ignore_denormal_mode,
11554 if (
T.isAMDGPU()) {
11555 if (!IsFineGrainedMemory)
11556 RMWInst->
setMetadata(
"amdgpu.no.fine.grained.memory",
11558 if (!IsRemoteMemory)
11562 Res.first = RMWInst;
11567 Res.second = Res.first;
11569 Res.second = emitRMWOpAsInstruction(Res.first, Expr, RMWOp);
11572 Builder.CreateLoad(XElemTy,
X,
X->getName() +
".atomic.load");
11578 OpenMPIRBuilder::AtomicInfo atomicInfo(
11580 OldVal->
getAlign(),
true , AllocaIP,
X);
11581 auto AtomicLoadRes = atomicInfo.EmitAtomicLoadLibcall(AO);
11584 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11591 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11592 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11593 Builder.SetInsertPoint(ContBB);
11595 PHI->addIncoming(AtomicLoadRes.first, CurBB);
11597 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11600 Value *Upd = *CBResult;
11601 Builder.CreateStore(Upd, NewAtomicAddr);
11604 auto Result = atomicInfo.EmitAtomicCompareExchangeLibcall(
11605 AtomicLoadRes.second, NewAtomicAddr, AO, Failure);
11606 LoadInst *PHILoad =
Builder.CreateLoad(XElemTy,
Result.first);
11607 PHI->addIncoming(PHILoad,
Builder.GetInsertBlock());
11610 Res.first = OldExprVal;
11613 if (UnreachableInst *ExitTI =
11616 Builder.SetInsertPoint(ExitBB);
11618 Builder.SetInsertPoint(ExitTI);
11621 IntegerType *IntCastTy =
11624 Builder.CreateLoad(IntCastTy,
X,
X->getName() +
".atomic.load");
11634 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11641 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11642 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11643 Builder.SetInsertPoint(ContBB);
11645 PHI->addIncoming(OldVal, CurBB);
11650 OldExprVal =
Builder.CreateBitCast(
PHI, XElemTy,
11651 X->getName() +
".atomic.fltCast");
11653 OldExprVal =
Builder.CreateIntToPtr(
PHI, XElemTy,
11654 X->getName() +
".atomic.ptrCast");
11658 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11661 Value *Upd = *CBResult;
11662 Builder.CreateStore(Upd, NewAtomicAddr);
11663 LoadInst *DesiredVal =
Builder.CreateLoad(IntCastTy, NewAtomicAddr);
11667 X,
PHI, DesiredVal, llvm::MaybeAlign(), AO, Failure);
11668 Result->setVolatile(VolatileX);
11669 Value *PreviousVal =
Builder.CreateExtractValue(Result, 0);
11670 Value *SuccessFailureVal =
Builder.CreateExtractValue(Result, 1);
11671 PHI->addIncoming(PreviousVal,
Builder.GetInsertBlock());
11672 Builder.CreateCondBr(SuccessFailureVal, ExitBB, ContBB);
11674 Res.first = OldExprVal;
11678 if (UnreachableInst *ExitTI =
11681 Builder.SetInsertPoint(ExitBB);
11683 Builder.SetInsertPoint(ExitTI);
11694 bool UpdateExpr,
bool IsPostfixUpdate,
bool IsXBinopExpr,
11695 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11700 Type *XTy =
X.Var->getType();
11702 "OMP Atomic expects a pointer to target memory");
11703 Type *XElemTy =
X.ElemTy;
11706 "OMP atomic capture expected a scalar or struct type");
11708 "OpenMP atomic does not support LT or GT operations");
11715 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, AtomicOp, UpdateOp,
X.IsVolatile,
11716 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11719 Value *CapturedVal =
11720 (IsPostfixUpdate ? AtomicResult->first : AtomicResult->second);
11721 Builder.CreateStore(CapturedVal, V.Var, V.IsVolatile);
11723 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Capture);
11731 bool IsFailOnly,
bool IsWeak) {
11735 IsPostfixUpdate, IsFailOnly, Failure, IsWeak);
11747 assert(
X.Var->getType()->isPointerTy() &&
11748 "OMP atomic expects a pointer to target memory");
11751 assert(V.Var->getType()->isPointerTy() &&
"v.var must be of pointer type");
11752 assert(V.ElemTy ==
X.ElemTy &&
"x and v must be of same type");
11755 bool IsInteger = E->getType()->isIntegerTy();
11757 if (
Op == OMPAtomicCompareOp::EQ) {
11760 Value *OldValue =
nullptr;
11761 Value *SuccessOrFail =
nullptr;
11799 X.Var->getName() +
".atomic.load");
11805 Value *EIsNaN =
Builder.CreateFCmpUNO(E, E,
"atomic.e.isnan");
11806 Value *XIsNaN =
Builder.CreateFCmpUNO(XFP, XFP,
"atomic.x.isnan");
11807 Value *EitherNaN =
Builder.CreateOr(EIsNaN, XIsNaN,
"atomic.either.nan");
11812 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11816 M.getContext(),
X.Var->getName() +
".atomic.nan",
F, ExitBB);
11818 M.getContext(),
X.Var->getName() +
".atomic.notnan",
F, ExitBB);
11820 M.getContext(),
X.Var->getName() +
".atomic.zero",
F, ExitBB);
11822 M.getContext(),
X.Var->getName() +
".atomic.normal",
F, ExitBB);
11826 Builder.SetInsertPoint(CurBB);
11827 Builder.CreateCondBr(EitherNaN, NaNBB, NotNaNBB);
11830 Builder.SetInsertPoint(NaNBB);
11834 Builder.SetInsertPoint(NotNaNBB);
11837 X.Var->getName() +
".atomic.xiszero");
11839 "atomic.e.iszero");
11840 Value *BothZero =
Builder.CreateAnd(XIsZero, EIsZero,
"atomic.both.zero");
11841 Builder.CreateCondBr(BothZero, ZeroBB, NormalBB);
11844 Builder.SetInsertPoint(ZeroBB);
11846 X.Var, XCurr, DBCast,
MaybeAlign(), AO, Failure);
11848 Value *OldZero =
Builder.CreateExtractValue(ResZero, 0);
11849 Value *OkZero =
Builder.CreateExtractValue(ResZero, 1);
11853 Builder.SetInsertPoint(NormalBB);
11855 X.Var, EBCast, DBCast,
MaybeAlign(), AO, Failure);
11857 Value *OldNormal =
Builder.CreateExtractValue(ResNormal, 0);
11858 Value *OkNormal =
Builder.CreateExtractValue(ResNormal, 1);
11864 Builder.CreatePHI(IntCastTy, 3,
X.Var->getName() +
".atomic.old");
11869 X.Var->getName() +
".atomic.ok");
11876 Builder.SetInsertPoint(ExitBB);
11881 OldValue =
Builder.CreateBitCast(OldIntPHI,
X.ElemTy,
11882 X.Var->getName() +
".atomic.old.fp");
11883 SuccessOrFail = SuccessPHI;
11891 Result =
Builder.CreateAtomicCmpXchg(
X.Var, EBCast, DBCast,
11897 Result->setWeak(IsWeak);
11900 OldValue =
Builder.CreateExtractValue(Result, 0);
11902 OldValue =
Builder.CreateBitCast(OldValue,
X.ElemTy);
11904 "OldValue and V must be of same type");
11905 if (IsPostfixUpdate) {
11906 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
11908 SuccessOrFail =
Builder.CreateExtractValue(Result, 1);
11912 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11914 CurBBTI,
X.Var->getName() +
".atomic.exit");
11920 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
11922 Builder.SetInsertPoint(ContBB);
11923 Builder.CreateStore(OldValue, V.Var);
11929 Builder.SetInsertPoint(ExitBB);
11931 Builder.SetInsertPoint(ExitTI);
11934 Value *CapturedValue =
11935 Builder.CreateSelect(SuccessOrFail, E, OldValue);
11936 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
11942 assert(R.Var->getType()->isPointerTy() &&
11943 "r.var must be of pointer type");
11944 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
11946 Value *SuccessFailureVal =
11947 Builder.CreateExtractValue(Result, 1);
11948 Value *ResultCast =
11949 R.IsSigned ?
Builder.CreateSExt(SuccessFailureVal, R.ElemTy)
11950 :
Builder.CreateZExt(SuccessFailureVal, R.ElemTy);
11951 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
11960 "OldValue and V must be of same type");
11961 if (IsPostfixUpdate) {
11962 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
11967 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11969 CurBBTI,
X.Var->getName() +
".atomic.exit");
11975 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
11977 Builder.SetInsertPoint(ContBB);
11978 Builder.CreateStore(OldValue, V.Var);
11984 Builder.SetInsertPoint(ExitBB);
11986 Builder.SetInsertPoint(ExitTI);
11989 Value *CapturedValue =
11990 Builder.CreateSelect(SuccessOrFail, E, OldValue);
11991 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
11997 assert(R.Var->getType()->isPointerTy() &&
11998 "r.var must be of pointer type");
11999 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
12001 Value *ResultCast = R.IsSigned
12002 ?
Builder.CreateSExt(SuccessOrFail, R.ElemTy)
12003 :
Builder.CreateZExt(SuccessOrFail, R.ElemTy);
12004 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
12008 assert((
Op == OMPAtomicCompareOp::MAX ||
Op == OMPAtomicCompareOp::MIN) &&
12009 "Op should be either max or min at this point");
12010 assert(!IsFailOnly &&
"IsFailOnly is only valid when the comparison is ==");
12021 if (IsXBinopExpr) {
12050 Value *CapturedValue =
nullptr;
12051 if (IsPostfixUpdate) {
12052 CapturedValue = OldValue;
12077 Value *NonAtomicCmp =
Builder.CreateCmp(Pred, OldValue, E);
12078 CapturedValue =
Builder.CreateSelect(NonAtomicCmp, E, OldValue);
12080 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
12084 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Compare);
12104 if (&OuterAllocaBB ==
Builder.GetInsertBlock()) {
12131 bool SubClausesPresent =
12132 (NumTeamsLower || NumTeamsUpper || ThreadLimit || IfExpr);
12134 if (!
Config.isTargetDevice() && SubClausesPresent) {
12135 assert((NumTeamsLower ==
nullptr || NumTeamsUpper !=
nullptr) &&
12136 "if lowerbound is non-null, then upperbound must also be non-null "
12137 "for bounds on num_teams");
12139 if (NumTeamsUpper ==
nullptr)
12140 NumTeamsUpper =
Builder.getInt32(0);
12142 if (NumTeamsLower ==
nullptr)
12143 NumTeamsLower = NumTeamsUpper;
12147 "argument to if clause must be an integer value");
12151 IfExpr =
Builder.CreateICmpNE(IfExpr,
12152 ConstantInt::get(IfExpr->
getType(), 0));
12153 NumTeamsUpper =
Builder.CreateSelect(
12154 IfExpr, NumTeamsUpper,
Builder.getInt32(1),
"numTeamsUpper");
12157 NumTeamsLower =
Builder.CreateSelect(
12158 IfExpr, NumTeamsLower,
Builder.getInt32(1),
"numTeamsLower");
12161 if (ThreadLimit ==
nullptr)
12162 ThreadLimit =
Builder.getInt32(0);
12166 Value *NumTeamsLowerInt32 =
12168 Value *NumTeamsUpperInt32 =
12170 Value *ThreadLimitInt32 =
12177 {Ident, ThreadNum, NumTeamsLowerInt32, NumTeamsUpperInt32,
12178 ThreadLimitInt32});
12183 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
12186 auto OI = std::make_unique<OutlineInfo>();
12187 OI->EntryBB = AllocaBB;
12188 OI->ExitBB = ExitBB;
12189 OI->OuterAllocBB = &OuterAllocaBB;
12195 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"gid",
true));
12197 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"tid",
true));
12199 auto HostPostOutlineCB = [
this, Ident,
12200 ToBeDeleted](
Function &OutlinedFn)
mutable {
12205 "there must be a single user for the outlined function");
12210 "Outlined function must have two or three arguments only");
12212 bool HasShared = OutlinedFn.
arg_size() == 3;
12220 assert(StaleCI &&
"Error while outlining - no CallInst user found for the "
12221 "outlined function.");
12222 Builder.SetInsertPoint(StaleCI);
12229 omp::RuntimeFunction::OMPRTL___kmpc_fork_teams),
12232 Builder.ClearInsertionPoint();
12234 I->eraseFromParent();
12237 if (!
Config.isTargetDevice())
12238 OI->PostOutlineCB = HostPostOutlineCB;
12242 Builder.SetInsertPoint(ExitBB);
12255 if (OuterAllocaBB ==
Builder.GetInsertBlock()) {
12270 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
12275 if (
Config.isTargetDevice()) {
12276 auto OI = std::make_unique<OutlineInfo>();
12277 OI->OuterAllocBB = OuterAllocIP.
getBlock();
12278 OI->EntryBB = AllocaBB;
12279 OI->ExitBB = ExitBB;
12280 OI->OuterDeallocBBs.reserve(OuterDeallocBlocks.
size());
12281 copy(OuterDeallocBlocks, OI->OuterDeallocBBs.
end());
12285 Builder.SetInsertPoint(ExitBB);
12292 std::string VarName) {
12301 return MapNamesArrayGlobal;
12306void OpenMPIRBuilder::initializeTypes(
Module &M) {
12310 unsigned ProgramAS = M.getDataLayout().getProgramAddressSpace();
12311#define OMP_TYPE(VarName, InitValue) VarName = InitValue;
12312#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \
12313 VarName##Ty = ArrayType::get(ElemTy, ArraySize); \
12314 VarName##PtrTy = PointerType::get(Ctx, DefaultTargetAS);
12315#define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) \
12316 VarName = FunctionType::get(ReturnType, {__VA_ARGS__}, IsVarArg); \
12317 VarName##Ptr = PointerType::get(Ctx, ProgramAS);
12318#define OMP_STRUCT_TYPE(VarName, StructName, Packed, ...) \
12319 T = StructType::getTypeByName(Ctx, StructName); \
12321 T = StructType::create(Ctx, {__VA_ARGS__}, StructName, Packed); \
12323 VarName##Ptr = PointerType::get(Ctx, DefaultTargetAS);
12324#include "llvm/Frontend/OpenMP/OMPKinds.def"
12335 while (!Worklist.
empty()) {
12339 if (
BlockSet.insert(SuccBB).second)
12344std::unique_ptr<CodeExtractor>
12346 bool ArgsInZeroAddressSpace,
12348 return std::make_unique<CodeExtractor>(
12358 Suffix.
str(), ArgsInZeroAddressSpace);
12361std::unique_ptr<CodeExtractor> DeviceSharedMemOutlineInfo::createCodeExtractor(
12363 return std::make_unique<DeviceSharedMemCodeExtractor>(
12364 OMPBuilder, Blocks,
nullptr,
12372 OuterDeallocBBs.empty()
12375 Suffix.
str(), ArgsInZeroAddressSpace);
12379 uint64_t
Size, int32_t Flags,
12385 Name.empty() ? Addr->
getName() : Name,
Size, Flags, 0);
12397 Fn->
addFnAttr(
"uniform-work-group-size");
12398 Fn->
addFnAttr(Attribute::MustProgress);
12416 auto &&GetMDInt = [
this](
unsigned V) {
12423 NamedMDNode *MD =
M.getOrInsertNamedMetadata(
"omp_offload.info");
12424 auto &&TargetRegionMetadataEmitter =
12425 [&
C, MD, &OrderedEntries, &GetMDInt, &GetMDString](
12440 GetMDInt(E.getKind()), GetMDInt(EntryInfo.DeviceID),
12441 GetMDInt(EntryInfo.FileID), GetMDString(EntryInfo.ParentName),
12442 GetMDInt(EntryInfo.Line), GetMDInt(EntryInfo.Count),
12443 GetMDInt(E.getOrder())};
12446 OrderedEntries[E.getOrder()] = std::make_pair(&E, EntryInfo);
12455 auto &&DeviceGlobalVarMetadataEmitter =
12456 [&
C, &OrderedEntries, &GetMDInt, &GetMDString, MD](
12466 Metadata *
Ops[] = {GetMDInt(E.getKind()), GetMDString(MangledName),
12467 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
12471 OrderedEntries[E.getOrder()] = std::make_pair(&E, varInfo);
12478 DeviceGlobalVarMetadataEmitter);
12480 for (
const auto &E : OrderedEntries) {
12481 assert(E.first &&
"All ordered entries must exist!");
12482 if (
const auto *CE =
12485 if (!CE->getID() || !CE->getAddress()) {
12489 if (!
M.getNamedValue(FnName))
12497 }
else if (
const auto *CE =
dyn_cast<
12506 if (
Config.isTargetDevice() &&
Config.hasRequiresUnifiedSharedMemory())
12508 if (!CE->getAddress()) {
12513 if (CE->getVarSize() == 0)
12517 assert(((
Config.isTargetDevice() && !CE->getAddress()) ||
12518 (!
Config.isTargetDevice() && CE->getAddress())) &&
12519 "Declaret target link address is set.");
12520 if (
Config.isTargetDevice())
12522 if (!CE->getAddress()) {
12529 if (!CE->getAddress()) {
12542 if ((
GV->hasLocalLinkage() ||
GV->hasHiddenVisibility()) &&
12546 OMPTargetGlobalVarEntryIndirectVTable))
12555 Flags, CE->getLinkage(), CE->getVarName());
12558 Flags, CE->getLinkage());
12569 if (
Config.hasRequiresFlags() && !
Config.isTargetDevice())
12575 Config.getRequiresFlags());
12585 OS <<
"_" <<
Count;
12590 unsigned NewCount = getTargetRegionEntryInfoCount(EntryInfo);
12593 EntryInfo.
Line, NewCount);
12601 auto FileIDInfo = CallBack();
12602 uint64_t FileID = 0;
12604 ID =
Status->getUniqueID();
12605 FileID =
Status->getUniqueID().getFile();
12609 FileID =
hash_value(std::get<0>(FileIDInfo));
12613 std::get<1>(FileIDInfo));
12618 for (uint64_t Remain =
12619 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12621 !(Remain & 1); Remain = Remain >> 1)
12639 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12641 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12648 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12654 Flags &=
~omp::OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
12655 Flags |= MemberOfFlag;
12661 bool IsDeclaration,
bool IsExternallyVisible,
12663 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12664 std::vector<Triple> TargetTriple,
Type *LlvmPtrTy,
12665 std::function<
Constant *()> GlobalInitializer,
12676 Config.hasRequiresUnifiedSharedMemory())) {
12681 if (!IsExternallyVisible)
12683 OS <<
"_decl_tgt_ref_ptr";
12686 Value *Ptr =
M.getNamedValue(PtrName);
12695 if (!
Config.isTargetDevice()) {
12696 if (GlobalInitializer)
12697 GV->setInitializer(GlobalInitializer());
12703 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12704 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12705 GlobalInitializer, VariableLinkage, LlvmPtrTy,
cast<Constant>(Ptr));
12717 bool IsDeclaration,
bool IsExternallyVisible,
12719 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12720 std::vector<Triple> TargetTriple,
12721 std::function<
Constant *()> GlobalInitializer,
12725 (TargetTriple.empty() && !
Config.isTargetDevice()))
12736 !
Config.hasRequiresUnifiedSharedMemory()) {
12738 VarName = MangledName;
12741 if (!IsDeclaration)
12743 M.getDataLayout().getTypeSizeInBits(LlvmVal->
getValueType()), 8);
12746 Linkage = (VariableLinkage) ? VariableLinkage() : LlvmVal->
getLinkage();
12750 if (
Config.isTargetDevice() &&
12759 if (!
M.getNamedValue(RefName)) {
12763 GvAddrRef->setConstant(
true);
12765 GvAddrRef->setInitializer(Addr);
12766 GeneratedRefs.push_back(GvAddrRef);
12775 if (
Config.isTargetDevice()) {
12776 VarName = (Addr) ? Addr->
getName() :
"";
12780 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12781 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12782 LlvmPtrTy, GlobalInitializer, VariableLinkage);
12783 VarName = (Addr) ? Addr->
getName() :
"";
12785 VarSize =
M.getDataLayout().getPointerSize();
12804 auto &&GetMDInt = [MN](
unsigned Idx) {
12809 auto &&GetMDString = [MN](
unsigned Idx) {
12811 return V->getString();
12814 switch (GetMDInt(0)) {
12818 case OffloadEntriesInfoManager::OffloadEntryInfo::
12819 OffloadingEntryInfoTargetRegion: {
12829 case OffloadEntriesInfoManager::OffloadEntryInfo::
12830 OffloadingEntryInfoDeviceGlobalVar:
12843 if (HostFilePath.
empty())
12847 if (std::error_code Err = Buf.getError()) {
12849 "OpenMPIRBuilder: " +
12857 if (std::error_code Err =
M.getError()) {
12859 (
"error parsing host file inside of OpenMPIRBuilder: " + Err.message())
12873 "expected a valid insertion block for creating an iterator loop");
12883 Builder.getCurrentDebugLocation(),
"omp.it.cont");
12895 T->eraseFromParent();
12904 if (!BodyBr || BodyBr->getSuccessor() != CLI->
getLatch()) {
12906 "iterator bodygen must terminate the canonical body with an "
12907 "unconditional branch to the loop latch",
12931 for (
const auto &
ParamAttr : ParamAttrs) {
12974 return std::string(Out.str());
12982 unsigned VecRegSize;
12984 ISADataTy ISAData[] = {
13003 for (
char Mask :
Masked) {
13004 for (
const ISADataTy &
Data : ISAData) {
13007 Out <<
"_ZGV" <<
Data.ISA << Mask;
13009 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
13023template <
typename T>
13026 StringRef MangledName,
bool OutputBecomesInput,
13030 Out << Prefix << ISA << LMask << VLEN;
13031 if (OutputBecomesInput)
13033 Out << ParSeq <<
'_' << MangledName;
13042 bool OutputBecomesInput,
13047 OutputBecomesInput, Fn);
13049 OutputBecomesInput, Fn);
13053 OutputBecomesInput, Fn);
13055 OutputBecomesInput, Fn);
13059 OutputBecomesInput, Fn);
13061 OutputBecomesInput, Fn);
13066 OutputBecomesInput, Fn);
13077 char ISA,
unsigned NarrowestDataSize,
bool OutputBecomesInput) {
13078 assert((ISA ==
'n' || ISA ==
's') &&
"Expected ISA either 's' or 'n'.");
13090 OutputBecomesInput, Fn);
13097 OutputBecomesInput, Fn);
13099 OutputBecomesInput, Fn);
13103 OutputBecomesInput, Fn);
13107 OutputBecomesInput, Fn);
13116 OutputBecomesInput, Fn);
13123 MangledName, OutputBecomesInput, Fn);
13125 MangledName, OutputBecomesInput, Fn);
13129 MangledName, OutputBecomesInput, Fn);
13133 MangledName, OutputBecomesInput, Fn);
13143 return OffloadEntriesTargetRegion.empty() &&
13144 OffloadEntriesDeviceGlobalVar.empty();
13147unsigned OffloadEntriesInfoManager::getTargetRegionEntryInfoCount(
13149 auto It = OffloadEntriesTargetRegionCount.find(
13150 getTargetRegionEntryCountKey(EntryInfo));
13151 if (It == OffloadEntriesTargetRegionCount.end())
13156void OffloadEntriesInfoManager::incrementTargetRegionEntryInfoCount(
13158 OffloadEntriesTargetRegionCount[getTargetRegionEntryCountKey(EntryInfo)] =
13159 EntryInfo.
Count + 1;
13165 OffloadEntriesTargetRegion[EntryInfo] =
13168 ++OffloadingEntriesNum;
13174 assert(EntryInfo.
Count == 0 &&
"expected default EntryInfo");
13177 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
13181 if (OMPBuilder->Config.isTargetDevice()) {
13186 auto &Entry = OffloadEntriesTargetRegion[EntryInfo];
13187 Entry.setAddress(Addr);
13189 Entry.setFlags(Flags);
13195 "Target region entry already registered!");
13197 OffloadEntriesTargetRegion[EntryInfo] = Entry;
13198 ++OffloadingEntriesNum;
13200 incrementTargetRegionEntryInfoCount(EntryInfo);
13207 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
13209 auto It = OffloadEntriesTargetRegion.find(EntryInfo);
13210 if (It == OffloadEntriesTargetRegion.end()) {
13214 if (!IgnoreAddressId && (It->second.getAddress() || It->second.getID()))
13222 for (
const auto &It : OffloadEntriesTargetRegion) {
13223 Action(It.first, It.second);
13229 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
13230 ++OffloadingEntriesNum;
13236 if (OMPBuilder->Config.isTargetDevice()) {
13240 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
13242 if (Entry.getVarSize() == 0) {
13243 Entry.setVarSize(VarSize);
13244 Entry.setLinkage(Linkage);
13248 Entry.setVarSize(VarSize);
13249 Entry.setLinkage(Linkage);
13250 Entry.setAddress(Addr);
13253 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
13254 assert(Entry.isValid() && Entry.getFlags() == Flags &&
13255 "Entry not initialized!");
13256 if (Entry.getVarSize() == 0) {
13257 Entry.setVarSize(VarSize);
13258 Entry.setLinkage(Linkage);
13265 OffloadEntriesDeviceGlobalVar.try_emplace(VarName, OffloadingEntriesNum,
13266 Addr, VarSize, Flags, Linkage,
13269 OffloadEntriesDeviceGlobalVar.try_emplace(
13270 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage,
"");
13271 ++OffloadingEntriesNum;
13278 for (
const auto &E : OffloadEntriesDeviceGlobalVar)
13279 Action(E.getKey(), E.getValue());
13286void CanonicalLoopInfo::collectControlBlocks(
13293 BBs.
append({getPreheader(), Header,
Cond, Latch, Exit, getAfter()});
13305void CanonicalLoopInfo::setTripCount(
Value *TripCount) {
13317void CanonicalLoopInfo::mapIndVar(
13327 for (
Use &U : OldIV->
uses()) {
13331 if (
User->getParent() == getCond())
13333 if (
User->getParent() == getLatch())
13339 Value *NewIV = Updater(OldIV);
13342 for (Use *U : ReplacableUses)
13363 "Preheader must terminate with unconditional branch");
13365 "Preheader must jump to header");
13369 "Header must terminate with unconditional branch");
13370 assert(Header->getSingleSuccessor() == Cond &&
13371 "Header must jump to exiting block");
13374 assert(Cond->getSinglePredecessor() == Header &&
13375 "Exiting block only reachable from header");
13378 "Exiting block must terminate with conditional branch");
13380 "Exiting block's first successor jump to the body");
13382 "Exiting block's second successor must exit the loop");
13386 "Body only reachable from exiting block");
13391 "Latch must terminate with unconditional branch");
13392 assert(Latch->getSingleSuccessor() == Header &&
"Latch must jump to header");
13395 assert(Latch->getSinglePredecessor() !=
nullptr);
13400 "Exit block must terminate with unconditional branch");
13401 assert(Exit->getSingleSuccessor() == After &&
13402 "Exit block must jump to after block");
13406 "After block only reachable from exit block");
13410 assert(IndVar &&
"Canonical induction variable not found?");
13412 "Induction variable must be an integer");
13414 "Induction variable must be a PHI in the loop header");
13420 auto *NextIndVar =
cast<PHINode>(IndVar)->getIncomingValue(1);
13428 assert(TripCount &&
"Loop trip count not found?");
13430 "Trip count and induction variable must have the same type");
13434 "Exit condition must be a signed less-than comparison");
13436 "Exit condition must compare the induction variable");
13438 "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 void emitTargetCall(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, Value *RTLocOverride, OpenMPIRBuilder::InsertPointTy AllocaIP, ArrayRef< BasicBlock * > DeallocBlocks, OpenMPIRBuilder::TargetDataInfo &Info, const OpenMPIRBuilder::TargetKernelDefaultAttrs &DefaultAttrs, const OpenMPIRBuilder::TargetKernelRuntimeAttrs &RuntimeAttrs, Value *IfCond, Function *OutlinedFn, Constant *OutlinedFnID, SmallVectorImpl< Value * > &Args, OpenMPIRBuilder::GenMapInfoCallbackTy GenMapInfoCB, OpenMPIRBuilder::CustomMapperCallbackTy CustomMapperCB, const OpenMPIRBuilder::DependenciesInfo &Dependencies, bool HasNoWait, Value *DynCGroupMem, OMPDynGroupprivateFallbackType DynCGroupMemFallback)
static 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 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::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.
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 createTarget(const LocationDescription &Loc, bool IsOffloadEntry, OpenMPIRBuilder::InsertPointTy AllocaIP, OpenMPIRBuilder::InsertPointTy CodeGenIP, ArrayRef< BasicBlock * > DeallocBlocks, TargetDataInfo &Info, TargetRegionEntryInfo &EntryInfo, const TargetKernelDefaultAttrs &DefaultAttrs, const TargetKernelRuntimeAttrs &RuntimeAttrs, Value *IfCond, SmallVectorImpl< Value * > &Inputs, GenMapInfoCallbackTy GenMapInfoCB, TargetBodyGenCallbackTy BodyGenCB, TargetGenArgAccessorsCallbackTy ArgAccessorFuncCB, CustomMapperCallbackTy CustomMapperCB, const DependenciesInfo &Dependencies={}, bool HasNowait=false, Value *DynCGroupMem=nullptr, omp::OMPDynGroupprivateFallbackType DynCGroupMemFallback=omp::OMPDynGroupprivateFallbackType::Abort, DebugLoc OutlinedFnLoc={}, Value *RTLocOverride=nullptr)
Generator for 'omp target'.
LLVM_ABI InsertPointOrErrorTy createTeams(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, Value *NumTeamsLower=nullptr, Value *NumTeamsUpper=nullptr, Value *ThreadLimit=nullptr, Value *IfExpr=nullptr)
Generator for #omp teams
std::forward_list< CanonicalLoopInfo > LoopInfos
Collection of owned canonical loop objects that eventually need to be free'd.
LLVM_ABI llvm::StructType * getKmpTaskAffinityInfoTy()
Return the LLVM struct type matching runtime kmp_task_affinity_info_t.
LLVM_ABI Constant * emitKernelEnvironment(const LocationDescription &Loc, const llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs)
The omp target interface.
LLVM_ABI std::string createPlatformSpecificName(ArrayRef< StringRef > Parts) const
Get the create a name using the platform specific separators.
LLVM_ABI FunctionCallee createDispatchNextFunction(unsigned IVSize, bool IVSigned)
Returns __kmpc_dispatch_next_* runtime function for the specified size IVSize and sign IVSigned.
static LLVM_ABI void getKernelArgsVector(TargetKernelArgs &KernelArgs, IRBuilderBase &Builder, SmallVector< Value * > &ArgsVector)
Create the kernel args vector used by emitTargetKernel.
LLVM_ABI void unrollLoopHeuristic(DebugLoc DL, CanonicalLoopInfo *Loop)
Fully or partially unroll a loop.
LLVM_ABI omp::OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position)
Get OMP_MAP_MEMBER_OF flag with extra bits reserved based on the position given.
LLVM_ABI void addAttributes(omp::RuntimeFunction FnID, Function &Fn)
Add attributes known for FnID to Fn.
Module & M
The underlying LLVM-IR module.
StringMap< Constant * > SrcLocStrMap
Map to remember source location strings.
LLVM_ABI void createMapperAllocas(const LocationDescription &Loc, InsertPointTy AllocaIP, unsigned NumOperands, struct MapperAllocas &MapperAllocas)
Create the allocas instruction used in call to mapper functions.
SmallVector< DeclareTargetGlobalReplacement, 8 > DeclareTargetGlobalReplacements
Collection of declare target globals to rewrite uses of during device module finalizaiton.
LLVM_ABI Constant * getOrCreateSrcLocStr(StringRef LocStr, uint32_t &SrcLocStrSize)
Return the (LLVM-IR) string describing the source location LocStr.
LLVM_ABI Error emitTargetRegionFunction(TargetRegionEntryInfo &EntryInfo, FunctionGenCallback &GenerateFunctionCallback, bool IsOffloadEntry, Function *&OutlinedFn, Constant *&OutlinedFnID)
Create a unique name for the entry function using the source location information of the current targ...
LLVM_ABI InsertPointOrErrorTy createIteratorLoop(LocationDescription Loc, llvm::Value *TripCount, IteratorBodyGenTy BodyGen, llvm::StringRef Name="iterator")
Create a canonical iterator loop at the current insertion point.
LLVM_ABI Expected< SmallVector< llvm::CanonicalLoopInfo * > > createCanonicalScanLoops(const LocationDescription &Loc, LoopBodyGenCallbackTy BodyGenCB, Value *Start, Value *Stop, Value *Step, bool IsSigned, bool InclusiveStop, InsertPointTy ComputeIP, const Twine &Name, ScanInfo *ScanRedInfo)
Generator for the control flow structure of an OpenMP canonical loops if the parent directive has an ...
LLVM_ABI FunctionCallee createDispatchFiniFunction(unsigned IVSize, bool IVSigned)
Returns __kmpc_dispatch_fini_* runtime function for the specified size IVSize and sign IVSigned.
function_ref< InsertPointOrErrorTy( InsertPointTy AllocaIP, InsertPointTy CodeGenIP, ArrayRef< BasicBlock * > DeallocBlocks)> TargetBodyGenCallbackTy
LLVM_ABI void unrollLoopPartial(DebugLoc DL, CanonicalLoopInfo *Loop, int32_t Factor, CanonicalLoopInfo **UnrolledCLI)
Partially unroll a loop.
function_ref< Error(Value *DeviceID, Value *RTLoc, IRBuilderBase::InsertPoint TargetTaskAllocaIP)> TargetTaskBodyCallbackTy
Callback type for generating the bodies of device directives that require outer target tasks (e....
Expected< MapInfosTy & > MapInfosOrErrorTy
bool HandleFPNegZero
Emit atomic compare for constructs: — Only scalar data types cond-expr-stmt: x = x ordop expr ?
LLVM_ABI void emitTaskyieldImpl(const LocationDescription &Loc)
Generate a taskyield runtime call.
LLVM_ABI void emitMapperCall(const LocationDescription &Loc, Function *MapperFunc, Value *SrcLocInfo, Value *MaptypesArg, Value *MapnamesArg, struct MapperAllocas &MapperAllocas, int64_t DeviceID, unsigned NumOperands)
Create the call for the target mapper function.
LLVM_ABI InsertPointOrErrorTy createDistribute(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< BasicBlock * > DeallocBlocks, BodyGenCallbackTy BodyGenCB)
Generator for #omp distribute
function_ref< Expected< Function * >(unsigned int)> CustomMapperCallbackTy
LLVM_ABI InsertPointTy createOrderedDepend(const LocationDescription &Loc, InsertPointTy AllocaIP, unsigned NumLoops, ArrayRef< llvm::Value * > StoreValues, const Twine &Name, bool IsDependSource)
Generator for 'omp ordered depend (source | sink)'.
LLVM_ABI InsertPointTy createCopyinClauseBlocks(InsertPointTy IP, Value *MasterAddr, Value *PrivateAddr, llvm::IntegerType *IntPtrTy, bool BranchtoEnd=true)
Generate conditional branch and relevant BasicBlocks through which private threads copy the 'copyin' ...
function_ref< InsertPointOrErrorTy( InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Value &Original, Value &Inner, Value *&ReplVal)> PrivatizeCallbackTy
Callback type for variable privatization (think copy & default constructor).
LLVM_ABI bool isFinalized()
Check whether the finalize function has already run.
SmallVector< FinalizationInfo, 8 > FinalizationStack
The finalization stack made up of finalize callbacks currently in-flight, wrapped into FinalizationIn...
LLVM_ABI std::vector< CanonicalLoopInfo * > tileLoops(DebugLoc DL, ArrayRef< CanonicalLoopInfo * > Loops, ArrayRef< Value * > TileSizes)
Tile a loop nest.
LLVM_ABI CallInst * createOMPInteropInit(const LocationDescription &Loc, Value *InteropVar, omp::OMPInteropType InteropType, Value *Device, Value *NumDependences, Value *DependenceAddress, bool HaveNowaitClause)
Create a runtime call for __tgt_interop_init.
LLVM_ABI Error emitIfClause(Value *Cond, BodyGenCallbackTy ThenGen, BodyGenCallbackTy ElseGen, InsertPointTy AllocaIP={}, ArrayRef< BasicBlock * > DeallocBlocks={})
Emits code for OpenMP 'if' clause using specified BodyGenCallbackTy Here is the logic: if (Cond) { Th...
LLVM_ABI void finalize(Function *Fn=nullptr)
Finalize the underlying module, e.g., by outlining regions.
LLVM_ABI Function * getOrCreateRuntimeFunctionPtr(omp::RuntimeFunction FnID)
void addOutlineInfo(std::unique_ptr< OutlineInfo > &&OI)
Add a new region that will be outlined later.
LLVM_ABI InsertPointTy createTargetInit(const LocationDescription &Loc, const llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs)
Create a runtime call for kmpc_target_init.
LLVM_ABI InsertPointOrErrorTy createReductions(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< ReductionInfo > ReductionInfos, ArrayRef< bool > IsByRef, bool IsNoWait=false, bool IsTeamsReduction=false)
Generator for 'omp reduction'.
const Triple T
The target triple of the underlying module.
DenseMap< std::pair< Constant *, uint64_t >, Constant * > IdentMap
Map to remember existing ident_t*.
LLVM_ABI CallInst * createOMPFree(const LocationDescription &Loc, Value *Addr, Value *Allocator, std::string Name="")
Create a runtime call for kmpc_free.
LLVM_ABI InsertPointOrErrorTy createReductionsGPU(const LocationDescription &Loc, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, ArrayRef< ReductionInfo > ReductionInfos, ArrayRef< bool > IsByRef, bool IsNoWait=false, bool IsTeamsReduction=false, bool IsSPMD=false, ReductionGenCBKind ReductionGenCBKind=ReductionGenCBKind::MLIR, std::optional< omp::GV > GridValue={}, Value *SrcLocInfo=nullptr)
Design of OpenMP reductions on the GPU.
LLVM_ABI FunctionCallee createForStaticInitFunction(unsigned IVSize, bool IVSigned, bool IsGPUDistribute)
Returns __kmpc_for_static_init_* runtime function for the specified size IVSize and sign IVSigned.
LLVM_ABI CallInst * createOMPAlloc(const LocationDescription &Loc, Value *Size, Value *Allocator, std::string Name="")
Create a runtime call for kmpc_alloc.
LLVM_ABI void emitNonContiguousDescriptor(InsertPointTy AllocaIP, InsertPointTy CodeGenIP, MapInfosTy &CombinedInfo, TargetDataInfo &Info)
Emit an array of struct descriptors to be assigned to the offload args.
LLVM_ABI InsertPointOrErrorTy createSection(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB)
Generator for 'omp section'.
LLVM_ABI InsertPointOrErrorTy createTaskgroup(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< BasicBlock * > DeallocBlocks, BodyGenCallbackTy BodyGenCB)
Generator for the taskgroup construct.
LLVM_ABI InsertPointOrErrorTy createParallel(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< BasicBlock * > DeallocBlocks, BodyGenCallbackTy BodyGenCB, PrivatizeCallbackTy PrivCB, FinalizeCallbackTy FiniCB, Value *IfCondition, Value *NumThreads, omp::ProcBindKind ProcBind, bool IsCancellable)
Generator for 'omp parallel'.
function_ref< InsertPointOrErrorTy(InsertPointTy)> EmitFallbackCallbackTy
Callback function type for functions emitting the host fallback code that is executed when the kernel...
static LLVM_ABI TargetRegionEntryInfo getTargetEntryUniqueInfo(FileIdentifierInfoCallbackTy CallBack, vfs::FileSystem &VFS, StringRef ParentName="")
Creates a unique info for a target entry when provided a filename and line number from.
LLVM_ABI void emitTaskDependency(IRBuilderBase &Builder, Value *Entry, const DependData &Dep)
Store one kmp_depend_info entry at the given Entry pointer.
LLVM_ABI void emitBlock(BasicBlock *BB, Function *CurFn, bool IsFinished=false)
LLVM_ABI Value * getOrCreateThreadID(Value *Ident)
Return the current thread ID.
LLVM_ABI InsertPointOrErrorTy createMaster(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB)
Generator for 'omp master'.
LLVM_ABI InsertPointOrErrorTy createTargetData(const LocationDescription &Loc, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, ArrayRef< BasicBlock * > DeallocBlocks, Value *DeviceID, Value *IfCond, TargetDataInfo &Info, GenMapInfoCallbackTy GenMapInfoCB, CustomMapperCallbackTy CustomMapperCB, omp::RuntimeFunction *MapperFunc=nullptr, function_ref< InsertPointOrErrorTy(InsertPointTy CodeGenIP, BodyGenTy BodyGenType)> BodyGenCB=nullptr, function_ref< void(unsigned int, Value *)> DeviceAddrCB=nullptr, Value *SrcLocInfo=nullptr)
Generator for 'omp target data'.
LLVM_ABI CallInst * createRuntimeFunctionCall(FunctionCallee Callee, ArrayRef< Value * > Args, StringRef Name="")
LLVM_ABI InsertPointOrErrorTy emitKernelLaunch(const LocationDescription &Loc, Value *OutlinedFnID, EmitFallbackCallbackTy EmitTargetCallFallbackCB, TargetKernelArgs &Args, Value *DeviceID, Value *RTLoc, InsertPointTy AllocaIP)
Generate a target region entry call and host fallback call.
StringMap< GlobalVariable *, BumpPtrAllocator > InternalVars
An ordered map of auto-generated variables to their unique names.
LLVM_ABI InsertPointOrErrorTy createCancellationPoint(const LocationDescription &Loc, omp::Directive CanceledDirective)
Generator for 'omp cancellation point'.
LLVM_ABI CallInst * createOMPAlignedAlloc(const LocationDescription &Loc, Value *Align, Value *Size, Value *Allocator, std::string Name="")
Create a runtime call for kmpc_align_alloc.
LLVM_ABI FunctionCallee createDispatchInitFunction(unsigned IVSize, bool IVSigned)
Returns __kmpc_dispatch_init_* runtime function for the specified size IVSize and sign IVSigned.
LLVM_ABI InsertPointOrErrorTy createScan(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< llvm::Value * > ScanVars, ArrayRef< llvm::Type * > ScanVarsType, bool IsInclusive, ScanInfo *ScanRedInfo)
This directive split and directs the control flow to input phase blocks or scan phase blocks based on...
LLVM_ABI CallInst * createOMPFreeShared(const LocationDescription &Loc, Value *Addr, Value *Size, const Twine &Name=Twine(""))
Create a runtime call for kmpc_free_shared.
LLVM_ABI CallInst * createOMPInteropUse(const LocationDescription &Loc, Value *InteropVar, Value *Device, Value *NumDependences, Value *DependenceAddress, bool HaveNowaitClause)
Create a runtime call for __tgt_interop_use.
IRBuilder<>::InsertPoint InsertPointTy
Type used throughout for insertion points.
LLVM_ABI GlobalVariable * getOrCreateInternalVariable(Type *Ty, const StringRef &Name, std::optional< unsigned > AddressSpace={})
Gets (if variable with the given name already exist) or creates internal global variable with the spe...
LLVM_ABI GlobalVariable * createOffloadMapnames(SmallVectorImpl< llvm::Constant * > &Names, std::string VarName)
Create the global variable holding the offload names information.
LLVM_ABI InsertPointOrErrorTy createTask(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< BasicBlock * > DeallocBlocks, BodyGenCallbackTy BodyGenCB, bool Tied=true, Value *Final=nullptr, Value *IfCondition=nullptr, const DependenciesInfo &Dependencies={}, const AffinityData &Affinities={}, bool Mergeable=false, Value *EventHandle=nullptr, Value *Priority=nullptr, bool FreeAgent=false)
Generator for #omp taskloop
std::forward_list< ScanInfo > ScanInfos
Collection of owned ScanInfo objects that eventually need to be free'd.
static LLVM_ABI void writeTeamsForKernel(const Triple &T, Function &Kernel, int32_t LB, int32_t UB)
LLVM_ABI Value * calculateCanonicalLoopTripCount(const LocationDescription &Loc, Value *Start, Value *Stop, Value *Step, bool IsSigned, bool InclusiveStop, const Twine &Name="loop")
Calculate the trip count of a canonical loop.
LLVM_ABI InsertPointOrErrorTy createBarrier(const LocationDescription &Loc, omp::Directive Kind, bool ForceSimpleCall=false, bool CheckCancelFlag=true)
Emitter methods for OpenMP directives.
LLVM_ABI void setCorrectMemberOfFlag(omp::OpenMPOffloadMappingFlags &Flags, omp::OpenMPOffloadMappingFlags MemberOfFlag)
Given an initial flag set, this function modifies it to contain the passed in MemberOfFlag generated ...
LLVM_ABI Error emitOffloadingArraysAndArgs(InsertPointTy AllocaIP, InsertPointTy CodeGenIP, TargetDataInfo &Info, TargetDataRTArgs &RTArgs, MapInfosTy &CombinedInfo, CustomMapperCallbackTy CustomMapperCB, bool IsNonContiguous=false, bool ForEndCall=false, function_ref< void(unsigned int, Value *)> DeviceAddrCB=nullptr)
Allocates memory for and populates the arrays required for offloading (offload_{baseptrs|ptrs|mappers...
LLVM_ABI Constant * getOrCreateDefaultSrcLocStr(uint32_t &SrcLocStrSize)
Return the (LLVM-IR) string describing the default source location.
LLVM_ABI InsertPointOrErrorTy createCritical(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, StringRef CriticalName, Value *HintInst)
Generator for 'omp critical'.
LLVM_ABI void createError(const LocationDescription &Loc, bool IsFatal, Value *Message)
Generate a call to the runtime to emit the diagnostic of an OpenMP error directive with at(execution)...
LLVM_ABI void createOffloadEntry(Constant *ID, Constant *Addr, uint64_t Size, int32_t Flags, GlobalValue::LinkageTypes, StringRef Name="")
Creates offloading entry for the provided entry ID ID, address Addr, size Size, and flags Flags.
static LLVM_ABI unsigned getOpenMPDefaultSimdAlign(const Triple &TargetTriple, const StringMap< bool > &Features)
Get the default alignment value for given target.
LLVM_ABI unsigned getFlagMemberOffset()
Get the offset of the OMP_MAP_MEMBER_OF field.
LLVM_ABI InsertPointOrErrorTy 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),...