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);
433 Builder.SetInsertPoint(Old);
436 Builder.SetCurrentDebugLocation(
DebugLoc);
448 Builder.SetInsertPoint(Old);
451 Builder.SetCurrentDebugLocation(
DebugLoc);
468 const Twine &Name =
"",
bool AsPtr =
true,
469 bool Is64Bit =
false) {
470 Builder.restoreIP(OuterAllocaIP);
474 Builder.CreateAlloca(IntTy,
nullptr, Name +
".addr");
478 FakeVal = FakeValAddr;
483 FakeValAddr, Builder.getPtrTy(), Name +
".ascast"));
487 FakeVal = Builder.CreateLoad(IntTy, FakeValAddr, Name +
".val");
492 Builder.restoreIP(InnerAllocaIP);
495 UseFakeVal = Builder.CreateLoad(IntTy, FakeVal, Name +
".use");
498 FakeVal, Is64Bit ? Builder.getInt64(10) : Builder.getInt32(10)));
511enum OpenMPOffloadingRequiresDirFlags {
513 OMP_REQ_UNDEFINED = 0x000,
515 OMP_REQ_NONE = 0x001,
517 OMP_REQ_REVERSE_OFFLOAD = 0x002,
519 OMP_REQ_UNIFIED_ADDRESS = 0x004,
521 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008,
523 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010,
530 DominatorTree *DT =
nullptr,
bool AggregateArgs =
false,
531 BlockFrequencyInfo *BFI =
nullptr,
532 BranchProbabilityInfo *BPI =
nullptr,
533 AssumptionCache *AC =
nullptr,
bool AllowVarArgs =
false,
534 bool AllowAlloca =
false,
535 BasicBlock *AllocationBlock =
nullptr,
537 std::string Suffix =
"",
bool ArgsInZeroAddressSpace =
false)
538 : CodeExtractor(BBs, DT, AggregateArgs, BFI, BPI, AC, AllowVarArgs,
539 AllowAlloca, AllocationBlock, DeallocationBlocks, Suffix,
540 ArgsInZeroAddressSpace),
541 OMPBuilder(OMPBuilder) {}
543 virtual ~OMPCodeExtractor() =
default;
546 OpenMPIRBuilder &OMPBuilder;
549class DeviceSharedMemCodeExtractor :
public OMPCodeExtractor {
551 using OMPCodeExtractor::OMPCodeExtractor;
552 virtual ~DeviceSharedMemCodeExtractor() =
default;
556 allocateVar(IRBuilder<>::InsertPoint AllocaIP,
DebugLoc DL,
Type *VarType,
557 const Twine &Name = Twine(
""),
558 AddrSpaceCastInst **CastedAlloc =
nullptr)
override {
559 return OMPBuilder.createOMPAllocShared({AllocaIP,
DL}, VarType,
Name);
562 virtual Instruction *deallocateVar(IRBuilder<>::InsertPoint DeallocIP,
564 Type *VarType)
override {
565 return OMPBuilder.createOMPFreeShared({DeallocIP,
DL}, Var, VarType);
572 OpenMPIRBuilder &OMPBuilder;
574 DeviceSharedMemOutlineInfo(OpenMPIRBuilder &OMPBuilder)
575 : OMPBuilder(OMPBuilder) {}
576 virtual ~DeviceSharedMemOutlineInfo() =
default;
578 virtual std::unique_ptr<CodeExtractor>
580 bool ArgsInZeroAddressSpace,
581 Twine Suffix = Twine(
""))
override;
587 : RequiresFlags(OMP_REQ_UNDEFINED) {}
591 bool HasRequiresReverseOffload,
bool HasRequiresUnifiedAddress,
592 bool HasRequiresUnifiedSharedMemory,
bool HasRequiresDynamicAllocators)
595 RequiresFlags(OMP_REQ_UNDEFINED) {
596 if (HasRequiresReverseOffload)
597 RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
598 if (HasRequiresUnifiedAddress)
599 RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
600 if (HasRequiresUnifiedSharedMemory)
601 RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
602 if (HasRequiresDynamicAllocators)
603 RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
607 return RequiresFlags & OMP_REQ_REVERSE_OFFLOAD;
611 return RequiresFlags & OMP_REQ_UNIFIED_ADDRESS;
615 return RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY;
619 return RequiresFlags & OMP_REQ_DYNAMIC_ALLOCATORS;
624 :
static_cast<int64_t
>(OMP_REQ_NONE);
629 RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
631 RequiresFlags &= ~OMP_REQ_REVERSE_OFFLOAD;
636 RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
638 RequiresFlags &= ~OMP_REQ_UNIFIED_ADDRESS;
643 RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
645 RequiresFlags &= ~OMP_REQ_UNIFIED_SHARED_MEMORY;
650 RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
652 RequiresFlags &= ~OMP_REQ_DYNAMIC_ALLOCATORS;
665 constexpr size_t MaxDim = 3;
670 Value *DynCGroupMemFallbackFlag =
672 DynCGroupMemFallbackFlag =
Builder.CreateShl(DynCGroupMemFallbackFlag, 2);
677 StrictBlocksFlag =
Builder.CreateShl(StrictBlocksFlag, 6);
678 StrictThreadsFlag =
Builder.CreateShl(StrictThreadsFlag, 7);
680 Value *Flags =
Builder.CreateOr(HasNoWaitFlag, DynCGroupMemFallbackFlag);
681 Flags =
Builder.CreateOr(Flags, StrictBlocksFlag);
682 Flags =
Builder.CreateOr(Flags, StrictThreadsFlag);
688 Value *NumThreads3D =
719 auto FnAttrs = Attrs.getFnAttrs();
720 auto RetAttrs = Attrs.getRetAttrs();
722 for (
size_t ArgNo = 0; ArgNo < Fn.
arg_size(); ++ArgNo)
727 bool Param =
true) ->
void {
728 bool HasSignExt = AS.hasAttribute(Attribute::SExt);
729 bool HasZeroExt = AS.hasAttribute(Attribute::ZExt);
730 if (HasSignExt || HasZeroExt) {
731 assert(AS.getNumAttributes() == 1 &&
732 "Currently not handling extension attr combined with others.");
734 if (
auto AK = TargetLibraryInfo::getExtAttrForI32Param(
T, HasSignExt))
737 TargetLibraryInfo::getExtAttrForI32Return(
T, HasSignExt))
744#define OMP_ATTRS_SET(VarName, AttrSet) AttributeSet VarName = AttrSet;
745#include "llvm/Frontend/OpenMP/OMPKinds.def"
749#define OMP_RTL_ATTRS(Enum, FnAttrSet, RetAttrSet, ArgAttrSets) \
751 FnAttrs = FnAttrs.addAttributes(Ctx, FnAttrSet); \
752 addAttrSet(RetAttrs, RetAttrSet, false); \
753 for (size_t ArgNo = 0; ArgNo < ArgAttrSets.size(); ++ArgNo) \
754 addAttrSet(ArgAttrs[ArgNo], ArgAttrSets[ArgNo]); \
755 Fn.setAttributes(AttributeList::get(Ctx, FnAttrs, RetAttrs, ArgAttrs)); \
757#include "llvm/Frontend/OpenMP/OMPKinds.def"
771#define OMP_RTL(Enum, Str, IsVarArg, ReturnType, ...) \
773 FnTy = FunctionType::get(ReturnType, ArrayRef<Type *>{__VA_ARGS__}, \
775 Fn = M.getFunction(Str); \
777#include "llvm/Frontend/OpenMP/OMPKinds.def"
783#define OMP_RTL(Enum, Str, ...) \
785 Fn = Function::Create(FnTy, GlobalValue::ExternalLinkage, Str, M); \
787#include "llvm/Frontend/OpenMP/OMPKinds.def"
791 if (FnID == OMPRTL___kmpc_fork_call || FnID == OMPRTL___kmpc_fork_teams) {
801 LLVMContext::MD_callback,
803 2, {-1, -1},
true)}));
816 assert(Fn &&
"Failed to create OpenMP runtime function");
827 Builder.SetInsertPoint(FiniBB);
839 FiniBB = OtherFiniBB;
841 Builder.SetInsertPoint(FiniBB->getFirstNonPHIIt());
849 auto EndIt = FiniBB->end();
850 if (FiniBB->size() >= 1)
851 if (
auto Prev = std::prev(EndIt); Prev->isTerminator())
856 FiniBB->replaceAllUsesWith(OtherFiniBB);
857 FiniBB->eraseFromParent();
858 FiniBB = OtherFiniBB;
865 assert(Fn &&
"Failed to create OpenMP runtime function pointer");
888 for (
auto Inst =
Block->getReverseIterator()->begin();
889 Inst !=
Block->getReverseIterator()->end();) {
918 Block.getParent()->getEntryBlock().getTerminator()->getIterator();
939 DeferredOutlines.
push_back(std::move(OI));
943 ParallelRegionBlockSet.
clear();
945 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
955 bool ArgsInZeroAddressSpace =
Config.isTargetDevice();
956 std::unique_ptr<CodeExtractor> Extractor =
957 OI->createCodeExtractor(Blocks, ArgsInZeroAddressSpace,
".omp_par");
961 <<
" Exit: " << OI->ExitBB->getName() <<
"\n");
962 assert(Extractor->isEligible() &&
963 "Expected OpenMP outlining to be possible!");
965 for (
auto *V : OI->ExcludeArgsFromAggregate)
966 Extractor->excludeArgFromAggregate(V);
969 Extractor->extractCodeRegion(CEAC, OI->Inputs, OI->Outputs);
973 if (TargetCpuAttr.isStringAttribute())
976 auto TargetFeaturesAttr = OuterFn->
getFnAttribute(
"target-features");
977 if (TargetFeaturesAttr.isStringAttribute())
978 OutlinedFn->
addFnAttr(TargetFeaturesAttr);
981 LLVM_DEBUG(
dbgs() <<
" Outlined function: " << *OutlinedFn <<
"\n");
983 "OpenMP outlined functions should not return a value!");
988 M.getFunctionList().insertAfter(OuterFn->
getIterator(), OutlinedFn);
995 assert(OI->EntryBB->getUniquePredecessor() == &ArtificialEntry);
1002 "Expected instructions to add in the outlined region entry");
1009 if (
I.isTerminator()) {
1011 if (
Instruction *TI = OI->EntryBB->getTerminatorOrNull())
1012 TI->adoptDbgRecords(&ArtificialEntry,
I.getIterator(),
false);
1016 I.moveBeforePreserving(*OI->EntryBB,
1017 OI->EntryBB->getFirstInsertionPt());
1020 OI->EntryBB->moveBefore(&ArtificialEntry);
1027 if (OI->PostOutlineCB)
1028 OI->PostOutlineCB(*OutlinedFn);
1030 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;
1920 if (NumCapturedVars) {
1921 assert(NumCapturedVars == 1 &&
"Expected an aggregate capture argument");
1924 ->getAllocatedType()
1926 "Expected a stack-allocated capture structure");
1932 CI->
getParent()->setName(
"omp_parallel");
1933 Builder.SetInsertPoint(CI);
1936 Value *ForkCallArgs[] = {Ident, Builder.getInt32(NumCapturedVars),
1940 RealArgs.
append(std::begin(ForkCallArgs), std::end(ForkCallArgs));
1942 Value *
Cond = Builder.CreateSExtOrTrunc(IfCondition, OMPIRBuilder->Int32);
1949 auto PtrTy = OMPIRBuilder->VoidPtr;
1950 if (IfCondition && NumCapturedVars == 0) {
1958 << *Builder.GetInsertBlock()->getParent() <<
"\n");
1961 Builder.SetInsertPoint(PrivTID);
1963 Builder.CreateStore(Builder.CreateLoad(OMPIRBuilder->Int32, OutlinedAI),
1970 I->eraseFromParent();
1978 Value *NumThreads, omp::ProcBindKind ProcBind,
bool IsCancellable) {
1987 const bool NeedThreadID = NumThreads ||
Config.isTargetDevice() ||
1988 (ProcBind != OMP_PROC_BIND_default);
1995 bool ArgsInZeroAddressSpace =
Config.isTargetDevice();
1999 if (NumThreads && !
Config.isTargetDevice()) {
2002 Builder.CreateIntCast(NumThreads, Int32,
false)};
2007 if (ProcBind != OMP_PROC_BIND_default) {
2011 ConstantInt::get(Int32,
unsigned(ProcBind),
true)};
2021 BasicBlock *OuterAllocaBlock = OuterAllocIP.getNodeParent();
2033 Builder.CreateAlloca(Int32,
nullptr,
"zero.addr");
2036 if (ArgsInZeroAddressSpace &&
M.getDataLayout().getAllocaAddrSpace() != 0) {
2039 TIDAddrAlloca, PointerType ::get(
M.getContext(), 0),
"tid.addr.ascast");
2043 PointerType ::get(
M.getContext(), 0),
2044 "zero.addr.ascast");
2057 UI->setDebugLoc(
Loc.DL);
2069 if (IP == IP.getNodeParent()->end()) {
2073 IP =
I->getIterator();
2075 assert(IP.getNodeParent()->getTerminator()->getNumSuccessors() == 1 &&
2076 IP.getNodeParent()->getTerminator()->getSuccessor(0) == PRegExitBB &&
2077 "Unexpected insertion point for finalization call!");
2089 Builder.CreateAlloca(Int32,
nullptr,
"tid.addr.local");
2095 Builder.CreateLoad(Int32, ZeroAddr,
"zero.addr.use");
2113 LLVM_DEBUG(
dbgs() <<
"Before body codegen: " << *OuterFn <<
"\n");
2116 assert(BodyGenCB &&
"Expected body generation callback!");
2118 if (
Error Err = BodyGenCB(InnerAllocaIP, CodeGenIP, PRegExitBB))
2121 LLVM_DEBUG(
dbgs() <<
"After body codegen: " << *OuterFn <<
"\n");
2125 bool UsesDeviceSharedMemory =
2127 std::unique_ptr<OutlineInfo> OI =
2128 UsesDeviceSharedMemory
2129 ? std::make_unique<DeviceSharedMemOutlineInfo>(*
this)
2130 : std::make_unique<OutlineInfo>();
2132 if (
Config.isTargetDevice()) {
2134 OI->PostOutlineCB = [=, ToBeDeletedVec =
2135 std::move(ToBeDeleted)](
Function &OutlinedFn) {
2137 IfCondition, NumThreads, PrivTID, PrivTIDAddr,
2138 ThreadID, ToBeDeletedVec);
2142 OI->PostOutlineCB = [=, ToBeDeletedVec =
2143 std::move(ToBeDeleted)](
Function &OutlinedFn) {
2145 PrivTID, PrivTIDAddr, ToBeDeletedVec);
2149 OI->FixUpNonEntryAllocas =
true;
2150 OI->OuterAllocBB = OuterAllocaBlock;
2151 OI->EntryBB = PRegEntryBB;
2152 OI->ExitBB = PRegExitBB;
2153 OI->OuterDeallocBBs.reserve(OuterDeallocBlocks.
size());
2154 copy(OuterDeallocBlocks, OI->OuterDeallocBBs.
end());
2158 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
2170 ".omp_par", ArgsInZeroAddressSpace);
2175 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
2177 Extractor.findInputsOutputs(Inputs, Outputs, SinkingCands,
2182 return GV->getValueType() == OpenMPIRBuilder::Ident;
2187 LLVM_DEBUG(
dbgs() <<
"Before privatization: " << *OuterFn <<
"\n");
2193 if (&V == TIDAddr || &V == ZeroAddr) {
2194 OI->ExcludeArgsFromAggregate.push_back(&V);
2199 for (
Use &U : V.uses())
2201 if (ParallelRegionBlockSet.
count(UserI->getParent()))
2211 if (!V.getType()->isPointerTy()) {
2215 Builder.restoreIP(OuterAllocIP);
2217 if (UsesDeviceSharedMemory) {
2220 V.getName() +
".reloaded");
2221 for (
BasicBlock *DeallocBlock : OuterDeallocBlocks) {
2222 assert(DeallocBlock->getParent() ==
2223 OuterAllocIP.getNodeParent()->getParent() &&
2224 "Dealloc block must be in the allocation's function to reuse "
2225 "its debug location");
2227 Builder.getCurrentDebugLocation()},
2231 Ptr =
Builder.CreateAlloca(V.getType(),
nullptr,
2232 V.getName() +
".reloaded");
2241 Builder.restoreIP(InnerAllocaIP);
2242 Inner =
Builder.CreateLoad(V.getType(), Ptr);
2245 Value *ReplacementValue =
nullptr;
2248 ReplacementValue = PrivTID;
2251 PrivCB(InnerAllocaIP,
Builder.saveIP(), V, *Inner, ReplacementValue);
2256 InnerAllocaIP.getNodeParent()->getTerminator()->getIterator();
2258 assert(ReplacementValue &&
2259 "Expected copy/create callback to set replacement value!");
2260 if (ReplacementValue == &V)
2265 UPtr->set(ReplacementValue);
2288 for (
Value *Output : Outputs)
2292 "OpenMP outlining should not produce live-out values!");
2294 LLVM_DEBUG(
dbgs() <<
"After privatization: " << *OuterFn <<
"\n");
2296 for (
auto *BB : Blocks)
2297 dbgs() <<
" PBR: " << BB->getName() <<
"\n";
2305 assert(FiniInfo.DK == OMPD_parallel &&
2306 "Unexpected finalization stack state!");
2317 Builder.CreateBr(*FiniBBOrErr);
2321 Term->eraseFromParent();
2328 UI->eraseFromParent();
2360 Value *Severity = ConstantInt::get(Int32, IsFatal ? 2 : 1);
2362 Value *Args[] = {Ident, Severity, MessageArg};
2391 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr));
2393 Builder.CreateStore(DepValPtr, Addr);
2396 DependInfo, Entry,
static_cast<unsigned int>(RTLDependInfoFields::Len));
2398 ConstantInt::get(SizeTy,
2403 DependInfo, Entry,
static_cast<unsigned int>(RTLDependInfoFields::Flags));
2405 static_cast<unsigned int>(Dep.
DepKind)),
2418 if (Dependencies.
empty())
2438 Type *DependInfo = OMPBuilder.DependInfo;
2440 Value *DepArray =
nullptr;
2446 Builder.SetInsertPoint(
2447 Builder.GetInsertBlock()->getParent()->getEntryBlock().getTerminator());
2448 DepArray = Builder.CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
2451 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies)) {
2453 Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
2478 Value *DepArray =
nullptr;
2479 Type *DepArrayTy =
nullptr;
2480 Value *NumDeps =
nullptr;
2483 NumDeps = Dependencies.
NumDeps;
2484 }
else if (!Dependencies.
Deps.empty()) {
2486 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
2490 Builder.GetInsertBlock()->getParent()->getEntryBlock();
2492 DepArray =
Builder.CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
2495 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies.
Deps)) {
2497 Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
2511 ConstantInt::get(
Builder.getInt32Ty(), 0),
2513 ConstantInt::get(
Builder.getInt32Ty(), IsNowait)};
2516 omp::RuntimeFunction::OMPRTL___kmpc_omp_taskwait_deps_51),
2526 unsigned ProgramAddressSpace = M.getDataLayout().getProgramAddressSpace();
2538 auto *VoidPtrTy =
PointerType::get(Builder.getContext(), ProgramAddressSpace);
2541 Builder.getVoidTy(), {VoidPtrTy, VoidPtrTy, Builder.getInt32Ty()},
2545 "omp_taskloop_dup", M);
2548 Value *LastprivateFlagArg = DupFunction->
getArg(2);
2549 DestTaskArg->
setName(
"dest_task");
2550 SrcTaskArg->
setName(
"src_task");
2551 LastprivateFlagArg->
setName(
"lastprivate_flag");
2554 Builder.SetInsertPoint(
2557 auto GetTaskContextPtrFromArg = [&](
Value *Arg) ->
Value * {
2558 Type *TaskWithPrivatesTy =
2560 Value *TaskPrivates = Builder.CreateGEP(
2561 TaskWithPrivatesTy, Arg, {Builder.getInt32(0), Builder.getInt32(1)});
2562 Value *ContextPtr = Builder.CreateGEP(
2563 PrivatesTy, TaskPrivates,
2564 {Builder.getInt32(0), Builder.getInt32(PrivatesIndex)});
2568 Value *DestTaskContextPtr = GetTaskContextPtrFromArg(DestTaskArg);
2569 Value *SrcTaskContextPtr = GetTaskContextPtrFromArg(SrcTaskArg);
2571 DestTaskContextPtr->
setName(
"destPtr");
2572 SrcTaskContextPtr->
setName(
"srcPtr");
2576 Expected<IRBuilderBase::InsertPoint> AfterIPOrError =
2577 DupCB(AllocaIP, CodeGenIP, DestTaskContextPtr, SrcTaskContextPtr);
2578 if (!AfterIPOrError)
2580 Builder.restoreIP(*AfterIPOrError);
2590 llvm::function_ref<llvm::Expected<llvm::CanonicalLoopInfo *>()> LoopInfo,
2592 Value *GrainSize,
bool NoGroup,
int Sched,
Value *Final,
bool Mergeable,
2594 Value *TaskContextStructPtrVal,
bool FreeAgent) {
2599 uint32_t SrcLocStrSize;
2613 if (
Error Err = BodyGenCB(TaskloopAllocaIP, TaskloopBodyIP, TaskloopExitBB))
2616 llvm::Expected<llvm::CanonicalLoopInfo *> result = LoopInfo();
2621 llvm::CanonicalLoopInfo *CLI = result.
get();
2622 auto OI = std::make_unique<OutlineInfo>();
2623 OI->EntryBB = TaskloopAllocaBB;
2624 OI->OuterAllocBB = AllocaIP.getNodeParent();
2625 OI->ExitBB = TaskloopExitBB;
2626 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2627 copy(DeallocBlocks, OI->OuterDeallocBBs.end());
2630 SmallVector<Instruction *> ToBeDeleted;
2633 Builder, AllocaIP, ToBeDeleted, TaskloopAllocaIP,
"global.tid",
false));
2635 TaskloopAllocaIP,
"lb",
false,
true);
2637 TaskloopAllocaIP,
"ub",
false,
true);
2639 TaskloopAllocaIP,
"step",
false,
true);
2642 OI->Inputs.insert(FakeLB);
2643 OI->Inputs.insert(FakeUB);
2644 OI->Inputs.insert(FakeStep);
2645 if (TaskContextStructPtrVal)
2646 OI->Inputs.insert(TaskContextStructPtrVal);
2647 assert(((TaskContextStructPtrVal && DupCB) ||
2648 (!TaskContextStructPtrVal && !DupCB)) &&
2649 "Task context struct ptr and duplication callback must be both set "
2655 unsigned ProgramAddressSpace =
M.getDataLayout().getProgramAddressSpace();
2659 {FakeLB->getType(), FakeUB->getType(), FakeStep->getType(), PointerTy});
2660 Expected<Value *> TaskDupFnOrErr = createTaskDuplicationFunction(
2663 if (!TaskDupFnOrErr) {
2666 Value *TaskDupFn = *TaskDupFnOrErr;
2668 OI->PostOutlineCB = [
this, Ident, LBVal, UBVal, StepVal, Untied,
2669 TaskloopAllocaBB, CLI, TaskDupFn, ToBeDeleted, IfCond,
2670 GrainSize, NoGroup, Sched, FakeLB, FakeUB, FakeStep,
2671 FakeSharedsTy, Final, Mergeable, Priority,
2673 FreeAgent](
Function &OutlinedFn)
mutable {
2675 assert(OutlinedFn.hasOneUse() &&
2676 "there must be a single user for the outlined function");
2683 Value *CastedLBVal =
2684 Builder.CreateIntCast(LBVal,
Builder.getInt64Ty(),
true,
"lb64");
2685 Value *CastedUBVal =
2686 Builder.CreateIntCast(UBVal,
Builder.getInt64Ty(),
true,
"ub64");
2687 Value *CastedStepVal =
2688 Builder.CreateIntCast(StepVal,
Builder.getInt64Ty(),
true,
"step64");
2690 Builder.SetInsertPoint(StaleCI);
2703 Builder.CreateCall(TaskgroupFn, {Ident, ThreadID});
2728 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
2730 AllocaInst *ArgStructAlloca =
2732 assert(ArgStructAlloca &&
2733 "Unable to find the alloca instruction corresponding to arguments "
2734 "for extracted function");
2735 std::optional<TypeSize> ArgAllocSize =
2738 "Unable to determine size of arguments for extracted function");
2739 Value *SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
2744 CallInst *TaskData =
Builder.CreateCall(
2745 TaskAllocFn, {Ident, ThreadID,
Flags,
2746 TaskSize, SharedsSize,
2751 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
2757 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(0)});
2760 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(1)});
2763 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(2)});
2769 IfCond ?
Builder.CreateIntCast(IfCond,
Builder.getInt32Ty(),
true)
2775 Value *GrainSizeVal =
2776 GrainSize ?
Builder.CreateIntCast(GrainSize,
Builder.getInt64Ty(),
true)
2778 Value *TaskDup = TaskDupFn;
2780 Value *
Args[] = {Ident, ThreadID, TaskData, IfCondVal, Lb, Ub,
2781 Loadstep, NoGroupVal, SchedVal, GrainSizeVal, TaskDup};
2786 Builder.CreateCall(TaskloopFn, Args);
2793 Builder.CreateCall(EndTaskgroupFn, {Ident, ThreadID});
2798 Builder.SetInsertPoint(TaskloopAllocaBB->begin());
2800 LoadInst *SharedsOutlined =
2801 Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
2802 OutlinedFn.getArg(1)->replaceUsesWithIf(
2804 [SharedsOutlined](Use &U) {
return U.getUser() != SharedsOutlined; });
2807 Type *IVTy =
IV->getType();
2813 Value *TaskLB =
nullptr;
2814 Value *TaskUB =
nullptr;
2815 Value *TaskStep =
nullptr;
2816 Value *LoadTaskLB =
nullptr;
2817 Value *LoadTaskUB =
nullptr;
2818 Value *LoadTaskStep =
nullptr;
2819 for (Instruction &
I : *TaskloopAllocaBB) {
2820 if (
I.getOpcode() == Instruction::GetElementPtr) {
2823 switch (CI->getZExtValue()) {
2835 }
else if (
I.getOpcode() == Instruction::Load) {
2837 if (
Load.getPointerOperand() == TaskLB) {
2838 assert(TaskLB !=
nullptr &&
"Expected value for TaskLB");
2840 }
else if (
Load.getPointerOperand() == TaskUB) {
2841 assert(TaskUB !=
nullptr &&
"Expected value for TaskUB");
2843 }
else if (
Load.getPointerOperand() == TaskStep) {
2844 assert(TaskStep !=
nullptr &&
"Expected value for TaskStep");
2850 Builder.SetInsertPoint(CLI->getPreheader()->getTerminator());
2852 assert(LoadTaskLB !=
nullptr &&
"Expected value for LoadTaskLB");
2853 assert(LoadTaskUB !=
nullptr &&
"Expected value for LoadTaskUB");
2854 assert(LoadTaskStep !=
nullptr &&
"Expected value for LoadTaskStep");
2856 Builder.CreateSub(LoadTaskUB, LoadTaskLB), LoadTaskStep);
2857 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One,
"trip_cnt");
2858 Value *CastedTripCount =
Builder.CreateIntCast(TripCount, IVTy,
true);
2859 Value *CastedTaskLB =
Builder.CreateIntCast(LoadTaskLB, IVTy,
true);
2861 CLI->setTripCount(CastedTripCount);
2863 Builder.SetInsertPoint(CLI->getBody()->getFirstInsertionPt());
2865 if (NumOfCollapseLoops > 1) {
2871 Builder.CreateSub(CastedTaskLB, ConstantInt::get(IVTy, 1)));
2874 for (
auto IVUse = CLI->getIndVar()->uses().begin();
2875 IVUse != CLI->getIndVar()->uses().end(); IVUse++) {
2876 User *IVUser = IVUse->getUser();
2878 if (
Op->getOpcode() == Instruction::URem ||
2879 Op->getOpcode() == Instruction::UDiv) {
2884 for (User *User : UsersToReplace) {
2885 User->replaceUsesOfWith(CLI->getIndVar(), IVPlusTaskLB);
2902 assert(CLI->getIndVar()->getNumUses() == 3 &&
2903 "Canonical loop should have exactly three uses of the ind var");
2904 for (User *IVUser : CLI->getIndVar()->users()) {
2906 if (
Mul->getOpcode() == Instruction::Mul) {
2907 for (User *MulUser :
Mul->users()) {
2909 if (
Add->getOpcode() == Instruction::Add) {
2910 Add->setOperand(1, CastedTaskLB);
2919 FakeLB->replaceAllUsesWith(CastedLBVal);
2920 FakeUB->replaceAllUsesWith(CastedUBVal);
2921 FakeStep->replaceAllUsesWith(CastedStepVal);
2923 I->eraseFromParent();
2934 M.getContext(),
M.getDataLayout().getPointerSizeInBits());
2944 bool Mergeable,
Value *EventHandle,
Value *Priority,
bool FreeAgent) {
2975 if (
Error Err = BodyGenCB(TaskAllocaIP, TaskBodyIP, TaskExitBB))
2978 auto OI = std::make_unique<OutlineInfo>();
2979 OI->EntryBB = TaskAllocaBB;
2980 OI->OuterAllocBB = AllocaIP.getNodeParent();
2981 OI->ExitBB = TaskExitBB;
2982 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2983 copy(DeallocBlocks, OI->OuterDeallocBBs.
end());
2988 Builder, AllocaIP, ToBeDeleted, TaskAllocaIP,
"global.tid",
false));
2990 OI->PostOutlineCB = [
this, Ident, Tied, Final, IfCondition, Dependencies,
2991 Affinities, Mergeable, Priority, EventHandle, FreeAgent,
2993 ToBeDeleted](
Function &OutlinedFn)
mutable {
2995 assert(OutlinedFn.hasOneUse() &&
2996 "there must be a single user for the outlined function");
3001 bool HasShareds = StaleCI->
arg_size() > 1;
3002 Builder.SetInsertPoint(StaleCI);
3029 bool UseMergedIf0Path = ConstIfCondition && ConstIfCondition->isZero();
3033 Flags =
Builder.CreateOr(FinalFlag, Flags);
3036 if (Mergeable || UseMergedIf0Path)
3050 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
3059 assert(ArgStructAlloca &&
3060 "Unable to find the alloca instruction corresponding to arguments "
3061 "for extracted function");
3062 std::optional<TypeSize> ArgAllocSize =
3065 "Unable to determine size of arguments for extracted function");
3066 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
3072 TaskAllocFn, {Ident, ThreadID, Flags,
3073 TaskSize, SharedsSize,
3076 if (Affinities.
Count && Affinities.
Info) {
3078 OMPRTL___kmpc_omp_reg_task_with_affinity);
3089 OMPRTL___kmpc_task_allow_completion_event);
3093 Builder.CreatePointerBitCastOrAddrSpaceCast(EventHandle,
3095 EventVal =
Builder.CreatePtrToInt(EventVal,
Builder.getInt64Ty());
3096 Builder.CreateStore(EventVal, EventHandleAddr);
3102 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
3117 Constant *Zero = ConstantInt::get(Int32Ty, 0);
3121 Builder.CreateInBoundsGEP(TaskPtr, TaskData, {Zero, Zero});
3124 VoidPtr, VoidPtr,
Builder.getInt32Ty(), VoidPtr, VoidPtr);
3126 TaskStructType, TaskGEP, {Zero, ConstantInt::get(Int32Ty, 4)});
3129 Value *CmplrData =
Builder.CreateInBoundsGEP(CmplrStructType,
3130 PriorityData, {Zero, Zero});
3131 Builder.CreateStore(Priority, CmplrData);
3134 Value *DepArray =
nullptr;
3135 Value *NumDeps =
nullptr;
3138 NumDeps = Dependencies.
NumDeps;
3139 }
else if (!Dependencies.
Deps.empty()) {
3141 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
3161 if (IfCondition && !UseMergedIf0Path) {
3166 Builder.GetInsertPoint()->getParent()->getTerminator();
3167 Instruction *ThenTI = IfTerminator, *ElseTI =
nullptr;
3168 Builder.SetInsertPoint(IfTerminator);
3171 Builder.SetInsertPoint(ElseTI);
3178 {Ident, ThreadID, NumDeps, DepArray,
3179 ConstantInt::get(
Builder.getInt32Ty(), 0),
3194 Builder.SetInsertPoint(ThenTI);
3202 {Ident, ThreadID, TaskData, NumDeps, DepArray,
3203 ConstantInt::get(
Builder.getInt32Ty(), 0),
3216 LoadInst *Shareds =
Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
3217 OutlinedFn.getArg(1)->replaceUsesWithIf(
3218 Shareds, [Shareds](
Use &U) {
return U.getUser() != Shareds; });
3224 Builder.ClearInsertionPoint();
3226 I->eraseFromParent();
3252 if (
Error Err = BodyGenCB(AllocaIP,
Builder.saveIP(), DeallocBlocks))
3255 Builder.SetInsertPoint(TaskgroupExitBB);
3298 unsigned CaseNumber = 0;
3299 for (
auto SectionCB : SectionCBs) {
3301 M.getContext(),
"omp_section_loop.body.case", CurFn,
Continue);
3303 Builder.SetInsertPoint(CaseBB);
3316 Value *LB = ConstantInt::get(I32Ty, 0);
3317 Value *UB = ConstantInt::get(I32Ty, SectionCBs.
size());
3318 Value *ST = ConstantInt::get(I32Ty, 1);
3320 Loc, LoopBodyGenCB, LB, UB, ST,
true,
false, AllocaIP,
"section_loop");
3325 applyStaticWorkshareLoop(
Loc.DL, *
LoopInfo, AllocaIP,
3326 WorksharingLoopType::ForStaticLoop, !IsNowait);
3332 assert(LoopFini &&
"Bad structure of static workshare loop finalization");
3336 assert(FiniInfo.DK == OMPD_sections &&
3337 "Unexpected finalization stack state!");
3338 if (
Error Err = FiniInfo.mergeFiniBB(
Builder, LoopFini))
3352 if (IP != IP.getNodeParent()->end())
3363 auto *CaseBB =
Loc.IP.getNodeParent();
3364 auto *CondBB = CaseBB->getSinglePredecessor()->getSinglePredecessor();
3365 auto *ExitBB = CondBB->getTerminator()->getSuccessor(1);
3367 IP =
I->getIterator();
3371 Directive OMPD = Directive::OMPD_sections;
3374 return EmitOMPInlinedRegion(OMPD,
nullptr,
nullptr, BodyGenCB, FiniCBWrapper,
3385Value *OpenMPIRBuilder::getGPUThreadID() {
3388 OMPRTL___kmpc_get_hardware_thread_id_in_block),
3392Value *OpenMPIRBuilder::getGPUWarpSize() {
3397Value *OpenMPIRBuilder::getNVPTXWarpID() {
3398 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3399 return Builder.CreateAShr(getGPUThreadID(), LaneIDBits,
"nvptx_warp_id");
3402Value *OpenMPIRBuilder::getNVPTXLaneID() {
3403 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3404 assert(LaneIDBits < 32 &&
"Invalid LaneIDBits size in NVPTX device.");
3405 unsigned LaneIDMask = ~0
u >> (32u - LaneIDBits);
3406 return Builder.CreateAnd(getGPUThreadID(),
Builder.getInt32(LaneIDMask),
3413 uint64_t FromSize =
M.getDataLayout().getTypeStoreSize(FromType);
3414 uint64_t ToSize =
M.getDataLayout().getTypeStoreSize(ToType);
3415 assert(FromSize > 0 &&
"From size must be greater than zero");
3416 assert(ToSize > 0 &&
"To size must be greater than zero");
3417 if (FromType == ToType)
3419 if (FromSize == ToSize)
3420 return Builder.CreateBitCast(From, ToType);
3422 return Builder.CreateIntCast(From, ToType,
true);
3428 Value *ValCastItem =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3429 CastItem,
Builder.getPtrTy(0));
3430 Builder.CreateStore(From, ValCastItem);
3431 return Builder.CreateLoad(ToType, CastItem);
3438 uint64_t Size =
M.getDataLayout().getTypeStoreSize(ElementType);
3439 assert(
Size <= 8 &&
"Unsupported bitwidth in shuffle instruction");
3443 Value *ElemCast = castValueToType(AllocaIP, Element, CastTy);
3445 Builder.CreateIntCast(getGPUWarpSize(),
Builder.getInt16Ty(),
true);
3447 Size <= 4 ? RuntimeFunction::OMPRTL___kmpc_shuffle_int32
3448 : RuntimeFunction::OMPRTL___kmpc_shuffle_int64);
3449 Value *WarpSizeCast =
3451 Value *ShuffleCall =
3456 return castValueToType(AllocaIP, ShuffleCall, ElementType);
3463 uint64_t Size =
M.getDataLayout().getTypeStoreSize(ElemType);
3475 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3476 Value *ElemPtr = DstAddr;
3477 Value *Ptr = SrcAddr;
3478 for (
unsigned IntSize = 8; IntSize >= 1; IntSize /= 2) {
3482 Ptr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3485 Builder.CreateGEP(ElemType, SrcAddr, {ConstantInt::get(IndexTy, 1)});
3486 ElemPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3490 if ((
Size / IntSize) > 1) {
3491 Value *PtrEnd =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3492 SrcAddrGEP,
Builder.getPtrTy());
3509 Builder.CreatePointerBitCastOrAddrSpaceCast(Ptr,
Builder.getPtrTy()));
3511 Builder.CreateICmpSGT(PtrDiff,
Builder.getInt64(IntSize - 1)), ThenBB,
3514 Value *Res = createRuntimeShuffleFunction(
3517 IntType, Ptr,
M.getDataLayout().getPrefTypeAlign(ElemType)),
3519 Builder.CreateAlignedStore(Res, ElemPtr,
3520 M.getDataLayout().getPrefTypeAlign(ElemType));
3522 Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3523 Value *LocalElemPtr =
3524 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3532 Value *Res = createRuntimeShuffleFunction(
3533 AllocaIP,
Builder.CreateLoad(IntType, Ptr), IntType,
Offset);
3534 Builder.CreateStore(Res, ElemPtr);
3535 Ptr =
Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3537 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3543Error OpenMPIRBuilder::emitReductionListCopy(
3548 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3549 Value *RemoteLaneOffset = CopyOptions.RemoteLaneOffset;
3553 for (
auto En :
enumerate(ReductionInfos)) {
3555 Value *SrcElementAddr =
nullptr;
3556 AllocaInst *DestAlloca =
nullptr;
3557 Value *DestElementAddr =
nullptr;
3558 Value *DestElementPtrAddr =
nullptr;
3560 bool ShuffleInElement =
false;
3563 bool UpdateDestListPtr =
false;
3567 ReductionArrayTy, SrcBase,
3568 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3569 SrcElementAddr =
Builder.CreateLoad(
Builder.getPtrTy(), SrcElementPtrAddr);
3573 DestElementPtrAddr =
Builder.CreateInBoundsGEP(
3574 ReductionArrayTy, DestBase,
3575 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3576 bool IsByRefElem = (!IsByRef.
empty() && IsByRef[En.index()]);
3582 Type *DestAllocaType =
3583 IsByRefElem ? RI.ByRefAllocatedType : RI.ElementType;
3584 DestAlloca =
Builder.CreateAlloca(DestAllocaType,
nullptr,
3585 ".omp.reduction.element");
3587 M.getDataLayout().getPrefTypeAlign(DestAllocaType));
3588 DestElementAddr = DestAlloca;
3591 DestElementAddr->
getName() +
".ascast");
3593 ShuffleInElement =
true;
3594 UpdateDestListPtr =
true;
3606 if (ShuffleInElement) {
3607 Type *ShuffleType = RI.ElementType;
3608 Value *ShuffleSrcAddr = SrcElementAddr;
3609 Value *ShuffleDestAddr = DestElementAddr;
3610 AllocaInst *LocalStorage =
nullptr;
3613 assert(RI.ByRefElementType &&
"Expected by-ref element type to be set");
3614 assert(RI.ByRefAllocatedType &&
3615 "Expected by-ref allocated type to be set");
3620 ShuffleType = RI.ByRefElementType;
3622 if (RI.DataPtrPtrGen) {
3625 Builder.saveIP(), ShuffleSrcAddr, ShuffleSrcAddr);
3628 return GenResult.takeError();
3637 LocalStorage =
Builder.CreateAlloca(ShuffleType);
3639 ShuffleDestAddr = LocalStorage;
3644 ShuffleDestAddr = DestElementAddr;
3648 shuffleAndStore(AllocaIP, ShuffleSrcAddr, ShuffleDestAddr, ShuffleType,
3649 RemoteLaneOffset, ReductionArrayTy, IsByRefElem);
3651 if (IsByRefElem && RI.DataPtrPtrGen) {
3653 Value *DestDescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3654 DestAlloca,
Builder.getPtrTy(),
".ascast");
3657 DestDescriptorAddr, LocalStorage, SrcElementAddr,
3658 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
3661 return GenResult.takeError();
3664 switch (RI.EvaluationKind) {
3666 Value *Elem =
Builder.CreateLoad(RI.ElementType, SrcElementAddr);
3668 Builder.CreateStore(Elem, DestElementAddr);
3672 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3673 RI.ElementType, SrcElementAddr, 0, 0,
".realp");
3675 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
3677 RI.ElementType, SrcElementAddr, 0, 1,
".imagp");
3679 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
3681 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3682 RI.ElementType, DestElementAddr, 0, 0,
".realp");
3683 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
3684 RI.ElementType, DestElementAddr, 0, 1,
".imagp");
3685 Builder.CreateStore(SrcReal, DestRealPtr);
3686 Builder.CreateStore(SrcImg, DestImgPtr);
3691 M.getDataLayout().getTypeStoreSize(RI.ElementType));
3693 DestElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3694 SrcElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3706 if (UpdateDestListPtr) {
3707 Value *CastDestAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3708 DestElementAddr,
Builder.getPtrTy(),
3709 DestElementAddr->
getName() +
".ascast");
3710 Builder.CreateStore(CastDestAddr, DestElementPtrAddr);
3717Expected<Function *> OpenMPIRBuilder::emitInterWarpCopyFunction(
3720 IRBuilder<>::InsertPointGuard IPG(
Builder);
3721 LLVMContext &Ctx =
M.getContext();
3723 Builder.getVoidTy(), {Builder.getPtrTy(), Builder.getInt32Ty()},
3727 "_omp_reduction_inter_warp_copy_func", &
M);
3733 Builder.SetInsertPoint(EntryBB);
3751 StringRef TransferMediumName =
3752 "__openmp_nvptx_data_transfer_temporary_storage";
3753 GlobalVariable *TransferMedium =
M.getGlobalVariable(TransferMediumName);
3754 unsigned WarpSize =
Config.getGridValue().GV_Warp_Size;
3756 if (!TransferMedium) {
3757 TransferMedium =
new GlobalVariable(
3765 Value *GPUThreadID = getGPUThreadID();
3767 Value *LaneID = getNVPTXLaneID();
3769 Value *WarpID = getNVPTXWarpID();
3775 AllocaInst *ReduceListAlloca =
Builder.CreateAlloca(
3776 Arg0Type,
nullptr, ReduceListArg->
getName() +
".addr");
3777 AllocaInst *NumWarpsAlloca =
3778 Builder.CreateAlloca(Arg1Type,
nullptr, NumWarpsArg->
getName() +
".addr");
3779 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3780 ReduceListAlloca, Arg0Type, ReduceListAlloca->
getName() +
".ascast");
3781 Value *NumWarpsAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3782 NumWarpsAlloca,
Builder.getPtrTy(0),
3783 NumWarpsAlloca->
getName() +
".ascast");
3784 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
3785 Builder.CreateStore(NumWarpsArg, NumWarpsAddrCast);
3794 for (
auto En :
enumerate(ReductionInfos)) {
3800 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
3801 unsigned RealTySize =
M.getDataLayout().getTypeAllocSize(
3802 IsByRefElem ? RI.ByRefElementType : RI.ElementType);
3803 for (
unsigned TySize = 4; TySize > 0 && RealTySize > 0; TySize /= 2) {
3806 unsigned NumIters = RealTySize / TySize;
3809 Value *Cnt =
nullptr;
3810 Value *CntAddr =
nullptr;
3817 Builder.CreateAlloca(
Builder.getInt32Ty(),
nullptr,
".cnt.addr");
3819 CntAddr =
Builder.CreateAddrSpaceCast(CntAddr,
Builder.getPtrTy(),
3820 CntAddr->
getName() +
".ascast");
3832 Cnt, ConstantInt::get(
Builder.getInt32Ty(), NumIters));
3833 Builder.CreateCondBr(Cmp, BodyBB, ExitBB);
3840 omp::Directive::OMPD_unknown,
3844 return BarrierIP1.takeError();
3850 Value *IsWarpMaster =
Builder.CreateIsNull(LaneID,
"warp_master");
3851 Builder.CreateCondBr(IsWarpMaster, ThenBB, ElseBB);
3855 auto *RedListArrayTy =
3858 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3860 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3861 {ConstantInt::get(IndexTy, 0),
3862 ConstantInt::get(IndexTy, En.index())});
3866 if (IsByRefElem && RI.DataPtrPtrGen) {
3868 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
3871 return GenRes.takeError();
3882 ArrayTy, TransferMedium, {
Builder.getInt64(0), WarpID});
3887 Builder.CreateStore(Elem, MediumPtr,
3899 omp::Directive::OMPD_unknown,
3903 return BarrierIP2.takeError();
3910 Value *NumWarpsVal =
3913 Value *IsActiveThread =
3914 Builder.CreateICmpULT(GPUThreadID, NumWarpsVal,
"is_active_thread");
3915 Builder.CreateCondBr(IsActiveThread, W0ThenBB, W0ElseBB);
3922 ArrayTy, TransferMedium, {
Builder.getInt64(0), GPUThreadID});
3924 Value *TargetElemPtrPtr =
3925 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3926 {ConstantInt::get(IndexTy, 0),
3927 ConstantInt::get(IndexTy, En.index())});
3928 Value *TargetElemPtrVal =
3930 Value *TargetElemPtr = TargetElemPtrVal;
3932 if (IsByRefElem && RI.DataPtrPtrGen) {
3934 RI.DataPtrPtrGen(
Builder.saveIP(), TargetElemPtr, TargetElemPtr);
3937 return GenRes.takeError();
3939 TargetElemPtr =
Builder.CreateLoad(
Builder.getPtrTy(), TargetElemPtr);
3947 Value *SrcMediumValue =
3948 Builder.CreateLoad(CType, SrcMediumPtrVal,
true);
3949 Builder.CreateStore(SrcMediumValue, TargetElemPtr);
3959 Cnt, ConstantInt::get(
Builder.getInt32Ty(), 1));
3960 Builder.CreateStore(Cnt, CntAddr,
false);
3962 auto *CurFn =
Builder.GetInsertBlock()->getParent();
3966 RealTySize %= TySize;
3975Expected<Function *> OpenMPIRBuilder::emitShuffleAndReduceFunction(
3978 LLVMContext &Ctx =
M.getContext();
3979 IRBuilder<>::InsertPointGuard IPG(
Builder);
3980 FunctionType *FuncTy =
3982 {Builder.getPtrTy(), Builder.getInt16Ty(),
3983 Builder.getInt16Ty(), Builder.getInt16Ty()},
3987 "_omp_reduction_shuffle_and_reduce_func", &
M);
3998 Builder.SetInsertPoint(EntryBB);
4010 Type *ReduceListArgType = ReduceListArg->
getType();
4014 ReduceListArgType,
nullptr, ReduceListArg->
getName() +
".addr");
4015 Value *LaneIdAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
4016 LaneIDArg->
getName() +
".addr");
4018 LaneIDArgType,
nullptr, RemoteLaneOffsetArg->
getName() +
".addr");
4019 Value *AlgoVerAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
4020 AlgoVerArg->
getName() +
".addr");
4027 RedListArrayTy,
nullptr,
".omp.reduction.remote_reduce_list");
4029 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4030 ReduceListAlloca, ReduceListArgType,
4031 ReduceListAlloca->
getName() +
".ascast");
4032 Value *LaneIdAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4033 LaneIdAlloca, LaneIDArgPtrType, LaneIdAlloca->
getName() +
".ascast");
4034 Value *RemoteLaneOffsetAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4035 RemoteLaneOffsetAlloca, LaneIDArgPtrType,
4036 RemoteLaneOffsetAlloca->
getName() +
".ascast");
4037 Value *AlgoVerAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4038 AlgoVerAlloca, LaneIDArgPtrType, AlgoVerAlloca->
getName() +
".ascast");
4039 Value *RemoteListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4040 RemoteReductionListAlloca,
Builder.getPtrTy(),
4041 RemoteReductionListAlloca->
getName() +
".ascast");
4043 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
4044 Builder.CreateStore(LaneIDArg, LaneIdAddrCast);
4045 Builder.CreateStore(RemoteLaneOffsetArg, RemoteLaneOffsetAddrCast);
4046 Builder.CreateStore(AlgoVerArg, AlgoVerAddrCast);
4048 Value *ReduceList =
Builder.CreateLoad(ReduceListArgType, ReduceListAddrCast);
4049 Value *LaneId =
Builder.CreateLoad(LaneIDArgType, LaneIdAddrCast);
4050 Value *RemoteLaneOffset =
4051 Builder.CreateLoad(LaneIDArgType, RemoteLaneOffsetAddrCast);
4052 Value *AlgoVer =
Builder.CreateLoad(LaneIDArgType, AlgoVerAddrCast);
4059 Error EmitRedLsCpRes = emitReductionListCopy(
4061 ReduceList, RemoteListAddrCast, IsByRef,
4062 {RemoteLaneOffset,
nullptr,
nullptr});
4065 return EmitRedLsCpRes;
4090 Value *LaneComp =
Builder.CreateICmpULT(LaneId, RemoteLaneOffset);
4095 Value *Algo2AndLaneIdComp =
Builder.CreateAnd(Algo2, LaneIdComp);
4096 Value *RemoteOffsetComp =
4098 Value *CondAlgo2 =
Builder.CreateAnd(Algo2AndLaneIdComp, RemoteOffsetComp);
4099 Value *CA0OrCA1 =
Builder.CreateOr(CondAlgo0, CondAlgo1);
4100 Value *CondReduce =
Builder.CreateOr(CA0OrCA1, CondAlgo2);
4106 Builder.CreateCondBr(CondReduce, ThenBB, ElseBB);
4108 Value *LocalReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4109 ReduceList,
Builder.getPtrTy());
4110 Value *RemoteReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4111 RemoteListAddrCast,
Builder.getPtrTy());
4113 ->addFnAttr(Attribute::NoUnwind);
4124 Value *LaneIdGtOffset =
Builder.CreateICmpUGE(LaneId, RemoteLaneOffset);
4125 Value *CondCopy =
Builder.CreateAnd(Algo1, LaneIdGtOffset);
4130 Builder.CreateCondBr(CondCopy, CpyThenBB, CpyElseBB);
4134 EmitRedLsCpRes = emitReductionListCopy(
4136 RemoteListAddrCast, ReduceList, IsByRef);
4139 return EmitRedLsCpRes;
4154OpenMPIRBuilder::generateReductionDescriptor(
4156 Type *DescriptorType,
4162 Value *DescriptorSize =
4163 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(DescriptorType));
4165 DescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4166 SrcDescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4170 Value *DataPtrField;
4172 DataPtrPtrGen(
Builder.saveIP(), DescriptorAddr, DataPtrField);
4175 return GenResult.takeError();
4178 DataPtr,
Builder.getPtrTy(),
".ascast"),
4184Expected<Value *> OpenMPIRBuilder::createReductionDescriptorCopy(
4186 Value *SrcDescriptorAddr,
Type *DescriptorPtrTy,
const Twine &Name) {
4190 AllocaInst *DescriptorAlloca =
4191 Builder.CreateAlloca(RI.ByRefAllocatedType,
nullptr, Name);
4193 M.getDataLayout().getPrefTypeAlign(RI.ByRefAllocatedType));
4194 Value *DescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4195 DescriptorAlloca, DescriptorPtrTy,
4196 DescriptorAlloca->
getName() +
".ascast");
4201 generateReductionDescriptor(DescriptorAddr, DataPtr, SrcDescriptorAddr,
4202 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
4204 return GenResult.takeError();
4206 return DescriptorAddr;
4209Expected<Function *> OpenMPIRBuilder::emitListToGlobalCopyFunction(
4212 IRBuilder<>::InsertPointGuard IPG(
Builder);
4213 LLVMContext &Ctx =
M.getContext();
4216 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4220 "_omp_reduction_list_to_global_copy_func", &
M);
4227 Builder.SetInsertPoint(EntryBlock);
4238 BufferArg->
getName() +
".addr");
4242 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4243 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4244 BufferArgAlloca,
Builder.getPtrTy(),
4245 BufferArgAlloca->
getName() +
".ascast");
4246 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4247 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4248 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4249 ReduceListArgAlloca,
Builder.getPtrTy(),
4250 ReduceListArgAlloca->
getName() +
".ascast");
4252 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4253 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4254 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4256 Value *LocalReduceList =
4258 Value *BufferArgVal =
4262 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4263 for (
auto En :
enumerate(ReductionInfos)) {
4265 auto *RedListArrayTy =
4269 RedListArrayTy, LocalReduceList,
4270 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4276 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferArgVal, Idxs);
4278 ReductionsBufferTy, BufferVD, 0, En.index());
4280 switch (RI.EvaluationKind) {
4282 Value *TargetElement;
4284 if (IsByRef.
empty() || !IsByRef[En.index()]) {
4285 TargetElement =
Builder.CreateLoad(RI.ElementType, ElemPtr);
4287 if (RI.DataPtrPtrGen) {
4289 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
4292 return GenResult.takeError();
4296 TargetElement =
Builder.CreateLoad(RI.ByRefElementType, ElemPtr);
4299 Builder.CreateStore(TargetElement, GlobVal);
4303 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4304 RI.ElementType, ElemPtr, 0, 0,
".realp");
4306 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
4308 RI.ElementType, ElemPtr, 0, 1,
".imagp");
4310 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
4312 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4313 RI.ElementType, GlobVal, 0, 0,
".realp");
4314 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4315 RI.ElementType, GlobVal, 0, 1,
".imagp");
4316 Builder.CreateStore(SrcReal, DestRealPtr);
4317 Builder.CreateStore(SrcImg, DestImgPtr);
4322 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(RI.ElementType));
4324 GlobVal,
M.getDataLayout().getPrefTypeAlign(RI.ElementType), ElemPtr,
4325 M.getDataLayout().getPrefTypeAlign(RI.ElementType), SizeVal,
false);
4335Expected<Function *> OpenMPIRBuilder::emitListToGlobalReduceFunction(
4338 IRBuilder<>::InsertPointGuard IPG(
Builder);
4339 LLVMContext &Ctx =
M.getContext();
4342 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4346 "_omp_reduction_list_to_global_reduce_func", &
M);
4353 Builder.SetInsertPoint(EntryBlock);
4364 BufferArg->
getName() +
".addr");
4368 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4369 auto *RedListArrayTy =
4374 Value *LocalReduceList =
4375 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4379 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4380 BufferArgAlloca,
Builder.getPtrTy(),
4381 BufferArgAlloca->
getName() +
".ascast");
4382 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4383 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4384 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4385 ReduceListArgAlloca,
Builder.getPtrTy(),
4386 ReduceListArgAlloca->
getName() +
".ascast");
4387 Value *LocalReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4388 LocalReduceList,
Builder.getPtrTy(),
4389 LocalReduceList->
getName() +
".ascast");
4391 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4392 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4393 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4398 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4399 for (
auto En :
enumerate(ReductionInfos)) {
4402 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4403 RedListArrayTy, LocalReduceListAddrCast,
4404 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4406 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4408 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4409 ReductionsBufferTy, BufferVD, 0, En.index());
4411 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4415 Value *SrcElementPtrPtr =
4416 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
4417 {ConstantInt::get(IndexTy, 0),
4418 ConstantInt::get(IndexTy, En.index())});
4419 Value *SrcDescriptorAddr =
4423 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4424 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4428 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4430 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4438 ->addFnAttr(Attribute::NoUnwind);
4443Expected<Function *> OpenMPIRBuilder::emitGlobalToListCopyFunction(
4446 IRBuilder<>::InsertPointGuard IPG(
Builder);
4447 LLVMContext &Ctx =
M.getContext();
4450 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4454 "_omp_reduction_global_to_list_copy_func", &
M);
4461 Builder.SetInsertPoint(EntryBlock);
4472 BufferArg->
getName() +
".addr");
4476 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4477 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4478 BufferArgAlloca,
Builder.getPtrTy(),
4479 BufferArgAlloca->
getName() +
".ascast");
4480 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4481 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4482 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4483 ReduceListArgAlloca,
Builder.getPtrTy(),
4484 ReduceListArgAlloca->
getName() +
".ascast");
4485 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4486 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4487 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4489 Value *LocalReduceList =
4494 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4495 for (
auto En :
enumerate(ReductionInfos)) {
4496 const OpenMPIRBuilder::ReductionInfo &RI = En.value();
4497 auto *RedListArrayTy =
4501 RedListArrayTy, LocalReduceList,
4502 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4507 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4508 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4509 ReductionsBufferTy, BufferVD, 0, En.index());
4515 if (!IsByRef.
empty() && IsByRef[En.index()]) {
4522 return GenResult.takeError();
4528 Value *TargetElement =
Builder.CreateLoad(ElemType, GlobValPtr);
4529 Builder.CreateStore(TargetElement, ElemPtr);
4533 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4542 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4544 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4546 Builder.CreateStore(SrcReal, DestRealPtr);
4547 Builder.CreateStore(SrcImg, DestImgPtr);
4554 ElemPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4555 GlobValPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4566Expected<Function *> OpenMPIRBuilder::emitGlobalToListReduceFunction(
4569 IRBuilder<>::InsertPointGuard IPG(
Builder);
4570 LLVMContext &Ctx =
M.getContext();
4573 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4577 "_omp_reduction_global_to_list_reduce_func", &
M);
4584 Builder.SetInsertPoint(EntryBlock);
4595 BufferArg->
getName() +
".addr");
4599 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4605 Value *LocalReduceList =
4606 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4610 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4611 BufferArgAlloca,
Builder.getPtrTy(),
4612 BufferArgAlloca->
getName() +
".ascast");
4613 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4614 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4615 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4616 ReduceListArgAlloca,
Builder.getPtrTy(),
4617 ReduceListArgAlloca->
getName() +
".ascast");
4618 Value *ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4619 LocalReduceList,
Builder.getPtrTy(),
4620 LocalReduceList->
getName() +
".ascast");
4622 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4623 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4624 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4629 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4630 for (
auto En :
enumerate(ReductionInfos)) {
4633 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4634 RedListArrayTy, ReductionList,
4635 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4638 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4639 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4640 ReductionsBufferTy, BufferVD, 0, En.index());
4642 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4644 Value *ReduceListVal =
4646 Value *SrcElementPtrPtr =
4647 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceListVal,
4648 {ConstantInt::get(IndexTy, 0),
4649 ConstantInt::get(IndexTy, En.index())});
4650 Value *SrcDescriptorAddr =
4654 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4655 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4659 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4661 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4669 ->addFnAttr(Attribute::NoUnwind);
4674std::string OpenMPIRBuilder::getReductionFuncName(StringRef Name)
const {
4675 std::string Suffix =
4677 return (Name + Suffix).str();
4680Expected<Function *> OpenMPIRBuilder::createReductionFunction(
4683 AttributeList FuncAttrs) {
4684 IRBuilder<>::InsertPointGuard IPG(
Builder);
4686 {Builder.getPtrTy(), Builder.getPtrTy()},
4688 std::string
Name = getReductionFuncName(ReducerName);
4697 Builder.SetInsertPoint(EntryBB);
4702 Value *LHSArrayPtr =
nullptr;
4703 Value *RHSArrayPtr =
nullptr;
4710 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
4712 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
4713 Value *LHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4714 LHSAlloca, Arg0Type, LHSAlloca->
getName() +
".ascast");
4715 Value *RHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4716 RHSAlloca, Arg1Type, RHSAlloca->
getName() +
".ascast");
4717 Builder.CreateStore(Arg0, LHSAddrCast);
4718 Builder.CreateStore(Arg1, RHSAddrCast);
4719 LHSArrayPtr =
Builder.CreateLoad(Arg0Type, LHSAddrCast);
4720 RHSArrayPtr =
Builder.CreateLoad(Arg1Type, RHSAddrCast);
4724 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4726 for (
auto En :
enumerate(ReductionInfos)) {
4729 RedArrayTy, RHSArrayPtr,
4730 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4732 Value *RHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4733 RHSI8Ptr, RI.PrivateVariable->getType(),
4734 RHSI8Ptr->
getName() +
".ascast");
4737 RedArrayTy, LHSArrayPtr,
4738 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4740 Value *LHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4741 LHSI8Ptr, RI.Variable->getType(), LHSI8Ptr->
getName() +
".ascast");
4750 if (!IsByRef.
empty() && !IsByRef[En.index()]) {
4751 LHS =
Builder.CreateLoad(RI.ElementType, LHSPtr);
4752 RHS =
Builder.CreateLoad(RI.ElementType, RHSPtr);
4759 return AfterIP.takeError();
4760 if (!
Builder.GetInsertBlock())
4761 return ReductionFunc;
4765 if (!IsByRef.
empty() && !IsByRef[En.index()])
4766 Builder.CreateStore(Reduced, LHSPtr);
4771 for (
auto En :
enumerate(ReductionInfos)) {
4772 unsigned Index = En.index();
4774 Value *LHSFixupPtr, *RHSFixupPtr;
4775 Builder.restoreIP(RI.ReductionGenClang(
4776 Builder.saveIP(), Index, &LHSFixupPtr, &RHSFixupPtr, ReductionFunc));
4781 LHSPtrs[Index], [ReductionFunc](
const Use &U) {
4786 RHSPtrs[Index], [ReductionFunc](
const Use &U) {
4800 return ReductionFunc;
4808 assert(RI.Variable &&
"expected non-null variable");
4809 assert(RI.PrivateVariable &&
"expected non-null private variable");
4810 assert((RI.ReductionGen || RI.ReductionGenClang) &&
4811 "expected non-null reduction generator callback");
4814 RI.Variable->getType() == RI.PrivateVariable->getType() &&
4815 "expected variables and their private equivalents to have the same "
4818 assert(RI.Variable->getType()->isPointerTy() &&
4819 "expected variables to be pointers");
4836 ArrayRef<bool> IsByRef,
bool IsNoWait,
bool IsTeamsReduction,
bool IsSPMD,
4838 Value *SrcLocInfo) {
4853 if (ReductionInfos.
size() == 0)
4867 AttrBuilder AttrBldr(Ctx);
4869 AttrBldr.addAttribute(Attr);
4870 AttrBldr.removeAttribute(Attribute::OptimizeNone);
4871 FuncAttrs = FuncAttrs.addFnAttributes(Ctx, AttrBldr);
4874 Builder.GetInsertBlock()->getParent()->getName(), ReductionInfos, IsByRef,
4876 if (!ReductionResult)
4878 Function *ReductionFunc = *ReductionResult;
4881 if (GridValue.has_value())
4882 Config.setGridValue(GridValue.value());
4897 Builder.getPtrTy(
M.getDataLayout().getProgramAddressSpace());
4899 Value *ReductionList;
4903 Value *ReductionListAlloca =
4904 Builder.CreateAlloca(RedArrayTy,
nullptr,
".omp.reduction.red_list");
4905 ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4906 ReductionListAlloca, PtrTy, ReductionListAlloca->
getName() +
".ascast");
4909 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4910 for (
auto En :
enumerate(ReductionInfos)) {
4913 RedArrayTy, ReductionList,
4914 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4917 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
4922 Builder.CreatePointerBitCastOrAddrSpaceCast(PrivateVar, PtrTy);
4923 Builder.CreateStore(CastElem, ElemPtr);
4926 ReductionInfos, ReductionFunc, FuncAttrs, IsByRef);
4932 emitInterWarpCopyFunction(
Loc, ReductionInfos, FuncAttrs, IsByRef);
4937 Value *RL =
Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList, PtrTy);
4946 unsigned MaxDataSize = 0;
4948 for (
auto En :
enumerate(ReductionInfos)) {
4952 Type *RedTypeArg = (!IsByRef.
empty() && IsByRef[En.index()])
4953 ? En.value().ByRefElementType
4954 : En.value().ElementType;
4955 auto Size =
M.getDataLayout().getTypeStoreSize(RedTypeArg);
4956 if (
Size > MaxDataSize)
4960 Value *ReductionDataSize =
4961 Builder.getInt64(MaxDataSize * ReductionInfos.
size());
4965 Function *CopyScratchToListFunc =
nullptr;
4967 Value *ScratchForCopyBack =
nullptr;
4970 Value *RLForCopyBack = RL;
4972 bool IsAtomicReduction =
4975 if (!IsTeamsReduction) {
4976 Value *SarFuncCast =
4977 Builder.CreatePointerBitCastOrAddrSpaceCast(*SarFunc, FuncPtrTy);
4979 Builder.CreatePointerBitCastOrAddrSpaceCast(WcFunc, FuncPtrTy);
4980 Value *Args[] = {SrcLocInfo, ReductionDataSize, RL, SarFuncCast,
4983 RuntimeFunction::OMPRTL___kmpc_nvptx_parallel_reduce_nowait_v2);
4985 }
else if (IsAtomicReduction) {
4989 RuntimeFunction::OMPRTL___kmpc_is_team_main_thread);
4993 Ctx, ReductionTypeArgs,
"struct._globalized_locals_ty");
4996 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
5001 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
5006 ReductionInfos, ReductionFunc, ReductionsBufferTy, FuncAttrs, IsByRef);
5027 Value *RuntimeRL = RL;
5030 Value *PerThreadScratch;
5036 Value *PerThreadScratchAlloca =
5037 Builder.CreateAlloca(ReductionsBufferTy,
nullptr,
5038 ".omp.reduction.scratch");
5039 PerThreadScratch =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5040 PerThreadScratchAlloca, PtrTy,
5041 PerThreadScratchAlloca->
getName() +
".ascast");
5044 Value *PerThreadRedListAlloca =
5045 Builder.CreateAlloca(RedArrayTy,
nullptr,
5046 ".omp.reduction.per_thread_red_list");
5047 RuntimeRL =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5048 PerThreadRedListAlloca, PtrTy,
5049 PerThreadRedListAlloca->
getName() +
".ascast");
5054 for (
auto En :
enumerate(ReductionInfos)) {
5056 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
5059 ReductionsBufferTy, PerThreadScratch, 0, En.index());
5060 Value *Slot =
Builder.CreateConstInBoundsGEP2_32(RedArrayTy, RuntimeRL,
5063 Value *RuntimeListEntry = FieldPtr;
5065 Value *SrcDescriptor =
5068 AllocaIP, RI, FieldPtr, SrcDescriptor, PtrTy);
5071 RuntimeListEntry = *Descriptor;
5073 Builder.CreateStore(RuntimeListEntry, Slot);
5079 Type *CopyArg0Ty = (*LtGCFunc)->getFunctionType()->getParamType(0);
5080 Type *CopyArg2Ty = (*LtGCFunc)->getFunctionType()->getParamType(2);
5081 ScratchForCopyBack =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5082 PerThreadScratch, CopyArg0Ty);
5084 Builder.CreatePointerBitCastOrAddrSpaceCast(RL, CopyArg2Ty);
5092 *LtGCFunc, {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
5093 CopyScratchToListFunc = *GtLCFunc;
5096 Value *Args3[] = {SrcLocInfo, RuntimeRL, *SarFunc, WcFunc,
5097 *LtGCFunc, *GtLCFunc, *GtLRFunc};
5100 RuntimeFunction::OMPRTL___kmpc_gpu_xteam_reduce_nowait);
5120 if (ScratchForCopyBack) {
5123 CopyScratchToListFunc,
5124 {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
5128 for (
auto En :
enumerate(ReductionInfos)) {
5134 if (IsAtomicReduction) {
5150 Value *LHSPtr, *RHSPtr;
5152 &LHSPtr, &RHSPtr, CurFunc));
5158 RedValue =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5160 if (RHSPtr->
getType() != RHS->getType())
5162 Builder.CreatePointerBitCastOrAddrSpaceCast(RHS, RHSPtr->
getType());
5173 if (IsByRef.
empty() || !IsByRef[En.index()]) {
5175 "red.value." +
Twine(En.index()));
5186 if (!IsByRef.
empty() && !IsByRef[En.index()])
5191 if (ContinuationBlock) {
5192 Builder.CreateBr(ContinuationBlock);
5193 Builder.SetInsertPoint(ContinuationBlock);
5195 Config.setEmitLLVMUsed();
5206 ".omp.reduction.func", &M);
5217 Builder.SetInsertPoint(ReductionFuncBlock);
5219 Value *LHSArrayPtr =
nullptr;
5220 Value *RHSArrayPtr =
nullptr;
5231 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
5233 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
5234 Value *LHSAddrCast =
5235 Builder.CreatePointerBitCastOrAddrSpaceCast(LHSAlloca, Arg0Type);
5236 Value *RHSAddrCast =
5237 Builder.CreatePointerBitCastOrAddrSpaceCast(RHSAlloca, Arg1Type);
5238 Builder.CreateStore(Arg0, LHSAddrCast);
5239 Builder.CreateStore(Arg1, RHSAddrCast);
5240 LHSArrayPtr = Builder.CreateLoad(Arg0Type, LHSAddrCast);
5241 RHSArrayPtr = Builder.CreateLoad(Arg1Type, RHSAddrCast);
5243 LHSArrayPtr = ReductionFunc->
getArg(0);
5244 RHSArrayPtr = ReductionFunc->
getArg(1);
5247 unsigned NumReductions = ReductionInfos.
size();
5250 for (
auto En :
enumerate(ReductionInfos)) {
5252 Value *LHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5253 RedArrayTy, LHSArrayPtr, 0, En.index());
5254 Value *LHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), LHSI8PtrPtr);
5255 Value *LHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5258 Value *RHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5259 RedArrayTy, RHSArrayPtr, 0, En.index());
5260 Value *RHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), RHSI8PtrPtr);
5261 Value *RHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5270 Builder.restoreIP(*AfterIP);
5272 if (!Builder.GetInsertBlock())
5276 if (!IsByRef[En.index()])
5277 Builder.CreateStore(Reduced, LHSPtr);
5279 Builder.CreateRetVoid();
5286 bool IsNoWait,
bool IsTeamsReduction) {
5290 IsByRef, IsNoWait, IsTeamsReduction);
5297 if (ReductionInfos.
size() == 0)
5307 unsigned NumReductions = ReductionInfos.
size();
5309 Builder.SetInsertPoint(AllocaIP.getNodeParent()->getTerminator());
5310 Value *RedArray =
Builder.CreateAlloca(RedArrayTy,
nullptr,
"red.array");
5317 for (
auto En :
enumerate(ReductionInfos)) {
5318 unsigned Index = En.index();
5320 Value *RedArrayElemPtr =
Builder.CreateConstInBoundsGEP2_64(
5321 RedArrayTy, RedArray, 0, Index,
"red.array.elem." +
Twine(Index));
5328 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
5338 ? IdentFlag::OMP_IDENT_FLAG_ATOMIC_REDUCE
5343 unsigned RedArrayByteSize =
DL.getTypeStoreSize(RedArrayTy);
5344 Constant *RedArraySize = ConstantInt::get(IndexTy, RedArrayByteSize);
5346 Value *Lock = getOMPCriticalRegionLock(
".reduction");
5348 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_reduce_nowait
5349 : RuntimeFunction::OMPRTL___kmpc_reduce);
5352 {Ident, ThreadId, NumVariables, RedArraySize,
5353 RedArray, ReductionFunc, Lock},
5364 Builder.CreateSwitch(ReduceCall, ContinuationBlock, 2);
5365 Switch->addCase(
Builder.getInt32(1), NonAtomicRedBlock);
5366 Switch->addCase(
Builder.getInt32(2), AtomicRedBlock);
5371 Builder.SetInsertPoint(NonAtomicRedBlock);
5372 for (
auto En :
enumerate(ReductionInfos)) {
5378 if (!IsByRef[En.index()]) {
5380 "red.value." +
Twine(En.index()));
5382 Value *PrivateRedValue =
5384 "red.private.value." +
Twine(En.index()));
5392 if (!
Builder.GetInsertBlock())
5395 if (!IsByRef[En.index()])
5399 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_end_reduce_nowait
5400 : RuntimeFunction::OMPRTL___kmpc_end_reduce);
5402 Builder.CreateBr(ContinuationBlock);
5407 Builder.SetInsertPoint(AtomicRedBlock);
5408 if (CanGenerateAtomic &&
llvm::none_of(IsByRef, [](
bool P) {
return P; })) {
5415 if (!
Builder.GetInsertBlock())
5418 Builder.CreateBr(ContinuationBlock);
5431 if (!
Builder.GetInsertBlock())
5434 Builder.SetInsertPoint(ContinuationBlock);
5445 Directive OMPD = Directive::OMPD_master;
5450 Value *Args[] = {Ident, ThreadId};
5458 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5470 Directive OMPD = Directive::OMPD_masked;
5476 Value *ArgsEnd[] = {Ident, ThreadId};
5484 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5494 Call->setDoesNotThrow();
5509 bool IsInclusive,
ScanInfo *ScanRedInfo) {
5511 llvm::Error Err = emitScanBasedDirectiveDeclsIR(AllocaIP, ScanVars,
5512 ScanVarsType, ScanRedInfo);
5523 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5526 Type *DestTy = ScanVarsType[i];
5527 Value *Val =
Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5530 Builder.CreateStore(Src, Val);
5535 Builder.GetInsertBlock()->getParent());
5538 IV = ScanRedInfo->
IV;
5541 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5544 Type *DestTy = ScanVarsType[i];
5546 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5548 Builder.CreateStore(Src, ScanVars[i]);
5562 Builder.GetInsertBlock()->getParent());
5567Error OpenMPIRBuilder::emitScanBasedDirectiveDeclsIR(
5571 Builder.restoreIP(AllocaIP);
5573 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5575 Builder.CreateAlloca(Builder.getPtrTy(),
nullptr,
"vla");
5582 Builder.restoreIP(CodeGenIP);
5584 Builder.CreateAdd(ScanRedInfo->
Span, Builder.getInt32(1));
5585 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5587 Value *Allocsize = Builder.CreateTypeSize(
5588 IntPtrTy, M.getDataLayout().getTypeAllocSize(ScanVarsType[i]));
5590 Builder.CreateMalloc(
IntPtrTy, Allocsize, AllocSpan,
nullptr,
"arr");
5591 Builder.CreateStore(Buff, (*(ScanRedInfo->
ScanBuffPtrs))[ScanVars[i]]);
5618Error OpenMPIRBuilder::emitScanBasedDirectiveFinalsIR(
5624 Value *PrivateVar = RedInfo.PrivateVariable;
5625 Value *OrigVar = RedInfo.Variable;
5629 Type *SrcTy = RedInfo.ElementType;
5634 Builder.CreateStore(Src, OrigVar);
5695 llvm::ConstantInt::get(ScanRedInfo->
Span->
getType(), 1));
5696 Builder.SetInsertPoint(InputBB);
5699 Builder.SetInsertPoint(LoopBB);
5715 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5717 Builder.SetInsertPoint(InnerLoopBB);
5721 Value *ReductionVal = RedInfo.PrivateVariable;
5724 Type *DestTy = RedInfo.ElementType;
5727 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5730 Builder.CreateInBoundsGEP(DestTy, Buff, OffsetIval,
"arrayOffset");
5735 RedInfo.ReductionGen(
Builder.saveIP(), LHS, RHS, Result);
5738 Builder.CreateStore(Result, LHSPtr);
5741 IVal, llvm::ConstantInt::get(
Builder.getInt32Ty(), 1));
5743 CmpI =
Builder.CreateICmpUGE(NextIVal, Pow2K);
5744 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5747 Counter, llvm::ConstantInt::get(Counter->
getType(), 1));
5753 Builder.CreateCondBr(Cmp, LoopBB, ExitBB);
5774 Error Err = emitScanBasedDirectiveFinalsIR(ReductionInfos, ScanRedInfo);
5781Error OpenMPIRBuilder::emitScanBasedDirectiveIR(
5793 Error Err = InputLoopGen();
5804 Error Err = ScanLoopGen(Builder);
5811void OpenMPIRBuilder::createScanBBs(ScanInfo *ScanRedInfo) {
5848 Builder.SetInsertPoint(Preheader);
5851 Builder.SetInsertPoint(Header);
5852 PHINode *IndVarPHI =
Builder.CreatePHI(IndVarTy, 2,
"omp_" + Name +
".iv");
5853 IndVarPHI->
addIncoming(ConstantInt::get(IndVarTy, 0), Preheader);
5858 Builder.CreateICmpULT(IndVarPHI, TripCount,
"omp_" + Name +
".cmp");
5859 Builder.CreateCondBr(Cmp, Body, Exit);
5864 Builder.SetInsertPoint(Latch);
5874 bool HasNSW =
Config.hasNoSignedWrap();
5877 unsigned BitWidth = CI->getType()->getIntegerBitWidth();
5879 if (CI->getValue().ugt(SignedMax))
5881 }
else if (IsCollapsed) {
5886 Builder.CreateAdd(IndVarPHI, ConstantInt::get(IndVarTy, 1),
5887 "omp_" + Name +
".next",
true, HasNSW);
5898 CL->Header = Header;
5917 NextBB, NextBB, Name);
5949 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
5958 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
5959 ScanRedInfo->
Span = TripCount;
5965 ScanRedInfo->
IV =
IV;
5966 createScanBBs(ScanRedInfo);
5969 assert(Terminator->getNumSuccessors() == 1);
5970 BasicBlock *ContinueBlock = Terminator->getSuccessor(0);
5973 Builder.GetInsertBlock()->getParent());
5976 Builder.GetInsertBlock()->getParent());
5977 Builder.CreateBr(ContinueBlock);
5983 const auto &&InputLoopGen = [&]() ->
Error {
5986 InclusiveStop, ComputeIP, Name,
true, ScanRedInfo);
5990 Builder.restoreIP((*LoopInfo)->getAfterIP());
5996 InclusiveStop, ComputeIP, Name,
true, ScanRedInfo);
6000 Builder.restoreIP((*LoopInfo)->getAfterIP());
6004 Error Err = emitScanBasedDirectiveIR(InputLoopGen, ScanLoopGen, ScanRedInfo);
6012 bool IsSigned,
bool InclusiveStop,
const Twine &Name) {
6022 assert(IndVarTy == Stop->
getType() &&
"Stop type mismatch");
6023 assert(IndVarTy == Step->
getType() &&
"Step type mismatch");
6027 ConstantInt *Zero = ConstantInt::get(IndVarTy, 0);
6043 Incr =
Builder.CreateSelect(IsNeg,
Builder.CreateNeg(Step), Step);
6046 Span =
Builder.CreateSub(UB, LB,
"",
false,
true);
6050 Span =
Builder.CreateSub(Stop, Start,
"",
true);
6055 Value *CountIfLooping;
6056 if (InclusiveStop) {
6057 CountIfLooping =
Builder.CreateAdd(
Builder.CreateUDiv(Span, Incr), One);
6063 CountIfLooping =
Builder.CreateSelect(OneCmp, One, CountIfTwo);
6066 return Builder.CreateSelect(ZeroCmp, Zero, CountIfLooping,
6067 "omp_" + Name +
".tripcount");
6072 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
6079 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
6084 Config.hasNoSignedWrap());
6085 Value *IndVar =
Builder.CreateAdd(Span, Start,
"",
false,
6086 Config.hasNoSignedWrap());
6088 ScanRedInfo->
IV = IndVar;
6089 return BodyGenCB(
Builder.saveIP(), IndVar);
6095 Builder.getCurrentDebugLocation());
6106 unsigned Bitwidth = Ty->getIntegerBitWidth();
6109 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_4u);
6112 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_8u);
6122 unsigned Bitwidth = Ty->getIntegerBitWidth();
6125 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_4u);
6128 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_8u);
6136 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6138 "Require dedicated allocate IP");
6144 uint32_t SrcLocStrSize;
6148 case WorksharingLoopType::ForStaticLoop:
6149 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6151 case WorksharingLoopType::DistributeStaticLoop:
6152 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6154 case WorksharingLoopType::DistributeForStaticLoop:
6155 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
6162 Type *IVTy =
IV->getType();
6163 FunctionCallee StaticInit =
6164 LoopType == WorksharingLoopType::DistributeForStaticLoop
6167 FunctionCallee StaticFini =
6171 Builder.SetInsertPoint(AllocaIP.getNodeParent()->getFirstNonPHIOrAlloca());
6174 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6175 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
6176 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
6177 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
6186 Constant *One = ConstantInt::get(IVTy, 1);
6187 Builder.CreateStore(Zero, PLowerBound);
6189 Builder.CreateStore(UpperBound, PUpperBound);
6190 Builder.CreateStore(One, PStride);
6196 (LoopType == WorksharingLoopType::DistributeStaticLoop)
6197 ? OMPScheduleType::OrderedDistribute
6200 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6204 auto BuildInitCall = [LoopType, SrcLoc, ThreadNum, PLastIter, PLowerBound,
6205 PUpperBound, IVTy, PStride, One,
Zero, StaticInit,
6208 PLowerBound, PUpperBound});
6209 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
6210 Value *PDistUpperBound =
6211 Builder.CreateAlloca(IVTy,
nullptr,
"p.distupperbound");
6212 Args.push_back(PDistUpperBound);
6217 BuildInitCall(SchedulingType,
Builder);
6218 if (HasDistSchedule &&
6219 LoopType != WorksharingLoopType::DistributeStaticLoop) {
6220 Constant *DistScheduleSchedType = ConstantInt::get(
6225 BuildInitCall(DistScheduleSchedType,
Builder);
6228 Value *InclusiveUpperBound =
Builder.CreateLoad(IVTy, PUpperBound);
6230 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One);
6231 CLI->setTripCount(TripCount);
6237 CLI->mapIndVar([&](Instruction *OldIV) ->
Value * {
6241 Config.hasNoSignedWrap());
6252 omp::Directive::OMPD_for,
false,
6255 return BarrierIP.takeError();
6282 Reachable.insert(
Block);
6296OpenMPIRBuilder::applyStaticChunkedWorkshareLoop(
6300 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6301 assert((ChunkSize || DistScheduleChunkSize) &&
"Chunk size is required");
6306 Type *IVTy =
IV->getType();
6308 "Max supported tripcount bitwidth is 64 bits");
6310 :
Type::getInt64Ty(Ctx);
6313 Constant *One = ConstantInt::get(InternalIVTy, 1);
6318 SmallVector<Instruction *> UIs;
6319 for (BasicBlock &BB : *
F)
6320 if (!BB.hasTerminator())
6321 UIs.
push_back(
new UnreachableInst(
F->getContext(), &BB));
6326 LoopInfo &&LI = LIA.
run(*
F,
FAM);
6327 for (Instruction *
I : UIs)
6328 I->eraseFromParent();
6331 if (ChunkSize || DistScheduleChunkSize)
6336 FunctionCallee StaticInit =
6338 FunctionCallee StaticFini =
6344 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6345 Value *PLowerBound =
6346 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.lowerbound");
6347 Value *PUpperBound =
6348 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.upperbound");
6349 Value *PStride =
Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.stride");
6358 ChunkSize ? ChunkSize : Zero, InternalIVTy,
"chunksize");
6359 Value *CastedDistScheduleChunkSize =
Builder.CreateZExtOrTrunc(
6360 DistScheduleChunkSize ? DistScheduleChunkSize : Zero, InternalIVTy,
6361 "distschedulechunksize");
6362 Value *CastedTripCount =
6363 Builder.CreateZExt(OrigTripCount, InternalIVTy,
"tripcount");
6366 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6368 ConstantInt::get(I32Type,
static_cast<int>(DistScheduleSchedType));
6369 Builder.CreateStore(Zero, PLowerBound);
6370 Value *OrigUpperBound =
Builder.CreateSub(CastedTripCount, One);
6371 Value *IsTripCountZero =
Builder.CreateICmpEQ(CastedTripCount, Zero);
6373 Builder.CreateSelect(IsTripCountZero, Zero, OrigUpperBound);
6374 Builder.CreateStore(UpperBound, PUpperBound);
6375 Builder.CreateStore(One, PStride);
6379 uint32_t SrcLocStrSize;
6382 if (DistScheduleSchedType != OMPScheduleType::None) {
6383 Flag |= OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6388 auto BuildInitCall = [StaticInit, SrcLoc, ThreadNum, PLastIter, PLowerBound,
6389 PUpperBound, PStride, One,
6390 this](
Value *SchedulingType,
Value *ChunkSize,
6393 StaticInit, {SrcLoc, ThreadNum,
6394 SchedulingType, PLastIter,
6395 PLowerBound, PUpperBound,
6399 BuildInitCall(SchedulingType, CastedChunkSize,
Builder);
6400 if (DistScheduleSchedType != OMPScheduleType::None &&
6401 SchedType != OMPScheduleType::OrderedDistributeChunked &&
6402 SchedType != OMPScheduleType::OrderedDistribute) {
6406 BuildInitCall(DistSchedulingType, CastedDistScheduleChunkSize,
Builder);
6410 Value *FirstChunkStart =
6411 Builder.CreateLoad(InternalIVTy, PLowerBound,
"omp_firstchunk.lb");
6412 Value *FirstChunkStop =
6413 Builder.CreateLoad(InternalIVTy, PUpperBound,
"omp_firstchunk.ub");
6414 Value *FirstChunkEnd =
Builder.CreateAdd(FirstChunkStop, One);
6416 Builder.CreateSub(FirstChunkEnd, FirstChunkStart,
"omp_chunk.range");
6417 Value *NextChunkStride =
6418 Builder.CreateLoad(InternalIVTy, PStride,
"omp_dispatch.stride");
6422 Value *DispatchCounter;
6430 DispatchCounter = Counter;
6433 FirstChunkStart, CastedTripCount, NextChunkStride,
6456 Value *ChunkEnd =
Builder.CreateAdd(DispatchCounter, ChunkRange);
6457 Value *IsLastChunk =
6458 Builder.CreateICmpUGE(ChunkEnd, CastedTripCount,
"omp_chunk.is_last");
6459 Value *CountUntilOrigTripCount =
6460 Builder.CreateSub(CastedTripCount, DispatchCounter);
6462 IsLastChunk, CountUntilOrigTripCount, ChunkRange,
"omp_chunk.tripcount");
6463 Value *BackcastedChunkTC =
6464 Builder.CreateTrunc(ChunkTripCount, IVTy,
"omp_chunk.tripcount.trunc");
6465 CLI->setTripCount(BackcastedChunkTC);
6470 Value *BackcastedDispatchCounter =
6471 Builder.CreateTrunc(DispatchCounter, IVTy,
"omp_dispatch.iv.trunc");
6472 CLI->mapIndVar([&](Instruction *) ->
Value * {
6474 return Builder.CreateAdd(
IV, BackcastedDispatchCounter);
6487 return AfterIP.takeError();
6502static FunctionCallee
6505 unsigned Bitwidth = Ty->getIntegerBitWidth();
6508 case WorksharingLoopType::ForStaticLoop:
6511 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_4u);
6514 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_8u);
6516 case WorksharingLoopType::DistributeStaticLoop:
6519 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_4u);
6522 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_8u);
6524 case WorksharingLoopType::DistributeForStaticLoop:
6527 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_4u);
6530 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_8u);
6533 if (Bitwidth != 32 && Bitwidth != 64) {
6545 Function &LoopBodyFn,
bool NoLoop) {
6556 if (LoopType == WorksharingLoopType::DistributeStaticLoop) {
6557 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6558 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6559 Builder.restoreIP(std::prev(InsertBlock->
end()));
6564 M, omp::RuntimeFunction::OMPRTL_omp_get_num_threads);
6565 Builder.restoreIP(std::prev(InsertBlock->
end()));
6569 Builder.CreateZExtOrTrunc(NumThreads, TripCountTy,
"num.threads.cast"));
6570 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6571 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
6572 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6573 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), NoLoop));
6575 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6599 Builder.restoreIP(Preheader->
end());
6602 Builder.CreateBr(CLI->
getExit());
6610 CleanUpInfo.
collectBlocks(RegionBlockSet, BlocksToBeRemoved);
6618 "Expected unique undroppable user of outlined function");
6620 assert(OutlinedFnCallInstruction &&
"Expected outlined function call");
6622 "Expected outlined function call to be located in loop preheader");
6624 if (OutlinedFnCallInstruction->
arg_size() > 1)
6631 LoopBodyArg, TripCount, OutlinedFn, NoLoop);
6633 for (
auto &ToBeDeletedItem : ToBeDeleted)
6634 ToBeDeletedItem->eraseFromParent();
6641 bool NeedsLastIter) {
6642 uint32_t SrcLocStrSize;
6646 if (NeedsLastIter) {
6649 AllocaInst *PLastIter =
6650 Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6654 Builder.CreateStore(ConstantInt::get(I32Type, 0), PLastIter);
6659 Builder.CreateSub(TripCount, ConstantInt::get(TripCount->
getType(), 1));
6662 Builder.CreateStore(
Builder.CreateZExt(IsLast, I32Type), PLastIter);
6667 case WorksharingLoopType::ForStaticLoop:
6668 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6670 case WorksharingLoopType::DistributeStaticLoop:
6671 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6673 case WorksharingLoopType::DistributeForStaticLoop:
6674 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
6679 auto OI = std::make_unique<OutlineInfo>();
6684 SmallVector<Instruction *, 4> ToBeDeleted;
6686 OI->OuterAllocBB = AllocaIP.getNodeParent();
6709 SmallPtrSet<BasicBlock *, 32> ParallelRegionBlockSet;
6711 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
6713 CodeExtractorAnalysisCache CEAC(*OuterFn);
6714 CodeExtractor Extractor(Blocks,
6728 SetVector<Value *> SinkingCands, HoistingCands;
6732 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
6739 for (
auto Use :
Users) {
6741 if (ParallelRegionBlockSet.
count(Inst->getParent())) {
6742 Inst->replaceUsesOfWith(CLI->
getIndVar(), NewLoopCntLoad);
6748 OI->ExcludeArgsFromAggregate.push_back(NewLoopCntLoad);
6755 OI->PostOutlineCB = [=, ToBeDeletedVec =
6756 std::move(ToBeDeleted)](
Function &OutlinedFn) {
6773 return BarrierIP.takeError();
6780 bool NeedsBarrier, omp::ScheduleKind SchedKind,
Value *ChunkSize,
6781 bool HasSimdModifier,
bool HasMonotonicModifier,
6782 bool HasNonmonotonicModifier,
bool HasOrderedClause,
6784 Value *DistScheduleChunkSize,
bool NeedsLastIter) {
6785 if (
Config.isTargetDevice())
6786 return applyWorkshareLoopTarget(
DL, CLI, AllocaIP, LoopType, NeedsBarrier,
6787 NoLoop, NeedsLastIter);
6789 SchedKind, ChunkSize, HasSimdModifier, HasMonotonicModifier,
6790 HasNonmonotonicModifier, HasOrderedClause, DistScheduleChunkSize);
6792 bool IsOrdered = (EffectiveScheduleType & OMPScheduleType::ModifierOrdered) ==
6793 OMPScheduleType::ModifierOrdered;
6795 if (HasDistSchedule) {
6796 DistScheduleSchedType = DistScheduleChunkSize
6797 ? OMPScheduleType::OrderedDistributeChunked
6798 : OMPScheduleType::OrderedDistribute;
6800 switch (EffectiveScheduleType & ~OMPScheduleType::ModifierMask) {
6801 case OMPScheduleType::BaseStatic:
6802 case OMPScheduleType::BaseDistribute:
6803 assert((!ChunkSize || !DistScheduleChunkSize) &&
6804 "No chunk size with static-chunked schedule");
6805 if (IsOrdered && !HasDistSchedule)
6806 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6807 NeedsBarrier, ChunkSize);
6809 if (DistScheduleChunkSize)
6810 return applyStaticChunkedWorkshareLoop(
6811 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6812 DistScheduleChunkSize, DistScheduleSchedType);
6813 return applyStaticWorkshareLoop(
DL, CLI, AllocaIP, LoopType, NeedsBarrier,
6816 case OMPScheduleType::BaseStaticChunked:
6817 case OMPScheduleType::BaseDistributeChunked:
6818 if (IsOrdered && !HasDistSchedule)
6819 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6820 NeedsBarrier, ChunkSize);
6822 return applyStaticChunkedWorkshareLoop(
6823 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6824 DistScheduleChunkSize, DistScheduleSchedType);
6826 case OMPScheduleType::BaseRuntime:
6827 case OMPScheduleType::BaseAuto:
6828 case OMPScheduleType::BaseGreedy:
6829 case OMPScheduleType::BaseBalanced:
6830 case OMPScheduleType::BaseSteal:
6831 case OMPScheduleType::BaseRuntimeSimd:
6833 "schedule type does not support user-defined chunk sizes");
6835 case OMPScheduleType::BaseGuidedSimd:
6836 case OMPScheduleType::BaseDynamicChunked:
6837 case OMPScheduleType::BaseGuidedChunked:
6838 case OMPScheduleType::BaseGuidedIterativeChunked:
6839 case OMPScheduleType::BaseGuidedAnalyticalChunked:
6840 case OMPScheduleType::BaseStaticBalancedChunked:
6841 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6842 NeedsBarrier, ChunkSize);
6855 unsigned Bitwidth = Ty->getIntegerBitWidth();
6858 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_4u);
6861 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_8u);
6869static FunctionCallee
6871 unsigned Bitwidth = Ty->getIntegerBitWidth();
6874 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_4u);
6877 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_8u);
6884static FunctionCallee
6886 unsigned Bitwidth = Ty->getIntegerBitWidth();
6889 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_4u);
6892 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_8u);
6897OpenMPIRBuilder::applyDynamicWorkshareLoop(
DebugLoc DL, CanonicalLoopInfo *CLI,
6900 bool NeedsBarrier,
Value *Chunk) {
6901 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6903 "Require dedicated allocate IP");
6905 "Require valid schedule type");
6907 bool Ordered = (SchedType & OMPScheduleType::ModifierOrdered) ==
6908 OMPScheduleType::ModifierOrdered;
6913 uint32_t SrcLocStrSize;
6920 Type *IVTy =
IV->getType();
6925 Builder.SetInsertPoint(AllocaIP.getNodeParent()->getFirstNonPHIOrAlloca());
6927 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6928 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
6929 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
6930 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
6939 Constant *One = ConstantInt::get(IVTy, 1);
6940 Builder.CreateStore(One, PLowerBound);
6942 Builder.CreateStore(UpperBound, PUpperBound);
6943 Builder.CreateStore(One, PStride);
6961 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6973 Builder.SetInsertPoint(OuterCond->getFirstInsertionPt());
6976 {SrcLoc, ThreadNum, PLastIter, PLowerBound, PUpperBound, PStride});
6977 Constant *Zero32 = ConstantInt::get(I32Type, 0);
6980 Builder.CreateSub(
Builder.CreateLoad(IVTy, PLowerBound), One,
"lb");
6981 Builder.CreateCondBr(MoreWork, Header, Exit);
6987 PI->setIncomingBlock(0, OuterCond);
6993 Br->setSuccessor(OuterCond);
6998 Builder.SetInsertPoint(
Cond->getFirstInsertionPt());
6999 UpperBound =
Builder.CreateLoad(IVTy, PUpperBound,
"ub");
7002 CI->setOperand(1, UpperBound);
7006 assert(BI->getSuccessor(1) == Exit);
7007 BI->setSuccessor(1, OuterCond);
7021 omp::Directive::OMPD_for,
false,
7024 return BarrierIP.takeError();
7076 assert(
Loops.size() >= 1 &&
"At least one loop required");
7077 size_t NumLoops =
Loops.size();
7081 return Loops.front();
7093 Loop->collectControlBlocks(OldControlBBs);
7097 if (ComputeIP.isValid())
7104 Value *CollapsedTripCount =
nullptr;
7107 "All loops to collapse must be valid canonical loops");
7108 Value *OrigTripCount = L->getTripCount();
7109 if (!CollapsedTripCount) {
7110 CollapsedTripCount = OrigTripCount;
7115 CollapsedTripCount =
7116 Builder.CreateNUWMul(CollapsedTripCount, OrigTripCount);
7122 OrigPreheader->
getNextNode(), OrigAfter,
"collapsed",
7129 Builder.restoreIP(Result->getBodyIP());
7131 Value *Leftover = Result->getIndVar();
7133 NewIndVars.
resize(NumLoops);
7134 for (
int i = NumLoops - 1; i >= 1; --i) {
7135 Value *OrigTripCount =
Loops[i]->getTripCount();
7137 Value *NewIndVar =
Builder.CreateURem(Leftover, OrigTripCount);
7138 NewIndVars[i] = NewIndVar;
7140 Leftover =
Builder.CreateUDiv(Leftover, OrigTripCount);
7143 NewIndVars[0] = Leftover;
7152 BasicBlock *ContinueBlock = Result->getBody();
7154 auto ContinueWith = [&ContinueBlock, &ContinuePred,
DL](
BasicBlock *Dest,
7161 ContinueBlock =
nullptr;
7162 ContinuePred = NextSrc;
7169 for (
size_t i = 0; i < NumLoops - 1; ++i)
7170 ContinueWith(
Loops[i]->getBody(),
Loops[i + 1]->getHeader());
7176 for (
size_t i = NumLoops - 1; i > 0; --i)
7177 ContinueWith(
Loops[i]->getAfter(),
Loops[i - 1]->getLatch());
7180 ContinueWith(Result->getLatch(),
nullptr);
7187 for (
size_t i = 0; i < NumLoops; ++i)
7188 Loops[i]->getIndVar()->replaceAllUsesWith(NewIndVars[i]);
7202std::vector<CanonicalLoopInfo *>
7206 "Must pass as many tile sizes as there are loops");
7207 int NumLoops =
Loops.size();
7208 assert(NumLoops >= 1 &&
"At least one loop to tile required");
7220 Loop->collectControlBlocks(OldControlBBs);
7228 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7229 OrigTripCounts.
push_back(L->getTripCount());
7240 for (
int i = 0; i < NumLoops - 1; ++i) {
7253 for (
int i = 0; i < NumLoops; ++i) {
7254 Value *TileSize = TileSizes[i];
7255 Value *OrigTripCount = OrigTripCounts[i];
7258 Value *FloorCompleteTripCount =
Builder.CreateUDiv(OrigTripCount, TileSize);
7259 Value *FloorTripRem =
Builder.CreateURem(OrigTripCount, TileSize);
7268 Value *FloorTripOverflow =
7269 Builder.CreateICmpNE(FloorTripRem, ConstantInt::get(IVType, 0));
7271 FloorTripOverflow =
Builder.CreateZExt(FloorTripOverflow, IVType);
7272 Value *FloorTripCount =
7273 Builder.CreateAdd(FloorCompleteTripCount, FloorTripOverflow,
7274 "omp_floor" +
Twine(i) +
".tripcount",
true);
7277 FloorCompleteCount.
push_back(FloorCompleteTripCount);
7283 std::vector<CanonicalLoopInfo *> Result;
7284 Result.reserve(NumLoops * 2);
7297 auto EmbeddNewLoop =
7298 [
this,
DL,
F, InnerEnter, &Enter, &
Continue, &OutroInsertBefore](
7301 DL, TripCount,
F, InnerEnter, OutroInsertBefore, Name);
7306 Enter = EmbeddedLoop->
getBody();
7308 OutroInsertBefore = EmbeddedLoop->
getLatch();
7309 return EmbeddedLoop;
7313 const Twine &NameBase) {
7316 EmbeddNewLoop(
P.value(), NameBase +
Twine(
P.index()));
7317 Result.push_back(EmbeddedLoop);
7321 EmbeddNewLoops(FloorCount,
"floor");
7327 for (
int i = 0; i < NumLoops; ++i) {
7329 Value *TileSize = TileSizes[i];
7331 Value *FloorIsEpilogue =
7333 Value *TileTripCount =
7334 Builder.CreateSelect(FloorIsEpilogue, FloorRems[i], TileSize);
7340 EmbeddNewLoops(TileCounts,
"tile");
7345 for (std::pair<BasicBlock *, BasicBlock *>
P : InbetweenCode) {
7354 BodyEnter =
nullptr;
7355 BodyEntered = ExitBB;
7367 Builder.restoreIP(Result.back()->getBodyIP());
7368 for (
int i = 0; i < NumLoops; ++i) {
7371 Value *OrigIndVar = OrigIndVars[i];
7422 assert(
Loop->isValid() &&
"Expecting a valid CanonicalLoopInfo");
7426 assert(Latch &&
"A valid CanonicalLoopInfo must have a unique latch");
7434 if (
I.mayReadOrWriteMemory()) {
7438 I.setMetadata(LLVMContext::MD_access_group,
AccessGroup);
7452 Loop->collectControlBlocks(oldControlBBs);
7457 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7458 origTripCounts.
push_back(L->getTripCount());
7467 Builder.SetInsertPoint(TCBlock);
7468 Value *fusedTripCount =
nullptr;
7470 assert(L->isValid() &&
"All loops to fuse must be valid canonical loops");
7471 Value *origTripCount = L->getTripCount();
7472 if (!fusedTripCount) {
7473 fusedTripCount = origTripCount;
7476 Value *condTP =
Builder.CreateICmpSGT(fusedTripCount, origTripCount);
7477 fusedTripCount =
Builder.CreateSelect(condTP, fusedTripCount, origTripCount,
7491 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7492 Loops[i]->getPreheader()->moveBefore(TCBlock);
7493 Loops[i]->getAfter()->moveBefore(TCBlock);
7497 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7509 for (
size_t i = 0; i <
Loops.size(); ++i) {
7511 F->getContext(),
"omp.fused.inner.cond",
F,
Loops[i]->getBody());
7512 Builder.SetInsertPoint(condBlock);
7520 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7521 Builder.SetInsertPoint(condBBs[i]);
7522 Builder.CreateCondBr(condValues[i],
Loops[i]->getBody(), condBBs[i + 1]);
7538 "omp.fused.pre_latch");
7571 const Twine &NamePrefix) {
7600 C, NamePrefix +
".if.then",
Cond->getParent(),
Cond->getNextNode());
7602 C, NamePrefix +
".if.else",
Cond->getParent(), CanonicalLoop->
getExit());
7605 Builder.SetInsertPoint(SplitBeforeIt);
7607 Builder.CreateCondBr(IfCond, ThenBlock, ElseBlock);
7610 spliceBB(IP, ThenBlock,
false, Builder.getCurrentDebugLocation());
7613 Builder.SetInsertPoint(ElseBlock);
7619 ExistingBlocks.
reserve(L->getNumBlocks() + 1);
7621 ExistingBlocks.
append(L->block_begin(), L->block_end());
7627 assert(LoopCond && LoopHeader &&
"Invalid loop structure");
7629 if (
Block == L->getLoopPreheader() ||
Block == L->getLoopLatch() ||
7636 if (
Block == ThenBlock)
7637 NewBB->
setName(NamePrefix +
".if.else");
7640 VMap[
Block] = NewBB;
7648 L->getLoopLatch()->splitBasicBlockBefore(
L->getLoopLatch()->begin(),
7649 NamePrefix +
".pre_latch");
7653 L->addBasicBlockToLoop(ThenBlock, LI);
7659 if (TargetTriple.
isX86()) {
7660 if (Features.
lookup(
"avx512f"))
7662 else if (Features.
lookup(
"avx"))
7666 if (TargetTriple.
isPPC())
7668 if (TargetTriple.
isWasm())
7677 Value *IfCond, OrderKind Order,
7687 if (!BB.hasTerminator())
7703 I->eraseFromParent();
7706 if (AlignedVars.
size()) {
7708 for (
auto &AlignedItem : AlignedVars) {
7709 Value *AlignedPtr = AlignedItem.first;
7713 Builder.CreateAlignmentAssumption(
F->getDataLayout(), AlignedPtr,
7721 createIfVersion(CanonicalLoop, IfCond, VMap, LIA, LI, L,
"simd");
7734 Reachable.insert(
Block);
7744 if ((Safelen ==
nullptr) || (Order == OrderKind::OMP_ORDER_concurrent))
7760 if (Simdlen || Safelen) {
7764 ConstantInt *VectorizeWidth = Simdlen ==
nullptr ? Safelen : Simdlen;
7790static std::unique_ptr<TargetMachine>
7794 StringRef CPU =
F->getFnAttribute(
"target-cpu").getValueAsString();
7795 StringRef Features =
F->getFnAttribute(
"target-features").getValueAsString();
7806 std::nullopt, OptLevel));
7824 if (!BB.hasTerminator())
7837 [&](
const Function &
F) {
return TM->getTargetTransformInfo(
F); });
7838 FAM.registerPass([&]() {
return TIRA; });
7852 I->eraseFromParent();
7855 assert(L &&
"Expecting CanonicalLoopInfo to be recognized as a loop");
7860 nullptr, ORE,
static_cast<int>(OptLevel),
7880 <<
" Threshold=" << UP.
Threshold <<
"\n"
7883 <<
" PartialOptSizeThreshold="
7903 Ptr =
Load->getPointerOperand();
7905 Ptr =
Store->getPointerOperand();
7912 if (Alloca->getParent() == &
F->getEntryBlock())
7932 int MaxTripCount = 0;
7933 bool MaxOrZero =
false;
7934 unsigned TripMultiple = 0;
7938 MaxTripCount, MaxOrZero, TripMultiple, UCE, UP, PP);
7939 LLVM_DEBUG(
dbgs() <<
"Suggesting unroll factor of " << Factor <<
"\n");
7950 assert(Factor >= 0 &&
"Unroll factor must not be negative");
7966 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst}));
7979 *UnrolledCLI =
Loop;
7984 "unrolling only makes sense with a factor of 2 or larger");
7986 Type *IndVarTy =
Loop->getIndVarType();
7993 std::vector<CanonicalLoopInfo *>
LoopNest =
8008 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst})});
8011 (*UnrolledCLI)->assertOK();
8029 Value *Args[] = {Ident, ThreadId, BufSize, CpyBuf, CpyFn, DidItLD};
8048 if (!CPVars.
empty()) {
8053 Directive OMPD = Directive::OMPD_single;
8058 Value *Args[] = {Ident, ThreadId};
8067 if (
Error Err = FiniCB(IP))
8088 EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCBWrapper,
8095 for (
size_t I = 0, E = CPVars.
size();
I < E; ++
I)
8098 ConstantInt::get(Int64, 0), CPVars[
I],
8101 }
else if (!IsNowait) {
8104 omp::Directive::OMPD_unknown,
false,
8122 Directive::OMPD_scope,
nullptr,
nullptr,
8123 BodyGenCB, FiniCB,
false,
true,
8131 omp::Directive::OMPD_unknown,
8147 Directive OMPD = Directive::OMPD_critical;
8152 Value *LockVar = getOMPCriticalRegionLock(CriticalName);
8153 Value *Args[] = {Ident, ThreadId, LockVar};
8170 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
8178 const Twine &Name,
bool IsDependSource) {
8181 [](
Value *SV) {
return SV->getType()->isIntegerTy(64); }) &&
8182 "OpenMP runtime requires depend vec with i64 type");
8195 for (
unsigned I = 0;
I < NumLoops; ++
I) {
8209 Value *Args[] = {Ident, ThreadId, DependBaseAddrGEP};
8227 Directive OMPD = Directive::OMPD_ordered_blockassoc;
8236 Value *Args[] = {Ident, ThreadId};
8246 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
8253 bool HasFinalize,
bool IsCancellable) {
8260 BasicBlock *EntryBB = Builder.GetInsertBlock();
8264 SplitPos->
setDebugLoc(Builder.getCurrentDebugLocation());
8271 emitCommonDirectiveEntry(OMPD, EntryCall, ExitBB, Conditional);
8283 "Unexpected control flow graph state!!");
8285 emitCommonDirectiveExit(OMPD, FinIP, ExitCall, HasFinalize);
8287 return AfterIP.takeError();
8292 "Unexpected Insertion point location!");
8295 auto InsertBB = merged ? ExitPredBB : ExitBB;
8298 Builder.SetInsertPoint(InsertBB);
8304 Directive OMPD,
Value *EntryCall, BasicBlock *ExitBB,
bool Conditional) {
8306 if (!Conditional || !EntryCall)
8312 auto *UI =
new UnreachableInst(
Builder.getContext(), ThenBB);
8322 Builder.CreateCondBr(CallBool, ThenBB, ExitBB);
8326 UI->eraseFromParent();
8334 omp::Directive OMPD,
InsertPointTy FinIP, Instruction *ExitCall,
8342 "Unexpected finalization stack state!");
8345 assert(Fi.DK == OMPD &&
"Unexpected Directive for Finalization call!");
8349 return std::move(Err);
8396 "copyin.not.master.end");
8403 Builder.SetInsertPoint(OMP_Entry);
8406 Value *cmp =
Builder.CreateICmpNE(MasterPtr, PrivatePtr);
8407 Builder.CreateCondBr(cmp, CopyBegin, CopyEnd);
8409 Builder.SetInsertPoint(CopyBegin);
8427 Value *Args[] = {ThreadId,
Size, Allocator};
8450 return Builder.CreateCall(Fn, Args, Name);
8464 Value *Args[] = {ThreadId, Addr, Allocator};
8471 const Twine &Name) {
8479 M.getContext(),
M.getDataLayout().getPrefTypeAlign(Int64)));
8485 const Twine &Name) {
8487 Loc,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)), Name);
8492 const Twine &Name) {
8498 return Builder.CreateCall(Fn, Args, Name);
8503 const Twine &Name) {
8505 Loc, Addr,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)),
8512 Value *DependenceAddress,
bool HaveNowaitClause) {
8522 else if (
Device->getType() != Int32)
8525 if (NumDependences ==
nullptr) {
8526 NumDependences = ConstantInt::get(Int32, 0);
8530 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8532 Ident, ThreadId, InteropVar, InteropTypeVal,
8533 Device, NumDependences, DependenceAddress, HaveNowaitClauseVal};
8542 Value *NumDependences,
Value *DependenceAddress,
bool HaveNowaitClause) {
8552 else if (
Device->getType() != Int32)
8554 if (NumDependences ==
nullptr) {
8555 NumDependences = ConstantInt::get(Int32, 0);
8559 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8561 Ident, ThreadId, InteropVar,
Device,
8562 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8571 Value *NumDependences,
8572 Value *DependenceAddress,
8573 bool HaveNowaitClause) {
8582 else if (
Device->getType() != Int32)
8584 if (NumDependences ==
nullptr) {
8585 NumDependences = ConstantInt::get(Int32, 0);
8589 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8591 Ident, ThreadId, InteropVar,
Device,
8592 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8622 assert(!Attrs.MaxThreads.empty() && !Attrs.MaxTeams.empty() &&
8623 "expected num_threads and num_teams to be specified");
8643 const std::string DebugPrefix =
"_debug__";
8644 if (KernelName.
ends_with(DebugPrefix)) {
8645 KernelName = KernelName.
drop_back(DebugPrefix.length());
8646 Kernel =
M.getFunction(KernelName);
8652 if (Attrs.MinTeams.front() > 1 || Attrs.MaxTeams.front() > 0)
8654 Attrs.MaxTeams.front());
8657 int32_t MaxThreadsVal = Attrs.MaxThreads.front();
8667 Attrs.MinThreads.front());
8672 if (MaxThreadsVal > 0 &&
8675 MaxThreadsVal = int32_t(
8676 std::min<int64_t>(int64_t(MaxThreadsVal) + 64,
8679 if (MaxThreadsVal > 0)
8694 Twine DynamicEnvironmentName = KernelName +
"_dynamic_environment";
8695 Constant *DynamicEnvironmentInitializer =
8699 DynamicEnvironmentInitializer, DynamicEnvironmentName,
8701 DL.getDefaultGlobalsAddressSpace());
8705 DynamicEnvironmentGV->
getType() == DynamicEnvironmentPtr
8706 ? DynamicEnvironmentGV
8708 DynamicEnvironmentPtr);
8711 ConfigurationEnvironment, {
8712 UseGenericStateMachineVal,
8713 MayUseNestedParallelismVal,
8722 KernelEnvironment, {
8723 ConfigurationEnvironmentInitializer,
8727 std::string KernelEnvironmentName =
8728 (KernelName +
"_kernel_environment").str();
8731 KernelEnvironmentInitializer, KernelEnvironmentName,
8733 DL.getDefaultGlobalsAddressSpace());
8736 return KernelEnvironmentGV->
getType() == KernelEnvironmentPtr
8737 ? KernelEnvironmentGV
8739 KernelEnvironmentPtr);
8746 if (!KernelEnvironment)
8754 omp::RuntimeFunction::OMPRTL___kmpc_target_init);
8756 Value *KernelLaunchEnvironment =
8759 KernelLaunchEnvironment =
8760 KernelLaunchEnvironment->
getType() == KernelLaunchEnvParamTy
8761 ? KernelLaunchEnvironment
8762 :
Builder.CreateAddrSpaceCast(KernelLaunchEnvironment,
8763 KernelLaunchEnvParamTy);
8765 Fn, {KernelEnvironment, KernelLaunchEnvironment});
8777 auto *UI =
Builder.CreateUnreachable();
8783 Builder.SetInsertPoint(WorkerExitBB);
8787 Builder.SetInsertPoint(CheckBBTI);
8788 Builder.CreateCondBr(ExecUserCode, UI->getParent(), WorkerExitBB);
8790 CheckBBTI->eraseFromParent();
8791 UI->eraseFromParent();
8799 int32_t TeamsReductionDataSize) {
8804 omp::RuntimeFunction::OMPRTL___kmpc_target_deinit);
8808 if (!TeamsReductionDataSize)
8814 const std::string DebugPrefix =
"_debug__";
8816 KernelName = KernelName.
drop_back(DebugPrefix.length());
8817 auto *KernelEnvironmentGV =
8818 M.getNamedGlobal((KernelName +
"_kernel_environment").str());
8819 assert(KernelEnvironmentGV &&
"Expected kernel environment global\n");
8820 auto *KernelEnvironmentInitializer = KernelEnvironmentGV->getInitializer();
8822 KernelEnvironmentInitializer,
8823 ConstantInt::get(Int32, TeamsReductionDataSize), {0, 7});
8824 KernelEnvironmentGV->setInitializer(NewInitializer);
8829 if (
Kernel.hasFnAttribute(Name)) {
8830 int32_t OldLimit =
Kernel.getFnAttributeAsParsedInteger(Name);
8836std::pair<int32_t, int32_t>
8838 int32_t ThreadLimit =
8839 Kernel.getFnAttributeAsParsedInteger(
"omp_target_thread_limit");
8842 const auto &Attr =
Kernel.getFnAttribute(
"amdgpu-flat-work-group-size");
8843 if (!Attr.isValid() || !Attr.isStringAttribute())
8844 return {0, ThreadLimit};
8845 auto [LBStr, UBStr] = Attr.getValueAsString().split(
',');
8848 return {0, ThreadLimit};
8849 UB = ThreadLimit ? std::min(ThreadLimit, UB) : UB;
8857 return {0, ThreadLimit ? std::min(ThreadLimit, UB) : UB};
8859 return {0, ThreadLimit};
8865 Kernel.addFnAttr(
"omp_target_thread_limit", std::to_string(UB));
8868 Kernel.addFnAttr(
"amdgpu-flat-work-group-size",
8876std::pair<int32_t, int32_t>
8879 return {0,
Kernel.getFnAttributeAsParsedInteger(
"omp_target_num_teams")};
8883 int32_t LB, int32_t UB) {
8891 Kernel.addFnAttr(
"omp_target_num_teams", std::to_string(LB));
8894void OpenMPIRBuilder::setOutlinedTargetRegionFunctionAttributes(
8903 else if (
T.isNVPTX())
8905 else if (
T.isSPIRV())
8911 StringRef EntryFnIDName) {
8912 if (
Config.isTargetDevice()) {
8913 assert(OutlinedFn &&
"The outlined function must exist if embedded");
8917 return new GlobalVariable(
8922Constant *OpenMPIRBuilder::createTargetRegionEntryAddr(
Function *OutlinedFn,
8923 StringRef EntryFnName) {
8927 assert(!
M.getGlobalVariable(EntryFnName,
true) &&
8928 "Named kernel already exists?");
8929 return new GlobalVariable(
8942 if (
Config.isTargetDevice() || !
Config.openMPOffloadMandatory()) {
8946 OutlinedFn = *CBResult;
8948 OutlinedFn =
nullptr;
8954 if (!IsOffloadEntry)
8957 std::string EntryFnIDName =
8959 ? std::string(EntryFnName)
8963 EntryFnName, EntryFnIDName);
8971 setOutlinedTargetRegionFunctionAttributes(OutlinedFn);
8972 auto OutlinedFnID = createOutlinedFunctionID(OutlinedFn, EntryFnIDName);
8973 auto EntryAddr = createTargetRegionEntryAddr(OutlinedFn, EntryFnName);
8975 EntryInfo, EntryAddr, OutlinedFnID,
8977 return OutlinedFnID;
8995 bool IsStandAlone = !BodyGenCB;
9002 MapInfo = &GenMapInfoCB(
Builder.saveIP());
9004 AllocaIP,
Builder.saveIP(), *MapInfo, Info, CustomMapperCB,
9005 true, DeviceAddrCB))
9012 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
9022 SrcLocInfo, DeviceID,
9029 assert(MapperFunc &&
"MapperFunc missing for standalone target data");
9033 if (Info.HasNoWait) {
9043 if (Info.HasNoWait) {
9047 emitBlock(OffloadContBlock, CurFn,
true);
9053 bool RequiresOuterTargetTask = Info.HasNoWait;
9054 if (!RequiresOuterTargetTask)
9055 cantFail(TaskBodyCB(
nullptr,
nullptr,
9059 {}, RTArgs, Info.HasNoWait));
9062 omp::OMPRTL___tgt_target_data_begin_mapper);
9066 for (
auto DeviceMap : Info.DevicePtrInfoMap) {
9070 Builder.CreateStore(LI, DeviceMap.second.second);
9107 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
9116 Value *OffloadingArgs[] = {SrcLocInfo, DeviceID,
9139 return emitIfClause(IfCond, BeginThenGen, BeginElseGen, AllocaIP);
9140 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9155 return emitIfClause(IfCond, EndThenGen, EndElseGen, AllocaIP);
9156 return EndThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9159 return emitIfClause(IfCond, BeginThenGen, EndElseGen, AllocaIP);
9160 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9171 bool IsGPUDistribute) {
9172 assert((IVSize == 32 || IVSize == 64) &&
9173 "IV size is not compatible with the omp runtime");
9175 if (IsGPUDistribute)
9177 ? (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_4
9178 : omp::OMPRTL___kmpc_distribute_static_init_4u)
9179 : (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_8
9180 : omp::OMPRTL___kmpc_distribute_static_init_8u);
9182 Name = IVSize == 32 ? (IVSigned ? omp::OMPRTL___kmpc_for_static_init_4
9183 : omp::OMPRTL___kmpc_for_static_init_4u)
9184 : (IVSigned ? omp::OMPRTL___kmpc_for_static_init_8
9185 : omp::OMPRTL___kmpc_for_static_init_8u);
9192 assert((IVSize == 32 || IVSize == 64) &&
9193 "IV size is not compatible with the omp runtime");
9195 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_4
9196 : omp::OMPRTL___kmpc_dispatch_init_4u)
9197 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_8
9198 : omp::OMPRTL___kmpc_dispatch_init_8u);
9205 assert((IVSize == 32 || IVSize == 64) &&
9206 "IV size is not compatible with the omp runtime");
9208 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_4
9209 : omp::OMPRTL___kmpc_dispatch_next_4u)
9210 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_8
9211 : omp::OMPRTL___kmpc_dispatch_next_8u);
9218 assert((IVSize == 32 || IVSize == 64) &&
9219 "IV size is not compatible with the omp runtime");
9221 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_4
9222 : omp::OMPRTL___kmpc_dispatch_fini_4u)
9223 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_8
9224 : omp::OMPRTL___kmpc_dispatch_fini_8u);
9235 DenseMap<
Value *, std::tuple<Value *, unsigned>> &ValueReplacementMap) {
9243 auto GetUpdatedDIVariable = [&](
DILocalVariable *OldVar,
unsigned arg) {
9247 if (NewVar && (arg == NewVar->
getArg()))
9257 auto UpdateDebugRecord = [&](
auto *DR) {
9260 for (
auto Loc : DR->location_ops()) {
9261 auto Iter = ValueReplacementMap.find(
Loc);
9262 if (Iter != ValueReplacementMap.end()) {
9263 DR->replaceVariableLocationOp(
Loc, std::get<0>(Iter->second));
9264 ArgNo = std::get<1>(Iter->second) + 1;
9268 DR->setVariable(GetUpdatedDIVariable(OldVar, ArgNo));
9273 if (DVR->getNumVariableLocationOps() != 1u) {
9274 DVR->setKillLocation();
9277 Value *
Loc = DVR->getVariableLocationOp(0u);
9284 RequiredBB = &DVR->getFunction()->getEntryBlock();
9286 if (RequiredBB && RequiredBB != CurBB) {
9298 UpdateDebugRecord(&DVR);
9299 MoveDebugRecordToCorrectBlock(&DVR);
9302 for (
auto *DVR : DVRsToDelete)
9303 DVR->getMarker()->MarkedInstr->dropOneDbgRecord(DVR);
9307 Module *M = Func->getParent();
9310 DB.createQualifiedType(dwarf::DW_TAG_pointer_type,
nullptr);
9311 unsigned ArgNo = Func->arg_size();
9313 NewSP,
"dyn_ptr", ArgNo, NewSP->
getFile(), 0, VoidPtrTy,
9314 false, DINode::DIFlags::FlagArtificial);
9316 Argument *LastArg = Func->getArg(Func->arg_size() - 1);
9317 DB.insertDeclare(LastArg, Var, DB.createExpression(),
Loc,
9339 for (
auto &Arg : Inputs)
9340 ParameterTypes.
push_back(Arg->getType()->isPointerTy()
9344 for (
auto &Arg : Inputs)
9345 ParameterTypes.
push_back(Arg->getType());
9353 auto BB = Builder.GetInsertBlock();
9354 auto M = BB->getModule();
9365 if (TargetCpuAttr.isStringAttribute())
9366 Func->addFnAttr(TargetCpuAttr);
9368 auto TargetFeaturesAttr = ParentFn->
getFnAttribute(
"target-features");
9369 if (TargetFeaturesAttr.isStringAttribute())
9370 Func->addFnAttr(TargetFeaturesAttr);
9375 OMPBuilder.
emitUsed(
"llvm.compiler.used", {ExecMode});
9385 Builder.SetCurrentDebugLocation(OutlinedFnLoc);
9389 Builder.SetInsertPoint(EntryBB);
9400 BasicBlock *UserCodeEntryBB = Builder.GetInsertBlock();
9409 splitBB(Builder,
true,
"outlined.body");
9411 CBFunc(Builder.saveIP(), OutlinedBodyBB->
begin(), ExitBB);
9414 Builder.SetInsertPoint(ExitBB);
9422 Builder.SetCurrentDebugLocation(OutlinedFnLoc);
9429 Builder.CreateRetVoid();
9433 auto AllocaIP = Builder.saveIP();
9438 const auto &ArgRange =
make_range(Func->arg_begin(), Func->arg_end() - 1);
9470 if (Instr->getFunction() == Func)
9471 Instr->replaceUsesOfWith(
Input, InputCopy);
9477 for (
auto InArg :
zip(Inputs, ArgRange)) {
9479 Argument &Arg = std::get<1>(InArg);
9480 Value *InputCopy =
nullptr;
9483 Arg,
Input, InputCopy, AllocaIP, Builder.saveIP(), ExitBB->
begin());
9486 Builder.restoreIP(*AfterIP);
9487 ValueReplacementMap[
Input] = std::make_tuple(InputCopy, Arg.
getArgNo());
9507 DeferredReplacement.push_back(std::make_pair(
Input, InputCopy));
9514 ReplaceValue(
Input, InputCopy, Func);
9518 for (
auto Deferred : DeferredReplacement)
9519 ReplaceValue(std::get<0>(Deferred), std::get<1>(Deferred), Func);
9522 ValueReplacementMap);
9530 Value *TaskWithPrivates,
9531 Type *TaskWithPrivatesTy) {
9533 Type *TaskTy = OMPIRBuilder.Task;
9536 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 0);
9537 Value *Shareds = TaskT;
9547 if (TaskWithPrivatesTy != TaskTy)
9548 Shareds = Builder.CreateStructGEP(TaskTy, TaskT, 0);
9565 const size_t NumOffloadingArrays,
const int SharedArgsOperandNo) {
9570 assert((!NumOffloadingArrays || PrivatesTy) &&
9571 "PrivatesTy cannot be nullptr when there are offloadingArrays"
9601 Type *TaskPtrTy = OMPBuilder.TaskPtr;
9602 [[maybe_unused]]
Type *TaskTy = OMPBuilder.Task;
9608 ".omp_target_task_proxy_func", M);
9609 Value *ThreadId = ProxyFn->getArg(0);
9610 Value *TaskWithPrivates = ProxyFn->getArg(1);
9611 ThreadId->
setName(
"thread.id");
9612 TaskWithPrivates->
setName(
"task");
9614 bool HasShareds = SharedArgsOperandNo > 0;
9615 bool HasOffloadingArrays = NumOffloadingArrays > 0;
9619 Builder.SetInsertPoint(EntryBB);
9626 if (HasOffloadingArrays) {
9627 assert(TaskTy != TaskWithPrivatesTy &&
9628 "If there are offloading arrays to pass to the target"
9629 "TaskTy cannot be the same as TaskWithPrivatesTy");
9632 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 1);
9633 for (
unsigned int i = 0; i < NumOffloadingArrays; ++i)
9635 Builder.CreateStructGEP(PrivatesTy, Privates, i));
9639 auto *ArgStructAlloca =
9641 assert(ArgStructAlloca &&
9642 "Unable to find the alloca instruction corresponding to arguments "
9643 "for extracted function");
9645 std::optional<TypeSize> ArgAllocSize =
9647 assert(ArgStructType && ArgAllocSize &&
9648 "Unable to determine size of arguments for extracted function");
9649 uint64_t StructSize = ArgAllocSize->getFixedValue();
9652 Builder.CreateAlloca(ArgStructType,
nullptr,
"structArg");
9654 Value *SharedsSize = Builder.getInt64(StructSize);
9657 OMPBuilder, Builder, TaskWithPrivates, TaskWithPrivatesTy);
9659 Builder.CreateMemCpy(
9660 NewArgStructAlloca, NewArgStructAlloca->
getAlign(), LoadShared,
9662 KernelLaunchArgs.
push_back(NewArgStructAlloca);
9665 Builder.CreateRetVoid();
9671 return GEP->getSourceElementType();
9673 return Alloca->getAllocatedType();
9696 if (OffloadingArraysToPrivatize.
empty())
9697 return OMPIRBuilder.Task;
9700 for (
Value *V : OffloadingArraysToPrivatize) {
9701 assert(V->getType()->isPointerTy() &&
9702 "Expected pointer to array to privatize. Got a non-pointer value "
9705 assert(ArrayTy &&
"ArrayType cannot be nullptr");
9711 "struct.task_with_privates");
9726 EntryFnName, Inputs, CBFunc,
9727 ArgAccessorFuncCB, OutlinedFnLoc);
9731 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
9870 auto OI = std::make_unique<OutlineInfo>();
9871 OI->EntryBB = TargetTaskAllocaBB;
9872 OI->OuterAllocBB = AllocaIP.getNodeParent();
9877 Builder, AllocaIP, ToBeDeleted, TargetTaskAllocaIP,
"global.tid",
false));
9880 Builder.restoreIP(TargetTaskBodyIP);
9881 if (
Error Err = TaskBodyCB(DeviceID, RTLoc, TargetTaskAllocaIP))
9899 bool NeedsTargetTask = HasNoWait && DeviceID;
9900 if (NeedsTargetTask) {
9906 OffloadingArraysToPrivatize.
push_back(V);
9907 OI->ExcludeArgsFromAggregate.push_back(V);
9911 OI->PostOutlineCB = [
this, ToBeDeleted, Dependencies, NeedsTargetTask,
9912 DeviceID, OffloadingArraysToPrivatize](
9915 "there must be a single user for the outlined function");
9929 const unsigned int NumStaleCIArgs = StaleCI->
arg_size();
9930 bool HasShareds = NumStaleCIArgs > OffloadingArraysToPrivatize.
size() + 1;
9932 NumStaleCIArgs == (OffloadingArraysToPrivatize.
size() + 2)) &&
9933 "Wrong number of arguments for StaleCI when shareds are present");
9934 int SharedArgOperandNo =
9935 HasShareds ? OffloadingArraysToPrivatize.
size() + 1 : 0;
9941 if (!OffloadingArraysToPrivatize.
empty())
9946 *
this,
Builder, StaleCI, PrivatesTy, TaskWithPrivatesTy,
9947 OffloadingArraysToPrivatize.
size(), SharedArgOperandNo);
9949 LLVM_DEBUG(
dbgs() <<
"Proxy task entry function created: " << *ProxyFn
9952 Builder.SetInsertPoint(StaleCI);
9969 OMPRTL___kmpc_omp_target_task_alloc);
9981 M.getDataLayout().getTypeStoreSize(TaskWithPrivatesTy));
9988 auto *ArgStructAlloca =
9990 assert(ArgStructAlloca &&
9991 "Unable to find the alloca instruction corresponding to arguments "
9992 "for extracted function");
9993 std::optional<TypeSize> ArgAllocSize =
9996 "Unable to determine size of arguments for extracted function");
9997 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
10016 TaskSize, SharedsSize,
10019 if (NeedsTargetTask) {
10020 assert(DeviceID &&
"Expected non-empty device ID.");
10030 *
this,
Builder, TaskData, TaskWithPrivatesTy);
10034 if (!OffloadingArraysToPrivatize.
empty()) {
10036 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskData, 1);
10037 for (
unsigned int i = 0; i < OffloadingArraysToPrivatize.
size(); ++i) {
10038 Value *PtrToPrivatize = OffloadingArraysToPrivatize[i];
10045 "ElementType should match ArrayType");
10048 Value *Dst =
Builder.CreateStructGEP(PrivatesTy, Privates, i);
10051 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(ElementType)));
10055 Value *DepArray =
nullptr;
10056 Value *NumDeps =
nullptr;
10059 NumDeps = Dependencies.
NumDeps;
10060 }
else if (!Dependencies.
Deps.empty()) {
10062 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
10073 if (!NeedsTargetTask) {
10082 ConstantInt::get(
Builder.getInt32Ty(), 0),
10095 }
else if (DepArray) {
10103 {Ident, ThreadID, TaskData, NumDeps, DepArray,
10104 ConstantInt::get(
Builder.getInt32Ty(), 0),
10112 Builder.ClearInsertionPoint();
10115 I->eraseFromParent();
10120 << *(
Builder.GetInsertBlock()) <<
"\n");
10122 << *(
Builder.getModule()) <<
"\n");
10133 CustomMapperCB, IsNonContiguous, DeviceAddrCB))
10156 Builder.restoreIP(IP);
10162 return Builder.saveIP();
10165 bool HasDependencies = !Dependencies.
empty();
10166 bool RequiresOuterTargetTask = HasNoWait || HasDependencies;
10183 if (OutlinedFnID && DeviceID)
10185 EmitTargetCallFallbackCB, KArgs,
10186 DeviceID, RTLoc, TargetTaskAllocaIP);
10194 return EmitTargetCallFallbackCB(OMPBuilder.
Builder.
saveIP());
10201 auto &&EmitTargetCallElse =
10208 if (RequiresOuterTargetTask) {
10215 Dependencies, EmptyRTArgs, HasNoWait);
10217 return EmitTargetCallFallbackCB(Builder.saveIP());
10220 Builder.restoreIP(AfterIP);
10224 auto &&EmitTargetCallThen =
10228 Info.HasNoWait = HasNoWait;
10233 AllocaIP, Builder.saveIP(), Info, RTArgs, MapInfo, CustomMapperCB,
10239 for (
auto [DefaultVal, RuntimeVal] :
10241 NumTeamsC.
push_back(RuntimeVal ? RuntimeVal
10242 : Builder.getInt32(DefaultVal));
10246 auto InitMaxThreadsClause = [&Builder](
Value *
Clause) {
10248 Clause = Builder.CreateIntCast(
Clause, Builder.getInt32Ty(),
10252 auto CombineMaxThreadsClauses = [&Builder](
Value *
Clause,
Value *&Result) {
10255 Result ? Builder.CreateSelect(Builder.CreateICmpULT(Result,
Clause),
10263 Value *MaxThreadsClause =
10265 ? InitMaxThreadsClause(RuntimeAttrs.
MaxThreads.front())
10268 for (
auto [TeamsVal, TargetVal] :
zip_equal(
10270 Value *TeamsThreadLimitClause = InitMaxThreadsClause(TeamsVal);
10271 Value *NumThreads = InitMaxThreadsClause(TargetVal);
10273 CombineMaxThreadsClauses(TeamsThreadLimitClause, NumThreads);
10274 CombineMaxThreadsClauses(MaxThreadsClause, NumThreads);
10276 NumThreadsC.
push_back(NumThreads ? NumThreads : Builder.getInt32(0));
10279 unsigned NumTargetItems = Info.NumberOfPtrs;
10280 Value *RTLoc = RTLocOverride;
10291 Builder.getInt64Ty(),
10293 : Builder.getInt64(0);
10297 DynCGroupMem = Builder.getInt32(0);
10300 NumTargetItems, RTArgs, TripCount, NumTeamsC, NumThreadsC, DynCGroupMem,
10301 HasNoWait,
false,
false,
10302 DynCGroupMemFallback);
10309 if (RequiresOuterTargetTask)
10311 RTLoc, AllocaIP, Dependencies,
10312 KArgs.
RTArgs, Info.HasNoWait);
10315 Builder, OutlinedFnID, EmitTargetCallFallbackCB, KArgs,
10316 RuntimeAttrs.
DeviceID, RTLoc, AllocaIP);
10319 Builder.restoreIP(AfterIP);
10326 if (!OutlinedFnID) {
10327 cantFail(EmitTargetCallElse(AllocaIP, Builder.saveIP(), DeallocBlocks));
10333 cantFail(EmitTargetCallThen(AllocaIP, Builder.saveIP(), DeallocBlocks));
10338 EmitTargetCallElse, AllocaIP));
10351 bool HasNowait,
Value *DynCGroupMem,
10353 Value *RTLocOverride) {
10358 Builder.restoreIP(CodeGenIP);
10366 *
this,
Builder, IsOffloadEntry, EntryInfo, DefaultAttrs, OutlinedFn,
10367 OutlinedFnID, Inputs, CBFunc, ArgAccessorFuncCB, OutlinedFnLoc))
10373 if (!
Config.isTargetDevice())
10375 DefaultAttrs, RuntimeAttrs, IfCond, OutlinedFn, OutlinedFnID,
10376 Inputs, GenMapInfoCB, CustomMapperCB, Dependencies,
10377 HasNowait, DynCGroupMem, DynCGroupMemFallback);
10391 return OS.
str().str();
10396 return OpenMPIRBuilder::getNameWithSeparators(Parts,
Config.firstSeparator(),
10402 auto &Elem = *
InternalVars.try_emplace(Name,
nullptr).first;
10404 assert(Elem.second->getValueType() == Ty &&
10405 "OMP internal variable has different type than requested");
10418 :
M.getTargetTriple().isAMDGPU()
10420 :
DL.getDefaultGlobalsAddressSpace();
10421 auto Linkage = this->
M.getTargetTriple().isWasm()
10429 const llvm::Align PtrAlign =
DL.getPointerABIAlignment(AddressSpaceVal);
10430 GV->setAlignment(std::max(TypeAlign, PtrAlign));
10434 return Elem.second;
10437Value *OpenMPIRBuilder::getOMPCriticalRegionLock(
StringRef CriticalName) {
10438 std::string Prefix =
Twine(
"gomp_critical_user_", CriticalName).
str();
10439 std::string Name = getNameWithSeparators({Prefix,
"var"},
".",
".");
10450 return SizePtrToInt;
10455 std::string VarName) {
10463 return MaptypesArrayGlobal;
10468 unsigned NumOperands,
10477 ArrI8PtrTy,
nullptr,
".offload_baseptrs");
10481 ArrI64Ty,
nullptr,
".offload_sizes");
10492 int64_t DeviceID,
unsigned NumOperands) {
10498 Value *ArgsBaseGEP =
10500 {Builder.getInt32(0), Builder.getInt32(0)});
10503 {Builder.getInt32(0), Builder.getInt32(0)});
10504 Value *ArgSizesGEP =
10506 {Builder.getInt32(0), Builder.getInt32(0)});
10510 Builder.getInt32(NumOperands),
10511 ArgsBaseGEP, ArgsGEP, ArgSizesGEP,
10512 MaptypesArg, MapnamesArg, NullPtr});
10519 assert((!ForEndCall || Info.separateBeginEndCalls()) &&
10520 "expected region end call to runtime only when end call is separate");
10522 auto VoidPtrTy = UnqualPtrTy;
10523 auto VoidPtrPtrTy = UnqualPtrTy;
10525 auto Int64PtrTy = UnqualPtrTy;
10527 if (!Info.NumberOfPtrs) {
10539 Info.RTArgs.BasePointersArray,
10542 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray,
10546 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
10550 ForEndCall && Info.RTArgs.MapTypesArrayEnd ? Info.RTArgs.MapTypesArrayEnd
10551 : Info.RTArgs.MapTypesArray,
10557 if (!Info.EmitDebug)
10561 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.MapNamesArray,
10566 if (!Info.HasMapper)
10570 Builder.CreatePointerCast(Info.RTArgs.MappersArray, VoidPtrPtrTy);
10591 "struct.descriptor_dim");
10593 enum { OffsetFD = 0, CountFD, StrideFD };
10597 for (
unsigned I = 0, L = 0, E = NonContigInfo.
Dims.
size();
I < E; ++
I) {
10600 if (NonContigInfo.
Dims[
I] == 1)
10605 Builder.CreateAlloca(ArrayTy,
nullptr,
"dims");
10606 Builder.restoreIP(CodeGenIP);
10607 for (
unsigned II = 0, EE = NonContigInfo.
Dims[
I];
II < EE; ++
II) {
10608 unsigned RevIdx = EE -
II - 1;
10612 Value *OffsetLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, OffsetFD);
10614 NonContigInfo.
Offsets[L][RevIdx], OffsetLVal,
10615 M.getDataLayout().getPrefTypeAlign(OffsetLVal->
getType()));
10617 Value *CountLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, CountFD);
10619 NonContigInfo.
Counts[L][RevIdx], CountLVal,
10620 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10622 Value *StrideLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, StrideFD);
10624 NonContigInfo.
Strides[L][RevIdx], StrideLVal,
10625 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10628 Builder.restoreIP(CodeGenIP);
10629 Value *DAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
10630 DimsAddr,
Builder.getPtrTy());
10633 Info.RTArgs.PointersArray, 0,
I);
10635 DAddr,
P,
M.getDataLayout().getPrefTypeAlign(
Builder.getPtrTy()));
10640void OpenMPIRBuilder::emitUDMapperArrayInitOrDel(
10644 StringRef Prefix = IsInit ?
".init" :
".del";
10650 Builder.CreateICmpSGT(
Size, Builder.getInt64(1),
"omp.arrayinit.isarray");
10651 Value *DeleteBit = Builder.CreateAnd(
10654 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10655 OpenMPOffloadMappingFlags::OMP_MAP_DELETE)));
10660 Value *BaseIsBegin = Builder.CreateICmpNE(
Base, Begin);
10661 Cond = Builder.CreateOr(IsArray, BaseIsBegin);
10662 DeleteCond = Builder.CreateIsNull(
10667 DeleteCond =
Builder.CreateIsNotNull(
10683 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10684 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10685 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10686 MapTypeArg =
Builder.CreateOr(
10689 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10690 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT)));
10694 Value *OffloadingArgs[] = {MapperHandle,
Base, Begin,
10695 ArraySize, MapTypeArg, MapName};
10706 bool PreserveMemberOfFlags,
bool PropagatePresentToPointee) {
10722 MapperFn->
addFnAttr(Attribute::NoInline);
10723 MapperFn->
addFnAttr(Attribute::NoUnwind);
10734 Builder.SetInsertPoint(EntryBB);
10749 Value *PtrBegin = BeginIn;
10755 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
10756 MapType, MapName, ElementSize, HeadBB,
10767 Builder.CreateICmpEQ(PtrBegin, PtrEnd,
"omp.arraymap.isempty");
10768 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
10774 Builder.CreatePHI(PtrBegin->
getType(), 2,
"omp.arraymap.ptrcurrent");
10775 PtrPHI->addIncoming(PtrBegin, HeadBB);
10780 return Info.takeError();
10784 Value *OffloadingArgs[] = {MapperHandle};
10788 Value *ShiftedPreviousSize =
10792 for (
unsigned I = 0;
I < Info->BasePointers.size(); ++
I) {
10793 Value *CurBaseArg = Info->BasePointers[
I];
10794 Value *CurBeginArg = Info->Pointers[
I];
10795 Value *CurSizeArg = Info->Sizes[
I];
10796 Value *CurNameArg = Info->Names.size()
10801 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10804 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10806 constexpr uint64_t MemberOfMask =
10807 static_cast<uint64_t
>(OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
10808 constexpr uint64_t AttachBit =
10809 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10810 OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
10868 Value *MemberMapType;
10869 if (PreserveMemberOfFlags || (RawType & AttachBit) ||
10870 Info->HasAttachPtr[
I]) {
10871 if (RawType & MemberOfMask)
10872 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
10874 MemberMapType = OriMapType;
10876 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
10894 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10895 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10896 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10906 Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
10912 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10913 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10914 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10920 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10921 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
10922 Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
10928 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10929 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10935 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10936 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10937 Builder.CreateCondBr(IsFrom, FromBB, EndBB);
10943 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10944 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
10953 CurMapType->
addIncoming(MemberMapType, ToElseBB);
10990 uint64_t ModifierBits =
10991 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10992 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
10993 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
10994 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
10995 if (PropagatePresentToPointee && Info->HasAttachPtr[
I])
10997 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10998 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
10999 Value *ImportedModifierBits =
11002 CurMapType, ImportedModifierBits,
"omp.maptype.with.modifiers");
11007 Value *FinalMapType =
11008 (RawType & AttachBit) ? CurMapType : CurMapTypeWithModifiers;
11010 Value *OffloadingArgs[] = {MapperHandle, CurBaseArg, CurBeginArg,
11011 CurSizeArg, FinalMapType, CurNameArg};
11013 auto ChildMapperFn = CustomMapperCB(
I);
11014 if (!ChildMapperFn)
11015 return ChildMapperFn.takeError();
11016 if (*ChildMapperFn) {
11032 "omp.arraymap.next");
11033 PtrPHI->addIncoming(PtrNext, LastBB);
11034 Value *IsDone =
Builder.CreateICmpEQ(PtrNext, PtrEnd,
"omp.arraymap.isdone");
11036 Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
11041 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
11042 MapType, MapName, ElementSize, DoneBB,
11055 bool IsNonContiguous,
11059 Info.clearArrayInfo();
11062 if (Info.NumberOfPtrs == 0)
11071 Info.RTArgs.BasePointersArray =
Builder.CreateAlloca(
11072 PointerArrayType,
nullptr,
".offload_baseptrs");
11074 Info.RTArgs.PointersArray =
Builder.CreateAlloca(
11075 PointerArrayType,
nullptr,
".offload_ptrs");
11077 PointerArrayType,
nullptr,
".offload_mappers");
11078 Info.RTArgs.MappersArray = MappersArray;
11085 ConstantInt::get(Int64Ty, 0));
11087 for (
unsigned I = 0, E = CombinedInfo.
Sizes.
size();
I < E; ++
I) {
11088 bool IsNonContigEntry =
11090 (
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11092 OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG) != 0);
11095 if (IsNonContigEntry) {
11097 "Index must be in-bounds for NON_CONTIG Dims array");
11099 assert(DimCount > 0 &&
"NON_CONTIG DimCount must be > 0");
11100 ConstSizes[
I] = ConstantInt::get(Int64Ty, DimCount);
11105 ConstSizes[
I] = CI;
11109 RuntimeSizes.
set(
I);
11112 if (RuntimeSizes.
all()) {
11114 Info.RTArgs.SizesArray =
Builder.CreateAlloca(
11115 SizeArrayType,
nullptr,
".offload_sizes");
11121 auto *SizesArrayGbl =
11126 if (!RuntimeSizes.
any()) {
11127 Info.RTArgs.SizesArray = SizesArrayGbl;
11129 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
11130 Align OffloadSizeAlign =
M.getDataLayout().getABIIntegerTypeAlignment(64);
11133 SizeArrayType,
nullptr,
".offload_sizes");
11137 Buffer,
M.getDataLayout().getPrefTypeAlign(Buffer->
getType()),
11138 SizesArrayGbl, OffloadSizeAlign,
11143 Info.RTArgs.SizesArray = Buffer;
11151 for (
auto mapFlag : CombinedInfo.
Types)
11153 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11157 Info.RTArgs.MapTypesArray = MapTypesArrayGbl;
11163 Info.RTArgs.MapNamesArray = MapNamesArrayGbl;
11164 Info.EmitDebug =
true;
11166 Info.RTArgs.MapNamesArray =
11168 Info.EmitDebug =
false;
11173 if (Info.separateBeginEndCalls()) {
11174 bool EndMapTypesDiffer =
false;
11175 for (uint64_t &
Type : Mapping) {
11176 if (
Type &
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11177 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT)) {
11178 Type &= ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
11179 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
11180 EndMapTypesDiffer =
true;
11183 if (EndMapTypesDiffer) {
11185 Info.RTArgs.MapTypesArrayEnd = MapTypesArrayGbl;
11190 for (
unsigned I = 0;
I < Info.NumberOfPtrs; ++
I) {
11193 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.BasePointersArray,
11195 Builder.CreateAlignedStore(BPVal, BP,
11196 M.getDataLayout().getPrefTypeAlign(PtrTy));
11198 if (Info.requiresDevicePointerInfo()) {
11200 CodeGenIP =
Builder.saveIP();
11202 Info.DevicePtrInfoMap[BPVal] = {BP,
Builder.CreateAlloca(PtrTy)};
11205 DeviceAddrCB(
I, Info.DevicePtrInfoMap[BPVal].second);
11207 Info.DevicePtrInfoMap[BPVal] = {BP, BP};
11209 DeviceAddrCB(
I, BP);
11215 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray, 0,
11218 Builder.CreateAlignedStore(PVal,
P,
11219 M.getDataLayout().getPrefTypeAlign(PtrTy));
11221 if (RuntimeSizes.
test(
I)) {
11223 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
11229 S,
M.getDataLayout().getPrefTypeAlign(PtrTy));
11232 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
11235 auto CustomMFunc = CustomMapperCB(
I);
11237 return CustomMFunc.takeError();
11239 MFunc =
Builder.CreatePointerCast(*CustomMFunc, PtrTy);
11242 PointerArrayType, MappersArray,
11245 MFunc, MAddr,
M.getDataLayout().getPrefTypeAlign(MAddr->
getType()));
11249 Info.NumberOfPtrs == 0)
11266 Builder.ClearInsertionPoint();
11297 auto CondConstant = CI->getSExtValue();
11299 return ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
11301 return ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
11311 Builder.CreateCondBr(
Cond, ThenBlock, ElseBlock);
11314 if (
Error Err = ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks))
11320 if (
Error Err = ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks))
11329bool OpenMPIRBuilder::checkAndEmitFlushAfterAtomic(
11333 "Unexpected Atomic Ordering.");
11335 bool Flush =
false;
11397 assert(
X.Var->getType()->isPointerTy() &&
11398 "OMP Atomic expects a pointer to target memory");
11399 Type *XElemTy =
X.ElemTy;
11402 "OMP atomic read expected a scalar type");
11404 Value *XRead =
nullptr;
11408 Builder.CreateLoad(XElemTy,
X.Var,
X.IsVolatile,
"omp.atomic.read");
11417 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11420 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11422 XRead = AtomicLoadRes.first;
11429 Builder.CreateLoad(IntCastTy,
X.Var,
X.IsVolatile,
"omp.atomic.load");
11432 XRead =
Builder.CreateBitCast(XLoad, XElemTy,
"atomic.flt.cast");
11434 XRead =
Builder.CreateIntToPtr(XLoad, XElemTy,
"atomic.ptr.cast");
11437 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Read);
11438 Builder.CreateStore(XRead, V.Var, V.IsVolatile);
11449 assert(
X.Var->getType()->isPointerTy() &&
11450 "OMP Atomic expects a pointer to target memory");
11451 Type *XElemTy =
X.ElemTy;
11454 "OMP atomic write expected a scalar type");
11462 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11465 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11473 Builder.CreateBitCast(Expr, IntCastTy,
"atomic.src.int.cast");
11478 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Write);
11485 AtomicUpdateCallbackTy &UpdateOp,
bool IsXBinopExpr,
11486 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11492 Type *XTy =
X.Var->getType();
11494 "OMP Atomic expects a pointer to target memory");
11495 Type *XElemTy =
X.ElemTy;
11498 "OMP atomic update expected a scalar or struct type");
11502 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, RMWOp, UpdateOp,
X.IsVolatile,
11503 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11505 return AtomicResult.takeError();
11506 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Update);
11511Value *OpenMPIRBuilder::emitRMWOpAsInstruction(
Value *Src1,
Value *Src2,
11515 return Builder.CreateAdd(Src1, Src2);
11517 return Builder.CreateSub(Src1, Src2);
11519 return Builder.CreateAnd(Src1, Src2);
11521 return Builder.CreateNeg(Builder.CreateAnd(Src1, Src2));
11523 return Builder.CreateOr(Src1, Src2);
11525 return Builder.CreateXor(Src1, Src2);
11527 return Builder.CreateBinaryIntrinsic(Intrinsic::smax, Src1, Src2);
11529 return Builder.CreateBinaryIntrinsic(Intrinsic::smin, Src1, Src2);
11531 return Builder.CreateBinaryIntrinsic(Intrinsic::umax, Src1, Src2);
11533 return Builder.CreateBinaryIntrinsic(Intrinsic::umin, Src1, Src2);
11535 return Builder.CreateFAdd(Src1, Src2);
11537 return Builder.CreateFSub(Src1, Src2);
11539 return Builder.CreateMaxNum(Src1, Src2);
11541 return Builder.CreateMinNum(Src1, Src2);
11543 return Builder.CreateMaximum(Src1, Src2);
11545 return Builder.CreateMinimum(Src1, Src2);
11574Expected<std::pair<Value *, Value *>> OpenMPIRBuilder::emitAtomicUpdate(
11577 AtomicUpdateCallbackTy &UpdateOp,
bool VolatileX,
bool IsXBinopExpr,
11578 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11580 bool emitRMWOp =
false;
11597 emitRMWOp = XElemTy;
11601 emitRMWOp = (IsXBinopExpr && XElemTy);
11609 std::pair<Value *, Value *> Res;
11611 AtomicRMWInst *RMWInst =
11612 Builder.CreateAtomicRMW(RMWOp,
X, Expr, llvm::MaybeAlign(), AO);
11613 if (IsIgnoreDenormalMode)
11614 RMWInst->
setMetadata(llvm::LLVMContext::MD_atomic_ignore_denormal_mode,
11616 if (
T.isAMDGPU()) {
11617 if (!IsFineGrainedMemory)
11618 RMWInst->
setMetadata(
"amdgpu.no.fine.grained.memory",
11620 if (!IsRemoteMemory)
11624 Res.first = RMWInst;
11629 Res.second = Res.first;
11631 Res.second = emitRMWOpAsInstruction(Res.first, Expr, RMWOp);
11634 Builder.CreateLoad(XElemTy,
X,
X->getName() +
".atomic.load");
11640 OpenMPIRBuilder::AtomicInfo atomicInfo(
11642 OldVal->
getAlign(),
true , AllocaIP,
X);
11643 auto AtomicLoadRes = atomicInfo.EmitAtomicLoadLibcall(AO);
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(AtomicLoadRes.first, CurBB);
11659 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11662 Value *Upd = *CBResult;
11663 Builder.CreateStore(Upd, NewAtomicAddr);
11666 auto Result = atomicInfo.EmitAtomicCompareExchangeLibcall(
11667 AtomicLoadRes.second, NewAtomicAddr, AO, Failure);
11668 LoadInst *PHILoad =
Builder.CreateLoad(XElemTy,
Result.first);
11669 PHI->addIncoming(PHILoad,
Builder.GetInsertBlock());
11672 Res.first = OldExprVal;
11675 if (UnreachableInst *ExitTI =
11678 Builder.SetInsertPoint(ExitBB);
11680 Builder.SetInsertPoint(ExitTI);
11683 IntegerType *IntCastTy =
11686 Builder.CreateLoad(IntCastTy,
X,
X->getName() +
".atomic.load");
11696 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11703 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11704 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11705 Builder.SetInsertPoint(ContBB);
11707 PHI->addIncoming(OldVal, CurBB);
11712 OldExprVal =
Builder.CreateBitCast(
PHI, XElemTy,
11713 X->getName() +
".atomic.fltCast");
11715 OldExprVal =
Builder.CreateIntToPtr(
PHI, XElemTy,
11716 X->getName() +
".atomic.ptrCast");
11720 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11723 Value *Upd = *CBResult;
11724 Builder.CreateStore(Upd, NewAtomicAddr);
11725 LoadInst *DesiredVal =
Builder.CreateLoad(IntCastTy, NewAtomicAddr);
11729 X,
PHI, DesiredVal, llvm::MaybeAlign(), AO, Failure);
11730 Result->setVolatile(VolatileX);
11731 Value *PreviousVal =
Builder.CreateExtractValue(Result, 0);
11732 Value *SuccessFailureVal =
Builder.CreateExtractValue(Result, 1);
11733 PHI->addIncoming(PreviousVal,
Builder.GetInsertBlock());
11734 Builder.CreateCondBr(SuccessFailureVal, ExitBB, ContBB);
11736 Res.first = OldExprVal;
11740 if (UnreachableInst *ExitTI =
11743 Builder.SetInsertPoint(ExitBB);
11745 Builder.SetInsertPoint(ExitTI);
11756 bool UpdateExpr,
bool IsPostfixUpdate,
bool IsXBinopExpr,
11757 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11762 Type *XTy =
X.Var->getType();
11764 "OMP Atomic expects a pointer to target memory");
11765 Type *XElemTy =
X.ElemTy;
11768 "OMP atomic capture expected a scalar or struct type");
11775 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, AtomicOp, UpdateOp,
X.IsVolatile,
11776 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11779 Value *CapturedVal =
11780 (IsPostfixUpdate ? AtomicResult->first : AtomicResult->second);
11781 Builder.CreateStore(CapturedVal, V.Var, V.IsVolatile);
11783 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Capture);
11791 bool IsFailOnly,
bool IsWeak) {
11795 IsPostfixUpdate, IsFailOnly, Failure, IsWeak);
11807 assert(
X.Var->getType()->isPointerTy() &&
11808 "OMP atomic expects a pointer to target memory");
11811 assert(V.Var->getType()->isPointerTy() &&
"v.var must be of pointer type");
11812 assert(V.ElemTy ==
X.ElemTy &&
"x and v must be of same type");
11815 bool IsInteger = E->getType()->isIntegerTy();
11817 if (
Op == OMPAtomicCompareOp::EQ) {
11820 Value *OldValue =
nullptr;
11821 Value *SuccessOrFail =
nullptr;
11859 X.Var->getName() +
".atomic.load");
11865 Value *EIsNaN =
Builder.CreateFCmpUNO(E, E,
"atomic.e.isnan");
11866 Value *XIsNaN =
Builder.CreateFCmpUNO(XFP, XFP,
"atomic.x.isnan");
11867 Value *EitherNaN =
Builder.CreateOr(EIsNaN, XIsNaN,
"atomic.either.nan");
11872 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11876 M.getContext(),
X.Var->getName() +
".atomic.nan",
F, ExitBB);
11878 M.getContext(),
X.Var->getName() +
".atomic.notnan",
F, ExitBB);
11880 M.getContext(),
X.Var->getName() +
".atomic.zero",
F, ExitBB);
11882 M.getContext(),
X.Var->getName() +
".atomic.normal",
F, ExitBB);
11886 Builder.SetInsertPoint(CurBB);
11887 Builder.CreateCondBr(EitherNaN, NaNBB, NotNaNBB);
11890 Builder.SetInsertPoint(NaNBB);
11894 Builder.SetInsertPoint(NotNaNBB);
11897 X.Var->getName() +
".atomic.xiszero");
11899 "atomic.e.iszero");
11900 Value *BothZero =
Builder.CreateAnd(XIsZero, EIsZero,
"atomic.both.zero");
11901 Builder.CreateCondBr(BothZero, ZeroBB, NormalBB);
11904 Builder.SetInsertPoint(ZeroBB);
11906 X.Var, XCurr, DBCast,
MaybeAlign(), AO, Failure);
11908 Value *OldZero =
Builder.CreateExtractValue(ResZero, 0);
11909 Value *OkZero =
Builder.CreateExtractValue(ResZero, 1);
11913 Builder.SetInsertPoint(NormalBB);
11915 X.Var, EBCast, DBCast,
MaybeAlign(), AO, Failure);
11917 Value *OldNormal =
Builder.CreateExtractValue(ResNormal, 0);
11918 Value *OkNormal =
Builder.CreateExtractValue(ResNormal, 1);
11924 Builder.CreatePHI(IntCastTy, 3,
X.Var->getName() +
".atomic.old");
11929 X.Var->getName() +
".atomic.ok");
11936 Builder.SetInsertPoint(ExitBB);
11941 OldValue =
Builder.CreateBitCast(OldIntPHI,
X.ElemTy,
11942 X.Var->getName() +
".atomic.old.fp");
11943 SuccessOrFail = SuccessPHI;
11951 Result =
Builder.CreateAtomicCmpXchg(
X.Var, EBCast, DBCast,
11957 Result->setWeak(IsWeak);
11960 OldValue =
Builder.CreateExtractValue(Result, 0);
11962 OldValue =
Builder.CreateBitCast(OldValue,
X.ElemTy);
11964 "OldValue and V must be of same type");
11965 if (IsPostfixUpdate) {
11966 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
11968 SuccessOrFail =
Builder.CreateExtractValue(Result, 1);
11972 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11974 CurBBTI,
X.Var->getName() +
".atomic.exit");
11980 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
11982 Builder.SetInsertPoint(ContBB);
11983 Builder.CreateStore(OldValue, V.Var);
11989 Builder.SetInsertPoint(ExitBB);
11991 Builder.SetInsertPoint(ExitTI);
11994 Value *CapturedValue =
11995 Builder.CreateSelect(SuccessOrFail, E, OldValue);
11996 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
12002 assert(R.Var->getType()->isPointerTy() &&
12003 "r.var must be of pointer type");
12004 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
12006 Value *SuccessFailureVal =
12007 Builder.CreateExtractValue(Result, 1);
12008 Value *ResultCast =
12009 R.IsSigned ?
Builder.CreateSExt(SuccessFailureVal, R.ElemTy)
12010 :
Builder.CreateZExt(SuccessFailureVal, R.ElemTy);
12011 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
12020 "OldValue and V must be of same type");
12021 if (IsPostfixUpdate) {
12022 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
12027 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
12029 CurBBTI,
X.Var->getName() +
".atomic.exit");
12035 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
12037 Builder.SetInsertPoint(ContBB);
12038 Builder.CreateStore(OldValue, V.Var);
12044 Builder.SetInsertPoint(ExitBB);
12046 Builder.SetInsertPoint(ExitTI);
12049 Value *CapturedValue =
12050 Builder.CreateSelect(SuccessOrFail, E, OldValue);
12051 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
12057 assert(R.Var->getType()->isPointerTy() &&
12058 "r.var must be of pointer type");
12059 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
12061 Value *ResultCast = R.IsSigned
12062 ?
Builder.CreateSExt(SuccessOrFail, R.ElemTy)
12063 :
Builder.CreateZExt(SuccessOrFail, R.ElemTy);
12064 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
12068 assert((
Op == OMPAtomicCompareOp::MAX ||
Op == OMPAtomicCompareOp::MIN) &&
12069 "Op should be either max or min at this point");
12070 assert(!IsFailOnly &&
"IsFailOnly is only valid when the comparison is ==");
12081 if (IsXBinopExpr) {
12110 Value *CapturedValue =
nullptr;
12111 if (IsPostfixUpdate) {
12112 CapturedValue = OldValue;
12137 Value *NonAtomicCmp =
Builder.CreateCmp(Pred, OldValue, E);
12138 CapturedValue =
Builder.CreateSelect(NonAtomicCmp, E, OldValue);
12140 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
12144 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Compare);
12164 if (&OuterAllocaBB ==
Builder.GetInsertBlock()) {
12191 bool SubClausesPresent =
12192 (NumTeamsLower || NumTeamsUpper || ThreadLimit || IfExpr);
12194 if (!
Config.isTargetDevice() && SubClausesPresent) {
12195 assert((NumTeamsLower ==
nullptr || NumTeamsUpper !=
nullptr) &&
12196 "if lowerbound is non-null, then upperbound must also be non-null "
12197 "for bounds on num_teams");
12199 if (NumTeamsUpper ==
nullptr)
12200 NumTeamsUpper =
Builder.getInt32(0);
12202 if (NumTeamsLower ==
nullptr)
12203 NumTeamsLower = NumTeamsUpper;
12207 "argument to if clause must be an integer value");
12211 IfExpr =
Builder.CreateICmpNE(IfExpr,
12212 ConstantInt::get(IfExpr->
getType(), 0));
12213 NumTeamsUpper =
Builder.CreateSelect(
12214 IfExpr, NumTeamsUpper,
Builder.getInt32(1),
"numTeamsUpper");
12217 NumTeamsLower =
Builder.CreateSelect(
12218 IfExpr, NumTeamsLower,
Builder.getInt32(1),
"numTeamsLower");
12221 if (ThreadLimit ==
nullptr)
12222 ThreadLimit =
Builder.getInt32(0);
12226 Value *NumTeamsLowerInt32 =
12228 Value *NumTeamsUpperInt32 =
12230 Value *ThreadLimitInt32 =
12237 {Ident, ThreadNum, NumTeamsLowerInt32, NumTeamsUpperInt32,
12238 ThreadLimitInt32});
12243 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
12246 auto OI = std::make_unique<OutlineInfo>();
12247 OI->EntryBB = AllocaBB;
12248 OI->ExitBB = ExitBB;
12249 OI->OuterAllocBB = &OuterAllocaBB;
12255 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"gid",
true));
12257 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"tid",
true));
12259 auto HostPostOutlineCB = [
this, Ident,
12260 ToBeDeleted](
Function &OutlinedFn)
mutable {
12265 "there must be a single user for the outlined function");
12270 "Outlined function must have two or three arguments only");
12272 bool HasShared = OutlinedFn.
arg_size() == 3;
12280 assert(StaleCI &&
"Error while outlining - no CallInst user found for the "
12281 "outlined function.");
12282 Builder.SetInsertPoint(StaleCI);
12289 omp::RuntimeFunction::OMPRTL___kmpc_fork_teams),
12292 Builder.ClearInsertionPoint();
12294 I->eraseFromParent();
12297 if (!
Config.isTargetDevice())
12298 OI->PostOutlineCB = HostPostOutlineCB;
12302 Builder.SetInsertPoint(ExitBB);
12313 BasicBlock *OuterAllocaBB = OuterAllocIP.getNodeParent();
12315 if (OuterAllocaBB ==
Builder.GetInsertBlock()) {
12330 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
12335 if (
Config.isTargetDevice()) {
12336 auto OI = std::make_unique<OutlineInfo>();
12337 OI->OuterAllocBB = OuterAllocIP.getNodeParent();
12338 OI->EntryBB = AllocaBB;
12339 OI->ExitBB = ExitBB;
12340 OI->OuterDeallocBBs.reserve(OuterDeallocBlocks.
size());
12341 copy(OuterDeallocBlocks, OI->OuterDeallocBBs.
end());
12345 Builder.SetInsertPoint(ExitBB);
12352 std::string VarName) {
12361 return MapNamesArrayGlobal;
12366void OpenMPIRBuilder::initializeTypes(
Module &M) {
12370 unsigned ProgramAS = M.getDataLayout().getProgramAddressSpace();
12371#define OMP_TYPE(VarName, InitValue) VarName = InitValue;
12372#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \
12373 VarName##Ty = ArrayType::get(ElemTy, ArraySize); \
12374 VarName##PtrTy = PointerType::get(Ctx, DefaultTargetAS);
12375#define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) \
12376 VarName = FunctionType::get(ReturnType, {__VA_ARGS__}, IsVarArg); \
12377 VarName##Ptr = PointerType::get(Ctx, ProgramAS);
12378#define OMP_STRUCT_TYPE(VarName, StructName, Packed, ...) \
12379 T = StructType::getTypeByName(Ctx, StructName); \
12381 T = StructType::create(Ctx, {__VA_ARGS__}, StructName, Packed); \
12383 VarName##Ptr = PointerType::get(Ctx, DefaultTargetAS);
12384#include "llvm/Frontend/OpenMP/OMPKinds.def"
12395 while (!Worklist.
empty()) {
12399 if (
BlockSet.insert(SuccBB).second)
12404std::unique_ptr<CodeExtractor>
12406 bool ArgsInZeroAddressSpace,
12408 return std::make_unique<CodeExtractor>(
12418 Suffix.
str(), ArgsInZeroAddressSpace);
12421std::unique_ptr<CodeExtractor> DeviceSharedMemOutlineInfo::createCodeExtractor(
12423 return std::make_unique<DeviceSharedMemCodeExtractor>(
12424 OMPBuilder, Blocks,
nullptr,
12432 OuterDeallocBBs.empty()
12435 Suffix.
str(), ArgsInZeroAddressSpace);
12439 uint64_t
Size, int32_t Flags,
12445 Name.empty() ? Addr->
getName() : Name,
Size, Flags, 0);
12457 Fn->
addFnAttr(
"uniform-work-group-size");
12458 Fn->
addFnAttr(Attribute::MustProgress);
12476 auto &&GetMDInt = [
this](
unsigned V) {
12483 NamedMDNode *MD =
M.getOrInsertNamedMetadata(
"omp_offload.info");
12484 auto &&TargetRegionMetadataEmitter =
12485 [&
C, MD, &OrderedEntries, &GetMDInt, &GetMDString](
12500 GetMDInt(E.getKind()), GetMDInt(EntryInfo.DeviceID),
12501 GetMDInt(EntryInfo.FileID), GetMDString(EntryInfo.ParentName),
12502 GetMDInt(EntryInfo.Line), GetMDInt(EntryInfo.Count),
12503 GetMDInt(E.getOrder())};
12506 OrderedEntries[E.getOrder()] = std::make_pair(&E, EntryInfo);
12515 auto &&DeviceGlobalVarMetadataEmitter =
12516 [&
C, &OrderedEntries, &GetMDInt, &GetMDString, MD](
12526 Metadata *
Ops[] = {GetMDInt(E.getKind()), GetMDString(MangledName),
12527 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
12531 OrderedEntries[E.getOrder()] = std::make_pair(&E, varInfo);
12538 DeviceGlobalVarMetadataEmitter);
12540 for (
const auto &E : OrderedEntries) {
12541 assert(E.first &&
"All ordered entries must exist!");
12542 if (
const auto *CE =
12545 if (!CE->getID() || !CE->getAddress()) {
12549 if (!
M.getNamedValue(FnName))
12557 }
else if (
const auto *CE =
dyn_cast<
12566 if (
Config.isTargetDevice() &&
Config.hasRequiresUnifiedSharedMemory())
12568 if (!CE->getAddress()) {
12573 if (CE->getVarSize() == 0)
12577 assert(((
Config.isTargetDevice() && !CE->getAddress()) ||
12578 (!
Config.isTargetDevice() && CE->getAddress())) &&
12579 "Declaret target link address is set.");
12580 if (
Config.isTargetDevice())
12582 if (!CE->getAddress()) {
12589 if (!CE->getAddress()) {
12602 if ((
GV->hasLocalLinkage() ||
GV->hasHiddenVisibility()) &&
12606 OMPTargetGlobalVarEntryIndirectVTable))
12615 Flags, CE->getLinkage(), CE->getVarName());
12618 Flags, CE->getLinkage());
12629 if (
Config.hasRequiresFlags() && !
Config.isTargetDevice())
12635 Config.getRequiresFlags());
12645 OS <<
"_" <<
Count;
12650 unsigned NewCount = getTargetRegionEntryInfoCount(EntryInfo);
12653 EntryInfo.
Line, NewCount);
12661 auto FileIDInfo = CallBack();
12662 uint64_t FileID = 0;
12664 ID =
Status->getUniqueID();
12665 FileID =
Status->getUniqueID().getFile();
12669 FileID =
hash_value(std::get<0>(FileIDInfo));
12673 std::get<1>(FileIDInfo));
12678 for (uint64_t Remain =
12679 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12681 !(Remain & 1); Remain = Remain >> 1)
12699 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12701 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12708 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12714 Flags &=
~omp::OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
12715 Flags |= MemberOfFlag;
12721 bool IsDeclaration,
bool IsExternallyVisible,
12723 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12724 std::vector<Triple> TargetTriple,
Type *LlvmPtrTy,
12725 std::function<
Constant *()> GlobalInitializer,
12736 Config.hasRequiresUnifiedSharedMemory())) {
12741 if (!IsExternallyVisible)
12743 OS <<
"_decl_tgt_ref_ptr";
12746 Value *Ptr =
M.getNamedValue(PtrName);
12755 if (!
Config.isTargetDevice()) {
12756 if (GlobalInitializer)
12757 GV->setInitializer(GlobalInitializer());
12763 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12764 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12765 GlobalInitializer, VariableLinkage, LlvmPtrTy,
cast<Constant>(Ptr));
12777 bool IsDeclaration,
bool IsExternallyVisible,
12779 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12780 std::vector<Triple> TargetTriple,
12781 std::function<
Constant *()> GlobalInitializer,
12785 (TargetTriple.empty() && !
Config.isTargetDevice()))
12796 !
Config.hasRequiresUnifiedSharedMemory()) {
12798 VarName = MangledName;
12801 if (!IsDeclaration)
12803 M.getDataLayout().getTypeSizeInBits(LlvmVal->
getValueType()), 8);
12806 Linkage = (VariableLinkage) ? VariableLinkage() : LlvmVal->
getLinkage();
12810 if (
Config.isTargetDevice() &&
12819 if (!
M.getNamedValue(RefName)) {
12823 GvAddrRef->setConstant(
true);
12825 GvAddrRef->setInitializer(Addr);
12826 GeneratedRefs.push_back(GvAddrRef);
12835 if (
Config.isTargetDevice()) {
12836 VarName = (Addr) ? Addr->
getName() :
"";
12840 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12841 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12842 LlvmPtrTy, GlobalInitializer, VariableLinkage);
12843 VarName = (Addr) ? Addr->
getName() :
"";
12845 VarSize =
M.getDataLayout().getPointerSize();
12864 auto &&GetMDInt = [MN](
unsigned Idx) {
12869 auto &&GetMDString = [MN](
unsigned Idx) {
12871 return V->getString();
12874 switch (GetMDInt(0)) {
12878 case OffloadEntriesInfoManager::OffloadEntryInfo::
12879 OffloadingEntryInfoTargetRegion: {
12889 case OffloadEntriesInfoManager::OffloadEntryInfo::
12890 OffloadingEntryInfoDeviceGlobalVar:
12903 if (HostFilePath.
empty())
12907 if (std::error_code Err = Buf.getError()) {
12909 "OpenMPIRBuilder: " +
12917 if (std::error_code Err =
M.getError()) {
12919 (
"error parsing host file inside of OpenMPIRBuilder: " + Err.message())
12933 "expected a valid insertion block for creating an iterator loop");
12937 if (SplitIP == CurBB->
end())
12939 SplitIP = Terminator->getIterator();
12943 Builder.getCurrentDebugLocation(),
"omp.it.cont");
12955 T->eraseFromParent();
12970 bool ReachesLatch =
false;
12973 while (!Worklist.
empty()) {
12978 "iterator bodygen must leave at most one unterminated block",
12984 if (Succ == Latch) {
12985 ReachesLatch =
true;
12990 "iterator bodygen must not branch out of the loop body",
12992 if (Visited.
insert(Succ).second)
12998 Builder.SetInsertPoint(OpenBB);
13000 }
else if (!ReachesLatch) {
13010 return ContBB->
begin();
13020 for (
const auto &
ParamAttr : ParamAttrs) {
13063 return std::string(Out.str());
13071 unsigned VecRegSize;
13073 ISADataTy ISAData[] = {
13092 for (
char Mask :
Masked) {
13093 for (
const ISADataTy &
Data : ISAData) {
13096 Out <<
"_ZGV" <<
Data.ISA << Mask;
13098 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
13112template <
typename T>
13115 StringRef MangledName,
bool OutputBecomesInput,
13119 Out << Prefix << ISA << LMask << VLEN;
13120 if (OutputBecomesInput)
13122 Out << ParSeq <<
'_' << MangledName;
13131 bool OutputBecomesInput,
13136 OutputBecomesInput, Fn);
13138 OutputBecomesInput, Fn);
13142 OutputBecomesInput, Fn);
13144 OutputBecomesInput, Fn);
13148 OutputBecomesInput, Fn);
13150 OutputBecomesInput, Fn);
13155 OutputBecomesInput, Fn);
13166 char ISA,
unsigned NarrowestDataSize,
bool OutputBecomesInput) {
13167 assert((ISA ==
'n' || ISA ==
's') &&
"Expected ISA either 's' or 'n'.");
13179 OutputBecomesInput, Fn);
13186 OutputBecomesInput, Fn);
13188 OutputBecomesInput, Fn);
13192 OutputBecomesInput, Fn);
13196 OutputBecomesInput, Fn);
13205 OutputBecomesInput, Fn);
13212 MangledName, OutputBecomesInput, Fn);
13214 MangledName, OutputBecomesInput, Fn);
13218 MangledName, OutputBecomesInput, Fn);
13222 MangledName, OutputBecomesInput, Fn);
13232 return OffloadEntriesTargetRegion.empty() &&
13233 OffloadEntriesDeviceGlobalVar.empty();
13236unsigned OffloadEntriesInfoManager::getTargetRegionEntryInfoCount(
13238 auto It = OffloadEntriesTargetRegionCount.find(
13239 getTargetRegionEntryCountKey(EntryInfo));
13240 if (It == OffloadEntriesTargetRegionCount.end())
13245void OffloadEntriesInfoManager::incrementTargetRegionEntryInfoCount(
13247 OffloadEntriesTargetRegionCount[getTargetRegionEntryCountKey(EntryInfo)] =
13248 EntryInfo.
Count + 1;
13254 OffloadEntriesTargetRegion[EntryInfo] =
13257 ++OffloadingEntriesNum;
13263 assert(EntryInfo.
Count == 0 &&
"expected default EntryInfo");
13266 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
13270 if (OMPBuilder->Config.isTargetDevice()) {
13275 auto &Entry = OffloadEntriesTargetRegion[EntryInfo];
13276 Entry.setAddress(Addr);
13278 Entry.setFlags(Flags);
13284 "Target region entry already registered!");
13286 OffloadEntriesTargetRegion[EntryInfo] = Entry;
13287 ++OffloadingEntriesNum;
13289 incrementTargetRegionEntryInfoCount(EntryInfo);
13296 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
13298 auto It = OffloadEntriesTargetRegion.find(EntryInfo);
13299 if (It == OffloadEntriesTargetRegion.end()) {
13303 if (!IgnoreAddressId && (It->second.getAddress() || It->second.getID()))
13311 for (
const auto &It : OffloadEntriesTargetRegion) {
13312 Action(It.first, It.second);
13318 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
13319 ++OffloadingEntriesNum;
13325 if (OMPBuilder->Config.isTargetDevice()) {
13329 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
13331 if (Entry.getVarSize() == 0) {
13332 Entry.setVarSize(VarSize);
13333 Entry.setLinkage(Linkage);
13337 Entry.setVarSize(VarSize);
13338 Entry.setLinkage(Linkage);
13339 Entry.setAddress(Addr);
13342 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
13343 assert(Entry.isValid() && Entry.getFlags() == Flags &&
13344 "Entry not initialized!");
13345 if (Entry.getVarSize() == 0) {
13346 Entry.setVarSize(VarSize);
13347 Entry.setLinkage(Linkage);
13354 OffloadEntriesDeviceGlobalVar.try_emplace(VarName, OffloadingEntriesNum,
13355 Addr, VarSize, Flags, Linkage,
13358 OffloadEntriesDeviceGlobalVar.try_emplace(
13359 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage,
"");
13360 ++OffloadingEntriesNum;
13367 for (
const auto &E : OffloadEntriesDeviceGlobalVar)
13368 Action(E.getKey(), E.getValue());
13375void CanonicalLoopInfo::collectControlBlocks(
13382 BBs.
append({getPreheader(), Header,
Cond, Latch, Exit, getAfter()});
13394void CanonicalLoopInfo::setTripCount(
Value *TripCount) {
13406void CanonicalLoopInfo::mapIndVar(
13416 for (
Use &U : OldIV->
uses()) {
13420 if (
User->getParent() == getCond())
13422 if (
User->getParent() == getLatch())
13428 Value *NewIV = Updater(OldIV);
13431 for (Use *U : ReplacableUses)
13452 "Preheader must terminate with unconditional branch");
13454 "Preheader must jump to header");
13458 "Header must terminate with unconditional branch");
13459 assert(Header->getSingleSuccessor() == Cond &&
13460 "Header must jump to exiting block");
13463 assert(Cond->getSinglePredecessor() == Header &&
13464 "Exiting block only reachable from header");
13467 "Exiting block must terminate with conditional branch");
13469 "Exiting block's first successor jump to the body");
13471 "Exiting block's second successor must exit the loop");
13475 "Body only reachable from exiting block");
13480 "Latch must terminate with unconditional branch");
13481 assert(Latch->getSingleSuccessor() == Header &&
"Latch must jump to header");
13484 assert(Latch->getSinglePredecessor() !=
nullptr);
13489 "Exit block must terminate with unconditional branch");
13490 assert(Exit->getSingleSuccessor() == After &&
13491 "Exit block must jump to after block");
13495 "After block only reachable from exit block");
13499 assert(IndVar &&
"Canonical induction variable not found?");
13501 "Induction variable must be an integer");
13503 "Induction variable must be a PHI in the loop header");
13509 auto *NextIndVar =
cast<PHINode>(IndVar)->getIncomingValue(1);
13517 assert(TripCount &&
"Loop trip count not found?");
13519 "Trip count and induction variable must have the same type");
13523 "Exit condition must be a signed less-than comparison");
13525 "Exit condition must compare the induction variable");
13527 "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 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 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 InstListType::const_iterator getFirstNonPHIOrPseudoProbe() const
Returns an iterator to the first instruction in this block that is not a PHINode or a pseudo operatio...
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.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
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 isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp 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),...