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.isValid() || !IP2.isValid())
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, 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");
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.getNodeParent()->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);
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)};
1990 BasicBlock *OuterAllocaBlock = OuterAllocIP.getNodeParent();
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 == IP.getNodeParent()->end()) {
2041 IP =
I->getIterator();
2043 assert(IP.getNodeParent()->getTerminator()->getNumSuccessors() == 1 &&
2044 IP.getNodeParent()->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() ==
2191 OuterAllocIP.getNodeParent()->getParent() &&
2192 "Dealloc block must be in the allocation's function to reuse "
2193 "its debug location");
2195 Builder.getCurrentDebugLocation()},
2199 Ptr =
Builder.CreateAlloca(V.getType(),
nullptr,
2200 V.getName() +
".reloaded");
2209 Builder.restoreIP(InnerAllocaIP);
2210 Inner =
Builder.CreateLoad(V.getType(), Ptr);
2213 Value *ReplacementValue =
nullptr;
2216 ReplacementValue = PrivTID;
2219 PrivCB(InnerAllocaIP,
Builder.saveIP(), V, *Inner, ReplacementValue);
2224 InnerAllocaIP.getNodeParent()->getTerminator()->getIterator();
2226 assert(ReplacementValue &&
2227 "Expected copy/create callback to set replacement value!");
2228 if (ReplacementValue == &V)
2233 UPtr->set(ReplacementValue);
2256 for (
Value *Output : Outputs)
2260 "OpenMP outlining should not produce live-out values!");
2262 LLVM_DEBUG(
dbgs() <<
"After privatization: " << *OuterFn <<
"\n");
2264 for (
auto *BB : Blocks)
2265 dbgs() <<
" PBR: " << BB->getName() <<
"\n";
2273 assert(FiniInfo.DK == OMPD_parallel &&
2274 "Unexpected finalization stack state!");
2285 Builder.CreateBr(*FiniBBOrErr);
2289 Term->eraseFromParent();
2296 UI->eraseFromParent();
2328 Value *Severity = ConstantInt::get(Int32, IsFatal ? 2 : 1);
2330 Value *Args[] = {Ident, Severity, MessageArg};
2359 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr));
2361 Builder.CreateStore(DepValPtr, Addr);
2364 DependInfo, Entry,
static_cast<unsigned int>(RTLDependInfoFields::Len));
2366 ConstantInt::get(SizeTy,
2371 DependInfo, Entry,
static_cast<unsigned int>(RTLDependInfoFields::Flags));
2373 static_cast<unsigned int>(Dep.
DepKind)),
2386 if (Dependencies.
empty())
2406 Type *DependInfo = OMPBuilder.DependInfo;
2408 Value *DepArray =
nullptr;
2414 Builder.SetInsertPoint(
2415 Builder.GetInsertBlock()->getParent()->getEntryBlock().getTerminator());
2416 DepArray = Builder.CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
2419 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies)) {
2421 Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
2446 Value *DepArray =
nullptr;
2447 Type *DepArrayTy =
nullptr;
2448 Value *NumDeps =
nullptr;
2451 NumDeps = Dependencies.
NumDeps;
2452 }
else if (!Dependencies.
Deps.empty()) {
2454 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
2458 Builder.GetInsertBlock()->getParent()->getEntryBlock();
2460 DepArray =
Builder.CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
2463 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies.
Deps)) {
2465 Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
2479 ConstantInt::get(
Builder.getInt32Ty(), 0),
2481 ConstantInt::get(
Builder.getInt32Ty(), IsNowait)};
2484 omp::RuntimeFunction::OMPRTL___kmpc_omp_taskwait_deps_51),
2494 unsigned ProgramAddressSpace = M.getDataLayout().getProgramAddressSpace();
2506 auto *VoidPtrTy =
PointerType::get(Builder.getContext(), ProgramAddressSpace);
2509 Builder.getVoidTy(), {VoidPtrTy, VoidPtrTy, Builder.getInt32Ty()},
2513 "omp_taskloop_dup", M);
2516 Value *LastprivateFlagArg = DupFunction->
getArg(2);
2517 DestTaskArg->
setName(
"dest_task");
2518 SrcTaskArg->
setName(
"src_task");
2519 LastprivateFlagArg->
setName(
"lastprivate_flag");
2522 Builder.SetInsertPoint(
2525 auto GetTaskContextPtrFromArg = [&](
Value *Arg) ->
Value * {
2526 Type *TaskWithPrivatesTy =
2528 Value *TaskPrivates = Builder.CreateGEP(
2529 TaskWithPrivatesTy, Arg, {Builder.getInt32(0), Builder.getInt32(1)});
2530 Value *ContextPtr = Builder.CreateGEP(
2531 PrivatesTy, TaskPrivates,
2532 {Builder.getInt32(0), Builder.getInt32(PrivatesIndex)});
2536 Value *DestTaskContextPtr = GetTaskContextPtrFromArg(DestTaskArg);
2537 Value *SrcTaskContextPtr = GetTaskContextPtrFromArg(SrcTaskArg);
2539 DestTaskContextPtr->
setName(
"destPtr");
2540 SrcTaskContextPtr->
setName(
"srcPtr");
2544 Expected<IRBuilderBase::InsertPoint> AfterIPOrError =
2545 DupCB(AllocaIP, CodeGenIP, DestTaskContextPtr, SrcTaskContextPtr);
2546 if (!AfterIPOrError)
2548 Builder.restoreIP(*AfterIPOrError);
2558 llvm::function_ref<llvm::Expected<llvm::CanonicalLoopInfo *>()> LoopInfo,
2560 Value *GrainSize,
bool NoGroup,
int Sched,
Value *Final,
bool Mergeable,
2562 Value *TaskContextStructPtrVal,
bool FreeAgent) {
2567 uint32_t SrcLocStrSize;
2581 if (
Error Err = BodyGenCB(TaskloopAllocaIP, TaskloopBodyIP, TaskloopExitBB))
2584 llvm::Expected<llvm::CanonicalLoopInfo *> result = LoopInfo();
2589 llvm::CanonicalLoopInfo *CLI = result.
get();
2590 auto OI = std::make_unique<OutlineInfo>();
2591 OI->EntryBB = TaskloopAllocaBB;
2592 OI->OuterAllocBB = AllocaIP.getNodeParent();
2593 OI->ExitBB = TaskloopExitBB;
2594 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2595 copy(DeallocBlocks, OI->OuterDeallocBBs.end());
2598 SmallVector<Instruction *> ToBeDeleted;
2601 Builder, AllocaIP, ToBeDeleted, TaskloopAllocaIP,
"global.tid",
false));
2603 TaskloopAllocaIP,
"lb",
false,
true);
2605 TaskloopAllocaIP,
"ub",
false,
true);
2607 TaskloopAllocaIP,
"step",
false,
true);
2610 OI->Inputs.insert(FakeLB);
2611 OI->Inputs.insert(FakeUB);
2612 OI->Inputs.insert(FakeStep);
2613 if (TaskContextStructPtrVal)
2614 OI->Inputs.insert(TaskContextStructPtrVal);
2615 assert(((TaskContextStructPtrVal && DupCB) ||
2616 (!TaskContextStructPtrVal && !DupCB)) &&
2617 "Task context struct ptr and duplication callback must be both set "
2623 unsigned ProgramAddressSpace =
M.getDataLayout().getProgramAddressSpace();
2627 {FakeLB->getType(), FakeUB->getType(), FakeStep->getType(), PointerTy});
2628 Expected<Value *> TaskDupFnOrErr = createTaskDuplicationFunction(
2631 if (!TaskDupFnOrErr) {
2634 Value *TaskDupFn = *TaskDupFnOrErr;
2636 OI->PostOutlineCB = [
this, Ident, LBVal, UBVal, StepVal, Untied,
2637 TaskloopAllocaBB, CLI, TaskDupFn, ToBeDeleted, IfCond,
2638 GrainSize, NoGroup, Sched, FakeLB, FakeUB, FakeStep,
2639 FakeSharedsTy, Final, Mergeable, Priority,
2641 FreeAgent](
Function &OutlinedFn)
mutable {
2643 assert(OutlinedFn.hasOneUse() &&
2644 "there must be a single user for the outlined function");
2651 Value *CastedLBVal =
2652 Builder.CreateIntCast(LBVal,
Builder.getInt64Ty(),
true,
"lb64");
2653 Value *CastedUBVal =
2654 Builder.CreateIntCast(UBVal,
Builder.getInt64Ty(),
true,
"ub64");
2655 Value *CastedStepVal =
2656 Builder.CreateIntCast(StepVal,
Builder.getInt64Ty(),
true,
"step64");
2658 Builder.SetInsertPoint(StaleCI);
2671 Builder.CreateCall(TaskgroupFn, {Ident, ThreadID});
2696 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
2698 AllocaInst *ArgStructAlloca =
2700 assert(ArgStructAlloca &&
2701 "Unable to find the alloca instruction corresponding to arguments "
2702 "for extracted function");
2703 std::optional<TypeSize> ArgAllocSize =
2706 "Unable to determine size of arguments for extracted function");
2707 Value *SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
2712 CallInst *TaskData =
Builder.CreateCall(
2713 TaskAllocFn, {Ident, ThreadID,
Flags,
2714 TaskSize, SharedsSize,
2719 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
2725 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(0)});
2728 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(1)});
2731 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(2)});
2737 IfCond ?
Builder.CreateIntCast(IfCond,
Builder.getInt32Ty(),
true)
2743 Value *GrainSizeVal =
2744 GrainSize ?
Builder.CreateIntCast(GrainSize,
Builder.getInt64Ty(),
true)
2746 Value *TaskDup = TaskDupFn;
2748 Value *
Args[] = {Ident, ThreadID, TaskData, IfCondVal, Lb, Ub,
2749 Loadstep, NoGroupVal, SchedVal, GrainSizeVal, TaskDup};
2754 Builder.CreateCall(TaskloopFn, Args);
2761 Builder.CreateCall(EndTaskgroupFn, {Ident, ThreadID});
2766 Builder.SetInsertPoint(TaskloopAllocaBB->begin());
2768 LoadInst *SharedsOutlined =
2769 Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
2770 OutlinedFn.getArg(1)->replaceUsesWithIf(
2772 [SharedsOutlined](Use &U) {
return U.getUser() != SharedsOutlined; });
2775 Type *IVTy =
IV->getType();
2781 Value *TaskLB =
nullptr;
2782 Value *TaskUB =
nullptr;
2783 Value *TaskStep =
nullptr;
2784 Value *LoadTaskLB =
nullptr;
2785 Value *LoadTaskUB =
nullptr;
2786 Value *LoadTaskStep =
nullptr;
2787 for (Instruction &
I : *TaskloopAllocaBB) {
2788 if (
I.getOpcode() == Instruction::GetElementPtr) {
2791 switch (CI->getZExtValue()) {
2803 }
else if (
I.getOpcode() == Instruction::Load) {
2805 if (
Load.getPointerOperand() == TaskLB) {
2806 assert(TaskLB !=
nullptr &&
"Expected value for TaskLB");
2808 }
else if (
Load.getPointerOperand() == TaskUB) {
2809 assert(TaskUB !=
nullptr &&
"Expected value for TaskUB");
2811 }
else if (
Load.getPointerOperand() == TaskStep) {
2812 assert(TaskStep !=
nullptr &&
"Expected value for TaskStep");
2818 Builder.SetInsertPoint(CLI->getPreheader()->getTerminator());
2820 assert(LoadTaskLB !=
nullptr &&
"Expected value for LoadTaskLB");
2821 assert(LoadTaskUB !=
nullptr &&
"Expected value for LoadTaskUB");
2822 assert(LoadTaskStep !=
nullptr &&
"Expected value for LoadTaskStep");
2824 Builder.CreateSub(LoadTaskUB, LoadTaskLB), LoadTaskStep);
2825 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One,
"trip_cnt");
2826 Value *CastedTripCount =
Builder.CreateIntCast(TripCount, IVTy,
true);
2827 Value *CastedTaskLB =
Builder.CreateIntCast(LoadTaskLB, IVTy,
true);
2829 CLI->setTripCount(CastedTripCount);
2831 Builder.SetInsertPoint(CLI->getBody()->getFirstInsertionPt());
2833 if (NumOfCollapseLoops > 1) {
2839 Builder.CreateSub(CastedTaskLB, ConstantInt::get(IVTy, 1)));
2842 for (
auto IVUse = CLI->getIndVar()->uses().begin();
2843 IVUse != CLI->getIndVar()->uses().end(); IVUse++) {
2844 User *IVUser = IVUse->getUser();
2846 if (
Op->getOpcode() == Instruction::URem ||
2847 Op->getOpcode() == Instruction::UDiv) {
2852 for (User *User : UsersToReplace) {
2853 User->replaceUsesOfWith(CLI->getIndVar(), IVPlusTaskLB);
2870 assert(CLI->getIndVar()->getNumUses() == 3 &&
2871 "Canonical loop should have exactly three uses of the ind var");
2872 for (User *IVUser : CLI->getIndVar()->users()) {
2874 if (
Mul->getOpcode() == Instruction::Mul) {
2875 for (User *MulUser :
Mul->users()) {
2877 if (
Add->getOpcode() == Instruction::Add) {
2878 Add->setOperand(1, CastedTaskLB);
2887 FakeLB->replaceAllUsesWith(CastedLBVal);
2888 FakeUB->replaceAllUsesWith(CastedUBVal);
2889 FakeStep->replaceAllUsesWith(CastedStepVal);
2891 I->eraseFromParent();
2902 M.getContext(),
M.getDataLayout().getPointerSizeInBits());
2912 bool Mergeable,
Value *EventHandle,
Value *Priority,
bool FreeAgent) {
2943 if (
Error Err = BodyGenCB(TaskAllocaIP, TaskBodyIP, TaskExitBB))
2946 auto OI = std::make_unique<OutlineInfo>();
2947 OI->EntryBB = TaskAllocaBB;
2948 OI->OuterAllocBB = AllocaIP.getNodeParent();
2949 OI->ExitBB = TaskExitBB;
2950 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2951 copy(DeallocBlocks, OI->OuterDeallocBBs.
end());
2956 Builder, AllocaIP, ToBeDeleted, TaskAllocaIP,
"global.tid",
false));
2958 OI->PostOutlineCB = [
this, Ident, Tied, Final, IfCondition, Dependencies,
2959 Affinities, Mergeable, Priority, EventHandle, FreeAgent,
2961 ToBeDeleted](
Function &OutlinedFn)
mutable {
2963 assert(OutlinedFn.hasOneUse() &&
2964 "there must be a single user for the outlined function");
2969 bool HasShareds = StaleCI->
arg_size() > 1;
2970 Builder.SetInsertPoint(StaleCI);
2997 bool UseMergedIf0Path = ConstIfCondition && ConstIfCondition->isZero();
3001 Flags =
Builder.CreateOr(FinalFlag, Flags);
3004 if (Mergeable || UseMergedIf0Path)
3018 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
3027 assert(ArgStructAlloca &&
3028 "Unable to find the alloca instruction corresponding to arguments "
3029 "for extracted function");
3030 std::optional<TypeSize> ArgAllocSize =
3033 "Unable to determine size of arguments for extracted function");
3034 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
3040 TaskAllocFn, {Ident, ThreadID, Flags,
3041 TaskSize, SharedsSize,
3044 if (Affinities.
Count && Affinities.
Info) {
3046 OMPRTL___kmpc_omp_reg_task_with_affinity);
3057 OMPRTL___kmpc_task_allow_completion_event);
3061 Builder.CreatePointerBitCastOrAddrSpaceCast(EventHandle,
3063 EventVal =
Builder.CreatePtrToInt(EventVal,
Builder.getInt64Ty());
3064 Builder.CreateStore(EventVal, EventHandleAddr);
3070 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
3085 Constant *Zero = ConstantInt::get(Int32Ty, 0);
3089 Builder.CreateInBoundsGEP(TaskPtr, TaskData, {Zero, Zero});
3092 VoidPtr, VoidPtr,
Builder.getInt32Ty(), VoidPtr, VoidPtr);
3094 TaskStructType, TaskGEP, {Zero, ConstantInt::get(Int32Ty, 4)});
3097 Value *CmplrData =
Builder.CreateInBoundsGEP(CmplrStructType,
3098 PriorityData, {Zero, Zero});
3099 Builder.CreateStore(Priority, CmplrData);
3102 Value *DepArray =
nullptr;
3103 Value *NumDeps =
nullptr;
3106 NumDeps = Dependencies.
NumDeps;
3107 }
else if (!Dependencies.
Deps.empty()) {
3109 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
3129 if (IfCondition && !UseMergedIf0Path) {
3134 Builder.GetInsertPoint()->getParent()->getTerminator();
3135 Instruction *ThenTI = IfTerminator, *ElseTI =
nullptr;
3136 Builder.SetInsertPoint(IfTerminator);
3139 Builder.SetInsertPoint(ElseTI);
3146 {Ident, ThreadID, NumDeps, DepArray,
3147 ConstantInt::get(
Builder.getInt32Ty(), 0),
3162 Builder.SetInsertPoint(ThenTI);
3170 {Ident, ThreadID, TaskData, NumDeps, DepArray,
3171 ConstantInt::get(
Builder.getInt32Ty(), 0),
3184 LoadInst *Shareds =
Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
3185 OutlinedFn.getArg(1)->replaceUsesWithIf(
3186 Shareds, [Shareds](
Use &U) {
return U.getUser() != Shareds; });
3192 Builder.ClearInsertionPoint();
3194 I->eraseFromParent();
3220 if (
Error Err = BodyGenCB(AllocaIP,
Builder.saveIP(), DeallocBlocks))
3223 Builder.SetInsertPoint(TaskgroupExitBB);
3266 unsigned CaseNumber = 0;
3267 for (
auto SectionCB : SectionCBs) {
3269 M.getContext(),
"omp_section_loop.body.case", CurFn,
Continue);
3271 Builder.SetInsertPoint(CaseBB);
3284 Value *LB = ConstantInt::get(I32Ty, 0);
3285 Value *UB = ConstantInt::get(I32Ty, SectionCBs.
size());
3286 Value *ST = ConstantInt::get(I32Ty, 1);
3288 Loc, LoopBodyGenCB, LB, UB, ST,
true,
false, AllocaIP,
"section_loop");
3293 applyStaticWorkshareLoop(
Loc.DL, *
LoopInfo, AllocaIP,
3294 WorksharingLoopType::ForStaticLoop, !IsNowait);
3300 assert(LoopFini &&
"Bad structure of static workshare loop finalization");
3304 assert(FiniInfo.DK == OMPD_sections &&
3305 "Unexpected finalization stack state!");
3306 if (
Error Err = FiniInfo.mergeFiniBB(
Builder, LoopFini))
3320 if (IP != IP.getNodeParent()->end())
3331 auto *CaseBB =
Loc.IP.getNodeParent();
3332 auto *CondBB = CaseBB->getSinglePredecessor()->getSinglePredecessor();
3333 auto *ExitBB = CondBB->getTerminator()->getSuccessor(1);
3335 IP =
I->getIterator();
3339 Directive OMPD = Directive::OMPD_sections;
3342 return EmitOMPInlinedRegion(OMPD,
nullptr,
nullptr, BodyGenCB, FiniCBWrapper,
3353Value *OpenMPIRBuilder::getGPUThreadID() {
3356 OMPRTL___kmpc_get_hardware_thread_id_in_block),
3360Value *OpenMPIRBuilder::getGPUWarpSize() {
3365Value *OpenMPIRBuilder::getNVPTXWarpID() {
3366 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3367 return Builder.CreateAShr(getGPUThreadID(), LaneIDBits,
"nvptx_warp_id");
3370Value *OpenMPIRBuilder::getNVPTXLaneID() {
3371 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3372 assert(LaneIDBits < 32 &&
"Invalid LaneIDBits size in NVPTX device.");
3373 unsigned LaneIDMask = ~0
u >> (32u - LaneIDBits);
3374 return Builder.CreateAnd(getGPUThreadID(),
Builder.getInt32(LaneIDMask),
3381 uint64_t FromSize =
M.getDataLayout().getTypeStoreSize(FromType);
3382 uint64_t ToSize =
M.getDataLayout().getTypeStoreSize(ToType);
3383 assert(FromSize > 0 &&
"From size must be greater than zero");
3384 assert(ToSize > 0 &&
"To size must be greater than zero");
3385 if (FromType == ToType)
3387 if (FromSize == ToSize)
3388 return Builder.CreateBitCast(From, ToType);
3390 return Builder.CreateIntCast(From, ToType,
true);
3396 Value *ValCastItem =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3397 CastItem,
Builder.getPtrTy(0));
3398 Builder.CreateStore(From, ValCastItem);
3399 return Builder.CreateLoad(ToType, CastItem);
3406 uint64_t Size =
M.getDataLayout().getTypeStoreSize(ElementType);
3407 assert(
Size <= 8 &&
"Unsupported bitwidth in shuffle instruction");
3411 Value *ElemCast = castValueToType(AllocaIP, Element, CastTy);
3413 Builder.CreateIntCast(getGPUWarpSize(),
Builder.getInt16Ty(),
true);
3415 Size <= 4 ? RuntimeFunction::OMPRTL___kmpc_shuffle_int32
3416 : RuntimeFunction::OMPRTL___kmpc_shuffle_int64);
3417 Value *WarpSizeCast =
3419 Value *ShuffleCall =
3424 return castValueToType(AllocaIP, ShuffleCall, ElementType);
3431 uint64_t Size =
M.getDataLayout().getTypeStoreSize(ElemType);
3443 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3444 Value *ElemPtr = DstAddr;
3445 Value *Ptr = SrcAddr;
3446 for (
unsigned IntSize = 8; IntSize >= 1; IntSize /= 2) {
3450 Ptr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3453 Builder.CreateGEP(ElemType, SrcAddr, {ConstantInt::get(IndexTy, 1)});
3454 ElemPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3458 if ((
Size / IntSize) > 1) {
3459 Value *PtrEnd =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3460 SrcAddrGEP,
Builder.getPtrTy());
3477 Builder.CreatePointerBitCastOrAddrSpaceCast(Ptr,
Builder.getPtrTy()));
3479 Builder.CreateICmpSGT(PtrDiff,
Builder.getInt64(IntSize - 1)), ThenBB,
3482 Value *Res = createRuntimeShuffleFunction(
3485 IntType, Ptr,
M.getDataLayout().getPrefTypeAlign(ElemType)),
3487 Builder.CreateAlignedStore(Res, ElemPtr,
3488 M.getDataLayout().getPrefTypeAlign(ElemType));
3490 Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3491 Value *LocalElemPtr =
3492 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3500 Value *Res = createRuntimeShuffleFunction(
3501 AllocaIP,
Builder.CreateLoad(IntType, Ptr), IntType,
Offset);
3502 Builder.CreateStore(Res, ElemPtr);
3503 Ptr =
Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3505 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3511Error OpenMPIRBuilder::emitReductionListCopy(
3516 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3517 Value *RemoteLaneOffset = CopyOptions.RemoteLaneOffset;
3521 for (
auto En :
enumerate(ReductionInfos)) {
3523 Value *SrcElementAddr =
nullptr;
3524 AllocaInst *DestAlloca =
nullptr;
3525 Value *DestElementAddr =
nullptr;
3526 Value *DestElementPtrAddr =
nullptr;
3528 bool ShuffleInElement =
false;
3531 bool UpdateDestListPtr =
false;
3535 ReductionArrayTy, SrcBase,
3536 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3537 SrcElementAddr =
Builder.CreateLoad(
Builder.getPtrTy(), SrcElementPtrAddr);
3541 DestElementPtrAddr =
Builder.CreateInBoundsGEP(
3542 ReductionArrayTy, DestBase,
3543 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3544 bool IsByRefElem = (!IsByRef.
empty() && IsByRef[En.index()]);
3550 Type *DestAllocaType =
3551 IsByRefElem ? RI.ByRefAllocatedType : RI.ElementType;
3552 DestAlloca =
Builder.CreateAlloca(DestAllocaType,
nullptr,
3553 ".omp.reduction.element");
3555 M.getDataLayout().getPrefTypeAlign(DestAllocaType));
3556 DestElementAddr = DestAlloca;
3559 DestElementAddr->
getName() +
".ascast");
3561 ShuffleInElement =
true;
3562 UpdateDestListPtr =
true;
3574 if (ShuffleInElement) {
3575 Type *ShuffleType = RI.ElementType;
3576 Value *ShuffleSrcAddr = SrcElementAddr;
3577 Value *ShuffleDestAddr = DestElementAddr;
3578 AllocaInst *LocalStorage =
nullptr;
3581 assert(RI.ByRefElementType &&
"Expected by-ref element type to be set");
3582 assert(RI.ByRefAllocatedType &&
3583 "Expected by-ref allocated type to be set");
3588 ShuffleType = RI.ByRefElementType;
3590 if (RI.DataPtrPtrGen) {
3593 Builder.saveIP(), ShuffleSrcAddr, ShuffleSrcAddr);
3596 return GenResult.takeError();
3605 LocalStorage =
Builder.CreateAlloca(ShuffleType);
3607 ShuffleDestAddr = LocalStorage;
3612 ShuffleDestAddr = DestElementAddr;
3616 shuffleAndStore(AllocaIP, ShuffleSrcAddr, ShuffleDestAddr, ShuffleType,
3617 RemoteLaneOffset, ReductionArrayTy, IsByRefElem);
3619 if (IsByRefElem && RI.DataPtrPtrGen) {
3621 Value *DestDescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3622 DestAlloca,
Builder.getPtrTy(),
".ascast");
3625 DestDescriptorAddr, LocalStorage, SrcElementAddr,
3626 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
3629 return GenResult.takeError();
3632 switch (RI.EvaluationKind) {
3634 Value *Elem =
Builder.CreateLoad(RI.ElementType, SrcElementAddr);
3636 Builder.CreateStore(Elem, DestElementAddr);
3640 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3641 RI.ElementType, SrcElementAddr, 0, 0,
".realp");
3643 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
3645 RI.ElementType, SrcElementAddr, 0, 1,
".imagp");
3647 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
3649 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3650 RI.ElementType, DestElementAddr, 0, 0,
".realp");
3651 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
3652 RI.ElementType, DestElementAddr, 0, 1,
".imagp");
3653 Builder.CreateStore(SrcReal, DestRealPtr);
3654 Builder.CreateStore(SrcImg, DestImgPtr);
3659 M.getDataLayout().getTypeStoreSize(RI.ElementType));
3661 DestElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3662 SrcElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3674 if (UpdateDestListPtr) {
3675 Value *CastDestAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3676 DestElementAddr,
Builder.getPtrTy(),
3677 DestElementAddr->
getName() +
".ascast");
3678 Builder.CreateStore(CastDestAddr, DestElementPtrAddr);
3685Expected<Function *> OpenMPIRBuilder::emitInterWarpCopyFunction(
3688 IRBuilder<>::InsertPointGuard IPG(
Builder);
3689 LLVMContext &Ctx =
M.getContext();
3691 Builder.getVoidTy(), {Builder.getPtrTy(), Builder.getInt32Ty()},
3695 "_omp_reduction_inter_warp_copy_func", &
M);
3701 Builder.SetInsertPoint(EntryBB);
3719 StringRef TransferMediumName =
3720 "__openmp_nvptx_data_transfer_temporary_storage";
3721 GlobalVariable *TransferMedium =
M.getGlobalVariable(TransferMediumName);
3722 unsigned WarpSize =
Config.getGridValue().GV_Warp_Size;
3724 if (!TransferMedium) {
3725 TransferMedium =
new GlobalVariable(
3733 Value *GPUThreadID = getGPUThreadID();
3735 Value *LaneID = getNVPTXLaneID();
3737 Value *WarpID = getNVPTXWarpID();
3743 AllocaInst *ReduceListAlloca =
Builder.CreateAlloca(
3744 Arg0Type,
nullptr, ReduceListArg->
getName() +
".addr");
3745 AllocaInst *NumWarpsAlloca =
3746 Builder.CreateAlloca(Arg1Type,
nullptr, NumWarpsArg->
getName() +
".addr");
3747 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3748 ReduceListAlloca, Arg0Type, ReduceListAlloca->
getName() +
".ascast");
3749 Value *NumWarpsAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3750 NumWarpsAlloca,
Builder.getPtrTy(0),
3751 NumWarpsAlloca->
getName() +
".ascast");
3752 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
3753 Builder.CreateStore(NumWarpsArg, NumWarpsAddrCast);
3762 for (
auto En :
enumerate(ReductionInfos)) {
3768 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
3769 unsigned RealTySize =
M.getDataLayout().getTypeAllocSize(
3770 IsByRefElem ? RI.ByRefElementType : RI.ElementType);
3771 for (
unsigned TySize = 4; TySize > 0 && RealTySize > 0; TySize /= 2) {
3774 unsigned NumIters = RealTySize / TySize;
3777 Value *Cnt =
nullptr;
3778 Value *CntAddr =
nullptr;
3785 Builder.CreateAlloca(
Builder.getInt32Ty(),
nullptr,
".cnt.addr");
3787 CntAddr =
Builder.CreateAddrSpaceCast(CntAddr,
Builder.getPtrTy(),
3788 CntAddr->
getName() +
".ascast");
3800 Cnt, ConstantInt::get(
Builder.getInt32Ty(), NumIters));
3801 Builder.CreateCondBr(Cmp, BodyBB, ExitBB);
3808 omp::Directive::OMPD_unknown,
3812 return BarrierIP1.takeError();
3818 Value *IsWarpMaster =
Builder.CreateIsNull(LaneID,
"warp_master");
3819 Builder.CreateCondBr(IsWarpMaster, ThenBB, ElseBB);
3823 auto *RedListArrayTy =
3826 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3828 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3829 {ConstantInt::get(IndexTy, 0),
3830 ConstantInt::get(IndexTy, En.index())});
3834 if (IsByRefElem && RI.DataPtrPtrGen) {
3836 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
3839 return GenRes.takeError();
3850 ArrayTy, TransferMedium, {
Builder.getInt64(0), WarpID});
3855 Builder.CreateStore(Elem, MediumPtr,
3867 omp::Directive::OMPD_unknown,
3871 return BarrierIP2.takeError();
3878 Value *NumWarpsVal =
3881 Value *IsActiveThread =
3882 Builder.CreateICmpULT(GPUThreadID, NumWarpsVal,
"is_active_thread");
3883 Builder.CreateCondBr(IsActiveThread, W0ThenBB, W0ElseBB);
3890 ArrayTy, TransferMedium, {
Builder.getInt64(0), GPUThreadID});
3892 Value *TargetElemPtrPtr =
3893 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3894 {ConstantInt::get(IndexTy, 0),
3895 ConstantInt::get(IndexTy, En.index())});
3896 Value *TargetElemPtrVal =
3898 Value *TargetElemPtr = TargetElemPtrVal;
3900 if (IsByRefElem && RI.DataPtrPtrGen) {
3902 RI.DataPtrPtrGen(
Builder.saveIP(), TargetElemPtr, TargetElemPtr);
3905 return GenRes.takeError();
3907 TargetElemPtr =
Builder.CreateLoad(
Builder.getPtrTy(), TargetElemPtr);
3915 Value *SrcMediumValue =
3916 Builder.CreateLoad(CType, SrcMediumPtrVal,
true);
3917 Builder.CreateStore(SrcMediumValue, TargetElemPtr);
3927 Cnt, ConstantInt::get(
Builder.getInt32Ty(), 1));
3928 Builder.CreateStore(Cnt, CntAddr,
false);
3930 auto *CurFn =
Builder.GetInsertBlock()->getParent();
3934 RealTySize %= TySize;
3943Expected<Function *> OpenMPIRBuilder::emitShuffleAndReduceFunction(
3946 LLVMContext &Ctx =
M.getContext();
3947 IRBuilder<>::InsertPointGuard IPG(
Builder);
3948 FunctionType *FuncTy =
3950 {Builder.getPtrTy(), Builder.getInt16Ty(),
3951 Builder.getInt16Ty(), Builder.getInt16Ty()},
3955 "_omp_reduction_shuffle_and_reduce_func", &
M);
3966 Builder.SetInsertPoint(EntryBB);
3978 Type *ReduceListArgType = ReduceListArg->
getType();
3982 ReduceListArgType,
nullptr, ReduceListArg->
getName() +
".addr");
3983 Value *LaneIdAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
3984 LaneIDArg->
getName() +
".addr");
3986 LaneIDArgType,
nullptr, RemoteLaneOffsetArg->
getName() +
".addr");
3987 Value *AlgoVerAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
3988 AlgoVerArg->
getName() +
".addr");
3995 RedListArrayTy,
nullptr,
".omp.reduction.remote_reduce_list");
3997 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3998 ReduceListAlloca, ReduceListArgType,
3999 ReduceListAlloca->
getName() +
".ascast");
4000 Value *LaneIdAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4001 LaneIdAlloca, LaneIDArgPtrType, LaneIdAlloca->
getName() +
".ascast");
4002 Value *RemoteLaneOffsetAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4003 RemoteLaneOffsetAlloca, LaneIDArgPtrType,
4004 RemoteLaneOffsetAlloca->
getName() +
".ascast");
4005 Value *AlgoVerAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4006 AlgoVerAlloca, LaneIDArgPtrType, AlgoVerAlloca->
getName() +
".ascast");
4007 Value *RemoteListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4008 RemoteReductionListAlloca,
Builder.getPtrTy(),
4009 RemoteReductionListAlloca->
getName() +
".ascast");
4011 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
4012 Builder.CreateStore(LaneIDArg, LaneIdAddrCast);
4013 Builder.CreateStore(RemoteLaneOffsetArg, RemoteLaneOffsetAddrCast);
4014 Builder.CreateStore(AlgoVerArg, AlgoVerAddrCast);
4016 Value *ReduceList =
Builder.CreateLoad(ReduceListArgType, ReduceListAddrCast);
4017 Value *LaneId =
Builder.CreateLoad(LaneIDArgType, LaneIdAddrCast);
4018 Value *RemoteLaneOffset =
4019 Builder.CreateLoad(LaneIDArgType, RemoteLaneOffsetAddrCast);
4020 Value *AlgoVer =
Builder.CreateLoad(LaneIDArgType, AlgoVerAddrCast);
4027 Error EmitRedLsCpRes = emitReductionListCopy(
4029 ReduceList, RemoteListAddrCast, IsByRef,
4030 {RemoteLaneOffset,
nullptr,
nullptr});
4033 return EmitRedLsCpRes;
4058 Value *LaneComp =
Builder.CreateICmpULT(LaneId, RemoteLaneOffset);
4063 Value *Algo2AndLaneIdComp =
Builder.CreateAnd(Algo2, LaneIdComp);
4064 Value *RemoteOffsetComp =
4066 Value *CondAlgo2 =
Builder.CreateAnd(Algo2AndLaneIdComp, RemoteOffsetComp);
4067 Value *CA0OrCA1 =
Builder.CreateOr(CondAlgo0, CondAlgo1);
4068 Value *CondReduce =
Builder.CreateOr(CA0OrCA1, CondAlgo2);
4074 Builder.CreateCondBr(CondReduce, ThenBB, ElseBB);
4076 Value *LocalReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4077 ReduceList,
Builder.getPtrTy());
4078 Value *RemoteReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4079 RemoteListAddrCast,
Builder.getPtrTy());
4081 ->addFnAttr(Attribute::NoUnwind);
4092 Value *LaneIdGtOffset =
Builder.CreateICmpUGE(LaneId, RemoteLaneOffset);
4093 Value *CondCopy =
Builder.CreateAnd(Algo1, LaneIdGtOffset);
4098 Builder.CreateCondBr(CondCopy, CpyThenBB, CpyElseBB);
4102 EmitRedLsCpRes = emitReductionListCopy(
4104 RemoteListAddrCast, ReduceList, IsByRef);
4107 return EmitRedLsCpRes;
4122OpenMPIRBuilder::generateReductionDescriptor(
4124 Type *DescriptorType,
4130 Value *DescriptorSize =
4131 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(DescriptorType));
4133 DescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4134 SrcDescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4138 Value *DataPtrField;
4140 DataPtrPtrGen(
Builder.saveIP(), DescriptorAddr, DataPtrField);
4143 return GenResult.takeError();
4146 DataPtr,
Builder.getPtrTy(),
".ascast"),
4152Expected<Value *> OpenMPIRBuilder::createReductionDescriptorCopy(
4154 Value *SrcDescriptorAddr,
Type *DescriptorPtrTy,
const Twine &Name) {
4158 AllocaInst *DescriptorAlloca =
4159 Builder.CreateAlloca(RI.ByRefAllocatedType,
nullptr, Name);
4161 M.getDataLayout().getPrefTypeAlign(RI.ByRefAllocatedType));
4162 Value *DescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4163 DescriptorAlloca, DescriptorPtrTy,
4164 DescriptorAlloca->
getName() +
".ascast");
4169 generateReductionDescriptor(DescriptorAddr, DataPtr, SrcDescriptorAddr,
4170 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
4172 return GenResult.takeError();
4174 return DescriptorAddr;
4177Expected<Function *> OpenMPIRBuilder::emitListToGlobalCopyFunction(
4180 IRBuilder<>::InsertPointGuard IPG(
Builder);
4181 LLVMContext &Ctx =
M.getContext();
4184 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4188 "_omp_reduction_list_to_global_copy_func", &
M);
4195 Builder.SetInsertPoint(EntryBlock);
4206 BufferArg->
getName() +
".addr");
4210 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4211 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4212 BufferArgAlloca,
Builder.getPtrTy(),
4213 BufferArgAlloca->
getName() +
".ascast");
4214 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4215 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4216 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4217 ReduceListArgAlloca,
Builder.getPtrTy(),
4218 ReduceListArgAlloca->
getName() +
".ascast");
4220 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4221 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4222 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4224 Value *LocalReduceList =
4226 Value *BufferArgVal =
4230 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4231 for (
auto En :
enumerate(ReductionInfos)) {
4233 auto *RedListArrayTy =
4237 RedListArrayTy, LocalReduceList,
4238 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4244 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferArgVal, Idxs);
4246 ReductionsBufferTy, BufferVD, 0, En.index());
4248 switch (RI.EvaluationKind) {
4250 Value *TargetElement;
4252 if (IsByRef.
empty() || !IsByRef[En.index()]) {
4253 TargetElement =
Builder.CreateLoad(RI.ElementType, ElemPtr);
4255 if (RI.DataPtrPtrGen) {
4257 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
4260 return GenResult.takeError();
4264 TargetElement =
Builder.CreateLoad(RI.ByRefElementType, ElemPtr);
4267 Builder.CreateStore(TargetElement, GlobVal);
4271 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4272 RI.ElementType, ElemPtr, 0, 0,
".realp");
4274 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
4276 RI.ElementType, ElemPtr, 0, 1,
".imagp");
4278 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
4280 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4281 RI.ElementType, GlobVal, 0, 0,
".realp");
4282 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4283 RI.ElementType, GlobVal, 0, 1,
".imagp");
4284 Builder.CreateStore(SrcReal, DestRealPtr);
4285 Builder.CreateStore(SrcImg, DestImgPtr);
4290 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(RI.ElementType));
4292 GlobVal,
M.getDataLayout().getPrefTypeAlign(RI.ElementType), ElemPtr,
4293 M.getDataLayout().getPrefTypeAlign(RI.ElementType), SizeVal,
false);
4303Expected<Function *> OpenMPIRBuilder::emitListToGlobalReduceFunction(
4306 IRBuilder<>::InsertPointGuard IPG(
Builder);
4307 LLVMContext &Ctx =
M.getContext();
4310 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4314 "_omp_reduction_list_to_global_reduce_func", &
M);
4321 Builder.SetInsertPoint(EntryBlock);
4332 BufferArg->
getName() +
".addr");
4336 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4337 auto *RedListArrayTy =
4342 Value *LocalReduceList =
4343 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4347 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4348 BufferArgAlloca,
Builder.getPtrTy(),
4349 BufferArgAlloca->
getName() +
".ascast");
4350 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4351 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4352 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4353 ReduceListArgAlloca,
Builder.getPtrTy(),
4354 ReduceListArgAlloca->
getName() +
".ascast");
4355 Value *LocalReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4356 LocalReduceList,
Builder.getPtrTy(),
4357 LocalReduceList->
getName() +
".ascast");
4359 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4360 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4361 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4366 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4367 for (
auto En :
enumerate(ReductionInfos)) {
4370 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4371 RedListArrayTy, LocalReduceListAddrCast,
4372 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4374 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4376 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4377 ReductionsBufferTy, BufferVD, 0, En.index());
4379 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4383 Value *SrcElementPtrPtr =
4384 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
4385 {ConstantInt::get(IndexTy, 0),
4386 ConstantInt::get(IndexTy, En.index())});
4387 Value *SrcDescriptorAddr =
4391 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4392 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4396 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4398 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4406 ->addFnAttr(Attribute::NoUnwind);
4411Expected<Function *> OpenMPIRBuilder::emitGlobalToListCopyFunction(
4414 IRBuilder<>::InsertPointGuard IPG(
Builder);
4415 LLVMContext &Ctx =
M.getContext();
4418 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4422 "_omp_reduction_global_to_list_copy_func", &
M);
4429 Builder.SetInsertPoint(EntryBlock);
4440 BufferArg->
getName() +
".addr");
4444 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4445 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4446 BufferArgAlloca,
Builder.getPtrTy(),
4447 BufferArgAlloca->
getName() +
".ascast");
4448 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4449 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4450 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4451 ReduceListArgAlloca,
Builder.getPtrTy(),
4452 ReduceListArgAlloca->
getName() +
".ascast");
4453 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4454 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4455 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4457 Value *LocalReduceList =
4462 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4463 for (
auto En :
enumerate(ReductionInfos)) {
4464 const OpenMPIRBuilder::ReductionInfo &RI = En.value();
4465 auto *RedListArrayTy =
4469 RedListArrayTy, LocalReduceList,
4470 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4475 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4476 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4477 ReductionsBufferTy, BufferVD, 0, En.index());
4483 if (!IsByRef.
empty() && IsByRef[En.index()]) {
4490 return GenResult.takeError();
4496 Value *TargetElement =
Builder.CreateLoad(ElemType, GlobValPtr);
4497 Builder.CreateStore(TargetElement, ElemPtr);
4501 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4510 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4512 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4514 Builder.CreateStore(SrcReal, DestRealPtr);
4515 Builder.CreateStore(SrcImg, DestImgPtr);
4522 ElemPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4523 GlobValPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4534Expected<Function *> OpenMPIRBuilder::emitGlobalToListReduceFunction(
4537 IRBuilder<>::InsertPointGuard IPG(
Builder);
4538 LLVMContext &Ctx =
M.getContext();
4541 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4545 "_omp_reduction_global_to_list_reduce_func", &
M);
4552 Builder.SetInsertPoint(EntryBlock);
4563 BufferArg->
getName() +
".addr");
4567 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4573 Value *LocalReduceList =
4574 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4578 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4579 BufferArgAlloca,
Builder.getPtrTy(),
4580 BufferArgAlloca->
getName() +
".ascast");
4581 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4582 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4583 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4584 ReduceListArgAlloca,
Builder.getPtrTy(),
4585 ReduceListArgAlloca->
getName() +
".ascast");
4586 Value *ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4587 LocalReduceList,
Builder.getPtrTy(),
4588 LocalReduceList->
getName() +
".ascast");
4590 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4591 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4592 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4597 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4598 for (
auto En :
enumerate(ReductionInfos)) {
4601 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4602 RedListArrayTy, ReductionList,
4603 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4606 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4607 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4608 ReductionsBufferTy, BufferVD, 0, En.index());
4610 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4612 Value *ReduceListVal =
4614 Value *SrcElementPtrPtr =
4615 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceListVal,
4616 {ConstantInt::get(IndexTy, 0),
4617 ConstantInt::get(IndexTy, En.index())});
4618 Value *SrcDescriptorAddr =
4622 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4623 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4627 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4629 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4637 ->addFnAttr(Attribute::NoUnwind);
4642std::string OpenMPIRBuilder::getReductionFuncName(StringRef Name)
const {
4643 std::string Suffix =
4645 return (Name + Suffix).str();
4648Expected<Function *> OpenMPIRBuilder::createReductionFunction(
4651 AttributeList FuncAttrs) {
4652 IRBuilder<>::InsertPointGuard IPG(
Builder);
4654 {Builder.getPtrTy(), Builder.getPtrTy()},
4656 std::string
Name = getReductionFuncName(ReducerName);
4665 Builder.SetInsertPoint(EntryBB);
4670 Value *LHSArrayPtr =
nullptr;
4671 Value *RHSArrayPtr =
nullptr;
4678 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
4680 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
4681 Value *LHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4682 LHSAlloca, Arg0Type, LHSAlloca->
getName() +
".ascast");
4683 Value *RHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4684 RHSAlloca, Arg1Type, RHSAlloca->
getName() +
".ascast");
4685 Builder.CreateStore(Arg0, LHSAddrCast);
4686 Builder.CreateStore(Arg1, RHSAddrCast);
4687 LHSArrayPtr =
Builder.CreateLoad(Arg0Type, LHSAddrCast);
4688 RHSArrayPtr =
Builder.CreateLoad(Arg1Type, RHSAddrCast);
4692 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4694 for (
auto En :
enumerate(ReductionInfos)) {
4697 RedArrayTy, RHSArrayPtr,
4698 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4700 Value *RHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4701 RHSI8Ptr, RI.PrivateVariable->getType(),
4702 RHSI8Ptr->
getName() +
".ascast");
4705 RedArrayTy, LHSArrayPtr,
4706 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4708 Value *LHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4709 LHSI8Ptr, RI.Variable->getType(), LHSI8Ptr->
getName() +
".ascast");
4718 if (!IsByRef.
empty() && !IsByRef[En.index()]) {
4719 LHS =
Builder.CreateLoad(RI.ElementType, LHSPtr);
4720 RHS =
Builder.CreateLoad(RI.ElementType, RHSPtr);
4727 return AfterIP.takeError();
4728 if (!
Builder.GetInsertBlock())
4729 return ReductionFunc;
4733 if (!IsByRef.
empty() && !IsByRef[En.index()])
4734 Builder.CreateStore(Reduced, LHSPtr);
4739 for (
auto En :
enumerate(ReductionInfos)) {
4740 unsigned Index = En.index();
4742 Value *LHSFixupPtr, *RHSFixupPtr;
4743 Builder.restoreIP(RI.ReductionGenClang(
4744 Builder.saveIP(), Index, &LHSFixupPtr, &RHSFixupPtr, ReductionFunc));
4749 LHSPtrs[Index], [ReductionFunc](
const Use &U) {
4754 RHSPtrs[Index], [ReductionFunc](
const Use &U) {
4768 return ReductionFunc;
4776 assert(RI.Variable &&
"expected non-null variable");
4777 assert(RI.PrivateVariable &&
"expected non-null private variable");
4778 assert((RI.ReductionGen || RI.ReductionGenClang) &&
4779 "expected non-null reduction generator callback");
4782 RI.Variable->getType() == RI.PrivateVariable->getType() &&
4783 "expected variables and their private equivalents to have the same "
4786 assert(RI.Variable->getType()->isPointerTy() &&
4787 "expected variables to be pointers");
4804 ArrayRef<bool> IsByRef,
bool IsNoWait,
bool IsTeamsReduction,
bool IsSPMD,
4806 Value *SrcLocInfo) {
4821 if (ReductionInfos.
size() == 0)
4835 AttrBuilder AttrBldr(Ctx);
4837 AttrBldr.addAttribute(Attr);
4838 AttrBldr.removeAttribute(Attribute::OptimizeNone);
4839 FuncAttrs = FuncAttrs.addFnAttributes(Ctx, AttrBldr);
4842 Builder.GetInsertBlock()->getParent()->getName(), ReductionInfos, IsByRef,
4844 if (!ReductionResult)
4846 Function *ReductionFunc = *ReductionResult;
4849 if (GridValue.has_value())
4850 Config.setGridValue(GridValue.value());
4865 Builder.getPtrTy(
M.getDataLayout().getProgramAddressSpace());
4867 Value *ReductionList;
4871 Value *ReductionListAlloca =
4872 Builder.CreateAlloca(RedArrayTy,
nullptr,
".omp.reduction.red_list");
4873 ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4874 ReductionListAlloca, PtrTy, ReductionListAlloca->
getName() +
".ascast");
4877 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4878 for (
auto En :
enumerate(ReductionInfos)) {
4881 RedArrayTy, ReductionList,
4882 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4885 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
4890 Builder.CreatePointerBitCastOrAddrSpaceCast(PrivateVar, PtrTy);
4891 Builder.CreateStore(CastElem, ElemPtr);
4894 ReductionInfos, ReductionFunc, FuncAttrs, IsByRef);
4900 emitInterWarpCopyFunction(
Loc, ReductionInfos, FuncAttrs, IsByRef);
4905 Value *RL =
Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList, PtrTy);
4914 unsigned MaxDataSize = 0;
4916 for (
auto En :
enumerate(ReductionInfos)) {
4920 Type *RedTypeArg = (!IsByRef.
empty() && IsByRef[En.index()])
4921 ? En.value().ByRefElementType
4922 : En.value().ElementType;
4923 auto Size =
M.getDataLayout().getTypeStoreSize(RedTypeArg);
4924 if (
Size > MaxDataSize)
4928 Value *ReductionDataSize =
4929 Builder.getInt64(MaxDataSize * ReductionInfos.
size());
4933 Function *CopyScratchToListFunc =
nullptr;
4935 Value *ScratchForCopyBack =
nullptr;
4938 Value *RLForCopyBack = RL;
4940 bool IsAtomicReduction =
4943 if (!IsTeamsReduction) {
4944 Value *SarFuncCast =
4945 Builder.CreatePointerBitCastOrAddrSpaceCast(*SarFunc, FuncPtrTy);
4947 Builder.CreatePointerBitCastOrAddrSpaceCast(WcFunc, FuncPtrTy);
4948 Value *Args[] = {SrcLocInfo, ReductionDataSize, RL, SarFuncCast,
4951 RuntimeFunction::OMPRTL___kmpc_nvptx_parallel_reduce_nowait_v2);
4953 }
else if (IsAtomicReduction) {
4957 RuntimeFunction::OMPRTL___kmpc_is_team_main_thread);
4961 Ctx, ReductionTypeArgs,
"struct._globalized_locals_ty");
4964 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
4969 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
4974 ReductionInfos, ReductionFunc, ReductionsBufferTy, FuncAttrs, IsByRef);
4995 Value *RuntimeRL = RL;
4998 Value *PerThreadScratch;
5004 Value *PerThreadScratchAlloca =
5005 Builder.CreateAlloca(ReductionsBufferTy,
nullptr,
5006 ".omp.reduction.scratch");
5007 PerThreadScratch =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5008 PerThreadScratchAlloca, PtrTy,
5009 PerThreadScratchAlloca->
getName() +
".ascast");
5012 Value *PerThreadRedListAlloca =
5013 Builder.CreateAlloca(RedArrayTy,
nullptr,
5014 ".omp.reduction.per_thread_red_list");
5015 RuntimeRL =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5016 PerThreadRedListAlloca, PtrTy,
5017 PerThreadRedListAlloca->
getName() +
".ascast");
5022 for (
auto En :
enumerate(ReductionInfos)) {
5024 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
5027 ReductionsBufferTy, PerThreadScratch, 0, En.index());
5028 Value *Slot =
Builder.CreateConstInBoundsGEP2_32(RedArrayTy, RuntimeRL,
5031 Value *RuntimeListEntry = FieldPtr;
5033 Value *SrcDescriptor =
5036 AllocaIP, RI, FieldPtr, SrcDescriptor, PtrTy);
5039 RuntimeListEntry = *Descriptor;
5041 Builder.CreateStore(RuntimeListEntry, Slot);
5047 Type *CopyArg0Ty = (*LtGCFunc)->getFunctionType()->getParamType(0);
5048 Type *CopyArg2Ty = (*LtGCFunc)->getFunctionType()->getParamType(2);
5049 ScratchForCopyBack =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5050 PerThreadScratch, CopyArg0Ty);
5052 Builder.CreatePointerBitCastOrAddrSpaceCast(RL, CopyArg2Ty);
5060 *LtGCFunc, {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
5061 CopyScratchToListFunc = *GtLCFunc;
5064 Value *Args3[] = {SrcLocInfo, RuntimeRL, *SarFunc, WcFunc,
5065 *LtGCFunc, *GtLCFunc, *GtLRFunc};
5068 RuntimeFunction::OMPRTL___kmpc_gpu_xteam_reduce_nowait);
5088 if (ScratchForCopyBack) {
5091 CopyScratchToListFunc,
5092 {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
5096 for (
auto En :
enumerate(ReductionInfos)) {
5102 if (IsAtomicReduction) {
5118 Value *LHSPtr, *RHSPtr;
5120 &LHSPtr, &RHSPtr, CurFunc));
5126 RedValue =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5128 if (RHSPtr->
getType() != RHS->getType())
5130 Builder.CreatePointerBitCastOrAddrSpaceCast(RHS, RHSPtr->
getType());
5141 if (IsByRef.
empty() || !IsByRef[En.index()]) {
5143 "red.value." +
Twine(En.index()));
5154 if (!IsByRef.
empty() && !IsByRef[En.index()])
5159 if (ContinuationBlock) {
5160 Builder.CreateBr(ContinuationBlock);
5161 Builder.SetInsertPoint(ContinuationBlock);
5163 Config.setEmitLLVMUsed();
5174 ".omp.reduction.func", &M);
5185 Builder.SetInsertPoint(ReductionFuncBlock);
5187 Value *LHSArrayPtr =
nullptr;
5188 Value *RHSArrayPtr =
nullptr;
5199 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
5201 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
5202 Value *LHSAddrCast =
5203 Builder.CreatePointerBitCastOrAddrSpaceCast(LHSAlloca, Arg0Type);
5204 Value *RHSAddrCast =
5205 Builder.CreatePointerBitCastOrAddrSpaceCast(RHSAlloca, Arg1Type);
5206 Builder.CreateStore(Arg0, LHSAddrCast);
5207 Builder.CreateStore(Arg1, RHSAddrCast);
5208 LHSArrayPtr = Builder.CreateLoad(Arg0Type, LHSAddrCast);
5209 RHSArrayPtr = Builder.CreateLoad(Arg1Type, RHSAddrCast);
5211 LHSArrayPtr = ReductionFunc->
getArg(0);
5212 RHSArrayPtr = ReductionFunc->
getArg(1);
5215 unsigned NumReductions = ReductionInfos.
size();
5218 for (
auto En :
enumerate(ReductionInfos)) {
5220 Value *LHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5221 RedArrayTy, LHSArrayPtr, 0, En.index());
5222 Value *LHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), LHSI8PtrPtr);
5223 Value *LHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5226 Value *RHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5227 RedArrayTy, RHSArrayPtr, 0, En.index());
5228 Value *RHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), RHSI8PtrPtr);
5229 Value *RHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5238 Builder.restoreIP(*AfterIP);
5240 if (!Builder.GetInsertBlock())
5244 if (!IsByRef[En.index()])
5245 Builder.CreateStore(Reduced, LHSPtr);
5247 Builder.CreateRetVoid();
5254 bool IsNoWait,
bool IsTeamsReduction) {
5258 IsByRef, IsNoWait, IsTeamsReduction);
5265 if (ReductionInfos.
size() == 0)
5275 unsigned NumReductions = ReductionInfos.
size();
5277 Builder.SetInsertPoint(AllocaIP.getNodeParent()->getTerminator());
5278 Value *RedArray =
Builder.CreateAlloca(RedArrayTy,
nullptr,
"red.array");
5285 for (
auto En :
enumerate(ReductionInfos)) {
5286 unsigned Index = En.index();
5288 Value *RedArrayElemPtr =
Builder.CreateConstInBoundsGEP2_64(
5289 RedArrayTy, RedArray, 0, Index,
"red.array.elem." +
Twine(Index));
5296 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
5306 ? IdentFlag::OMP_IDENT_FLAG_ATOMIC_REDUCE
5311 unsigned RedArrayByteSize =
DL.getTypeStoreSize(RedArrayTy);
5312 Constant *RedArraySize = ConstantInt::get(IndexTy, RedArrayByteSize);
5314 Value *Lock = getOMPCriticalRegionLock(
".reduction");
5316 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_reduce_nowait
5317 : RuntimeFunction::OMPRTL___kmpc_reduce);
5320 {Ident, ThreadId, NumVariables, RedArraySize,
5321 RedArray, ReductionFunc, Lock},
5332 Builder.CreateSwitch(ReduceCall, ContinuationBlock, 2);
5333 Switch->addCase(
Builder.getInt32(1), NonAtomicRedBlock);
5334 Switch->addCase(
Builder.getInt32(2), AtomicRedBlock);
5339 Builder.SetInsertPoint(NonAtomicRedBlock);
5340 for (
auto En :
enumerate(ReductionInfos)) {
5346 if (!IsByRef[En.index()]) {
5348 "red.value." +
Twine(En.index()));
5350 Value *PrivateRedValue =
5352 "red.private.value." +
Twine(En.index()));
5360 if (!
Builder.GetInsertBlock())
5363 if (!IsByRef[En.index()])
5367 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_end_reduce_nowait
5368 : RuntimeFunction::OMPRTL___kmpc_end_reduce);
5370 Builder.CreateBr(ContinuationBlock);
5375 Builder.SetInsertPoint(AtomicRedBlock);
5376 if (CanGenerateAtomic &&
llvm::none_of(IsByRef, [](
bool P) {
return P; })) {
5383 if (!
Builder.GetInsertBlock())
5386 Builder.CreateBr(ContinuationBlock);
5399 if (!
Builder.GetInsertBlock())
5402 Builder.SetInsertPoint(ContinuationBlock);
5413 Directive OMPD = Directive::OMPD_master;
5418 Value *Args[] = {Ident, ThreadId};
5426 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5438 Directive OMPD = Directive::OMPD_masked;
5444 Value *ArgsEnd[] = {Ident, ThreadId};
5452 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5462 Call->setDoesNotThrow();
5477 bool IsInclusive,
ScanInfo *ScanRedInfo) {
5479 llvm::Error Err = emitScanBasedDirectiveDeclsIR(AllocaIP, ScanVars,
5480 ScanVarsType, ScanRedInfo);
5491 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5494 Type *DestTy = ScanVarsType[i];
5495 Value *Val =
Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5498 Builder.CreateStore(Src, Val);
5503 Builder.GetInsertBlock()->getParent());
5506 IV = ScanRedInfo->
IV;
5509 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5512 Type *DestTy = ScanVarsType[i];
5514 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5516 Builder.CreateStore(Src, ScanVars[i]);
5530 Builder.GetInsertBlock()->getParent());
5535Error OpenMPIRBuilder::emitScanBasedDirectiveDeclsIR(
5539 Builder.restoreIP(AllocaIP);
5541 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5543 Builder.CreateAlloca(Builder.getPtrTy(),
nullptr,
"vla");
5550 Builder.restoreIP(CodeGenIP);
5552 Builder.CreateAdd(ScanRedInfo->
Span, Builder.getInt32(1));
5553 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5555 Value *Allocsize = Builder.CreateTypeSize(
5556 IntPtrTy, M.getDataLayout().getTypeAllocSize(ScanVarsType[i]));
5558 Builder.CreateMalloc(
IntPtrTy, Allocsize, AllocSpan,
nullptr,
"arr");
5559 Builder.CreateStore(Buff, (*(ScanRedInfo->
ScanBuffPtrs))[ScanVars[i]]);
5586Error OpenMPIRBuilder::emitScanBasedDirectiveFinalsIR(
5592 Value *PrivateVar = RedInfo.PrivateVariable;
5593 Value *OrigVar = RedInfo.Variable;
5597 Type *SrcTy = RedInfo.ElementType;
5602 Builder.CreateStore(Src, OrigVar);
5663 llvm::ConstantInt::get(ScanRedInfo->
Span->
getType(), 1));
5664 Builder.SetInsertPoint(InputBB);
5667 Builder.SetInsertPoint(LoopBB);
5683 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5685 Builder.SetInsertPoint(InnerLoopBB);
5689 Value *ReductionVal = RedInfo.PrivateVariable;
5692 Type *DestTy = RedInfo.ElementType;
5695 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5698 Builder.CreateInBoundsGEP(DestTy, Buff, OffsetIval,
"arrayOffset");
5703 RedInfo.ReductionGen(
Builder.saveIP(), LHS, RHS, Result);
5706 Builder.CreateStore(Result, LHSPtr);
5709 IVal, llvm::ConstantInt::get(
Builder.getInt32Ty(), 1));
5711 CmpI =
Builder.CreateICmpUGE(NextIVal, Pow2K);
5712 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5715 Counter, llvm::ConstantInt::get(Counter->
getType(), 1));
5721 Builder.CreateCondBr(Cmp, LoopBB, ExitBB);
5742 Error Err = emitScanBasedDirectiveFinalsIR(ReductionInfos, ScanRedInfo);
5749Error OpenMPIRBuilder::emitScanBasedDirectiveIR(
5761 Error Err = InputLoopGen();
5772 Error Err = ScanLoopGen(Builder);
5779void OpenMPIRBuilder::createScanBBs(ScanInfo *ScanRedInfo) {
5816 Builder.SetInsertPoint(Preheader);
5819 Builder.SetInsertPoint(Header);
5820 PHINode *IndVarPHI =
Builder.CreatePHI(IndVarTy, 2,
"omp_" + Name +
".iv");
5821 IndVarPHI->
addIncoming(ConstantInt::get(IndVarTy, 0), Preheader);
5826 Builder.CreateICmpULT(IndVarPHI, TripCount,
"omp_" + Name +
".cmp");
5827 Builder.CreateCondBr(Cmp, Body, Exit);
5832 Builder.SetInsertPoint(Latch);
5842 bool HasNSW =
Config.hasNoSignedWrap();
5845 unsigned BitWidth = CI->getType()->getIntegerBitWidth();
5847 if (CI->getValue().ugt(SignedMax))
5849 }
else if (IsCollapsed) {
5854 Builder.CreateAdd(IndVarPHI, ConstantInt::get(IndVarTy, 1),
5855 "omp_" + Name +
".next",
true, HasNSW);
5866 CL->Header = Header;
5885 NextBB, NextBB, Name);
5917 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
5926 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
5927 ScanRedInfo->
Span = TripCount;
5933 ScanRedInfo->
IV =
IV;
5934 createScanBBs(ScanRedInfo);
5937 assert(Terminator->getNumSuccessors() == 1);
5938 BasicBlock *ContinueBlock = Terminator->getSuccessor(0);
5941 Builder.GetInsertBlock()->getParent());
5944 Builder.GetInsertBlock()->getParent());
5945 Builder.CreateBr(ContinueBlock);
5951 const auto &&InputLoopGen = [&]() ->
Error {
5954 InclusiveStop, ComputeIP, Name,
true, ScanRedInfo);
5958 Builder.restoreIP((*LoopInfo)->getAfterIP());
5964 InclusiveStop, ComputeIP, Name,
true, ScanRedInfo);
5968 Builder.restoreIP((*LoopInfo)->getAfterIP());
5972 Error Err = emitScanBasedDirectiveIR(InputLoopGen, ScanLoopGen, ScanRedInfo);
5980 bool IsSigned,
bool InclusiveStop,
const Twine &Name) {
5990 assert(IndVarTy == Stop->
getType() &&
"Stop type mismatch");
5991 assert(IndVarTy == Step->
getType() &&
"Step type mismatch");
5995 ConstantInt *Zero = ConstantInt::get(IndVarTy, 0);
6011 Incr =
Builder.CreateSelect(IsNeg,
Builder.CreateNeg(Step), Step);
6014 Span =
Builder.CreateSub(UB, LB,
"",
false,
true);
6018 Span =
Builder.CreateSub(Stop, Start,
"",
true);
6023 Value *CountIfLooping;
6024 if (InclusiveStop) {
6025 CountIfLooping =
Builder.CreateAdd(
Builder.CreateUDiv(Span, Incr), One);
6031 CountIfLooping =
Builder.CreateSelect(OneCmp, One, CountIfTwo);
6034 return Builder.CreateSelect(ZeroCmp, Zero, CountIfLooping,
6035 "omp_" + Name +
".tripcount");
6040 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
6047 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
6052 Config.hasNoSignedWrap());
6053 Value *IndVar =
Builder.CreateAdd(Span, Start,
"",
false,
6054 Config.hasNoSignedWrap());
6056 ScanRedInfo->
IV = IndVar;
6057 return BodyGenCB(
Builder.saveIP(), IndVar);
6063 Builder.getCurrentDebugLocation());
6074 unsigned Bitwidth = Ty->getIntegerBitWidth();
6077 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_4u);
6080 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_8u);
6090 unsigned Bitwidth = Ty->getIntegerBitWidth();
6093 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_4u);
6096 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_8u);
6104 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6106 "Require dedicated allocate IP");
6112 uint32_t SrcLocStrSize;
6116 case WorksharingLoopType::ForStaticLoop:
6117 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6119 case WorksharingLoopType::DistributeStaticLoop:
6120 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6122 case WorksharingLoopType::DistributeForStaticLoop:
6123 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
6130 Type *IVTy =
IV->getType();
6131 FunctionCallee StaticInit =
6132 LoopType == WorksharingLoopType::DistributeForStaticLoop
6135 FunctionCallee StaticFini =
6140 AllocaIP.getNodeParent()->getFirstNonPHIOrDbgOrAlloca());
6143 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6144 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
6145 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
6146 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
6155 Constant *One = ConstantInt::get(IVTy, 1);
6156 Builder.CreateStore(Zero, PLowerBound);
6158 Builder.CreateStore(UpperBound, PUpperBound);
6159 Builder.CreateStore(One, PStride);
6165 (LoopType == WorksharingLoopType::DistributeStaticLoop)
6166 ? OMPScheduleType::OrderedDistribute
6169 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6173 auto BuildInitCall = [LoopType, SrcLoc, ThreadNum, PLastIter, PLowerBound,
6174 PUpperBound, IVTy, PStride, One,
Zero, StaticInit,
6177 PLowerBound, PUpperBound});
6178 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
6179 Value *PDistUpperBound =
6180 Builder.CreateAlloca(IVTy,
nullptr,
"p.distupperbound");
6181 Args.push_back(PDistUpperBound);
6186 BuildInitCall(SchedulingType,
Builder);
6187 if (HasDistSchedule &&
6188 LoopType != WorksharingLoopType::DistributeStaticLoop) {
6189 Constant *DistScheduleSchedType = ConstantInt::get(
6194 BuildInitCall(DistScheduleSchedType,
Builder);
6197 Value *InclusiveUpperBound =
Builder.CreateLoad(IVTy, PUpperBound);
6199 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One);
6200 CLI->setTripCount(TripCount);
6206 CLI->mapIndVar([&](Instruction *OldIV) ->
Value * {
6210 Config.hasNoSignedWrap());
6221 omp::Directive::OMPD_for,
false,
6224 return BarrierIP.takeError();
6251 Reachable.insert(
Block);
6265OpenMPIRBuilder::applyStaticChunkedWorkshareLoop(
6269 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6270 assert((ChunkSize || DistScheduleChunkSize) &&
"Chunk size is required");
6275 Type *IVTy =
IV->getType();
6277 "Max supported tripcount bitwidth is 64 bits");
6279 :
Type::getInt64Ty(Ctx);
6282 Constant *One = ConstantInt::get(InternalIVTy, 1);
6287 SmallVector<Instruction *> UIs;
6288 for (BasicBlock &BB : *
F)
6289 if (!BB.hasTerminator())
6290 UIs.
push_back(
new UnreachableInst(
F->getContext(), &BB));
6295 LoopInfo &&LI = LIA.
run(*
F,
FAM);
6296 for (Instruction *
I : UIs)
6297 I->eraseFromParent();
6300 if (ChunkSize || DistScheduleChunkSize)
6305 FunctionCallee StaticInit =
6307 FunctionCallee StaticFini =
6313 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6314 Value *PLowerBound =
6315 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.lowerbound");
6316 Value *PUpperBound =
6317 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.upperbound");
6318 Value *PStride =
Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.stride");
6327 ChunkSize ? ChunkSize : Zero, InternalIVTy,
"chunksize");
6328 Value *CastedDistScheduleChunkSize =
Builder.CreateZExtOrTrunc(
6329 DistScheduleChunkSize ? DistScheduleChunkSize : Zero, InternalIVTy,
6330 "distschedulechunksize");
6331 Value *CastedTripCount =
6332 Builder.CreateZExt(OrigTripCount, InternalIVTy,
"tripcount");
6335 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6337 ConstantInt::get(I32Type,
static_cast<int>(DistScheduleSchedType));
6338 Builder.CreateStore(Zero, PLowerBound);
6339 Value *OrigUpperBound =
Builder.CreateSub(CastedTripCount, One);
6340 Value *IsTripCountZero =
Builder.CreateICmpEQ(CastedTripCount, Zero);
6342 Builder.CreateSelect(IsTripCountZero, Zero, OrigUpperBound);
6343 Builder.CreateStore(UpperBound, PUpperBound);
6344 Builder.CreateStore(One, PStride);
6348 uint32_t SrcLocStrSize;
6351 if (DistScheduleSchedType != OMPScheduleType::None) {
6352 Flag |= OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6357 auto BuildInitCall = [StaticInit, SrcLoc, ThreadNum, PLastIter, PLowerBound,
6358 PUpperBound, PStride, One,
6359 this](
Value *SchedulingType,
Value *ChunkSize,
6362 StaticInit, {SrcLoc, ThreadNum,
6363 SchedulingType, PLastIter,
6364 PLowerBound, PUpperBound,
6368 BuildInitCall(SchedulingType, CastedChunkSize,
Builder);
6369 if (DistScheduleSchedType != OMPScheduleType::None &&
6370 SchedType != OMPScheduleType::OrderedDistributeChunked &&
6371 SchedType != OMPScheduleType::OrderedDistribute) {
6375 BuildInitCall(DistSchedulingType, CastedDistScheduleChunkSize,
Builder);
6379 Value *FirstChunkStart =
6380 Builder.CreateLoad(InternalIVTy, PLowerBound,
"omp_firstchunk.lb");
6381 Value *FirstChunkStop =
6382 Builder.CreateLoad(InternalIVTy, PUpperBound,
"omp_firstchunk.ub");
6383 Value *FirstChunkEnd =
Builder.CreateAdd(FirstChunkStop, One);
6385 Builder.CreateSub(FirstChunkEnd, FirstChunkStart,
"omp_chunk.range");
6386 Value *NextChunkStride =
6387 Builder.CreateLoad(InternalIVTy, PStride,
"omp_dispatch.stride");
6391 Value *DispatchCounter;
6399 DispatchCounter = Counter;
6402 FirstChunkStart, CastedTripCount, NextChunkStride,
6425 Value *ChunkEnd =
Builder.CreateAdd(DispatchCounter, ChunkRange);
6426 Value *IsLastChunk =
6427 Builder.CreateICmpUGE(ChunkEnd, CastedTripCount,
"omp_chunk.is_last");
6428 Value *CountUntilOrigTripCount =
6429 Builder.CreateSub(CastedTripCount, DispatchCounter);
6431 IsLastChunk, CountUntilOrigTripCount, ChunkRange,
"omp_chunk.tripcount");
6432 Value *BackcastedChunkTC =
6433 Builder.CreateTrunc(ChunkTripCount, IVTy,
"omp_chunk.tripcount.trunc");
6434 CLI->setTripCount(BackcastedChunkTC);
6439 Value *BackcastedDispatchCounter =
6440 Builder.CreateTrunc(DispatchCounter, IVTy,
"omp_dispatch.iv.trunc");
6441 CLI->mapIndVar([&](Instruction *) ->
Value * {
6443 return Builder.CreateAdd(
IV, BackcastedDispatchCounter);
6456 return AfterIP.takeError();
6471static FunctionCallee
6474 unsigned Bitwidth = Ty->getIntegerBitWidth();
6477 case WorksharingLoopType::ForStaticLoop:
6480 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_4u);
6483 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_8u);
6485 case WorksharingLoopType::DistributeStaticLoop:
6488 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_4u);
6491 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_8u);
6493 case WorksharingLoopType::DistributeForStaticLoop:
6496 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_4u);
6499 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_8u);
6502 if (Bitwidth != 32 && Bitwidth != 64) {
6514 Function &LoopBodyFn,
bool NoLoop) {
6525 if (LoopType == WorksharingLoopType::DistributeStaticLoop) {
6526 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6527 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6528 Builder.restoreIP(std::prev(InsertBlock->
end()));
6533 M, omp::RuntimeFunction::OMPRTL_omp_get_num_threads);
6534 Builder.restoreIP(std::prev(InsertBlock->
end()));
6538 Builder.CreateZExtOrTrunc(NumThreads, TripCountTy,
"num.threads.cast"));
6539 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6540 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
6541 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6542 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), NoLoop));
6544 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6568 Builder.restoreIP(Preheader->
end());
6571 Builder.CreateBr(CLI->
getExit());
6579 CleanUpInfo.
collectBlocks(RegionBlockSet, BlocksToBeRemoved);
6587 "Expected unique undroppable user of outlined function");
6589 assert(OutlinedFnCallInstruction &&
"Expected outlined function call");
6591 "Expected outlined function call to be located in loop preheader");
6593 if (OutlinedFnCallInstruction->
arg_size() > 1)
6600 LoopBodyArg, TripCount, OutlinedFn, NoLoop);
6602 for (
auto &ToBeDeletedItem : ToBeDeleted)
6603 ToBeDeletedItem->eraseFromParent();
6610 bool NeedsLastIter) {
6611 uint32_t SrcLocStrSize;
6615 if (NeedsLastIter) {
6618 AllocaInst *PLastIter =
6619 Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6623 Builder.CreateStore(ConstantInt::get(I32Type, 0), PLastIter);
6628 Builder.CreateSub(TripCount, ConstantInt::get(TripCount->
getType(), 1));
6631 Builder.CreateStore(
Builder.CreateZExt(IsLast, I32Type), PLastIter);
6636 case WorksharingLoopType::ForStaticLoop:
6637 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6639 case WorksharingLoopType::DistributeStaticLoop:
6640 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6642 case WorksharingLoopType::DistributeForStaticLoop:
6643 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
6648 auto OI = std::make_unique<OutlineInfo>();
6653 SmallVector<Instruction *, 4> ToBeDeleted;
6655 OI->OuterAllocBB = AllocaIP.getNodeParent();
6678 SmallPtrSet<BasicBlock *, 32> ParallelRegionBlockSet;
6680 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
6682 CodeExtractorAnalysisCache CEAC(*OuterFn);
6683 CodeExtractor Extractor(Blocks,
6697 SetVector<Value *> SinkingCands, HoistingCands;
6701 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
6708 for (
auto Use :
Users) {
6710 if (ParallelRegionBlockSet.
count(Inst->getParent())) {
6711 Inst->replaceUsesOfWith(CLI->
getIndVar(), NewLoopCntLoad);
6717 OI->ExcludeArgsFromAggregate.push_back(NewLoopCntLoad);
6724 OI->PostOutlineCB = [=, ToBeDeletedVec =
6725 std::move(ToBeDeleted)](
Function &OutlinedFn) {
6742 return BarrierIP.takeError();
6749 bool NeedsBarrier, omp::ScheduleKind SchedKind,
Value *ChunkSize,
6750 bool HasSimdModifier,
bool HasMonotonicModifier,
6751 bool HasNonmonotonicModifier,
bool HasOrderedClause,
6753 Value *DistScheduleChunkSize,
bool NeedsLastIter) {
6754 if (
Config.isTargetDevice())
6755 return applyWorkshareLoopTarget(
DL, CLI, AllocaIP, LoopType, NeedsBarrier,
6756 NoLoop, NeedsLastIter);
6758 SchedKind, ChunkSize, HasSimdModifier, HasMonotonicModifier,
6759 HasNonmonotonicModifier, HasOrderedClause, DistScheduleChunkSize);
6761 bool IsOrdered = (EffectiveScheduleType & OMPScheduleType::ModifierOrdered) ==
6762 OMPScheduleType::ModifierOrdered;
6764 if (HasDistSchedule) {
6765 DistScheduleSchedType = DistScheduleChunkSize
6766 ? OMPScheduleType::OrderedDistributeChunked
6767 : OMPScheduleType::OrderedDistribute;
6769 switch (EffectiveScheduleType & ~OMPScheduleType::ModifierMask) {
6770 case OMPScheduleType::BaseStatic:
6771 case OMPScheduleType::BaseDistribute:
6772 assert((!ChunkSize || !DistScheduleChunkSize) &&
6773 "No chunk size with static-chunked schedule");
6774 if (IsOrdered && !HasDistSchedule)
6775 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6776 NeedsBarrier, ChunkSize);
6778 if (DistScheduleChunkSize)
6779 return applyStaticChunkedWorkshareLoop(
6780 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6781 DistScheduleChunkSize, DistScheduleSchedType);
6782 return applyStaticWorkshareLoop(
DL, CLI, AllocaIP, LoopType, NeedsBarrier,
6785 case OMPScheduleType::BaseStaticChunked:
6786 case OMPScheduleType::BaseDistributeChunked:
6787 if (IsOrdered && !HasDistSchedule)
6788 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6789 NeedsBarrier, ChunkSize);
6791 return applyStaticChunkedWorkshareLoop(
6792 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6793 DistScheduleChunkSize, DistScheduleSchedType);
6795 case OMPScheduleType::BaseRuntime:
6796 case OMPScheduleType::BaseAuto:
6797 case OMPScheduleType::BaseGreedy:
6798 case OMPScheduleType::BaseBalanced:
6799 case OMPScheduleType::BaseSteal:
6800 case OMPScheduleType::BaseRuntimeSimd:
6802 "schedule type does not support user-defined chunk sizes");
6804 case OMPScheduleType::BaseGuidedSimd:
6805 case OMPScheduleType::BaseDynamicChunked:
6806 case OMPScheduleType::BaseGuidedChunked:
6807 case OMPScheduleType::BaseGuidedIterativeChunked:
6808 case OMPScheduleType::BaseGuidedAnalyticalChunked:
6809 case OMPScheduleType::BaseStaticBalancedChunked:
6810 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6811 NeedsBarrier, ChunkSize);
6824 unsigned Bitwidth = Ty->getIntegerBitWidth();
6827 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_4u);
6830 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_8u);
6838static FunctionCallee
6840 unsigned Bitwidth = Ty->getIntegerBitWidth();
6843 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_4u);
6846 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_8u);
6853static FunctionCallee
6855 unsigned Bitwidth = Ty->getIntegerBitWidth();
6858 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_4u);
6861 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_8u);
6866OpenMPIRBuilder::applyDynamicWorkshareLoop(
DebugLoc DL, CanonicalLoopInfo *CLI,
6869 bool NeedsBarrier,
Value *Chunk) {
6870 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6872 "Require dedicated allocate IP");
6874 "Require valid schedule type");
6876 bool Ordered = (SchedType & OMPScheduleType::ModifierOrdered) ==
6877 OMPScheduleType::ModifierOrdered;
6882 uint32_t SrcLocStrSize;
6889 Type *IVTy =
IV->getType();
6895 AllocaIP.getNodeParent()->getFirstNonPHIOrDbgOrAlloca());
6897 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6898 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
6899 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
6900 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
6909 Constant *One = ConstantInt::get(IVTy, 1);
6910 Builder.CreateStore(One, PLowerBound);
6912 Builder.CreateStore(UpperBound, PUpperBound);
6913 Builder.CreateStore(One, PStride);
6931 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6943 Builder.SetInsertPoint(OuterCond->getFirstInsertionPt());
6946 {SrcLoc, ThreadNum, PLastIter, PLowerBound, PUpperBound, PStride});
6947 Constant *Zero32 = ConstantInt::get(I32Type, 0);
6950 Builder.CreateSub(
Builder.CreateLoad(IVTy, PLowerBound), One,
"lb");
6951 Builder.CreateCondBr(MoreWork, Header, Exit);
6957 PI->setIncomingBlock(0, OuterCond);
6963 Br->setSuccessor(OuterCond);
6968 Builder.SetInsertPoint(
Cond->getFirstInsertionPt());
6969 UpperBound =
Builder.CreateLoad(IVTy, PUpperBound,
"ub");
6972 CI->setOperand(1, UpperBound);
6976 assert(BI->getSuccessor(1) == Exit);
6977 BI->setSuccessor(1, OuterCond);
6991 omp::Directive::OMPD_for,
false,
6994 return BarrierIP.takeError();
7046 assert(
Loops.size() >= 1 &&
"At least one loop required");
7047 size_t NumLoops =
Loops.size();
7051 return Loops.front();
7063 Loop->collectControlBlocks(OldControlBBs);
7067 if (ComputeIP.isValid())
7074 Value *CollapsedTripCount =
nullptr;
7077 "All loops to collapse must be valid canonical loops");
7078 Value *OrigTripCount = L->getTripCount();
7079 if (!CollapsedTripCount) {
7080 CollapsedTripCount = OrigTripCount;
7085 CollapsedTripCount =
7086 Builder.CreateNUWMul(CollapsedTripCount, OrigTripCount);
7092 OrigPreheader->
getNextNode(), OrigAfter,
"collapsed",
7099 Builder.restoreIP(Result->getBodyIP());
7101 Value *Leftover = Result->getIndVar();
7103 NewIndVars.
resize(NumLoops);
7104 for (
int i = NumLoops - 1; i >= 1; --i) {
7105 Value *OrigTripCount =
Loops[i]->getTripCount();
7107 Value *NewIndVar =
Builder.CreateURem(Leftover, OrigTripCount);
7108 NewIndVars[i] = NewIndVar;
7110 Leftover =
Builder.CreateUDiv(Leftover, OrigTripCount);
7113 NewIndVars[0] = Leftover;
7122 BasicBlock *ContinueBlock = Result->getBody();
7124 auto ContinueWith = [&ContinueBlock, &ContinuePred,
DL](
BasicBlock *Dest,
7131 ContinueBlock =
nullptr;
7132 ContinuePred = NextSrc;
7139 for (
size_t i = 0; i < NumLoops - 1; ++i)
7140 ContinueWith(
Loops[i]->getBody(),
Loops[i + 1]->getHeader());
7146 for (
size_t i = NumLoops - 1; i > 0; --i)
7147 ContinueWith(
Loops[i]->getAfter(),
Loops[i - 1]->getLatch());
7150 ContinueWith(Result->getLatch(),
nullptr);
7157 for (
size_t i = 0; i < NumLoops; ++i)
7158 Loops[i]->getIndVar()->replaceAllUsesWith(NewIndVars[i]);
7172std::vector<CanonicalLoopInfo *>
7176 "Must pass as many tile sizes as there are loops");
7177 int NumLoops =
Loops.size();
7178 assert(NumLoops >= 1 &&
"At least one loop to tile required");
7190 Loop->collectControlBlocks(OldControlBBs);
7198 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7199 OrigTripCounts.
push_back(L->getTripCount());
7210 for (
int i = 0; i < NumLoops - 1; ++i) {
7223 for (
int i = 0; i < NumLoops; ++i) {
7224 Value *TileSize = TileSizes[i];
7225 Value *OrigTripCount = OrigTripCounts[i];
7228 Value *FloorCompleteTripCount =
Builder.CreateUDiv(OrigTripCount, TileSize);
7229 Value *FloorTripRem =
Builder.CreateURem(OrigTripCount, TileSize);
7238 Value *FloorTripOverflow =
7239 Builder.CreateICmpNE(FloorTripRem, ConstantInt::get(IVType, 0));
7241 FloorTripOverflow =
Builder.CreateZExt(FloorTripOverflow, IVType);
7242 Value *FloorTripCount =
7243 Builder.CreateAdd(FloorCompleteTripCount, FloorTripOverflow,
7244 "omp_floor" +
Twine(i) +
".tripcount",
true);
7247 FloorCompleteCount.
push_back(FloorCompleteTripCount);
7253 std::vector<CanonicalLoopInfo *> Result;
7254 Result.reserve(NumLoops * 2);
7267 auto EmbeddNewLoop =
7268 [
this,
DL,
F, InnerEnter, &Enter, &
Continue, &OutroInsertBefore](
7271 DL, TripCount,
F, InnerEnter, OutroInsertBefore, Name);
7276 Enter = EmbeddedLoop->
getBody();
7278 OutroInsertBefore = EmbeddedLoop->
getLatch();
7279 return EmbeddedLoop;
7283 const Twine &NameBase) {
7286 EmbeddNewLoop(
P.value(), NameBase +
Twine(
P.index()));
7287 Result.push_back(EmbeddedLoop);
7291 EmbeddNewLoops(FloorCount,
"floor");
7297 for (
int i = 0; i < NumLoops; ++i) {
7299 Value *TileSize = TileSizes[i];
7301 Value *FloorIsEpilogue =
7303 Value *TileTripCount =
7304 Builder.CreateSelect(FloorIsEpilogue, FloorRems[i], TileSize);
7310 EmbeddNewLoops(TileCounts,
"tile");
7315 for (std::pair<BasicBlock *, BasicBlock *>
P : InbetweenCode) {
7324 BodyEnter =
nullptr;
7325 BodyEntered = ExitBB;
7337 Builder.restoreIP(Result.back()->getBodyIP());
7338 for (
int i = 0; i < NumLoops; ++i) {
7341 Value *OrigIndVar = OrigIndVars[i];
7392 assert(
Loop->isValid() &&
"Expecting a valid CanonicalLoopInfo");
7396 assert(Latch &&
"A valid CanonicalLoopInfo must have a unique latch");
7404 if (
I.mayReadOrWriteMemory()) {
7408 I.setMetadata(LLVMContext::MD_access_group,
AccessGroup);
7422 Loop->collectControlBlocks(oldControlBBs);
7427 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7428 origTripCounts.
push_back(L->getTripCount());
7437 Builder.SetInsertPoint(TCBlock);
7438 Value *fusedTripCount =
nullptr;
7440 assert(L->isValid() &&
"All loops to fuse must be valid canonical loops");
7441 Value *origTripCount = L->getTripCount();
7442 if (!fusedTripCount) {
7443 fusedTripCount = origTripCount;
7446 Value *condTP =
Builder.CreateICmpSGT(fusedTripCount, origTripCount);
7447 fusedTripCount =
Builder.CreateSelect(condTP, fusedTripCount, origTripCount,
7461 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7462 Loops[i]->getPreheader()->moveBefore(TCBlock);
7463 Loops[i]->getAfter()->moveBefore(TCBlock);
7467 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7479 for (
size_t i = 0; i <
Loops.size(); ++i) {
7481 F->getContext(),
"omp.fused.inner.cond",
F,
Loops[i]->getBody());
7482 Builder.SetInsertPoint(condBlock);
7490 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7491 Builder.SetInsertPoint(condBBs[i]);
7492 Builder.CreateCondBr(condValues[i],
Loops[i]->getBody(), condBBs[i + 1]);
7508 "omp.fused.pre_latch");
7541 const Twine &NamePrefix) {
7570 C, NamePrefix +
".if.then",
Cond->getParent(),
Cond->getNextNode());
7572 C, NamePrefix +
".if.else",
Cond->getParent(), CanonicalLoop->
getExit());
7575 Builder.SetInsertPoint(SplitBeforeIt);
7577 Builder.CreateCondBr(IfCond, ThenBlock, ElseBlock);
7580 spliceBB(IP, ThenBlock,
false, Builder.getCurrentDebugLocation());
7583 Builder.SetInsertPoint(ElseBlock);
7589 ExistingBlocks.
reserve(L->getNumBlocks() + 1);
7591 ExistingBlocks.
append(L->block_begin(), L->block_end());
7597 assert(LoopCond && LoopHeader &&
"Invalid loop structure");
7599 if (
Block == L->getLoopPreheader() ||
Block == L->getLoopLatch() ||
7606 if (
Block == ThenBlock)
7607 NewBB->
setName(NamePrefix +
".if.else");
7610 VMap[
Block] = NewBB;
7618 L->getLoopLatch()->splitBasicBlockBefore(
L->getLoopLatch()->begin(),
7619 NamePrefix +
".pre_latch");
7623 L->addBasicBlockToLoop(ThenBlock, LI);
7629 if (TargetTriple.
isX86()) {
7630 if (Features.
lookup(
"avx512f"))
7632 else if (Features.
lookup(
"avx"))
7636 if (TargetTriple.
isPPC())
7638 if (TargetTriple.
isWasm())
7647 Value *IfCond, OrderKind Order,
7657 if (!BB.hasTerminator())
7673 I->eraseFromParent();
7676 if (AlignedVars.
size()) {
7678 for (
auto &AlignedItem : AlignedVars) {
7679 Value *AlignedPtr = AlignedItem.first;
7683 Builder.CreateAlignmentAssumption(
F->getDataLayout(), AlignedPtr,
7691 createIfVersion(CanonicalLoop, IfCond, VMap, LIA, LI, L,
"simd");
7704 Reachable.insert(
Block);
7714 if ((Safelen ==
nullptr) || (Order == OrderKind::OMP_ORDER_concurrent))
7730 if (Simdlen || Safelen) {
7734 ConstantInt *VectorizeWidth = Simdlen ==
nullptr ? Safelen : Simdlen;
7760static std::unique_ptr<TargetMachine>
7764 StringRef CPU =
F->getFnAttribute(
"target-cpu").getValueAsString();
7765 StringRef Features =
F->getFnAttribute(
"target-features").getValueAsString();
7776 std::nullopt, OptLevel));
7794 if (!BB.hasTerminator())
7807 [&](
const Function &
F) {
return TM->getTargetTransformInfo(
F); });
7808 FAM.registerPass([&]() {
return TIRA; });
7822 I->eraseFromParent();
7825 assert(L &&
"Expecting CanonicalLoopInfo to be recognized as a loop");
7830 nullptr, ORE,
static_cast<int>(OptLevel),
7850 <<
" Threshold=" << UP.
Threshold <<
"\n"
7853 <<
" PartialOptSizeThreshold="
7873 Ptr =
Load->getPointerOperand();
7875 Ptr =
Store->getPointerOperand();
7882 if (Alloca->getParent() == &
F->getEntryBlock())
7902 int MaxTripCount = 0;
7903 bool MaxOrZero =
false;
7904 unsigned TripMultiple = 0;
7908 MaxTripCount, MaxOrZero, TripMultiple, UCE, UP, PP);
7909 LLVM_DEBUG(
dbgs() <<
"Suggesting unroll factor of " << Factor <<
"\n");
7920 assert(Factor >= 0 &&
"Unroll factor must not be negative");
7936 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst}));
7949 *UnrolledCLI =
Loop;
7954 "unrolling only makes sense with a factor of 2 or larger");
7956 Type *IndVarTy =
Loop->getIndVarType();
7963 std::vector<CanonicalLoopInfo *>
LoopNest =
7978 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst})});
7981 (*UnrolledCLI)->assertOK();
7999 Value *Args[] = {Ident, ThreadId, BufSize, CpyBuf, CpyFn, DidItLD};
8018 if (!CPVars.
empty()) {
8023 Directive OMPD = Directive::OMPD_single;
8028 Value *Args[] = {Ident, ThreadId};
8037 if (
Error Err = FiniCB(IP))
8058 EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCBWrapper,
8065 for (
size_t I = 0, E = CPVars.
size();
I < E; ++
I)
8068 ConstantInt::get(Int64, 0), CPVars[
I],
8071 }
else if (!IsNowait) {
8074 omp::Directive::OMPD_unknown,
false,
8092 Directive::OMPD_scope,
nullptr,
nullptr,
8093 BodyGenCB, FiniCB,
false,
true,
8101 omp::Directive::OMPD_unknown,
8117 Directive OMPD = Directive::OMPD_critical;
8122 Value *LockVar = getOMPCriticalRegionLock(CriticalName);
8123 Value *Args[] = {Ident, ThreadId, LockVar};
8140 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
8148 const Twine &Name,
bool IsDependSource) {
8151 [](
Value *SV) {
return SV->getType()->isIntegerTy(64); }) &&
8152 "OpenMP runtime requires depend vec with i64 type");
8165 for (
unsigned I = 0;
I < NumLoops; ++
I) {
8179 Value *Args[] = {Ident, ThreadId, DependBaseAddrGEP};
8197 Directive OMPD = Directive::OMPD_ordered_blockassoc;
8206 Value *Args[] = {Ident, ThreadId};
8216 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
8223 bool HasFinalize,
bool IsCancellable) {
8230 BasicBlock *EntryBB = Builder.GetInsertBlock();
8239 emitCommonDirectiveEntry(OMPD, EntryCall, ExitBB, Conditional);
8251 "Unexpected control flow graph state!!");
8253 emitCommonDirectiveExit(OMPD, FinIP, ExitCall, HasFinalize);
8255 return AfterIP.takeError();
8260 "Unexpected Insertion point location!");
8263 auto InsertBB = merged ? ExitPredBB : ExitBB;
8266 Builder.SetInsertPoint(InsertBB);
8268 return Builder.saveIP();
8272 Directive OMPD,
Value *EntryCall, BasicBlock *ExitBB,
bool Conditional) {
8274 if (!Conditional || !EntryCall)
8280 auto *UI =
new UnreachableInst(
Builder.getContext(), ThenBB);
8290 Builder.CreateCondBr(CallBool, ThenBB, ExitBB);
8294 UI->eraseFromParent();
8302 omp::Directive OMPD,
InsertPointTy FinIP, Instruction *ExitCall,
8310 "Unexpected finalization stack state!");
8313 assert(Fi.DK == OMPD &&
"Unexpected Directive for Finalization call!");
8317 return std::move(Err);
8364 "copyin.not.master.end");
8371 Builder.SetInsertPoint(OMP_Entry);
8374 Value *cmp =
Builder.CreateICmpNE(MasterPtr, PrivatePtr);
8375 Builder.CreateCondBr(cmp, CopyBegin, CopyEnd);
8377 Builder.SetInsertPoint(CopyBegin);
8395 Value *Args[] = {ThreadId,
Size, Allocator};
8418 return Builder.CreateCall(Fn, Args, Name);
8432 Value *Args[] = {ThreadId, Addr, Allocator};
8439 const Twine &Name) {
8447 M.getContext(),
M.getDataLayout().getPrefTypeAlign(Int64)));
8453 const Twine &Name) {
8455 Loc,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)), Name);
8460 const Twine &Name) {
8466 return Builder.CreateCall(Fn, Args, Name);
8471 const Twine &Name) {
8473 Loc, Addr,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)),
8480 Value *DependenceAddress,
bool HaveNowaitClause) {
8490 else if (
Device->getType() != Int32)
8493 if (NumDependences ==
nullptr) {
8494 NumDependences = ConstantInt::get(Int32, 0);
8498 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8500 Ident, ThreadId, InteropVar, InteropTypeVal,
8501 Device, NumDependences, DependenceAddress, HaveNowaitClauseVal};
8510 Value *NumDependences,
Value *DependenceAddress,
bool HaveNowaitClause) {
8520 else if (
Device->getType() != Int32)
8522 if (NumDependences ==
nullptr) {
8523 NumDependences = ConstantInt::get(Int32, 0);
8527 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8529 Ident, ThreadId, InteropVar,
Device,
8530 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8539 Value *NumDependences,
8540 Value *DependenceAddress,
8541 bool HaveNowaitClause) {
8550 else if (
Device->getType() != Int32)
8552 if (NumDependences ==
nullptr) {
8553 NumDependences = ConstantInt::get(Int32, 0);
8557 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8559 Ident, ThreadId, InteropVar,
Device,
8560 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8590 assert(!Attrs.MaxThreads.empty() && !Attrs.MaxTeams.empty() &&
8591 "expected num_threads and num_teams to be specified");
8611 const std::string DebugPrefix =
"_debug__";
8612 if (KernelName.
ends_with(DebugPrefix)) {
8613 KernelName = KernelName.
drop_back(DebugPrefix.length());
8614 Kernel =
M.getFunction(KernelName);
8620 if (Attrs.MinTeams.front() > 1 || Attrs.MaxTeams.front() > 0)
8622 Attrs.MaxTeams.front());
8625 int32_t MaxThreadsVal = Attrs.MaxThreads.front();
8635 Attrs.MinThreads.front());
8640 if (MaxThreadsVal > 0 &&
8643 MaxThreadsVal = int32_t(
8644 std::min<int64_t>(int64_t(MaxThreadsVal) + 64,
8647 if (MaxThreadsVal > 0)
8662 Twine DynamicEnvironmentName = KernelName +
"_dynamic_environment";
8663 Constant *DynamicEnvironmentInitializer =
8667 DynamicEnvironmentInitializer, DynamicEnvironmentName,
8669 DL.getDefaultGlobalsAddressSpace());
8673 DynamicEnvironmentGV->
getType() == DynamicEnvironmentPtr
8674 ? DynamicEnvironmentGV
8676 DynamicEnvironmentPtr);
8679 ConfigurationEnvironment, {
8680 UseGenericStateMachineVal,
8681 MayUseNestedParallelismVal,
8690 KernelEnvironment, {
8691 ConfigurationEnvironmentInitializer,
8695 std::string KernelEnvironmentName =
8696 (KernelName +
"_kernel_environment").str();
8699 KernelEnvironmentInitializer, KernelEnvironmentName,
8701 DL.getDefaultGlobalsAddressSpace());
8704 return KernelEnvironmentGV->
getType() == KernelEnvironmentPtr
8705 ? KernelEnvironmentGV
8707 KernelEnvironmentPtr);
8714 if (!KernelEnvironment)
8722 omp::RuntimeFunction::OMPRTL___kmpc_target_init);
8724 Value *KernelLaunchEnvironment =
8727 KernelLaunchEnvironment =
8728 KernelLaunchEnvironment->
getType() == KernelLaunchEnvParamTy
8729 ? KernelLaunchEnvironment
8730 :
Builder.CreateAddrSpaceCast(KernelLaunchEnvironment,
8731 KernelLaunchEnvParamTy);
8733 Fn, {KernelEnvironment, KernelLaunchEnvironment});
8745 auto *UI =
Builder.CreateUnreachable();
8751 Builder.SetInsertPoint(WorkerExitBB);
8755 Builder.SetInsertPoint(CheckBBTI);
8756 Builder.CreateCondBr(ExecUserCode, UI->getParent(), WorkerExitBB);
8758 CheckBBTI->eraseFromParent();
8759 UI->eraseFromParent();
8767 int32_t TeamsReductionDataSize) {
8772 omp::RuntimeFunction::OMPRTL___kmpc_target_deinit);
8776 if (!TeamsReductionDataSize)
8782 const std::string DebugPrefix =
"_debug__";
8784 KernelName = KernelName.
drop_back(DebugPrefix.length());
8785 auto *KernelEnvironmentGV =
8786 M.getNamedGlobal((KernelName +
"_kernel_environment").str());
8787 assert(KernelEnvironmentGV &&
"Expected kernel environment global\n");
8788 auto *KernelEnvironmentInitializer = KernelEnvironmentGV->getInitializer();
8790 KernelEnvironmentInitializer,
8791 ConstantInt::get(Int32, TeamsReductionDataSize), {0, 7});
8792 KernelEnvironmentGV->setInitializer(NewInitializer);
8797 if (
Kernel.hasFnAttribute(Name)) {
8798 int32_t OldLimit =
Kernel.getFnAttributeAsParsedInteger(Name);
8804std::pair<int32_t, int32_t>
8806 int32_t ThreadLimit =
8807 Kernel.getFnAttributeAsParsedInteger(
"omp_target_thread_limit");
8810 const auto &Attr =
Kernel.getFnAttribute(
"amdgpu-flat-work-group-size");
8811 if (!Attr.isValid() || !Attr.isStringAttribute())
8812 return {0, ThreadLimit};
8813 auto [LBStr, UBStr] = Attr.getValueAsString().split(
',');
8816 return {0, ThreadLimit};
8817 UB = ThreadLimit ? std::min(ThreadLimit, UB) : UB;
8825 return {0, ThreadLimit ? std::min(ThreadLimit, UB) : UB};
8827 return {0, ThreadLimit};
8833 Kernel.addFnAttr(
"omp_target_thread_limit", std::to_string(UB));
8836 Kernel.addFnAttr(
"amdgpu-flat-work-group-size",
8844std::pair<int32_t, int32_t>
8847 return {0,
Kernel.getFnAttributeAsParsedInteger(
"omp_target_num_teams")};
8851 int32_t LB, int32_t UB) {
8859 Kernel.addFnAttr(
"omp_target_num_teams", std::to_string(LB));
8862void OpenMPIRBuilder::setOutlinedTargetRegionFunctionAttributes(
8871 else if (
T.isNVPTX())
8873 else if (
T.isSPIRV())
8879 StringRef EntryFnIDName) {
8880 if (
Config.isTargetDevice()) {
8881 assert(OutlinedFn &&
"The outlined function must exist if embedded");
8885 return new GlobalVariable(
8890Constant *OpenMPIRBuilder::createTargetRegionEntryAddr(
Function *OutlinedFn,
8891 StringRef EntryFnName) {
8895 assert(!
M.getGlobalVariable(EntryFnName,
true) &&
8896 "Named kernel already exists?");
8897 return new GlobalVariable(
8910 if (
Config.isTargetDevice() || !
Config.openMPOffloadMandatory()) {
8914 OutlinedFn = *CBResult;
8916 OutlinedFn =
nullptr;
8922 if (!IsOffloadEntry)
8925 std::string EntryFnIDName =
8927 ? std::string(EntryFnName)
8931 EntryFnName, EntryFnIDName);
8939 setOutlinedTargetRegionFunctionAttributes(OutlinedFn);
8940 auto OutlinedFnID = createOutlinedFunctionID(OutlinedFn, EntryFnIDName);
8941 auto EntryAddr = createTargetRegionEntryAddr(OutlinedFn, EntryFnName);
8943 EntryInfo, EntryAddr, OutlinedFnID,
8945 return OutlinedFnID;
8963 bool IsStandAlone = !BodyGenCB;
8970 MapInfo = &GenMapInfoCB(
Builder.saveIP());
8972 AllocaIP,
Builder.saveIP(), *MapInfo, Info, CustomMapperCB,
8973 true, DeviceAddrCB))
8980 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
8990 SrcLocInfo, DeviceID,
8997 assert(MapperFunc &&
"MapperFunc missing for standalone target data");
9001 if (Info.HasNoWait) {
9011 if (Info.HasNoWait) {
9015 emitBlock(OffloadContBlock, CurFn,
true);
9021 bool RequiresOuterTargetTask = Info.HasNoWait;
9022 if (!RequiresOuterTargetTask)
9023 cantFail(TaskBodyCB(
nullptr,
nullptr,
9027 {}, RTArgs, Info.HasNoWait));
9030 omp::OMPRTL___tgt_target_data_begin_mapper);
9034 for (
auto DeviceMap : Info.DevicePtrInfoMap) {
9038 Builder.CreateStore(LI, DeviceMap.second.second);
9075 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
9084 Value *OffloadingArgs[] = {SrcLocInfo, DeviceID,
9107 return emitIfClause(IfCond, BeginThenGen, BeginElseGen, AllocaIP);
9108 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9123 return emitIfClause(IfCond, EndThenGen, EndElseGen, AllocaIP);
9124 return EndThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9127 return emitIfClause(IfCond, BeginThenGen, EndElseGen, AllocaIP);
9128 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9139 bool IsGPUDistribute) {
9140 assert((IVSize == 32 || IVSize == 64) &&
9141 "IV size is not compatible with the omp runtime");
9143 if (IsGPUDistribute)
9145 ? (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_4
9146 : omp::OMPRTL___kmpc_distribute_static_init_4u)
9147 : (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_8
9148 : omp::OMPRTL___kmpc_distribute_static_init_8u);
9150 Name = IVSize == 32 ? (IVSigned ? omp::OMPRTL___kmpc_for_static_init_4
9151 : omp::OMPRTL___kmpc_for_static_init_4u)
9152 : (IVSigned ? omp::OMPRTL___kmpc_for_static_init_8
9153 : omp::OMPRTL___kmpc_for_static_init_8u);
9160 assert((IVSize == 32 || IVSize == 64) &&
9161 "IV size is not compatible with the omp runtime");
9163 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_4
9164 : omp::OMPRTL___kmpc_dispatch_init_4u)
9165 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_8
9166 : omp::OMPRTL___kmpc_dispatch_init_8u);
9173 assert((IVSize == 32 || IVSize == 64) &&
9174 "IV size is not compatible with the omp runtime");
9176 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_4
9177 : omp::OMPRTL___kmpc_dispatch_next_4u)
9178 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_8
9179 : omp::OMPRTL___kmpc_dispatch_next_8u);
9186 assert((IVSize == 32 || IVSize == 64) &&
9187 "IV size is not compatible with the omp runtime");
9189 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_4
9190 : omp::OMPRTL___kmpc_dispatch_fini_4u)
9191 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_8
9192 : omp::OMPRTL___kmpc_dispatch_fini_8u);
9203 DenseMap<
Value *, std::tuple<Value *, unsigned>> &ValueReplacementMap) {
9211 auto GetUpdatedDIVariable = [&](
DILocalVariable *OldVar,
unsigned arg) {
9215 if (NewVar && (arg == NewVar->
getArg()))
9225 auto UpdateDebugRecord = [&](
auto *DR) {
9228 for (
auto Loc : DR->location_ops()) {
9229 auto Iter = ValueReplacementMap.find(
Loc);
9230 if (Iter != ValueReplacementMap.end()) {
9231 DR->replaceVariableLocationOp(
Loc, std::get<0>(Iter->second));
9232 ArgNo = std::get<1>(Iter->second) + 1;
9236 DR->setVariable(GetUpdatedDIVariable(OldVar, ArgNo));
9241 if (DVR->getNumVariableLocationOps() != 1u) {
9242 DVR->setKillLocation();
9245 Value *
Loc = DVR->getVariableLocationOp(0u);
9252 RequiredBB = &DVR->getFunction()->getEntryBlock();
9254 if (RequiredBB && RequiredBB != CurBB) {
9266 "Unexpected debug intrinsic");
9268 UpdateDebugRecord(&DVR);
9269 MoveDebugRecordToCorrectBlock(&DVR);
9272 for (
auto *DVR : DVRsToDelete)
9273 DVR->getMarker()->MarkedInstr->dropOneDbgRecord(DVR);
9277 Module *M = Func->getParent();
9280 DB.createQualifiedType(dwarf::DW_TAG_pointer_type,
nullptr);
9281 unsigned ArgNo = Func->arg_size();
9283 NewSP,
"dyn_ptr", ArgNo, NewSP->
getFile(), 0, VoidPtrTy,
9284 false, DINode::DIFlags::FlagArtificial);
9286 Argument *LastArg = Func->getArg(Func->arg_size() - 1);
9287 DB.insertDeclare(LastArg, Var, DB.createExpression(),
Loc,
9309 for (
auto &Arg : Inputs)
9310 ParameterTypes.
push_back(Arg->getType()->isPointerTy()
9314 for (
auto &Arg : Inputs)
9315 ParameterTypes.
push_back(Arg->getType());
9323 auto BB = Builder.GetInsertBlock();
9324 auto M = BB->getModule();
9335 if (TargetCpuAttr.isStringAttribute())
9336 Func->addFnAttr(TargetCpuAttr);
9338 auto TargetFeaturesAttr = ParentFn->
getFnAttribute(
"target-features");
9339 if (TargetFeaturesAttr.isStringAttribute())
9340 Func->addFnAttr(TargetFeaturesAttr);
9345 OMPBuilder.
emitUsed(
"llvm.compiler.used", {ExecMode});
9355 Builder.SetCurrentDebugLocation(OutlinedFnLoc);
9359 Builder.SetInsertPoint(EntryBB);
9370 BasicBlock *UserCodeEntryBB = Builder.GetInsertBlock();
9380 splitBB(Builder,
true,
"outlined.body");
9382 CBFunc(Builder.saveIP(), OutlinedBodyBB->
begin(), ExitBB);
9385 Builder.SetInsertPoint(ExitBB);
9393 Builder.SetCurrentDebugLocation(OutlinedFnLoc);
9400 Builder.CreateRetVoid();
9404 auto AllocaIP = Builder.saveIP();
9409 const auto &ArgRange =
make_range(Func->arg_begin(), Func->arg_end() - 1);
9441 if (Instr->getFunction() == Func)
9442 Instr->replaceUsesOfWith(
Input, InputCopy);
9448 for (
auto InArg :
zip(Inputs, ArgRange)) {
9450 Argument &Arg = std::get<1>(InArg);
9451 Value *InputCopy =
nullptr;
9454 Arg,
Input, InputCopy, AllocaIP, Builder.saveIP(), ExitBB->
begin());
9457 Builder.restoreIP(*AfterIP);
9458 ValueReplacementMap[
Input] = std::make_tuple(InputCopy, Arg.
getArgNo());
9478 DeferredReplacement.push_back(std::make_pair(
Input, InputCopy));
9485 ReplaceValue(
Input, InputCopy, Func);
9489 for (
auto Deferred : DeferredReplacement)
9490 ReplaceValue(std::get<0>(Deferred), std::get<1>(Deferred), Func);
9493 ValueReplacementMap);
9501 Value *TaskWithPrivates,
9502 Type *TaskWithPrivatesTy) {
9504 Type *TaskTy = OMPIRBuilder.Task;
9507 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 0);
9508 Value *Shareds = TaskT;
9518 if (TaskWithPrivatesTy != TaskTy)
9519 Shareds = Builder.CreateStructGEP(TaskTy, TaskT, 0);
9536 const size_t NumOffloadingArrays,
const int SharedArgsOperandNo) {
9541 assert((!NumOffloadingArrays || PrivatesTy) &&
9542 "PrivatesTy cannot be nullptr when there are offloadingArrays"
9572 Type *TaskPtrTy = OMPBuilder.TaskPtr;
9573 [[maybe_unused]]
Type *TaskTy = OMPBuilder.Task;
9579 ".omp_target_task_proxy_func", M);
9580 Value *ThreadId = ProxyFn->getArg(0);
9581 Value *TaskWithPrivates = ProxyFn->getArg(1);
9582 ThreadId->
setName(
"thread.id");
9583 TaskWithPrivates->
setName(
"task");
9585 bool HasShareds = SharedArgsOperandNo > 0;
9586 bool HasOffloadingArrays = NumOffloadingArrays > 0;
9590 Builder.SetInsertPoint(EntryBB);
9597 if (HasOffloadingArrays) {
9598 assert(TaskTy != TaskWithPrivatesTy &&
9599 "If there are offloading arrays to pass to the target"
9600 "TaskTy cannot be the same as TaskWithPrivatesTy");
9603 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 1);
9604 for (
unsigned int i = 0; i < NumOffloadingArrays; ++i)
9606 Builder.CreateStructGEP(PrivatesTy, Privates, i));
9610 auto *ArgStructAlloca =
9612 assert(ArgStructAlloca &&
9613 "Unable to find the alloca instruction corresponding to arguments "
9614 "for extracted function");
9616 std::optional<TypeSize> ArgAllocSize =
9618 assert(ArgStructType && ArgAllocSize &&
9619 "Unable to determine size of arguments for extracted function");
9620 uint64_t StructSize = ArgAllocSize->getFixedValue();
9623 Builder.CreateAlloca(ArgStructType,
nullptr,
"structArg");
9625 Value *SharedsSize = Builder.getInt64(StructSize);
9628 OMPBuilder, Builder, TaskWithPrivates, TaskWithPrivatesTy);
9630 Builder.CreateMemCpy(
9631 NewArgStructAlloca, NewArgStructAlloca->
getAlign(), LoadShared,
9633 KernelLaunchArgs.
push_back(NewArgStructAlloca);
9636 Builder.CreateRetVoid();
9642 return GEP->getSourceElementType();
9644 return Alloca->getAllocatedType();
9667 if (OffloadingArraysToPrivatize.
empty())
9668 return OMPIRBuilder.Task;
9671 for (
Value *V : OffloadingArraysToPrivatize) {
9672 assert(V->getType()->isPointerTy() &&
9673 "Expected pointer to array to privatize. Got a non-pointer value "
9676 assert(ArrayTy &&
"ArrayType cannot be nullptr");
9682 "struct.task_with_privates");
9697 EntryFnName, Inputs, CBFunc,
9698 ArgAccessorFuncCB, OutlinedFnLoc);
9702 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
9841 auto OI = std::make_unique<OutlineInfo>();
9842 OI->EntryBB = TargetTaskAllocaBB;
9843 OI->OuterAllocBB = AllocaIP.getNodeParent();
9848 Builder, AllocaIP, ToBeDeleted, TargetTaskAllocaIP,
"global.tid",
false));
9851 Builder.restoreIP(TargetTaskBodyIP);
9852 if (
Error Err = TaskBodyCB(DeviceID, RTLoc, TargetTaskAllocaIP))
9870 bool NeedsTargetTask = HasNoWait && DeviceID;
9871 if (NeedsTargetTask) {
9877 OffloadingArraysToPrivatize.
push_back(V);
9878 OI->ExcludeArgsFromAggregate.push_back(V);
9882 OI->PostOutlineCB = [
this, ToBeDeleted, Dependencies, NeedsTargetTask,
9883 DeviceID, OffloadingArraysToPrivatize](
9886 "there must be a single user for the outlined function");
9900 const unsigned int NumStaleCIArgs = StaleCI->
arg_size();
9901 bool HasShareds = NumStaleCIArgs > OffloadingArraysToPrivatize.
size() + 1;
9903 NumStaleCIArgs == (OffloadingArraysToPrivatize.
size() + 2)) &&
9904 "Wrong number of arguments for StaleCI when shareds are present");
9905 int SharedArgOperandNo =
9906 HasShareds ? OffloadingArraysToPrivatize.
size() + 1 : 0;
9912 if (!OffloadingArraysToPrivatize.
empty())
9917 *
this,
Builder, StaleCI, PrivatesTy, TaskWithPrivatesTy,
9918 OffloadingArraysToPrivatize.
size(), SharedArgOperandNo);
9920 LLVM_DEBUG(
dbgs() <<
"Proxy task entry function created: " << *ProxyFn
9923 Builder.SetInsertPoint(StaleCI);
9940 OMPRTL___kmpc_omp_target_task_alloc);
9952 M.getDataLayout().getTypeStoreSize(TaskWithPrivatesTy));
9959 auto *ArgStructAlloca =
9961 assert(ArgStructAlloca &&
9962 "Unable to find the alloca instruction corresponding to arguments "
9963 "for extracted function");
9964 std::optional<TypeSize> ArgAllocSize =
9967 "Unable to determine size of arguments for extracted function");
9968 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
9987 TaskSize, SharedsSize,
9990 if (NeedsTargetTask) {
9991 assert(DeviceID &&
"Expected non-empty device ID.");
10001 *
this,
Builder, TaskData, TaskWithPrivatesTy);
10005 if (!OffloadingArraysToPrivatize.
empty()) {
10007 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskData, 1);
10008 for (
unsigned int i = 0; i < OffloadingArraysToPrivatize.
size(); ++i) {
10009 Value *PtrToPrivatize = OffloadingArraysToPrivatize[i];
10016 "ElementType should match ArrayType");
10019 Value *Dst =
Builder.CreateStructGEP(PrivatesTy, Privates, i);
10022 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(ElementType)));
10026 Value *DepArray =
nullptr;
10027 Value *NumDeps =
nullptr;
10030 NumDeps = Dependencies.
NumDeps;
10031 }
else if (!Dependencies.
Deps.empty()) {
10033 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
10044 if (!NeedsTargetTask) {
10053 ConstantInt::get(
Builder.getInt32Ty(), 0),
10066 }
else if (DepArray) {
10074 {Ident, ThreadID, TaskData, NumDeps, DepArray,
10075 ConstantInt::get(
Builder.getInt32Ty(), 0),
10083 Builder.ClearInsertionPoint();
10086 I->eraseFromParent();
10091 << *(
Builder.GetInsertBlock()) <<
"\n");
10093 << *(
Builder.getModule()) <<
"\n");
10104 CustomMapperCB, IsNonContiguous, DeviceAddrCB))
10127 Builder.restoreIP(IP);
10133 return Builder.saveIP();
10136 bool HasDependencies = !Dependencies.
empty();
10137 bool RequiresOuterTargetTask = HasNoWait || HasDependencies;
10154 if (OutlinedFnID && DeviceID)
10156 EmitTargetCallFallbackCB, KArgs,
10157 DeviceID, RTLoc, TargetTaskAllocaIP);
10165 return EmitTargetCallFallbackCB(OMPBuilder.
Builder.
saveIP());
10172 auto &&EmitTargetCallElse =
10179 if (RequiresOuterTargetTask) {
10186 Dependencies, EmptyRTArgs, HasNoWait);
10188 return EmitTargetCallFallbackCB(Builder.saveIP());
10191 Builder.restoreIP(AfterIP);
10195 auto &&EmitTargetCallThen =
10199 Info.HasNoWait = HasNoWait;
10204 AllocaIP, Builder.saveIP(), Info, RTArgs, MapInfo, CustomMapperCB,
10210 for (
auto [DefaultVal, RuntimeVal] :
10212 NumTeamsC.
push_back(RuntimeVal ? RuntimeVal
10213 : Builder.getInt32(DefaultVal));
10217 auto InitMaxThreadsClause = [&Builder](
Value *
Clause) {
10219 Clause = Builder.CreateIntCast(
Clause, Builder.getInt32Ty(),
10223 auto CombineMaxThreadsClauses = [&Builder](
Value *
Clause,
Value *&Result) {
10226 Result ? Builder.CreateSelect(Builder.CreateICmpULT(Result,
Clause),
10234 Value *MaxThreadsClause =
10236 ? InitMaxThreadsClause(RuntimeAttrs.
MaxThreads.front())
10239 for (
auto [TeamsVal, TargetVal] :
zip_equal(
10241 Value *TeamsThreadLimitClause = InitMaxThreadsClause(TeamsVal);
10242 Value *NumThreads = InitMaxThreadsClause(TargetVal);
10244 CombineMaxThreadsClauses(TeamsThreadLimitClause, NumThreads);
10245 CombineMaxThreadsClauses(MaxThreadsClause, NumThreads);
10247 NumThreadsC.
push_back(NumThreads ? NumThreads : Builder.getInt32(0));
10250 unsigned NumTargetItems = Info.NumberOfPtrs;
10251 Value *RTLoc = RTLocOverride;
10262 Builder.getInt64Ty(),
10264 : Builder.getInt64(0);
10268 DynCGroupMem = Builder.getInt32(0);
10271 NumTargetItems, RTArgs, TripCount, NumTeamsC, NumThreadsC, DynCGroupMem,
10272 HasNoWait,
false,
false,
10273 DynCGroupMemFallback);
10280 if (RequiresOuterTargetTask)
10282 RTLoc, AllocaIP, Dependencies,
10283 KArgs.
RTArgs, Info.HasNoWait);
10286 Builder, OutlinedFnID, EmitTargetCallFallbackCB, KArgs,
10287 RuntimeAttrs.
DeviceID, RTLoc, AllocaIP);
10290 Builder.restoreIP(AfterIP);
10297 if (!OutlinedFnID) {
10298 cantFail(EmitTargetCallElse(AllocaIP, Builder.saveIP(), DeallocBlocks));
10304 cantFail(EmitTargetCallThen(AllocaIP, Builder.saveIP(), DeallocBlocks));
10309 EmitTargetCallElse, AllocaIP));
10322 bool HasNowait,
Value *DynCGroupMem,
10324 Value *RTLocOverride) {
10329 Builder.restoreIP(CodeGenIP);
10337 *
this,
Builder, IsOffloadEntry, EntryInfo, DefaultAttrs, OutlinedFn,
10338 OutlinedFnID, Inputs, CBFunc, ArgAccessorFuncCB, OutlinedFnLoc))
10344 if (!
Config.isTargetDevice())
10346 DefaultAttrs, RuntimeAttrs, IfCond, OutlinedFn, OutlinedFnID,
10347 Inputs, GenMapInfoCB, CustomMapperCB, Dependencies,
10348 HasNowait, DynCGroupMem, DynCGroupMemFallback);
10362 return OS.
str().str();
10367 return OpenMPIRBuilder::getNameWithSeparators(Parts,
Config.firstSeparator(),
10373 auto &Elem = *
InternalVars.try_emplace(Name,
nullptr).first;
10375 assert(Elem.second->getValueType() == Ty &&
10376 "OMP internal variable has different type than requested");
10389 :
M.getTargetTriple().isAMDGPU()
10391 :
DL.getDefaultGlobalsAddressSpace();
10392 auto Linkage = this->
M.getTargetTriple().isWasm()
10400 const llvm::Align PtrAlign =
DL.getPointerABIAlignment(AddressSpaceVal);
10401 GV->setAlignment(std::max(TypeAlign, PtrAlign));
10405 return Elem.second;
10408Value *OpenMPIRBuilder::getOMPCriticalRegionLock(
StringRef CriticalName) {
10409 std::string Prefix =
Twine(
"gomp_critical_user_", CriticalName).
str();
10410 std::string Name = getNameWithSeparators({Prefix,
"var"},
".",
".");
10421 return SizePtrToInt;
10426 std::string VarName) {
10434 return MaptypesArrayGlobal;
10439 unsigned NumOperands,
10448 ArrI8PtrTy,
nullptr,
".offload_baseptrs");
10452 ArrI64Ty,
nullptr,
".offload_sizes");
10463 int64_t DeviceID,
unsigned NumOperands) {
10469 Value *ArgsBaseGEP =
10471 {Builder.getInt32(0), Builder.getInt32(0)});
10474 {Builder.getInt32(0), Builder.getInt32(0)});
10475 Value *ArgSizesGEP =
10477 {Builder.getInt32(0), Builder.getInt32(0)});
10481 Builder.getInt32(NumOperands),
10482 ArgsBaseGEP, ArgsGEP, ArgSizesGEP,
10483 MaptypesArg, MapnamesArg, NullPtr});
10490 assert((!ForEndCall || Info.separateBeginEndCalls()) &&
10491 "expected region end call to runtime only when end call is separate");
10493 auto VoidPtrTy = UnqualPtrTy;
10494 auto VoidPtrPtrTy = UnqualPtrTy;
10496 auto Int64PtrTy = UnqualPtrTy;
10498 if (!Info.NumberOfPtrs) {
10510 Info.RTArgs.BasePointersArray,
10513 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray,
10517 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
10521 ForEndCall && Info.RTArgs.MapTypesArrayEnd ? Info.RTArgs.MapTypesArrayEnd
10522 : Info.RTArgs.MapTypesArray,
10528 if (!Info.EmitDebug)
10532 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.MapNamesArray,
10537 if (!Info.HasMapper)
10541 Builder.CreatePointerCast(Info.RTArgs.MappersArray, VoidPtrPtrTy);
10562 "struct.descriptor_dim");
10564 enum { OffsetFD = 0, CountFD, StrideFD };
10568 for (
unsigned I = 0, L = 0, E = NonContigInfo.
Dims.
size();
I < E; ++
I) {
10571 if (NonContigInfo.
Dims[
I] == 1)
10576 Builder.CreateAlloca(ArrayTy,
nullptr,
"dims");
10577 Builder.restoreIP(CodeGenIP);
10578 for (
unsigned II = 0, EE = NonContigInfo.
Dims[
I];
II < EE; ++
II) {
10579 unsigned RevIdx = EE -
II - 1;
10583 Value *OffsetLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, OffsetFD);
10585 NonContigInfo.
Offsets[L][RevIdx], OffsetLVal,
10586 M.getDataLayout().getPrefTypeAlign(OffsetLVal->
getType()));
10588 Value *CountLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, CountFD);
10590 NonContigInfo.
Counts[L][RevIdx], CountLVal,
10591 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10593 Value *StrideLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, StrideFD);
10595 NonContigInfo.
Strides[L][RevIdx], StrideLVal,
10596 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10599 Builder.restoreIP(CodeGenIP);
10600 Value *DAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
10601 DimsAddr,
Builder.getPtrTy());
10604 Info.RTArgs.PointersArray, 0,
I);
10606 DAddr,
P,
M.getDataLayout().getPrefTypeAlign(
Builder.getPtrTy()));
10611void OpenMPIRBuilder::emitUDMapperArrayInitOrDel(
10615 StringRef Prefix = IsInit ?
".init" :
".del";
10621 Builder.CreateICmpSGT(
Size, Builder.getInt64(1),
"omp.arrayinit.isarray");
10622 Value *DeleteBit = Builder.CreateAnd(
10625 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10626 OpenMPOffloadMappingFlags::OMP_MAP_DELETE)));
10631 Value *BaseIsBegin = Builder.CreateICmpNE(
Base, Begin);
10632 Cond = Builder.CreateOr(IsArray, BaseIsBegin);
10633 DeleteCond = Builder.CreateIsNull(
10638 DeleteCond =
Builder.CreateIsNotNull(
10654 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10655 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10656 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10657 MapTypeArg =
Builder.CreateOr(
10660 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10661 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT)));
10665 Value *OffloadingArgs[] = {MapperHandle,
Base, Begin,
10666 ArraySize, MapTypeArg, MapName};
10677 bool PreserveMemberOfFlags,
bool PropagatePresentToPointee) {
10693 MapperFn->
addFnAttr(Attribute::NoInline);
10694 MapperFn->
addFnAttr(Attribute::NoUnwind);
10705 Builder.SetInsertPoint(EntryBB);
10720 Value *PtrBegin = BeginIn;
10726 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
10727 MapType, MapName, ElementSize, HeadBB,
10738 Builder.CreateICmpEQ(PtrBegin, PtrEnd,
"omp.arraymap.isempty");
10739 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
10745 Builder.CreatePHI(PtrBegin->
getType(), 2,
"omp.arraymap.ptrcurrent");
10746 PtrPHI->addIncoming(PtrBegin, HeadBB);
10751 return Info.takeError();
10755 Value *OffloadingArgs[] = {MapperHandle};
10759 Value *ShiftedPreviousSize =
10763 for (
unsigned I = 0;
I < Info->BasePointers.size(); ++
I) {
10764 Value *CurBaseArg = Info->BasePointers[
I];
10765 Value *CurBeginArg = Info->Pointers[
I];
10766 Value *CurSizeArg = Info->Sizes[
I];
10767 Value *CurNameArg = Info->Names.size()
10772 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10775 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10777 constexpr uint64_t MemberOfMask =
10778 static_cast<uint64_t
>(OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
10779 constexpr uint64_t AttachBit =
10780 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10781 OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
10839 Value *MemberMapType;
10840 if (PreserveMemberOfFlags || (RawType & AttachBit) ||
10841 Info->HasAttachPtr[
I]) {
10842 if (RawType & MemberOfMask)
10843 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
10845 MemberMapType = OriMapType;
10847 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
10865 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10866 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10867 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10877 Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
10883 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10884 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10885 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10891 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10892 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
10893 Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
10899 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10900 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10906 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10907 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10908 Builder.CreateCondBr(IsFrom, FromBB, EndBB);
10914 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10915 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
10924 CurMapType->
addIncoming(MemberMapType, ToElseBB);
10961 uint64_t ModifierBits =
10962 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10963 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
10964 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
10965 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
10966 if (PropagatePresentToPointee && Info->HasAttachPtr[
I])
10968 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10969 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
10970 Value *ImportedModifierBits =
10973 CurMapType, ImportedModifierBits,
"omp.maptype.with.modifiers");
10978 Value *FinalMapType =
10979 (RawType & AttachBit) ? CurMapType : CurMapTypeWithModifiers;
10981 Value *OffloadingArgs[] = {MapperHandle, CurBaseArg, CurBeginArg,
10982 CurSizeArg, FinalMapType, CurNameArg};
10984 auto ChildMapperFn = CustomMapperCB(
I);
10985 if (!ChildMapperFn)
10986 return ChildMapperFn.takeError();
10987 if (*ChildMapperFn) {
11003 "omp.arraymap.next");
11004 PtrPHI->addIncoming(PtrNext, LastBB);
11005 Value *IsDone =
Builder.CreateICmpEQ(PtrNext, PtrEnd,
"omp.arraymap.isdone");
11007 Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
11012 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
11013 MapType, MapName, ElementSize, DoneBB,
11026 bool IsNonContiguous,
11030 Info.clearArrayInfo();
11033 if (Info.NumberOfPtrs == 0)
11042 Info.RTArgs.BasePointersArray =
Builder.CreateAlloca(
11043 PointerArrayType,
nullptr,
".offload_baseptrs");
11045 Info.RTArgs.PointersArray =
Builder.CreateAlloca(
11046 PointerArrayType,
nullptr,
".offload_ptrs");
11048 PointerArrayType,
nullptr,
".offload_mappers");
11049 Info.RTArgs.MappersArray = MappersArray;
11056 ConstantInt::get(Int64Ty, 0));
11058 for (
unsigned I = 0, E = CombinedInfo.
Sizes.
size();
I < E; ++
I) {
11059 bool IsNonContigEntry =
11061 (
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11063 OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG) != 0);
11066 if (IsNonContigEntry) {
11068 "Index must be in-bounds for NON_CONTIG Dims array");
11070 assert(DimCount > 0 &&
"NON_CONTIG DimCount must be > 0");
11071 ConstSizes[
I] = ConstantInt::get(Int64Ty, DimCount);
11076 ConstSizes[
I] = CI;
11080 RuntimeSizes.
set(
I);
11083 if (RuntimeSizes.
all()) {
11085 Info.RTArgs.SizesArray =
Builder.CreateAlloca(
11086 SizeArrayType,
nullptr,
".offload_sizes");
11092 auto *SizesArrayGbl =
11097 if (!RuntimeSizes.
any()) {
11098 Info.RTArgs.SizesArray = SizesArrayGbl;
11100 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
11101 Align OffloadSizeAlign =
M.getDataLayout().getABIIntegerTypeAlignment(64);
11104 SizeArrayType,
nullptr,
".offload_sizes");
11108 Buffer,
M.getDataLayout().getPrefTypeAlign(Buffer->
getType()),
11109 SizesArrayGbl, OffloadSizeAlign,
11114 Info.RTArgs.SizesArray = Buffer;
11122 for (
auto mapFlag : CombinedInfo.
Types)
11124 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11128 Info.RTArgs.MapTypesArray = MapTypesArrayGbl;
11134 Info.RTArgs.MapNamesArray = MapNamesArrayGbl;
11135 Info.EmitDebug =
true;
11137 Info.RTArgs.MapNamesArray =
11139 Info.EmitDebug =
false;
11144 if (Info.separateBeginEndCalls()) {
11145 bool EndMapTypesDiffer =
false;
11146 for (uint64_t &
Type : Mapping) {
11147 if (
Type &
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11148 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT)) {
11149 Type &= ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
11150 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
11151 EndMapTypesDiffer =
true;
11154 if (EndMapTypesDiffer) {
11156 Info.RTArgs.MapTypesArrayEnd = MapTypesArrayGbl;
11161 for (
unsigned I = 0;
I < Info.NumberOfPtrs; ++
I) {
11164 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.BasePointersArray,
11166 Builder.CreateAlignedStore(BPVal, BP,
11167 M.getDataLayout().getPrefTypeAlign(PtrTy));
11169 if (Info.requiresDevicePointerInfo()) {
11171 CodeGenIP =
Builder.saveIP();
11173 Info.DevicePtrInfoMap[BPVal] = {BP,
Builder.CreateAlloca(PtrTy)};
11176 DeviceAddrCB(
I, Info.DevicePtrInfoMap[BPVal].second);
11178 Info.DevicePtrInfoMap[BPVal] = {BP, BP};
11180 DeviceAddrCB(
I, BP);
11186 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray, 0,
11189 Builder.CreateAlignedStore(PVal,
P,
11190 M.getDataLayout().getPrefTypeAlign(PtrTy));
11192 if (RuntimeSizes.
test(
I)) {
11194 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
11200 S,
M.getDataLayout().getPrefTypeAlign(PtrTy));
11203 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
11206 auto CustomMFunc = CustomMapperCB(
I);
11208 return CustomMFunc.takeError();
11210 MFunc =
Builder.CreatePointerCast(*CustomMFunc, PtrTy);
11213 PointerArrayType, MappersArray,
11216 MFunc, MAddr,
M.getDataLayout().getPrefTypeAlign(MAddr->
getType()));
11220 Info.NumberOfPtrs == 0)
11237 Builder.ClearInsertionPoint();
11268 auto CondConstant = CI->getSExtValue();
11270 return ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
11272 return ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
11282 Builder.CreateCondBr(
Cond, ThenBlock, ElseBlock);
11285 if (
Error Err = ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks))
11291 if (
Error Err = ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks))
11300bool OpenMPIRBuilder::checkAndEmitFlushAfterAtomic(
11304 "Unexpected Atomic Ordering.");
11306 bool Flush =
false;
11368 assert(
X.Var->getType()->isPointerTy() &&
11369 "OMP Atomic expects a pointer to target memory");
11370 Type *XElemTy =
X.ElemTy;
11373 "OMP atomic read expected a scalar type");
11375 Value *XRead =
nullptr;
11379 Builder.CreateLoad(XElemTy,
X.Var,
X.IsVolatile,
"omp.atomic.read");
11388 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11391 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11393 XRead = AtomicLoadRes.first;
11400 Builder.CreateLoad(IntCastTy,
X.Var,
X.IsVolatile,
"omp.atomic.load");
11403 XRead =
Builder.CreateBitCast(XLoad, XElemTy,
"atomic.flt.cast");
11405 XRead =
Builder.CreateIntToPtr(XLoad, XElemTy,
"atomic.ptr.cast");
11408 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Read);
11409 Builder.CreateStore(XRead, V.Var, V.IsVolatile);
11420 assert(
X.Var->getType()->isPointerTy() &&
11421 "OMP Atomic expects a pointer to target memory");
11422 Type *XElemTy =
X.ElemTy;
11425 "OMP atomic write expected a scalar type");
11433 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11436 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11444 Builder.CreateBitCast(Expr, IntCastTy,
"atomic.src.int.cast");
11449 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Write);
11456 AtomicUpdateCallbackTy &UpdateOp,
bool IsXBinopExpr,
11457 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11463 Type *XTy =
X.Var->getType();
11465 "OMP Atomic expects a pointer to target memory");
11466 Type *XElemTy =
X.ElemTy;
11469 "OMP atomic update expected a scalar or struct type");
11472 "OpenMP atomic does not support LT or GT operations");
11476 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, RMWOp, UpdateOp,
X.IsVolatile,
11477 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11479 return AtomicResult.takeError();
11480 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Update);
11485Value *OpenMPIRBuilder::emitRMWOpAsInstruction(
Value *Src1,
Value *Src2,
11489 return Builder.CreateAdd(Src1, Src2);
11491 return Builder.CreateSub(Src1, Src2);
11493 return Builder.CreateAnd(Src1, Src2);
11495 return Builder.CreateNeg(Builder.CreateAnd(Src1, Src2));
11497 return Builder.CreateOr(Src1, Src2);
11499 return Builder.CreateXor(Src1, Src2);
11538Expected<std::pair<Value *, Value *>> OpenMPIRBuilder::emitAtomicUpdate(
11541 AtomicUpdateCallbackTy &UpdateOp,
bool VolatileX,
bool IsXBinopExpr,
11542 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11544 bool emitRMWOp =
false;
11552 emitRMWOp = XElemTy;
11555 emitRMWOp = (IsXBinopExpr && XElemTy);
11562 std::pair<Value *, Value *> Res;
11564 AtomicRMWInst *RMWInst =
11565 Builder.CreateAtomicRMW(RMWOp,
X, Expr, llvm::MaybeAlign(), AO);
11566 if (IsIgnoreDenormalMode)
11567 RMWInst->
setMetadata(llvm::LLVMContext::MD_atomic_ignore_denormal_mode,
11569 if (
T.isAMDGPU()) {
11570 if (!IsFineGrainedMemory)
11571 RMWInst->
setMetadata(
"amdgpu.no.fine.grained.memory",
11573 if (!IsRemoteMemory)
11577 Res.first = RMWInst;
11582 Res.second = Res.first;
11584 Res.second = emitRMWOpAsInstruction(Res.first, Expr, RMWOp);
11587 Builder.CreateLoad(XElemTy,
X,
X->getName() +
".atomic.load");
11593 OpenMPIRBuilder::AtomicInfo atomicInfo(
11595 OldVal->
getAlign(),
true , AllocaIP,
X);
11596 auto AtomicLoadRes = atomicInfo.EmitAtomicLoadLibcall(AO);
11599 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11606 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11607 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11608 Builder.SetInsertPoint(ContBB);
11610 PHI->addIncoming(AtomicLoadRes.first, CurBB);
11612 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11615 Value *Upd = *CBResult;
11616 Builder.CreateStore(Upd, NewAtomicAddr);
11619 auto Result = atomicInfo.EmitAtomicCompareExchangeLibcall(
11620 AtomicLoadRes.second, NewAtomicAddr, AO, Failure);
11621 LoadInst *PHILoad =
Builder.CreateLoad(XElemTy,
Result.first);
11622 PHI->addIncoming(PHILoad,
Builder.GetInsertBlock());
11625 Res.first = OldExprVal;
11628 if (UnreachableInst *ExitTI =
11631 Builder.SetInsertPoint(ExitBB);
11633 Builder.SetInsertPoint(ExitTI);
11636 IntegerType *IntCastTy =
11639 Builder.CreateLoad(IntCastTy,
X,
X->getName() +
".atomic.load");
11649 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11656 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11657 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11658 Builder.SetInsertPoint(ContBB);
11660 PHI->addIncoming(OldVal, CurBB);
11665 OldExprVal =
Builder.CreateBitCast(
PHI, XElemTy,
11666 X->getName() +
".atomic.fltCast");
11668 OldExprVal =
Builder.CreateIntToPtr(
PHI, XElemTy,
11669 X->getName() +
".atomic.ptrCast");
11673 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11676 Value *Upd = *CBResult;
11677 Builder.CreateStore(Upd, NewAtomicAddr);
11678 LoadInst *DesiredVal =
Builder.CreateLoad(IntCastTy, NewAtomicAddr);
11682 X,
PHI, DesiredVal, llvm::MaybeAlign(), AO, Failure);
11683 Result->setVolatile(VolatileX);
11684 Value *PreviousVal =
Builder.CreateExtractValue(Result, 0);
11685 Value *SuccessFailureVal =
Builder.CreateExtractValue(Result, 1);
11686 PHI->addIncoming(PreviousVal,
Builder.GetInsertBlock());
11687 Builder.CreateCondBr(SuccessFailureVal, ExitBB, ContBB);
11689 Res.first = OldExprVal;
11693 if (UnreachableInst *ExitTI =
11696 Builder.SetInsertPoint(ExitBB);
11698 Builder.SetInsertPoint(ExitTI);
11709 bool UpdateExpr,
bool IsPostfixUpdate,
bool IsXBinopExpr,
11710 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11715 Type *XTy =
X.Var->getType();
11717 "OMP Atomic expects a pointer to target memory");
11718 Type *XElemTy =
X.ElemTy;
11721 "OMP atomic capture expected a scalar or struct type");
11723 "OpenMP atomic does not support LT or GT operations");
11730 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, AtomicOp, UpdateOp,
X.IsVolatile,
11731 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11734 Value *CapturedVal =
11735 (IsPostfixUpdate ? AtomicResult->first : AtomicResult->second);
11736 Builder.CreateStore(CapturedVal, V.Var, V.IsVolatile);
11738 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Capture);
11746 bool IsFailOnly,
bool IsWeak) {
11750 IsPostfixUpdate, IsFailOnly, Failure, IsWeak);
11762 assert(
X.Var->getType()->isPointerTy() &&
11763 "OMP atomic expects a pointer to target memory");
11766 assert(V.Var->getType()->isPointerTy() &&
"v.var must be of pointer type");
11767 assert(V.ElemTy ==
X.ElemTy &&
"x and v must be of same type");
11770 bool IsInteger = E->getType()->isIntegerTy();
11772 if (
Op == OMPAtomicCompareOp::EQ) {
11775 Value *OldValue =
nullptr;
11776 Value *SuccessOrFail =
nullptr;
11814 X.Var->getName() +
".atomic.load");
11820 Value *EIsNaN =
Builder.CreateFCmpUNO(E, E,
"atomic.e.isnan");
11821 Value *XIsNaN =
Builder.CreateFCmpUNO(XFP, XFP,
"atomic.x.isnan");
11822 Value *EitherNaN =
Builder.CreateOr(EIsNaN, XIsNaN,
"atomic.either.nan");
11827 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11831 M.getContext(),
X.Var->getName() +
".atomic.nan",
F, ExitBB);
11833 M.getContext(),
X.Var->getName() +
".atomic.notnan",
F, ExitBB);
11835 M.getContext(),
X.Var->getName() +
".atomic.zero",
F, ExitBB);
11837 M.getContext(),
X.Var->getName() +
".atomic.normal",
F, ExitBB);
11841 Builder.SetInsertPoint(CurBB);
11842 Builder.CreateCondBr(EitherNaN, NaNBB, NotNaNBB);
11845 Builder.SetInsertPoint(NaNBB);
11849 Builder.SetInsertPoint(NotNaNBB);
11852 X.Var->getName() +
".atomic.xiszero");
11854 "atomic.e.iszero");
11855 Value *BothZero =
Builder.CreateAnd(XIsZero, EIsZero,
"atomic.both.zero");
11856 Builder.CreateCondBr(BothZero, ZeroBB, NormalBB);
11859 Builder.SetInsertPoint(ZeroBB);
11861 X.Var, XCurr, DBCast,
MaybeAlign(), AO, Failure);
11863 Value *OldZero =
Builder.CreateExtractValue(ResZero, 0);
11864 Value *OkZero =
Builder.CreateExtractValue(ResZero, 1);
11868 Builder.SetInsertPoint(NormalBB);
11870 X.Var, EBCast, DBCast,
MaybeAlign(), AO, Failure);
11872 Value *OldNormal =
Builder.CreateExtractValue(ResNormal, 0);
11873 Value *OkNormal =
Builder.CreateExtractValue(ResNormal, 1);
11879 Builder.CreatePHI(IntCastTy, 3,
X.Var->getName() +
".atomic.old");
11884 X.Var->getName() +
".atomic.ok");
11891 Builder.SetInsertPoint(ExitBB);
11896 OldValue =
Builder.CreateBitCast(OldIntPHI,
X.ElemTy,
11897 X.Var->getName() +
".atomic.old.fp");
11898 SuccessOrFail = SuccessPHI;
11906 Result =
Builder.CreateAtomicCmpXchg(
X.Var, EBCast, DBCast,
11912 Result->setWeak(IsWeak);
11915 OldValue =
Builder.CreateExtractValue(Result, 0);
11917 OldValue =
Builder.CreateBitCast(OldValue,
X.ElemTy);
11919 "OldValue and V must be of same type");
11920 if (IsPostfixUpdate) {
11921 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
11923 SuccessOrFail =
Builder.CreateExtractValue(Result, 1);
11927 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11929 CurBBTI,
X.Var->getName() +
".atomic.exit");
11935 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
11937 Builder.SetInsertPoint(ContBB);
11938 Builder.CreateStore(OldValue, V.Var);
11944 Builder.SetInsertPoint(ExitBB);
11946 Builder.SetInsertPoint(ExitTI);
11949 Value *CapturedValue =
11950 Builder.CreateSelect(SuccessOrFail, E, OldValue);
11951 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
11957 assert(R.Var->getType()->isPointerTy() &&
11958 "r.var must be of pointer type");
11959 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
11961 Value *SuccessFailureVal =
11962 Builder.CreateExtractValue(Result, 1);
11963 Value *ResultCast =
11964 R.IsSigned ?
Builder.CreateSExt(SuccessFailureVal, R.ElemTy)
11965 :
Builder.CreateZExt(SuccessFailureVal, R.ElemTy);
11966 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
11975 "OldValue and V must be of same type");
11976 if (IsPostfixUpdate) {
11977 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
11982 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11984 CurBBTI,
X.Var->getName() +
".atomic.exit");
11990 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
11992 Builder.SetInsertPoint(ContBB);
11993 Builder.CreateStore(OldValue, V.Var);
11999 Builder.SetInsertPoint(ExitBB);
12001 Builder.SetInsertPoint(ExitTI);
12004 Value *CapturedValue =
12005 Builder.CreateSelect(SuccessOrFail, E, OldValue);
12006 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
12012 assert(R.Var->getType()->isPointerTy() &&
12013 "r.var must be of pointer type");
12014 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
12016 Value *ResultCast = R.IsSigned
12017 ?
Builder.CreateSExt(SuccessOrFail, R.ElemTy)
12018 :
Builder.CreateZExt(SuccessOrFail, R.ElemTy);
12019 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
12023 assert((
Op == OMPAtomicCompareOp::MAX ||
Op == OMPAtomicCompareOp::MIN) &&
12024 "Op should be either max or min at this point");
12025 assert(!IsFailOnly &&
"IsFailOnly is only valid when the comparison is ==");
12036 if (IsXBinopExpr) {
12065 Value *CapturedValue =
nullptr;
12066 if (IsPostfixUpdate) {
12067 CapturedValue = OldValue;
12092 Value *NonAtomicCmp =
Builder.CreateCmp(Pred, OldValue, E);
12093 CapturedValue =
Builder.CreateSelect(NonAtomicCmp, E, OldValue);
12095 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
12099 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Compare);
12119 if (&OuterAllocaBB ==
Builder.GetInsertBlock()) {
12146 bool SubClausesPresent =
12147 (NumTeamsLower || NumTeamsUpper || ThreadLimit || IfExpr);
12149 if (!
Config.isTargetDevice() && SubClausesPresent) {
12150 assert((NumTeamsLower ==
nullptr || NumTeamsUpper !=
nullptr) &&
12151 "if lowerbound is non-null, then upperbound must also be non-null "
12152 "for bounds on num_teams");
12154 if (NumTeamsUpper ==
nullptr)
12155 NumTeamsUpper =
Builder.getInt32(0);
12157 if (NumTeamsLower ==
nullptr)
12158 NumTeamsLower = NumTeamsUpper;
12162 "argument to if clause must be an integer value");
12166 IfExpr =
Builder.CreateICmpNE(IfExpr,
12167 ConstantInt::get(IfExpr->
getType(), 0));
12168 NumTeamsUpper =
Builder.CreateSelect(
12169 IfExpr, NumTeamsUpper,
Builder.getInt32(1),
"numTeamsUpper");
12172 NumTeamsLower =
Builder.CreateSelect(
12173 IfExpr, NumTeamsLower,
Builder.getInt32(1),
"numTeamsLower");
12176 if (ThreadLimit ==
nullptr)
12177 ThreadLimit =
Builder.getInt32(0);
12181 Value *NumTeamsLowerInt32 =
12183 Value *NumTeamsUpperInt32 =
12185 Value *ThreadLimitInt32 =
12192 {Ident, ThreadNum, NumTeamsLowerInt32, NumTeamsUpperInt32,
12193 ThreadLimitInt32});
12198 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
12201 auto OI = std::make_unique<OutlineInfo>();
12202 OI->EntryBB = AllocaBB;
12203 OI->ExitBB = ExitBB;
12204 OI->OuterAllocBB = &OuterAllocaBB;
12210 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"gid",
true));
12212 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"tid",
true));
12214 auto HostPostOutlineCB = [
this, Ident,
12215 ToBeDeleted](
Function &OutlinedFn)
mutable {
12220 "there must be a single user for the outlined function");
12225 "Outlined function must have two or three arguments only");
12227 bool HasShared = OutlinedFn.
arg_size() == 3;
12235 assert(StaleCI &&
"Error while outlining - no CallInst user found for the "
12236 "outlined function.");
12237 Builder.SetInsertPoint(StaleCI);
12244 omp::RuntimeFunction::OMPRTL___kmpc_fork_teams),
12247 Builder.ClearInsertionPoint();
12249 I->eraseFromParent();
12252 if (!
Config.isTargetDevice())
12253 OI->PostOutlineCB = HostPostOutlineCB;
12257 Builder.SetInsertPoint(ExitBB);
12268 BasicBlock *OuterAllocaBB = OuterAllocIP.getNodeParent();
12270 if (OuterAllocaBB ==
Builder.GetInsertBlock()) {
12285 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
12290 if (
Config.isTargetDevice()) {
12291 auto OI = std::make_unique<OutlineInfo>();
12292 OI->OuterAllocBB = OuterAllocIP.getNodeParent();
12293 OI->EntryBB = AllocaBB;
12294 OI->ExitBB = ExitBB;
12295 OI->OuterDeallocBBs.reserve(OuterDeallocBlocks.
size());
12296 copy(OuterDeallocBlocks, OI->OuterDeallocBBs.
end());
12300 Builder.SetInsertPoint(ExitBB);
12307 std::string VarName) {
12316 return MapNamesArrayGlobal;
12321void OpenMPIRBuilder::initializeTypes(
Module &M) {
12325 unsigned ProgramAS = M.getDataLayout().getProgramAddressSpace();
12326#define OMP_TYPE(VarName, InitValue) VarName = InitValue;
12327#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \
12328 VarName##Ty = ArrayType::get(ElemTy, ArraySize); \
12329 VarName##PtrTy = PointerType::get(Ctx, DefaultTargetAS);
12330#define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) \
12331 VarName = FunctionType::get(ReturnType, {__VA_ARGS__}, IsVarArg); \
12332 VarName##Ptr = PointerType::get(Ctx, ProgramAS);
12333#define OMP_STRUCT_TYPE(VarName, StructName, Packed, ...) \
12334 T = StructType::getTypeByName(Ctx, StructName); \
12336 T = StructType::create(Ctx, {__VA_ARGS__}, StructName, Packed); \
12338 VarName##Ptr = PointerType::get(Ctx, DefaultTargetAS);
12339#include "llvm/Frontend/OpenMP/OMPKinds.def"
12350 while (!Worklist.
empty()) {
12354 if (
BlockSet.insert(SuccBB).second)
12359std::unique_ptr<CodeExtractor>
12361 bool ArgsInZeroAddressSpace,
12363 return std::make_unique<CodeExtractor>(
12373 Suffix.
str(), ArgsInZeroAddressSpace);
12376std::unique_ptr<CodeExtractor> DeviceSharedMemOutlineInfo::createCodeExtractor(
12378 return std::make_unique<DeviceSharedMemCodeExtractor>(
12379 OMPBuilder, Blocks,
nullptr,
12387 OuterDeallocBBs.empty()
12390 Suffix.
str(), ArgsInZeroAddressSpace);
12394 uint64_t
Size, int32_t Flags,
12400 Name.empty() ? Addr->
getName() : Name,
Size, Flags, 0);
12412 Fn->
addFnAttr(
"uniform-work-group-size");
12413 Fn->
addFnAttr(Attribute::MustProgress);
12431 auto &&GetMDInt = [
this](
unsigned V) {
12438 NamedMDNode *MD =
M.getOrInsertNamedMetadata(
"omp_offload.info");
12439 auto &&TargetRegionMetadataEmitter =
12440 [&
C, MD, &OrderedEntries, &GetMDInt, &GetMDString](
12455 GetMDInt(E.getKind()), GetMDInt(EntryInfo.DeviceID),
12456 GetMDInt(EntryInfo.FileID), GetMDString(EntryInfo.ParentName),
12457 GetMDInt(EntryInfo.Line), GetMDInt(EntryInfo.Count),
12458 GetMDInt(E.getOrder())};
12461 OrderedEntries[E.getOrder()] = std::make_pair(&E, EntryInfo);
12470 auto &&DeviceGlobalVarMetadataEmitter =
12471 [&
C, &OrderedEntries, &GetMDInt, &GetMDString, MD](
12481 Metadata *
Ops[] = {GetMDInt(E.getKind()), GetMDString(MangledName),
12482 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
12486 OrderedEntries[E.getOrder()] = std::make_pair(&E, varInfo);
12493 DeviceGlobalVarMetadataEmitter);
12495 for (
const auto &E : OrderedEntries) {
12496 assert(E.first &&
"All ordered entries must exist!");
12497 if (
const auto *CE =
12500 if (!CE->getID() || !CE->getAddress()) {
12504 if (!
M.getNamedValue(FnName))
12512 }
else if (
const auto *CE =
dyn_cast<
12521 if (
Config.isTargetDevice() &&
Config.hasRequiresUnifiedSharedMemory())
12523 if (!CE->getAddress()) {
12528 if (CE->getVarSize() == 0)
12532 assert(((
Config.isTargetDevice() && !CE->getAddress()) ||
12533 (!
Config.isTargetDevice() && CE->getAddress())) &&
12534 "Declaret target link address is set.");
12535 if (
Config.isTargetDevice())
12537 if (!CE->getAddress()) {
12544 if (!CE->getAddress()) {
12557 if ((
GV->hasLocalLinkage() ||
GV->hasHiddenVisibility()) &&
12561 OMPTargetGlobalVarEntryIndirectVTable))
12570 Flags, CE->getLinkage(), CE->getVarName());
12573 Flags, CE->getLinkage());
12584 if (
Config.hasRequiresFlags() && !
Config.isTargetDevice())
12590 Config.getRequiresFlags());
12600 OS <<
"_" <<
Count;
12605 unsigned NewCount = getTargetRegionEntryInfoCount(EntryInfo);
12608 EntryInfo.
Line, NewCount);
12616 auto FileIDInfo = CallBack();
12617 uint64_t FileID = 0;
12619 ID =
Status->getUniqueID();
12620 FileID =
Status->getUniqueID().getFile();
12624 FileID =
hash_value(std::get<0>(FileIDInfo));
12628 std::get<1>(FileIDInfo));
12633 for (uint64_t Remain =
12634 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12636 !(Remain & 1); Remain = Remain >> 1)
12654 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12656 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12663 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12669 Flags &=
~omp::OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
12670 Flags |= MemberOfFlag;
12676 bool IsDeclaration,
bool IsExternallyVisible,
12678 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12679 std::vector<Triple> TargetTriple,
Type *LlvmPtrTy,
12680 std::function<
Constant *()> GlobalInitializer,
12691 Config.hasRequiresUnifiedSharedMemory())) {
12696 if (!IsExternallyVisible)
12698 OS <<
"_decl_tgt_ref_ptr";
12701 Value *Ptr =
M.getNamedValue(PtrName);
12710 if (!
Config.isTargetDevice()) {
12711 if (GlobalInitializer)
12712 GV->setInitializer(GlobalInitializer());
12718 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12719 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12720 GlobalInitializer, VariableLinkage, LlvmPtrTy,
cast<Constant>(Ptr));
12732 bool IsDeclaration,
bool IsExternallyVisible,
12734 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12735 std::vector<Triple> TargetTriple,
12736 std::function<
Constant *()> GlobalInitializer,
12740 (TargetTriple.empty() && !
Config.isTargetDevice()))
12751 !
Config.hasRequiresUnifiedSharedMemory()) {
12753 VarName = MangledName;
12756 if (!IsDeclaration)
12758 M.getDataLayout().getTypeSizeInBits(LlvmVal->
getValueType()), 8);
12761 Linkage = (VariableLinkage) ? VariableLinkage() : LlvmVal->
getLinkage();
12765 if (
Config.isTargetDevice() &&
12774 if (!
M.getNamedValue(RefName)) {
12778 GvAddrRef->setConstant(
true);
12780 GvAddrRef->setInitializer(Addr);
12781 GeneratedRefs.push_back(GvAddrRef);
12790 if (
Config.isTargetDevice()) {
12791 VarName = (Addr) ? Addr->
getName() :
"";
12795 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12796 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12797 LlvmPtrTy, GlobalInitializer, VariableLinkage);
12798 VarName = (Addr) ? Addr->
getName() :
"";
12800 VarSize =
M.getDataLayout().getPointerSize();
12819 auto &&GetMDInt = [MN](
unsigned Idx) {
12824 auto &&GetMDString = [MN](
unsigned Idx) {
12826 return V->getString();
12829 switch (GetMDInt(0)) {
12833 case OffloadEntriesInfoManager::OffloadEntryInfo::
12834 OffloadingEntryInfoTargetRegion: {
12844 case OffloadEntriesInfoManager::OffloadEntryInfo::
12845 OffloadingEntryInfoDeviceGlobalVar:
12858 if (HostFilePath.
empty())
12862 if (std::error_code Err = Buf.getError()) {
12864 "OpenMPIRBuilder: " +
12872 if (std::error_code Err =
M.getError()) {
12874 (
"error parsing host file inside of OpenMPIRBuilder: " + Err.message())
12888 "expected a valid insertion block for creating an iterator loop");
12892 if (SplitIP == CurBB->
end())
12894 SplitIP = Terminator->getIterator();
12898 Builder.getCurrentDebugLocation(),
"omp.it.cont");
12910 T->eraseFromParent();
12925 bool ReachesLatch =
false;
12928 while (!Worklist.
empty()) {
12933 "iterator bodygen must leave at most one unterminated block",
12939 if (Succ == Latch) {
12940 ReachesLatch =
true;
12945 "iterator bodygen must not branch out of the loop body",
12947 if (Visited.
insert(Succ).second)
12953 Builder.SetInsertPoint(OpenBB);
12955 }
else if (!ReachesLatch) {
12965 return ContBB->
begin();
12975 for (
const auto &
ParamAttr : ParamAttrs) {
13018 return std::string(Out.str());
13026 unsigned VecRegSize;
13028 ISADataTy ISAData[] = {
13047 for (
char Mask :
Masked) {
13048 for (
const ISADataTy &
Data : ISAData) {
13051 Out <<
"_ZGV" <<
Data.ISA << Mask;
13053 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
13067template <
typename T>
13070 StringRef MangledName,
bool OutputBecomesInput,
13074 Out << Prefix << ISA << LMask << VLEN;
13075 if (OutputBecomesInput)
13077 Out << ParSeq <<
'_' << MangledName;
13086 bool OutputBecomesInput,
13091 OutputBecomesInput, Fn);
13093 OutputBecomesInput, Fn);
13097 OutputBecomesInput, Fn);
13099 OutputBecomesInput, Fn);
13103 OutputBecomesInput, Fn);
13105 OutputBecomesInput, Fn);
13110 OutputBecomesInput, Fn);
13121 char ISA,
unsigned NarrowestDataSize,
bool OutputBecomesInput) {
13122 assert((ISA ==
'n' || ISA ==
's') &&
"Expected ISA either 's' or 'n'.");
13134 OutputBecomesInput, Fn);
13141 OutputBecomesInput, Fn);
13143 OutputBecomesInput, Fn);
13147 OutputBecomesInput, Fn);
13151 OutputBecomesInput, Fn);
13160 OutputBecomesInput, Fn);
13167 MangledName, OutputBecomesInput, Fn);
13169 MangledName, OutputBecomesInput, Fn);
13173 MangledName, OutputBecomesInput, Fn);
13177 MangledName, OutputBecomesInput, Fn);
13187 return OffloadEntriesTargetRegion.empty() &&
13188 OffloadEntriesDeviceGlobalVar.empty();
13191unsigned OffloadEntriesInfoManager::getTargetRegionEntryInfoCount(
13193 auto It = OffloadEntriesTargetRegionCount.find(
13194 getTargetRegionEntryCountKey(EntryInfo));
13195 if (It == OffloadEntriesTargetRegionCount.end())
13200void OffloadEntriesInfoManager::incrementTargetRegionEntryInfoCount(
13202 OffloadEntriesTargetRegionCount[getTargetRegionEntryCountKey(EntryInfo)] =
13203 EntryInfo.
Count + 1;
13209 OffloadEntriesTargetRegion[EntryInfo] =
13212 ++OffloadingEntriesNum;
13218 assert(EntryInfo.
Count == 0 &&
"expected default EntryInfo");
13221 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
13225 if (OMPBuilder->Config.isTargetDevice()) {
13230 auto &Entry = OffloadEntriesTargetRegion[EntryInfo];
13231 Entry.setAddress(Addr);
13233 Entry.setFlags(Flags);
13239 "Target region entry already registered!");
13241 OffloadEntriesTargetRegion[EntryInfo] = Entry;
13242 ++OffloadingEntriesNum;
13244 incrementTargetRegionEntryInfoCount(EntryInfo);
13251 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
13253 auto It = OffloadEntriesTargetRegion.find(EntryInfo);
13254 if (It == OffloadEntriesTargetRegion.end()) {
13258 if (!IgnoreAddressId && (It->second.getAddress() || It->second.getID()))
13266 for (
const auto &It : OffloadEntriesTargetRegion) {
13267 Action(It.first, It.second);
13273 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
13274 ++OffloadingEntriesNum;
13280 if (OMPBuilder->Config.isTargetDevice()) {
13284 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
13286 if (Entry.getVarSize() == 0) {
13287 Entry.setVarSize(VarSize);
13288 Entry.setLinkage(Linkage);
13292 Entry.setVarSize(VarSize);
13293 Entry.setLinkage(Linkage);
13294 Entry.setAddress(Addr);
13297 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
13298 assert(Entry.isValid() && Entry.getFlags() == Flags &&
13299 "Entry not initialized!");
13300 if (Entry.getVarSize() == 0) {
13301 Entry.setVarSize(VarSize);
13302 Entry.setLinkage(Linkage);
13309 OffloadEntriesDeviceGlobalVar.try_emplace(VarName, OffloadingEntriesNum,
13310 Addr, VarSize, Flags, Linkage,
13313 OffloadEntriesDeviceGlobalVar.try_emplace(
13314 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage,
"");
13315 ++OffloadingEntriesNum;
13322 for (
const auto &E : OffloadEntriesDeviceGlobalVar)
13323 Action(E.getKey(), E.getValue());
13330void CanonicalLoopInfo::collectControlBlocks(
13337 BBs.
append({getPreheader(), Header,
Cond, Latch, Exit, getAfter()});
13349void CanonicalLoopInfo::setTripCount(
Value *TripCount) {
13361void CanonicalLoopInfo::mapIndVar(
13371 for (
Use &U : OldIV->
uses()) {
13375 if (
User->getParent() == getCond())
13377 if (
User->getParent() == getLatch())
13383 Value *NewIV = Updater(OldIV);
13386 for (Use *U : ReplacableUses)
13407 "Preheader must terminate with unconditional branch");
13409 "Preheader must jump to header");
13413 "Header must terminate with unconditional branch");
13414 assert(Header->getSingleSuccessor() == Cond &&
13415 "Header must jump to exiting block");
13418 assert(Cond->getSinglePredecessor() == Header &&
13419 "Exiting block only reachable from header");
13422 "Exiting block must terminate with conditional branch");
13424 "Exiting block's first successor jump to the body");
13426 "Exiting block's second successor must exit the loop");
13430 "Body only reachable from exiting block");
13435 "Latch must terminate with unconditional branch");
13436 assert(Latch->getSingleSuccessor() == Header &&
"Latch must jump to header");
13439 assert(Latch->getSinglePredecessor() !=
nullptr);
13444 "Exit block must terminate with unconditional branch");
13445 assert(Exit->getSingleSuccessor() == After &&
13446 "Exit block must jump to after block");
13450 "After block only reachable from exit block");
13454 assert(IndVar &&
"Canonical induction variable not found?");
13456 "Induction variable must be an integer");
13458 "Induction variable must be a PHI in the loop header");
13464 auto *NextIndVar =
cast<PHINode>(IndVar)->getIncomingValue(1);
13472 assert(TripCount &&
"Loop trip count not found?");
13474 "Trip count and induction variable must have the same type");
13478 "Exit condition must be a signed less-than comparison");
13480 "Exit condition must compare the induction variable");
13482 "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)
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.
Common base class shared among various IRBuilders.
InsertPoint saveIP() const
Returns the current insert point.
BasicBlock::iterator InsertPoint
InsertPoint - A saved insertion point.
void restoreIP(InsertPoint IP)
Sets the current insert point to a previously-saved location.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI void removeFromParent()
This method unlinks 'this' from the containing basic block, but does not delete it.
LLVM_ABI unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI void moveBefore(InstListType::iterator InsertPos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
LLVM_ABI BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY
Return the specified successor. This instruction must be a terminator.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
user_iterator user_begin()
LLVM_ABI void moveBeforePreserving(InstListType::iterator MovePos)
Perform a moveBefore operation, while signalling that the caller intends to preserve the original ord...
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI void insertAfter(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately after the specified instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this load instruction.
Align getAlign() const
Return the alignment of the access that is being performed.
Analysis pass that exposes the LoopInfo for a function.
LLVM_ABI LoopInfo run(Function &F, FunctionAnalysisManager &AM)
ArrayRef< BlockT * > getBlocks() const
Get a list of the basic blocks which make up this loop.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
This class represents a loop nest and can be used to query its properties.
Represents a single loop in the control flow graph.
LLVM_ABI MDNode * createCallbackEncoding(unsigned CalleeArgNo, ArrayRef< int > Arguments, bool VarArgsArePassed)
Return metadata describing a callback (see llvm::AbstractCallSite).
LLVM_ABI void replaceOperandWith(unsigned I, Metadata *New)
Replace a specific operand.
static MDTuple * getDistinct(LLVMContext &Context, ArrayRef< Metadata * > MDs)
ArrayRef< MDOperand > operands() const
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
This class implements a map that also provides access to all stored values in a deterministic order.
A Module instance is used to store all the information related to an LLVM module.
LLVMContext & getContext() const
Get the global data context.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
iterator_range< op_iterator > operands()
LLVM_ABI void addOperand(MDNode *M)
Device global variable entries info.
Target region entries info.
Base class of the entries info.
Class that manages information about offload code regions and data.
function_ref< void(StringRef, const OffloadEntryInfoDeviceGlobalVar &)> OffloadDeviceGlobalVarEntryInfoActTy
Applies action Action on all registered entries.
OMPTargetDeviceClauseKind
Kind of device clause for declare target variables and functions NOTE: Currently not used as a part o...
@ OMPTargetDeviceClauseAny
The target is marked for all devices.
LLVM_ABI void registerDeviceGlobalVarEntryInfo(StringRef VarName, Constant *Addr, int64_t VarSize, OMPTargetGlobalVarEntryKind Flags, GlobalValue::LinkageTypes Linkage)
Register device global variable entry.
LLVM_ABI void initializeDeviceGlobalVarEntryInfo(StringRef Name, OMPTargetGlobalVarEntryKind Flags, unsigned Order)
Initialize device global variable entry.
LLVM_ABI void actOnDeviceGlobalVarEntriesInfo(const OffloadDeviceGlobalVarEntryInfoActTy &Action)
OMPTargetRegionEntryKind
Kind of the target registry entry.
@ OMPTargetRegionEntryTargetRegion
Mark the entry as target region.
LLVM_ABI void getTargetRegionEntryFnName(SmallVectorImpl< char > &Name, const TargetRegionEntryInfo &EntryInfo)
LLVM_ABI bool hasTargetRegionEntryInfo(TargetRegionEntryInfo EntryInfo, bool IgnoreAddressId=false) const
Return true if a target region entry with the provided information exists.
LLVM_ABI void registerTargetRegionEntryInfo(TargetRegionEntryInfo EntryInfo, Constant *Addr, Constant *ID, OMPTargetRegionEntryKind Flags)
Register target region entry.
LLVM_ABI void actOnTargetRegionEntriesInfo(const OffloadTargetRegionEntryInfoActTy &Action)
LLVM_ABI void initializeTargetRegionEntryInfo(const TargetRegionEntryInfo &EntryInfo, unsigned Order)
Initialize target region entry.
OMPTargetGlobalVarEntryKind
Kind of the global variable entry..
@ OMPTargetGlobalVarEntryEnter
Mark the entry as a declare target enter.
@ OMPTargetGlobalRegisterRequires
Mark the entry as a register requires global.
@ OMPTargetGlobalVarEntryIndirect
Mark the entry as a declare target indirect global.
@ OMPTargetGlobalVarEntryLink
Mark the entry as a to declare target link.
@ OMPTargetGlobalVarEntryTo
Mark the entry as a to declare target.
@ OMPTargetGlobalVarEntryIndirectVTable
Mark the entry as a declare target indirect vtable.
function_ref< void(const TargetRegionEntryInfo &EntryInfo, const OffloadEntryInfoTargetRegion &)> OffloadTargetRegionEntryInfoActTy
brief Applies action Action on all registered entries.
bool hasDeviceGlobalVarEntryInfo(StringRef VarName) const
Checks if the variable with the given name has been registered already.
LLVM_ABI bool empty() const
Return true if a there are no entries defined.
std::optional< bool > IsTargetDevice
Flag to define whether to generate code for the role of the OpenMP host (if set to false) or device (...
std::optional< bool > IsGPU
Flag for specifying if the compilation is done for an accelerator.
LLVM_ABI int64_t getRequiresFlags() const
Returns requires directive clauses as flags compatible with those expected by libomptarget.
std::optional< bool > OpenMPOffloadMandatory
Flag for specifying if offloading is mandatory.
LLVM_ABI void setHasRequiresReverseOffload(bool Value)
LLVM_ABI OpenMPIRBuilderConfig()
LLVM_ABI bool hasRequiresUnifiedSharedMemory() const
LLVM_ABI void setHasRequiresUnifiedSharedMemory(bool Value)
unsigned getDefaultTargetAS() const
LLVM_ABI bool hasRequiresDynamicAllocators() const
LLVM_ABI void setHasRequiresUnifiedAddress(bool Value)
bool isTargetDevice() const
LLVM_ABI void setHasRequiresDynamicAllocators(bool Value)
LLVM_ABI bool hasRequiresReverseOffload() const
bool hasRequiresFlags() const
LLVM_ABI bool hasRequiresUnifiedAddress() const
Struct that keeps the information that should be kept throughout a 'target data' region.
An interface to create LLVM-IR for OpenMP directives.
LLVM_ABI InsertPointOrErrorTy createOrderedThreadsSimd(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, bool IsThreads)
Generator for 'omp ordered [threads | simd]'.
LLVM_ABI void emitAArch64DeclareSimdFunction(llvm::Function *Fn, unsigned VLENVal, llvm::ArrayRef< DeclareSimdAttrTy > ParamAttrs, DeclareSimdBranch Branch, char ISA, unsigned NarrowestDataSize, bool OutputBecomesInput)
Emit AArch64 vector-function ABI attributes for a declare simd function.
LLVM_ABI Constant * getOrCreateIdent(Constant *SrcLocStr, uint32_t SrcLocStrSize, omp::IdentFlag Flags=omp::IdentFlag(0), unsigned Reserve2Flags=0)
Return an ident_t* encoding the source location SrcLocStr and Flags.
LLVM_ABI void registerDeclareTargetGlobalReplacement(GlobalValue *Original, GlobalValue *Replacement)
Register a module-scope replacement of a declare target global variable.
LLVM_ABI FunctionCallee getOrCreateRuntimeFunction(Module &M, omp::RuntimeFunction FnID)
Return the function declaration for the runtime function with FnID.
LLVM_ABI InsertPointOrErrorTy createCancel(const LocationDescription &Loc, Value *IfCondition, omp::Directive CanceledDirective)
Generator for 'omp cancel'.
std::function< Expected< Function * >(StringRef FunctionName)> FunctionGenCallback
Functions used to generate a function with the given name.
LLVM_ABI CallInst * createOMPAllocShared(const LocationDescription &Loc, Value *Size, const Twine &Name=Twine(""))
Create a runtime call for kmpc_alloc_shared.
ReductionGenCBKind
Enum class for the RedctionGen CallBack type to be used.
LLVM_ABI CanonicalLoopInfo * collapseLoops(DebugLoc DL, ArrayRef< CanonicalLoopInfo * > Loops, InsertPointTy ComputeIP)
Collapse a loop nest 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 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.
LLVM_ABI InsertPointOrErrorTy applyWorkshareLoop(DebugLoc DL, CanonicalLoopInfo *CLI, InsertPointTy AllocaIP, bool NeedsBarrier, llvm::omp::ScheduleKind SchedKind=llvm::omp::OMP_SCHEDULE_Default, Value *ChunkSize=nullptr, bool HasSimdModifier=false, bool HasMonotonicModifier=false, bool HasNonmonotonicModifier=false, bool HasOrderedClause=false, omp::WorksharingLoopType LoopType=omp::WorksharingLoopType::ForStaticLoop, bool NoLoop=false, bool HasDistSchedule=false, Value *DistScheduleChunkSize=nullptr, bool NeedsLastIter=false)
Modifies the canonical loop to be a workshare loop.
Expected< InsertPointTy > InsertPointOrErrorTy
Type used to represent an insertion point or an error value.
LLVM_ABI InsertPointTy createCopyPrivate(const LocationDescription &Loc, llvm::Value *BufSize, llvm::Value *CpyBuf, llvm::Value *CpyFn, llvm::Value *DidIt)
Generator for __kmpc_copyprivate.
LLVM_ABI InsertPointOrErrorTy createSections(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< StorableBodyGenCallbackTy > SectionCBs, PrivatizeCallbackTy PrivCB, FinalizeCallbackTy FiniCB, bool IsCancellable, bool IsNowait)
Generator for 'omp sections'.
std::function< void(EmitMetadataErrorKind, TargetRegionEntryInfo)> EmitMetadataErrorReportFunctionTy
Callback function type.
function_ref< InsertPointOrErrorTy( Argument &Arg, Value *Input, Value *&RetVal, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, ArrayRef< InsertPointTy > DeallocIPs)> TargetGenArgAccessorsCallbackTy
LLVM_ABI Expected< ScanInfo * > scanInfoInitialize()
Creates a ScanInfo object, allocates and returns the pointer.
LLVM_ABI InsertPointOrErrorTy emitTargetTask(TargetTaskBodyCallbackTy TaskBodyCB, Value *DeviceID, Value *RTLoc, OpenMPIRBuilder::InsertPointTy AllocaIP, const DependenciesInfo &Dependencies, const TargetDataRTArgs &RTArgs, bool HasNoWait)
Generate a target-task for the target construct.
LLVM_ABI InsertPointTy createAtomicRead(const LocationDescription &Loc, AtomicOpValue &X, AtomicOpValue &V, AtomicOrdering AO, InsertPointTy AllocaIP)
Emit atomic Read for : V = X — Only Scalar data types.
function_ref< Error(InsertPointTy AllocaIP, InsertPointTy CodeGenIP, ArrayRef< BasicBlock * > DeallocBlocks)> BodyGenCallbackTy
Callback type for body (=inner region) code generation.
bool updateToLocation(const LocationDescription &Loc)
Update the internal location to Loc.
LLVM_ABI void createFlush(const LocationDescription &Loc)
Generator for 'omp flush'.
LLVM_ABI Constant * getAddrOfDeclareTargetVar(OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind CaptureClause, OffloadEntriesInfoManager::OMPTargetDeviceClauseKind DeviceClause, bool IsDeclaration, bool IsExternallyVisible, TargetRegionEntryInfo EntryInfo, StringRef MangledName, std::vector< GlobalVariable * > &GeneratedRefs, bool OpenMPSIMD, std::vector< Triple > TargetTriple, Type *LlvmPtrTy, std::function< Constant *()> GlobalInitializer, std::function< GlobalValue::LinkageTypes()> VariableLinkage)
Retrieve (or create if non-existent) the address of a declare target variable, used in conjunction wi...
LLVM_ABI void createTaskwait(const LocationDescription &Loc, DependenciesInfo Dependencies={}, bool IsNowait=false)
Generator for 'omp taskwait'.
origPtr *with the address space normalization required by the runtime entry point *The NULL descriptor makes the runtime walk the enclosing taskgroups to *find the matching task_reduction registration for the item The lookups *are emitted at p Loc
EmitMetadataErrorKind
The kind of errors that can occur when emitting the offload entries and metadata.
@ EMIT_MD_DECLARE_TARGET_ERROR
@ EMIT_MD_GLOBAL_VAR_INDIRECT_ERROR
@ EMIT_MD_GLOBAL_VAR_LINK_ERROR
@ EMIT_MD_TARGET_REGION_ERROR
unsigned getOpcode() const
Return the opcode for this Instruction or ConstantExpr.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
Pseudo-analysis pass that exposes the PassInstrumentation to pass managers.
Class to represent pointers.
static PointerType * getUnqual(LLVMContext &C)
This constructs an opaque pointer to an object in the default address space (address space zero).
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
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.
OMPAtomicCompareOp
Atomic compare operations. Currently OpenMP only supports ==, >, and <.
EnumSet< Property > Properties
NodeAddr< PhiNode * > Phi
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
LLVM_ABI BasicBlock * splitBBWithSuffix(IRBuilderBase &Builder, bool CreateBranch, llvm::Twine Suffix=".split")
Like splitBB, but reuses the current block's name for the new name.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
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,...
@ End
Run the machine verifier once, at the end of the pipeline.
static auto filterDbgVars(iterator_range< simple_ilist< DbgRecord >::iterator > R)
Filter the DbgRecord range to DbgVariableRecord types only and downcast.
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),...