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);
2320 Builder.GetInsertBlock()->getTerminator()->eraseFromParent();
2327 UI->eraseFromParent();
2359 Value *Severity = ConstantInt::get(Int32, IsFatal ? 2 : 1);
2361 Value *Args[] = {Ident, Severity, MessageArg};
2390 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr));
2392 Builder.CreateStore(DepValPtr, Addr);
2395 DependInfo, Entry,
static_cast<unsigned int>(RTLDependInfoFields::Len));
2397 ConstantInt::get(SizeTy,
2402 DependInfo, Entry,
static_cast<unsigned int>(RTLDependInfoFields::Flags));
2404 static_cast<unsigned int>(Dep.
DepKind)),
2417 if (Dependencies.
empty())
2437 Type *DependInfo = OMPBuilder.DependInfo;
2439 Value *DepArray =
nullptr;
2445 Builder.SetInsertPoint(
2446 Builder.GetInsertBlock()->getParent()->getEntryBlock().getTerminator());
2447 DepArray = Builder.CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
2450 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies)) {
2452 Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
2477 Value *DepArray =
nullptr;
2478 Type *DepArrayTy =
nullptr;
2479 Value *NumDeps =
nullptr;
2482 NumDeps = Dependencies.
NumDeps;
2483 }
else if (!Dependencies.
Deps.empty()) {
2485 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
2489 Builder.GetInsertBlock()->getParent()->getEntryBlock();
2491 DepArray =
Builder.CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
2494 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies.
Deps)) {
2496 Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
2510 ConstantInt::get(
Builder.getInt32Ty(), 0),
2512 ConstantInt::get(
Builder.getInt32Ty(), IsNowait)};
2515 omp::RuntimeFunction::OMPRTL___kmpc_omp_taskwait_deps_51),
2525 unsigned ProgramAddressSpace = M.getDataLayout().getProgramAddressSpace();
2537 auto *VoidPtrTy =
PointerType::get(Builder.getContext(), ProgramAddressSpace);
2540 Builder.getVoidTy(), {VoidPtrTy, VoidPtrTy, Builder.getInt32Ty()},
2544 "omp_taskloop_dup", M);
2547 Value *LastprivateFlagArg = DupFunction->
getArg(2);
2548 DestTaskArg->
setName(
"dest_task");
2549 SrcTaskArg->
setName(
"src_task");
2550 LastprivateFlagArg->
setName(
"lastprivate_flag");
2553 Builder.SetInsertPoint(
2556 auto GetTaskContextPtrFromArg = [&](
Value *Arg) ->
Value * {
2557 Type *TaskWithPrivatesTy =
2559 Value *TaskPrivates = Builder.CreateGEP(
2560 TaskWithPrivatesTy, Arg, {Builder.getInt32(0), Builder.getInt32(1)});
2561 Value *ContextPtr = Builder.CreateGEP(
2562 PrivatesTy, TaskPrivates,
2563 {Builder.getInt32(0), Builder.getInt32(PrivatesIndex)});
2567 Value *DestTaskContextPtr = GetTaskContextPtrFromArg(DestTaskArg);
2568 Value *SrcTaskContextPtr = GetTaskContextPtrFromArg(SrcTaskArg);
2570 DestTaskContextPtr->
setName(
"destPtr");
2571 SrcTaskContextPtr->
setName(
"srcPtr");
2575 Expected<IRBuilderBase::InsertPoint> AfterIPOrError =
2576 DupCB(AllocaIP, CodeGenIP, DestTaskContextPtr, SrcTaskContextPtr);
2577 if (!AfterIPOrError)
2579 Builder.restoreIP(*AfterIPOrError);
2589 llvm::function_ref<llvm::Expected<llvm::CanonicalLoopInfo *>()> LoopInfo,
2591 Value *GrainSize,
bool NoGroup,
int Sched,
Value *Final,
bool Mergeable,
2593 Value *TaskContextStructPtrVal,
bool FreeAgent) {
2598 uint32_t SrcLocStrSize;
2612 if (
Error Err = BodyGenCB(TaskloopAllocaIP, TaskloopBodyIP, TaskloopExitBB))
2615 llvm::Expected<llvm::CanonicalLoopInfo *> result = LoopInfo();
2620 llvm::CanonicalLoopInfo *CLI = result.
get();
2621 if (CLI->VirtualCollapse)
2622 CLI->reportUnsupportedVirtualCollapse();
2623 auto OI = std::make_unique<OutlineInfo>();
2624 OI->EntryBB = TaskloopAllocaBB;
2625 OI->OuterAllocBB = AllocaIP.getNodeParent();
2626 OI->ExitBB = TaskloopExitBB;
2627 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2628 copy(DeallocBlocks, OI->OuterDeallocBBs.end());
2631 SmallVector<Instruction *> ToBeDeleted;
2634 Builder, AllocaIP, ToBeDeleted, TaskloopAllocaIP,
"global.tid",
false));
2636 TaskloopAllocaIP,
"lb",
false,
true);
2638 TaskloopAllocaIP,
"ub",
false,
true);
2640 TaskloopAllocaIP,
"step",
false,
true);
2643 OI->Inputs.insert(FakeLB);
2644 OI->Inputs.insert(FakeUB);
2645 OI->Inputs.insert(FakeStep);
2646 if (TaskContextStructPtrVal)
2647 OI->Inputs.insert(TaskContextStructPtrVal);
2648 assert(((TaskContextStructPtrVal && DupCB) ||
2649 (!TaskContextStructPtrVal && !DupCB)) &&
2650 "Task context struct ptr and duplication callback must be both set "
2656 unsigned ProgramAddressSpace =
M.getDataLayout().getProgramAddressSpace();
2660 {FakeLB->getType(), FakeUB->getType(), FakeStep->getType(), PointerTy});
2661 Expected<Value *> TaskDupFnOrErr = createTaskDuplicationFunction(
2664 if (!TaskDupFnOrErr) {
2667 Value *TaskDupFn = *TaskDupFnOrErr;
2669 OI->PostOutlineCB = [
this, Ident, LBVal, UBVal, StepVal, Untied,
2670 TaskloopAllocaBB, CLI, TaskDupFn, ToBeDeleted, IfCond,
2671 GrainSize, NoGroup, Sched, FakeLB, FakeUB, FakeStep,
2672 FakeSharedsTy, Final, Mergeable, Priority,
2674 FreeAgent](
Function &OutlinedFn)
mutable {
2676 assert(OutlinedFn.hasOneUse() &&
2677 "there must be a single user for the outlined function");
2684 Value *CastedLBVal =
2685 Builder.CreateIntCast(LBVal,
Builder.getInt64Ty(),
true,
"lb64");
2686 Value *CastedUBVal =
2687 Builder.CreateIntCast(UBVal,
Builder.getInt64Ty(),
true,
"ub64");
2688 Value *CastedStepVal =
2689 Builder.CreateIntCast(StepVal,
Builder.getInt64Ty(),
true,
"step64");
2691 Builder.SetInsertPoint(StaleCI);
2704 Builder.CreateCall(TaskgroupFn, {Ident, ThreadID});
2729 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
2731 AllocaInst *ArgStructAlloca =
2733 assert(ArgStructAlloca &&
2734 "Unable to find the alloca instruction corresponding to arguments "
2735 "for extracted function");
2736 std::optional<TypeSize> ArgAllocSize =
2739 "Unable to determine size of arguments for extracted function");
2740 Value *SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
2745 CallInst *TaskData =
Builder.CreateCall(
2746 TaskAllocFn, {Ident, ThreadID,
Flags,
2747 TaskSize, SharedsSize,
2752 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
2758 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(0)});
2761 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(1)});
2764 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(2)});
2770 IfCond ?
Builder.CreateIntCast(IfCond,
Builder.getInt32Ty(),
true)
2776 Value *GrainSizeVal =
2777 GrainSize ?
Builder.CreateIntCast(GrainSize,
Builder.getInt64Ty(),
true)
2779 Value *TaskDup = TaskDupFn;
2781 Value *
Args[] = {Ident, ThreadID, TaskData, IfCondVal, Lb, Ub,
2782 Loadstep, NoGroupVal, SchedVal, GrainSizeVal, TaskDup};
2787 Builder.CreateCall(TaskloopFn, Args);
2794 Builder.CreateCall(EndTaskgroupFn, {Ident, ThreadID});
2799 Builder.SetInsertPoint(TaskloopAllocaBB->begin());
2801 LoadInst *SharedsOutlined =
2802 Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
2803 OutlinedFn.getArg(1)->replaceUsesWithIf(
2805 [SharedsOutlined](Use &U) {
return U.getUser() != SharedsOutlined; });
2808 Type *IVTy =
IV->getType();
2814 Value *TaskLB =
nullptr;
2815 Value *TaskUB =
nullptr;
2816 Value *TaskStep =
nullptr;
2817 Value *LoadTaskLB =
nullptr;
2818 Value *LoadTaskUB =
nullptr;
2819 Value *LoadTaskStep =
nullptr;
2820 for (Instruction &
I : *TaskloopAllocaBB) {
2821 if (
I.getOpcode() == Instruction::GetElementPtr) {
2824 switch (CI->getZExtValue()) {
2836 }
else if (
I.getOpcode() == Instruction::Load) {
2838 if (
Load.getPointerOperand() == TaskLB) {
2839 assert(TaskLB !=
nullptr &&
"Expected value for TaskLB");
2841 }
else if (
Load.getPointerOperand() == TaskUB) {
2842 assert(TaskUB !=
nullptr &&
"Expected value for TaskUB");
2844 }
else if (
Load.getPointerOperand() == TaskStep) {
2845 assert(TaskStep !=
nullptr &&
"Expected value for TaskStep");
2851 Builder.SetInsertPoint(CLI->getPreheader()->getTerminator());
2853 assert(LoadTaskLB !=
nullptr &&
"Expected value for LoadTaskLB");
2854 assert(LoadTaskUB !=
nullptr &&
"Expected value for LoadTaskUB");
2855 assert(LoadTaskStep !=
nullptr &&
"Expected value for LoadTaskStep");
2857 Builder.CreateSub(LoadTaskUB, LoadTaskLB), LoadTaskStep);
2858 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One,
"trip_cnt");
2859 Value *CastedTripCount =
Builder.CreateIntCast(TripCount, IVTy,
true);
2860 Value *CastedTaskLB =
Builder.CreateIntCast(LoadTaskLB, IVTy,
true);
2862 CLI->setTripCount(CastedTripCount);
2864 Builder.SetInsertPoint(CLI->getBody()->getFirstInsertionPt());
2866 if (NumOfCollapseLoops > 1) {
2872 Builder.CreateSub(CastedTaskLB, ConstantInt::get(IVTy, 1)));
2875 for (
auto IVUse = CLI->getIndVar()->uses().begin();
2876 IVUse != CLI->getIndVar()->uses().end(); IVUse++) {
2877 User *IVUser = IVUse->getUser();
2879 if (
Op->getOpcode() == Instruction::URem ||
2880 Op->getOpcode() == Instruction::UDiv) {
2885 for (User *User : UsersToReplace) {
2886 User->replaceUsesOfWith(CLI->getIndVar(), IVPlusTaskLB);
2903 assert(CLI->getIndVar()->getNumUses() == 3 &&
2904 "Canonical loop should have exactly three uses of the ind var");
2905 for (User *IVUser : CLI->getIndVar()->users()) {
2907 if (
Mul->getOpcode() == Instruction::Mul) {
2908 for (User *MulUser :
Mul->users()) {
2910 if (
Add->getOpcode() == Instruction::Add) {
2911 Add->setOperand(1, CastedTaskLB);
2920 FakeLB->replaceAllUsesWith(CastedLBVal);
2921 FakeUB->replaceAllUsesWith(CastedUBVal);
2922 FakeStep->replaceAllUsesWith(CastedStepVal);
2924 I->eraseFromParent();
2935 M.getContext(),
M.getDataLayout().getPointerSizeInBits());
2945 bool Mergeable,
Value *EventHandle,
Value *Priority,
bool FreeAgent) {
2976 if (
Error Err = BodyGenCB(TaskAllocaIP, TaskBodyIP, TaskExitBB))
2979 auto OI = std::make_unique<OutlineInfo>();
2980 OI->EntryBB = TaskAllocaBB;
2981 OI->OuterAllocBB = AllocaIP.getNodeParent();
2982 OI->ExitBB = TaskExitBB;
2983 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2984 copy(DeallocBlocks, OI->OuterDeallocBBs.
end());
2989 Builder, AllocaIP, ToBeDeleted, TaskAllocaIP,
"global.tid",
false));
2991 OI->PostOutlineCB = [
this, Ident, Tied, Final, IfCondition, Dependencies,
2992 Affinities, Mergeable, Priority, EventHandle, FreeAgent,
2994 ToBeDeleted](
Function &OutlinedFn)
mutable {
2996 assert(OutlinedFn.hasOneUse() &&
2997 "there must be a single user for the outlined function");
3002 bool HasShareds = StaleCI->
arg_size() > 1;
3003 Builder.SetInsertPoint(StaleCI);
3030 bool UseMergedIf0Path = ConstIfCondition && ConstIfCondition->isZero();
3034 Flags =
Builder.CreateOr(FinalFlag, Flags);
3037 if (Mergeable || UseMergedIf0Path)
3051 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
3060 assert(ArgStructAlloca &&
3061 "Unable to find the alloca instruction corresponding to arguments "
3062 "for extracted function");
3063 std::optional<TypeSize> ArgAllocSize =
3066 "Unable to determine size of arguments for extracted function");
3067 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
3073 TaskAllocFn, {Ident, ThreadID, Flags,
3074 TaskSize, SharedsSize,
3077 if (Affinities.
Count && Affinities.
Info) {
3079 OMPRTL___kmpc_omp_reg_task_with_affinity);
3090 OMPRTL___kmpc_task_allow_completion_event);
3094 Builder.CreatePointerBitCastOrAddrSpaceCast(EventHandle,
3096 EventVal =
Builder.CreatePtrToInt(EventVal,
Builder.getInt64Ty());
3097 Builder.CreateStore(EventVal, EventHandleAddr);
3103 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
3118 Constant *Zero = ConstantInt::get(Int32Ty, 0);
3122 Builder.CreateInBoundsGEP(TaskPtr, TaskData, {Zero, Zero});
3125 VoidPtr, VoidPtr,
Builder.getInt32Ty(), VoidPtr, VoidPtr);
3127 TaskStructType, TaskGEP, {Zero, ConstantInt::get(Int32Ty, 4)});
3130 Value *CmplrData =
Builder.CreateInBoundsGEP(CmplrStructType,
3131 PriorityData, {Zero, Zero});
3132 Builder.CreateStore(Priority, CmplrData);
3135 Value *DepArray =
nullptr;
3136 Value *NumDeps =
nullptr;
3139 NumDeps = Dependencies.
NumDeps;
3140 }
else if (!Dependencies.
Deps.empty()) {
3142 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
3162 if (IfCondition && !UseMergedIf0Path) {
3167 Builder.GetInsertPoint()->getParent()->getTerminator();
3168 Instruction *ThenTI = IfTerminator, *ElseTI =
nullptr;
3169 Builder.SetInsertPoint(IfTerminator);
3172 Builder.SetInsertPoint(ElseTI);
3179 {Ident, ThreadID, NumDeps, DepArray,
3180 ConstantInt::get(
Builder.getInt32Ty(), 0),
3195 Builder.SetInsertPoint(ThenTI);
3203 {Ident, ThreadID, TaskData, NumDeps, DepArray,
3204 ConstantInt::get(
Builder.getInt32Ty(), 0),
3217 LoadInst *Shareds =
Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
3218 OutlinedFn.getArg(1)->replaceUsesWithIf(
3219 Shareds, [Shareds](
Use &U) {
return U.getUser() != Shareds; });
3225 Builder.ClearInsertionPoint();
3227 I->eraseFromParent();
3253 if (
Error Err = BodyGenCB(AllocaIP,
Builder.saveIP(), DeallocBlocks))
3256 Builder.SetInsertPoint(TaskgroupExitBB);
3299 unsigned CaseNumber = 0;
3300 for (
auto SectionCB : SectionCBs) {
3302 M.getContext(),
"omp_section_loop.body.case", CurFn,
Continue);
3304 Builder.SetInsertPoint(CaseBB);
3317 Value *LB = ConstantInt::get(I32Ty, 0);
3318 Value *UB = ConstantInt::get(I32Ty, SectionCBs.
size());
3319 Value *ST = ConstantInt::get(I32Ty, 1);
3321 Loc, LoopBodyGenCB, LB, UB, ST,
true,
false, AllocaIP,
"section_loop");
3326 applyStaticWorkshareLoop(
Loc.DL, *
LoopInfo, AllocaIP,
3327 WorksharingLoopType::ForStaticLoop, !IsNowait);
3333 assert(LoopFini &&
"Bad structure of static workshare loop finalization");
3337 assert(FiniInfo.DK == OMPD_sections &&
3338 "Unexpected finalization stack state!");
3339 if (
Error Err = FiniInfo.mergeFiniBB(
Builder, LoopFini))
3353 if (IP != IP.getNodeParent()->end())
3364 auto *CaseBB =
Loc.IP.getNodeParent();
3365 auto *CondBB = CaseBB->getSinglePredecessor()->getSinglePredecessor();
3366 auto *ExitBB = CondBB->getTerminator()->getSuccessor(1);
3368 IP =
I->getIterator();
3372 Directive OMPD = Directive::OMPD_sections;
3375 return EmitOMPInlinedRegion(OMPD,
nullptr,
nullptr, BodyGenCB, FiniCBWrapper,
3386Value *OpenMPIRBuilder::getGPUThreadID() {
3389 OMPRTL___kmpc_get_hardware_thread_id_in_block),
3393Value *OpenMPIRBuilder::getGPUWarpSize() {
3398Value *OpenMPIRBuilder::getNVPTXWarpID() {
3399 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3400 return Builder.CreateAShr(getGPUThreadID(), LaneIDBits,
"nvptx_warp_id");
3403Value *OpenMPIRBuilder::getNVPTXLaneID() {
3404 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3405 assert(LaneIDBits < 32 &&
"Invalid LaneIDBits size in NVPTX device.");
3406 unsigned LaneIDMask = ~0
u >> (32u - LaneIDBits);
3407 return Builder.CreateAnd(getGPUThreadID(),
Builder.getInt32(LaneIDMask),
3414 uint64_t FromSize =
M.getDataLayout().getTypeStoreSize(FromType);
3415 uint64_t ToSize =
M.getDataLayout().getTypeStoreSize(ToType);
3416 assert(FromSize > 0 &&
"From size must be greater than zero");
3417 assert(ToSize > 0 &&
"To size must be greater than zero");
3418 if (FromType == ToType)
3420 if (FromSize == ToSize)
3421 return Builder.CreateBitCast(From, ToType);
3423 return Builder.CreateIntCast(From, ToType,
true);
3429 Value *ValCastItem =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3430 CastItem,
Builder.getPtrTy(0));
3431 Builder.CreateStore(From, ValCastItem);
3432 return Builder.CreateLoad(ToType, CastItem);
3439 uint64_t Size =
M.getDataLayout().getTypeStoreSize(ElementType);
3440 assert(
Size <= 8 &&
"Unsupported bitwidth in shuffle instruction");
3444 Value *ElemCast = castValueToType(AllocaIP, Element, CastTy);
3446 Builder.CreateIntCast(getGPUWarpSize(),
Builder.getInt16Ty(),
true);
3448 Size <= 4 ? RuntimeFunction::OMPRTL___kmpc_shuffle_int32
3449 : RuntimeFunction::OMPRTL___kmpc_shuffle_int64);
3450 Value *WarpSizeCast =
3452 Value *ShuffleCall =
3457 return castValueToType(AllocaIP, ShuffleCall, ElementType);
3464 uint64_t Size =
M.getDataLayout().getTypeStoreSize(ElemType);
3476 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3477 Value *ElemPtr = DstAddr;
3478 Value *Ptr = SrcAddr;
3479 for (
unsigned IntSize = 8; IntSize >= 1; IntSize /= 2) {
3483 Ptr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3486 Builder.CreateGEP(ElemType, SrcAddr, {ConstantInt::get(IndexTy, 1)});
3487 ElemPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3491 if ((
Size / IntSize) > 1) {
3492 Value *PtrEnd =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3493 SrcAddrGEP,
Builder.getPtrTy());
3510 Builder.CreatePointerBitCastOrAddrSpaceCast(Ptr,
Builder.getPtrTy()));
3512 Builder.CreateICmpSGT(PtrDiff,
Builder.getInt64(IntSize - 1)), ThenBB,
3515 Value *Res = createRuntimeShuffleFunction(
3518 IntType, Ptr,
M.getDataLayout().getPrefTypeAlign(ElemType)),
3520 Builder.CreateAlignedStore(Res, ElemPtr,
3521 M.getDataLayout().getPrefTypeAlign(ElemType));
3523 Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3524 Value *LocalElemPtr =
3525 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3533 Value *Res = createRuntimeShuffleFunction(
3534 AllocaIP,
Builder.CreateLoad(IntType, Ptr), IntType,
Offset);
3535 Builder.CreateStore(Res, ElemPtr);
3536 Ptr =
Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3538 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3544Error OpenMPIRBuilder::emitReductionListCopy(
3549 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3550 Value *RemoteLaneOffset = CopyOptions.RemoteLaneOffset;
3554 for (
auto En :
enumerate(ReductionInfos)) {
3556 Value *SrcElementAddr =
nullptr;
3557 AllocaInst *DestAlloca =
nullptr;
3558 Value *DestElementAddr =
nullptr;
3559 Value *DestElementPtrAddr =
nullptr;
3561 bool ShuffleInElement =
false;
3564 bool UpdateDestListPtr =
false;
3568 ReductionArrayTy, SrcBase,
3569 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3570 SrcElementAddr =
Builder.CreateLoad(
Builder.getPtrTy(), SrcElementPtrAddr);
3574 DestElementPtrAddr =
Builder.CreateInBoundsGEP(
3575 ReductionArrayTy, DestBase,
3576 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3577 bool IsByRefElem = (!IsByRef.
empty() && IsByRef[En.index()]);
3583 Type *DestAllocaType =
3584 IsByRefElem ? RI.ByRefAllocatedType : RI.ElementType;
3585 DestAlloca =
Builder.CreateAlloca(DestAllocaType,
nullptr,
3586 ".omp.reduction.element");
3588 M.getDataLayout().getPrefTypeAlign(DestAllocaType));
3589 DestElementAddr = DestAlloca;
3592 DestElementAddr->
getName() +
".ascast");
3594 ShuffleInElement =
true;
3595 UpdateDestListPtr =
true;
3607 if (ShuffleInElement) {
3608 Type *ShuffleType = RI.ElementType;
3609 Value *ShuffleSrcAddr = SrcElementAddr;
3610 Value *ShuffleDestAddr = DestElementAddr;
3611 AllocaInst *LocalStorage =
nullptr;
3614 assert(RI.ByRefElementType &&
"Expected by-ref element type to be set");
3615 assert(RI.ByRefAllocatedType &&
3616 "Expected by-ref allocated type to be set");
3621 ShuffleType = RI.ByRefElementType;
3623 if (RI.DataPtrPtrGen) {
3626 Builder.saveIP(), ShuffleSrcAddr, ShuffleSrcAddr);
3629 return GenResult.takeError();
3638 LocalStorage =
Builder.CreateAlloca(ShuffleType);
3640 ShuffleDestAddr = LocalStorage;
3645 ShuffleDestAddr = DestElementAddr;
3649 shuffleAndStore(AllocaIP, ShuffleSrcAddr, ShuffleDestAddr, ShuffleType,
3650 RemoteLaneOffset, ReductionArrayTy, IsByRefElem);
3652 if (IsByRefElem && RI.DataPtrPtrGen) {
3654 Value *DestDescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3655 DestAlloca,
Builder.getPtrTy(),
".ascast");
3658 DestDescriptorAddr, LocalStorage, SrcElementAddr,
3659 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
3662 return GenResult.takeError();
3665 switch (RI.EvaluationKind) {
3667 Value *Elem =
Builder.CreateLoad(RI.ElementType, SrcElementAddr);
3669 Builder.CreateStore(Elem, DestElementAddr);
3673 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3674 RI.ElementType, SrcElementAddr, 0, 0,
".realp");
3676 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
3678 RI.ElementType, SrcElementAddr, 0, 1,
".imagp");
3680 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
3682 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3683 RI.ElementType, DestElementAddr, 0, 0,
".realp");
3684 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
3685 RI.ElementType, DestElementAddr, 0, 1,
".imagp");
3686 Builder.CreateStore(SrcReal, DestRealPtr);
3687 Builder.CreateStore(SrcImg, DestImgPtr);
3692 M.getDataLayout().getTypeStoreSize(RI.ElementType));
3694 DestElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3695 SrcElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3707 if (UpdateDestListPtr) {
3708 Value *CastDestAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3709 DestElementAddr,
Builder.getPtrTy(),
3710 DestElementAddr->
getName() +
".ascast");
3711 Builder.CreateStore(CastDestAddr, DestElementPtrAddr);
3718Expected<Function *> OpenMPIRBuilder::emitInterWarpCopyFunction(
3721 IRBuilder<>::InsertPointGuard IPG(
Builder);
3722 LLVMContext &Ctx =
M.getContext();
3724 Builder.getVoidTy(), {Builder.getPtrTy(), Builder.getInt32Ty()},
3728 "_omp_reduction_inter_warp_copy_func", &
M);
3734 Builder.SetInsertPoint(EntryBB);
3752 StringRef TransferMediumName =
3753 "__openmp_nvptx_data_transfer_temporary_storage";
3754 GlobalVariable *TransferMedium =
M.getGlobalVariable(TransferMediumName);
3755 unsigned WarpSize =
Config.getGridValue().GV_Warp_Size;
3757 if (!TransferMedium) {
3758 TransferMedium =
new GlobalVariable(
3766 Value *GPUThreadID = getGPUThreadID();
3768 Value *LaneID = getNVPTXLaneID();
3770 Value *WarpID = getNVPTXWarpID();
3776 AllocaInst *ReduceListAlloca =
Builder.CreateAlloca(
3777 Arg0Type,
nullptr, ReduceListArg->
getName() +
".addr");
3778 AllocaInst *NumWarpsAlloca =
3779 Builder.CreateAlloca(Arg1Type,
nullptr, NumWarpsArg->
getName() +
".addr");
3780 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3781 ReduceListAlloca, Arg0Type, ReduceListAlloca->
getName() +
".ascast");
3782 Value *NumWarpsAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3783 NumWarpsAlloca,
Builder.getPtrTy(0),
3784 NumWarpsAlloca->
getName() +
".ascast");
3785 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
3786 Builder.CreateStore(NumWarpsArg, NumWarpsAddrCast);
3795 for (
auto En :
enumerate(ReductionInfos)) {
3801 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
3802 unsigned RealTySize =
M.getDataLayout().getTypeAllocSize(
3803 IsByRefElem ? RI.ByRefElementType : RI.ElementType);
3804 for (
unsigned TySize = 4; TySize > 0 && RealTySize > 0; TySize /= 2) {
3807 unsigned NumIters = RealTySize / TySize;
3810 Value *Cnt =
nullptr;
3811 Value *CntAddr =
nullptr;
3818 Builder.CreateAlloca(
Builder.getInt32Ty(),
nullptr,
".cnt.addr");
3820 CntAddr =
Builder.CreateAddrSpaceCast(CntAddr,
Builder.getPtrTy(),
3821 CntAddr->
getName() +
".ascast");
3833 Cnt, ConstantInt::get(
Builder.getInt32Ty(), NumIters));
3834 Builder.CreateCondBr(Cmp, BodyBB, ExitBB);
3841 omp::Directive::OMPD_unknown,
3845 return BarrierIP1.takeError();
3851 Value *IsWarpMaster =
Builder.CreateIsNull(LaneID,
"warp_master");
3852 Builder.CreateCondBr(IsWarpMaster, ThenBB, ElseBB);
3856 auto *RedListArrayTy =
3859 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3861 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3862 {ConstantInt::get(IndexTy, 0),
3863 ConstantInt::get(IndexTy, En.index())});
3867 if (IsByRefElem && RI.DataPtrPtrGen) {
3869 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
3872 return GenRes.takeError();
3883 ArrayTy, TransferMedium, {
Builder.getInt64(0), WarpID});
3888 Builder.CreateStore(Elem, MediumPtr,
3900 omp::Directive::OMPD_unknown,
3904 return BarrierIP2.takeError();
3911 Value *NumWarpsVal =
3914 Value *IsActiveThread =
3915 Builder.CreateICmpULT(GPUThreadID, NumWarpsVal,
"is_active_thread");
3916 Builder.CreateCondBr(IsActiveThread, W0ThenBB, W0ElseBB);
3923 ArrayTy, TransferMedium, {
Builder.getInt64(0), GPUThreadID});
3925 Value *TargetElemPtrPtr =
3926 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3927 {ConstantInt::get(IndexTy, 0),
3928 ConstantInt::get(IndexTy, En.index())});
3929 Value *TargetElemPtrVal =
3931 Value *TargetElemPtr = TargetElemPtrVal;
3933 if (IsByRefElem && RI.DataPtrPtrGen) {
3935 RI.DataPtrPtrGen(
Builder.saveIP(), TargetElemPtr, TargetElemPtr);
3938 return GenRes.takeError();
3940 TargetElemPtr =
Builder.CreateLoad(
Builder.getPtrTy(), TargetElemPtr);
3948 Value *SrcMediumValue =
3949 Builder.CreateLoad(CType, SrcMediumPtrVal,
true);
3950 Builder.CreateStore(SrcMediumValue, TargetElemPtr);
3960 Cnt, ConstantInt::get(
Builder.getInt32Ty(), 1));
3961 Builder.CreateStore(Cnt, CntAddr,
false);
3963 auto *CurFn =
Builder.GetInsertBlock()->getParent();
3967 RealTySize %= TySize;
3976Expected<Function *> OpenMPIRBuilder::emitShuffleAndReduceFunction(
3979 LLVMContext &Ctx =
M.getContext();
3980 IRBuilder<>::InsertPointGuard IPG(
Builder);
3981 FunctionType *FuncTy =
3983 {Builder.getPtrTy(), Builder.getInt16Ty(),
3984 Builder.getInt16Ty(), Builder.getInt16Ty()},
3988 "_omp_reduction_shuffle_and_reduce_func", &
M);
3999 Builder.SetInsertPoint(EntryBB);
4011 Type *ReduceListArgType = ReduceListArg->
getType();
4015 ReduceListArgType,
nullptr, ReduceListArg->
getName() +
".addr");
4016 Value *LaneIdAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
4017 LaneIDArg->
getName() +
".addr");
4019 LaneIDArgType,
nullptr, RemoteLaneOffsetArg->
getName() +
".addr");
4020 Value *AlgoVerAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
4021 AlgoVerArg->
getName() +
".addr");
4028 RedListArrayTy,
nullptr,
".omp.reduction.remote_reduce_list");
4030 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4031 ReduceListAlloca, ReduceListArgType,
4032 ReduceListAlloca->
getName() +
".ascast");
4033 Value *LaneIdAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4034 LaneIdAlloca, LaneIDArgPtrType, LaneIdAlloca->
getName() +
".ascast");
4035 Value *RemoteLaneOffsetAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4036 RemoteLaneOffsetAlloca, LaneIDArgPtrType,
4037 RemoteLaneOffsetAlloca->
getName() +
".ascast");
4038 Value *AlgoVerAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4039 AlgoVerAlloca, LaneIDArgPtrType, AlgoVerAlloca->
getName() +
".ascast");
4040 Value *RemoteListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4041 RemoteReductionListAlloca,
Builder.getPtrTy(),
4042 RemoteReductionListAlloca->
getName() +
".ascast");
4044 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
4045 Builder.CreateStore(LaneIDArg, LaneIdAddrCast);
4046 Builder.CreateStore(RemoteLaneOffsetArg, RemoteLaneOffsetAddrCast);
4047 Builder.CreateStore(AlgoVerArg, AlgoVerAddrCast);
4049 Value *ReduceList =
Builder.CreateLoad(ReduceListArgType, ReduceListAddrCast);
4050 Value *LaneId =
Builder.CreateLoad(LaneIDArgType, LaneIdAddrCast);
4051 Value *RemoteLaneOffset =
4052 Builder.CreateLoad(LaneIDArgType, RemoteLaneOffsetAddrCast);
4053 Value *AlgoVer =
Builder.CreateLoad(LaneIDArgType, AlgoVerAddrCast);
4060 Error EmitRedLsCpRes = emitReductionListCopy(
4062 ReduceList, RemoteListAddrCast, IsByRef,
4063 {RemoteLaneOffset,
nullptr,
nullptr});
4066 return EmitRedLsCpRes;
4091 Value *LaneComp =
Builder.CreateICmpULT(LaneId, RemoteLaneOffset);
4096 Value *Algo2AndLaneIdComp =
Builder.CreateAnd(Algo2, LaneIdComp);
4097 Value *RemoteOffsetComp =
4099 Value *CondAlgo2 =
Builder.CreateAnd(Algo2AndLaneIdComp, RemoteOffsetComp);
4100 Value *CA0OrCA1 =
Builder.CreateOr(CondAlgo0, CondAlgo1);
4101 Value *CondReduce =
Builder.CreateOr(CA0OrCA1, CondAlgo2);
4107 Builder.CreateCondBr(CondReduce, ThenBB, ElseBB);
4109 Value *LocalReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4110 ReduceList,
Builder.getPtrTy());
4111 Value *RemoteReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4112 RemoteListAddrCast,
Builder.getPtrTy());
4114 ->addFnAttr(Attribute::NoUnwind);
4125 Value *LaneIdGtOffset =
Builder.CreateICmpUGE(LaneId, RemoteLaneOffset);
4126 Value *CondCopy =
Builder.CreateAnd(Algo1, LaneIdGtOffset);
4131 Builder.CreateCondBr(CondCopy, CpyThenBB, CpyElseBB);
4135 EmitRedLsCpRes = emitReductionListCopy(
4137 RemoteListAddrCast, ReduceList, IsByRef);
4140 return EmitRedLsCpRes;
4155OpenMPIRBuilder::generateReductionDescriptor(
4157 Type *DescriptorType,
4163 Value *DescriptorSize =
4164 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(DescriptorType));
4166 DescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4167 SrcDescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4171 Value *DataPtrField;
4173 DataPtrPtrGen(
Builder.saveIP(), DescriptorAddr, DataPtrField);
4176 return GenResult.takeError();
4179 DataPtr,
Builder.getPtrTy(),
".ascast"),
4185Expected<Value *> OpenMPIRBuilder::createReductionDescriptorCopy(
4187 Value *SrcDescriptorAddr,
Type *DescriptorPtrTy,
const Twine &Name) {
4191 AllocaInst *DescriptorAlloca =
4192 Builder.CreateAlloca(RI.ByRefAllocatedType,
nullptr, Name);
4194 M.getDataLayout().getPrefTypeAlign(RI.ByRefAllocatedType));
4195 Value *DescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4196 DescriptorAlloca, DescriptorPtrTy,
4197 DescriptorAlloca->
getName() +
".ascast");
4202 generateReductionDescriptor(DescriptorAddr, DataPtr, SrcDescriptorAddr,
4203 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
4205 return GenResult.takeError();
4207 return DescriptorAddr;
4210Expected<Function *> OpenMPIRBuilder::emitListToGlobalCopyFunction(
4213 IRBuilder<>::InsertPointGuard IPG(
Builder);
4214 LLVMContext &Ctx =
M.getContext();
4217 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4221 "_omp_reduction_list_to_global_copy_func", &
M);
4228 Builder.SetInsertPoint(EntryBlock);
4239 BufferArg->
getName() +
".addr");
4243 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4244 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4245 BufferArgAlloca,
Builder.getPtrTy(),
4246 BufferArgAlloca->
getName() +
".ascast");
4247 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4248 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4249 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4250 ReduceListArgAlloca,
Builder.getPtrTy(),
4251 ReduceListArgAlloca->
getName() +
".ascast");
4253 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4254 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4255 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4257 Value *LocalReduceList =
4259 Value *BufferArgVal =
4263 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4264 for (
auto En :
enumerate(ReductionInfos)) {
4266 auto *RedListArrayTy =
4270 RedListArrayTy, LocalReduceList,
4271 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4277 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferArgVal, Idxs);
4279 ReductionsBufferTy, BufferVD, 0, En.index());
4281 switch (RI.EvaluationKind) {
4283 Value *TargetElement;
4285 if (IsByRef.
empty() || !IsByRef[En.index()]) {
4286 TargetElement =
Builder.CreateLoad(RI.ElementType, ElemPtr);
4288 if (RI.DataPtrPtrGen) {
4290 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
4293 return GenResult.takeError();
4297 TargetElement =
Builder.CreateLoad(RI.ByRefElementType, ElemPtr);
4300 Builder.CreateStore(TargetElement, GlobVal);
4304 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4305 RI.ElementType, ElemPtr, 0, 0,
".realp");
4307 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
4309 RI.ElementType, ElemPtr, 0, 1,
".imagp");
4311 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
4313 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4314 RI.ElementType, GlobVal, 0, 0,
".realp");
4315 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4316 RI.ElementType, GlobVal, 0, 1,
".imagp");
4317 Builder.CreateStore(SrcReal, DestRealPtr);
4318 Builder.CreateStore(SrcImg, DestImgPtr);
4323 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(RI.ElementType));
4325 GlobVal,
M.getDataLayout().getPrefTypeAlign(RI.ElementType), ElemPtr,
4326 M.getDataLayout().getPrefTypeAlign(RI.ElementType), SizeVal,
false);
4336Expected<Function *> OpenMPIRBuilder::emitListToGlobalReduceFunction(
4339 IRBuilder<>::InsertPointGuard IPG(
Builder);
4340 LLVMContext &Ctx =
M.getContext();
4343 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4347 "_omp_reduction_list_to_global_reduce_func", &
M);
4354 Builder.SetInsertPoint(EntryBlock);
4365 BufferArg->
getName() +
".addr");
4369 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4370 auto *RedListArrayTy =
4375 Value *LocalReduceList =
4376 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4380 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4381 BufferArgAlloca,
Builder.getPtrTy(),
4382 BufferArgAlloca->
getName() +
".ascast");
4383 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4384 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4385 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4386 ReduceListArgAlloca,
Builder.getPtrTy(),
4387 ReduceListArgAlloca->
getName() +
".ascast");
4388 Value *LocalReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4389 LocalReduceList,
Builder.getPtrTy(),
4390 LocalReduceList->
getName() +
".ascast");
4392 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4393 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4394 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4399 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4400 for (
auto En :
enumerate(ReductionInfos)) {
4403 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4404 RedListArrayTy, LocalReduceListAddrCast,
4405 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4407 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4409 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4410 ReductionsBufferTy, BufferVD, 0, En.index());
4412 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4416 Value *SrcElementPtrPtr =
4417 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
4418 {ConstantInt::get(IndexTy, 0),
4419 ConstantInt::get(IndexTy, En.index())});
4420 Value *SrcDescriptorAddr =
4424 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4425 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4429 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4431 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4439 ->addFnAttr(Attribute::NoUnwind);
4444Expected<Function *> OpenMPIRBuilder::emitGlobalToListCopyFunction(
4447 IRBuilder<>::InsertPointGuard IPG(
Builder);
4448 LLVMContext &Ctx =
M.getContext();
4451 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4455 "_omp_reduction_global_to_list_copy_func", &
M);
4462 Builder.SetInsertPoint(EntryBlock);
4473 BufferArg->
getName() +
".addr");
4477 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4478 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4479 BufferArgAlloca,
Builder.getPtrTy(),
4480 BufferArgAlloca->
getName() +
".ascast");
4481 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4482 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4483 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4484 ReduceListArgAlloca,
Builder.getPtrTy(),
4485 ReduceListArgAlloca->
getName() +
".ascast");
4486 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4487 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4488 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4490 Value *LocalReduceList =
4495 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4496 for (
auto En :
enumerate(ReductionInfos)) {
4497 const OpenMPIRBuilder::ReductionInfo &RI = En.value();
4498 auto *RedListArrayTy =
4502 RedListArrayTy, LocalReduceList,
4503 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4508 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4509 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4510 ReductionsBufferTy, BufferVD, 0, En.index());
4516 if (!IsByRef.
empty() && IsByRef[En.index()]) {
4523 return GenResult.takeError();
4529 Value *TargetElement =
Builder.CreateLoad(ElemType, GlobValPtr);
4530 Builder.CreateStore(TargetElement, ElemPtr);
4534 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4543 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4545 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4547 Builder.CreateStore(SrcReal, DestRealPtr);
4548 Builder.CreateStore(SrcImg, DestImgPtr);
4555 ElemPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4556 GlobValPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4567Expected<Function *> OpenMPIRBuilder::emitGlobalToListReduceFunction(
4570 IRBuilder<>::InsertPointGuard IPG(
Builder);
4571 LLVMContext &Ctx =
M.getContext();
4574 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4578 "_omp_reduction_global_to_list_reduce_func", &
M);
4585 Builder.SetInsertPoint(EntryBlock);
4596 BufferArg->
getName() +
".addr");
4600 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4606 Value *LocalReduceList =
4607 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4611 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4612 BufferArgAlloca,
Builder.getPtrTy(),
4613 BufferArgAlloca->
getName() +
".ascast");
4614 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4615 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4616 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4617 ReduceListArgAlloca,
Builder.getPtrTy(),
4618 ReduceListArgAlloca->
getName() +
".ascast");
4619 Value *ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4620 LocalReduceList,
Builder.getPtrTy(),
4621 LocalReduceList->
getName() +
".ascast");
4623 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4624 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4625 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4630 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4631 for (
auto En :
enumerate(ReductionInfos)) {
4634 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4635 RedListArrayTy, ReductionList,
4636 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4639 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4640 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4641 ReductionsBufferTy, BufferVD, 0, En.index());
4643 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4645 Value *ReduceListVal =
4647 Value *SrcElementPtrPtr =
4648 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceListVal,
4649 {ConstantInt::get(IndexTy, 0),
4650 ConstantInt::get(IndexTy, En.index())});
4651 Value *SrcDescriptorAddr =
4655 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4656 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4660 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4662 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4670 ->addFnAttr(Attribute::NoUnwind);
4675std::string OpenMPIRBuilder::getReductionFuncName(StringRef Name)
const {
4676 std::string Suffix =
4678 return (Name + Suffix).str();
4681Expected<Function *> OpenMPIRBuilder::createReductionFunction(
4684 AttributeList FuncAttrs) {
4685 IRBuilder<>::InsertPointGuard IPG(
Builder);
4687 {Builder.getPtrTy(), Builder.getPtrTy()},
4689 std::string
Name = getReductionFuncName(ReducerName);
4698 Builder.SetInsertPoint(EntryBB);
4703 Value *LHSArrayPtr =
nullptr;
4704 Value *RHSArrayPtr =
nullptr;
4711 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
4713 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
4714 Value *LHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4715 LHSAlloca, Arg0Type, LHSAlloca->
getName() +
".ascast");
4716 Value *RHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4717 RHSAlloca, Arg1Type, RHSAlloca->
getName() +
".ascast");
4718 Builder.CreateStore(Arg0, LHSAddrCast);
4719 Builder.CreateStore(Arg1, RHSAddrCast);
4720 LHSArrayPtr =
Builder.CreateLoad(Arg0Type, LHSAddrCast);
4721 RHSArrayPtr =
Builder.CreateLoad(Arg1Type, RHSAddrCast);
4725 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4727 for (
auto En :
enumerate(ReductionInfos)) {
4730 RedArrayTy, RHSArrayPtr,
4731 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4733 Value *RHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4734 RHSI8Ptr, RI.PrivateVariable->getType(),
4735 RHSI8Ptr->
getName() +
".ascast");
4738 RedArrayTy, LHSArrayPtr,
4739 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4741 Value *LHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4742 LHSI8Ptr, RI.Variable->getType(), LHSI8Ptr->
getName() +
".ascast");
4751 if (!IsByRef.
empty() && !IsByRef[En.index()]) {
4752 LHS =
Builder.CreateLoad(RI.ElementType, LHSPtr);
4753 RHS =
Builder.CreateLoad(RI.ElementType, RHSPtr);
4760 return AfterIP.takeError();
4761 if (!
Builder.GetInsertBlock())
4762 return ReductionFunc;
4766 if (!IsByRef.
empty() && !IsByRef[En.index()])
4767 Builder.CreateStore(Reduced, LHSPtr);
4772 for (
auto En :
enumerate(ReductionInfos)) {
4773 unsigned Index = En.index();
4775 Value *LHSFixupPtr, *RHSFixupPtr;
4776 Builder.restoreIP(RI.ReductionGenClang(
4777 Builder.saveIP(), Index, &LHSFixupPtr, &RHSFixupPtr, ReductionFunc));
4782 LHSPtrs[Index], [ReductionFunc](
const Use &U) {
4787 RHSPtrs[Index], [ReductionFunc](
const Use &U) {
4801 return ReductionFunc;
4809 assert(RI.Variable &&
"expected non-null variable");
4810 assert(RI.PrivateVariable &&
"expected non-null private variable");
4811 assert((RI.ReductionGen || RI.ReductionGenClang) &&
4812 "expected non-null reduction generator callback");
4815 RI.Variable->getType() == RI.PrivateVariable->getType() &&
4816 "expected variables and their private equivalents to have the same "
4819 assert(RI.Variable->getType()->isPointerTy() &&
4820 "expected variables to be pointers");
4837 ArrayRef<bool> IsByRef,
bool IsNoWait,
bool IsTeamsReduction,
bool IsSPMD,
4839 Value *SrcLocInfo) {
4854 if (ReductionInfos.
size() == 0)
4868 AttrBuilder AttrBldr(Ctx);
4870 AttrBldr.addAttribute(Attr);
4871 AttrBldr.removeAttribute(Attribute::OptimizeNone);
4872 FuncAttrs = FuncAttrs.addFnAttributes(Ctx, AttrBldr);
4875 Builder.GetInsertBlock()->getParent()->getName(), ReductionInfos, IsByRef,
4877 if (!ReductionResult)
4879 Function *ReductionFunc = *ReductionResult;
4882 if (GridValue.has_value())
4883 Config.setGridValue(GridValue.value());
4898 Builder.getPtrTy(
M.getDataLayout().getProgramAddressSpace());
4900 Value *ReductionList;
4904 Value *ReductionListAlloca =
4905 Builder.CreateAlloca(RedArrayTy,
nullptr,
".omp.reduction.red_list");
4906 ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4907 ReductionListAlloca, PtrTy, ReductionListAlloca->
getName() +
".ascast");
4910 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4911 for (
auto En :
enumerate(ReductionInfos)) {
4914 RedArrayTy, ReductionList,
4915 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4918 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
4923 Builder.CreatePointerBitCastOrAddrSpaceCast(PrivateVar, PtrTy);
4924 Builder.CreateStore(CastElem, ElemPtr);
4927 ReductionInfos, ReductionFunc, FuncAttrs, IsByRef);
4933 emitInterWarpCopyFunction(
Loc, ReductionInfos, FuncAttrs, IsByRef);
4938 Value *RL =
Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList, PtrTy);
4947 unsigned MaxDataSize = 0;
4949 for (
auto En :
enumerate(ReductionInfos)) {
4953 Type *RedTypeArg = (!IsByRef.
empty() && IsByRef[En.index()])
4954 ? En.value().ByRefElementType
4955 : En.value().ElementType;
4956 auto Size =
M.getDataLayout().getTypeStoreSize(RedTypeArg);
4957 if (
Size > MaxDataSize)
4961 Value *ReductionDataSize =
4962 Builder.getInt64(MaxDataSize * ReductionInfos.
size());
4966 Function *CopyScratchToListFunc =
nullptr;
4968 Value *ScratchForCopyBack =
nullptr;
4971 Value *RLForCopyBack = RL;
4973 bool IsAtomicReduction =
4976 if (!IsTeamsReduction) {
4977 Value *SarFuncCast =
4978 Builder.CreatePointerBitCastOrAddrSpaceCast(*SarFunc, FuncPtrTy);
4980 Builder.CreatePointerBitCastOrAddrSpaceCast(WcFunc, FuncPtrTy);
4981 Value *Args[] = {SrcLocInfo, ReductionDataSize, RL, SarFuncCast,
4984 RuntimeFunction::OMPRTL___kmpc_nvptx_parallel_reduce_nowait_v2);
4986 }
else if (IsAtomicReduction) {
4990 RuntimeFunction::OMPRTL___kmpc_is_team_main_thread);
4994 Ctx, ReductionTypeArgs,
"struct._globalized_locals_ty");
4997 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
5002 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
5007 ReductionInfos, ReductionFunc, ReductionsBufferTy, FuncAttrs, IsByRef);
5028 Value *RuntimeRL = RL;
5031 Value *PerThreadScratch;
5037 Value *PerThreadScratchAlloca =
5038 Builder.CreateAlloca(ReductionsBufferTy,
nullptr,
5039 ".omp.reduction.scratch");
5040 PerThreadScratch =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5041 PerThreadScratchAlloca, PtrTy,
5042 PerThreadScratchAlloca->
getName() +
".ascast");
5045 Value *PerThreadRedListAlloca =
5046 Builder.CreateAlloca(RedArrayTy,
nullptr,
5047 ".omp.reduction.per_thread_red_list");
5048 RuntimeRL =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5049 PerThreadRedListAlloca, PtrTy,
5050 PerThreadRedListAlloca->
getName() +
".ascast");
5055 for (
auto En :
enumerate(ReductionInfos)) {
5057 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
5060 ReductionsBufferTy, PerThreadScratch, 0, En.index());
5061 Value *Slot =
Builder.CreateConstInBoundsGEP2_32(RedArrayTy, RuntimeRL,
5064 Value *RuntimeListEntry = FieldPtr;
5066 Value *SrcDescriptor =
5069 AllocaIP, RI, FieldPtr, SrcDescriptor, PtrTy);
5072 RuntimeListEntry = *Descriptor;
5074 Builder.CreateStore(RuntimeListEntry, Slot);
5080 Type *CopyArg0Ty = (*LtGCFunc)->getFunctionType()->getParamType(0);
5081 Type *CopyArg2Ty = (*LtGCFunc)->getFunctionType()->getParamType(2);
5082 ScratchForCopyBack =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5083 PerThreadScratch, CopyArg0Ty);
5085 Builder.CreatePointerBitCastOrAddrSpaceCast(RL, CopyArg2Ty);
5093 *LtGCFunc, {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
5094 CopyScratchToListFunc = *GtLCFunc;
5097 Value *Args3[] = {SrcLocInfo, RuntimeRL, *SarFunc, WcFunc,
5098 *LtGCFunc, *GtLCFunc, *GtLRFunc};
5101 RuntimeFunction::OMPRTL___kmpc_gpu_xteam_reduce_nowait);
5121 if (ScratchForCopyBack) {
5124 CopyScratchToListFunc,
5125 {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
5129 for (
auto En :
enumerate(ReductionInfos)) {
5135 if (IsAtomicReduction) {
5151 Value *LHSPtr, *RHSPtr;
5153 &LHSPtr, &RHSPtr, CurFunc));
5159 RedValue =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5161 if (RHSPtr->
getType() != RHS->getType())
5163 Builder.CreatePointerBitCastOrAddrSpaceCast(RHS, RHSPtr->
getType());
5174 if (IsByRef.
empty() || !IsByRef[En.index()]) {
5176 "red.value." +
Twine(En.index()));
5187 if (!IsByRef.
empty() && !IsByRef[En.index()])
5192 if (ContinuationBlock) {
5193 Builder.CreateBr(ContinuationBlock);
5194 Builder.SetInsertPoint(ContinuationBlock);
5196 Config.setEmitLLVMUsed();
5207 ".omp.reduction.func", &M);
5218 Builder.SetInsertPoint(ReductionFuncBlock);
5220 Value *LHSArrayPtr =
nullptr;
5221 Value *RHSArrayPtr =
nullptr;
5232 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
5234 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
5235 Value *LHSAddrCast =
5236 Builder.CreatePointerBitCastOrAddrSpaceCast(LHSAlloca, Arg0Type);
5237 Value *RHSAddrCast =
5238 Builder.CreatePointerBitCastOrAddrSpaceCast(RHSAlloca, Arg1Type);
5239 Builder.CreateStore(Arg0, LHSAddrCast);
5240 Builder.CreateStore(Arg1, RHSAddrCast);
5241 LHSArrayPtr = Builder.CreateLoad(Arg0Type, LHSAddrCast);
5242 RHSArrayPtr = Builder.CreateLoad(Arg1Type, RHSAddrCast);
5244 LHSArrayPtr = ReductionFunc->
getArg(0);
5245 RHSArrayPtr = ReductionFunc->
getArg(1);
5248 unsigned NumReductions = ReductionInfos.
size();
5251 for (
auto En :
enumerate(ReductionInfos)) {
5253 Value *LHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5254 RedArrayTy, LHSArrayPtr, 0, En.index());
5255 Value *LHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), LHSI8PtrPtr);
5256 Value *LHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5259 Value *RHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5260 RedArrayTy, RHSArrayPtr, 0, En.index());
5261 Value *RHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), RHSI8PtrPtr);
5262 Value *RHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5271 Builder.restoreIP(*AfterIP);
5273 if (!Builder.GetInsertBlock())
5277 if (!IsByRef[En.index()])
5278 Builder.CreateStore(Reduced, LHSPtr);
5280 Builder.CreateRetVoid();
5287 bool IsNoWait,
bool IsTeamsReduction) {
5291 IsByRef, IsNoWait, IsTeamsReduction);
5298 if (ReductionInfos.
size() == 0)
5308 unsigned NumReductions = ReductionInfos.
size();
5310 Builder.SetInsertPoint(AllocaIP.getNodeParent()->getTerminator());
5311 Value *RedArray =
Builder.CreateAlloca(RedArrayTy,
nullptr,
"red.array");
5318 for (
auto En :
enumerate(ReductionInfos)) {
5319 unsigned Index = En.index();
5321 Value *RedArrayElemPtr =
Builder.CreateConstInBoundsGEP2_64(
5322 RedArrayTy, RedArray, 0, Index,
"red.array.elem." +
Twine(Index));
5329 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
5339 ? IdentFlag::OMP_IDENT_FLAG_ATOMIC_REDUCE
5344 unsigned RedArrayByteSize =
DL.getTypeStoreSize(RedArrayTy);
5345 Constant *RedArraySize = ConstantInt::get(IndexTy, RedArrayByteSize);
5347 Value *Lock = getOMPCriticalRegionLock(
".reduction");
5349 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_reduce_nowait
5350 : RuntimeFunction::OMPRTL___kmpc_reduce);
5353 {Ident, ThreadId, NumVariables, RedArraySize,
5354 RedArray, ReductionFunc, Lock},
5365 Builder.CreateSwitch(ReduceCall, ContinuationBlock, 2);
5366 Switch->addCase(
Builder.getInt32(1), NonAtomicRedBlock);
5367 Switch->addCase(
Builder.getInt32(2), AtomicRedBlock);
5372 Builder.SetInsertPoint(NonAtomicRedBlock);
5373 for (
auto En :
enumerate(ReductionInfos)) {
5379 if (!IsByRef[En.index()]) {
5381 "red.value." +
Twine(En.index()));
5383 Value *PrivateRedValue =
5385 "red.private.value." +
Twine(En.index()));
5393 if (!
Builder.GetInsertBlock())
5396 if (!IsByRef[En.index()])
5400 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_end_reduce_nowait
5401 : RuntimeFunction::OMPRTL___kmpc_end_reduce);
5403 Builder.CreateBr(ContinuationBlock);
5408 Builder.SetInsertPoint(AtomicRedBlock);
5409 if (CanGenerateAtomic &&
llvm::none_of(IsByRef, [](
bool P) {
return P; })) {
5416 if (!
Builder.GetInsertBlock())
5419 Builder.CreateBr(ContinuationBlock);
5432 if (!
Builder.GetInsertBlock())
5435 Builder.SetInsertPoint(ContinuationBlock);
5446 Directive OMPD = Directive::OMPD_master;
5451 Value *Args[] = {Ident, ThreadId};
5459 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5471 Directive OMPD = Directive::OMPD_masked;
5477 Value *ArgsEnd[] = {Ident, ThreadId};
5485 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5495 Call->setDoesNotThrow();
5510 bool IsInclusive,
ScanInfo *ScanRedInfo) {
5512 llvm::Error Err = emitScanBasedDirectiveDeclsIR(AllocaIP, ScanVars,
5513 ScanVarsType, ScanRedInfo);
5524 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5527 Type *DestTy = ScanVarsType[i];
5528 Value *Val =
Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5531 Builder.CreateStore(Src, Val);
5536 Builder.GetInsertBlock()->getParent());
5539 IV = ScanRedInfo->
IV;
5542 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5545 Type *DestTy = ScanVarsType[i];
5547 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5549 Builder.CreateStore(Src, ScanVars[i]);
5563 Builder.GetInsertBlock()->getParent());
5568Error OpenMPIRBuilder::emitScanBasedDirectiveDeclsIR(
5572 Builder.restoreIP(AllocaIP);
5574 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5576 Builder.CreateAlloca(Builder.getPtrTy(),
nullptr,
"vla");
5583 Builder.restoreIP(CodeGenIP);
5585 Builder.CreateAdd(ScanRedInfo->
Span, Builder.getInt32(1));
5586 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5588 Value *Allocsize = Builder.CreateTypeSize(
5589 IntPtrTy, M.getDataLayout().getTypeAllocSize(ScanVarsType[i]));
5591 Builder.CreateMalloc(
IntPtrTy, Allocsize, AllocSpan,
nullptr,
"arr");
5592 Builder.CreateStore(Buff, (*(ScanRedInfo->
ScanBuffPtrs))[ScanVars[i]]);
5619Error OpenMPIRBuilder::emitScanBasedDirectiveFinalsIR(
5625 Value *PrivateVar = RedInfo.PrivateVariable;
5626 Value *OrigVar = RedInfo.Variable;
5630 Type *SrcTy = RedInfo.ElementType;
5635 Builder.CreateStore(Src, OrigVar);
5696 llvm::ConstantInt::get(ScanRedInfo->
Span->
getType(), 1));
5697 Builder.SetInsertPoint(InputBB);
5700 Builder.SetInsertPoint(LoopBB);
5716 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5718 Builder.SetInsertPoint(InnerLoopBB);
5722 Value *ReductionVal = RedInfo.PrivateVariable;
5725 Type *DestTy = RedInfo.ElementType;
5728 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5731 Builder.CreateInBoundsGEP(DestTy, Buff, OffsetIval,
"arrayOffset");
5736 RedInfo.ReductionGen(
Builder.saveIP(), LHS, RHS, Result);
5739 Builder.CreateStore(Result, LHSPtr);
5742 IVal, llvm::ConstantInt::get(
Builder.getInt32Ty(), 1));
5744 CmpI =
Builder.CreateICmpUGE(NextIVal, Pow2K);
5745 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5748 Counter, llvm::ConstantInt::get(Counter->
getType(), 1));
5754 Builder.CreateCondBr(Cmp, LoopBB, ExitBB);
5775 Error Err = emitScanBasedDirectiveFinalsIR(ReductionInfos, ScanRedInfo);
5782Error OpenMPIRBuilder::emitScanBasedDirectiveIR(
5794 Error Err = InputLoopGen();
5805 Error Err = ScanLoopGen(Builder);
5812void OpenMPIRBuilder::createScanBBs(ScanInfo *ScanRedInfo) {
5849 Builder.SetInsertPoint(Preheader);
5852 Builder.SetInsertPoint(Header);
5853 PHINode *IndVarPHI =
Builder.CreatePHI(IndVarTy, 2,
"omp_" + Name +
".iv");
5854 IndVarPHI->
addIncoming(ConstantInt::get(IndVarTy, 0), Preheader);
5859 Builder.CreateICmpULT(IndVarPHI, TripCount,
"omp_" + Name +
".cmp");
5860 Builder.CreateCondBr(Cmp, Body, Exit);
5865 Builder.SetInsertPoint(Latch);
5875 bool HasNSW =
Config.hasNoSignedWrap();
5878 unsigned BitWidth = CI->getType()->getIntegerBitWidth();
5880 if (CI->getValue().ugt(SignedMax))
5882 }
else if (IsCollapsed) {
5887 Builder.CreateAdd(IndVarPHI, ConstantInt::get(IndVarTy, 1),
5888 "omp_" + Name +
".next",
true, HasNSW);
5899 CL->Header = Header;
5918 NextBB, NextBB, Name);
5950 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
5959 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
5960 ScanRedInfo->
Span = TripCount;
5966 ScanRedInfo->
IV =
IV;
5967 createScanBBs(ScanRedInfo);
5970 assert(Terminator->getNumSuccessors() == 1);
5971 BasicBlock *ContinueBlock = Terminator->getSuccessor(0);
5974 Builder.GetInsertBlock()->getParent());
5977 Builder.GetInsertBlock()->getParent());
5978 Builder.CreateBr(ContinueBlock);
5984 const auto &&InputLoopGen = [&]() ->
Error {
5987 InclusiveStop, ComputeIP, Name,
true, ScanRedInfo);
5991 Builder.restoreIP((*LoopInfo)->getAfterIP());
5997 InclusiveStop, ComputeIP, Name,
true, ScanRedInfo);
6001 Builder.restoreIP((*LoopInfo)->getAfterIP());
6005 Error Err = emitScanBasedDirectiveIR(InputLoopGen, ScanLoopGen, ScanRedInfo);
6013 bool IsSigned,
bool InclusiveStop,
const Twine &Name) {
6023 assert(IndVarTy == Stop->
getType() &&
"Stop type mismatch");
6024 assert(IndVarTy == Step->
getType() &&
"Step type mismatch");
6028 ConstantInt *Zero = ConstantInt::get(IndVarTy, 0);
6044 Incr =
Builder.CreateSelect(IsNeg,
Builder.CreateNeg(Step), Step);
6047 Span =
Builder.CreateSub(UB, LB,
"",
false,
true);
6051 Span =
Builder.CreateSub(Stop, Start,
"",
true);
6056 Value *CountIfLooping;
6057 if (InclusiveStop) {
6058 CountIfLooping =
Builder.CreateAdd(
Builder.CreateUDiv(Span, Incr), One);
6064 CountIfLooping =
Builder.CreateSelect(OneCmp, One, CountIfTwo);
6067 return Builder.CreateSelect(ZeroCmp, Zero, CountIfLooping,
6068 "omp_" + Name +
".tripcount");
6073 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
6080 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
6085 Config.hasNoSignedWrap());
6086 Value *IndVar =
Builder.CreateAdd(Span, Start,
"",
false,
6087 Config.hasNoSignedWrap());
6089 ScanRedInfo->
IV = IndVar;
6090 return BodyGenCB(
Builder.saveIP(), IndVar);
6096 Builder.getCurrentDebugLocation());
6107 unsigned Bitwidth = Ty->getIntegerBitWidth();
6110 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_4u);
6113 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_8u);
6123 unsigned Bitwidth = Ty->getIntegerBitWidth();
6126 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_4u);
6129 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_8u);
6137 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6139 "Require dedicated allocate IP");
6145 uint32_t SrcLocStrSize;
6149 case WorksharingLoopType::ForStaticLoop:
6150 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6152 case WorksharingLoopType::DistributeStaticLoop:
6153 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6155 case WorksharingLoopType::DistributeForStaticLoop:
6156 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
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 if (CLI->VirtualCollapse) {
6232 bindCollapsedRange(CLI,
LowerBound, TripCount);
6237 CLI->setTripCount(TripCount);
6244 if (!CLI->VirtualCollapse)
6245 CLI->mapIndVar([&](Instruction *OldIV) ->
Value * {
6249 Config.hasNoSignedWrap());
6260 omp::Directive::OMPD_for,
false,
6263 return BarrierIP.takeError();
6294 Reachable.insert(
Block);
6308OpenMPIRBuilder::applyStaticChunkedWorkshareLoop(
6312 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6313 assert((ChunkSize || DistScheduleChunkSize) &&
"Chunk size is required");
6318 Type *IVTy =
IV->getType();
6320 "Max supported tripcount bitwidth is 64 bits");
6322 :
Type::getInt64Ty(Ctx);
6325 Constant *One = ConstantInt::get(InternalIVTy, 1);
6330 SmallVector<Instruction *> UIs;
6331 for (BasicBlock &BB : *
F)
6332 if (!BB.hasTerminator())
6333 UIs.
push_back(
new UnreachableInst(
F->getContext(), &BB));
6338 LoopInfo &&LI = LIA.
run(*
F,
FAM);
6339 for (Instruction *
I : UIs)
6340 I->eraseFromParent();
6343 if (ChunkSize || DistScheduleChunkSize)
6348 FunctionCallee StaticInit =
6350 FunctionCallee StaticFini =
6356 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6357 Value *PLowerBound =
6358 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.lowerbound");
6359 Value *PUpperBound =
6360 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.upperbound");
6361 Value *PStride =
Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.stride");
6370 ChunkSize ? ChunkSize : Zero, InternalIVTy,
"chunksize");
6371 Value *CastedDistScheduleChunkSize =
Builder.CreateZExtOrTrunc(
6372 DistScheduleChunkSize ? DistScheduleChunkSize : Zero, InternalIVTy,
6373 "distschedulechunksize");
6374 Value *CastedTripCount =
6375 Builder.CreateZExt(OrigTripCount, InternalIVTy,
"tripcount");
6378 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6380 ConstantInt::get(I32Type,
static_cast<int>(DistScheduleSchedType));
6381 Builder.CreateStore(Zero, PLowerBound);
6382 Value *OrigUpperBound =
Builder.CreateSub(CastedTripCount, One);
6383 Value *IsTripCountZero =
Builder.CreateICmpEQ(CastedTripCount, Zero);
6385 Builder.CreateSelect(IsTripCountZero, Zero, OrigUpperBound);
6386 Builder.CreateStore(UpperBound, PUpperBound);
6387 Builder.CreateStore(One, PStride);
6391 uint32_t SrcLocStrSize;
6394 if (DistScheduleSchedType != OMPScheduleType::None) {
6395 Flag |= OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6400 auto BuildInitCall = [StaticInit, SrcLoc, ThreadNum, PLastIter, PLowerBound,
6401 PUpperBound, PStride, One,
6402 this](
Value *SchedulingType,
Value *ChunkSize,
6405 StaticInit, {SrcLoc, ThreadNum,
6406 SchedulingType, PLastIter,
6407 PLowerBound, PUpperBound,
6411 BuildInitCall(SchedulingType, CastedChunkSize,
Builder);
6412 if (DistScheduleSchedType != OMPScheduleType::None &&
6413 SchedType != OMPScheduleType::OrderedDistributeChunked &&
6414 SchedType != OMPScheduleType::OrderedDistribute) {
6418 BuildInitCall(DistSchedulingType, CastedDistScheduleChunkSize,
Builder);
6422 Value *FirstChunkStart =
6423 Builder.CreateLoad(InternalIVTy, PLowerBound,
"omp_firstchunk.lb");
6424 Value *FirstChunkStop =
6425 Builder.CreateLoad(InternalIVTy, PUpperBound,
"omp_firstchunk.ub");
6426 Value *FirstChunkEnd =
Builder.CreateAdd(FirstChunkStop, One);
6428 Builder.CreateSub(FirstChunkEnd, FirstChunkStart,
"omp_chunk.range");
6429 Value *NextChunkStride =
6430 Builder.CreateLoad(InternalIVTy, PStride,
"omp_dispatch.stride");
6434 Value *DispatchCounter;
6442 DispatchCounter = Counter;
6445 FirstChunkStart, CastedTripCount, NextChunkStride,
6468 Value *ChunkEnd =
Builder.CreateAdd(DispatchCounter, ChunkRange);
6469 Value *IsLastChunk =
6470 Builder.CreateICmpUGE(ChunkEnd, CastedTripCount,
"omp_chunk.is_last");
6471 Value *CountUntilOrigTripCount =
6472 Builder.CreateSub(CastedTripCount, DispatchCounter);
6474 IsLastChunk, CountUntilOrigTripCount, ChunkRange,
"omp_chunk.tripcount");
6475 Value *BackcastedChunkTC =
6476 Builder.CreateTrunc(ChunkTripCount, IVTy,
"omp_chunk.tripcount.trunc");
6477 CLI->setTripCount(BackcastedChunkTC);
6482 Value *BackcastedDispatchCounter =
6483 Builder.CreateTrunc(DispatchCounter, IVTy,
"omp_dispatch.iv.trunc");
6484 CLI->mapIndVar([&](Instruction *) ->
Value * {
6486 return Builder.CreateAdd(
IV, BackcastedDispatchCounter);
6499 return AfterIP.takeError();
6514static FunctionCallee
6517 unsigned Bitwidth = Ty->getIntegerBitWidth();
6520 case WorksharingLoopType::ForStaticLoop:
6523 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_4u);
6526 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_8u);
6528 case WorksharingLoopType::DistributeStaticLoop:
6531 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_4u);
6534 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_8u);
6536 case WorksharingLoopType::DistributeForStaticLoop:
6539 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_4u);
6542 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_8u);
6545 if (Bitwidth != 32 && Bitwidth != 64) {
6557 Function &LoopBodyFn,
bool NoLoop) {
6568 if (LoopType == WorksharingLoopType::DistributeStaticLoop) {
6569 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6570 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6571 Builder.restoreIP(std::prev(InsertBlock->
end()));
6576 M, omp::RuntimeFunction::OMPRTL_omp_get_num_threads);
6577 Builder.restoreIP(std::prev(InsertBlock->
end()));
6581 Builder.CreateZExtOrTrunc(NumThreads, TripCountTy,
"num.threads.cast"));
6582 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6583 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
6584 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6585 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), NoLoop));
6587 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6611 Builder.restoreIP(Preheader->
end());
6614 Builder.CreateBr(CLI->
getExit());
6622 CleanUpInfo.
collectBlocks(RegionBlockSet, BlocksToBeRemoved);
6630 "Expected unique undroppable user of outlined function");
6632 assert(OutlinedFnCallInstruction &&
"Expected outlined function call");
6634 "Expected outlined function call to be located in loop preheader");
6636 if (OutlinedFnCallInstruction->
arg_size() > 1)
6643 LoopBodyArg, TripCount, OutlinedFn, NoLoop);
6645 for (
auto &ToBeDeletedItem : ToBeDeleted)
6646 ToBeDeletedItem->eraseFromParent();
6653 bool NeedsLastIter) {
6654 uint32_t SrcLocStrSize;
6658 if (NeedsLastIter) {
6661 AllocaInst *PLastIter =
6662 Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6666 Builder.CreateStore(ConstantInt::get(I32Type, 0), PLastIter);
6671 Builder.CreateSub(TripCount, ConstantInt::get(TripCount->
getType(), 1));
6674 Builder.CreateStore(
Builder.CreateZExt(IsLast, I32Type), PLastIter);
6679 case WorksharingLoopType::ForStaticLoop:
6680 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6682 case WorksharingLoopType::DistributeStaticLoop:
6683 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6685 case WorksharingLoopType::DistributeForStaticLoop:
6686 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
6691 auto OI = std::make_unique<OutlineInfo>();
6696 SmallVector<Instruction *, 4> ToBeDeleted;
6698 OI->OuterAllocBB = AllocaIP.getNodeParent();
6721 SmallPtrSet<BasicBlock *, 32> ParallelRegionBlockSet;
6723 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
6725 CodeExtractorAnalysisCache CEAC(*OuterFn);
6726 CodeExtractor Extractor(Blocks,
6740 SetVector<Value *> SinkingCands, HoistingCands;
6744 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
6751 for (
auto Use :
Users) {
6753 if (ParallelRegionBlockSet.
count(Inst->getParent())) {
6754 Inst->replaceUsesOfWith(CLI->
getIndVar(), NewLoopCntLoad);
6760 OI->ExcludeArgsFromAggregate.push_back(NewLoopCntLoad);
6767 OI->PostOutlineCB = [=, ToBeDeletedVec =
6768 std::move(ToBeDeleted)](
Function &OutlinedFn) {
6785 return BarrierIP.takeError();
6792 bool NeedsBarrier, omp::ScheduleKind SchedKind,
Value *ChunkSize,
6793 bool HasSimdModifier,
bool HasMonotonicModifier,
6794 bool HasNonmonotonicModifier,
bool HasOrderedClause,
6796 Value *DistScheduleChunkSize,
bool NeedsLastIter) {
6797 if (CLI->VirtualCollapse &&
6798 (
Config.isTargetDevice() ||
6799 (SchedKind != omp::OMP_SCHEDULE_Static &&
6800 SchedKind != omp::OMP_SCHEDULE_Default) ||
6801 ChunkSize || HasOrderedClause || HasDistSchedule ||
6802 DistScheduleChunkSize || LoopType != WorksharingLoopType::ForStaticLoop))
6804 "Virtual collapse requires unchunked static worksharing");
6805 if (
Config.isTargetDevice())
6806 return applyWorkshareLoopTarget(
DL, CLI, AllocaIP, LoopType, NeedsBarrier,
6807 NoLoop, NeedsLastIter);
6809 SchedKind, ChunkSize, HasSimdModifier, HasMonotonicModifier,
6810 HasNonmonotonicModifier, HasOrderedClause, DistScheduleChunkSize);
6812 bool IsOrdered = (EffectiveScheduleType & OMPScheduleType::ModifierOrdered) ==
6813 OMPScheduleType::ModifierOrdered;
6815 if (HasDistSchedule) {
6816 DistScheduleSchedType = DistScheduleChunkSize
6817 ? OMPScheduleType::OrderedDistributeChunked
6818 : OMPScheduleType::OrderedDistribute;
6820 switch (EffectiveScheduleType & ~OMPScheduleType::ModifierMask) {
6821 case OMPScheduleType::BaseStatic:
6822 case OMPScheduleType::BaseDistribute:
6823 assert((!ChunkSize || !DistScheduleChunkSize) &&
6824 "No chunk size with static-chunked schedule");
6825 if (IsOrdered && !HasDistSchedule)
6826 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6827 NeedsBarrier, ChunkSize);
6829 if (DistScheduleChunkSize)
6830 return applyStaticChunkedWorkshareLoop(
6831 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6832 DistScheduleChunkSize, DistScheduleSchedType);
6833 return applyStaticWorkshareLoop(
DL, CLI, AllocaIP, LoopType, NeedsBarrier,
6836 case OMPScheduleType::BaseStaticChunked:
6837 case OMPScheduleType::BaseDistributeChunked:
6838 if (IsOrdered && !HasDistSchedule)
6839 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6840 NeedsBarrier, ChunkSize);
6842 return applyStaticChunkedWorkshareLoop(
6843 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6844 DistScheduleChunkSize, DistScheduleSchedType);
6846 case OMPScheduleType::BaseRuntime:
6847 case OMPScheduleType::BaseAuto:
6848 case OMPScheduleType::BaseGreedy:
6849 case OMPScheduleType::BaseBalanced:
6850 case OMPScheduleType::BaseSteal:
6851 case OMPScheduleType::BaseRuntimeSimd:
6853 "schedule type does not support user-defined chunk sizes");
6855 case OMPScheduleType::BaseGuidedSimd:
6856 case OMPScheduleType::BaseDynamicChunked:
6857 case OMPScheduleType::BaseGuidedChunked:
6858 case OMPScheduleType::BaseGuidedIterativeChunked:
6859 case OMPScheduleType::BaseGuidedAnalyticalChunked:
6860 case OMPScheduleType::BaseStaticBalancedChunked:
6861 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6862 NeedsBarrier, ChunkSize);
6875 unsigned Bitwidth = Ty->getIntegerBitWidth();
6878 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_4u);
6881 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_8u);
6889static FunctionCallee
6891 unsigned Bitwidth = Ty->getIntegerBitWidth();
6894 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_4u);
6897 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_8u);
6904static FunctionCallee
6906 unsigned Bitwidth = Ty->getIntegerBitWidth();
6909 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_4u);
6912 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_8u);
6917OpenMPIRBuilder::applyDynamicWorkshareLoop(
DebugLoc DL, CanonicalLoopInfo *CLI,
6920 bool NeedsBarrier,
Value *Chunk) {
6921 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6923 "Require dedicated allocate IP");
6925 "Require valid schedule type");
6927 bool Ordered = (SchedType & OMPScheduleType::ModifierOrdered) ==
6928 OMPScheduleType::ModifierOrdered;
6933 uint32_t SrcLocStrSize;
6940 Type *IVTy =
IV->getType();
6945 Builder.SetInsertPoint(AllocaIP.getNodeParent()->getFirstNonPHIOrAlloca());
6947 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6948 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
6949 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
6950 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
6959 Constant *One = ConstantInt::get(IVTy, 1);
6960 Builder.CreateStore(One, PLowerBound);
6962 Builder.CreateStore(UpperBound, PUpperBound);
6963 Builder.CreateStore(One, PStride);
6981 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6993 Builder.SetInsertPoint(OuterCond->getFirstInsertionPt());
6996 {SrcLoc, ThreadNum, PLastIter, PLowerBound, PUpperBound, PStride});
6997 Constant *Zero32 = ConstantInt::get(I32Type, 0);
7000 Builder.CreateSub(
Builder.CreateLoad(IVTy, PLowerBound), One,
"lb");
7001 Builder.CreateCondBr(MoreWork, Header, Exit);
7007 PI->setIncomingBlock(0, OuterCond);
7013 Br->setSuccessor(OuterCond);
7018 Builder.SetInsertPoint(
Cond->getFirstInsertionPt());
7019 UpperBound =
Builder.CreateLoad(IVTy, PUpperBound,
"ub");
7022 CI->setOperand(1, UpperBound);
7026 assert(BI->getSuccessor(1) == Exit);
7027 BI->setSuccessor(1, OuterCond);
7041 omp::Directive::OMPD_for,
false,
7044 return BarrierIP.takeError();
7107 "Virtual collapse requires unobserved canonical loop controls");
7116 if (
Loops.front()->getBody()->getUniqueSuccessor() !=
7118 Loops.back()->getAfter()->getSingleSuccessor() != Plan.
Latches.front())
7125 const VirtualRowPlan &Plan,
7129 DebugLoc DL = Builder.getCurrentDebugLocation();
7132 Constant *Zero = ConstantInt::get(IVType, 0);
7135 Builder.SetInsertPoint(Entry);
7137 Builder.CreateURem(Begin, TripCounts.
back(),
"omp_collapsed.begin.1");
7139 Builder.CreateUDiv(Begin, TripCounts.
back(),
"omp_collapsed.begin.0");
7142 Value *InitialRemaining =
7143 Builder.CreateAdd(
Count, InnerBegin,
"omp_collapsed.row.remaining");
7144 Builder.CreateBr(OuterHeader);
7147 Builder.SetCurrentDebugLocation(
DL);
7149 Builder.CreatePHI(IVType, 2,
"omp_collapsed.row.remaining.0");
7155 Builder.CreatePHI(IVType, 2,
"omp_collapsed.row.start.1.0");
7156 Start->addIncoming(InnerBegin, Entry);
7157 Start->addIncoming(Zero, Plan.Latches.front());
7158 Plan.IndVars.back()->setIncomingValue(0, Start);
7163 BasicBlock *InnerHeader = Plan.IndVars.back()->getParent();
7167 Builder.SetInsertPoint(InnerEntry);
7169 Builder.CreateBr(InnerHeader);
7170 InnerBr->setSuccessor(InnerEntry);
7171 Plan.IndVars.back()->setIncomingBlock(0, InnerEntry);
7173 Builder.SetInsertPoint(Plan.Preheaders.back()->getTerminator());
7176 "omp_collapsed.row.is_final");
7178 IsFinalRow, Remaining, TripCounts.
back(),
"omp_collapsed.row.stop");
7179 Plan.InnerCmp->setOperand(1, InnerStop);
7187 "omp_collapsed.row.remaining.next",
7195 Builder.SetInsertPoint(Guard);
7197 Plan.IndVars.front()->setIncomingValue(0, OuterBegin);
7198 Plan.IndVars.front()->setIncomingBlock(0, Entry);
7201CanonicalLoopInfo *OpenMPIRBuilder::createVirtualCollapsedLoop(
7204 Value *CollapsedTripCount) {
7212 BasicBlock *Preheader = Plan.Preheaders.front();
7226 auto *Begin =
Builder.Insert(BinaryOperator::CreateAdd(Zero, Zero),
7227 "omp_collapsed.range.begin");
7229 Builder.Insert(BinaryOperator::CreateAdd(CollapsedTripCount, Zero),
7230 "omp_collapsed.range.count");
7233 Result->VirtualCollapse =
7234 CanonicalLoopInfo::VirtualCollapseInfo{Begin,
Count};
7238 createVirtualRowExecutor(Result, Plan, TripCounts, Begin,
Count, Entry);
7248void OpenMPIRBuilder::bindCollapsedRange(CanonicalLoopInfo *
Loop,
Value *Begin,
7251 Loop->VirtualCollapse->Begin->setOperand(0, Begin);
7252 Loop->VirtualCollapse->Count->setOperand(0,
Count);
7258 assert(
Loops.size() >= 1 &&
"At least one loop required");
7259 size_t NumLoops =
Loops.size();
7263 return Loops.front();
7265 if (
Config.CollapseMapping == CollapseIVMapping::Virtual) {
7266 if (
Loops.size() != 2)
7268 "Virtual collapse requires two constant-count loops");
7271 if (
Loop->VirtualCollapse)
7272 Loop->reportUnsupportedVirtualCollapse();
7276 "Virtual collapse requires two constant-count loops");
7281 Value *CollapsedTripCount =
7283 return createVirtualCollapsedLoop(
DL,
Loops, Plan, TripCounts,
7284 CollapsedTripCount);
7297 Loop->collectControlBlocks(OldControlBBs);
7301 if (ComputeIP.isValid())
7308 Value *CollapsedTripCount =
nullptr;
7311 "All loops to collapse must be valid canonical loops");
7312 Value *OrigTripCount = L->getTripCount();
7313 if (!CollapsedTripCount) {
7314 CollapsedTripCount = OrigTripCount;
7319 CollapsedTripCount =
7320 Builder.CreateNUWMul(CollapsedTripCount, OrigTripCount);
7326 OrigPreheader->
getNextNode(), OrigAfter,
"collapsed",
7333 Builder.restoreIP(Result->getBodyIP());
7335 Value *Leftover = Result->getIndVar();
7337 NewIndVars.
resize(NumLoops);
7338 for (
int i = NumLoops - 1; i >= 1; --i) {
7339 Value *OrigTripCount =
Loops[i]->getTripCount();
7341 Value *NewIndVar =
Builder.CreateURem(Leftover, OrigTripCount);
7342 NewIndVars[i] = NewIndVar;
7344 Leftover =
Builder.CreateUDiv(Leftover, OrigTripCount);
7347 NewIndVars[0] = Leftover;
7356 BasicBlock *ContinueBlock = Result->getBody();
7358 auto ContinueWith = [&ContinueBlock, &ContinuePred,
DL](
BasicBlock *Dest,
7365 ContinueBlock =
nullptr;
7366 ContinuePred = NextSrc;
7373 for (
size_t i = 0; i < NumLoops - 1; ++i)
7374 ContinueWith(
Loops[i]->getBody(),
Loops[i + 1]->getHeader());
7380 for (
size_t i = NumLoops - 1; i > 0; --i)
7381 ContinueWith(
Loops[i]->getAfter(),
Loops[i - 1]->getLatch());
7384 ContinueWith(Result->getLatch(),
nullptr);
7391 for (
size_t i = 0; i < NumLoops; ++i)
7392 Loops[i]->getIndVar()->replaceAllUsesWith(NewIndVars[i]);
7406std::vector<CanonicalLoopInfo *>
7410 "Must pass as many tile sizes as there are loops");
7411 int NumLoops =
Loops.size();
7412 assert(NumLoops >= 1 &&
"At least one loop to tile required");
7424 Loop->collectControlBlocks(OldControlBBs);
7432 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7433 OrigTripCounts.
push_back(L->getTripCount());
7444 for (
int i = 0; i < NumLoops - 1; ++i) {
7457 for (
int i = 0; i < NumLoops; ++i) {
7458 Value *TileSize = TileSizes[i];
7459 Value *OrigTripCount = OrigTripCounts[i];
7462 Value *FloorCompleteTripCount =
Builder.CreateUDiv(OrigTripCount, TileSize);
7463 Value *FloorTripRem =
Builder.CreateURem(OrigTripCount, TileSize);
7472 Value *FloorTripOverflow =
7473 Builder.CreateICmpNE(FloorTripRem, ConstantInt::get(IVType, 0));
7475 FloorTripOverflow =
Builder.CreateZExt(FloorTripOverflow, IVType);
7476 Value *FloorTripCount =
7477 Builder.CreateAdd(FloorCompleteTripCount, FloorTripOverflow,
7478 "omp_floor" +
Twine(i) +
".tripcount",
true);
7481 FloorCompleteCount.
push_back(FloorCompleteTripCount);
7487 std::vector<CanonicalLoopInfo *> Result;
7488 Result.reserve(NumLoops * 2);
7501 auto EmbeddNewLoop =
7502 [
this,
DL,
F, InnerEnter, &Enter, &
Continue, &OutroInsertBefore](
7505 DL, TripCount,
F, InnerEnter, OutroInsertBefore, Name);
7510 Enter = EmbeddedLoop->
getBody();
7512 OutroInsertBefore = EmbeddedLoop->
getLatch();
7513 return EmbeddedLoop;
7517 const Twine &NameBase) {
7520 EmbeddNewLoop(
P.value(), NameBase +
Twine(
P.index()));
7521 Result.push_back(EmbeddedLoop);
7525 EmbeddNewLoops(FloorCount,
"floor");
7531 for (
int i = 0; i < NumLoops; ++i) {
7533 Value *TileSize = TileSizes[i];
7535 Value *FloorIsEpilogue =
7537 Value *TileTripCount =
7538 Builder.CreateSelect(FloorIsEpilogue, FloorRems[i], TileSize);
7544 EmbeddNewLoops(TileCounts,
"tile");
7549 for (std::pair<BasicBlock *, BasicBlock *>
P : InbetweenCode) {
7558 BodyEnter =
nullptr;
7559 BodyEntered = ExitBB;
7571 Builder.restoreIP(Result.back()->getBodyIP());
7572 for (
int i = 0; i < NumLoops; ++i) {
7575 Value *OrigIndVar = OrigIndVars[i];
7626 assert(
Loop->isValid() &&
"Expecting a valid CanonicalLoopInfo");
7630 assert(Latch &&
"A valid CanonicalLoopInfo must have a unique latch");
7638 if (
I.mayReadOrWriteMemory()) {
7642 I.setMetadata(LLVMContext::MD_access_group,
AccessGroup);
7656 Loop->collectControlBlocks(oldControlBBs);
7661 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7662 origTripCounts.
push_back(L->getTripCount());
7671 Builder.SetInsertPoint(TCBlock);
7672 Value *fusedTripCount =
nullptr;
7674 assert(L->isValid() &&
"All loops to fuse must be valid canonical loops");
7675 Value *origTripCount = L->getTripCount();
7676 if (!fusedTripCount) {
7677 fusedTripCount = origTripCount;
7680 Value *condTP =
Builder.CreateICmpSGT(fusedTripCount, origTripCount);
7681 fusedTripCount =
Builder.CreateSelect(condTP, fusedTripCount, origTripCount,
7695 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7696 Loops[i]->getPreheader()->moveBefore(TCBlock);
7697 Loops[i]->getAfter()->moveBefore(TCBlock);
7701 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7713 for (
size_t i = 0; i <
Loops.size(); ++i) {
7715 F->getContext(),
"omp.fused.inner.cond",
F,
Loops[i]->getBody());
7716 Builder.SetInsertPoint(condBlock);
7724 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7725 Builder.SetInsertPoint(condBBs[i]);
7726 Builder.CreateCondBr(condValues[i],
Loops[i]->getBody(), condBBs[i + 1]);
7742 "omp.fused.pre_latch");
7759 assert(
Loop->isValid() &&
"Expecting a valid CanonicalLoopInfo");
7760 if (
Loop->VirtualCollapse)
7783 const Twine &NamePrefix) {
7812 C, NamePrefix +
".if.then",
Cond->getParent(),
Cond->getNextNode());
7814 C, NamePrefix +
".if.else",
Cond->getParent(), CanonicalLoop->
getExit());
7817 Builder.SetInsertPoint(SplitBeforeIt);
7819 Builder.CreateCondBr(IfCond, ThenBlock, ElseBlock);
7822 spliceBB(IP, ThenBlock,
false, Builder.getCurrentDebugLocation());
7825 Builder.SetInsertPoint(ElseBlock);
7831 ExistingBlocks.
reserve(L->getNumBlocks() + 1);
7833 ExistingBlocks.
append(L->block_begin(), L->block_end());
7839 assert(LoopCond && LoopHeader &&
"Invalid loop structure");
7841 if (
Block == L->getLoopPreheader() ||
Block == L->getLoopLatch() ||
7848 if (
Block == ThenBlock)
7849 NewBB->
setName(NamePrefix +
".if.else");
7852 VMap[
Block] = NewBB;
7860 L->getLoopLatch()->splitBasicBlockBefore(
L->getLoopLatch()->begin(),
7861 NamePrefix +
".pre_latch");
7865 L->addBasicBlockToLoop(ThenBlock, LI);
7871 if (TargetTriple.
isX86()) {
7872 if (Features.
lookup(
"avx512f"))
7874 else if (Features.
lookup(
"avx"))
7878 if (TargetTriple.
isPPC())
7880 if (TargetTriple.
isWasm())
7889 Value *IfCond, OrderKind Order,
7891 if (CanonicalLoop->VirtualCollapse)
7892 CanonicalLoop->reportUnsupportedVirtualCollapse();
7901 if (!BB.hasTerminator())
7917 I->eraseFromParent();
7920 if (AlignedVars.
size()) {
7922 for (
auto &AlignedItem : AlignedVars) {
7923 Value *AlignedPtr = AlignedItem.first;
7927 Builder.CreateAlignmentAssumption(
F->getDataLayout(), AlignedPtr,
7935 createIfVersion(CanonicalLoop, IfCond, VMap, LIA, LI, L,
"simd");
7948 Reachable.insert(
Block);
7958 if ((Safelen ==
nullptr) || (Order == OrderKind::OMP_ORDER_concurrent))
7974 if (Simdlen || Safelen) {
7978 ConstantInt *VectorizeWidth = Simdlen ==
nullptr ? Safelen : Simdlen;
8004static std::unique_ptr<TargetMachine>
8008 StringRef CPU =
F->getFnAttribute(
"target-cpu").getValueAsString();
8009 StringRef Features =
F->getFnAttribute(
"target-features").getValueAsString();
8020 std::nullopt, OptLevel));
8038 if (!BB.hasTerminator())
8051 [&](
const Function &
F) {
return TM->getTargetTransformInfo(
F); });
8052 FAM.registerPass([&]() {
return TIRA; });
8066 I->eraseFromParent();
8069 assert(L &&
"Expecting CanonicalLoopInfo to be recognized as a loop");
8074 nullptr, ORE,
static_cast<int>(OptLevel),
8094 <<
" Threshold=" << UP.
Threshold <<
"\n"
8097 <<
" PartialOptSizeThreshold="
8117 Ptr =
Load->getPointerOperand();
8119 Ptr =
Store->getPointerOperand();
8126 if (Alloca->getParent() == &
F->getEntryBlock())
8146 int MaxTripCount = 0;
8147 bool MaxOrZero =
false;
8148 unsigned TripMultiple = 0;
8152 MaxTripCount, MaxOrZero, TripMultiple, UCE, UP, PP);
8153 LLVM_DEBUG(
dbgs() <<
"Suggesting unroll factor of " << Factor <<
"\n");
8164 assert(Factor >= 0 &&
"Unroll factor must not be negative");
8180 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst}));
8183 addUnrollMetadata(
Loop, LoopMetadata);
8189 if (
Loop->VirtualCollapse)
8190 Loop->reportUnsupportedVirtualCollapse();
8196 *UnrolledCLI =
Loop;
8201 "unrolling only makes sense with a factor of 2 or larger");
8203 Type *IndVarTy =
Loop->getIndVarType();
8210 std::vector<CanonicalLoopInfo *>
LoopNest =
8225 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst})});
8228 (*UnrolledCLI)->assertOK();
8246 Value *Args[] = {Ident, ThreadId, BufSize, CpyBuf, CpyFn, DidItLD};
8265 if (!CPVars.
empty()) {
8270 Directive OMPD = Directive::OMPD_single;
8275 Value *Args[] = {Ident, ThreadId};
8284 if (
Error Err = FiniCB(IP))
8305 EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCBWrapper,
8312 for (
size_t I = 0, E = CPVars.
size();
I < E; ++
I)
8315 ConstantInt::get(Int64, 0), CPVars[
I],
8318 }
else if (!IsNowait) {
8321 omp::Directive::OMPD_unknown,
false,
8339 Directive::OMPD_scope,
nullptr,
nullptr,
8340 BodyGenCB, FiniCB,
false,
true,
8348 omp::Directive::OMPD_unknown,
8364 Directive OMPD = Directive::OMPD_critical;
8369 Value *LockVar = getOMPCriticalRegionLock(CriticalName);
8370 Value *Args[] = {Ident, ThreadId, LockVar};
8387 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
8395 const Twine &Name,
bool IsDependSource) {
8398 [](
Value *SV) {
return SV->getType()->isIntegerTy(64); }) &&
8399 "OpenMP runtime requires depend vec with i64 type");
8412 for (
unsigned I = 0;
I < NumLoops; ++
I) {
8426 Value *Args[] = {Ident, ThreadId, DependBaseAddrGEP};
8444 Directive OMPD = Directive::OMPD_ordered_blockassoc;
8453 Value *Args[] = {Ident, ThreadId};
8463 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
8470 bool HasFinalize,
bool IsCancellable) {
8477 BasicBlock *EntryBB = Builder.GetInsertBlock();
8481 SplitPos->
setDebugLoc(Builder.getCurrentDebugLocation());
8488 emitCommonDirectiveEntry(OMPD, EntryCall, ExitBB, Conditional);
8500 "Unexpected control flow graph state!!");
8502 emitCommonDirectiveExit(OMPD, FinIP, ExitCall, HasFinalize);
8504 return AfterIP.takeError();
8509 "Unexpected Insertion point location!");
8512 auto InsertBB = merged ? ExitPredBB : ExitBB;
8515 Builder.SetInsertPoint(InsertBB);
8521 Directive OMPD,
Value *EntryCall, BasicBlock *ExitBB,
bool Conditional) {
8523 if (!Conditional || !EntryCall)
8529 auto *UI =
new UnreachableInst(
Builder.getContext(), ThenBB);
8539 Builder.CreateCondBr(CallBool, ThenBB, ExitBB);
8543 UI->eraseFromParent();
8551 omp::Directive OMPD,
InsertPointTy FinIP, Instruction *ExitCall,
8559 "Unexpected finalization stack state!");
8562 assert(Fi.DK == OMPD &&
"Unexpected Directive for Finalization call!");
8566 return std::move(Err);
8613 "copyin.not.master.end");
8620 Builder.SetInsertPoint(OMP_Entry);
8623 Value *cmp =
Builder.CreateICmpNE(MasterPtr, PrivatePtr);
8624 Builder.CreateCondBr(cmp, CopyBegin, CopyEnd);
8626 Builder.SetInsertPoint(CopyBegin);
8644 Value *Args[] = {ThreadId,
Size, Allocator};
8667 return Builder.CreateCall(Fn, Args, Name);
8681 Value *Args[] = {ThreadId, Addr, Allocator};
8688 const Twine &Name) {
8696 M.getContext(),
M.getDataLayout().getPrefTypeAlign(Int64)));
8702 const Twine &Name) {
8704 Loc,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)), Name);
8709 const Twine &Name) {
8715 return Builder.CreateCall(Fn, Args, Name);
8720 const Twine &Name) {
8722 Loc, Addr,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)),
8729 Value *DependenceAddress,
bool HaveNowaitClause) {
8739 else if (
Device->getType() != Int32)
8742 if (NumDependences ==
nullptr) {
8743 NumDependences = ConstantInt::get(Int32, 0);
8747 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8749 Ident, ThreadId, InteropVar, InteropTypeVal,
8750 Device, NumDependences, DependenceAddress, HaveNowaitClauseVal};
8759 Value *NumDependences,
Value *DependenceAddress,
bool HaveNowaitClause) {
8769 else if (
Device->getType() != Int32)
8771 if (NumDependences ==
nullptr) {
8772 NumDependences = ConstantInt::get(Int32, 0);
8776 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8778 Ident, ThreadId, InteropVar,
Device,
8779 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8788 Value *NumDependences,
8789 Value *DependenceAddress,
8790 bool HaveNowaitClause) {
8799 else if (
Device->getType() != Int32)
8801 if (NumDependences ==
nullptr) {
8802 NumDependences = ConstantInt::get(Int32, 0);
8806 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8808 Ident, ThreadId, InteropVar,
Device,
8809 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8839 assert(!Attrs.MaxThreads.empty() && !Attrs.MaxTeams.empty() &&
8840 "expected num_threads and num_teams to be specified");
8860 const std::string DebugPrefix =
"_debug__";
8861 if (KernelName.
ends_with(DebugPrefix)) {
8862 KernelName = KernelName.
drop_back(DebugPrefix.length());
8863 Kernel =
M.getFunction(KernelName);
8869 if (Attrs.MinTeams.front() > 1 || Attrs.MaxTeams.front() > 0)
8871 Attrs.MaxTeams.front());
8874 int32_t MaxThreadsVal = Attrs.MaxThreads.front();
8884 Attrs.MinThreads.front());
8889 if (MaxThreadsVal > 0 &&
8892 MaxThreadsVal = int32_t(
8893 std::min<int64_t>(int64_t(MaxThreadsVal) + 64,
8896 if (MaxThreadsVal > 0)
8911 Twine DynamicEnvironmentName = KernelName +
"_dynamic_environment";
8912 Constant *DynamicEnvironmentInitializer =
8916 DynamicEnvironmentInitializer, DynamicEnvironmentName,
8918 DL.getDefaultGlobalsAddressSpace());
8922 DynamicEnvironmentGV->
getType() == DynamicEnvironmentPtr
8923 ? DynamicEnvironmentGV
8925 DynamicEnvironmentPtr);
8928 ConfigurationEnvironment, {
8929 UseGenericStateMachineVal,
8930 MayUseNestedParallelismVal,
8939 KernelEnvironment, {
8940 ConfigurationEnvironmentInitializer,
8944 std::string KernelEnvironmentName =
8945 (KernelName +
"_kernel_environment").str();
8948 KernelEnvironmentInitializer, KernelEnvironmentName,
8950 DL.getDefaultGlobalsAddressSpace());
8953 return KernelEnvironmentGV->
getType() == KernelEnvironmentPtr
8954 ? KernelEnvironmentGV
8956 KernelEnvironmentPtr);
8963 if (!KernelEnvironment)
8971 omp::RuntimeFunction::OMPRTL___kmpc_target_init);
8973 Value *KernelLaunchEnvironment =
8976 KernelLaunchEnvironment =
8977 KernelLaunchEnvironment->
getType() == KernelLaunchEnvParamTy
8978 ? KernelLaunchEnvironment
8979 :
Builder.CreateAddrSpaceCast(KernelLaunchEnvironment,
8980 KernelLaunchEnvParamTy);
8982 Fn, {KernelEnvironment, KernelLaunchEnvironment});
8994 auto *UI =
Builder.CreateUnreachable();
9000 Builder.SetInsertPoint(WorkerExitBB);
9004 Builder.SetInsertPoint(CheckBBTI);
9005 Builder.CreateCondBr(ExecUserCode, UI->getParent(), WorkerExitBB);
9007 CheckBBTI->eraseFromParent();
9008 UI->eraseFromParent();
9016 int32_t TeamsReductionDataSize) {
9021 omp::RuntimeFunction::OMPRTL___kmpc_target_deinit);
9025 if (!TeamsReductionDataSize)
9031 const std::string DebugPrefix =
"_debug__";
9033 KernelName = KernelName.
drop_back(DebugPrefix.length());
9034 auto *KernelEnvironmentGV =
9035 M.getNamedGlobal((KernelName +
"_kernel_environment").str());
9036 assert(KernelEnvironmentGV &&
"Expected kernel environment global\n");
9037 auto *KernelEnvironmentInitializer = KernelEnvironmentGV->getInitializer();
9039 KernelEnvironmentInitializer,
9040 ConstantInt::get(Int32, TeamsReductionDataSize), {0, 7});
9041 KernelEnvironmentGV->setInitializer(NewInitializer);
9046 if (
Kernel.hasFnAttribute(Name)) {
9047 int32_t OldLimit =
Kernel.getFnAttributeAsParsedInteger(Name);
9053std::pair<int32_t, int32_t>
9055 int32_t ThreadLimit =
9056 Kernel.getFnAttributeAsParsedInteger(
"omp_target_thread_limit");
9059 const auto &Attr =
Kernel.getFnAttribute(
"amdgpu-flat-work-group-size");
9060 if (!Attr.isValid() || !Attr.isStringAttribute())
9061 return {0, ThreadLimit};
9062 auto [LBStr, UBStr] = Attr.getValueAsString().split(
',');
9065 return {0, ThreadLimit};
9066 UB = ThreadLimit ? std::min(ThreadLimit, UB) : UB;
9074 return {0, ThreadLimit ? std::min(ThreadLimit, UB) : UB};
9076 return {0, ThreadLimit};
9082 Kernel.addFnAttr(
"omp_target_thread_limit", std::to_string(UB));
9085 Kernel.addFnAttr(
"amdgpu-flat-work-group-size",
9093std::pair<int32_t, int32_t>
9096 return {0,
Kernel.getFnAttributeAsParsedInteger(
"omp_target_num_teams")};
9100 int32_t LB, int32_t UB) {
9108 Kernel.addFnAttr(
"omp_target_num_teams", std::to_string(LB));
9111void OpenMPIRBuilder::setOutlinedTargetRegionFunctionAttributes(
9120 else if (
T.isNVPTX())
9122 else if (
T.isSPIRV())
9128 StringRef EntryFnIDName) {
9129 if (
Config.isTargetDevice()) {
9130 assert(OutlinedFn &&
"The outlined function must exist if embedded");
9134 return new GlobalVariable(
9139Constant *OpenMPIRBuilder::createTargetRegionEntryAddr(
Function *OutlinedFn,
9140 StringRef EntryFnName) {
9144 assert(!
M.getGlobalVariable(EntryFnName,
true) &&
9145 "Named kernel already exists?");
9146 return new GlobalVariable(
9159 if (
Config.isTargetDevice() || !
Config.openMPOffloadMandatory()) {
9163 OutlinedFn = *CBResult;
9165 OutlinedFn =
nullptr;
9171 if (!IsOffloadEntry)
9174 std::string EntryFnIDName =
9176 ? std::string(EntryFnName)
9180 EntryFnName, EntryFnIDName);
9188 setOutlinedTargetRegionFunctionAttributes(OutlinedFn);
9189 auto OutlinedFnID = createOutlinedFunctionID(OutlinedFn, EntryFnIDName);
9190 auto EntryAddr = createTargetRegionEntryAddr(OutlinedFn, EntryFnName);
9192 EntryInfo, EntryAddr, OutlinedFnID,
9194 return OutlinedFnID;
9212 bool IsStandAlone = !BodyGenCB;
9219 MapInfo = &GenMapInfoCB(
Builder.saveIP());
9221 AllocaIP,
Builder.saveIP(), *MapInfo, Info, CustomMapperCB,
9222 true, DeviceAddrCB))
9229 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
9239 SrcLocInfo, DeviceID,
9246 assert(MapperFunc &&
"MapperFunc missing for standalone target data");
9250 if (Info.HasNoWait) {
9260 if (Info.HasNoWait) {
9264 emitBlock(OffloadContBlock, CurFn,
true);
9270 bool RequiresOuterTargetTask = Info.HasNoWait;
9271 if (!RequiresOuterTargetTask)
9272 cantFail(TaskBodyCB(
nullptr,
nullptr,
9276 {}, RTArgs, Info.HasNoWait));
9279 omp::OMPRTL___tgt_target_data_begin_mapper);
9283 for (
auto DeviceMap : Info.DevicePtrInfoMap) {
9287 Builder.CreateStore(LI, DeviceMap.second.second);
9324 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
9333 Value *OffloadingArgs[] = {SrcLocInfo, DeviceID,
9356 return emitIfClause(IfCond, BeginThenGen, BeginElseGen, AllocaIP);
9357 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9372 return emitIfClause(IfCond, EndThenGen, EndElseGen, AllocaIP);
9373 return EndThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9376 return emitIfClause(IfCond, BeginThenGen, EndElseGen, AllocaIP);
9377 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9388 bool IsGPUDistribute) {
9389 assert((IVSize == 32 || IVSize == 64) &&
9390 "IV size is not compatible with the omp runtime");
9392 if (IsGPUDistribute)
9394 ? (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_4
9395 : omp::OMPRTL___kmpc_distribute_static_init_4u)
9396 : (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_8
9397 : omp::OMPRTL___kmpc_distribute_static_init_8u);
9399 Name = IVSize == 32 ? (IVSigned ? omp::OMPRTL___kmpc_for_static_init_4
9400 : omp::OMPRTL___kmpc_for_static_init_4u)
9401 : (IVSigned ? omp::OMPRTL___kmpc_for_static_init_8
9402 : omp::OMPRTL___kmpc_for_static_init_8u);
9409 assert((IVSize == 32 || IVSize == 64) &&
9410 "IV size is not compatible with the omp runtime");
9412 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_4
9413 : omp::OMPRTL___kmpc_dispatch_init_4u)
9414 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_8
9415 : omp::OMPRTL___kmpc_dispatch_init_8u);
9422 assert((IVSize == 32 || IVSize == 64) &&
9423 "IV size is not compatible with the omp runtime");
9425 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_4
9426 : omp::OMPRTL___kmpc_dispatch_next_4u)
9427 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_8
9428 : omp::OMPRTL___kmpc_dispatch_next_8u);
9435 assert((IVSize == 32 || IVSize == 64) &&
9436 "IV size is not compatible with the omp runtime");
9438 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_4
9439 : omp::OMPRTL___kmpc_dispatch_fini_4u)
9440 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_8
9441 : omp::OMPRTL___kmpc_dispatch_fini_8u);
9452 DenseMap<
Value *, std::tuple<Value *, unsigned>> &ValueReplacementMap) {
9460 auto GetUpdatedDIVariable = [&](
DILocalVariable *OldVar,
unsigned arg) {
9464 if (NewVar && (arg == NewVar->
getArg()))
9474 auto UpdateDebugRecord = [&](
auto *DR) {
9477 for (
auto Loc : DR->location_ops()) {
9478 auto Iter = ValueReplacementMap.find(
Loc);
9479 if (Iter != ValueReplacementMap.end()) {
9480 DR->replaceVariableLocationOp(
Loc, std::get<0>(Iter->second));
9481 ArgNo = std::get<1>(Iter->second) + 1;
9485 DR->setVariable(GetUpdatedDIVariable(OldVar, ArgNo));
9490 if (DVR->getNumVariableLocationOps() != 1u) {
9491 DVR->setKillLocation();
9494 Value *
Loc = DVR->getVariableLocationOp(0u);
9501 RequiredBB = &DVR->getFunction()->getEntryBlock();
9503 if (RequiredBB && RequiredBB != CurBB) {
9515 UpdateDebugRecord(&DVR);
9516 MoveDebugRecordToCorrectBlock(&DVR);
9519 for (
auto *DVR : DVRsToDelete)
9520 DVR->getMarker()->MarkedInstr->dropOneDbgRecord(DVR);
9524 Module *M = Func->getParent();
9527 DB.createQualifiedType(dwarf::DW_TAG_pointer_type,
nullptr);
9528 unsigned ArgNo = Func->arg_size();
9530 NewSP,
"dyn_ptr", ArgNo, NewSP->
getFile(), 0, VoidPtrTy,
9531 false, DINode::DIFlags::FlagArtificial);
9533 Argument *LastArg = Func->getArg(Func->arg_size() - 1);
9534 DB.insertDeclare(LastArg, Var, DB.createExpression(),
Loc,
9556 for (
auto &Arg : Inputs)
9557 ParameterTypes.
push_back(Arg->getType()->isPointerTy()
9561 for (
auto &Arg : Inputs)
9562 ParameterTypes.
push_back(Arg->getType());
9570 auto BB = Builder.GetInsertBlock();
9571 auto M = BB->getModule();
9582 if (TargetCpuAttr.isStringAttribute())
9583 Func->addFnAttr(TargetCpuAttr);
9585 auto TargetFeaturesAttr = ParentFn->
getFnAttribute(
"target-features");
9586 if (TargetFeaturesAttr.isStringAttribute())
9587 Func->addFnAttr(TargetFeaturesAttr);
9592 OMPBuilder.
emitUsed(
"llvm.compiler.used", {ExecMode});
9602 Builder.SetCurrentDebugLocation(OutlinedFnLoc);
9606 Builder.SetInsertPoint(EntryBB);
9617 BasicBlock *UserCodeEntryBB = Builder.GetInsertBlock();
9626 splitBB(Builder,
true,
"outlined.body");
9628 CBFunc(Builder.saveIP(), OutlinedBodyBB->
begin(), ExitBB);
9631 Builder.SetInsertPoint(ExitBB);
9639 Builder.SetCurrentDebugLocation(OutlinedFnLoc);
9646 Builder.CreateRetVoid();
9650 auto AllocaIP = Builder.saveIP();
9655 const auto &ArgRange =
make_range(Func->arg_begin(), Func->arg_end() - 1);
9687 if (Instr->getFunction() == Func)
9688 Instr->replaceUsesOfWith(
Input, InputCopy);
9694 for (
auto InArg :
zip(Inputs, ArgRange)) {
9696 Argument &Arg = std::get<1>(InArg);
9697 Value *InputCopy =
nullptr;
9700 Arg,
Input, InputCopy, AllocaIP, Builder.saveIP(), ExitBB->
begin());
9703 Builder.restoreIP(*AfterIP);
9704 ValueReplacementMap[
Input] = std::make_tuple(InputCopy, Arg.
getArgNo());
9724 DeferredReplacement.push_back(std::make_pair(
Input, InputCopy));
9731 ReplaceValue(
Input, InputCopy, Func);
9735 for (
auto Deferred : DeferredReplacement)
9736 ReplaceValue(std::get<0>(Deferred), std::get<1>(Deferred), Func);
9739 ValueReplacementMap);
9747 Value *TaskWithPrivates,
9748 Type *TaskWithPrivatesTy) {
9750 Type *TaskTy = OMPIRBuilder.Task;
9753 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 0);
9754 Value *Shareds = TaskT;
9764 if (TaskWithPrivatesTy != TaskTy)
9765 Shareds = Builder.CreateStructGEP(TaskTy, TaskT, 0);
9782 const size_t NumOffloadingArrays,
const int SharedArgsOperandNo) {
9787 assert((!NumOffloadingArrays || PrivatesTy) &&
9788 "PrivatesTy cannot be nullptr when there are offloadingArrays"
9818 Type *TaskPtrTy = OMPBuilder.TaskPtr;
9819 [[maybe_unused]]
Type *TaskTy = OMPBuilder.Task;
9825 ".omp_target_task_proxy_func", M);
9826 Value *ThreadId = ProxyFn->getArg(0);
9827 Value *TaskWithPrivates = ProxyFn->getArg(1);
9828 ThreadId->
setName(
"thread.id");
9829 TaskWithPrivates->
setName(
"task");
9831 bool HasShareds = SharedArgsOperandNo > 0;
9832 bool HasOffloadingArrays = NumOffloadingArrays > 0;
9836 Builder.SetInsertPoint(EntryBB);
9843 if (HasOffloadingArrays) {
9844 assert(TaskTy != TaskWithPrivatesTy &&
9845 "If there are offloading arrays to pass to the target"
9846 "TaskTy cannot be the same as TaskWithPrivatesTy");
9849 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 1);
9850 for (
unsigned int i = 0; i < NumOffloadingArrays; ++i)
9852 Builder.CreateStructGEP(PrivatesTy, Privates, i));
9856 auto *ArgStructAlloca =
9858 assert(ArgStructAlloca &&
9859 "Unable to find the alloca instruction corresponding to arguments "
9860 "for extracted function");
9862 std::optional<TypeSize> ArgAllocSize =
9864 assert(ArgStructType && ArgAllocSize &&
9865 "Unable to determine size of arguments for extracted function");
9866 uint64_t StructSize = ArgAllocSize->getFixedValue();
9869 Builder.CreateAlloca(ArgStructType,
nullptr,
"structArg");
9871 Value *SharedsSize = Builder.getInt64(StructSize);
9874 OMPBuilder, Builder, TaskWithPrivates, TaskWithPrivatesTy);
9876 Builder.CreateMemCpy(
9877 NewArgStructAlloca, NewArgStructAlloca->
getAlign(), LoadShared,
9879 KernelLaunchArgs.
push_back(NewArgStructAlloca);
9882 Builder.CreateRetVoid();
9888 return GEP->getSourceElementType();
9890 return Alloca->getAllocatedType();
9913 if (OffloadingArraysToPrivatize.
empty())
9914 return OMPIRBuilder.Task;
9917 for (
Value *V : OffloadingArraysToPrivatize) {
9918 assert(V->getType()->isPointerTy() &&
9919 "Expected pointer to array to privatize. Got a non-pointer value "
9922 assert(ArrayTy &&
"ArrayType cannot be nullptr");
9928 "struct.task_with_privates");
9943 EntryFnName, Inputs, CBFunc,
9944 ArgAccessorFuncCB, OutlinedFnLoc);
9948 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
10087 auto OI = std::make_unique<OutlineInfo>();
10088 OI->EntryBB = TargetTaskAllocaBB;
10089 OI->OuterAllocBB = AllocaIP.getNodeParent();
10094 Builder, AllocaIP, ToBeDeleted, TargetTaskAllocaIP,
"global.tid",
false));
10097 Builder.restoreIP(TargetTaskBodyIP);
10098 if (
Error Err = TaskBodyCB(DeviceID, RTLoc, TargetTaskAllocaIP))
10116 bool NeedsTargetTask = HasNoWait && DeviceID;
10117 if (NeedsTargetTask) {
10123 OffloadingArraysToPrivatize.
push_back(V);
10124 OI->ExcludeArgsFromAggregate.push_back(V);
10128 OI->PostOutlineCB = [
this, ToBeDeleted, Dependencies, NeedsTargetTask,
10129 DeviceID, OffloadingArraysToPrivatize](
10132 "there must be a single user for the outlined function");
10146 const unsigned int NumStaleCIArgs = StaleCI->
arg_size();
10147 bool HasShareds = NumStaleCIArgs > OffloadingArraysToPrivatize.
size() + 1;
10149 NumStaleCIArgs == (OffloadingArraysToPrivatize.
size() + 2)) &&
10150 "Wrong number of arguments for StaleCI when shareds are present");
10151 int SharedArgOperandNo =
10152 HasShareds ? OffloadingArraysToPrivatize.
size() + 1 : 0;
10158 if (!OffloadingArraysToPrivatize.
empty())
10163 *
this,
Builder, StaleCI, PrivatesTy, TaskWithPrivatesTy,
10164 OffloadingArraysToPrivatize.
size(), SharedArgOperandNo);
10166 LLVM_DEBUG(
dbgs() <<
"Proxy task entry function created: " << *ProxyFn
10169 Builder.SetInsertPoint(StaleCI);
10186 OMPRTL___kmpc_omp_target_task_alloc);
10198 M.getDataLayout().getTypeStoreSize(TaskWithPrivatesTy));
10205 auto *ArgStructAlloca =
10207 assert(ArgStructAlloca &&
10208 "Unable to find the alloca instruction corresponding to arguments "
10209 "for extracted function");
10210 std::optional<TypeSize> ArgAllocSize =
10213 "Unable to determine size of arguments for extracted function");
10214 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
10233 TaskSize, SharedsSize,
10236 if (NeedsTargetTask) {
10237 assert(DeviceID &&
"Expected non-empty device ID.");
10247 *
this,
Builder, TaskData, TaskWithPrivatesTy);
10251 if (!OffloadingArraysToPrivatize.
empty()) {
10253 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskData, 1);
10254 for (
unsigned int i = 0; i < OffloadingArraysToPrivatize.
size(); ++i) {
10255 Value *PtrToPrivatize = OffloadingArraysToPrivatize[i];
10262 "ElementType should match ArrayType");
10265 Value *Dst =
Builder.CreateStructGEP(PrivatesTy, Privates, i);
10268 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(ElementType)));
10272 Value *DepArray =
nullptr;
10273 Value *NumDeps =
nullptr;
10276 NumDeps = Dependencies.
NumDeps;
10277 }
else if (!Dependencies.
Deps.empty()) {
10279 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
10290 if (!NeedsTargetTask) {
10299 ConstantInt::get(
Builder.getInt32Ty(), 0),
10312 }
else if (DepArray) {
10320 {Ident, ThreadID, TaskData, NumDeps, DepArray,
10321 ConstantInt::get(
Builder.getInt32Ty(), 0),
10329 Builder.ClearInsertionPoint();
10332 I->eraseFromParent();
10337 << *(
Builder.GetInsertBlock()) <<
"\n");
10339 << *(
Builder.getModule()) <<
"\n");
10350 CustomMapperCB, IsNonContiguous, DeviceAddrCB))
10373 Builder.restoreIP(IP);
10379 return Builder.saveIP();
10382 bool HasDependencies = !Dependencies.
empty();
10383 bool RequiresOuterTargetTask = HasNoWait || HasDependencies;
10400 if (OutlinedFnID && DeviceID)
10402 EmitTargetCallFallbackCB, KArgs,
10403 DeviceID, RTLoc, TargetTaskAllocaIP);
10411 return EmitTargetCallFallbackCB(OMPBuilder.
Builder.
saveIP());
10418 auto &&EmitTargetCallElse =
10425 if (RequiresOuterTargetTask) {
10432 Dependencies, EmptyRTArgs, HasNoWait);
10434 return EmitTargetCallFallbackCB(Builder.saveIP());
10437 Builder.restoreIP(AfterIP);
10441 auto &&EmitTargetCallThen =
10445 Info.HasNoWait = HasNoWait;
10450 AllocaIP, Builder.saveIP(), Info, RTArgs, MapInfo, CustomMapperCB,
10456 for (
auto [DefaultVal, RuntimeVal] :
10458 NumTeamsC.
push_back(RuntimeVal ? RuntimeVal
10459 : Builder.getInt32(DefaultVal));
10463 auto InitMaxThreadsClause = [&Builder](
Value *
Clause) {
10465 Clause = Builder.CreateIntCast(
Clause, Builder.getInt32Ty(),
10469 auto CombineMaxThreadsClauses = [&Builder](
Value *
Clause,
Value *&Result) {
10472 Result ? Builder.CreateSelect(Builder.CreateICmpULT(Result,
Clause),
10480 Value *MaxThreadsClause =
10482 ? InitMaxThreadsClause(RuntimeAttrs.
MaxThreads.front())
10485 for (
auto [TeamsVal, TargetVal] :
zip_equal(
10487 Value *TeamsThreadLimitClause = InitMaxThreadsClause(TeamsVal);
10488 Value *NumThreads = InitMaxThreadsClause(TargetVal);
10490 CombineMaxThreadsClauses(TeamsThreadLimitClause, NumThreads);
10491 CombineMaxThreadsClauses(MaxThreadsClause, NumThreads);
10493 NumThreadsC.
push_back(NumThreads ? NumThreads : Builder.getInt32(0));
10496 unsigned NumTargetItems = Info.NumberOfPtrs;
10497 Value *RTLoc = RTLocOverride;
10508 Builder.getInt64Ty(),
10510 : Builder.getInt64(0);
10514 DynCGroupMem = Builder.getInt32(0);
10517 NumTargetItems, RTArgs, TripCount, NumTeamsC, NumThreadsC, DynCGroupMem,
10518 HasNoWait,
false,
false,
10519 DynCGroupMemFallback);
10526 if (RequiresOuterTargetTask)
10528 RTLoc, AllocaIP, Dependencies,
10529 KArgs.
RTArgs, Info.HasNoWait);
10532 Builder, OutlinedFnID, EmitTargetCallFallbackCB, KArgs,
10533 RuntimeAttrs.
DeviceID, RTLoc, AllocaIP);
10536 Builder.restoreIP(AfterIP);
10543 if (!OutlinedFnID) {
10544 cantFail(EmitTargetCallElse(AllocaIP, Builder.saveIP(), DeallocBlocks));
10550 cantFail(EmitTargetCallThen(AllocaIP, Builder.saveIP(), DeallocBlocks));
10555 EmitTargetCallElse, AllocaIP));
10568 bool HasNowait,
Value *DynCGroupMem,
10570 Value *RTLocOverride) {
10575 Builder.restoreIP(CodeGenIP);
10583 *
this,
Builder, IsOffloadEntry, EntryInfo, DefaultAttrs, OutlinedFn,
10584 OutlinedFnID, Inputs, CBFunc, ArgAccessorFuncCB, OutlinedFnLoc))
10590 if (!
Config.isTargetDevice())
10592 DefaultAttrs, RuntimeAttrs, IfCond, OutlinedFn, OutlinedFnID,
10593 Inputs, GenMapInfoCB, CustomMapperCB, Dependencies,
10594 HasNowait, DynCGroupMem, DynCGroupMemFallback);
10608 return OS.
str().str();
10613 return OpenMPIRBuilder::getNameWithSeparators(Parts,
Config.firstSeparator(),
10619 auto &Elem = *
InternalVars.try_emplace(Name,
nullptr).first;
10621 assert(Elem.second->getValueType() == Ty &&
10622 "OMP internal variable has different type than requested");
10635 :
M.getTargetTriple().isAMDGPU()
10637 :
DL.getDefaultGlobalsAddressSpace();
10638 auto Linkage = this->
M.getTargetTriple().isWasm()
10646 const llvm::Align PtrAlign =
DL.getPointerABIAlignment(AddressSpaceVal);
10647 GV->setAlignment(std::max(TypeAlign, PtrAlign));
10651 return Elem.second;
10654Value *OpenMPIRBuilder::getOMPCriticalRegionLock(
StringRef CriticalName) {
10655 std::string Prefix =
Twine(
"gomp_critical_user_", CriticalName).
str();
10656 std::string Name = getNameWithSeparators({Prefix,
"var"},
".",
".");
10667 return SizePtrToInt;
10672 std::string VarName) {
10680 return MaptypesArrayGlobal;
10685 unsigned NumOperands,
10694 ArrI8PtrTy,
nullptr,
".offload_baseptrs");
10698 ArrI64Ty,
nullptr,
".offload_sizes");
10709 int64_t DeviceID,
unsigned NumOperands) {
10715 Value *ArgsBaseGEP =
10717 {Builder.getInt32(0), Builder.getInt32(0)});
10720 {Builder.getInt32(0), Builder.getInt32(0)});
10721 Value *ArgSizesGEP =
10723 {Builder.getInt32(0), Builder.getInt32(0)});
10727 Builder.getInt32(NumOperands),
10728 ArgsBaseGEP, ArgsGEP, ArgSizesGEP,
10729 MaptypesArg, MapnamesArg, NullPtr});
10736 assert((!ForEndCall || Info.separateBeginEndCalls()) &&
10737 "expected region end call to runtime only when end call is separate");
10739 auto VoidPtrTy = UnqualPtrTy;
10740 auto VoidPtrPtrTy = UnqualPtrTy;
10742 auto Int64PtrTy = UnqualPtrTy;
10744 if (!Info.NumberOfPtrs) {
10756 Info.RTArgs.BasePointersArray,
10759 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray,
10763 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
10767 ForEndCall && Info.RTArgs.MapTypesArrayEnd ? Info.RTArgs.MapTypesArrayEnd
10768 : Info.RTArgs.MapTypesArray,
10774 if (!Info.EmitDebug)
10778 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.MapNamesArray,
10783 if (!Info.HasMapper)
10787 Builder.CreatePointerCast(Info.RTArgs.MappersArray, VoidPtrPtrTy);
10808 "struct.descriptor_dim");
10810 enum { OffsetFD = 0, CountFD, StrideFD };
10814 for (
unsigned I = 0, L = 0, E = NonContigInfo.
Dims.
size();
I < E; ++
I) {
10817 if (NonContigInfo.
Dims[
I] == 1)
10822 Builder.CreateAlloca(ArrayTy,
nullptr,
"dims");
10823 Builder.restoreIP(CodeGenIP);
10824 for (
unsigned II = 0, EE = NonContigInfo.
Dims[
I];
II < EE; ++
II) {
10825 unsigned RevIdx = EE -
II - 1;
10829 Value *OffsetLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, OffsetFD);
10831 NonContigInfo.
Offsets[L][RevIdx], OffsetLVal,
10832 M.getDataLayout().getPrefTypeAlign(OffsetLVal->
getType()));
10834 Value *CountLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, CountFD);
10836 NonContigInfo.
Counts[L][RevIdx], CountLVal,
10837 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10839 Value *StrideLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, StrideFD);
10841 NonContigInfo.
Strides[L][RevIdx], StrideLVal,
10842 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10845 Builder.restoreIP(CodeGenIP);
10846 Value *DAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
10847 DimsAddr,
Builder.getPtrTy());
10850 Info.RTArgs.PointersArray, 0,
I);
10852 DAddr,
P,
M.getDataLayout().getPrefTypeAlign(
Builder.getPtrTy()));
10857void OpenMPIRBuilder::emitUDMapperArrayInitOrDel(
10861 StringRef Prefix = IsInit ?
".init" :
".del";
10867 Builder.CreateICmpSGT(
Size, Builder.getInt64(1),
"omp.arrayinit.isarray");
10868 Value *DeleteBit = Builder.CreateAnd(
10871 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10872 OpenMPOffloadMappingFlags::OMP_MAP_DELETE)));
10877 Value *BaseIsBegin = Builder.CreateICmpNE(
Base, Begin);
10878 Cond = Builder.CreateOr(IsArray, BaseIsBegin);
10879 DeleteCond = Builder.CreateIsNull(
10884 DeleteCond =
Builder.CreateIsNotNull(
10900 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10901 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10902 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10903 MapTypeArg =
Builder.CreateOr(
10906 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10907 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT)));
10911 Value *OffloadingArgs[] = {MapperHandle,
Base, Begin,
10912 ArraySize, MapTypeArg, MapName};
10923 bool PreserveMemberOfFlags,
bool PropagatePresentToPointee) {
10937 MapperFn->
addFnAttr(Attribute::NoInline);
10938 MapperFn->
addFnAttr(Attribute::NoUnwind);
10949 Builder.SetInsertPoint(EntryBB);
10964 Value *PtrBegin = BeginIn;
10970 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
10971 MapType, MapName, ElementSize, HeadBB,
10982 Builder.CreateICmpEQ(PtrBegin, PtrEnd,
"omp.arraymap.isempty");
10983 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
10989 Builder.CreatePHI(PtrBegin->
getType(), 2,
"omp.arraymap.ptrcurrent");
10990 PtrPHI->addIncoming(PtrBegin, HeadBB);
10995 return Info.takeError();
10999 Value *OffloadingArgs[] = {MapperHandle};
11003 Value *ShiftedPreviousSize =
11007 for (
unsigned I = 0;
I < Info->BasePointers.size(); ++
I) {
11008 Value *CurBaseArg = Info->BasePointers[
I];
11009 Value *CurBeginArg = Info->Pointers[
I];
11010 Value *CurSizeArg = Info->Sizes[
I];
11011 Value *CurNameArg = Info->Names.size()
11016 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11019 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11021 constexpr uint64_t MemberOfMask =
11022 static_cast<uint64_t
>(OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
11023 constexpr uint64_t AttachBit =
11024 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11025 OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
11083 Value *MemberMapType;
11084 if (PreserveMemberOfFlags || (RawType & AttachBit) ||
11085 Info->HasAttachPtr[
I]) {
11086 if (RawType & MemberOfMask)
11087 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
11089 MemberMapType = OriMapType;
11091 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
11109 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11110 OpenMPOffloadMappingFlags::OMP_MAP_TO |
11111 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
11121 Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
11127 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11128 OpenMPOffloadMappingFlags::OMP_MAP_TO |
11129 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
11135 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11136 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
11137 Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
11143 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11144 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
11150 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11151 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
11152 Builder.CreateCondBr(IsFrom, FromBB, EndBB);
11158 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11159 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
11168 CurMapType->
addIncoming(MemberMapType, ToElseBB);
11205 uint64_t ModifierBits =
11206 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11207 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
11208 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
11209 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
11210 if (PropagatePresentToPointee && Info->HasAttachPtr[
I])
11212 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11213 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
11214 Value *ImportedModifierBits =
11217 CurMapType, ImportedModifierBits,
"omp.maptype.with.modifiers");
11222 Value *FinalMapType =
11223 (RawType & AttachBit) ? CurMapType : CurMapTypeWithModifiers;
11225 Value *OffloadingArgs[] = {MapperHandle, CurBaseArg, CurBeginArg,
11226 CurSizeArg, FinalMapType, CurNameArg};
11228 auto ChildMapperFn = CustomMapperCB(
I);
11229 if (!ChildMapperFn)
11230 return ChildMapperFn.takeError();
11231 if (*ChildMapperFn) {
11247 "omp.arraymap.next");
11248 PtrPHI->addIncoming(PtrNext, LastBB);
11249 Value *IsDone =
Builder.CreateICmpEQ(PtrNext, PtrEnd,
"omp.arraymap.isdone");
11251 Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
11256 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
11257 MapType, MapName, ElementSize, DoneBB,
11270 bool IsNonContiguous,
11274 Info.clearArrayInfo();
11277 if (Info.NumberOfPtrs == 0)
11286 Info.RTArgs.BasePointersArray =
Builder.CreateAlloca(
11287 PointerArrayType,
nullptr,
".offload_baseptrs");
11289 Info.RTArgs.PointersArray =
Builder.CreateAlloca(
11290 PointerArrayType,
nullptr,
".offload_ptrs");
11292 PointerArrayType,
nullptr,
".offload_mappers");
11293 Info.RTArgs.MappersArray = MappersArray;
11300 ConstantInt::get(Int64Ty, 0));
11302 for (
unsigned I = 0, E = CombinedInfo.
Sizes.
size();
I < E; ++
I) {
11303 bool IsNonContigEntry =
11305 (
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11307 OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG) != 0);
11310 if (IsNonContigEntry) {
11312 "Index must be in-bounds for NON_CONTIG Dims array");
11314 assert(DimCount > 0 &&
"NON_CONTIG DimCount must be > 0");
11315 ConstSizes[
I] = ConstantInt::get(Int64Ty, DimCount);
11320 ConstSizes[
I] = CI;
11324 RuntimeSizes.
set(
I);
11327 if (RuntimeSizes.
all()) {
11329 Info.RTArgs.SizesArray =
Builder.CreateAlloca(
11330 SizeArrayType,
nullptr,
".offload_sizes");
11336 auto *SizesArrayGbl =
11341 if (!RuntimeSizes.
any()) {
11342 Info.RTArgs.SizesArray = SizesArrayGbl;
11344 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
11345 Align OffloadSizeAlign =
M.getDataLayout().getABIIntegerTypeAlignment(64);
11348 SizeArrayType,
nullptr,
".offload_sizes");
11352 Buffer,
M.getDataLayout().getPrefTypeAlign(Buffer->
getType()),
11353 SizesArrayGbl, OffloadSizeAlign,
11358 Info.RTArgs.SizesArray = Buffer;
11366 for (
auto mapFlag : CombinedInfo.
Types)
11368 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11372 Info.RTArgs.MapTypesArray = MapTypesArrayGbl;
11378 Info.RTArgs.MapNamesArray = MapNamesArrayGbl;
11379 Info.EmitDebug =
true;
11381 Info.RTArgs.MapNamesArray =
11383 Info.EmitDebug =
false;
11388 if (Info.separateBeginEndCalls()) {
11389 bool EndMapTypesDiffer =
false;
11390 for (uint64_t &
Type : Mapping) {
11391 if (
Type &
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11392 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT)) {
11393 Type &= ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
11394 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
11395 EndMapTypesDiffer =
true;
11398 if (EndMapTypesDiffer) {
11400 Info.RTArgs.MapTypesArrayEnd = MapTypesArrayGbl;
11405 for (
unsigned I = 0;
I < Info.NumberOfPtrs; ++
I) {
11408 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.BasePointersArray,
11410 Builder.CreateAlignedStore(BPVal, BP,
11411 M.getDataLayout().getPrefTypeAlign(PtrTy));
11413 if (Info.requiresDevicePointerInfo()) {
11415 CodeGenIP =
Builder.saveIP();
11417 Info.DevicePtrInfoMap[BPVal] = {BP,
Builder.CreateAlloca(PtrTy)};
11420 DeviceAddrCB(
I, Info.DevicePtrInfoMap[BPVal].second);
11422 Info.DevicePtrInfoMap[BPVal] = {BP, BP};
11424 DeviceAddrCB(
I, BP);
11430 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray, 0,
11433 Builder.CreateAlignedStore(PVal,
P,
11434 M.getDataLayout().getPrefTypeAlign(PtrTy));
11436 if (RuntimeSizes.
test(
I)) {
11438 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
11444 S,
M.getDataLayout().getPrefTypeAlign(PtrTy));
11447 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
11450 auto CustomMFunc = CustomMapperCB(
I);
11452 return CustomMFunc.takeError();
11454 MFunc =
Builder.CreatePointerCast(*CustomMFunc, PtrTy);
11457 PointerArrayType, MappersArray,
11460 MFunc, MAddr,
M.getDataLayout().getPrefTypeAlign(MAddr->
getType()));
11464 Info.NumberOfPtrs == 0)
11481 Builder.ClearInsertionPoint();
11512 auto CondConstant = CI->getSExtValue();
11514 return ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
11516 return ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
11526 Builder.CreateCondBr(
Cond, ThenBlock, ElseBlock);
11529 if (
Error Err = ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks))
11535 if (
Error Err = ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks))
11544bool OpenMPIRBuilder::checkAndEmitFlushAfterAtomic(
11548 "Unexpected Atomic Ordering.");
11550 bool Flush =
false;
11612 assert(
X.Var->getType()->isPointerTy() &&
11613 "OMP Atomic expects a pointer to target memory");
11614 Type *XElemTy =
X.ElemTy;
11617 "OMP atomic read expected a scalar type");
11619 Value *XRead =
nullptr;
11623 Builder.CreateLoad(XElemTy,
X.Var,
X.IsVolatile,
"omp.atomic.read");
11632 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11635 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11637 XRead = AtomicLoadRes.first;
11644 Builder.CreateLoad(IntCastTy,
X.Var,
X.IsVolatile,
"omp.atomic.load");
11647 XRead =
Builder.CreateBitCast(XLoad, XElemTy,
"atomic.flt.cast");
11649 XRead =
Builder.CreateIntToPtr(XLoad, XElemTy,
"atomic.ptr.cast");
11652 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Read);
11653 Builder.CreateStore(XRead, V.Var, V.IsVolatile);
11664 assert(
X.Var->getType()->isPointerTy() &&
11665 "OMP Atomic expects a pointer to target memory");
11666 Type *XElemTy =
X.ElemTy;
11669 "OMP atomic write expected a scalar type");
11677 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11680 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11688 Builder.CreateBitCast(Expr, IntCastTy,
"atomic.src.int.cast");
11693 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Write);
11700 AtomicUpdateCallbackTy &UpdateOp,
bool IsXBinopExpr,
11701 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11707 Type *XTy =
X.Var->getType();
11709 "OMP Atomic expects a pointer to target memory");
11710 Type *XElemTy =
X.ElemTy;
11713 "OMP atomic update expected a scalar or struct type");
11717 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, RMWOp, UpdateOp,
X.IsVolatile,
11718 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11720 return AtomicResult.takeError();
11721 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Update);
11726Value *OpenMPIRBuilder::emitRMWOpAsInstruction(
Value *Src1,
Value *Src2,
11730 return Builder.CreateAdd(Src1, Src2);
11732 return Builder.CreateSub(Src1, Src2);
11734 return Builder.CreateAnd(Src1, Src2);
11736 return Builder.CreateNeg(Builder.CreateAnd(Src1, Src2));
11738 return Builder.CreateOr(Src1, Src2);
11740 return Builder.CreateXor(Src1, Src2);
11742 return Builder.CreateBinaryIntrinsic(Intrinsic::smax, Src1, Src2);
11744 return Builder.CreateBinaryIntrinsic(Intrinsic::smin, Src1, Src2);
11746 return Builder.CreateBinaryIntrinsic(Intrinsic::umax, Src1, Src2);
11748 return Builder.CreateBinaryIntrinsic(Intrinsic::umin, Src1, Src2);
11750 return Builder.CreateFAdd(Src1, Src2);
11752 return Builder.CreateFSub(Src1, Src2);
11754 return Builder.CreateMaxNum(Src1, Src2);
11756 return Builder.CreateMinNum(Src1, Src2);
11758 return Builder.CreateMaximum(Src1, Src2);
11760 return Builder.CreateMinimum(Src1, Src2);
11789Expected<std::pair<Value *, Value *>> OpenMPIRBuilder::emitAtomicUpdate(
11792 AtomicUpdateCallbackTy &UpdateOp,
bool VolatileX,
bool IsXBinopExpr,
11793 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11795 bool emitRMWOp =
false;
11812 emitRMWOp = XElemTy;
11816 emitRMWOp = (IsXBinopExpr && XElemTy);
11824 std::pair<Value *, Value *> Res;
11826 AtomicRMWInst *RMWInst =
11827 Builder.CreateAtomicRMW(RMWOp,
X, Expr, llvm::MaybeAlign(), AO);
11828 if (IsIgnoreDenormalMode)
11829 RMWInst->
setMetadata(llvm::LLVMContext::MD_atomic_ignore_denormal_mode,
11831 if (
T.isAMDGPU()) {
11832 if (!IsFineGrainedMemory)
11833 RMWInst->
setMetadata(
"amdgpu.no.fine.grained.memory",
11835 if (!IsRemoteMemory)
11839 Res.first = RMWInst;
11844 Res.second = Res.first;
11846 Res.second = emitRMWOpAsInstruction(Res.first, Expr, RMWOp);
11849 Builder.CreateLoad(XElemTy,
X,
X->getName() +
".atomic.load");
11855 OpenMPIRBuilder::AtomicInfo atomicInfo(
11857 OldVal->
getAlign(),
true , AllocaIP,
X);
11858 auto AtomicLoadRes = atomicInfo.EmitAtomicLoadLibcall(AO);
11861 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11868 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11869 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11870 Builder.SetInsertPoint(ContBB);
11872 PHI->addIncoming(AtomicLoadRes.first, CurBB);
11874 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11877 Value *Upd = *CBResult;
11878 Builder.CreateStore(Upd, NewAtomicAddr);
11881 auto Result = atomicInfo.EmitAtomicCompareExchangeLibcall(
11882 AtomicLoadRes.second, NewAtomicAddr, AO, Failure);
11883 LoadInst *PHILoad =
Builder.CreateLoad(XElemTy,
Result.first);
11884 PHI->addIncoming(PHILoad,
Builder.GetInsertBlock());
11887 Res.first = OldExprVal;
11890 if (UnreachableInst *ExitTI =
11893 Builder.SetInsertPoint(ExitBB);
11895 Builder.SetInsertPoint(ExitTI);
11898 IntegerType *IntCastTy =
11901 Builder.CreateLoad(IntCastTy,
X,
X->getName() +
".atomic.load");
11911 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11918 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11919 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11920 Builder.SetInsertPoint(ContBB);
11922 PHI->addIncoming(OldVal, CurBB);
11927 OldExprVal =
Builder.CreateBitCast(
PHI, XElemTy,
11928 X->getName() +
".atomic.fltCast");
11930 OldExprVal =
Builder.CreateIntToPtr(
PHI, XElemTy,
11931 X->getName() +
".atomic.ptrCast");
11935 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11938 Value *Upd = *CBResult;
11939 Builder.CreateStore(Upd, NewAtomicAddr);
11940 LoadInst *DesiredVal =
Builder.CreateLoad(IntCastTy, NewAtomicAddr);
11944 X,
PHI, DesiredVal, llvm::MaybeAlign(), AO, Failure);
11945 Result->setVolatile(VolatileX);
11946 Value *PreviousVal =
Builder.CreateExtractValue(Result, 0);
11947 Value *SuccessFailureVal =
Builder.CreateExtractValue(Result, 1);
11948 PHI->addIncoming(PreviousVal,
Builder.GetInsertBlock());
11949 Builder.CreateCondBr(SuccessFailureVal, ExitBB, ContBB);
11951 Res.first = OldExprVal;
11955 if (UnreachableInst *ExitTI =
11958 Builder.SetInsertPoint(ExitBB);
11960 Builder.SetInsertPoint(ExitTI);
11971 bool UpdateExpr,
bool IsPostfixUpdate,
bool IsXBinopExpr,
11972 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11977 Type *XTy =
X.Var->getType();
11979 "OMP Atomic expects a pointer to target memory");
11980 Type *XElemTy =
X.ElemTy;
11983 "OMP atomic capture expected a scalar or struct type");
11990 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, AtomicOp, UpdateOp,
X.IsVolatile,
11991 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11994 Value *CapturedVal =
11995 (IsPostfixUpdate ? AtomicResult->first : AtomicResult->second);
11996 Builder.CreateStore(CapturedVal, V.Var, V.IsVolatile);
11998 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Capture);
12006 bool IsFailOnly,
bool IsWeak) {
12010 IsPostfixUpdate, IsFailOnly, Failure, IsWeak);
12022 assert(
X.Var->getType()->isPointerTy() &&
12023 "OMP atomic expects a pointer to target memory");
12026 assert(V.Var->getType()->isPointerTy() &&
"v.var must be of pointer type");
12027 assert(V.ElemTy ==
X.ElemTy &&
"x and v must be of same type");
12030 bool IsInteger = E->getType()->isIntegerTy();
12032 if (
Op == OMPAtomicCompareOp::EQ) {
12035 Value *OldValue =
nullptr;
12036 Value *SuccessOrFail =
nullptr;
12074 X.Var->getName() +
".atomic.load");
12080 Value *EIsNaN =
Builder.CreateFCmpUNO(E, E,
"atomic.e.isnan");
12081 Value *XIsNaN =
Builder.CreateFCmpUNO(XFP, XFP,
"atomic.x.isnan");
12082 Value *EitherNaN =
Builder.CreateOr(EIsNaN, XIsNaN,
"atomic.either.nan");
12087 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
12091 M.getContext(),
X.Var->getName() +
".atomic.nan",
F, ExitBB);
12093 M.getContext(),
X.Var->getName() +
".atomic.notnan",
F, ExitBB);
12095 M.getContext(),
X.Var->getName() +
".atomic.zero",
F, ExitBB);
12097 M.getContext(),
X.Var->getName() +
".atomic.normal",
F, ExitBB);
12101 Builder.SetInsertPoint(CurBB);
12102 Builder.CreateCondBr(EitherNaN, NaNBB, NotNaNBB);
12105 Builder.SetInsertPoint(NaNBB);
12109 Builder.SetInsertPoint(NotNaNBB);
12112 X.Var->getName() +
".atomic.xiszero");
12114 "atomic.e.iszero");
12115 Value *BothZero =
Builder.CreateAnd(XIsZero, EIsZero,
"atomic.both.zero");
12116 Builder.CreateCondBr(BothZero, ZeroBB, NormalBB);
12119 Builder.SetInsertPoint(ZeroBB);
12121 X.Var, XCurr, DBCast,
MaybeAlign(), AO, Failure);
12123 Value *OldZero =
Builder.CreateExtractValue(ResZero, 0);
12124 Value *OkZero =
Builder.CreateExtractValue(ResZero, 1);
12128 Builder.SetInsertPoint(NormalBB);
12130 X.Var, EBCast, DBCast,
MaybeAlign(), AO, Failure);
12132 Value *OldNormal =
Builder.CreateExtractValue(ResNormal, 0);
12133 Value *OkNormal =
Builder.CreateExtractValue(ResNormal, 1);
12139 Builder.CreatePHI(IntCastTy, 3,
X.Var->getName() +
".atomic.old");
12144 X.Var->getName() +
".atomic.ok");
12151 Builder.SetInsertPoint(ExitBB);
12156 OldValue =
Builder.CreateBitCast(OldIntPHI,
X.ElemTy,
12157 X.Var->getName() +
".atomic.old.fp");
12158 SuccessOrFail = SuccessPHI;
12166 Result =
Builder.CreateAtomicCmpXchg(
X.Var, EBCast, DBCast,
12172 Result->setWeak(IsWeak);
12175 OldValue =
Builder.CreateExtractValue(Result, 0);
12177 OldValue =
Builder.CreateBitCast(OldValue,
X.ElemTy);
12179 "OldValue and V must be of same type");
12180 if (IsPostfixUpdate) {
12181 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
12183 SuccessOrFail =
Builder.CreateExtractValue(Result, 1);
12187 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
12189 CurBBTI,
X.Var->getName() +
".atomic.exit");
12195 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
12197 Builder.SetInsertPoint(ContBB);
12198 Builder.CreateStore(OldValue, V.Var);
12204 Builder.SetInsertPoint(ExitBB);
12206 Builder.SetInsertPoint(ExitTI);
12209 Value *CapturedValue =
12210 Builder.CreateSelect(SuccessOrFail, E, OldValue);
12211 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
12217 assert(R.Var->getType()->isPointerTy() &&
12218 "r.var must be of pointer type");
12219 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
12221 Value *SuccessFailureVal =
12222 Builder.CreateExtractValue(Result, 1);
12223 Value *ResultCast =
12224 R.IsSigned ?
Builder.CreateSExt(SuccessFailureVal, R.ElemTy)
12225 :
Builder.CreateZExt(SuccessFailureVal, R.ElemTy);
12226 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
12235 "OldValue and V must be of same type");
12236 if (IsPostfixUpdate) {
12237 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
12242 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
12244 CurBBTI,
X.Var->getName() +
".atomic.exit");
12250 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
12252 Builder.SetInsertPoint(ContBB);
12253 Builder.CreateStore(OldValue, V.Var);
12259 Builder.SetInsertPoint(ExitBB);
12261 Builder.SetInsertPoint(ExitTI);
12264 Value *CapturedValue =
12265 Builder.CreateSelect(SuccessOrFail, E, OldValue);
12266 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
12272 assert(R.Var->getType()->isPointerTy() &&
12273 "r.var must be of pointer type");
12274 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
12276 Value *ResultCast = R.IsSigned
12277 ?
Builder.CreateSExt(SuccessOrFail, R.ElemTy)
12278 :
Builder.CreateZExt(SuccessOrFail, R.ElemTy);
12279 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
12283 assert((
Op == OMPAtomicCompareOp::MAX ||
Op == OMPAtomicCompareOp::MIN) &&
12284 "Op should be either max or min at this point");
12285 assert(!IsFailOnly &&
"IsFailOnly is only valid when the comparison is ==");
12296 if (IsXBinopExpr) {
12325 Value *CapturedValue =
nullptr;
12326 if (IsPostfixUpdate) {
12327 CapturedValue = OldValue;
12352 Value *NonAtomicCmp =
Builder.CreateCmp(Pred, OldValue, E);
12353 CapturedValue =
Builder.CreateSelect(NonAtomicCmp, E, OldValue);
12355 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
12359 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Compare);
12379 if (&OuterAllocaBB ==
Builder.GetInsertBlock()) {
12406 bool SubClausesPresent =
12407 (NumTeamsLower || NumTeamsUpper || ThreadLimit || IfExpr);
12409 if (!
Config.isTargetDevice() && SubClausesPresent) {
12410 assert((NumTeamsLower ==
nullptr || NumTeamsUpper !=
nullptr) &&
12411 "if lowerbound is non-null, then upperbound must also be non-null "
12412 "for bounds on num_teams");
12414 if (NumTeamsUpper ==
nullptr)
12415 NumTeamsUpper =
Builder.getInt32(0);
12417 if (NumTeamsLower ==
nullptr)
12418 NumTeamsLower = NumTeamsUpper;
12422 "argument to if clause must be an integer value");
12426 IfExpr =
Builder.CreateICmpNE(IfExpr,
12427 ConstantInt::get(IfExpr->
getType(), 0));
12428 NumTeamsUpper =
Builder.CreateSelect(
12429 IfExpr, NumTeamsUpper,
Builder.getInt32(1),
"numTeamsUpper");
12432 NumTeamsLower =
Builder.CreateSelect(
12433 IfExpr, NumTeamsLower,
Builder.getInt32(1),
"numTeamsLower");
12436 if (ThreadLimit ==
nullptr)
12437 ThreadLimit =
Builder.getInt32(0);
12441 Value *NumTeamsLowerInt32 =
12443 Value *NumTeamsUpperInt32 =
12445 Value *ThreadLimitInt32 =
12452 {Ident, ThreadNum, NumTeamsLowerInt32, NumTeamsUpperInt32,
12453 ThreadLimitInt32});
12458 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
12461 auto OI = std::make_unique<OutlineInfo>();
12462 OI->EntryBB = AllocaBB;
12463 OI->ExitBB = ExitBB;
12464 OI->OuterAllocBB = &OuterAllocaBB;
12470 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"gid",
true));
12472 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"tid",
true));
12474 auto HostPostOutlineCB = [
this, Ident,
12475 ToBeDeleted](
Function &OutlinedFn)
mutable {
12480 "there must be a single user for the outlined function");
12485 "Outlined function must have two or three arguments only");
12487 bool HasShared = OutlinedFn.
arg_size() == 3;
12495 assert(StaleCI &&
"Error while outlining - no CallInst user found for the "
12496 "outlined function.");
12497 Builder.SetInsertPoint(StaleCI);
12504 omp::RuntimeFunction::OMPRTL___kmpc_fork_teams),
12507 Builder.ClearInsertionPoint();
12509 I->eraseFromParent();
12512 if (!
Config.isTargetDevice())
12513 OI->PostOutlineCB = HostPostOutlineCB;
12517 Builder.SetInsertPoint(ExitBB);
12528 BasicBlock *OuterAllocaBB = OuterAllocIP.getNodeParent();
12530 if (OuterAllocaBB ==
Builder.GetInsertBlock()) {
12545 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
12550 if (
Config.isTargetDevice()) {
12551 auto OI = std::make_unique<OutlineInfo>();
12552 OI->OuterAllocBB = OuterAllocIP.getNodeParent();
12553 OI->EntryBB = AllocaBB;
12554 OI->ExitBB = ExitBB;
12555 OI->OuterDeallocBBs.reserve(OuterDeallocBlocks.
size());
12556 copy(OuterDeallocBlocks, OI->OuterDeallocBBs.
end());
12560 Builder.SetInsertPoint(ExitBB);
12567 std::string VarName) {
12576 return MapNamesArrayGlobal;
12581void OpenMPIRBuilder::initializeTypes(
Module &M) {
12585 unsigned ProgramAS = M.getDataLayout().getProgramAddressSpace();
12586#define OMP_TYPE(VarName, InitValue) VarName = InitValue;
12587#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \
12588 VarName##Ty = ArrayType::get(ElemTy, ArraySize); \
12589 VarName##PtrTy = PointerType::get(Ctx, DefaultTargetAS);
12590#define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) \
12591 VarName = FunctionType::get(ReturnType, {__VA_ARGS__}, IsVarArg); \
12592 VarName##Ptr = PointerType::get(Ctx, ProgramAS);
12593#define OMP_STRUCT_TYPE(VarName, StructName, Packed, ...) \
12594 T = StructType::getTypeByName(Ctx, StructName); \
12596 T = StructType::create(Ctx, {__VA_ARGS__}, StructName, Packed); \
12598 VarName##Ptr = PointerType::get(Ctx, DefaultTargetAS);
12599#include "llvm/Frontend/OpenMP/OMPKinds.def"
12610 while (!Worklist.
empty()) {
12614 if (
BlockSet.insert(SuccBB).second)
12619std::unique_ptr<CodeExtractor>
12621 bool ArgsInZeroAddressSpace,
12623 return std::make_unique<CodeExtractor>(
12633 Suffix.
str(), ArgsInZeroAddressSpace);
12636std::unique_ptr<CodeExtractor> DeviceSharedMemOutlineInfo::createCodeExtractor(
12638 return std::make_unique<DeviceSharedMemCodeExtractor>(
12639 OMPBuilder, Blocks,
nullptr,
12647 OuterDeallocBBs.empty()
12650 Suffix.
str(), ArgsInZeroAddressSpace);
12654 uint64_t
Size, int32_t Flags,
12660 Name.empty() ? Addr->
getName() : Name,
Size, Flags, 0);
12672 Fn->
addFnAttr(
"uniform-work-group-size");
12673 Fn->
addFnAttr(Attribute::MustProgress);
12691 auto &&GetMDInt = [
this](
unsigned V) {
12698 NamedMDNode *MD =
M.getOrInsertNamedMetadata(
"omp_offload.info");
12699 auto &&TargetRegionMetadataEmitter =
12700 [&
C, MD, &OrderedEntries, &GetMDInt, &GetMDString](
12715 GetMDInt(E.getKind()), GetMDInt(EntryInfo.DeviceID),
12716 GetMDInt(EntryInfo.FileID), GetMDString(EntryInfo.ParentName),
12717 GetMDInt(EntryInfo.Line), GetMDInt(EntryInfo.Count),
12718 GetMDInt(E.getOrder())};
12721 OrderedEntries[E.getOrder()] = std::make_pair(&E, EntryInfo);
12730 auto &&DeviceGlobalVarMetadataEmitter =
12731 [&
C, &OrderedEntries, &GetMDInt, &GetMDString, MD](
12741 Metadata *
Ops[] = {GetMDInt(E.getKind()), GetMDString(MangledName),
12742 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
12746 OrderedEntries[E.getOrder()] = std::make_pair(&E, varInfo);
12753 DeviceGlobalVarMetadataEmitter);
12755 for (
const auto &E : OrderedEntries) {
12756 assert(E.first &&
"All ordered entries must exist!");
12757 if (
const auto *CE =
12760 if (!CE->getID() || !CE->getAddress()) {
12764 if (!
M.getNamedValue(FnName))
12772 }
else if (
const auto *CE =
dyn_cast<
12781 if (
Config.isTargetDevice() &&
Config.hasRequiresUnifiedSharedMemory())
12783 if (!CE->getAddress()) {
12788 if (CE->getVarSize() == 0)
12792 assert(((
Config.isTargetDevice() && !CE->getAddress()) ||
12793 (!
Config.isTargetDevice() && CE->getAddress())) &&
12794 "Declaret target link address is set.");
12795 if (
Config.isTargetDevice())
12797 if (!CE->getAddress()) {
12804 if (!CE->getAddress()) {
12817 if ((
GV->hasLocalLinkage() ||
GV->hasHiddenVisibility()) &&
12821 OMPTargetGlobalVarEntryIndirectVTable))
12830 Flags, CE->getLinkage(), CE->getVarName());
12833 Flags, CE->getLinkage());
12844 if (
Config.hasRequiresFlags() && !
Config.isTargetDevice())
12850 Config.getRequiresFlags());
12860 OS <<
"_" <<
Count;
12865 unsigned NewCount = getTargetRegionEntryInfoCount(EntryInfo);
12868 EntryInfo.
Line, NewCount);
12876 auto FileIDInfo = CallBack();
12877 uint64_t FileID = 0;
12879 ID =
Status->getUniqueID();
12880 FileID =
Status->getUniqueID().getFile();
12884 FileID =
hash_value(std::get<0>(FileIDInfo));
12888 std::get<1>(FileIDInfo));
12893 for (uint64_t Remain =
12894 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12896 !(Remain & 1); Remain = Remain >> 1)
12914 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12916 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12923 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12929 Flags &=
~omp::OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
12930 Flags |= MemberOfFlag;
12936 bool IsDeclaration,
bool IsExternallyVisible,
12938 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12939 std::vector<Triple> TargetTriple,
Type *LlvmPtrTy,
12940 std::function<
Constant *()> GlobalInitializer,
12951 Config.hasRequiresUnifiedSharedMemory())) {
12956 if (!IsExternallyVisible)
12958 OS <<
"_decl_tgt_ref_ptr";
12961 Value *Ptr =
M.getNamedValue(PtrName);
12970 if (!
Config.isTargetDevice()) {
12971 if (GlobalInitializer)
12972 GV->setInitializer(GlobalInitializer());
12978 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12979 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12980 GlobalInitializer, VariableLinkage, LlvmPtrTy,
cast<Constant>(Ptr));
12992 bool IsDeclaration,
bool IsExternallyVisible,
12994 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12995 std::vector<Triple> TargetTriple,
12996 std::function<
Constant *()> GlobalInitializer,
13000 (TargetTriple.empty() && !
Config.isTargetDevice()))
13011 !
Config.hasRequiresUnifiedSharedMemory()) {
13013 VarName = MangledName;
13016 if (!IsDeclaration)
13018 M.getDataLayout().getTypeSizeInBits(LlvmVal->
getValueType()), 8);
13021 Linkage = (VariableLinkage) ? VariableLinkage() : LlvmVal->
getLinkage();
13025 if (
Config.isTargetDevice() &&
13034 if (!
M.getNamedValue(RefName)) {
13038 GvAddrRef->setConstant(
true);
13040 GvAddrRef->setInitializer(Addr);
13041 GeneratedRefs.push_back(GvAddrRef);
13050 if (
Config.isTargetDevice()) {
13051 VarName = (Addr) ? Addr->
getName() :
"";
13055 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
13056 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
13057 LlvmPtrTy, GlobalInitializer, VariableLinkage);
13058 VarName = (Addr) ? Addr->
getName() :
"";
13060 VarSize =
M.getDataLayout().getPointerSize();
13079 auto &&GetMDInt = [MN](
unsigned Idx) {
13084 auto &&GetMDString = [MN](
unsigned Idx) {
13086 return V->getString();
13089 switch (GetMDInt(0)) {
13093 case OffloadEntriesInfoManager::OffloadEntryInfo::
13094 OffloadingEntryInfoTargetRegion: {
13104 case OffloadEntriesInfoManager::OffloadEntryInfo::
13105 OffloadingEntryInfoDeviceGlobalVar:
13118 if (HostFilePath.
empty())
13122 if (std::error_code Err = Buf.getError()) {
13124 "OpenMPIRBuilder: " +
13132 if (std::error_code Err =
M.getError()) {
13134 (
"error parsing host file inside of OpenMPIRBuilder: " + Err.message())
13148 "expected a valid insertion block for creating an iterator loop");
13152 if (SplitIP == CurBB->
end())
13154 SplitIP = Terminator->getIterator();
13158 Builder.getCurrentDebugLocation(),
"omp.it.cont");
13170 T->eraseFromParent();
13185 bool ReachesLatch =
false;
13188 while (!Worklist.
empty()) {
13193 "iterator bodygen must leave at most one unterminated block",
13199 if (Succ == Latch) {
13200 ReachesLatch =
true;
13205 "iterator bodygen must not branch out of the loop body",
13207 if (Visited.
insert(Succ).second)
13213 Builder.SetInsertPoint(OpenBB);
13215 }
else if (!ReachesLatch) {
13225 return ContBB->
begin();
13235 for (
const auto &
ParamAttr : ParamAttrs) {
13278 return std::string(Out.str());
13286 unsigned VecRegSize;
13288 ISADataTy ISAData[] = {
13307 for (
char Mask :
Masked) {
13308 for (
const ISADataTy &
Data : ISAData) {
13311 Out <<
"_ZGV" <<
Data.ISA << Mask;
13313 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
13327template <
typename T>
13330 StringRef MangledName,
bool OutputBecomesInput,
13334 Out << Prefix << ISA << LMask << VLEN;
13335 if (OutputBecomesInput)
13337 Out << ParSeq <<
'_' << MangledName;
13346 bool OutputBecomesInput,
13351 OutputBecomesInput, Fn);
13353 OutputBecomesInput, Fn);
13357 OutputBecomesInput, Fn);
13359 OutputBecomesInput, Fn);
13363 OutputBecomesInput, Fn);
13365 OutputBecomesInput, Fn);
13370 OutputBecomesInput, Fn);
13381 char ISA,
unsigned NarrowestDataSize,
bool OutputBecomesInput) {
13382 assert((ISA ==
'n' || ISA ==
's') &&
"Expected ISA either 's' or 'n'.");
13394 OutputBecomesInput, Fn);
13401 OutputBecomesInput, Fn);
13403 OutputBecomesInput, Fn);
13407 OutputBecomesInput, Fn);
13411 OutputBecomesInput, Fn);
13420 OutputBecomesInput, Fn);
13427 MangledName, OutputBecomesInput, Fn);
13429 MangledName, OutputBecomesInput, Fn);
13433 MangledName, OutputBecomesInput, Fn);
13437 MangledName, OutputBecomesInput, Fn);
13447 return OffloadEntriesTargetRegion.empty() &&
13448 OffloadEntriesDeviceGlobalVar.empty();
13451unsigned OffloadEntriesInfoManager::getTargetRegionEntryInfoCount(
13453 auto It = OffloadEntriesTargetRegionCount.find(
13454 getTargetRegionEntryCountKey(EntryInfo));
13455 if (It == OffloadEntriesTargetRegionCount.end())
13460void OffloadEntriesInfoManager::incrementTargetRegionEntryInfoCount(
13462 OffloadEntriesTargetRegionCount[getTargetRegionEntryCountKey(EntryInfo)] =
13463 EntryInfo.
Count + 1;
13469 OffloadEntriesTargetRegion[EntryInfo] =
13472 ++OffloadingEntriesNum;
13478 assert(EntryInfo.
Count == 0 &&
"expected default EntryInfo");
13481 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
13485 if (OMPBuilder->Config.isTargetDevice()) {
13490 auto &Entry = OffloadEntriesTargetRegion[EntryInfo];
13491 Entry.setAddress(Addr);
13493 Entry.setFlags(Flags);
13499 "Target region entry already registered!");
13501 OffloadEntriesTargetRegion[EntryInfo] = Entry;
13502 ++OffloadingEntriesNum;
13504 incrementTargetRegionEntryInfoCount(EntryInfo);
13511 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
13513 auto It = OffloadEntriesTargetRegion.find(EntryInfo);
13514 if (It == OffloadEntriesTargetRegion.end()) {
13518 if (!IgnoreAddressId && (It->second.getAddress() || It->second.getID()))
13526 for (
const auto &It : OffloadEntriesTargetRegion) {
13527 Action(It.first, It.second);
13533 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
13534 ++OffloadingEntriesNum;
13540 if (OMPBuilder->Config.isTargetDevice()) {
13544 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
13546 if (Entry.getVarSize() == 0) {
13547 Entry.setVarSize(VarSize);
13548 Entry.setLinkage(Linkage);
13552 Entry.setVarSize(VarSize);
13553 Entry.setLinkage(Linkage);
13554 Entry.setAddress(Addr);
13557 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
13558 assert(Entry.isValid() && Entry.getFlags() == Flags &&
13559 "Entry not initialized!");
13560 if (Entry.getVarSize() == 0) {
13561 Entry.setVarSize(VarSize);
13562 Entry.setLinkage(Linkage);
13569 OffloadEntriesDeviceGlobalVar.try_emplace(VarName, OffloadingEntriesNum,
13570 Addr, VarSize, Flags, Linkage,
13573 OffloadEntriesDeviceGlobalVar.try_emplace(
13574 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage,
"");
13575 ++OffloadingEntriesNum;
13582 for (
const auto &E : OffloadEntriesDeviceGlobalVar)
13583 Action(E.getKey(), E.getValue());
13590void CanonicalLoopInfo::reportUnsupportedVirtualCollapse()
const {
13592 assert(VirtualCollapse &&
"Requires Virtual collapse state");
13594 "virtual collapse must be the final structural loop transformation");
13597void CanonicalLoopInfo::collectControlBlocks(
13599 if (VirtualCollapse)
13600 reportUnsupportedVirtualCollapse();
13606 BBs.
append({getPreheader(), Header,
Cond, Latch, Exit, getAfter()});
13609BasicBlock *CanonicalLoopInfo::getVirtualCollapseInit()
const {
13610 return VirtualCollapse ? VirtualCollapse->Count->getParent() :
nullptr;
13615 if (VirtualCollapse)
13616 return getVirtualCollapseInit()->getSinglePredecessor();
13625void CanonicalLoopInfo::setTripCount(
Value *TripCount) {
13637void CanonicalLoopInfo::mapIndVar(
13647 for (
Use &U : OldIV->
uses()) {
13651 if (
User->getParent() == getCond())
13653 if (
User->getParent() == getLatch())
13659 Value *NewIV = Updater(OldIV);
13662 for (Use *U : ReplacableUses)
13676 bool IsVirtual = VirtualCollapse.has_value();
13682 IndVarEntry = Guard->getSuccessor(0);
13685 assert(Guard->getSuccessor(1) == Exit);
13686 assert(VirtualCollapse->Begin->getParent() ==
Init);
13688 {VirtualCollapse->Begin, VirtualCollapse->Count}) {
13690 assert(Copy->getOpcode() == Instruction::Add && Zero && Zero->isZero() &&
13691 "Virtual range copies must add zero");
13695 NonEmpty->getOperand(0) == VirtualCollapse->Count &&
13697 "Collapsed guard must skip empty ranges with zero count");
13709 "Preheader must terminate with unconditional branch");
13712 "Preheader must jump to collapsed initialization");
13715 "Preheader must jump to header");
13719 "Header must terminate with unconditional branch");
13720 assert(Header->getSingleSuccessor() == Cond &&
13721 "Header must jump to exiting block");
13724 assert(Cond->getSinglePredecessor() == Header &&
13725 "Exiting block only reachable from header");
13728 "Exiting block must terminate with conditional branch");
13730 "Exiting block's first successor jump to the body");
13732 "Exiting block's second successor must exit the loop");
13736 "Body only reachable from exiting block");
13741 "Latch must terminate with unconditional branch");
13742 assert(Latch->getSingleSuccessor() == Header &&
"Latch must jump to header");
13745 assert(Latch->getSinglePredecessor() !=
nullptr);
13750 "Exit block must terminate with unconditional branch");
13751 assert(Exit->getSingleSuccessor() == After &&
13752 "Exit block must jump to after block");
13756 "After block only reachable from exit block");
13760 assert(IndVar &&
"Canonical induction variable not found?");
13762 "Induction variable must be an integer");
13764 "Induction variable must be a PHI in the loop header");
13771 auto *NextIndVar =
cast<PHINode>(IndVar)->getIncomingValue(1);
13780 assert(TripCount &&
"Loop trip count not found?");
13782 "Trip count and induction variable must have the same type");
13786 "Exit condition must be a signed less-than comparison");
13788 "Exit condition must compare the induction variable");
13790 "Exit condition must compare with the trip count");
13799 VirtualCollapse.reset();
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 ...
SmallVector< MachineOperand, 4 > 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),...
const T & back() const
Get the last element.
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.
This class is the base class for the comparison instructions.
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 using Config.CollapseMapping.
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)
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
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.
Physical handles captured before the source descriptors are invalidated.
SmallVector< PHINode *, 4 > IndVars
SmallVector< BasicBlock *, 4 > Preheaders
SmallVector< BasicBlock *, 4 > Latches
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),...