68#define DEBUG_TYPE "openmp-ir-builder"
75 cl::desc(
"Use optimistic attributes describing "
76 "'as-if' properties of runtime calls."),
80 "openmp-ir-builder-unroll-threshold-factor",
cl::Hidden,
81 cl::desc(
"Factor for the unroll threshold to account for code "
82 "simplifications still taking place"),
86 "openmp-ir-builder-use-default-max-threads",
cl::Hidden,
97 if (!IP1.isValid() || !IP2.isValid())
104 switch (SchedType & ~OMPScheduleType::MonotonicityMask) {
105 case OMPScheduleType::UnorderedStaticChunked:
106 case OMPScheduleType::UnorderedStatic:
107 case OMPScheduleType::UnorderedDynamicChunked:
108 case OMPScheduleType::UnorderedGuidedChunked:
109 case OMPScheduleType::UnorderedRuntime:
110 case OMPScheduleType::UnorderedAuto:
111 case OMPScheduleType::UnorderedTrapezoidal:
112 case OMPScheduleType::UnorderedGreedy:
113 case OMPScheduleType::UnorderedBalanced:
114 case OMPScheduleType::UnorderedGuidedIterativeChunked:
115 case OMPScheduleType::UnorderedGuidedAnalyticalChunked:
116 case OMPScheduleType::UnorderedSteal:
117 case OMPScheduleType::UnorderedStaticBalancedChunked:
118 case OMPScheduleType::UnorderedGuidedSimd:
119 case OMPScheduleType::UnorderedRuntimeSimd:
120 case OMPScheduleType::OrderedStaticChunked:
121 case OMPScheduleType::OrderedStatic:
122 case OMPScheduleType::OrderedDynamicChunked:
123 case OMPScheduleType::OrderedGuidedChunked:
124 case OMPScheduleType::OrderedRuntime:
125 case OMPScheduleType::OrderedAuto:
126 case OMPScheduleType::OrderdTrapezoidal:
127 case OMPScheduleType::NomergeUnorderedStaticChunked:
128 case OMPScheduleType::NomergeUnorderedStatic:
129 case OMPScheduleType::NomergeUnorderedDynamicChunked:
130 case OMPScheduleType::NomergeUnorderedGuidedChunked:
131 case OMPScheduleType::NomergeUnorderedRuntime:
132 case OMPScheduleType::NomergeUnorderedAuto:
133 case OMPScheduleType::NomergeUnorderedTrapezoidal:
134 case OMPScheduleType::NomergeUnorderedGreedy:
135 case OMPScheduleType::NomergeUnorderedBalanced:
136 case OMPScheduleType::NomergeUnorderedGuidedIterativeChunked:
137 case OMPScheduleType::NomergeUnorderedGuidedAnalyticalChunked:
138 case OMPScheduleType::NomergeUnorderedSteal:
139 case OMPScheduleType::NomergeOrderedStaticChunked:
140 case OMPScheduleType::NomergeOrderedStatic:
141 case OMPScheduleType::NomergeOrderedDynamicChunked:
142 case OMPScheduleType::NomergeOrderedGuidedChunked:
143 case OMPScheduleType::NomergeOrderedRuntime:
144 case OMPScheduleType::NomergeOrderedAuto:
145 case OMPScheduleType::NomergeOrderedTrapezoidal:
146 case OMPScheduleType::OrderedDistributeChunked:
147 case OMPScheduleType::OrderedDistribute:
155 SchedType & OMPScheduleType::MonotonicityMask;
156 if (MonotonicityFlags == OMPScheduleType::MonotonicityMask)
170 Builder.restoreIP(IP);
174 if (Builder.GetInsertPoint() != BB->
end())
184 unsigned Line = FSP->getScopeLine() ? FSP->getScopeLine() : FSP->getLine();
185 Builder.SetCurrentDebugLocation(
191 return T.isAMDGPU() ||
T.isNVPTX() ||
T.isSPIRV();
197 Kernel->getFnAttribute(
"target-features").getValueAsString();
198 if (Features.
count(
"+wavefrontsize64"))
213 bool HasSimdModifier,
bool HasDistScheduleChunks) {
215 switch (ClauseKind) {
216 case OMP_SCHEDULE_Default:
217 case OMP_SCHEDULE_Static:
218 return HasChunks ? OMPScheduleType::BaseStaticChunked
219 : OMPScheduleType::BaseStatic;
220 case OMP_SCHEDULE_Dynamic:
221 return OMPScheduleType::BaseDynamicChunked;
222 case OMP_SCHEDULE_Guided:
223 return HasSimdModifier ? OMPScheduleType::BaseGuidedSimd
224 : OMPScheduleType::BaseGuidedChunked;
225 case OMP_SCHEDULE_Auto:
227 case OMP_SCHEDULE_Runtime:
228 return HasSimdModifier ? OMPScheduleType::BaseRuntimeSimd
229 : OMPScheduleType::BaseRuntime;
230 case OMP_SCHEDULE_Distribute:
231 return HasDistScheduleChunks ? OMPScheduleType::BaseDistributeChunked
232 : OMPScheduleType::BaseDistribute;
240 bool HasOrderedClause) {
241 assert((BaseScheduleType & OMPScheduleType::ModifierMask) ==
242 OMPScheduleType::None &&
243 "Must not have ordering nor monotonicity flags already set");
246 ? OMPScheduleType::ModifierOrdered
247 : OMPScheduleType::ModifierUnordered;
251 if (OrderingScheduleType ==
252 (OMPScheduleType::BaseGuidedSimd | OMPScheduleType::ModifierOrdered))
253 return OMPScheduleType::OrderedGuidedChunked;
254 else if (OrderingScheduleType == (OMPScheduleType::BaseRuntimeSimd |
255 OMPScheduleType::ModifierOrdered))
256 return OMPScheduleType::OrderedRuntime;
258 return OrderingScheduleType;
264 bool HasSimdModifier,
bool HasMonotonic,
265 bool HasNonmonotonic,
bool HasOrderedClause) {
266 assert((ScheduleType & OMPScheduleType::MonotonicityMask) ==
267 OMPScheduleType::None &&
268 "Must not have monotonicity flags already set");
269 assert((!HasMonotonic || !HasNonmonotonic) &&
270 "Monotonic and Nonmonotonic are contradicting each other");
273 return ScheduleType | OMPScheduleType::ModifierMonotonic;
274 }
else if (HasNonmonotonic) {
275 return ScheduleType | OMPScheduleType::ModifierNonmonotonic;
285 if ((BaseScheduleType == OMPScheduleType::BaseStatic) ||
286 (BaseScheduleType == OMPScheduleType::BaseStaticChunked) ||
292 return ScheduleType | OMPScheduleType::ModifierNonmonotonic;
300 bool HasSimdModifier,
bool HasMonotonicModifier,
301 bool HasNonmonotonicModifier,
bool HasOrderedClause,
302 bool HasDistScheduleChunks) {
304 ClauseKind, HasChunks, HasSimdModifier, HasDistScheduleChunks);
308 OrderedSchedule, HasSimdModifier, HasMonotonicModifier,
309 HasNonmonotonicModifier, HasOrderedClause);
317static std::optional<omp::OMPTgtExecModeFlags>
322 if (
Call->getCalledFunction()->getName() ==
"__kmpc_target_init") {
323 TargetInitCall =
Call;
348 std::optional<omp::OMPTgtExecModeFlags> ExecMode =
360 if (
Instruction *Term = Source->getTerminatorOrNull()) {
369 NewBr->setDebugLoc(
DL);
374 assert(New->getFirstInsertionPt() == New->begin() &&
375 "Target BB must not have PHI nodes");
391 New->splice(New->begin(), Old, IP, Old->
end());
395 NewBr->setDebugLoc(
DL);
407 Builder.SetInsertPoint(Old);
411 Builder.SetCurrentDebugLocation(
DebugLoc);
421 New->replaceSuccessorsPhiUsesWith(Old, New);
430 Builder.SetInsertPoint(Builder.GetInsertBlock()->getTerminator());
432 Builder.SetInsertPoint(Builder.GetInsertBlock());
435 Builder.SetCurrentDebugLocation(
DebugLoc);
444 Builder.SetInsertPoint(Builder.GetInsertBlock()->getTerminator());
446 Builder.SetInsertPoint(Builder.GetInsertBlock());
449 Builder.SetCurrentDebugLocation(
DebugLoc);
466 const Twine &Name =
"",
bool AsPtr =
true,
467 bool Is64Bit =
false) {
468 Builder.restoreIP(OuterAllocaIP);
472 Builder.CreateAlloca(IntTy,
nullptr, Name +
".addr");
476 FakeVal = FakeValAddr;
481 FakeValAddr, Builder.getPtrTy(), Name +
".ascast"));
485 FakeVal = Builder.CreateLoad(IntTy, FakeValAddr, Name +
".val");
490 Builder.restoreIP(InnerAllocaIP);
493 UseFakeVal = Builder.CreateLoad(IntTy, FakeVal, Name +
".use");
496 FakeVal, Is64Bit ? Builder.getInt64(10) : Builder.getInt32(10)));
509enum OpenMPOffloadingRequiresDirFlags {
511 OMP_REQ_UNDEFINED = 0x000,
513 OMP_REQ_NONE = 0x001,
515 OMP_REQ_REVERSE_OFFLOAD = 0x002,
517 OMP_REQ_UNIFIED_ADDRESS = 0x004,
519 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008,
521 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010,
528 DominatorTree *DT =
nullptr,
bool AggregateArgs =
false,
529 BlockFrequencyInfo *BFI =
nullptr,
530 BranchProbabilityInfo *BPI =
nullptr,
531 AssumptionCache *AC =
nullptr,
bool AllowVarArgs =
false,
532 bool AllowAlloca =
false,
533 BasicBlock *AllocationBlock =
nullptr,
535 std::string Suffix =
"",
bool ArgsInZeroAddressSpace =
false)
536 : CodeExtractor(BBs, DT, AggregateArgs, BFI, BPI, AC, AllowVarArgs,
537 AllowAlloca, AllocationBlock, DeallocationBlocks, Suffix,
538 ArgsInZeroAddressSpace),
539 OMPBuilder(OMPBuilder) {}
541 virtual ~OMPCodeExtractor() =
default;
544 OpenMPIRBuilder &OMPBuilder;
547class DeviceSharedMemCodeExtractor :
public OMPCodeExtractor {
549 using OMPCodeExtractor::OMPCodeExtractor;
550 virtual ~DeviceSharedMemCodeExtractor() =
default;
554 allocateVar(IRBuilder<>::InsertPoint AllocaIP,
DebugLoc DL,
Type *VarType,
555 const Twine &Name = Twine(
""),
556 AddrSpaceCastInst **CastedAlloc =
nullptr)
override {
557 return OMPBuilder.createOMPAllocShared({AllocaIP,
DL}, VarType,
Name);
560 virtual Instruction *deallocateVar(IRBuilder<>::InsertPoint DeallocIP,
562 Type *VarType)
override {
563 return OMPBuilder.createOMPFreeShared({DeallocIP,
DL}, Var, VarType);
570 OpenMPIRBuilder &OMPBuilder;
572 DeviceSharedMemOutlineInfo(OpenMPIRBuilder &OMPBuilder)
573 : OMPBuilder(OMPBuilder) {}
574 virtual ~DeviceSharedMemOutlineInfo() =
default;
576 virtual std::unique_ptr<CodeExtractor>
578 bool ArgsInZeroAddressSpace,
579 Twine Suffix = Twine(
""))
override;
585 : RequiresFlags(OMP_REQ_UNDEFINED) {}
589 bool HasRequiresReverseOffload,
bool HasRequiresUnifiedAddress,
590 bool HasRequiresUnifiedSharedMemory,
bool HasRequiresDynamicAllocators)
593 RequiresFlags(OMP_REQ_UNDEFINED) {
594 if (HasRequiresReverseOffload)
595 RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
596 if (HasRequiresUnifiedAddress)
597 RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
598 if (HasRequiresUnifiedSharedMemory)
599 RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
600 if (HasRequiresDynamicAllocators)
601 RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
605 return RequiresFlags & OMP_REQ_REVERSE_OFFLOAD;
609 return RequiresFlags & OMP_REQ_UNIFIED_ADDRESS;
613 return RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY;
617 return RequiresFlags & OMP_REQ_DYNAMIC_ALLOCATORS;
622 :
static_cast<int64_t
>(OMP_REQ_NONE);
627 RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
629 RequiresFlags &= ~OMP_REQ_REVERSE_OFFLOAD;
634 RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
636 RequiresFlags &= ~OMP_REQ_UNIFIED_ADDRESS;
641 RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
643 RequiresFlags &= ~OMP_REQ_UNIFIED_SHARED_MEMORY;
648 RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
650 RequiresFlags &= ~OMP_REQ_DYNAMIC_ALLOCATORS;
663 constexpr size_t MaxDim = 3;
668 Value *DynCGroupMemFallbackFlag =
670 DynCGroupMemFallbackFlag =
Builder.CreateShl(DynCGroupMemFallbackFlag, 2);
675 StrictBlocksFlag =
Builder.CreateShl(StrictBlocksFlag, 6);
676 StrictThreadsFlag =
Builder.CreateShl(StrictThreadsFlag, 7);
678 Value *Flags =
Builder.CreateOr(HasNoWaitFlag, DynCGroupMemFallbackFlag);
679 Flags =
Builder.CreateOr(Flags, StrictBlocksFlag);
680 Flags =
Builder.CreateOr(Flags, StrictThreadsFlag);
686 Value *NumThreads3D =
717 auto FnAttrs = Attrs.getFnAttrs();
718 auto RetAttrs = Attrs.getRetAttrs();
720 for (
size_t ArgNo = 0; ArgNo < Fn.
arg_size(); ++ArgNo)
725 bool Param =
true) ->
void {
726 bool HasSignExt = AS.hasAttribute(Attribute::SExt);
727 bool HasZeroExt = AS.hasAttribute(Attribute::ZExt);
728 if (HasSignExt || HasZeroExt) {
729 assert(AS.getNumAttributes() == 1 &&
730 "Currently not handling extension attr combined with others.");
732 if (
auto AK = TargetLibraryInfo::getExtAttrForI32Param(
T, HasSignExt))
735 TargetLibraryInfo::getExtAttrForI32Return(
T, HasSignExt))
742#define OMP_ATTRS_SET(VarName, AttrSet) AttributeSet VarName = AttrSet;
743#include "llvm/Frontend/OpenMP/OMPKinds.def"
747#define OMP_RTL_ATTRS(Enum, FnAttrSet, RetAttrSet, ArgAttrSets) \
749 FnAttrs = FnAttrs.addAttributes(Ctx, FnAttrSet); \
750 addAttrSet(RetAttrs, RetAttrSet, false); \
751 for (size_t ArgNo = 0; ArgNo < ArgAttrSets.size(); ++ArgNo) \
752 addAttrSet(ArgAttrs[ArgNo], ArgAttrSets[ArgNo]); \
753 Fn.setAttributes(AttributeList::get(Ctx, FnAttrs, RetAttrs, ArgAttrs)); \
755#include "llvm/Frontend/OpenMP/OMPKinds.def"
769#define OMP_RTL(Enum, Str, IsVarArg, ReturnType, ...) \
771 FnTy = FunctionType::get(ReturnType, ArrayRef<Type *>{__VA_ARGS__}, \
773 Fn = M.getFunction(Str); \
775#include "llvm/Frontend/OpenMP/OMPKinds.def"
781#define OMP_RTL(Enum, Str, ...) \
783 Fn = Function::Create(FnTy, GlobalValue::ExternalLinkage, Str, M); \
785#include "llvm/Frontend/OpenMP/OMPKinds.def"
789 if (FnID == OMPRTL___kmpc_fork_call || FnID == OMPRTL___kmpc_fork_teams) {
799 LLVMContext::MD_callback,
801 2, {-1, -1},
true)}));
814 assert(Fn &&
"Failed to create OpenMP runtime function");
825 Builder.SetInsertPoint(FiniBB);
837 FiniBB = OtherFiniBB;
839 Builder.SetInsertPoint(FiniBB->getFirstNonPHIIt());
847 auto EndIt = FiniBB->end();
848 if (FiniBB->size() >= 1)
849 if (
auto Prev = std::prev(EndIt); Prev->isTerminator())
854 FiniBB->replaceAllUsesWith(OtherFiniBB);
855 FiniBB->eraseFromParent();
856 FiniBB = OtherFiniBB;
863 assert(Fn &&
"Failed to create OpenMP runtime function pointer");
886 for (
auto Inst =
Block->getReverseIterator()->begin();
887 Inst !=
Block->getReverseIterator()->end();) {
916 Block.getParent()->getEntryBlock().getTerminator()->getIterator();
937 DeferredOutlines.
push_back(std::move(OI));
941 ParallelRegionBlockSet.
clear();
943 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
953 bool ArgsInZeroAddressSpace =
Config.isTargetDevice();
954 std::unique_ptr<CodeExtractor> Extractor =
955 OI->createCodeExtractor(Blocks, ArgsInZeroAddressSpace,
".omp_par");
959 <<
" Exit: " << OI->ExitBB->getName() <<
"\n");
960 assert(Extractor->isEligible() &&
961 "Expected OpenMP outlining to be possible!");
963 for (
auto *V : OI->ExcludeArgsFromAggregate)
964 Extractor->excludeArgFromAggregate(V);
967 Extractor->extractCodeRegion(CEAC, OI->Inputs, OI->Outputs);
971 if (TargetCpuAttr.isStringAttribute())
974 auto TargetFeaturesAttr = OuterFn->
getFnAttribute(
"target-features");
975 if (TargetFeaturesAttr.isStringAttribute())
976 OutlinedFn->
addFnAttr(TargetFeaturesAttr);
979 LLVM_DEBUG(
dbgs() <<
" Outlined function: " << *OutlinedFn <<
"\n");
981 "OpenMP outlined functions should not return a value!");
986 M.getFunctionList().insertAfter(OuterFn->
getIterator(), OutlinedFn);
993 assert(OI->EntryBB->getUniquePredecessor() == &ArtificialEntry);
1000 "Expected instructions to add in the outlined region entry");
1007 if (
I.isTerminator()) {
1009 if (
Instruction *TI = OI->EntryBB->getTerminatorOrNull())
1010 TI->adoptDbgRecords(&ArtificialEntry,
I.getIterator(),
false);
1014 I.moveBeforePreserving(*OI->EntryBB,
1015 OI->EntryBB->getFirstInsertionPt());
1018 OI->EntryBB->moveBefore(&ArtificialEntry);
1025 if (OI->PostOutlineCB)
1026 OI->PostOutlineCB(*OutlinedFn);
1028 if (OI->FixUpNonEntryAllocas)
1060 errs() <<
"Error of kind: " << Kind
1061 <<
" when emitting offload entries and metadata during "
1062 "OMPIRBuilder finalization \n";
1070 if (
Config.isTargetDevice())
1071 applyDeclareTargetGlobalReplacements();
1073 if (
Config.EmitLLVMUsedMetaInfo.value_or(
false)) {
1074 std::vector<WeakTrackingVH> LLVMCompilerUsed = {
1075 M.getGlobalVariable(
"__openmp_nvptx_data_transfer_temporary_storage")};
1076 emitUsed(
"llvm.compiler.used", LLVMCompilerUsed);
1086 assert(Original && Replacement &&
1087 "Null values provided to registerDeclareTargetGlobalReplacement");
1091void OpenMPIRBuilder::applyDeclareTargetGlobalReplacements() {
1097 "A null value was inserted into DeclareTargetGlobalReplacements");
1101 if (!OldGV || !NewGV)
1135 for (
unsigned I = 0, E =
PHI->getNumIncomingValues();
I < E; ++
I) {
1136 if (
PHI->getIncomingValue(
I) != OldGV)
1141 Builder.SetCurrentDebugLocation(
PHI->getDebugLoc());
1143 PHI->setIncomingValue(
I, EdgeLoad);
1149 Builder.SetCurrentDebugLocation(Insn->getDebugLoc());
1165 "Non-default address space declare target global");
1167 unsigned DestAS = ASC->getType()->getPointerAddressSpace();
1168 if (DestAS == 0 && NewGVAS != OldGVAS) {
1169 ASC->replaceAllUsesWith(
Load);
1170 ASC->eraseFromParent();
1175 Insn->replaceUsesOfWith(OldGV,
Load);
1191 ConstantInt::get(I32Ty,
Value), Name);
1204 for (
unsigned I = 0, E =
List.size();
I != E; ++
I)
1208 if (UsedArray.
empty())
1215 GV->setSection(
"llvm.metadata");
1221 auto *Int8Ty =
Builder.getInt8Ty();
1224 ConstantInt::get(Int8Ty, Mode),
Twine(KernelName,
"_exec_mode"));
1232 unsigned Reserve2Flags) {
1234 LocFlags |= OMP_IDENT_FLAG_KMPC;
1241 ConstantInt::get(Int32,
uint32_t(LocFlags)),
1242 ConstantInt::get(Int32, Reserve2Flags),
1243 ConstantInt::get(Int32, SrcLocStrSize), SrcLocStr};
1245 size_t SrcLocStrArgIdx = 4;
1246 if (OpenMPIRBuilder::Ident->getElementType(SrcLocStrArgIdx)
1250 SrcLocStr, OpenMPIRBuilder::Ident->getElementType(SrcLocStrArgIdx));
1257 if (
GV.getValueType() == OpenMPIRBuilder::Ident &&
GV.hasInitializer())
1258 if (
GV.getInitializer() == Initializer)
1263 M, OpenMPIRBuilder::Ident,
1266 M.getDataLayout().getDefaultGlobalsAddressSpace());
1278 SrcLocStrSize = LocStr.
size();
1287 if (
GV.isConstant() &&
GV.hasInitializer() &&
1288 GV.getInitializer() == Initializer)
1291 SrcLocStr =
Builder.CreateGlobalString(
1292 LocStr,
"",
M.getDataLayout().getDefaultGlobalsAddressSpace(),
1300 unsigned Line,
unsigned Column,
1306 Buffer.
append(FunctionName);
1308 Buffer.
append(std::to_string(Line));
1310 Buffer.
append(std::to_string(Column));
1318 StringRef UnknownLoc =
";unknown;unknown;0;0;;";
1329 !DIL->getFilename().empty() ? DIL->getFilename() :
M.getName();
1334 DIL->getColumn(), SrcLocStrSize);
1340 Loc.IP.getNodeParent()->getParent());
1346 "omp_global_thread_num");
1354 "expected one result pointer type per in_reduction item");
1357 if (OrigPtrs.
empty())
1358 return Builder.saveIP();
1377 for (
unsigned Idx = 0; Idx < OrigPtrs.
size(); ++Idx) {
1380 Value *OrigPtr = OrigPtrs[Idx];
1382 OrigPtrTy && OrigPtrTy->getAddressSpace() != 0)
1383 OrigPtr = Builder.CreateAddrSpaceCast(OrigPtr, PtrTy);
1385 Value *
Priv = Builder.CreateCall(GetThData, {Gtid, NullDesc, OrigPtr},
1391 ResPtrTy && ResPtrTy->getAddressSpace() != 0)
1392 Priv = Builder.CreateAddrSpaceCast(
Priv, ResultPtrTys[Idx]);
1394 MapPrivateCB(Idx,
Priv);
1401 bool ForceSimpleCall,
bool CheckCancelFlag) {
1411 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_FOR;
1414 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SECTIONS;
1417 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SINGLE;
1420 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_EXPL;
1423 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL;
1436 bool UseCancelBarrier =
1441 ? OMPRTL___kmpc_cancel_barrier
1442 : OMPRTL___kmpc_barrier),
1445 if (UseCancelBarrier && CheckCancelFlag)
1455 omp::Directive CanceledDirective) {
1460 auto *UI =
Builder.CreateUnreachable();
1468 Builder.SetInsertPoint(ElseTI);
1469 auto ElseIP =
Builder.saveIP();
1477 Builder.SetInsertPoint(ThenTI);
1479 Value *CancelKind =
nullptr;
1480 switch (CanceledDirective) {
1481#define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) \
1482 case DirectiveEnum: \
1483 CancelKind = Builder.getInt32(Value); \
1485#include "llvm/Frontend/OpenMP/OMPKinds.def"
1502 Builder.SetInsertPoint(UI->getParent());
1503 UI->eraseFromParent();
1510 omp::Directive CanceledDirective) {
1515 auto *UI =
Builder.CreateUnreachable();
1518 Value *CancelKind =
nullptr;
1519 switch (CanceledDirective) {
1520#define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) \
1521 case DirectiveEnum: \
1522 CancelKind = Builder.getInt32(Value); \
1524#include "llvm/Frontend/OpenMP/OMPKinds.def"
1541 Builder.SetInsertPoint(UI->getParent());
1542 UI->eraseFromParent();
1555 auto *KernelArgsPtr =
1556 Builder.CreateAlloca(OpenMPIRBuilder::KernelArgs,
nullptr,
"kernel_args");
1561 Builder.CreateStructGEP(OpenMPIRBuilder::KernelArgs, KernelArgsPtr,
I);
1564 M.getDataLayout().getPrefTypeAlign(KernelArgs[
I]->getType()));
1568 NumThreads, HostPtr, KernelArgsPtr};
1595 assert(OutlinedFnID &&
"Invalid outlined function ID!");
1599 Value *Return =
nullptr;
1619 Builder, AllocaIP, Return, RTLoc, DeviceID, Args.NumTeams.front(),
1620 Args.NumThreads.front(), OutlinedFnID, ArgsVector));
1627 Builder.CreateCondBr(
Failed, OffloadFailedBlock, OffloadContBlock);
1629 auto CurFn =
Builder.GetInsertBlock()->getParent();
1636 emitBlock(OffloadContBlock, CurFn,
true);
1641 Value *CancelFlag, omp::Directive CanceledDirective) {
1643 "Unexpected cancellation!");
1663 Builder.CreateCondBr(Cmp, NonCancellationBlock, CancellationBlock,
1672 Builder.SetInsertPoint(CancellationBlock);
1673 Builder.CreateBr(*FiniBBOrErr);
1688 size_t NumArgs = OutlinedFn.
arg_size();
1689 assert((NumArgs == 2 || NumArgs == 3) &&
1690 "expected a 2-3 argument parallel outlined function");
1691 bool UseArgStruct = NumArgs == 3;
1696 {Builder.getInt16Ty(), Builder.getInt32Ty()},
1700 OutlinedFn.
getName() +
".wrapper", OMPIRBuilder->
M);
1702 WrapperFn->addParamAttr(0, Attribute::NoUndef);
1703 WrapperFn->addParamAttr(0, Attribute::ZExt);
1704 WrapperFn->addParamAttr(1, Attribute::NoUndef);
1708 Builder.SetInsertPoint(EntryBB);
1711 Value *AddrAlloca = Builder.CreateAlloca(Builder.getInt32Ty(),
1713 AddrAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1714 AddrAlloca, Builder.getPtrTy(0),
1715 AddrAlloca->
getName() +
".ascast");
1717 Value *ZeroAlloca = Builder.CreateAlloca(Builder.getInt32Ty(),
1719 ZeroAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1720 ZeroAlloca, Builder.getPtrTy(0),
1721 ZeroAlloca->
getName() +
".ascast");
1723 Value *ArgsAlloca =
nullptr;
1725 ArgsAlloca = Builder.CreateAlloca(Builder.getPtrTy(),
1726 nullptr,
"global_args");
1727 ArgsAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1728 ArgsAlloca, Builder.getPtrTy(0),
1729 ArgsAlloca->
getName() +
".ascast");
1733 Builder.CreateStore(WrapperFn->getArg(1), AddrAlloca);
1734 Builder.CreateStore(Builder.getInt32(0), ZeroAlloca);
1738 llvm::omp::RuntimeFunction::OMPRTL___kmpc_get_shared_variables),
1746 Value *StructArg = Builder.CreateLoad(Builder.getPtrTy(), ArgsAlloca);
1747 StructArg = Builder.CreateInBoundsGEP(Builder.getPtrTy(), StructArg,
1748 {Builder.getInt64(0)});
1749 StructArg = Builder.CreateLoad(Builder.getPtrTy(), StructArg,
"structArg");
1750 Args.push_back(StructArg);
1754 Builder.CreateCall(&OutlinedFn, Args);
1755 Builder.CreateRetVoid();
1770 "Expected at least tid and bounded tid as arguments");
1771 unsigned NumCapturedVars = OutlinedFn.
arg_size() - 2;
1779 OutlinedFn.
addFnAttr(Attribute::NoUnwind);
1782 assert(CI &&
"Expected call instruction to outlined function");
1783 CI->
getParent()->setName(
"omp_parallel");
1785 Builder.SetInsertPoint(CI);
1786 Type *PtrTy = OMPIRBuilder->VoidPtr;
1789 OpenMPIRBuilder ::InsertPointTy CurrentIP = Builder.saveIP();
1793 Value *Args = ArgsAlloca;
1797 Args = Builder.CreatePointerCast(ArgsAlloca, PtrTy);
1798 Builder.restoreIP(CurrentIP);
1801 for (
unsigned Idx = 0; Idx < NumCapturedVars; Idx++) {
1803 Value *StoreAddress = Builder.CreateConstInBoundsGEP2_64(
1805 Builder.CreateStore(V, StoreAddress);
1809 IfCondition ? Builder.CreateSExtOrTrunc(IfCondition, OMPIRBuilder->Int32)
1810 : Builder.getInt32(1);
1811 Value *NumThreadsArg =
1812 NumThreads ? Builder.CreateZExtOrTrunc(NumThreads, OMPIRBuilder->Int32)
1813 : Builder.getInt32(-1);
1823 Value *Parallel60CallArgs[] = {
1828 Builder.getInt32(-1),
1832 Builder.getInt64(NumCapturedVars),
1833 Builder.getInt32(0)};
1841 << *Builder.GetInsertBlock()->getParent() <<
"\n");
1844 Builder.SetInsertPoint(PrivTID);
1846 Builder.CreateStore(Builder.CreateLoad(OMPIRBuilder->Int32, OutlinedAI),
1853 I->eraseFromParent();
1876 if (!
F->hasMetadata(LLVMContext::MD_callback)) {
1884 F->addMetadata(LLVMContext::MD_callback,
1893 OutlinedFn.
addFnAttr(Attribute::NoUnwind);
1896 "Expected at least tid and bounded tid as arguments");
1897 unsigned NumCapturedVars = OutlinedFn.
arg_size() - 2;
1900 CI->
getParent()->setName(
"omp_parallel");
1901 Builder.SetInsertPoint(CI);
1904 Value *ForkCallArgs[] = {Ident, Builder.getInt32(NumCapturedVars),
1908 RealArgs.
append(std::begin(ForkCallArgs), std::end(ForkCallArgs));
1910 Value *
Cond = Builder.CreateSExtOrTrunc(IfCondition, OMPIRBuilder->Int32);
1917 auto PtrTy = OMPIRBuilder->VoidPtr;
1918 if (IfCondition && NumCapturedVars == 0) {
1926 << *Builder.GetInsertBlock()->getParent() <<
"\n");
1929 Builder.SetInsertPoint(PrivTID);
1931 Builder.CreateStore(Builder.CreateLoad(OMPIRBuilder->Int32, OutlinedAI),
1938 I->eraseFromParent();
1946 Value *NumThreads, omp::ProcBindKind ProcBind,
bool IsCancellable) {
1955 const bool NeedThreadID = NumThreads ||
Config.isTargetDevice() ||
1956 (ProcBind != OMP_PROC_BIND_default);
1963 bool ArgsInZeroAddressSpace =
Config.isTargetDevice();
1967 if (NumThreads && !
Config.isTargetDevice()) {
1970 Builder.CreateIntCast(NumThreads, Int32,
false)};
1975 if (ProcBind != OMP_PROC_BIND_default) {
1979 ConstantInt::get(Int32,
unsigned(ProcBind),
true)};
1989 BasicBlock *OuterAllocaBlock = OuterAllocIP.getNodeParent();
2001 Builder.CreateAlloca(Int32,
nullptr,
"zero.addr");
2004 if (ArgsInZeroAddressSpace &&
M.getDataLayout().getAllocaAddrSpace() != 0) {
2007 TIDAddrAlloca, PointerType ::get(
M.getContext(), 0),
"tid.addr.ascast");
2011 PointerType ::get(
M.getContext(), 0),
2012 "zero.addr.ascast");
2036 if (IP == IP.getNodeParent()->end()) {
2040 IP =
I->getIterator();
2042 assert(IP.getNodeParent()->getTerminator()->getNumSuccessors() == 1 &&
2043 IP.getNodeParent()->getTerminator()->getSuccessor(0) == PRegExitBB &&
2044 "Unexpected insertion point for finalization call!");
2056 Builder.CreateAlloca(Int32,
nullptr,
"tid.addr.local");
2062 Builder.CreateLoad(Int32, ZeroAddr,
"zero.addr.use");
2080 LLVM_DEBUG(
dbgs() <<
"Before body codegen: " << *OuterFn <<
"\n");
2083 assert(BodyGenCB &&
"Expected body generation callback!");
2085 if (
Error Err = BodyGenCB(InnerAllocaIP, CodeGenIP, PRegExitBB))
2088 LLVM_DEBUG(
dbgs() <<
"After body codegen: " << *OuterFn <<
"\n");
2092 bool UsesDeviceSharedMemory =
2094 std::unique_ptr<OutlineInfo> OI =
2095 UsesDeviceSharedMemory
2096 ? std::make_unique<DeviceSharedMemOutlineInfo>(*
this)
2097 : std::make_unique<OutlineInfo>();
2099 if (
Config.isTargetDevice()) {
2101 OI->PostOutlineCB = [=, ToBeDeletedVec =
2102 std::move(ToBeDeleted)](
Function &OutlinedFn) {
2104 IfCondition, NumThreads, PrivTID, PrivTIDAddr,
2105 ThreadID, ToBeDeletedVec);
2109 OI->PostOutlineCB = [=, ToBeDeletedVec =
2110 std::move(ToBeDeleted)](
Function &OutlinedFn) {
2112 PrivTID, PrivTIDAddr, ToBeDeletedVec);
2116 OI->FixUpNonEntryAllocas =
true;
2117 OI->OuterAllocBB = OuterAllocaBlock;
2118 OI->EntryBB = PRegEntryBB;
2119 OI->ExitBB = PRegExitBB;
2120 OI->OuterDeallocBBs.reserve(OuterDeallocBlocks.
size());
2121 copy(OuterDeallocBlocks, OI->OuterDeallocBBs.
end());
2125 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
2137 ".omp_par", ArgsInZeroAddressSpace);
2142 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
2144 Extractor.findInputsOutputs(Inputs, Outputs, SinkingCands,
2149 return GV->getValueType() == OpenMPIRBuilder::Ident;
2154 LLVM_DEBUG(
dbgs() <<
"Before privatization: " << *OuterFn <<
"\n");
2160 if (&V == TIDAddr || &V == ZeroAddr) {
2161 OI->ExcludeArgsFromAggregate.push_back(&V);
2166 for (
Use &U : V.uses())
2168 if (ParallelRegionBlockSet.
count(UserI->getParent()))
2178 if (!V.getType()->isPointerTy()) {
2182 Builder.restoreIP(OuterAllocIP);
2184 if (UsesDeviceSharedMemory) {
2187 V.getName() +
".reloaded");
2188 for (
BasicBlock *DeallocBlock : OuterDeallocBlocks) {
2189 assert(DeallocBlock->getParent() ==
2190 OuterAllocIP.getNodeParent()->getParent() &&
2191 "Dealloc block must be in the allocation's function to reuse "
2192 "its debug location");
2194 Builder.getCurrentDebugLocation()},
2198 Ptr =
Builder.CreateAlloca(V.getType(),
nullptr,
2199 V.getName() +
".reloaded");
2208 Builder.restoreIP(InnerAllocaIP);
2209 Inner =
Builder.CreateLoad(V.getType(), Ptr);
2212 Value *ReplacementValue =
nullptr;
2215 ReplacementValue = PrivTID;
2218 PrivCB(InnerAllocaIP,
Builder.saveIP(), V, *Inner, ReplacementValue);
2223 InnerAllocaIP.getNodeParent()->getTerminator()->getIterator();
2225 assert(ReplacementValue &&
2226 "Expected copy/create callback to set replacement value!");
2227 if (ReplacementValue == &V)
2232 UPtr->set(ReplacementValue);
2255 for (
Value *Output : Outputs)
2259 "OpenMP outlining should not produce live-out values!");
2261 LLVM_DEBUG(
dbgs() <<
"After privatization: " << *OuterFn <<
"\n");
2263 for (
auto *BB : Blocks)
2264 dbgs() <<
" PBR: " << BB->getName() <<
"\n";
2272 assert(FiniInfo.DK == OMPD_parallel &&
2273 "Unexpected finalization stack state!");
2284 Builder.CreateBr(*FiniBBOrErr);
2288 Term->eraseFromParent();
2295 UI->eraseFromParent();
2327 Value *Severity = ConstantInt::get(Int32, IsFatal ? 2 : 1);
2329 Value *Args[] = {Ident, Severity, MessageArg};
2358 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr));
2360 Builder.CreateStore(DepValPtr, Addr);
2363 DependInfo, Entry,
static_cast<unsigned int>(RTLDependInfoFields::Len));
2365 ConstantInt::get(SizeTy,
2370 DependInfo, Entry,
static_cast<unsigned int>(RTLDependInfoFields::Flags));
2372 static_cast<unsigned int>(Dep.
DepKind)),
2385 if (Dependencies.
empty())
2405 Type *DependInfo = OMPBuilder.DependInfo;
2407 Value *DepArray =
nullptr;
2413 Builder.SetInsertPoint(
2414 Builder.GetInsertBlock()->getParent()->getEntryBlock().getTerminator());
2415 DepArray = Builder.CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
2418 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies)) {
2420 Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
2445 Value *DepArray =
nullptr;
2446 Type *DepArrayTy =
nullptr;
2447 Value *NumDeps =
nullptr;
2450 NumDeps = Dependencies.
NumDeps;
2451 }
else if (!Dependencies.
Deps.empty()) {
2453 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
2457 Builder.GetInsertBlock()->getParent()->getEntryBlock();
2459 DepArray =
Builder.CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
2462 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies.
Deps)) {
2464 Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
2478 ConstantInt::get(
Builder.getInt32Ty(), 0),
2480 ConstantInt::get(
Builder.getInt32Ty(), IsNowait)};
2483 omp::RuntimeFunction::OMPRTL___kmpc_omp_taskwait_deps_51),
2493 unsigned ProgramAddressSpace = M.getDataLayout().getProgramAddressSpace();
2505 auto *VoidPtrTy =
PointerType::get(Builder.getContext(), ProgramAddressSpace);
2508 Builder.getVoidTy(), {VoidPtrTy, VoidPtrTy, Builder.getInt32Ty()},
2512 "omp_taskloop_dup", M);
2515 Value *LastprivateFlagArg = DupFunction->
getArg(2);
2516 DestTaskArg->
setName(
"dest_task");
2517 SrcTaskArg->
setName(
"src_task");
2518 LastprivateFlagArg->
setName(
"lastprivate_flag");
2521 Builder.SetInsertPoint(
2524 auto GetTaskContextPtrFromArg = [&](
Value *Arg) ->
Value * {
2525 Type *TaskWithPrivatesTy =
2527 Value *TaskPrivates = Builder.CreateGEP(
2528 TaskWithPrivatesTy, Arg, {Builder.getInt32(0), Builder.getInt32(1)});
2529 Value *ContextPtr = Builder.CreateGEP(
2530 PrivatesTy, TaskPrivates,
2531 {Builder.getInt32(0), Builder.getInt32(PrivatesIndex)});
2535 Value *DestTaskContextPtr = GetTaskContextPtrFromArg(DestTaskArg);
2536 Value *SrcTaskContextPtr = GetTaskContextPtrFromArg(SrcTaskArg);
2538 DestTaskContextPtr->
setName(
"destPtr");
2539 SrcTaskContextPtr->
setName(
"srcPtr");
2543 Expected<IRBuilderBase::InsertPoint> AfterIPOrError =
2544 DupCB(AllocaIP, CodeGenIP, DestTaskContextPtr, SrcTaskContextPtr);
2545 if (!AfterIPOrError)
2547 Builder.restoreIP(*AfterIPOrError);
2557 llvm::function_ref<llvm::Expected<llvm::CanonicalLoopInfo *>()> LoopInfo,
2559 Value *GrainSize,
bool NoGroup,
int Sched,
Value *Final,
bool Mergeable,
2561 Value *TaskContextStructPtrVal,
bool FreeAgent) {
2566 uint32_t SrcLocStrSize;
2580 if (
Error Err = BodyGenCB(TaskloopAllocaIP, TaskloopBodyIP, TaskloopExitBB))
2583 llvm::Expected<llvm::CanonicalLoopInfo *> result = LoopInfo();
2588 llvm::CanonicalLoopInfo *CLI = result.
get();
2589 auto OI = std::make_unique<OutlineInfo>();
2590 OI->EntryBB = TaskloopAllocaBB;
2591 OI->OuterAllocBB = AllocaIP.getNodeParent();
2592 OI->ExitBB = TaskloopExitBB;
2593 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2594 copy(DeallocBlocks, OI->OuterDeallocBBs.end());
2597 SmallVector<Instruction *> ToBeDeleted;
2600 Builder, AllocaIP, ToBeDeleted, TaskloopAllocaIP,
"global.tid",
false));
2602 TaskloopAllocaIP,
"lb",
false,
true);
2604 TaskloopAllocaIP,
"ub",
false,
true);
2606 TaskloopAllocaIP,
"step",
false,
true);
2609 OI->Inputs.insert(FakeLB);
2610 OI->Inputs.insert(FakeUB);
2611 OI->Inputs.insert(FakeStep);
2612 if (TaskContextStructPtrVal)
2613 OI->Inputs.insert(TaskContextStructPtrVal);
2614 assert(((TaskContextStructPtrVal && DupCB) ||
2615 (!TaskContextStructPtrVal && !DupCB)) &&
2616 "Task context struct ptr and duplication callback must be both set "
2622 unsigned ProgramAddressSpace =
M.getDataLayout().getProgramAddressSpace();
2626 {FakeLB->getType(), FakeUB->getType(), FakeStep->getType(), PointerTy});
2627 Expected<Value *> TaskDupFnOrErr = createTaskDuplicationFunction(
2630 if (!TaskDupFnOrErr) {
2633 Value *TaskDupFn = *TaskDupFnOrErr;
2635 OI->PostOutlineCB = [
this, Ident, LBVal, UBVal, StepVal, Untied,
2636 TaskloopAllocaBB, CLI, TaskDupFn, ToBeDeleted, IfCond,
2637 GrainSize, NoGroup, Sched, FakeLB, FakeUB, FakeStep,
2638 FakeSharedsTy, Final, Mergeable, Priority,
2640 FreeAgent](
Function &OutlinedFn)
mutable {
2642 assert(OutlinedFn.hasOneUse() &&
2643 "there must be a single user for the outlined function");
2650 Value *CastedLBVal =
2651 Builder.CreateIntCast(LBVal,
Builder.getInt64Ty(),
true,
"lb64");
2652 Value *CastedUBVal =
2653 Builder.CreateIntCast(UBVal,
Builder.getInt64Ty(),
true,
"ub64");
2654 Value *CastedStepVal =
2655 Builder.CreateIntCast(StepVal,
Builder.getInt64Ty(),
true,
"step64");
2657 Builder.SetInsertPoint(StaleCI);
2670 Builder.CreateCall(TaskgroupFn, {Ident, ThreadID});
2695 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
2697 AllocaInst *ArgStructAlloca =
2699 assert(ArgStructAlloca &&
2700 "Unable to find the alloca instruction corresponding to arguments "
2701 "for extracted function");
2702 std::optional<TypeSize> ArgAllocSize =
2705 "Unable to determine size of arguments for extracted function");
2706 Value *SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
2711 CallInst *TaskData =
Builder.CreateCall(
2712 TaskAllocFn, {Ident, ThreadID,
Flags,
2713 TaskSize, SharedsSize,
2718 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
2724 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(0)});
2727 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(1)});
2730 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(2)});
2736 IfCond ?
Builder.CreateIntCast(IfCond,
Builder.getInt32Ty(),
true)
2742 Value *GrainSizeVal =
2743 GrainSize ?
Builder.CreateIntCast(GrainSize,
Builder.getInt64Ty(),
true)
2745 Value *TaskDup = TaskDupFn;
2747 Value *
Args[] = {Ident, ThreadID, TaskData, IfCondVal, Lb, Ub,
2748 Loadstep, NoGroupVal, SchedVal, GrainSizeVal, TaskDup};
2753 Builder.CreateCall(TaskloopFn, Args);
2760 Builder.CreateCall(EndTaskgroupFn, {Ident, ThreadID});
2765 Builder.SetInsertPoint(TaskloopAllocaBB->begin());
2767 LoadInst *SharedsOutlined =
2768 Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
2769 OutlinedFn.getArg(1)->replaceUsesWithIf(
2771 [SharedsOutlined](Use &U) {
return U.getUser() != SharedsOutlined; });
2774 Type *IVTy =
IV->getType();
2780 Value *TaskLB =
nullptr;
2781 Value *TaskUB =
nullptr;
2782 Value *TaskStep =
nullptr;
2783 Value *LoadTaskLB =
nullptr;
2784 Value *LoadTaskUB =
nullptr;
2785 Value *LoadTaskStep =
nullptr;
2786 for (Instruction &
I : *TaskloopAllocaBB) {
2787 if (
I.getOpcode() == Instruction::GetElementPtr) {
2790 switch (CI->getZExtValue()) {
2802 }
else if (
I.getOpcode() == Instruction::Load) {
2804 if (
Load.getPointerOperand() == TaskLB) {
2805 assert(TaskLB !=
nullptr &&
"Expected value for TaskLB");
2807 }
else if (
Load.getPointerOperand() == TaskUB) {
2808 assert(TaskUB !=
nullptr &&
"Expected value for TaskUB");
2810 }
else if (
Load.getPointerOperand() == TaskStep) {
2811 assert(TaskStep !=
nullptr &&
"Expected value for TaskStep");
2817 Builder.SetInsertPoint(CLI->getPreheader()->getTerminator());
2819 assert(LoadTaskLB !=
nullptr &&
"Expected value for LoadTaskLB");
2820 assert(LoadTaskUB !=
nullptr &&
"Expected value for LoadTaskUB");
2821 assert(LoadTaskStep !=
nullptr &&
"Expected value for LoadTaskStep");
2823 Builder.CreateSub(LoadTaskUB, LoadTaskLB), LoadTaskStep);
2824 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One,
"trip_cnt");
2825 Value *CastedTripCount =
Builder.CreateIntCast(TripCount, IVTy,
true);
2826 Value *CastedTaskLB =
Builder.CreateIntCast(LoadTaskLB, IVTy,
true);
2828 CLI->setTripCount(CastedTripCount);
2830 Builder.SetInsertPoint(CLI->getBody()->getFirstInsertionPt());
2832 if (NumOfCollapseLoops > 1) {
2838 Builder.CreateSub(CastedTaskLB, ConstantInt::get(IVTy, 1)));
2841 for (
auto IVUse = CLI->getIndVar()->uses().begin();
2842 IVUse != CLI->getIndVar()->uses().end(); IVUse++) {
2843 User *IVUser = IVUse->getUser();
2845 if (
Op->getOpcode() == Instruction::URem ||
2846 Op->getOpcode() == Instruction::UDiv) {
2851 for (User *User : UsersToReplace) {
2852 User->replaceUsesOfWith(CLI->getIndVar(), IVPlusTaskLB);
2869 assert(CLI->getIndVar()->getNumUses() == 3 &&
2870 "Canonical loop should have exactly three uses of the ind var");
2871 for (User *IVUser : CLI->getIndVar()->users()) {
2873 if (
Mul->getOpcode() == Instruction::Mul) {
2874 for (User *MulUser :
Mul->users()) {
2876 if (
Add->getOpcode() == Instruction::Add) {
2877 Add->setOperand(1, CastedTaskLB);
2886 FakeLB->replaceAllUsesWith(CastedLBVal);
2887 FakeUB->replaceAllUsesWith(CastedUBVal);
2888 FakeStep->replaceAllUsesWith(CastedStepVal);
2890 I->eraseFromParent();
2901 M.getContext(),
M.getDataLayout().getPointerSizeInBits());
2911 bool Mergeable,
Value *EventHandle,
Value *Priority,
bool FreeAgent) {
2942 if (
Error Err = BodyGenCB(TaskAllocaIP, TaskBodyIP, TaskExitBB))
2945 auto OI = std::make_unique<OutlineInfo>();
2946 OI->EntryBB = TaskAllocaBB;
2947 OI->OuterAllocBB = AllocaIP.getNodeParent();
2948 OI->ExitBB = TaskExitBB;
2949 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2950 copy(DeallocBlocks, OI->OuterDeallocBBs.
end());
2955 Builder, AllocaIP, ToBeDeleted, TaskAllocaIP,
"global.tid",
false));
2957 OI->PostOutlineCB = [
this, Ident, Tied, Final, IfCondition, Dependencies,
2958 Affinities, Mergeable, Priority, EventHandle, FreeAgent,
2960 ToBeDeleted](
Function &OutlinedFn)
mutable {
2962 assert(OutlinedFn.hasOneUse() &&
2963 "there must be a single user for the outlined function");
2968 bool HasShareds = StaleCI->
arg_size() > 1;
2969 Builder.SetInsertPoint(StaleCI);
2996 bool UseMergedIf0Path = ConstIfCondition && ConstIfCondition->isZero();
3000 Flags =
Builder.CreateOr(FinalFlag, Flags);
3003 if (Mergeable || UseMergedIf0Path)
3017 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
3026 assert(ArgStructAlloca &&
3027 "Unable to find the alloca instruction corresponding to arguments "
3028 "for extracted function");
3029 std::optional<TypeSize> ArgAllocSize =
3032 "Unable to determine size of arguments for extracted function");
3033 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
3039 TaskAllocFn, {Ident, ThreadID, Flags,
3040 TaskSize, SharedsSize,
3043 if (Affinities.
Count && Affinities.
Info) {
3045 OMPRTL___kmpc_omp_reg_task_with_affinity);
3056 OMPRTL___kmpc_task_allow_completion_event);
3060 Builder.CreatePointerBitCastOrAddrSpaceCast(EventHandle,
3062 EventVal =
Builder.CreatePtrToInt(EventVal,
Builder.getInt64Ty());
3063 Builder.CreateStore(EventVal, EventHandleAddr);
3069 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
3084 Constant *Zero = ConstantInt::get(Int32Ty, 0);
3088 Builder.CreateInBoundsGEP(TaskPtr, TaskData, {Zero, Zero});
3091 VoidPtr, VoidPtr,
Builder.getInt32Ty(), VoidPtr, VoidPtr);
3093 TaskStructType, TaskGEP, {Zero, ConstantInt::get(Int32Ty, 4)});
3096 Value *CmplrData =
Builder.CreateInBoundsGEP(CmplrStructType,
3097 PriorityData, {Zero, Zero});
3098 Builder.CreateStore(Priority, CmplrData);
3101 Value *DepArray =
nullptr;
3102 Value *NumDeps =
nullptr;
3105 NumDeps = Dependencies.
NumDeps;
3106 }
else if (!Dependencies.
Deps.empty()) {
3108 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
3128 if (IfCondition && !UseMergedIf0Path) {
3133 Builder.GetInsertPoint()->getParent()->getTerminator();
3134 Instruction *ThenTI = IfTerminator, *ElseTI =
nullptr;
3135 Builder.SetInsertPoint(IfTerminator);
3138 Builder.SetInsertPoint(ElseTI);
3145 {Ident, ThreadID, NumDeps, DepArray,
3146 ConstantInt::get(
Builder.getInt32Ty(), 0),
3161 Builder.SetInsertPoint(ThenTI);
3169 {Ident, ThreadID, TaskData, NumDeps, DepArray,
3170 ConstantInt::get(
Builder.getInt32Ty(), 0),
3183 LoadInst *Shareds =
Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
3184 OutlinedFn.getArg(1)->replaceUsesWithIf(
3185 Shareds, [Shareds](
Use &U) {
return U.getUser() != Shareds; });
3191 Builder.ClearInsertionPoint();
3193 I->eraseFromParent();
3219 if (
Error Err = BodyGenCB(AllocaIP,
Builder.saveIP(), DeallocBlocks))
3222 Builder.SetInsertPoint(TaskgroupExitBB);
3265 unsigned CaseNumber = 0;
3266 for (
auto SectionCB : SectionCBs) {
3268 M.getContext(),
"omp_section_loop.body.case", CurFn,
Continue);
3270 Builder.SetInsertPoint(CaseBB);
3283 Value *LB = ConstantInt::get(I32Ty, 0);
3284 Value *UB = ConstantInt::get(I32Ty, SectionCBs.
size());
3285 Value *ST = ConstantInt::get(I32Ty, 1);
3287 Loc, LoopBodyGenCB, LB, UB, ST,
true,
false, AllocaIP,
"section_loop");
3292 applyStaticWorkshareLoop(
Loc.DL, *
LoopInfo, AllocaIP,
3293 WorksharingLoopType::ForStaticLoop, !IsNowait);
3299 assert(LoopFini &&
"Bad structure of static workshare loop finalization");
3303 assert(FiniInfo.DK == OMPD_sections &&
3304 "Unexpected finalization stack state!");
3305 if (
Error Err = FiniInfo.mergeFiniBB(
Builder, LoopFini))
3319 if (IP != IP.getNodeParent()->end())
3330 auto *CaseBB =
Loc.IP.getNodeParent();
3331 auto *CondBB = CaseBB->getSinglePredecessor()->getSinglePredecessor();
3332 auto *ExitBB = CondBB->getTerminator()->getSuccessor(1);
3334 IP =
I->getIterator();
3338 Directive OMPD = Directive::OMPD_sections;
3341 return EmitOMPInlinedRegion(OMPD,
nullptr,
nullptr, BodyGenCB, FiniCBWrapper,
3352Value *OpenMPIRBuilder::getGPUThreadID() {
3355 OMPRTL___kmpc_get_hardware_thread_id_in_block),
3359Value *OpenMPIRBuilder::getGPUWarpSize() {
3364Value *OpenMPIRBuilder::getNVPTXWarpID() {
3365 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3366 return Builder.CreateAShr(getGPUThreadID(), LaneIDBits,
"nvptx_warp_id");
3369Value *OpenMPIRBuilder::getNVPTXLaneID() {
3370 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3371 assert(LaneIDBits < 32 &&
"Invalid LaneIDBits size in NVPTX device.");
3372 unsigned LaneIDMask = ~0
u >> (32u - LaneIDBits);
3373 return Builder.CreateAnd(getGPUThreadID(),
Builder.getInt32(LaneIDMask),
3380 uint64_t FromSize =
M.getDataLayout().getTypeStoreSize(FromType);
3381 uint64_t ToSize =
M.getDataLayout().getTypeStoreSize(ToType);
3382 assert(FromSize > 0 &&
"From size must be greater than zero");
3383 assert(ToSize > 0 &&
"To size must be greater than zero");
3384 if (FromType == ToType)
3386 if (FromSize == ToSize)
3387 return Builder.CreateBitCast(From, ToType);
3389 return Builder.CreateIntCast(From, ToType,
true);
3395 Value *ValCastItem =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3396 CastItem,
Builder.getPtrTy(0));
3397 Builder.CreateStore(From, ValCastItem);
3398 return Builder.CreateLoad(ToType, CastItem);
3405 uint64_t Size =
M.getDataLayout().getTypeStoreSize(ElementType);
3406 assert(
Size <= 8 &&
"Unsupported bitwidth in shuffle instruction");
3410 Value *ElemCast = castValueToType(AllocaIP, Element, CastTy);
3412 Builder.CreateIntCast(getGPUWarpSize(),
Builder.getInt16Ty(),
true);
3414 Size <= 4 ? RuntimeFunction::OMPRTL___kmpc_shuffle_int32
3415 : RuntimeFunction::OMPRTL___kmpc_shuffle_int64);
3416 Value *WarpSizeCast =
3418 Value *ShuffleCall =
3423 return castValueToType(AllocaIP, ShuffleCall, ElementType);
3430 uint64_t Size =
M.getDataLayout().getTypeStoreSize(ElemType);
3442 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3443 Value *ElemPtr = DstAddr;
3444 Value *Ptr = SrcAddr;
3445 for (
unsigned IntSize = 8; IntSize >= 1; IntSize /= 2) {
3449 Ptr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3452 Builder.CreateGEP(ElemType, SrcAddr, {ConstantInt::get(IndexTy, 1)});
3453 ElemPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3457 if ((
Size / IntSize) > 1) {
3458 Value *PtrEnd =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3459 SrcAddrGEP,
Builder.getPtrTy());
3476 Builder.CreatePointerBitCastOrAddrSpaceCast(Ptr,
Builder.getPtrTy()));
3478 Builder.CreateICmpSGT(PtrDiff,
Builder.getInt64(IntSize - 1)), ThenBB,
3481 Value *Res = createRuntimeShuffleFunction(
3484 IntType, Ptr,
M.getDataLayout().getPrefTypeAlign(ElemType)),
3486 Builder.CreateAlignedStore(Res, ElemPtr,
3487 M.getDataLayout().getPrefTypeAlign(ElemType));
3489 Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3490 Value *LocalElemPtr =
3491 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3499 Value *Res = createRuntimeShuffleFunction(
3500 AllocaIP,
Builder.CreateLoad(IntType, Ptr), IntType,
Offset);
3501 Builder.CreateStore(Res, ElemPtr);
3502 Ptr =
Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3504 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3510Error OpenMPIRBuilder::emitReductionListCopy(
3515 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3516 Value *RemoteLaneOffset = CopyOptions.RemoteLaneOffset;
3520 for (
auto En :
enumerate(ReductionInfos)) {
3522 Value *SrcElementAddr =
nullptr;
3523 AllocaInst *DestAlloca =
nullptr;
3524 Value *DestElementAddr =
nullptr;
3525 Value *DestElementPtrAddr =
nullptr;
3527 bool ShuffleInElement =
false;
3530 bool UpdateDestListPtr =
false;
3534 ReductionArrayTy, SrcBase,
3535 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3536 SrcElementAddr =
Builder.CreateLoad(
Builder.getPtrTy(), SrcElementPtrAddr);
3540 DestElementPtrAddr =
Builder.CreateInBoundsGEP(
3541 ReductionArrayTy, DestBase,
3542 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3543 bool IsByRefElem = (!IsByRef.
empty() && IsByRef[En.index()]);
3549 Type *DestAllocaType =
3550 IsByRefElem ? RI.ByRefAllocatedType : RI.ElementType;
3551 DestAlloca =
Builder.CreateAlloca(DestAllocaType,
nullptr,
3552 ".omp.reduction.element");
3554 M.getDataLayout().getPrefTypeAlign(DestAllocaType));
3555 DestElementAddr = DestAlloca;
3558 DestElementAddr->
getName() +
".ascast");
3560 ShuffleInElement =
true;
3561 UpdateDestListPtr =
true;
3573 if (ShuffleInElement) {
3574 Type *ShuffleType = RI.ElementType;
3575 Value *ShuffleSrcAddr = SrcElementAddr;
3576 Value *ShuffleDestAddr = DestElementAddr;
3577 AllocaInst *LocalStorage =
nullptr;
3580 assert(RI.ByRefElementType &&
"Expected by-ref element type to be set");
3581 assert(RI.ByRefAllocatedType &&
3582 "Expected by-ref allocated type to be set");
3587 ShuffleType = RI.ByRefElementType;
3589 if (RI.DataPtrPtrGen) {
3592 Builder.saveIP(), ShuffleSrcAddr, ShuffleSrcAddr);
3595 return GenResult.takeError();
3604 LocalStorage =
Builder.CreateAlloca(ShuffleType);
3606 ShuffleDestAddr = LocalStorage;
3611 ShuffleDestAddr = DestElementAddr;
3615 shuffleAndStore(AllocaIP, ShuffleSrcAddr, ShuffleDestAddr, ShuffleType,
3616 RemoteLaneOffset, ReductionArrayTy, IsByRefElem);
3618 if (IsByRefElem && RI.DataPtrPtrGen) {
3620 Value *DestDescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3621 DestAlloca,
Builder.getPtrTy(),
".ascast");
3624 DestDescriptorAddr, LocalStorage, SrcElementAddr,
3625 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
3628 return GenResult.takeError();
3631 switch (RI.EvaluationKind) {
3633 Value *Elem =
Builder.CreateLoad(RI.ElementType, SrcElementAddr);
3635 Builder.CreateStore(Elem, DestElementAddr);
3639 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3640 RI.ElementType, SrcElementAddr, 0, 0,
".realp");
3642 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
3644 RI.ElementType, SrcElementAddr, 0, 1,
".imagp");
3646 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
3648 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3649 RI.ElementType, DestElementAddr, 0, 0,
".realp");
3650 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
3651 RI.ElementType, DestElementAddr, 0, 1,
".imagp");
3652 Builder.CreateStore(SrcReal, DestRealPtr);
3653 Builder.CreateStore(SrcImg, DestImgPtr);
3658 M.getDataLayout().getTypeStoreSize(RI.ElementType));
3660 DestElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3661 SrcElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3673 if (UpdateDestListPtr) {
3674 Value *CastDestAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3675 DestElementAddr,
Builder.getPtrTy(),
3676 DestElementAddr->
getName() +
".ascast");
3677 Builder.CreateStore(CastDestAddr, DestElementPtrAddr);
3684Expected<Function *> OpenMPIRBuilder::emitInterWarpCopyFunction(
3687 IRBuilder<>::InsertPointGuard IPG(
Builder);
3688 LLVMContext &Ctx =
M.getContext();
3690 Builder.getVoidTy(), {Builder.getPtrTy(), Builder.getInt32Ty()},
3694 "_omp_reduction_inter_warp_copy_func", &
M);
3700 Builder.SetInsertPoint(EntryBB);
3718 StringRef TransferMediumName =
3719 "__openmp_nvptx_data_transfer_temporary_storage";
3720 GlobalVariable *TransferMedium =
M.getGlobalVariable(TransferMediumName);
3721 unsigned WarpSize =
Config.getGridValue().GV_Warp_Size;
3723 if (!TransferMedium) {
3724 TransferMedium =
new GlobalVariable(
3732 Value *GPUThreadID = getGPUThreadID();
3734 Value *LaneID = getNVPTXLaneID();
3736 Value *WarpID = getNVPTXWarpID();
3742 AllocaInst *ReduceListAlloca =
Builder.CreateAlloca(
3743 Arg0Type,
nullptr, ReduceListArg->
getName() +
".addr");
3744 AllocaInst *NumWarpsAlloca =
3745 Builder.CreateAlloca(Arg1Type,
nullptr, NumWarpsArg->
getName() +
".addr");
3746 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3747 ReduceListAlloca, Arg0Type, ReduceListAlloca->
getName() +
".ascast");
3748 Value *NumWarpsAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3749 NumWarpsAlloca,
Builder.getPtrTy(0),
3750 NumWarpsAlloca->
getName() +
".ascast");
3751 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
3752 Builder.CreateStore(NumWarpsArg, NumWarpsAddrCast);
3761 for (
auto En :
enumerate(ReductionInfos)) {
3767 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
3768 unsigned RealTySize =
M.getDataLayout().getTypeAllocSize(
3769 IsByRefElem ? RI.ByRefElementType : RI.ElementType);
3770 for (
unsigned TySize = 4; TySize > 0 && RealTySize > 0; TySize /= 2) {
3773 unsigned NumIters = RealTySize / TySize;
3776 Value *Cnt =
nullptr;
3777 Value *CntAddr =
nullptr;
3784 Builder.CreateAlloca(
Builder.getInt32Ty(),
nullptr,
".cnt.addr");
3786 CntAddr =
Builder.CreateAddrSpaceCast(CntAddr,
Builder.getPtrTy(),
3787 CntAddr->
getName() +
".ascast");
3799 Cnt, ConstantInt::get(
Builder.getInt32Ty(), NumIters));
3800 Builder.CreateCondBr(Cmp, BodyBB, ExitBB);
3807 omp::Directive::OMPD_unknown,
3811 return BarrierIP1.takeError();
3817 Value *IsWarpMaster =
Builder.CreateIsNull(LaneID,
"warp_master");
3818 Builder.CreateCondBr(IsWarpMaster, ThenBB, ElseBB);
3822 auto *RedListArrayTy =
3825 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3827 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3828 {ConstantInt::get(IndexTy, 0),
3829 ConstantInt::get(IndexTy, En.index())});
3833 if (IsByRefElem && RI.DataPtrPtrGen) {
3835 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
3838 return GenRes.takeError();
3849 ArrayTy, TransferMedium, {
Builder.getInt64(0), WarpID});
3854 Builder.CreateStore(Elem, MediumPtr,
3866 omp::Directive::OMPD_unknown,
3870 return BarrierIP2.takeError();
3877 Value *NumWarpsVal =
3880 Value *IsActiveThread =
3881 Builder.CreateICmpULT(GPUThreadID, NumWarpsVal,
"is_active_thread");
3882 Builder.CreateCondBr(IsActiveThread, W0ThenBB, W0ElseBB);
3889 ArrayTy, TransferMedium, {
Builder.getInt64(0), GPUThreadID});
3891 Value *TargetElemPtrPtr =
3892 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3893 {ConstantInt::get(IndexTy, 0),
3894 ConstantInt::get(IndexTy, En.index())});
3895 Value *TargetElemPtrVal =
3897 Value *TargetElemPtr = TargetElemPtrVal;
3899 if (IsByRefElem && RI.DataPtrPtrGen) {
3901 RI.DataPtrPtrGen(
Builder.saveIP(), TargetElemPtr, TargetElemPtr);
3904 return GenRes.takeError();
3906 TargetElemPtr =
Builder.CreateLoad(
Builder.getPtrTy(), TargetElemPtr);
3914 Value *SrcMediumValue =
3915 Builder.CreateLoad(CType, SrcMediumPtrVal,
true);
3916 Builder.CreateStore(SrcMediumValue, TargetElemPtr);
3926 Cnt, ConstantInt::get(
Builder.getInt32Ty(), 1));
3927 Builder.CreateStore(Cnt, CntAddr,
false);
3929 auto *CurFn =
Builder.GetInsertBlock()->getParent();
3933 RealTySize %= TySize;
3942Expected<Function *> OpenMPIRBuilder::emitShuffleAndReduceFunction(
3945 LLVMContext &Ctx =
M.getContext();
3946 IRBuilder<>::InsertPointGuard IPG(
Builder);
3947 FunctionType *FuncTy =
3949 {Builder.getPtrTy(), Builder.getInt16Ty(),
3950 Builder.getInt16Ty(), Builder.getInt16Ty()},
3954 "_omp_reduction_shuffle_and_reduce_func", &
M);
3965 Builder.SetInsertPoint(EntryBB);
3977 Type *ReduceListArgType = ReduceListArg->
getType();
3981 ReduceListArgType,
nullptr, ReduceListArg->
getName() +
".addr");
3982 Value *LaneIdAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
3983 LaneIDArg->
getName() +
".addr");
3985 LaneIDArgType,
nullptr, RemoteLaneOffsetArg->
getName() +
".addr");
3986 Value *AlgoVerAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
3987 AlgoVerArg->
getName() +
".addr");
3994 RedListArrayTy,
nullptr,
".omp.reduction.remote_reduce_list");
3996 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3997 ReduceListAlloca, ReduceListArgType,
3998 ReduceListAlloca->
getName() +
".ascast");
3999 Value *LaneIdAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4000 LaneIdAlloca, LaneIDArgPtrType, LaneIdAlloca->
getName() +
".ascast");
4001 Value *RemoteLaneOffsetAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4002 RemoteLaneOffsetAlloca, LaneIDArgPtrType,
4003 RemoteLaneOffsetAlloca->
getName() +
".ascast");
4004 Value *AlgoVerAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4005 AlgoVerAlloca, LaneIDArgPtrType, AlgoVerAlloca->
getName() +
".ascast");
4006 Value *RemoteListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4007 RemoteReductionListAlloca,
Builder.getPtrTy(),
4008 RemoteReductionListAlloca->
getName() +
".ascast");
4010 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
4011 Builder.CreateStore(LaneIDArg, LaneIdAddrCast);
4012 Builder.CreateStore(RemoteLaneOffsetArg, RemoteLaneOffsetAddrCast);
4013 Builder.CreateStore(AlgoVerArg, AlgoVerAddrCast);
4015 Value *ReduceList =
Builder.CreateLoad(ReduceListArgType, ReduceListAddrCast);
4016 Value *LaneId =
Builder.CreateLoad(LaneIDArgType, LaneIdAddrCast);
4017 Value *RemoteLaneOffset =
4018 Builder.CreateLoad(LaneIDArgType, RemoteLaneOffsetAddrCast);
4019 Value *AlgoVer =
Builder.CreateLoad(LaneIDArgType, AlgoVerAddrCast);
4026 Error EmitRedLsCpRes = emitReductionListCopy(
4028 ReduceList, RemoteListAddrCast, IsByRef,
4029 {RemoteLaneOffset,
nullptr,
nullptr});
4032 return EmitRedLsCpRes;
4057 Value *LaneComp =
Builder.CreateICmpULT(LaneId, RemoteLaneOffset);
4062 Value *Algo2AndLaneIdComp =
Builder.CreateAnd(Algo2, LaneIdComp);
4063 Value *RemoteOffsetComp =
4065 Value *CondAlgo2 =
Builder.CreateAnd(Algo2AndLaneIdComp, RemoteOffsetComp);
4066 Value *CA0OrCA1 =
Builder.CreateOr(CondAlgo0, CondAlgo1);
4067 Value *CondReduce =
Builder.CreateOr(CA0OrCA1, CondAlgo2);
4073 Builder.CreateCondBr(CondReduce, ThenBB, ElseBB);
4075 Value *LocalReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4076 ReduceList,
Builder.getPtrTy());
4077 Value *RemoteReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4078 RemoteListAddrCast,
Builder.getPtrTy());
4080 ->addFnAttr(Attribute::NoUnwind);
4091 Value *LaneIdGtOffset =
Builder.CreateICmpUGE(LaneId, RemoteLaneOffset);
4092 Value *CondCopy =
Builder.CreateAnd(Algo1, LaneIdGtOffset);
4097 Builder.CreateCondBr(CondCopy, CpyThenBB, CpyElseBB);
4101 EmitRedLsCpRes = emitReductionListCopy(
4103 RemoteListAddrCast, ReduceList, IsByRef);
4106 return EmitRedLsCpRes;
4121OpenMPIRBuilder::generateReductionDescriptor(
4123 Type *DescriptorType,
4129 Value *DescriptorSize =
4130 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(DescriptorType));
4132 DescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4133 SrcDescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4137 Value *DataPtrField;
4139 DataPtrPtrGen(
Builder.saveIP(), DescriptorAddr, DataPtrField);
4142 return GenResult.takeError();
4145 DataPtr,
Builder.getPtrTy(),
".ascast"),
4151Expected<Value *> OpenMPIRBuilder::createReductionDescriptorCopy(
4153 Value *SrcDescriptorAddr,
Type *DescriptorPtrTy,
const Twine &Name) {
4157 AllocaInst *DescriptorAlloca =
4158 Builder.CreateAlloca(RI.ByRefAllocatedType,
nullptr, Name);
4160 M.getDataLayout().getPrefTypeAlign(RI.ByRefAllocatedType));
4161 Value *DescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4162 DescriptorAlloca, DescriptorPtrTy,
4163 DescriptorAlloca->
getName() +
".ascast");
4168 generateReductionDescriptor(DescriptorAddr, DataPtr, SrcDescriptorAddr,
4169 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
4171 return GenResult.takeError();
4173 return DescriptorAddr;
4176Expected<Function *> OpenMPIRBuilder::emitListToGlobalCopyFunction(
4179 IRBuilder<>::InsertPointGuard IPG(
Builder);
4180 LLVMContext &Ctx =
M.getContext();
4183 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4187 "_omp_reduction_list_to_global_copy_func", &
M);
4194 Builder.SetInsertPoint(EntryBlock);
4205 BufferArg->
getName() +
".addr");
4209 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4210 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4211 BufferArgAlloca,
Builder.getPtrTy(),
4212 BufferArgAlloca->
getName() +
".ascast");
4213 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4214 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4215 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4216 ReduceListArgAlloca,
Builder.getPtrTy(),
4217 ReduceListArgAlloca->
getName() +
".ascast");
4219 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4220 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4221 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4223 Value *LocalReduceList =
4225 Value *BufferArgVal =
4229 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4230 for (
auto En :
enumerate(ReductionInfos)) {
4232 auto *RedListArrayTy =
4236 RedListArrayTy, LocalReduceList,
4237 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4243 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferArgVal, Idxs);
4245 ReductionsBufferTy, BufferVD, 0, En.index());
4247 switch (RI.EvaluationKind) {
4249 Value *TargetElement;
4251 if (IsByRef.
empty() || !IsByRef[En.index()]) {
4252 TargetElement =
Builder.CreateLoad(RI.ElementType, ElemPtr);
4254 if (RI.DataPtrPtrGen) {
4256 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
4259 return GenResult.takeError();
4263 TargetElement =
Builder.CreateLoad(RI.ByRefElementType, ElemPtr);
4266 Builder.CreateStore(TargetElement, GlobVal);
4270 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4271 RI.ElementType, ElemPtr, 0, 0,
".realp");
4273 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
4275 RI.ElementType, ElemPtr, 0, 1,
".imagp");
4277 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
4279 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4280 RI.ElementType, GlobVal, 0, 0,
".realp");
4281 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4282 RI.ElementType, GlobVal, 0, 1,
".imagp");
4283 Builder.CreateStore(SrcReal, DestRealPtr);
4284 Builder.CreateStore(SrcImg, DestImgPtr);
4289 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(RI.ElementType));
4291 GlobVal,
M.getDataLayout().getPrefTypeAlign(RI.ElementType), ElemPtr,
4292 M.getDataLayout().getPrefTypeAlign(RI.ElementType), SizeVal,
false);
4302Expected<Function *> OpenMPIRBuilder::emitListToGlobalReduceFunction(
4305 IRBuilder<>::InsertPointGuard IPG(
Builder);
4306 LLVMContext &Ctx =
M.getContext();
4309 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4313 "_omp_reduction_list_to_global_reduce_func", &
M);
4320 Builder.SetInsertPoint(EntryBlock);
4331 BufferArg->
getName() +
".addr");
4335 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4336 auto *RedListArrayTy =
4341 Value *LocalReduceList =
4342 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4346 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4347 BufferArgAlloca,
Builder.getPtrTy(),
4348 BufferArgAlloca->
getName() +
".ascast");
4349 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4350 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4351 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4352 ReduceListArgAlloca,
Builder.getPtrTy(),
4353 ReduceListArgAlloca->
getName() +
".ascast");
4354 Value *LocalReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4355 LocalReduceList,
Builder.getPtrTy(),
4356 LocalReduceList->
getName() +
".ascast");
4358 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4359 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4360 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4365 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4366 for (
auto En :
enumerate(ReductionInfos)) {
4369 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4370 RedListArrayTy, LocalReduceListAddrCast,
4371 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4373 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4375 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4376 ReductionsBufferTy, BufferVD, 0, En.index());
4378 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4382 Value *SrcElementPtrPtr =
4383 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
4384 {ConstantInt::get(IndexTy, 0),
4385 ConstantInt::get(IndexTy, En.index())});
4386 Value *SrcDescriptorAddr =
4390 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4391 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4395 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4397 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4405 ->addFnAttr(Attribute::NoUnwind);
4410Expected<Function *> OpenMPIRBuilder::emitGlobalToListCopyFunction(
4413 IRBuilder<>::InsertPointGuard IPG(
Builder);
4414 LLVMContext &Ctx =
M.getContext();
4417 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4421 "_omp_reduction_global_to_list_copy_func", &
M);
4428 Builder.SetInsertPoint(EntryBlock);
4439 BufferArg->
getName() +
".addr");
4443 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4444 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4445 BufferArgAlloca,
Builder.getPtrTy(),
4446 BufferArgAlloca->
getName() +
".ascast");
4447 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4448 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4449 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4450 ReduceListArgAlloca,
Builder.getPtrTy(),
4451 ReduceListArgAlloca->
getName() +
".ascast");
4452 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4453 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4454 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4456 Value *LocalReduceList =
4461 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4462 for (
auto En :
enumerate(ReductionInfos)) {
4463 const OpenMPIRBuilder::ReductionInfo &RI = En.value();
4464 auto *RedListArrayTy =
4468 RedListArrayTy, LocalReduceList,
4469 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4474 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4475 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4476 ReductionsBufferTy, BufferVD, 0, En.index());
4482 if (!IsByRef.
empty() && IsByRef[En.index()]) {
4489 return GenResult.takeError();
4495 Value *TargetElement =
Builder.CreateLoad(ElemType, GlobValPtr);
4496 Builder.CreateStore(TargetElement, ElemPtr);
4500 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4509 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4511 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4513 Builder.CreateStore(SrcReal, DestRealPtr);
4514 Builder.CreateStore(SrcImg, DestImgPtr);
4521 ElemPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4522 GlobValPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4533Expected<Function *> OpenMPIRBuilder::emitGlobalToListReduceFunction(
4536 IRBuilder<>::InsertPointGuard IPG(
Builder);
4537 LLVMContext &Ctx =
M.getContext();
4540 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4544 "_omp_reduction_global_to_list_reduce_func", &
M);
4551 Builder.SetInsertPoint(EntryBlock);
4562 BufferArg->
getName() +
".addr");
4566 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4572 Value *LocalReduceList =
4573 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4577 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4578 BufferArgAlloca,
Builder.getPtrTy(),
4579 BufferArgAlloca->
getName() +
".ascast");
4580 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4581 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4582 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4583 ReduceListArgAlloca,
Builder.getPtrTy(),
4584 ReduceListArgAlloca->
getName() +
".ascast");
4585 Value *ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4586 LocalReduceList,
Builder.getPtrTy(),
4587 LocalReduceList->
getName() +
".ascast");
4589 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4590 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4591 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4596 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4597 for (
auto En :
enumerate(ReductionInfos)) {
4600 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4601 RedListArrayTy, ReductionList,
4602 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4605 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4606 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4607 ReductionsBufferTy, BufferVD, 0, En.index());
4609 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4611 Value *ReduceListVal =
4613 Value *SrcElementPtrPtr =
4614 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceListVal,
4615 {ConstantInt::get(IndexTy, 0),
4616 ConstantInt::get(IndexTy, En.index())});
4617 Value *SrcDescriptorAddr =
4621 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4622 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4626 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4628 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4636 ->addFnAttr(Attribute::NoUnwind);
4641std::string OpenMPIRBuilder::getReductionFuncName(StringRef Name)
const {
4642 std::string Suffix =
4644 return (Name + Suffix).str();
4647Expected<Function *> OpenMPIRBuilder::createReductionFunction(
4650 AttributeList FuncAttrs) {
4651 IRBuilder<>::InsertPointGuard IPG(
Builder);
4653 {Builder.getPtrTy(), Builder.getPtrTy()},
4655 std::string
Name = getReductionFuncName(ReducerName);
4664 Builder.SetInsertPoint(EntryBB);
4669 Value *LHSArrayPtr =
nullptr;
4670 Value *RHSArrayPtr =
nullptr;
4677 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
4679 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
4680 Value *LHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4681 LHSAlloca, Arg0Type, LHSAlloca->
getName() +
".ascast");
4682 Value *RHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4683 RHSAlloca, Arg1Type, RHSAlloca->
getName() +
".ascast");
4684 Builder.CreateStore(Arg0, LHSAddrCast);
4685 Builder.CreateStore(Arg1, RHSAddrCast);
4686 LHSArrayPtr =
Builder.CreateLoad(Arg0Type, LHSAddrCast);
4687 RHSArrayPtr =
Builder.CreateLoad(Arg1Type, RHSAddrCast);
4691 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4693 for (
auto En :
enumerate(ReductionInfos)) {
4696 RedArrayTy, RHSArrayPtr,
4697 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4699 Value *RHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4700 RHSI8Ptr, RI.PrivateVariable->getType(),
4701 RHSI8Ptr->
getName() +
".ascast");
4704 RedArrayTy, LHSArrayPtr,
4705 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4707 Value *LHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4708 LHSI8Ptr, RI.Variable->getType(), LHSI8Ptr->
getName() +
".ascast");
4717 if (!IsByRef.
empty() && !IsByRef[En.index()]) {
4718 LHS =
Builder.CreateLoad(RI.ElementType, LHSPtr);
4719 RHS =
Builder.CreateLoad(RI.ElementType, RHSPtr);
4726 return AfterIP.takeError();
4727 if (!
Builder.GetInsertBlock())
4728 return ReductionFunc;
4732 if (!IsByRef.
empty() && !IsByRef[En.index()])
4733 Builder.CreateStore(Reduced, LHSPtr);
4738 for (
auto En :
enumerate(ReductionInfos)) {
4739 unsigned Index = En.index();
4741 Value *LHSFixupPtr, *RHSFixupPtr;
4742 Builder.restoreIP(RI.ReductionGenClang(
4743 Builder.saveIP(), Index, &LHSFixupPtr, &RHSFixupPtr, ReductionFunc));
4748 LHSPtrs[Index], [ReductionFunc](
const Use &U) {
4753 RHSPtrs[Index], [ReductionFunc](
const Use &U) {
4767 return ReductionFunc;
4775 assert(RI.Variable &&
"expected non-null variable");
4776 assert(RI.PrivateVariable &&
"expected non-null private variable");
4777 assert((RI.ReductionGen || RI.ReductionGenClang) &&
4778 "expected non-null reduction generator callback");
4781 RI.Variable->getType() == RI.PrivateVariable->getType() &&
4782 "expected variables and their private equivalents to have the same "
4785 assert(RI.Variable->getType()->isPointerTy() &&
4786 "expected variables to be pointers");
4803 ArrayRef<bool> IsByRef,
bool IsNoWait,
bool IsTeamsReduction,
bool IsSPMD,
4805 Value *SrcLocInfo) {
4820 if (ReductionInfos.
size() == 0)
4834 AttrBuilder AttrBldr(Ctx);
4836 AttrBldr.addAttribute(Attr);
4837 AttrBldr.removeAttribute(Attribute::OptimizeNone);
4838 FuncAttrs = FuncAttrs.addFnAttributes(Ctx, AttrBldr);
4841 Builder.GetInsertBlock()->getParent()->getName(), ReductionInfos, IsByRef,
4843 if (!ReductionResult)
4845 Function *ReductionFunc = *ReductionResult;
4848 if (GridValue.has_value())
4849 Config.setGridValue(GridValue.value());
4864 Builder.getPtrTy(
M.getDataLayout().getProgramAddressSpace());
4866 Value *ReductionList;
4870 Value *ReductionListAlloca =
4871 Builder.CreateAlloca(RedArrayTy,
nullptr,
".omp.reduction.red_list");
4872 ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4873 ReductionListAlloca, PtrTy, ReductionListAlloca->
getName() +
".ascast");
4876 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4877 for (
auto En :
enumerate(ReductionInfos)) {
4880 RedArrayTy, ReductionList,
4881 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4884 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
4889 Builder.CreatePointerBitCastOrAddrSpaceCast(PrivateVar, PtrTy);
4890 Builder.CreateStore(CastElem, ElemPtr);
4893 ReductionInfos, ReductionFunc, FuncAttrs, IsByRef);
4899 emitInterWarpCopyFunction(
Loc, ReductionInfos, FuncAttrs, IsByRef);
4904 Value *RL =
Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList, PtrTy);
4913 unsigned MaxDataSize = 0;
4915 for (
auto En :
enumerate(ReductionInfos)) {
4919 Type *RedTypeArg = (!IsByRef.
empty() && IsByRef[En.index()])
4920 ? En.value().ByRefElementType
4921 : En.value().ElementType;
4922 auto Size =
M.getDataLayout().getTypeStoreSize(RedTypeArg);
4923 if (
Size > MaxDataSize)
4927 Value *ReductionDataSize =
4928 Builder.getInt64(MaxDataSize * ReductionInfos.
size());
4932 Function *CopyScratchToListFunc =
nullptr;
4934 Value *ScratchForCopyBack =
nullptr;
4937 Value *RLForCopyBack = RL;
4939 bool IsAtomicReduction =
4942 if (!IsTeamsReduction) {
4943 Value *SarFuncCast =
4944 Builder.CreatePointerBitCastOrAddrSpaceCast(*SarFunc, FuncPtrTy);
4946 Builder.CreatePointerBitCastOrAddrSpaceCast(WcFunc, FuncPtrTy);
4947 Value *Args[] = {SrcLocInfo, ReductionDataSize, RL, SarFuncCast,
4950 RuntimeFunction::OMPRTL___kmpc_nvptx_parallel_reduce_nowait_v2);
4952 }
else if (IsAtomicReduction) {
4956 RuntimeFunction::OMPRTL___kmpc_is_team_main_thread);
4960 Ctx, ReductionTypeArgs,
"struct._globalized_locals_ty");
4963 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
4968 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
4973 ReductionInfos, ReductionFunc, ReductionsBufferTy, FuncAttrs, IsByRef);
4994 Value *RuntimeRL = RL;
4997 Value *PerThreadScratch;
5003 Value *PerThreadScratchAlloca =
5004 Builder.CreateAlloca(ReductionsBufferTy,
nullptr,
5005 ".omp.reduction.scratch");
5006 PerThreadScratch =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5007 PerThreadScratchAlloca, PtrTy,
5008 PerThreadScratchAlloca->
getName() +
".ascast");
5011 Value *PerThreadRedListAlloca =
5012 Builder.CreateAlloca(RedArrayTy,
nullptr,
5013 ".omp.reduction.per_thread_red_list");
5014 RuntimeRL =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5015 PerThreadRedListAlloca, PtrTy,
5016 PerThreadRedListAlloca->
getName() +
".ascast");
5021 for (
auto En :
enumerate(ReductionInfos)) {
5023 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
5026 ReductionsBufferTy, PerThreadScratch, 0, En.index());
5027 Value *Slot =
Builder.CreateConstInBoundsGEP2_32(RedArrayTy, RuntimeRL,
5030 Value *RuntimeListEntry = FieldPtr;
5032 Value *SrcDescriptor =
5035 AllocaIP, RI, FieldPtr, SrcDescriptor, PtrTy);
5038 RuntimeListEntry = *Descriptor;
5040 Builder.CreateStore(RuntimeListEntry, Slot);
5046 Type *CopyArg0Ty = (*LtGCFunc)->getFunctionType()->getParamType(0);
5047 Type *CopyArg2Ty = (*LtGCFunc)->getFunctionType()->getParamType(2);
5048 ScratchForCopyBack =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5049 PerThreadScratch, CopyArg0Ty);
5051 Builder.CreatePointerBitCastOrAddrSpaceCast(RL, CopyArg2Ty);
5059 *LtGCFunc, {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
5060 CopyScratchToListFunc = *GtLCFunc;
5063 Value *Args3[] = {SrcLocInfo, RuntimeRL, *SarFunc, WcFunc,
5064 *LtGCFunc, *GtLCFunc, *GtLRFunc};
5067 RuntimeFunction::OMPRTL___kmpc_gpu_xteam_reduce_nowait);
5087 if (ScratchForCopyBack) {
5090 CopyScratchToListFunc,
5091 {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
5095 for (
auto En :
enumerate(ReductionInfos)) {
5101 if (IsAtomicReduction) {
5117 Value *LHSPtr, *RHSPtr;
5119 &LHSPtr, &RHSPtr, CurFunc));
5125 RedValue =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5127 if (RHSPtr->
getType() != RHS->getType())
5129 Builder.CreatePointerBitCastOrAddrSpaceCast(RHS, RHSPtr->
getType());
5140 if (IsByRef.
empty() || !IsByRef[En.index()]) {
5142 "red.value." +
Twine(En.index()));
5153 if (!IsByRef.
empty() && !IsByRef[En.index()])
5158 if (ContinuationBlock) {
5159 Builder.CreateBr(ContinuationBlock);
5160 Builder.SetInsertPoint(ContinuationBlock);
5162 Config.setEmitLLVMUsed();
5173 ".omp.reduction.func", &M);
5184 Builder.SetInsertPoint(ReductionFuncBlock);
5186 Value *LHSArrayPtr =
nullptr;
5187 Value *RHSArrayPtr =
nullptr;
5198 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
5200 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
5201 Value *LHSAddrCast =
5202 Builder.CreatePointerBitCastOrAddrSpaceCast(LHSAlloca, Arg0Type);
5203 Value *RHSAddrCast =
5204 Builder.CreatePointerBitCastOrAddrSpaceCast(RHSAlloca, Arg1Type);
5205 Builder.CreateStore(Arg0, LHSAddrCast);
5206 Builder.CreateStore(Arg1, RHSAddrCast);
5207 LHSArrayPtr = Builder.CreateLoad(Arg0Type, LHSAddrCast);
5208 RHSArrayPtr = Builder.CreateLoad(Arg1Type, RHSAddrCast);
5210 LHSArrayPtr = ReductionFunc->
getArg(0);
5211 RHSArrayPtr = ReductionFunc->
getArg(1);
5214 unsigned NumReductions = ReductionInfos.
size();
5217 for (
auto En :
enumerate(ReductionInfos)) {
5219 Value *LHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5220 RedArrayTy, LHSArrayPtr, 0, En.index());
5221 Value *LHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), LHSI8PtrPtr);
5222 Value *LHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5225 Value *RHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5226 RedArrayTy, RHSArrayPtr, 0, En.index());
5227 Value *RHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), RHSI8PtrPtr);
5228 Value *RHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5237 Builder.restoreIP(*AfterIP);
5239 if (!Builder.GetInsertBlock())
5243 if (!IsByRef[En.index()])
5244 Builder.CreateStore(Reduced, LHSPtr);
5246 Builder.CreateRetVoid();
5253 bool IsNoWait,
bool IsTeamsReduction) {
5257 IsByRef, IsNoWait, IsTeamsReduction);
5264 if (ReductionInfos.
size() == 0)
5274 unsigned NumReductions = ReductionInfos.
size();
5276 Builder.SetInsertPoint(AllocaIP.getNodeParent()->getTerminator());
5277 Value *RedArray =
Builder.CreateAlloca(RedArrayTy,
nullptr,
"red.array");
5284 for (
auto En :
enumerate(ReductionInfos)) {
5285 unsigned Index = En.index();
5287 Value *RedArrayElemPtr =
Builder.CreateConstInBoundsGEP2_64(
5288 RedArrayTy, RedArray, 0, Index,
"red.array.elem." +
Twine(Index));
5295 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
5305 ? IdentFlag::OMP_IDENT_FLAG_ATOMIC_REDUCE
5310 unsigned RedArrayByteSize =
DL.getTypeStoreSize(RedArrayTy);
5311 Constant *RedArraySize = ConstantInt::get(IndexTy, RedArrayByteSize);
5313 Value *Lock = getOMPCriticalRegionLock(
".reduction");
5315 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_reduce_nowait
5316 : RuntimeFunction::OMPRTL___kmpc_reduce);
5319 {Ident, ThreadId, NumVariables, RedArraySize,
5320 RedArray, ReductionFunc, Lock},
5331 Builder.CreateSwitch(ReduceCall, ContinuationBlock, 2);
5332 Switch->addCase(
Builder.getInt32(1), NonAtomicRedBlock);
5333 Switch->addCase(
Builder.getInt32(2), AtomicRedBlock);
5338 Builder.SetInsertPoint(NonAtomicRedBlock);
5339 for (
auto En :
enumerate(ReductionInfos)) {
5345 if (!IsByRef[En.index()]) {
5347 "red.value." +
Twine(En.index()));
5349 Value *PrivateRedValue =
5351 "red.private.value." +
Twine(En.index()));
5359 if (!
Builder.GetInsertBlock())
5362 if (!IsByRef[En.index()])
5366 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_end_reduce_nowait
5367 : RuntimeFunction::OMPRTL___kmpc_end_reduce);
5369 Builder.CreateBr(ContinuationBlock);
5374 Builder.SetInsertPoint(AtomicRedBlock);
5375 if (CanGenerateAtomic &&
llvm::none_of(IsByRef, [](
bool P) {
return P; })) {
5382 if (!
Builder.GetInsertBlock())
5385 Builder.CreateBr(ContinuationBlock);
5398 if (!
Builder.GetInsertBlock())
5401 Builder.SetInsertPoint(ContinuationBlock);
5412 Directive OMPD = Directive::OMPD_master;
5417 Value *Args[] = {Ident, ThreadId};
5425 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5437 Directive OMPD = Directive::OMPD_masked;
5443 Value *ArgsEnd[] = {Ident, ThreadId};
5451 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5461 Call->setDoesNotThrow();
5476 bool IsInclusive,
ScanInfo *ScanRedInfo) {
5478 llvm::Error Err = emitScanBasedDirectiveDeclsIR(AllocaIP, ScanVars,
5479 ScanVarsType, ScanRedInfo);
5490 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5493 Type *DestTy = ScanVarsType[i];
5494 Value *Val =
Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5497 Builder.CreateStore(Src, Val);
5502 Builder.GetInsertBlock()->getParent());
5505 IV = ScanRedInfo->
IV;
5508 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5511 Type *DestTy = ScanVarsType[i];
5513 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5515 Builder.CreateStore(Src, ScanVars[i]);
5529 Builder.GetInsertBlock()->getParent());
5534Error OpenMPIRBuilder::emitScanBasedDirectiveDeclsIR(
5538 Builder.restoreIP(AllocaIP);
5540 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5542 Builder.CreateAlloca(Builder.getPtrTy(),
nullptr,
"vla");
5549 Builder.restoreIP(CodeGenIP);
5551 Builder.CreateAdd(ScanRedInfo->
Span, Builder.getInt32(1));
5552 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5554 Value *Allocsize = Builder.CreateTypeSize(
5555 IntPtrTy, M.getDataLayout().getTypeAllocSize(ScanVarsType[i]));
5557 Builder.CreateMalloc(
IntPtrTy, Allocsize, AllocSpan,
nullptr,
"arr");
5558 Builder.CreateStore(Buff, (*(ScanRedInfo->
ScanBuffPtrs))[ScanVars[i]]);
5585Error OpenMPIRBuilder::emitScanBasedDirectiveFinalsIR(
5591 Value *PrivateVar = RedInfo.PrivateVariable;
5592 Value *OrigVar = RedInfo.Variable;
5596 Type *SrcTy = RedInfo.ElementType;
5601 Builder.CreateStore(Src, OrigVar);
5662 llvm::ConstantInt::get(ScanRedInfo->
Span->
getType(), 1));
5663 Builder.SetInsertPoint(InputBB);
5666 Builder.SetInsertPoint(LoopBB);
5682 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5684 Builder.SetInsertPoint(InnerLoopBB);
5688 Value *ReductionVal = RedInfo.PrivateVariable;
5691 Type *DestTy = RedInfo.ElementType;
5694 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5697 Builder.CreateInBoundsGEP(DestTy, Buff, OffsetIval,
"arrayOffset");
5702 RedInfo.ReductionGen(
Builder.saveIP(), LHS, RHS, Result);
5705 Builder.CreateStore(Result, LHSPtr);
5708 IVal, llvm::ConstantInt::get(
Builder.getInt32Ty(), 1));
5710 CmpI =
Builder.CreateICmpUGE(NextIVal, Pow2K);
5711 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5714 Counter, llvm::ConstantInt::get(Counter->
getType(), 1));
5720 Builder.CreateCondBr(Cmp, LoopBB, ExitBB);
5741 Error Err = emitScanBasedDirectiveFinalsIR(ReductionInfos, ScanRedInfo);
5748Error OpenMPIRBuilder::emitScanBasedDirectiveIR(
5760 Error Err = InputLoopGen();
5771 Error Err = ScanLoopGen(Builder);
5778void OpenMPIRBuilder::createScanBBs(ScanInfo *ScanRedInfo) {
5815 Builder.SetInsertPoint(Preheader);
5818 Builder.SetInsertPoint(Header);
5819 PHINode *IndVarPHI =
Builder.CreatePHI(IndVarTy, 2,
"omp_" + Name +
".iv");
5820 IndVarPHI->
addIncoming(ConstantInt::get(IndVarTy, 0), Preheader);
5825 Builder.CreateICmpULT(IndVarPHI, TripCount,
"omp_" + Name +
".cmp");
5826 Builder.CreateCondBr(Cmp, Body, Exit);
5831 Builder.SetInsertPoint(Latch);
5841 bool HasNSW =
Config.hasNoSignedWrap();
5844 unsigned BitWidth = CI->getType()->getIntegerBitWidth();
5846 if (CI->getValue().ugt(SignedMax))
5848 }
else if (IsCollapsed) {
5853 Builder.CreateAdd(IndVarPHI, ConstantInt::get(IndVarTy, 1),
5854 "omp_" + Name +
".next",
true, HasNSW);
5865 CL->Header = Header;
5884 NextBB, NextBB, Name);
5916 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
5925 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
5926 ScanRedInfo->
Span = TripCount;
5932 ScanRedInfo->
IV =
IV;
5933 createScanBBs(ScanRedInfo);
5936 assert(Terminator->getNumSuccessors() == 1);
5937 BasicBlock *ContinueBlock = Terminator->getSuccessor(0);
5940 Builder.GetInsertBlock()->getParent());
5943 Builder.GetInsertBlock()->getParent());
5944 Builder.CreateBr(ContinueBlock);
5950 const auto &&InputLoopGen = [&]() ->
Error {
5953 InclusiveStop, ComputeIP, Name,
true, ScanRedInfo);
5957 Builder.restoreIP((*LoopInfo)->getAfterIP());
5963 InclusiveStop, ComputeIP, Name,
true, ScanRedInfo);
5967 Builder.restoreIP((*LoopInfo)->getAfterIP());
5971 Error Err = emitScanBasedDirectiveIR(InputLoopGen, ScanLoopGen, ScanRedInfo);
5979 bool IsSigned,
bool InclusiveStop,
const Twine &Name) {
5989 assert(IndVarTy == Stop->
getType() &&
"Stop type mismatch");
5990 assert(IndVarTy == Step->
getType() &&
"Step type mismatch");
5994 ConstantInt *Zero = ConstantInt::get(IndVarTy, 0);
6010 Incr =
Builder.CreateSelect(IsNeg,
Builder.CreateNeg(Step), Step);
6013 Span =
Builder.CreateSub(UB, LB,
"",
false,
true);
6017 Span =
Builder.CreateSub(Stop, Start,
"",
true);
6022 Value *CountIfLooping;
6023 if (InclusiveStop) {
6024 CountIfLooping =
Builder.CreateAdd(
Builder.CreateUDiv(Span, Incr), One);
6030 CountIfLooping =
Builder.CreateSelect(OneCmp, One, CountIfTwo);
6033 return Builder.CreateSelect(ZeroCmp, Zero, CountIfLooping,
6034 "omp_" + Name +
".tripcount");
6039 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
6046 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
6051 Config.hasNoSignedWrap());
6052 Value *IndVar =
Builder.CreateAdd(Span, Start,
"",
false,
6053 Config.hasNoSignedWrap());
6055 ScanRedInfo->
IV = IndVar;
6056 return BodyGenCB(
Builder.saveIP(), IndVar);
6062 Builder.getCurrentDebugLocation());
6073 unsigned Bitwidth = Ty->getIntegerBitWidth();
6076 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_4u);
6079 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_8u);
6089 unsigned Bitwidth = Ty->getIntegerBitWidth();
6092 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_4u);
6095 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_8u);
6103 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6105 "Require dedicated allocate IP");
6111 uint32_t SrcLocStrSize;
6115 case WorksharingLoopType::ForStaticLoop:
6116 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6118 case WorksharingLoopType::DistributeStaticLoop:
6119 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6121 case WorksharingLoopType::DistributeForStaticLoop:
6122 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
6129 Type *IVTy =
IV->getType();
6130 FunctionCallee StaticInit =
6131 LoopType == WorksharingLoopType::DistributeForStaticLoop
6134 FunctionCallee StaticFini =
6139 AllocaIP.getNodeParent()->getFirstNonPHIOrDbgOrAlloca());
6142 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6143 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
6144 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
6145 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
6154 Constant *One = ConstantInt::get(IVTy, 1);
6155 Builder.CreateStore(Zero, PLowerBound);
6157 Builder.CreateStore(UpperBound, PUpperBound);
6158 Builder.CreateStore(One, PStride);
6164 (LoopType == WorksharingLoopType::DistributeStaticLoop)
6165 ? OMPScheduleType::OrderedDistribute
6168 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6172 auto BuildInitCall = [LoopType, SrcLoc, ThreadNum, PLastIter, PLowerBound,
6173 PUpperBound, IVTy, PStride, One,
Zero, StaticInit,
6176 PLowerBound, PUpperBound});
6177 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
6178 Value *PDistUpperBound =
6179 Builder.CreateAlloca(IVTy,
nullptr,
"p.distupperbound");
6180 Args.push_back(PDistUpperBound);
6185 BuildInitCall(SchedulingType,
Builder);
6186 if (HasDistSchedule &&
6187 LoopType != WorksharingLoopType::DistributeStaticLoop) {
6188 Constant *DistScheduleSchedType = ConstantInt::get(
6193 BuildInitCall(DistScheduleSchedType,
Builder);
6196 Value *InclusiveUpperBound =
Builder.CreateLoad(IVTy, PUpperBound);
6198 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One);
6199 CLI->setTripCount(TripCount);
6205 CLI->mapIndVar([&](Instruction *OldIV) ->
Value * {
6209 Config.hasNoSignedWrap());
6220 omp::Directive::OMPD_for,
false,
6223 return BarrierIP.takeError();
6250 Reachable.insert(
Block);
6264OpenMPIRBuilder::applyStaticChunkedWorkshareLoop(
6268 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6269 assert((ChunkSize || DistScheduleChunkSize) &&
"Chunk size is required");
6274 Type *IVTy =
IV->getType();
6276 "Max supported tripcount bitwidth is 64 bits");
6278 :
Type::getInt64Ty(Ctx);
6281 Constant *One = ConstantInt::get(InternalIVTy, 1);
6286 SmallVector<Instruction *> UIs;
6287 for (BasicBlock &BB : *
F)
6288 if (!BB.hasTerminator())
6289 UIs.
push_back(
new UnreachableInst(
F->getContext(), &BB));
6294 LoopInfo &&LI = LIA.
run(*
F,
FAM);
6295 for (Instruction *
I : UIs)
6296 I->eraseFromParent();
6299 if (ChunkSize || DistScheduleChunkSize)
6304 FunctionCallee StaticInit =
6306 FunctionCallee StaticFini =
6312 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6313 Value *PLowerBound =
6314 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.lowerbound");
6315 Value *PUpperBound =
6316 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.upperbound");
6317 Value *PStride =
Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.stride");
6326 ChunkSize ? ChunkSize : Zero, InternalIVTy,
"chunksize");
6327 Value *CastedDistScheduleChunkSize =
Builder.CreateZExtOrTrunc(
6328 DistScheduleChunkSize ? DistScheduleChunkSize : Zero, InternalIVTy,
6329 "distschedulechunksize");
6330 Value *CastedTripCount =
6331 Builder.CreateZExt(OrigTripCount, InternalIVTy,
"tripcount");
6334 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6336 ConstantInt::get(I32Type,
static_cast<int>(DistScheduleSchedType));
6337 Builder.CreateStore(Zero, PLowerBound);
6338 Value *OrigUpperBound =
Builder.CreateSub(CastedTripCount, One);
6339 Value *IsTripCountZero =
Builder.CreateICmpEQ(CastedTripCount, Zero);
6341 Builder.CreateSelect(IsTripCountZero, Zero, OrigUpperBound);
6342 Builder.CreateStore(UpperBound, PUpperBound);
6343 Builder.CreateStore(One, PStride);
6347 uint32_t SrcLocStrSize;
6350 if (DistScheduleSchedType != OMPScheduleType::None) {
6351 Flag |= OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6356 auto BuildInitCall = [StaticInit, SrcLoc, ThreadNum, PLastIter, PLowerBound,
6357 PUpperBound, PStride, One,
6358 this](
Value *SchedulingType,
Value *ChunkSize,
6361 StaticInit, {SrcLoc, ThreadNum,
6362 SchedulingType, PLastIter,
6363 PLowerBound, PUpperBound,
6367 BuildInitCall(SchedulingType, CastedChunkSize,
Builder);
6368 if (DistScheduleSchedType != OMPScheduleType::None &&
6369 SchedType != OMPScheduleType::OrderedDistributeChunked &&
6370 SchedType != OMPScheduleType::OrderedDistribute) {
6374 BuildInitCall(DistSchedulingType, CastedDistScheduleChunkSize,
Builder);
6378 Value *FirstChunkStart =
6379 Builder.CreateLoad(InternalIVTy, PLowerBound,
"omp_firstchunk.lb");
6380 Value *FirstChunkStop =
6381 Builder.CreateLoad(InternalIVTy, PUpperBound,
"omp_firstchunk.ub");
6382 Value *FirstChunkEnd =
Builder.CreateAdd(FirstChunkStop, One);
6384 Builder.CreateSub(FirstChunkEnd, FirstChunkStart,
"omp_chunk.range");
6385 Value *NextChunkStride =
6386 Builder.CreateLoad(InternalIVTy, PStride,
"omp_dispatch.stride");
6390 Value *DispatchCounter;
6398 DispatchCounter = Counter;
6401 FirstChunkStart, CastedTripCount, NextChunkStride,
6424 Value *ChunkEnd =
Builder.CreateAdd(DispatchCounter, ChunkRange);
6425 Value *IsLastChunk =
6426 Builder.CreateICmpUGE(ChunkEnd, CastedTripCount,
"omp_chunk.is_last");
6427 Value *CountUntilOrigTripCount =
6428 Builder.CreateSub(CastedTripCount, DispatchCounter);
6430 IsLastChunk, CountUntilOrigTripCount, ChunkRange,
"omp_chunk.tripcount");
6431 Value *BackcastedChunkTC =
6432 Builder.CreateTrunc(ChunkTripCount, IVTy,
"omp_chunk.tripcount.trunc");
6433 CLI->setTripCount(BackcastedChunkTC);
6438 Value *BackcastedDispatchCounter =
6439 Builder.CreateTrunc(DispatchCounter, IVTy,
"omp_dispatch.iv.trunc");
6440 CLI->mapIndVar([&](Instruction *) ->
Value * {
6442 return Builder.CreateAdd(
IV, BackcastedDispatchCounter);
6455 return AfterIP.takeError();
6470static FunctionCallee
6473 unsigned Bitwidth = Ty->getIntegerBitWidth();
6476 case WorksharingLoopType::ForStaticLoop:
6479 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_4u);
6482 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_8u);
6484 case WorksharingLoopType::DistributeStaticLoop:
6487 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_4u);
6490 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_8u);
6492 case WorksharingLoopType::DistributeForStaticLoop:
6495 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_4u);
6498 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_8u);
6501 if (Bitwidth != 32 && Bitwidth != 64) {
6513 Function &LoopBodyFn,
bool NoLoop) {
6524 if (LoopType == WorksharingLoopType::DistributeStaticLoop) {
6525 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6526 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6527 Builder.restoreIP(std::prev(InsertBlock->
end()));
6532 M, omp::RuntimeFunction::OMPRTL_omp_get_num_threads);
6533 Builder.restoreIP(std::prev(InsertBlock->
end()));
6537 Builder.CreateZExtOrTrunc(NumThreads, TripCountTy,
"num.threads.cast"));
6538 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6539 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
6540 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6541 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), NoLoop));
6543 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6567 Builder.restoreIP(Preheader->
end());
6570 Builder.CreateBr(CLI->
getExit());
6578 CleanUpInfo.
collectBlocks(RegionBlockSet, BlocksToBeRemoved);
6586 "Expected unique undroppable user of outlined function");
6588 assert(OutlinedFnCallInstruction &&
"Expected outlined function call");
6590 "Expected outlined function call to be located in loop preheader");
6592 if (OutlinedFnCallInstruction->
arg_size() > 1)
6599 LoopBodyArg, TripCount, OutlinedFn, NoLoop);
6601 for (
auto &ToBeDeletedItem : ToBeDeleted)
6602 ToBeDeletedItem->eraseFromParent();
6609 bool NeedsLastIter) {
6610 uint32_t SrcLocStrSize;
6614 if (NeedsLastIter) {
6617 AllocaInst *PLastIter =
6618 Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6622 Builder.CreateStore(ConstantInt::get(I32Type, 0), PLastIter);
6627 Builder.CreateSub(TripCount, ConstantInt::get(TripCount->
getType(), 1));
6630 Builder.CreateStore(
Builder.CreateZExt(IsLast, I32Type), PLastIter);
6635 case WorksharingLoopType::ForStaticLoop:
6636 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6638 case WorksharingLoopType::DistributeStaticLoop:
6639 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6641 case WorksharingLoopType::DistributeForStaticLoop:
6642 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
6647 auto OI = std::make_unique<OutlineInfo>();
6652 SmallVector<Instruction *, 4> ToBeDeleted;
6654 OI->OuterAllocBB = AllocaIP.getNodeParent();
6677 SmallPtrSet<BasicBlock *, 32> ParallelRegionBlockSet;
6679 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
6681 CodeExtractorAnalysisCache CEAC(*OuterFn);
6682 CodeExtractor Extractor(Blocks,
6696 SetVector<Value *> SinkingCands, HoistingCands;
6700 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
6707 for (
auto Use :
Users) {
6709 if (ParallelRegionBlockSet.
count(Inst->getParent())) {
6710 Inst->replaceUsesOfWith(CLI->
getIndVar(), NewLoopCntLoad);
6716 OI->ExcludeArgsFromAggregate.push_back(NewLoopCntLoad);
6723 OI->PostOutlineCB = [=, ToBeDeletedVec =
6724 std::move(ToBeDeleted)](
Function &OutlinedFn) {
6741 return BarrierIP.takeError();
6748 bool NeedsBarrier, omp::ScheduleKind SchedKind,
Value *ChunkSize,
6749 bool HasSimdModifier,
bool HasMonotonicModifier,
6750 bool HasNonmonotonicModifier,
bool HasOrderedClause,
6752 Value *DistScheduleChunkSize,
bool NeedsLastIter) {
6753 if (
Config.isTargetDevice())
6754 return applyWorkshareLoopTarget(
DL, CLI, AllocaIP, LoopType, NeedsBarrier,
6755 NoLoop, NeedsLastIter);
6757 SchedKind, ChunkSize, HasSimdModifier, HasMonotonicModifier,
6758 HasNonmonotonicModifier, HasOrderedClause, DistScheduleChunkSize);
6760 bool IsOrdered = (EffectiveScheduleType & OMPScheduleType::ModifierOrdered) ==
6761 OMPScheduleType::ModifierOrdered;
6763 if (HasDistSchedule) {
6764 DistScheduleSchedType = DistScheduleChunkSize
6765 ? OMPScheduleType::OrderedDistributeChunked
6766 : OMPScheduleType::OrderedDistribute;
6768 switch (EffectiveScheduleType & ~OMPScheduleType::ModifierMask) {
6769 case OMPScheduleType::BaseStatic:
6770 case OMPScheduleType::BaseDistribute:
6771 assert((!ChunkSize || !DistScheduleChunkSize) &&
6772 "No chunk size with static-chunked schedule");
6773 if (IsOrdered && !HasDistSchedule)
6774 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6775 NeedsBarrier, ChunkSize);
6777 if (DistScheduleChunkSize)
6778 return applyStaticChunkedWorkshareLoop(
6779 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6780 DistScheduleChunkSize, DistScheduleSchedType);
6781 return applyStaticWorkshareLoop(
DL, CLI, AllocaIP, LoopType, NeedsBarrier,
6784 case OMPScheduleType::BaseStaticChunked:
6785 case OMPScheduleType::BaseDistributeChunked:
6786 if (IsOrdered && !HasDistSchedule)
6787 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6788 NeedsBarrier, ChunkSize);
6790 return applyStaticChunkedWorkshareLoop(
6791 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6792 DistScheduleChunkSize, DistScheduleSchedType);
6794 case OMPScheduleType::BaseRuntime:
6795 case OMPScheduleType::BaseAuto:
6796 case OMPScheduleType::BaseGreedy:
6797 case OMPScheduleType::BaseBalanced:
6798 case OMPScheduleType::BaseSteal:
6799 case OMPScheduleType::BaseRuntimeSimd:
6801 "schedule type does not support user-defined chunk sizes");
6803 case OMPScheduleType::BaseGuidedSimd:
6804 case OMPScheduleType::BaseDynamicChunked:
6805 case OMPScheduleType::BaseGuidedChunked:
6806 case OMPScheduleType::BaseGuidedIterativeChunked:
6807 case OMPScheduleType::BaseGuidedAnalyticalChunked:
6808 case OMPScheduleType::BaseStaticBalancedChunked:
6809 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6810 NeedsBarrier, ChunkSize);
6823 unsigned Bitwidth = Ty->getIntegerBitWidth();
6826 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_4u);
6829 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_8u);
6837static FunctionCallee
6839 unsigned Bitwidth = Ty->getIntegerBitWidth();
6842 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_4u);
6845 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_8u);
6852static FunctionCallee
6854 unsigned Bitwidth = Ty->getIntegerBitWidth();
6857 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_4u);
6860 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_8u);
6865OpenMPIRBuilder::applyDynamicWorkshareLoop(
DebugLoc DL, CanonicalLoopInfo *CLI,
6868 bool NeedsBarrier,
Value *Chunk) {
6869 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6871 "Require dedicated allocate IP");
6873 "Require valid schedule type");
6875 bool Ordered = (SchedType & OMPScheduleType::ModifierOrdered) ==
6876 OMPScheduleType::ModifierOrdered;
6881 uint32_t SrcLocStrSize;
6888 Type *IVTy =
IV->getType();
6894 AllocaIP.getNodeParent()->getFirstNonPHIOrDbgOrAlloca());
6896 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6897 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
6898 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
6899 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
6908 Constant *One = ConstantInt::get(IVTy, 1);
6909 Builder.CreateStore(One, PLowerBound);
6911 Builder.CreateStore(UpperBound, PUpperBound);
6912 Builder.CreateStore(One, PStride);
6930 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6942 Builder.SetInsertPoint(OuterCond->getFirstInsertionPt());
6945 {SrcLoc, ThreadNum, PLastIter, PLowerBound, PUpperBound, PStride});
6946 Constant *Zero32 = ConstantInt::get(I32Type, 0);
6949 Builder.CreateSub(
Builder.CreateLoad(IVTy, PLowerBound), One,
"lb");
6950 Builder.CreateCondBr(MoreWork, Header, Exit);
6956 PI->setIncomingBlock(0, OuterCond);
6962 Br->setSuccessor(OuterCond);
6967 Builder.SetInsertPoint(
Cond->getFirstInsertionPt());
6968 UpperBound =
Builder.CreateLoad(IVTy, PUpperBound,
"ub");
6971 CI->setOperand(1, UpperBound);
6975 assert(BI->getSuccessor(1) == Exit);
6976 BI->setSuccessor(1, OuterCond);
6990 omp::Directive::OMPD_for,
false,
6993 return BarrierIP.takeError();
7045 assert(
Loops.size() >= 1 &&
"At least one loop required");
7046 size_t NumLoops =
Loops.size();
7050 return Loops.front();
7062 Loop->collectControlBlocks(OldControlBBs);
7066 if (ComputeIP.isValid())
7073 Value *CollapsedTripCount =
nullptr;
7076 "All loops to collapse must be valid canonical loops");
7077 Value *OrigTripCount = L->getTripCount();
7078 if (!CollapsedTripCount) {
7079 CollapsedTripCount = OrigTripCount;
7084 CollapsedTripCount =
7085 Builder.CreateNUWMul(CollapsedTripCount, OrigTripCount);
7091 OrigPreheader->
getNextNode(), OrigAfter,
"collapsed",
7098 Builder.restoreIP(Result->getBodyIP());
7100 Value *Leftover = Result->getIndVar();
7102 NewIndVars.
resize(NumLoops);
7103 for (
int i = NumLoops - 1; i >= 1; --i) {
7104 Value *OrigTripCount =
Loops[i]->getTripCount();
7106 Value *NewIndVar =
Builder.CreateURem(Leftover, OrigTripCount);
7107 NewIndVars[i] = NewIndVar;
7109 Leftover =
Builder.CreateUDiv(Leftover, OrigTripCount);
7112 NewIndVars[0] = Leftover;
7121 BasicBlock *ContinueBlock = Result->getBody();
7123 auto ContinueWith = [&ContinueBlock, &ContinuePred,
DL](
BasicBlock *Dest,
7130 ContinueBlock =
nullptr;
7131 ContinuePred = NextSrc;
7138 for (
size_t i = 0; i < NumLoops - 1; ++i)
7139 ContinueWith(
Loops[i]->getBody(),
Loops[i + 1]->getHeader());
7145 for (
size_t i = NumLoops - 1; i > 0; --i)
7146 ContinueWith(
Loops[i]->getAfter(),
Loops[i - 1]->getLatch());
7149 ContinueWith(Result->getLatch(),
nullptr);
7156 for (
size_t i = 0; i < NumLoops; ++i)
7157 Loops[i]->getIndVar()->replaceAllUsesWith(NewIndVars[i]);
7171std::vector<CanonicalLoopInfo *>
7175 "Must pass as many tile sizes as there are loops");
7176 int NumLoops =
Loops.size();
7177 assert(NumLoops >= 1 &&
"At least one loop to tile required");
7189 Loop->collectControlBlocks(OldControlBBs);
7197 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7198 OrigTripCounts.
push_back(L->getTripCount());
7209 for (
int i = 0; i < NumLoops - 1; ++i) {
7222 for (
int i = 0; i < NumLoops; ++i) {
7223 Value *TileSize = TileSizes[i];
7224 Value *OrigTripCount = OrigTripCounts[i];
7227 Value *FloorCompleteTripCount =
Builder.CreateUDiv(OrigTripCount, TileSize);
7228 Value *FloorTripRem =
Builder.CreateURem(OrigTripCount, TileSize);
7237 Value *FloorTripOverflow =
7238 Builder.CreateICmpNE(FloorTripRem, ConstantInt::get(IVType, 0));
7240 FloorTripOverflow =
Builder.CreateZExt(FloorTripOverflow, IVType);
7241 Value *FloorTripCount =
7242 Builder.CreateAdd(FloorCompleteTripCount, FloorTripOverflow,
7243 "omp_floor" +
Twine(i) +
".tripcount",
true);
7246 FloorCompleteCount.
push_back(FloorCompleteTripCount);
7252 std::vector<CanonicalLoopInfo *> Result;
7253 Result.reserve(NumLoops * 2);
7266 auto EmbeddNewLoop =
7267 [
this,
DL,
F, InnerEnter, &Enter, &
Continue, &OutroInsertBefore](
7270 DL, TripCount,
F, InnerEnter, OutroInsertBefore, Name);
7275 Enter = EmbeddedLoop->
getBody();
7277 OutroInsertBefore = EmbeddedLoop->
getLatch();
7278 return EmbeddedLoop;
7282 const Twine &NameBase) {
7285 EmbeddNewLoop(
P.value(), NameBase +
Twine(
P.index()));
7286 Result.push_back(EmbeddedLoop);
7290 EmbeddNewLoops(FloorCount,
"floor");
7296 for (
int i = 0; i < NumLoops; ++i) {
7298 Value *TileSize = TileSizes[i];
7300 Value *FloorIsEpilogue =
7302 Value *TileTripCount =
7303 Builder.CreateSelect(FloorIsEpilogue, FloorRems[i], TileSize);
7309 EmbeddNewLoops(TileCounts,
"tile");
7314 for (std::pair<BasicBlock *, BasicBlock *>
P : InbetweenCode) {
7323 BodyEnter =
nullptr;
7324 BodyEntered = ExitBB;
7336 Builder.restoreIP(Result.back()->getBodyIP());
7337 for (
int i = 0; i < NumLoops; ++i) {
7340 Value *OrigIndVar = OrigIndVars[i];
7391 assert(
Loop->isValid() &&
"Expecting a valid CanonicalLoopInfo");
7395 assert(Latch &&
"A valid CanonicalLoopInfo must have a unique latch");
7403 if (
I.mayReadOrWriteMemory()) {
7407 I.setMetadata(LLVMContext::MD_access_group,
AccessGroup);
7421 Loop->collectControlBlocks(oldControlBBs);
7426 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7427 origTripCounts.
push_back(L->getTripCount());
7436 Builder.SetInsertPoint(TCBlock);
7437 Value *fusedTripCount =
nullptr;
7439 assert(L->isValid() &&
"All loops to fuse must be valid canonical loops");
7440 Value *origTripCount = L->getTripCount();
7441 if (!fusedTripCount) {
7442 fusedTripCount = origTripCount;
7445 Value *condTP =
Builder.CreateICmpSGT(fusedTripCount, origTripCount);
7446 fusedTripCount =
Builder.CreateSelect(condTP, fusedTripCount, origTripCount,
7460 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7461 Loops[i]->getPreheader()->moveBefore(TCBlock);
7462 Loops[i]->getAfter()->moveBefore(TCBlock);
7466 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7478 for (
size_t i = 0; i <
Loops.size(); ++i) {
7480 F->getContext(),
"omp.fused.inner.cond",
F,
Loops[i]->getBody());
7481 Builder.SetInsertPoint(condBlock);
7489 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7490 Builder.SetInsertPoint(condBBs[i]);
7491 Builder.CreateCondBr(condValues[i],
Loops[i]->getBody(), condBBs[i + 1]);
7507 "omp.fused.pre_latch");
7540 const Twine &NamePrefix) {
7569 C, NamePrefix +
".if.then",
Cond->getParent(),
Cond->getNextNode());
7571 C, NamePrefix +
".if.else",
Cond->getParent(), CanonicalLoop->
getExit());
7574 Builder.SetInsertPoint(SplitBeforeIt);
7576 Builder.CreateCondBr(IfCond, ThenBlock, ElseBlock);
7579 spliceBB(IP, ThenBlock,
false, Builder.getCurrentDebugLocation());
7582 Builder.SetInsertPoint(ElseBlock);
7588 ExistingBlocks.
reserve(L->getNumBlocks() + 1);
7590 ExistingBlocks.
append(L->block_begin(), L->block_end());
7596 assert(LoopCond && LoopHeader &&
"Invalid loop structure");
7598 if (
Block == L->getLoopPreheader() ||
Block == L->getLoopLatch() ||
7605 if (
Block == ThenBlock)
7606 NewBB->
setName(NamePrefix +
".if.else");
7609 VMap[
Block] = NewBB;
7617 L->getLoopLatch()->splitBasicBlockBefore(
L->getLoopLatch()->begin(),
7618 NamePrefix +
".pre_latch");
7622 L->addBasicBlockToLoop(ThenBlock, LI);
7628 if (TargetTriple.
isX86()) {
7629 if (Features.
lookup(
"avx512f"))
7631 else if (Features.
lookup(
"avx"))
7635 if (TargetTriple.
isPPC())
7637 if (TargetTriple.
isWasm())
7646 Value *IfCond, OrderKind Order,
7656 if (!BB.hasTerminator())
7672 I->eraseFromParent();
7675 if (AlignedVars.
size()) {
7677 for (
auto &AlignedItem : AlignedVars) {
7678 Value *AlignedPtr = AlignedItem.first;
7682 Builder.CreateAlignmentAssumption(
F->getDataLayout(), AlignedPtr,
7690 createIfVersion(CanonicalLoop, IfCond, VMap, LIA, LI, L,
"simd");
7703 Reachable.insert(
Block);
7713 if ((Safelen ==
nullptr) || (Order == OrderKind::OMP_ORDER_concurrent))
7729 if (Simdlen || Safelen) {
7733 ConstantInt *VectorizeWidth = Simdlen ==
nullptr ? Safelen : Simdlen;
7759static std::unique_ptr<TargetMachine>
7763 StringRef CPU =
F->getFnAttribute(
"target-cpu").getValueAsString();
7764 StringRef Features =
F->getFnAttribute(
"target-features").getValueAsString();
7775 std::nullopt, OptLevel));
7793 if (!BB.hasTerminator())
7806 [&](
const Function &
F) {
return TM->getTargetTransformInfo(
F); });
7807 FAM.registerPass([&]() {
return TIRA; });
7821 I->eraseFromParent();
7824 assert(L &&
"Expecting CanonicalLoopInfo to be recognized as a loop");
7829 nullptr, ORE,
static_cast<int>(OptLevel),
7849 <<
" Threshold=" << UP.
Threshold <<
"\n"
7852 <<
" PartialOptSizeThreshold="
7872 Ptr =
Load->getPointerOperand();
7874 Ptr =
Store->getPointerOperand();
7881 if (Alloca->getParent() == &
F->getEntryBlock())
7901 int MaxTripCount = 0;
7902 bool MaxOrZero =
false;
7903 unsigned TripMultiple = 0;
7907 MaxTripCount, MaxOrZero, TripMultiple, UCE, UP, PP);
7908 LLVM_DEBUG(
dbgs() <<
"Suggesting unroll factor of " << Factor <<
"\n");
7919 assert(Factor >= 0 &&
"Unroll factor must not be negative");
7935 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst}));
7948 *UnrolledCLI =
Loop;
7953 "unrolling only makes sense with a factor of 2 or larger");
7955 Type *IndVarTy =
Loop->getIndVarType();
7962 std::vector<CanonicalLoopInfo *>
LoopNest =
7977 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst})});
7980 (*UnrolledCLI)->assertOK();
7998 Value *Args[] = {Ident, ThreadId, BufSize, CpyBuf, CpyFn, DidItLD};
8017 if (!CPVars.
empty()) {
8022 Directive OMPD = Directive::OMPD_single;
8027 Value *Args[] = {Ident, ThreadId};
8036 if (
Error Err = FiniCB(IP))
8057 EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCBWrapper,
8064 for (
size_t I = 0, E = CPVars.
size();
I < E; ++
I)
8067 ConstantInt::get(Int64, 0), CPVars[
I],
8070 }
else if (!IsNowait) {
8073 omp::Directive::OMPD_unknown,
false,
8091 Directive::OMPD_scope,
nullptr,
nullptr,
8092 BodyGenCB, FiniCB,
false,
true,
8100 omp::Directive::OMPD_unknown,
8116 Directive OMPD = Directive::OMPD_critical;
8121 Value *LockVar = getOMPCriticalRegionLock(CriticalName);
8122 Value *Args[] = {Ident, ThreadId, LockVar};
8139 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
8147 const Twine &Name,
bool IsDependSource) {
8150 [](
Value *SV) {
return SV->getType()->isIntegerTy(64); }) &&
8151 "OpenMP runtime requires depend vec with i64 type");
8164 for (
unsigned I = 0;
I < NumLoops; ++
I) {
8178 Value *Args[] = {Ident, ThreadId, DependBaseAddrGEP};
8196 Directive OMPD = Directive::OMPD_ordered_blockassoc;
8205 Value *Args[] = {Ident, ThreadId};
8215 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
8222 bool HasFinalize,
bool IsCancellable) {
8229 BasicBlock *EntryBB = Builder.GetInsertBlock();
8238 emitCommonDirectiveEntry(OMPD, EntryCall, ExitBB, Conditional);
8250 "Unexpected control flow graph state!!");
8252 emitCommonDirectiveExit(OMPD, FinIP, ExitCall, HasFinalize);
8254 return AfterIP.takeError();
8259 "Unexpected Insertion point location!");
8262 auto InsertBB = merged ? ExitPredBB : ExitBB;
8265 Builder.SetInsertPoint(InsertBB);
8267 return Builder.saveIP();
8271 Directive OMPD,
Value *EntryCall, BasicBlock *ExitBB,
bool Conditional) {
8273 if (!Conditional || !EntryCall)
8279 auto *UI =
new UnreachableInst(
Builder.getContext(), ThenBB);
8289 Builder.CreateCondBr(CallBool, ThenBB, ExitBB);
8293 UI->eraseFromParent();
8301 omp::Directive OMPD,
InsertPointTy FinIP, Instruction *ExitCall,
8309 "Unexpected finalization stack state!");
8312 assert(Fi.DK == OMPD &&
"Unexpected Directive for Finalization call!");
8316 return std::move(Err);
8363 "copyin.not.master.end");
8370 Builder.SetInsertPoint(OMP_Entry);
8373 Value *cmp =
Builder.CreateICmpNE(MasterPtr, PrivatePtr);
8374 Builder.CreateCondBr(cmp, CopyBegin, CopyEnd);
8376 Builder.SetInsertPoint(CopyBegin);
8394 Value *Args[] = {ThreadId,
Size, Allocator};
8417 return Builder.CreateCall(Fn, Args, Name);
8431 Value *Args[] = {ThreadId, Addr, Allocator};
8438 const Twine &Name) {
8446 M.getContext(),
M.getDataLayout().getPrefTypeAlign(Int64)));
8452 const Twine &Name) {
8454 Loc,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)), Name);
8459 const Twine &Name) {
8465 return Builder.CreateCall(Fn, Args, Name);
8470 const Twine &Name) {
8472 Loc, Addr,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)),
8479 Value *DependenceAddress,
bool HaveNowaitClause) {
8489 else if (
Device->getType() != Int32)
8492 if (NumDependences ==
nullptr) {
8493 NumDependences = ConstantInt::get(Int32, 0);
8497 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8499 Ident, ThreadId, InteropVar, InteropTypeVal,
8500 Device, NumDependences, DependenceAddress, HaveNowaitClauseVal};
8509 Value *NumDependences,
Value *DependenceAddress,
bool HaveNowaitClause) {
8519 else if (
Device->getType() != Int32)
8521 if (NumDependences ==
nullptr) {
8522 NumDependences = ConstantInt::get(Int32, 0);
8526 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8528 Ident, ThreadId, InteropVar,
Device,
8529 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8538 Value *NumDependences,
8539 Value *DependenceAddress,
8540 bool HaveNowaitClause) {
8549 else if (
Device->getType() != Int32)
8551 if (NumDependences ==
nullptr) {
8552 NumDependences = ConstantInt::get(Int32, 0);
8556 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8558 Ident, ThreadId, InteropVar,
Device,
8559 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8589 assert(!Attrs.MaxThreads.empty() && !Attrs.MaxTeams.empty() &&
8590 "expected num_threads and num_teams to be specified");
8610 const std::string DebugPrefix =
"_debug__";
8611 if (KernelName.
ends_with(DebugPrefix)) {
8612 KernelName = KernelName.
drop_back(DebugPrefix.length());
8613 Kernel =
M.getFunction(KernelName);
8619 if (Attrs.MinTeams.front() > 1 || Attrs.MaxTeams.front() > 0)
8621 Attrs.MaxTeams.front());
8624 int32_t MaxThreadsVal = Attrs.MaxThreads.front();
8634 Attrs.MinThreads.front());
8639 if (MaxThreadsVal > 0 &&
8642 MaxThreadsVal = int32_t(
8643 std::min<int64_t>(int64_t(MaxThreadsVal) + 64,
8646 if (MaxThreadsVal > 0)
8661 Twine DynamicEnvironmentName = KernelName +
"_dynamic_environment";
8662 Constant *DynamicEnvironmentInitializer =
8666 DynamicEnvironmentInitializer, DynamicEnvironmentName,
8668 DL.getDefaultGlobalsAddressSpace());
8672 DynamicEnvironmentGV->
getType() == DynamicEnvironmentPtr
8673 ? DynamicEnvironmentGV
8675 DynamicEnvironmentPtr);
8678 ConfigurationEnvironment, {
8679 UseGenericStateMachineVal,
8680 MayUseNestedParallelismVal,
8689 KernelEnvironment, {
8690 ConfigurationEnvironmentInitializer,
8694 std::string KernelEnvironmentName =
8695 (KernelName +
"_kernel_environment").str();
8698 KernelEnvironmentInitializer, KernelEnvironmentName,
8700 DL.getDefaultGlobalsAddressSpace());
8703 return KernelEnvironmentGV->
getType() == KernelEnvironmentPtr
8704 ? KernelEnvironmentGV
8706 KernelEnvironmentPtr);
8713 if (!KernelEnvironment)
8721 omp::RuntimeFunction::OMPRTL___kmpc_target_init);
8723 Value *KernelLaunchEnvironment =
8726 KernelLaunchEnvironment =
8727 KernelLaunchEnvironment->
getType() == KernelLaunchEnvParamTy
8728 ? KernelLaunchEnvironment
8729 :
Builder.CreateAddrSpaceCast(KernelLaunchEnvironment,
8730 KernelLaunchEnvParamTy);
8732 Fn, {KernelEnvironment, KernelLaunchEnvironment});
8744 auto *UI =
Builder.CreateUnreachable();
8750 Builder.SetInsertPoint(WorkerExitBB);
8754 Builder.SetInsertPoint(CheckBBTI);
8755 Builder.CreateCondBr(ExecUserCode, UI->getParent(), WorkerExitBB);
8757 CheckBBTI->eraseFromParent();
8758 UI->eraseFromParent();
8766 int32_t TeamsReductionDataSize) {
8771 omp::RuntimeFunction::OMPRTL___kmpc_target_deinit);
8775 if (!TeamsReductionDataSize)
8781 const std::string DebugPrefix =
"_debug__";
8783 KernelName = KernelName.
drop_back(DebugPrefix.length());
8784 auto *KernelEnvironmentGV =
8785 M.getNamedGlobal((KernelName +
"_kernel_environment").str());
8786 assert(KernelEnvironmentGV &&
"Expected kernel environment global\n");
8787 auto *KernelEnvironmentInitializer = KernelEnvironmentGV->getInitializer();
8789 KernelEnvironmentInitializer,
8790 ConstantInt::get(Int32, TeamsReductionDataSize), {0, 7});
8791 KernelEnvironmentGV->setInitializer(NewInitializer);
8796 if (
Kernel.hasFnAttribute(Name)) {
8797 int32_t OldLimit =
Kernel.getFnAttributeAsParsedInteger(Name);
8803std::pair<int32_t, int32_t>
8805 int32_t ThreadLimit =
8806 Kernel.getFnAttributeAsParsedInteger(
"omp_target_thread_limit");
8809 const auto &Attr =
Kernel.getFnAttribute(
"amdgpu-flat-work-group-size");
8810 if (!Attr.isValid() || !Attr.isStringAttribute())
8811 return {0, ThreadLimit};
8812 auto [LBStr, UBStr] = Attr.getValueAsString().split(
',');
8815 return {0, ThreadLimit};
8816 UB = ThreadLimit ? std::min(ThreadLimit, UB) : UB;
8824 return {0, ThreadLimit ? std::min(ThreadLimit, UB) : UB};
8826 return {0, ThreadLimit};
8832 Kernel.addFnAttr(
"omp_target_thread_limit", std::to_string(UB));
8835 Kernel.addFnAttr(
"amdgpu-flat-work-group-size",
8843std::pair<int32_t, int32_t>
8846 return {0,
Kernel.getFnAttributeAsParsedInteger(
"omp_target_num_teams")};
8850 int32_t LB, int32_t UB) {
8858 Kernel.addFnAttr(
"omp_target_num_teams", std::to_string(LB));
8861void OpenMPIRBuilder::setOutlinedTargetRegionFunctionAttributes(
8870 else if (
T.isNVPTX())
8872 else if (
T.isSPIRV())
8878 StringRef EntryFnIDName) {
8879 if (
Config.isTargetDevice()) {
8880 assert(OutlinedFn &&
"The outlined function must exist if embedded");
8884 return new GlobalVariable(
8889Constant *OpenMPIRBuilder::createTargetRegionEntryAddr(
Function *OutlinedFn,
8890 StringRef EntryFnName) {
8894 assert(!
M.getGlobalVariable(EntryFnName,
true) &&
8895 "Named kernel already exists?");
8896 return new GlobalVariable(
8909 if (
Config.isTargetDevice() || !
Config.openMPOffloadMandatory()) {
8913 OutlinedFn = *CBResult;
8915 OutlinedFn =
nullptr;
8921 if (!IsOffloadEntry)
8924 std::string EntryFnIDName =
8926 ? std::string(EntryFnName)
8930 EntryFnName, EntryFnIDName);
8938 setOutlinedTargetRegionFunctionAttributes(OutlinedFn);
8939 auto OutlinedFnID = createOutlinedFunctionID(OutlinedFn, EntryFnIDName);
8940 auto EntryAddr = createTargetRegionEntryAddr(OutlinedFn, EntryFnName);
8942 EntryInfo, EntryAddr, OutlinedFnID,
8944 return OutlinedFnID;
8962 bool IsStandAlone = !BodyGenCB;
8969 MapInfo = &GenMapInfoCB(
Builder.saveIP());
8971 AllocaIP,
Builder.saveIP(), *MapInfo, Info, CustomMapperCB,
8972 true, DeviceAddrCB))
8979 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
8989 SrcLocInfo, DeviceID,
8996 assert(MapperFunc &&
"MapperFunc missing for standalone target data");
9000 if (Info.HasNoWait) {
9010 if (Info.HasNoWait) {
9014 emitBlock(OffloadContBlock, CurFn,
true);
9020 bool RequiresOuterTargetTask = Info.HasNoWait;
9021 if (!RequiresOuterTargetTask)
9022 cantFail(TaskBodyCB(
nullptr,
nullptr,
9026 {}, RTArgs, Info.HasNoWait));
9029 omp::OMPRTL___tgt_target_data_begin_mapper);
9033 for (
auto DeviceMap : Info.DevicePtrInfoMap) {
9037 Builder.CreateStore(LI, DeviceMap.second.second);
9074 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
9083 Value *OffloadingArgs[] = {SrcLocInfo, DeviceID,
9106 return emitIfClause(IfCond, BeginThenGen, BeginElseGen, AllocaIP);
9107 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9122 return emitIfClause(IfCond, EndThenGen, EndElseGen, AllocaIP);
9123 return EndThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9126 return emitIfClause(IfCond, BeginThenGen, EndElseGen, AllocaIP);
9127 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9138 bool IsGPUDistribute) {
9139 assert((IVSize == 32 || IVSize == 64) &&
9140 "IV size is not compatible with the omp runtime");
9142 if (IsGPUDistribute)
9144 ? (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_4
9145 : omp::OMPRTL___kmpc_distribute_static_init_4u)
9146 : (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_8
9147 : omp::OMPRTL___kmpc_distribute_static_init_8u);
9149 Name = IVSize == 32 ? (IVSigned ? omp::OMPRTL___kmpc_for_static_init_4
9150 : omp::OMPRTL___kmpc_for_static_init_4u)
9151 : (IVSigned ? omp::OMPRTL___kmpc_for_static_init_8
9152 : omp::OMPRTL___kmpc_for_static_init_8u);
9159 assert((IVSize == 32 || IVSize == 64) &&
9160 "IV size is not compatible with the omp runtime");
9162 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_4
9163 : omp::OMPRTL___kmpc_dispatch_init_4u)
9164 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_8
9165 : omp::OMPRTL___kmpc_dispatch_init_8u);
9172 assert((IVSize == 32 || IVSize == 64) &&
9173 "IV size is not compatible with the omp runtime");
9175 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_4
9176 : omp::OMPRTL___kmpc_dispatch_next_4u)
9177 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_8
9178 : omp::OMPRTL___kmpc_dispatch_next_8u);
9185 assert((IVSize == 32 || IVSize == 64) &&
9186 "IV size is not compatible with the omp runtime");
9188 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_4
9189 : omp::OMPRTL___kmpc_dispatch_fini_4u)
9190 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_8
9191 : omp::OMPRTL___kmpc_dispatch_fini_8u);
9202 DenseMap<
Value *, std::tuple<Value *, unsigned>> &ValueReplacementMap) {
9210 auto GetUpdatedDIVariable = [&](
DILocalVariable *OldVar,
unsigned arg) {
9214 if (NewVar && (arg == NewVar->
getArg()))
9224 auto UpdateDebugRecord = [&](
auto *DR) {
9227 for (
auto Loc : DR->location_ops()) {
9228 auto Iter = ValueReplacementMap.find(
Loc);
9229 if (Iter != ValueReplacementMap.end()) {
9230 DR->replaceVariableLocationOp(
Loc, std::get<0>(Iter->second));
9231 ArgNo = std::get<1>(Iter->second) + 1;
9235 DR->setVariable(GetUpdatedDIVariable(OldVar, ArgNo));
9240 if (DVR->getNumVariableLocationOps() != 1u) {
9241 DVR->setKillLocation();
9244 Value *
Loc = DVR->getVariableLocationOp(0u);
9251 RequiredBB = &DVR->getFunction()->getEntryBlock();
9253 if (RequiredBB && RequiredBB != CurBB) {
9265 UpdateDebugRecord(&DVR);
9266 MoveDebugRecordToCorrectBlock(&DVR);
9269 for (
auto *DVR : DVRsToDelete)
9270 DVR->getMarker()->MarkedInstr->dropOneDbgRecord(DVR);
9274 Module *M = Func->getParent();
9277 DB.createQualifiedType(dwarf::DW_TAG_pointer_type,
nullptr);
9278 unsigned ArgNo = Func->arg_size();
9280 NewSP,
"dyn_ptr", ArgNo, NewSP->
getFile(), 0, VoidPtrTy,
9281 false, DINode::DIFlags::FlagArtificial);
9283 Argument *LastArg = Func->getArg(Func->arg_size() - 1);
9284 DB.insertDeclare(LastArg, Var, DB.createExpression(),
Loc,
9306 for (
auto &Arg : Inputs)
9307 ParameterTypes.
push_back(Arg->getType()->isPointerTy()
9311 for (
auto &Arg : Inputs)
9312 ParameterTypes.
push_back(Arg->getType());
9320 auto BB = Builder.GetInsertBlock();
9321 auto M = BB->getModule();
9332 if (TargetCpuAttr.isStringAttribute())
9333 Func->addFnAttr(TargetCpuAttr);
9335 auto TargetFeaturesAttr = ParentFn->
getFnAttribute(
"target-features");
9336 if (TargetFeaturesAttr.isStringAttribute())
9337 Func->addFnAttr(TargetFeaturesAttr);
9342 OMPBuilder.
emitUsed(
"llvm.compiler.used", {ExecMode});
9352 Builder.SetCurrentDebugLocation(OutlinedFnLoc);
9356 Builder.SetInsertPoint(EntryBB);
9367 BasicBlock *UserCodeEntryBB = Builder.GetInsertBlock();
9377 splitBB(Builder,
true,
"outlined.body");
9379 CBFunc(Builder.saveIP(), OutlinedBodyBB->
begin(), ExitBB);
9382 Builder.SetInsertPoint(ExitBB);
9390 Builder.SetCurrentDebugLocation(OutlinedFnLoc);
9397 Builder.CreateRetVoid();
9401 auto AllocaIP = Builder.saveIP();
9406 const auto &ArgRange =
make_range(Func->arg_begin(), Func->arg_end() - 1);
9438 if (Instr->getFunction() == Func)
9439 Instr->replaceUsesOfWith(
Input, InputCopy);
9445 for (
auto InArg :
zip(Inputs, ArgRange)) {
9447 Argument &Arg = std::get<1>(InArg);
9448 Value *InputCopy =
nullptr;
9451 Arg,
Input, InputCopy, AllocaIP, Builder.saveIP(), ExitBB->
begin());
9454 Builder.restoreIP(*AfterIP);
9455 ValueReplacementMap[
Input] = std::make_tuple(InputCopy, Arg.
getArgNo());
9475 DeferredReplacement.push_back(std::make_pair(
Input, InputCopy));
9482 ReplaceValue(
Input, InputCopy, Func);
9486 for (
auto Deferred : DeferredReplacement)
9487 ReplaceValue(std::get<0>(Deferred), std::get<1>(Deferred), Func);
9490 ValueReplacementMap);
9498 Value *TaskWithPrivates,
9499 Type *TaskWithPrivatesTy) {
9501 Type *TaskTy = OMPIRBuilder.Task;
9504 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 0);
9505 Value *Shareds = TaskT;
9515 if (TaskWithPrivatesTy != TaskTy)
9516 Shareds = Builder.CreateStructGEP(TaskTy, TaskT, 0);
9533 const size_t NumOffloadingArrays,
const int SharedArgsOperandNo) {
9538 assert((!NumOffloadingArrays || PrivatesTy) &&
9539 "PrivatesTy cannot be nullptr when there are offloadingArrays"
9569 Type *TaskPtrTy = OMPBuilder.TaskPtr;
9570 [[maybe_unused]]
Type *TaskTy = OMPBuilder.Task;
9576 ".omp_target_task_proxy_func", M);
9577 Value *ThreadId = ProxyFn->getArg(0);
9578 Value *TaskWithPrivates = ProxyFn->getArg(1);
9579 ThreadId->
setName(
"thread.id");
9580 TaskWithPrivates->
setName(
"task");
9582 bool HasShareds = SharedArgsOperandNo > 0;
9583 bool HasOffloadingArrays = NumOffloadingArrays > 0;
9587 Builder.SetInsertPoint(EntryBB);
9594 if (HasOffloadingArrays) {
9595 assert(TaskTy != TaskWithPrivatesTy &&
9596 "If there are offloading arrays to pass to the target"
9597 "TaskTy cannot be the same as TaskWithPrivatesTy");
9600 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 1);
9601 for (
unsigned int i = 0; i < NumOffloadingArrays; ++i)
9603 Builder.CreateStructGEP(PrivatesTy, Privates, i));
9607 auto *ArgStructAlloca =
9609 assert(ArgStructAlloca &&
9610 "Unable to find the alloca instruction corresponding to arguments "
9611 "for extracted function");
9613 std::optional<TypeSize> ArgAllocSize =
9615 assert(ArgStructType && ArgAllocSize &&
9616 "Unable to determine size of arguments for extracted function");
9617 uint64_t StructSize = ArgAllocSize->getFixedValue();
9620 Builder.CreateAlloca(ArgStructType,
nullptr,
"structArg");
9622 Value *SharedsSize = Builder.getInt64(StructSize);
9625 OMPBuilder, Builder, TaskWithPrivates, TaskWithPrivatesTy);
9627 Builder.CreateMemCpy(
9628 NewArgStructAlloca, NewArgStructAlloca->
getAlign(), LoadShared,
9630 KernelLaunchArgs.
push_back(NewArgStructAlloca);
9633 Builder.CreateRetVoid();
9639 return GEP->getSourceElementType();
9641 return Alloca->getAllocatedType();
9664 if (OffloadingArraysToPrivatize.
empty())
9665 return OMPIRBuilder.Task;
9668 for (
Value *V : OffloadingArraysToPrivatize) {
9669 assert(V->getType()->isPointerTy() &&
9670 "Expected pointer to array to privatize. Got a non-pointer value "
9673 assert(ArrayTy &&
"ArrayType cannot be nullptr");
9679 "struct.task_with_privates");
9694 EntryFnName, Inputs, CBFunc,
9695 ArgAccessorFuncCB, OutlinedFnLoc);
9699 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
9838 auto OI = std::make_unique<OutlineInfo>();
9839 OI->EntryBB = TargetTaskAllocaBB;
9840 OI->OuterAllocBB = AllocaIP.getNodeParent();
9845 Builder, AllocaIP, ToBeDeleted, TargetTaskAllocaIP,
"global.tid",
false));
9848 Builder.restoreIP(TargetTaskBodyIP);
9849 if (
Error Err = TaskBodyCB(DeviceID, RTLoc, TargetTaskAllocaIP))
9867 bool NeedsTargetTask = HasNoWait && DeviceID;
9868 if (NeedsTargetTask) {
9874 OffloadingArraysToPrivatize.
push_back(V);
9875 OI->ExcludeArgsFromAggregate.push_back(V);
9879 OI->PostOutlineCB = [
this, ToBeDeleted, Dependencies, NeedsTargetTask,
9880 DeviceID, OffloadingArraysToPrivatize](
9883 "there must be a single user for the outlined function");
9897 const unsigned int NumStaleCIArgs = StaleCI->
arg_size();
9898 bool HasShareds = NumStaleCIArgs > OffloadingArraysToPrivatize.
size() + 1;
9900 NumStaleCIArgs == (OffloadingArraysToPrivatize.
size() + 2)) &&
9901 "Wrong number of arguments for StaleCI when shareds are present");
9902 int SharedArgOperandNo =
9903 HasShareds ? OffloadingArraysToPrivatize.
size() + 1 : 0;
9909 if (!OffloadingArraysToPrivatize.
empty())
9914 *
this,
Builder, StaleCI, PrivatesTy, TaskWithPrivatesTy,
9915 OffloadingArraysToPrivatize.
size(), SharedArgOperandNo);
9917 LLVM_DEBUG(
dbgs() <<
"Proxy task entry function created: " << *ProxyFn
9920 Builder.SetInsertPoint(StaleCI);
9937 OMPRTL___kmpc_omp_target_task_alloc);
9949 M.getDataLayout().getTypeStoreSize(TaskWithPrivatesTy));
9956 auto *ArgStructAlloca =
9958 assert(ArgStructAlloca &&
9959 "Unable to find the alloca instruction corresponding to arguments "
9960 "for extracted function");
9961 std::optional<TypeSize> ArgAllocSize =
9964 "Unable to determine size of arguments for extracted function");
9965 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
9984 TaskSize, SharedsSize,
9987 if (NeedsTargetTask) {
9988 assert(DeviceID &&
"Expected non-empty device ID.");
9998 *
this,
Builder, TaskData, TaskWithPrivatesTy);
10002 if (!OffloadingArraysToPrivatize.
empty()) {
10004 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskData, 1);
10005 for (
unsigned int i = 0; i < OffloadingArraysToPrivatize.
size(); ++i) {
10006 Value *PtrToPrivatize = OffloadingArraysToPrivatize[i];
10013 "ElementType should match ArrayType");
10016 Value *Dst =
Builder.CreateStructGEP(PrivatesTy, Privates, i);
10019 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(ElementType)));
10023 Value *DepArray =
nullptr;
10024 Value *NumDeps =
nullptr;
10027 NumDeps = Dependencies.
NumDeps;
10028 }
else if (!Dependencies.
Deps.empty()) {
10030 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
10041 if (!NeedsTargetTask) {
10050 ConstantInt::get(
Builder.getInt32Ty(), 0),
10063 }
else if (DepArray) {
10071 {Ident, ThreadID, TaskData, NumDeps, DepArray,
10072 ConstantInt::get(
Builder.getInt32Ty(), 0),
10080 Builder.ClearInsertionPoint();
10083 I->eraseFromParent();
10088 << *(
Builder.GetInsertBlock()) <<
"\n");
10090 << *(
Builder.getModule()) <<
"\n");
10101 CustomMapperCB, IsNonContiguous, DeviceAddrCB))
10124 Builder.restoreIP(IP);
10130 return Builder.saveIP();
10133 bool HasDependencies = !Dependencies.
empty();
10134 bool RequiresOuterTargetTask = HasNoWait || HasDependencies;
10151 if (OutlinedFnID && DeviceID)
10153 EmitTargetCallFallbackCB, KArgs,
10154 DeviceID, RTLoc, TargetTaskAllocaIP);
10162 return EmitTargetCallFallbackCB(OMPBuilder.
Builder.
saveIP());
10169 auto &&EmitTargetCallElse =
10176 if (RequiresOuterTargetTask) {
10183 Dependencies, EmptyRTArgs, HasNoWait);
10185 return EmitTargetCallFallbackCB(Builder.saveIP());
10188 Builder.restoreIP(AfterIP);
10192 auto &&EmitTargetCallThen =
10196 Info.HasNoWait = HasNoWait;
10201 AllocaIP, Builder.saveIP(), Info, RTArgs, MapInfo, CustomMapperCB,
10207 for (
auto [DefaultVal, RuntimeVal] :
10209 NumTeamsC.
push_back(RuntimeVal ? RuntimeVal
10210 : Builder.getInt32(DefaultVal));
10214 auto InitMaxThreadsClause = [&Builder](
Value *
Clause) {
10216 Clause = Builder.CreateIntCast(
Clause, Builder.getInt32Ty(),
10220 auto CombineMaxThreadsClauses = [&Builder](
Value *
Clause,
Value *&Result) {
10223 Result ? Builder.CreateSelect(Builder.CreateICmpULT(Result,
Clause),
10231 Value *MaxThreadsClause =
10233 ? InitMaxThreadsClause(RuntimeAttrs.
MaxThreads.front())
10236 for (
auto [TeamsVal, TargetVal] :
zip_equal(
10238 Value *TeamsThreadLimitClause = InitMaxThreadsClause(TeamsVal);
10239 Value *NumThreads = InitMaxThreadsClause(TargetVal);
10241 CombineMaxThreadsClauses(TeamsThreadLimitClause, NumThreads);
10242 CombineMaxThreadsClauses(MaxThreadsClause, NumThreads);
10244 NumThreadsC.
push_back(NumThreads ? NumThreads : Builder.getInt32(0));
10247 unsigned NumTargetItems = Info.NumberOfPtrs;
10248 Value *RTLoc = RTLocOverride;
10259 Builder.getInt64Ty(),
10261 : Builder.getInt64(0);
10265 DynCGroupMem = Builder.getInt32(0);
10268 NumTargetItems, RTArgs, TripCount, NumTeamsC, NumThreadsC, DynCGroupMem,
10269 HasNoWait,
false,
false,
10270 DynCGroupMemFallback);
10277 if (RequiresOuterTargetTask)
10279 RTLoc, AllocaIP, Dependencies,
10280 KArgs.
RTArgs, Info.HasNoWait);
10283 Builder, OutlinedFnID, EmitTargetCallFallbackCB, KArgs,
10284 RuntimeAttrs.
DeviceID, RTLoc, AllocaIP);
10287 Builder.restoreIP(AfterIP);
10294 if (!OutlinedFnID) {
10295 cantFail(EmitTargetCallElse(AllocaIP, Builder.saveIP(), DeallocBlocks));
10301 cantFail(EmitTargetCallThen(AllocaIP, Builder.saveIP(), DeallocBlocks));
10306 EmitTargetCallElse, AllocaIP));
10319 bool HasNowait,
Value *DynCGroupMem,
10321 Value *RTLocOverride) {
10326 Builder.restoreIP(CodeGenIP);
10334 *
this,
Builder, IsOffloadEntry, EntryInfo, DefaultAttrs, OutlinedFn,
10335 OutlinedFnID, Inputs, CBFunc, ArgAccessorFuncCB, OutlinedFnLoc))
10341 if (!
Config.isTargetDevice())
10343 DefaultAttrs, RuntimeAttrs, IfCond, OutlinedFn, OutlinedFnID,
10344 Inputs, GenMapInfoCB, CustomMapperCB, Dependencies,
10345 HasNowait, DynCGroupMem, DynCGroupMemFallback);
10359 return OS.
str().str();
10364 return OpenMPIRBuilder::getNameWithSeparators(Parts,
Config.firstSeparator(),
10370 auto &Elem = *
InternalVars.try_emplace(Name,
nullptr).first;
10372 assert(Elem.second->getValueType() == Ty &&
10373 "OMP internal variable has different type than requested");
10386 :
M.getTargetTriple().isAMDGPU()
10388 :
DL.getDefaultGlobalsAddressSpace();
10389 auto Linkage = this->
M.getTargetTriple().isWasm()
10397 const llvm::Align PtrAlign =
DL.getPointerABIAlignment(AddressSpaceVal);
10398 GV->setAlignment(std::max(TypeAlign, PtrAlign));
10402 return Elem.second;
10405Value *OpenMPIRBuilder::getOMPCriticalRegionLock(
StringRef CriticalName) {
10406 std::string Prefix =
Twine(
"gomp_critical_user_", CriticalName).
str();
10407 std::string Name = getNameWithSeparators({Prefix,
"var"},
".",
".");
10418 return SizePtrToInt;
10423 std::string VarName) {
10431 return MaptypesArrayGlobal;
10436 unsigned NumOperands,
10445 ArrI8PtrTy,
nullptr,
".offload_baseptrs");
10449 ArrI64Ty,
nullptr,
".offload_sizes");
10460 int64_t DeviceID,
unsigned NumOperands) {
10466 Value *ArgsBaseGEP =
10468 {Builder.getInt32(0), Builder.getInt32(0)});
10471 {Builder.getInt32(0), Builder.getInt32(0)});
10472 Value *ArgSizesGEP =
10474 {Builder.getInt32(0), Builder.getInt32(0)});
10478 Builder.getInt32(NumOperands),
10479 ArgsBaseGEP, ArgsGEP, ArgSizesGEP,
10480 MaptypesArg, MapnamesArg, NullPtr});
10487 assert((!ForEndCall || Info.separateBeginEndCalls()) &&
10488 "expected region end call to runtime only when end call is separate");
10490 auto VoidPtrTy = UnqualPtrTy;
10491 auto VoidPtrPtrTy = UnqualPtrTy;
10493 auto Int64PtrTy = UnqualPtrTy;
10495 if (!Info.NumberOfPtrs) {
10507 Info.RTArgs.BasePointersArray,
10510 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray,
10514 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
10518 ForEndCall && Info.RTArgs.MapTypesArrayEnd ? Info.RTArgs.MapTypesArrayEnd
10519 : Info.RTArgs.MapTypesArray,
10525 if (!Info.EmitDebug)
10529 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.MapNamesArray,
10534 if (!Info.HasMapper)
10538 Builder.CreatePointerCast(Info.RTArgs.MappersArray, VoidPtrPtrTy);
10559 "struct.descriptor_dim");
10561 enum { OffsetFD = 0, CountFD, StrideFD };
10565 for (
unsigned I = 0, L = 0, E = NonContigInfo.
Dims.
size();
I < E; ++
I) {
10568 if (NonContigInfo.
Dims[
I] == 1)
10573 Builder.CreateAlloca(ArrayTy,
nullptr,
"dims");
10574 Builder.restoreIP(CodeGenIP);
10575 for (
unsigned II = 0, EE = NonContigInfo.
Dims[
I];
II < EE; ++
II) {
10576 unsigned RevIdx = EE -
II - 1;
10580 Value *OffsetLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, OffsetFD);
10582 NonContigInfo.
Offsets[L][RevIdx], OffsetLVal,
10583 M.getDataLayout().getPrefTypeAlign(OffsetLVal->
getType()));
10585 Value *CountLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, CountFD);
10587 NonContigInfo.
Counts[L][RevIdx], CountLVal,
10588 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10590 Value *StrideLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, StrideFD);
10592 NonContigInfo.
Strides[L][RevIdx], StrideLVal,
10593 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10596 Builder.restoreIP(CodeGenIP);
10597 Value *DAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
10598 DimsAddr,
Builder.getPtrTy());
10601 Info.RTArgs.PointersArray, 0,
I);
10603 DAddr,
P,
M.getDataLayout().getPrefTypeAlign(
Builder.getPtrTy()));
10608void OpenMPIRBuilder::emitUDMapperArrayInitOrDel(
10612 StringRef Prefix = IsInit ?
".init" :
".del";
10618 Builder.CreateICmpSGT(
Size, Builder.getInt64(1),
"omp.arrayinit.isarray");
10619 Value *DeleteBit = Builder.CreateAnd(
10622 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10623 OpenMPOffloadMappingFlags::OMP_MAP_DELETE)));
10628 Value *BaseIsBegin = Builder.CreateICmpNE(
Base, Begin);
10629 Cond = Builder.CreateOr(IsArray, BaseIsBegin);
10630 DeleteCond = Builder.CreateIsNull(
10635 DeleteCond =
Builder.CreateIsNotNull(
10651 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10652 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10653 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10654 MapTypeArg =
Builder.CreateOr(
10657 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10658 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT)));
10662 Value *OffloadingArgs[] = {MapperHandle,
Base, Begin,
10663 ArraySize, MapTypeArg, MapName};
10674 bool PreserveMemberOfFlags,
bool PropagatePresentToPointee) {
10690 MapperFn->
addFnAttr(Attribute::NoInline);
10691 MapperFn->
addFnAttr(Attribute::NoUnwind);
10702 Builder.SetInsertPoint(EntryBB);
10717 Value *PtrBegin = BeginIn;
10723 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
10724 MapType, MapName, ElementSize, HeadBB,
10735 Builder.CreateICmpEQ(PtrBegin, PtrEnd,
"omp.arraymap.isempty");
10736 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
10742 Builder.CreatePHI(PtrBegin->
getType(), 2,
"omp.arraymap.ptrcurrent");
10743 PtrPHI->addIncoming(PtrBegin, HeadBB);
10748 return Info.takeError();
10752 Value *OffloadingArgs[] = {MapperHandle};
10756 Value *ShiftedPreviousSize =
10760 for (
unsigned I = 0;
I < Info->BasePointers.size(); ++
I) {
10761 Value *CurBaseArg = Info->BasePointers[
I];
10762 Value *CurBeginArg = Info->Pointers[
I];
10763 Value *CurSizeArg = Info->Sizes[
I];
10764 Value *CurNameArg = Info->Names.size()
10769 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10772 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10774 constexpr uint64_t MemberOfMask =
10775 static_cast<uint64_t
>(OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
10776 constexpr uint64_t AttachBit =
10777 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10778 OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
10836 Value *MemberMapType;
10837 if (PreserveMemberOfFlags || (RawType & AttachBit) ||
10838 Info->HasAttachPtr[
I]) {
10839 if (RawType & MemberOfMask)
10840 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
10842 MemberMapType = OriMapType;
10844 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
10862 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10863 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10864 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10874 Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
10880 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10881 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10882 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10888 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10889 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
10890 Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
10896 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10897 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10903 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10904 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10905 Builder.CreateCondBr(IsFrom, FromBB, EndBB);
10911 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10912 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
10921 CurMapType->
addIncoming(MemberMapType, ToElseBB);
10958 uint64_t ModifierBits =
10959 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10960 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
10961 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
10962 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
10963 if (PropagatePresentToPointee && Info->HasAttachPtr[
I])
10965 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10966 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
10967 Value *ImportedModifierBits =
10970 CurMapType, ImportedModifierBits,
"omp.maptype.with.modifiers");
10975 Value *FinalMapType =
10976 (RawType & AttachBit) ? CurMapType : CurMapTypeWithModifiers;
10978 Value *OffloadingArgs[] = {MapperHandle, CurBaseArg, CurBeginArg,
10979 CurSizeArg, FinalMapType, CurNameArg};
10981 auto ChildMapperFn = CustomMapperCB(
I);
10982 if (!ChildMapperFn)
10983 return ChildMapperFn.takeError();
10984 if (*ChildMapperFn) {
11000 "omp.arraymap.next");
11001 PtrPHI->addIncoming(PtrNext, LastBB);
11002 Value *IsDone =
Builder.CreateICmpEQ(PtrNext, PtrEnd,
"omp.arraymap.isdone");
11004 Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
11009 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
11010 MapType, MapName, ElementSize, DoneBB,
11023 bool IsNonContiguous,
11027 Info.clearArrayInfo();
11030 if (Info.NumberOfPtrs == 0)
11039 Info.RTArgs.BasePointersArray =
Builder.CreateAlloca(
11040 PointerArrayType,
nullptr,
".offload_baseptrs");
11042 Info.RTArgs.PointersArray =
Builder.CreateAlloca(
11043 PointerArrayType,
nullptr,
".offload_ptrs");
11045 PointerArrayType,
nullptr,
".offload_mappers");
11046 Info.RTArgs.MappersArray = MappersArray;
11053 ConstantInt::get(Int64Ty, 0));
11055 for (
unsigned I = 0, E = CombinedInfo.
Sizes.
size();
I < E; ++
I) {
11056 bool IsNonContigEntry =
11058 (
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11060 OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG) != 0);
11063 if (IsNonContigEntry) {
11065 "Index must be in-bounds for NON_CONTIG Dims array");
11067 assert(DimCount > 0 &&
"NON_CONTIG DimCount must be > 0");
11068 ConstSizes[
I] = ConstantInt::get(Int64Ty, DimCount);
11073 ConstSizes[
I] = CI;
11077 RuntimeSizes.
set(
I);
11080 if (RuntimeSizes.
all()) {
11082 Info.RTArgs.SizesArray =
Builder.CreateAlloca(
11083 SizeArrayType,
nullptr,
".offload_sizes");
11089 auto *SizesArrayGbl =
11094 if (!RuntimeSizes.
any()) {
11095 Info.RTArgs.SizesArray = SizesArrayGbl;
11097 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
11098 Align OffloadSizeAlign =
M.getDataLayout().getABIIntegerTypeAlignment(64);
11101 SizeArrayType,
nullptr,
".offload_sizes");
11105 Buffer,
M.getDataLayout().getPrefTypeAlign(Buffer->
getType()),
11106 SizesArrayGbl, OffloadSizeAlign,
11111 Info.RTArgs.SizesArray = Buffer;
11119 for (
auto mapFlag : CombinedInfo.
Types)
11121 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11125 Info.RTArgs.MapTypesArray = MapTypesArrayGbl;
11131 Info.RTArgs.MapNamesArray = MapNamesArrayGbl;
11132 Info.EmitDebug =
true;
11134 Info.RTArgs.MapNamesArray =
11136 Info.EmitDebug =
false;
11141 if (Info.separateBeginEndCalls()) {
11142 bool EndMapTypesDiffer =
false;
11143 for (uint64_t &
Type : Mapping) {
11144 if (
Type &
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11145 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT)) {
11146 Type &= ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
11147 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
11148 EndMapTypesDiffer =
true;
11151 if (EndMapTypesDiffer) {
11153 Info.RTArgs.MapTypesArrayEnd = MapTypesArrayGbl;
11158 for (
unsigned I = 0;
I < Info.NumberOfPtrs; ++
I) {
11161 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.BasePointersArray,
11163 Builder.CreateAlignedStore(BPVal, BP,
11164 M.getDataLayout().getPrefTypeAlign(PtrTy));
11166 if (Info.requiresDevicePointerInfo()) {
11168 CodeGenIP =
Builder.saveIP();
11170 Info.DevicePtrInfoMap[BPVal] = {BP,
Builder.CreateAlloca(PtrTy)};
11173 DeviceAddrCB(
I, Info.DevicePtrInfoMap[BPVal].second);
11175 Info.DevicePtrInfoMap[BPVal] = {BP, BP};
11177 DeviceAddrCB(
I, BP);
11183 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray, 0,
11186 Builder.CreateAlignedStore(PVal,
P,
11187 M.getDataLayout().getPrefTypeAlign(PtrTy));
11189 if (RuntimeSizes.
test(
I)) {
11191 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
11197 S,
M.getDataLayout().getPrefTypeAlign(PtrTy));
11200 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
11203 auto CustomMFunc = CustomMapperCB(
I);
11205 return CustomMFunc.takeError();
11207 MFunc =
Builder.CreatePointerCast(*CustomMFunc, PtrTy);
11210 PointerArrayType, MappersArray,
11213 MFunc, MAddr,
M.getDataLayout().getPrefTypeAlign(MAddr->
getType()));
11217 Info.NumberOfPtrs == 0)
11234 Builder.ClearInsertionPoint();
11265 auto CondConstant = CI->getSExtValue();
11267 return ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
11269 return ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
11279 Builder.CreateCondBr(
Cond, ThenBlock, ElseBlock);
11282 if (
Error Err = ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks))
11288 if (
Error Err = ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks))
11297bool OpenMPIRBuilder::checkAndEmitFlushAfterAtomic(
11301 "Unexpected Atomic Ordering.");
11303 bool Flush =
false;
11365 assert(
X.Var->getType()->isPointerTy() &&
11366 "OMP Atomic expects a pointer to target memory");
11367 Type *XElemTy =
X.ElemTy;
11370 "OMP atomic read expected a scalar type");
11372 Value *XRead =
nullptr;
11376 Builder.CreateLoad(XElemTy,
X.Var,
X.IsVolatile,
"omp.atomic.read");
11385 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11388 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11390 XRead = AtomicLoadRes.first;
11397 Builder.CreateLoad(IntCastTy,
X.Var,
X.IsVolatile,
"omp.atomic.load");
11400 XRead =
Builder.CreateBitCast(XLoad, XElemTy,
"atomic.flt.cast");
11402 XRead =
Builder.CreateIntToPtr(XLoad, XElemTy,
"atomic.ptr.cast");
11405 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Read);
11406 Builder.CreateStore(XRead, V.Var, V.IsVolatile);
11417 assert(
X.Var->getType()->isPointerTy() &&
11418 "OMP Atomic expects a pointer to target memory");
11419 Type *XElemTy =
X.ElemTy;
11422 "OMP atomic write expected a scalar type");
11430 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11433 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11441 Builder.CreateBitCast(Expr, IntCastTy,
"atomic.src.int.cast");
11446 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Write);
11453 AtomicUpdateCallbackTy &UpdateOp,
bool IsXBinopExpr,
11454 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11460 Type *XTy =
X.Var->getType();
11462 "OMP Atomic expects a pointer to target memory");
11463 Type *XElemTy =
X.ElemTy;
11466 "OMP atomic update expected a scalar or struct type");
11469 "OpenMP atomic does not support LT or GT operations");
11473 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, RMWOp, UpdateOp,
X.IsVolatile,
11474 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11476 return AtomicResult.takeError();
11477 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Update);
11482Value *OpenMPIRBuilder::emitRMWOpAsInstruction(
Value *Src1,
Value *Src2,
11486 return Builder.CreateAdd(Src1, Src2);
11488 return Builder.CreateSub(Src1, Src2);
11490 return Builder.CreateAnd(Src1, Src2);
11492 return Builder.CreateNeg(Builder.CreateAnd(Src1, Src2));
11494 return Builder.CreateOr(Src1, Src2);
11496 return Builder.CreateXor(Src1, Src2);
11535Expected<std::pair<Value *, Value *>> OpenMPIRBuilder::emitAtomicUpdate(
11538 AtomicUpdateCallbackTy &UpdateOp,
bool VolatileX,
bool IsXBinopExpr,
11539 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11541 bool emitRMWOp =
false;
11549 emitRMWOp = XElemTy;
11552 emitRMWOp = (IsXBinopExpr && XElemTy);
11559 std::pair<Value *, Value *> Res;
11561 AtomicRMWInst *RMWInst =
11562 Builder.CreateAtomicRMW(RMWOp,
X, Expr, llvm::MaybeAlign(), AO);
11563 if (IsIgnoreDenormalMode)
11564 RMWInst->
setMetadata(llvm::LLVMContext::MD_atomic_ignore_denormal_mode,
11566 if (
T.isAMDGPU()) {
11567 if (!IsFineGrainedMemory)
11568 RMWInst->
setMetadata(
"amdgpu.no.fine.grained.memory",
11570 if (!IsRemoteMemory)
11574 Res.first = RMWInst;
11579 Res.second = Res.first;
11581 Res.second = emitRMWOpAsInstruction(Res.first, Expr, RMWOp);
11584 Builder.CreateLoad(XElemTy,
X,
X->getName() +
".atomic.load");
11590 OpenMPIRBuilder::AtomicInfo atomicInfo(
11592 OldVal->
getAlign(),
true , AllocaIP,
X);
11593 auto AtomicLoadRes = atomicInfo.EmitAtomicLoadLibcall(AO);
11596 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11603 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11604 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11605 Builder.SetInsertPoint(ContBB);
11607 PHI->addIncoming(AtomicLoadRes.first, CurBB);
11609 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11612 Value *Upd = *CBResult;
11613 Builder.CreateStore(Upd, NewAtomicAddr);
11616 auto Result = atomicInfo.EmitAtomicCompareExchangeLibcall(
11617 AtomicLoadRes.second, NewAtomicAddr, AO, Failure);
11618 LoadInst *PHILoad =
Builder.CreateLoad(XElemTy,
Result.first);
11619 PHI->addIncoming(PHILoad,
Builder.GetInsertBlock());
11622 Res.first = OldExprVal;
11625 if (UnreachableInst *ExitTI =
11628 Builder.SetInsertPoint(ExitBB);
11630 Builder.SetInsertPoint(ExitTI);
11633 IntegerType *IntCastTy =
11636 Builder.CreateLoad(IntCastTy,
X,
X->getName() +
".atomic.load");
11646 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11653 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11654 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11655 Builder.SetInsertPoint(ContBB);
11657 PHI->addIncoming(OldVal, CurBB);
11662 OldExprVal =
Builder.CreateBitCast(
PHI, XElemTy,
11663 X->getName() +
".atomic.fltCast");
11665 OldExprVal =
Builder.CreateIntToPtr(
PHI, XElemTy,
11666 X->getName() +
".atomic.ptrCast");
11670 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11673 Value *Upd = *CBResult;
11674 Builder.CreateStore(Upd, NewAtomicAddr);
11675 LoadInst *DesiredVal =
Builder.CreateLoad(IntCastTy, NewAtomicAddr);
11679 X,
PHI, DesiredVal, llvm::MaybeAlign(), AO, Failure);
11680 Result->setVolatile(VolatileX);
11681 Value *PreviousVal =
Builder.CreateExtractValue(Result, 0);
11682 Value *SuccessFailureVal =
Builder.CreateExtractValue(Result, 1);
11683 PHI->addIncoming(PreviousVal,
Builder.GetInsertBlock());
11684 Builder.CreateCondBr(SuccessFailureVal, ExitBB, ContBB);
11686 Res.first = OldExprVal;
11690 if (UnreachableInst *ExitTI =
11693 Builder.SetInsertPoint(ExitBB);
11695 Builder.SetInsertPoint(ExitTI);
11706 bool UpdateExpr,
bool IsPostfixUpdate,
bool IsXBinopExpr,
11707 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11712 Type *XTy =
X.Var->getType();
11714 "OMP Atomic expects a pointer to target memory");
11715 Type *XElemTy =
X.ElemTy;
11718 "OMP atomic capture expected a scalar or struct type");
11720 "OpenMP atomic does not support LT or GT operations");
11727 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, AtomicOp, UpdateOp,
X.IsVolatile,
11728 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11731 Value *CapturedVal =
11732 (IsPostfixUpdate ? AtomicResult->first : AtomicResult->second);
11733 Builder.CreateStore(CapturedVal, V.Var, V.IsVolatile);
11735 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Capture);
11743 bool IsFailOnly,
bool IsWeak) {
11747 IsPostfixUpdate, IsFailOnly, Failure, IsWeak);
11759 assert(
X.Var->getType()->isPointerTy() &&
11760 "OMP atomic expects a pointer to target memory");
11763 assert(V.Var->getType()->isPointerTy() &&
"v.var must be of pointer type");
11764 assert(V.ElemTy ==
X.ElemTy &&
"x and v must be of same type");
11767 bool IsInteger = E->getType()->isIntegerTy();
11769 if (
Op == OMPAtomicCompareOp::EQ) {
11772 Value *OldValue =
nullptr;
11773 Value *SuccessOrFail =
nullptr;
11811 X.Var->getName() +
".atomic.load");
11817 Value *EIsNaN =
Builder.CreateFCmpUNO(E, E,
"atomic.e.isnan");
11818 Value *XIsNaN =
Builder.CreateFCmpUNO(XFP, XFP,
"atomic.x.isnan");
11819 Value *EitherNaN =
Builder.CreateOr(EIsNaN, XIsNaN,
"atomic.either.nan");
11824 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11828 M.getContext(),
X.Var->getName() +
".atomic.nan",
F, ExitBB);
11830 M.getContext(),
X.Var->getName() +
".atomic.notnan",
F, ExitBB);
11832 M.getContext(),
X.Var->getName() +
".atomic.zero",
F, ExitBB);
11834 M.getContext(),
X.Var->getName() +
".atomic.normal",
F, ExitBB);
11838 Builder.SetInsertPoint(CurBB);
11839 Builder.CreateCondBr(EitherNaN, NaNBB, NotNaNBB);
11842 Builder.SetInsertPoint(NaNBB);
11846 Builder.SetInsertPoint(NotNaNBB);
11849 X.Var->getName() +
".atomic.xiszero");
11851 "atomic.e.iszero");
11852 Value *BothZero =
Builder.CreateAnd(XIsZero, EIsZero,
"atomic.both.zero");
11853 Builder.CreateCondBr(BothZero, ZeroBB, NormalBB);
11856 Builder.SetInsertPoint(ZeroBB);
11858 X.Var, XCurr, DBCast,
MaybeAlign(), AO, Failure);
11860 Value *OldZero =
Builder.CreateExtractValue(ResZero, 0);
11861 Value *OkZero =
Builder.CreateExtractValue(ResZero, 1);
11865 Builder.SetInsertPoint(NormalBB);
11867 X.Var, EBCast, DBCast,
MaybeAlign(), AO, Failure);
11869 Value *OldNormal =
Builder.CreateExtractValue(ResNormal, 0);
11870 Value *OkNormal =
Builder.CreateExtractValue(ResNormal, 1);
11876 Builder.CreatePHI(IntCastTy, 3,
X.Var->getName() +
".atomic.old");
11881 X.Var->getName() +
".atomic.ok");
11888 Builder.SetInsertPoint(ExitBB);
11893 OldValue =
Builder.CreateBitCast(OldIntPHI,
X.ElemTy,
11894 X.Var->getName() +
".atomic.old.fp");
11895 SuccessOrFail = SuccessPHI;
11903 Result =
Builder.CreateAtomicCmpXchg(
X.Var, EBCast, DBCast,
11909 Result->setWeak(IsWeak);
11912 OldValue =
Builder.CreateExtractValue(Result, 0);
11914 OldValue =
Builder.CreateBitCast(OldValue,
X.ElemTy);
11916 "OldValue and V must be of same type");
11917 if (IsPostfixUpdate) {
11918 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
11920 SuccessOrFail =
Builder.CreateExtractValue(Result, 1);
11924 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11926 CurBBTI,
X.Var->getName() +
".atomic.exit");
11932 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
11934 Builder.SetInsertPoint(ContBB);
11935 Builder.CreateStore(OldValue, V.Var);
11941 Builder.SetInsertPoint(ExitBB);
11943 Builder.SetInsertPoint(ExitTI);
11946 Value *CapturedValue =
11947 Builder.CreateSelect(SuccessOrFail, E, OldValue);
11948 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
11954 assert(R.Var->getType()->isPointerTy() &&
11955 "r.var must be of pointer type");
11956 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
11958 Value *SuccessFailureVal =
11959 Builder.CreateExtractValue(Result, 1);
11960 Value *ResultCast =
11961 R.IsSigned ?
Builder.CreateSExt(SuccessFailureVal, R.ElemTy)
11962 :
Builder.CreateZExt(SuccessFailureVal, R.ElemTy);
11963 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
11972 "OldValue and V must be of same type");
11973 if (IsPostfixUpdate) {
11974 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
11979 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11981 CurBBTI,
X.Var->getName() +
".atomic.exit");
11987 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
11989 Builder.SetInsertPoint(ContBB);
11990 Builder.CreateStore(OldValue, V.Var);
11996 Builder.SetInsertPoint(ExitBB);
11998 Builder.SetInsertPoint(ExitTI);
12001 Value *CapturedValue =
12002 Builder.CreateSelect(SuccessOrFail, E, OldValue);
12003 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
12009 assert(R.Var->getType()->isPointerTy() &&
12010 "r.var must be of pointer type");
12011 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
12013 Value *ResultCast = R.IsSigned
12014 ?
Builder.CreateSExt(SuccessOrFail, R.ElemTy)
12015 :
Builder.CreateZExt(SuccessOrFail, R.ElemTy);
12016 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
12020 assert((
Op == OMPAtomicCompareOp::MAX ||
Op == OMPAtomicCompareOp::MIN) &&
12021 "Op should be either max or min at this point");
12022 assert(!IsFailOnly &&
"IsFailOnly is only valid when the comparison is ==");
12033 if (IsXBinopExpr) {
12062 Value *CapturedValue =
nullptr;
12063 if (IsPostfixUpdate) {
12064 CapturedValue = OldValue;
12089 Value *NonAtomicCmp =
Builder.CreateCmp(Pred, OldValue, E);
12090 CapturedValue =
Builder.CreateSelect(NonAtomicCmp, E, OldValue);
12092 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
12096 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Compare);
12116 if (&OuterAllocaBB ==
Builder.GetInsertBlock()) {
12143 bool SubClausesPresent =
12144 (NumTeamsLower || NumTeamsUpper || ThreadLimit || IfExpr);
12146 if (!
Config.isTargetDevice() && SubClausesPresent) {
12147 assert((NumTeamsLower ==
nullptr || NumTeamsUpper !=
nullptr) &&
12148 "if lowerbound is non-null, then upperbound must also be non-null "
12149 "for bounds on num_teams");
12151 if (NumTeamsUpper ==
nullptr)
12152 NumTeamsUpper =
Builder.getInt32(0);
12154 if (NumTeamsLower ==
nullptr)
12155 NumTeamsLower = NumTeamsUpper;
12159 "argument to if clause must be an integer value");
12163 IfExpr =
Builder.CreateICmpNE(IfExpr,
12164 ConstantInt::get(IfExpr->
getType(), 0));
12165 NumTeamsUpper =
Builder.CreateSelect(
12166 IfExpr, NumTeamsUpper,
Builder.getInt32(1),
"numTeamsUpper");
12169 NumTeamsLower =
Builder.CreateSelect(
12170 IfExpr, NumTeamsLower,
Builder.getInt32(1),
"numTeamsLower");
12173 if (ThreadLimit ==
nullptr)
12174 ThreadLimit =
Builder.getInt32(0);
12178 Value *NumTeamsLowerInt32 =
12180 Value *NumTeamsUpperInt32 =
12182 Value *ThreadLimitInt32 =
12189 {Ident, ThreadNum, NumTeamsLowerInt32, NumTeamsUpperInt32,
12190 ThreadLimitInt32});
12195 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
12198 auto OI = std::make_unique<OutlineInfo>();
12199 OI->EntryBB = AllocaBB;
12200 OI->ExitBB = ExitBB;
12201 OI->OuterAllocBB = &OuterAllocaBB;
12207 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"gid",
true));
12209 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"tid",
true));
12211 auto HostPostOutlineCB = [
this, Ident,
12212 ToBeDeleted](
Function &OutlinedFn)
mutable {
12217 "there must be a single user for the outlined function");
12222 "Outlined function must have two or three arguments only");
12224 bool HasShared = OutlinedFn.
arg_size() == 3;
12232 assert(StaleCI &&
"Error while outlining - no CallInst user found for the "
12233 "outlined function.");
12234 Builder.SetInsertPoint(StaleCI);
12241 omp::RuntimeFunction::OMPRTL___kmpc_fork_teams),
12244 Builder.ClearInsertionPoint();
12246 I->eraseFromParent();
12249 if (!
Config.isTargetDevice())
12250 OI->PostOutlineCB = HostPostOutlineCB;
12254 Builder.SetInsertPoint(ExitBB);
12265 BasicBlock *OuterAllocaBB = OuterAllocIP.getNodeParent();
12267 if (OuterAllocaBB ==
Builder.GetInsertBlock()) {
12282 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
12287 if (
Config.isTargetDevice()) {
12288 auto OI = std::make_unique<OutlineInfo>();
12289 OI->OuterAllocBB = OuterAllocIP.getNodeParent();
12290 OI->EntryBB = AllocaBB;
12291 OI->ExitBB = ExitBB;
12292 OI->OuterDeallocBBs.reserve(OuterDeallocBlocks.
size());
12293 copy(OuterDeallocBlocks, OI->OuterDeallocBBs.
end());
12297 Builder.SetInsertPoint(ExitBB);
12304 std::string VarName) {
12313 return MapNamesArrayGlobal;
12318void OpenMPIRBuilder::initializeTypes(
Module &M) {
12322 unsigned ProgramAS = M.getDataLayout().getProgramAddressSpace();
12323#define OMP_TYPE(VarName, InitValue) VarName = InitValue;
12324#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \
12325 VarName##Ty = ArrayType::get(ElemTy, ArraySize); \
12326 VarName##PtrTy = PointerType::get(Ctx, DefaultTargetAS);
12327#define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) \
12328 VarName = FunctionType::get(ReturnType, {__VA_ARGS__}, IsVarArg); \
12329 VarName##Ptr = PointerType::get(Ctx, ProgramAS);
12330#define OMP_STRUCT_TYPE(VarName, StructName, Packed, ...) \
12331 T = StructType::getTypeByName(Ctx, StructName); \
12333 T = StructType::create(Ctx, {__VA_ARGS__}, StructName, Packed); \
12335 VarName##Ptr = PointerType::get(Ctx, DefaultTargetAS);
12336#include "llvm/Frontend/OpenMP/OMPKinds.def"
12347 while (!Worklist.
empty()) {
12351 if (
BlockSet.insert(SuccBB).second)
12356std::unique_ptr<CodeExtractor>
12358 bool ArgsInZeroAddressSpace,
12360 return std::make_unique<CodeExtractor>(
12370 Suffix.
str(), ArgsInZeroAddressSpace);
12373std::unique_ptr<CodeExtractor> DeviceSharedMemOutlineInfo::createCodeExtractor(
12375 return std::make_unique<DeviceSharedMemCodeExtractor>(
12376 OMPBuilder, Blocks,
nullptr,
12384 OuterDeallocBBs.empty()
12387 Suffix.
str(), ArgsInZeroAddressSpace);
12391 uint64_t
Size, int32_t Flags,
12397 Name.empty() ? Addr->
getName() : Name,
Size, Flags, 0);
12409 Fn->
addFnAttr(
"uniform-work-group-size");
12410 Fn->
addFnAttr(Attribute::MustProgress);
12428 auto &&GetMDInt = [
this](
unsigned V) {
12435 NamedMDNode *MD =
M.getOrInsertNamedMetadata(
"omp_offload.info");
12436 auto &&TargetRegionMetadataEmitter =
12437 [&
C, MD, &OrderedEntries, &GetMDInt, &GetMDString](
12452 GetMDInt(E.getKind()), GetMDInt(EntryInfo.DeviceID),
12453 GetMDInt(EntryInfo.FileID), GetMDString(EntryInfo.ParentName),
12454 GetMDInt(EntryInfo.Line), GetMDInt(EntryInfo.Count),
12455 GetMDInt(E.getOrder())};
12458 OrderedEntries[E.getOrder()] = std::make_pair(&E, EntryInfo);
12467 auto &&DeviceGlobalVarMetadataEmitter =
12468 [&
C, &OrderedEntries, &GetMDInt, &GetMDString, MD](
12478 Metadata *
Ops[] = {GetMDInt(E.getKind()), GetMDString(MangledName),
12479 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
12483 OrderedEntries[E.getOrder()] = std::make_pair(&E, varInfo);
12490 DeviceGlobalVarMetadataEmitter);
12492 for (
const auto &E : OrderedEntries) {
12493 assert(E.first &&
"All ordered entries must exist!");
12494 if (
const auto *CE =
12497 if (!CE->getID() || !CE->getAddress()) {
12501 if (!
M.getNamedValue(FnName))
12509 }
else if (
const auto *CE =
dyn_cast<
12518 if (
Config.isTargetDevice() &&
Config.hasRequiresUnifiedSharedMemory())
12520 if (!CE->getAddress()) {
12525 if (CE->getVarSize() == 0)
12529 assert(((
Config.isTargetDevice() && !CE->getAddress()) ||
12530 (!
Config.isTargetDevice() && CE->getAddress())) &&
12531 "Declaret target link address is set.");
12532 if (
Config.isTargetDevice())
12534 if (!CE->getAddress()) {
12541 if (!CE->getAddress()) {
12554 if ((
GV->hasLocalLinkage() ||
GV->hasHiddenVisibility()) &&
12558 OMPTargetGlobalVarEntryIndirectVTable))
12567 Flags, CE->getLinkage(), CE->getVarName());
12570 Flags, CE->getLinkage());
12581 if (
Config.hasRequiresFlags() && !
Config.isTargetDevice())
12587 Config.getRequiresFlags());
12597 OS <<
"_" <<
Count;
12602 unsigned NewCount = getTargetRegionEntryInfoCount(EntryInfo);
12605 EntryInfo.
Line, NewCount);
12613 auto FileIDInfo = CallBack();
12614 uint64_t FileID = 0;
12616 ID =
Status->getUniqueID();
12617 FileID =
Status->getUniqueID().getFile();
12621 FileID =
hash_value(std::get<0>(FileIDInfo));
12625 std::get<1>(FileIDInfo));
12630 for (uint64_t Remain =
12631 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12633 !(Remain & 1); Remain = Remain >> 1)
12651 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12653 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12660 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12666 Flags &=
~omp::OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
12667 Flags |= MemberOfFlag;
12673 bool IsDeclaration,
bool IsExternallyVisible,
12675 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12676 std::vector<Triple> TargetTriple,
Type *LlvmPtrTy,
12677 std::function<
Constant *()> GlobalInitializer,
12688 Config.hasRequiresUnifiedSharedMemory())) {
12693 if (!IsExternallyVisible)
12695 OS <<
"_decl_tgt_ref_ptr";
12698 Value *Ptr =
M.getNamedValue(PtrName);
12707 if (!
Config.isTargetDevice()) {
12708 if (GlobalInitializer)
12709 GV->setInitializer(GlobalInitializer());
12715 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12716 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12717 GlobalInitializer, VariableLinkage, LlvmPtrTy,
cast<Constant>(Ptr));
12729 bool IsDeclaration,
bool IsExternallyVisible,
12731 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12732 std::vector<Triple> TargetTriple,
12733 std::function<
Constant *()> GlobalInitializer,
12737 (TargetTriple.empty() && !
Config.isTargetDevice()))
12748 !
Config.hasRequiresUnifiedSharedMemory()) {
12750 VarName = MangledName;
12753 if (!IsDeclaration)
12755 M.getDataLayout().getTypeSizeInBits(LlvmVal->
getValueType()), 8);
12758 Linkage = (VariableLinkage) ? VariableLinkage() : LlvmVal->
getLinkage();
12762 if (
Config.isTargetDevice() &&
12771 if (!
M.getNamedValue(RefName)) {
12775 GvAddrRef->setConstant(
true);
12777 GvAddrRef->setInitializer(Addr);
12778 GeneratedRefs.push_back(GvAddrRef);
12787 if (
Config.isTargetDevice()) {
12788 VarName = (Addr) ? Addr->
getName() :
"";
12792 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12793 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12794 LlvmPtrTy, GlobalInitializer, VariableLinkage);
12795 VarName = (Addr) ? Addr->
getName() :
"";
12797 VarSize =
M.getDataLayout().getPointerSize();
12816 auto &&GetMDInt = [MN](
unsigned Idx) {
12821 auto &&GetMDString = [MN](
unsigned Idx) {
12823 return V->getString();
12826 switch (GetMDInt(0)) {
12830 case OffloadEntriesInfoManager::OffloadEntryInfo::
12831 OffloadingEntryInfoTargetRegion: {
12841 case OffloadEntriesInfoManager::OffloadEntryInfo::
12842 OffloadingEntryInfoDeviceGlobalVar:
12855 if (HostFilePath.
empty())
12859 if (std::error_code Err = Buf.getError()) {
12861 "OpenMPIRBuilder: " +
12869 if (std::error_code Err =
M.getError()) {
12871 (
"error parsing host file inside of OpenMPIRBuilder: " + Err.message())
12885 "expected a valid insertion block for creating an iterator loop");
12889 if (SplitIP == CurBB->
end())
12891 SplitIP = Terminator->getIterator();
12895 Builder.getCurrentDebugLocation(),
"omp.it.cont");
12907 T->eraseFromParent();
12922 bool ReachesLatch =
false;
12925 while (!Worklist.
empty()) {
12930 "iterator bodygen must leave at most one unterminated block",
12936 if (Succ == Latch) {
12937 ReachesLatch =
true;
12942 "iterator bodygen must not branch out of the loop body",
12944 if (Visited.
insert(Succ).second)
12950 Builder.SetInsertPoint(OpenBB);
12952 }
else if (!ReachesLatch) {
12962 return ContBB->
begin();
12972 for (
const auto &
ParamAttr : ParamAttrs) {
13015 return std::string(Out.str());
13023 unsigned VecRegSize;
13025 ISADataTy ISAData[] = {
13044 for (
char Mask :
Masked) {
13045 for (
const ISADataTy &
Data : ISAData) {
13048 Out <<
"_ZGV" <<
Data.ISA << Mask;
13050 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
13064template <
typename T>
13067 StringRef MangledName,
bool OutputBecomesInput,
13071 Out << Prefix << ISA << LMask << VLEN;
13072 if (OutputBecomesInput)
13074 Out << ParSeq <<
'_' << MangledName;
13083 bool OutputBecomesInput,
13088 OutputBecomesInput, Fn);
13090 OutputBecomesInput, Fn);
13094 OutputBecomesInput, Fn);
13096 OutputBecomesInput, Fn);
13100 OutputBecomesInput, Fn);
13102 OutputBecomesInput, Fn);
13107 OutputBecomesInput, Fn);
13118 char ISA,
unsigned NarrowestDataSize,
bool OutputBecomesInput) {
13119 assert((ISA ==
'n' || ISA ==
's') &&
"Expected ISA either 's' or 'n'.");
13131 OutputBecomesInput, Fn);
13138 OutputBecomesInput, Fn);
13140 OutputBecomesInput, Fn);
13144 OutputBecomesInput, Fn);
13148 OutputBecomesInput, Fn);
13157 OutputBecomesInput, Fn);
13164 MangledName, OutputBecomesInput, Fn);
13166 MangledName, OutputBecomesInput, Fn);
13170 MangledName, OutputBecomesInput, Fn);
13174 MangledName, OutputBecomesInput, Fn);
13184 return OffloadEntriesTargetRegion.empty() &&
13185 OffloadEntriesDeviceGlobalVar.empty();
13188unsigned OffloadEntriesInfoManager::getTargetRegionEntryInfoCount(
13190 auto It = OffloadEntriesTargetRegionCount.find(
13191 getTargetRegionEntryCountKey(EntryInfo));
13192 if (It == OffloadEntriesTargetRegionCount.end())
13197void OffloadEntriesInfoManager::incrementTargetRegionEntryInfoCount(
13199 OffloadEntriesTargetRegionCount[getTargetRegionEntryCountKey(EntryInfo)] =
13200 EntryInfo.
Count + 1;
13206 OffloadEntriesTargetRegion[EntryInfo] =
13209 ++OffloadingEntriesNum;
13215 assert(EntryInfo.
Count == 0 &&
"expected default EntryInfo");
13218 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
13222 if (OMPBuilder->Config.isTargetDevice()) {
13227 auto &Entry = OffloadEntriesTargetRegion[EntryInfo];
13228 Entry.setAddress(Addr);
13230 Entry.setFlags(Flags);
13236 "Target region entry already registered!");
13238 OffloadEntriesTargetRegion[EntryInfo] = Entry;
13239 ++OffloadingEntriesNum;
13241 incrementTargetRegionEntryInfoCount(EntryInfo);
13248 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
13250 auto It = OffloadEntriesTargetRegion.find(EntryInfo);
13251 if (It == OffloadEntriesTargetRegion.end()) {
13255 if (!IgnoreAddressId && (It->second.getAddress() || It->second.getID()))
13263 for (
const auto &It : OffloadEntriesTargetRegion) {
13264 Action(It.first, It.second);
13270 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
13271 ++OffloadingEntriesNum;
13277 if (OMPBuilder->Config.isTargetDevice()) {
13281 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
13283 if (Entry.getVarSize() == 0) {
13284 Entry.setVarSize(VarSize);
13285 Entry.setLinkage(Linkage);
13289 Entry.setVarSize(VarSize);
13290 Entry.setLinkage(Linkage);
13291 Entry.setAddress(Addr);
13294 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
13295 assert(Entry.isValid() && Entry.getFlags() == Flags &&
13296 "Entry not initialized!");
13297 if (Entry.getVarSize() == 0) {
13298 Entry.setVarSize(VarSize);
13299 Entry.setLinkage(Linkage);
13306 OffloadEntriesDeviceGlobalVar.try_emplace(VarName, OffloadingEntriesNum,
13307 Addr, VarSize, Flags, Linkage,
13310 OffloadEntriesDeviceGlobalVar.try_emplace(
13311 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage,
"");
13312 ++OffloadingEntriesNum;
13319 for (
const auto &E : OffloadEntriesDeviceGlobalVar)
13320 Action(E.getKey(), E.getValue());
13327void CanonicalLoopInfo::collectControlBlocks(
13334 BBs.
append({getPreheader(), Header,
Cond, Latch, Exit, getAfter()});
13346void CanonicalLoopInfo::setTripCount(
Value *TripCount) {
13358void CanonicalLoopInfo::mapIndVar(
13368 for (
Use &U : OldIV->
uses()) {
13372 if (
User->getParent() == getCond())
13374 if (
User->getParent() == getLatch())
13380 Value *NewIV = Updater(OldIV);
13383 for (Use *U : ReplacableUses)
13404 "Preheader must terminate with unconditional branch");
13406 "Preheader must jump to header");
13410 "Header must terminate with unconditional branch");
13411 assert(Header->getSingleSuccessor() == Cond &&
13412 "Header must jump to exiting block");
13415 assert(Cond->getSinglePredecessor() == Header &&
13416 "Exiting block only reachable from header");
13419 "Exiting block must terminate with conditional branch");
13421 "Exiting block's first successor jump to the body");
13423 "Exiting block's second successor must exit the loop");
13427 "Body only reachable from exiting block");
13432 "Latch must terminate with unconditional branch");
13433 assert(Latch->getSingleSuccessor() == Header &&
"Latch must jump to header");
13436 assert(Latch->getSinglePredecessor() !=
nullptr);
13441 "Exit block must terminate with unconditional branch");
13442 assert(Exit->getSingleSuccessor() == After &&
13443 "Exit block must jump to after block");
13447 "After block only reachable from exit block");
13451 assert(IndVar &&
"Canonical induction variable not found?");
13453 "Induction variable must be an integer");
13455 "Induction variable must be a PHI in the loop header");
13461 auto *NextIndVar =
cast<PHINode>(IndVar)->getIncomingValue(1);
13469 assert(TripCount &&
"Loop trip count not found?");
13471 "Trip count and induction variable must have the same type");
13475 "Exit condition must be a signed less-than comparison");
13477 "Exit condition must compare the induction variable");
13479 "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),...