68#define DEBUG_TYPE "openmp-ir-builder"
75 cl::desc(
"Use optimistic attributes describing "
76 "'as-if' properties of runtime calls."),
80 "openmp-ir-builder-unroll-threshold-factor",
cl::Hidden,
81 cl::desc(
"Factor for the unroll threshold to account for code "
82 "simplifications still taking place"),
86 "openmp-ir-builder-use-default-max-threads",
cl::Hidden,
97 if (!IP1.isValid() || !IP2.isValid())
104 switch (SchedType & ~OMPScheduleType::MonotonicityMask) {
105 case OMPScheduleType::UnorderedStaticChunked:
106 case OMPScheduleType::UnorderedStatic:
107 case OMPScheduleType::UnorderedDynamicChunked:
108 case OMPScheduleType::UnorderedGuidedChunked:
109 case OMPScheduleType::UnorderedRuntime:
110 case OMPScheduleType::UnorderedAuto:
111 case OMPScheduleType::UnorderedTrapezoidal:
112 case OMPScheduleType::UnorderedGreedy:
113 case OMPScheduleType::UnorderedBalanced:
114 case OMPScheduleType::UnorderedGuidedIterativeChunked:
115 case OMPScheduleType::UnorderedGuidedAnalyticalChunked:
116 case OMPScheduleType::UnorderedSteal:
117 case OMPScheduleType::UnorderedStaticBalancedChunked:
118 case OMPScheduleType::UnorderedGuidedSimd:
119 case OMPScheduleType::UnorderedRuntimeSimd:
120 case OMPScheduleType::OrderedStaticChunked:
121 case OMPScheduleType::OrderedStatic:
122 case OMPScheduleType::OrderedDynamicChunked:
123 case OMPScheduleType::OrderedGuidedChunked:
124 case OMPScheduleType::OrderedRuntime:
125 case OMPScheduleType::OrderedAuto:
126 case OMPScheduleType::OrderdTrapezoidal:
127 case OMPScheduleType::NomergeUnorderedStaticChunked:
128 case OMPScheduleType::NomergeUnorderedStatic:
129 case OMPScheduleType::NomergeUnorderedDynamicChunked:
130 case OMPScheduleType::NomergeUnorderedGuidedChunked:
131 case OMPScheduleType::NomergeUnorderedRuntime:
132 case OMPScheduleType::NomergeUnorderedAuto:
133 case OMPScheduleType::NomergeUnorderedTrapezoidal:
134 case OMPScheduleType::NomergeUnorderedGreedy:
135 case OMPScheduleType::NomergeUnorderedBalanced:
136 case OMPScheduleType::NomergeUnorderedGuidedIterativeChunked:
137 case OMPScheduleType::NomergeUnorderedGuidedAnalyticalChunked:
138 case OMPScheduleType::NomergeUnorderedSteal:
139 case OMPScheduleType::NomergeOrderedStaticChunked:
140 case OMPScheduleType::NomergeOrderedStatic:
141 case OMPScheduleType::NomergeOrderedDynamicChunked:
142 case OMPScheduleType::NomergeOrderedGuidedChunked:
143 case OMPScheduleType::NomergeOrderedRuntime:
144 case OMPScheduleType::NomergeOrderedAuto:
145 case OMPScheduleType::NomergeOrderedTrapezoidal:
146 case OMPScheduleType::OrderedDistributeChunked:
147 case OMPScheduleType::OrderedDistribute:
155 SchedType & OMPScheduleType::MonotonicityMask;
156 if (MonotonicityFlags == OMPScheduleType::MonotonicityMask)
170 Builder.restoreIP(IP);
174 if (Builder.GetInsertPoint() != BB->
end())
184 unsigned Line = FSP->getScopeLine() ? FSP->getScopeLine() : FSP->getLine();
185 Builder.SetCurrentDebugLocation(
191 return T.isAMDGPU() ||
T.isNVPTX() ||
T.isSPIRV();
197 Kernel->getFnAttribute(
"target-features").getValueAsString();
198 if (Features.
count(
"+wavefrontsize64"))
213 bool HasSimdModifier,
bool HasDistScheduleChunks) {
215 switch (ClauseKind) {
216 case OMP_SCHEDULE_Default:
217 case OMP_SCHEDULE_Static:
218 return HasChunks ? OMPScheduleType::BaseStaticChunked
219 : OMPScheduleType::BaseStatic;
220 case OMP_SCHEDULE_Dynamic:
221 return OMPScheduleType::BaseDynamicChunked;
222 case OMP_SCHEDULE_Guided:
223 return HasSimdModifier ? OMPScheduleType::BaseGuidedSimd
224 : OMPScheduleType::BaseGuidedChunked;
225 case OMP_SCHEDULE_Auto:
227 case OMP_SCHEDULE_Runtime:
228 return HasSimdModifier ? OMPScheduleType::BaseRuntimeSimd
229 : OMPScheduleType::BaseRuntime;
230 case OMP_SCHEDULE_Distribute:
231 return HasDistScheduleChunks ? OMPScheduleType::BaseDistributeChunked
232 : OMPScheduleType::BaseDistribute;
240 bool HasOrderedClause) {
241 assert((BaseScheduleType & OMPScheduleType::ModifierMask) ==
242 OMPScheduleType::None &&
243 "Must not have ordering nor monotonicity flags already set");
246 ? OMPScheduleType::ModifierOrdered
247 : OMPScheduleType::ModifierUnordered;
251 if (OrderingScheduleType ==
252 (OMPScheduleType::BaseGuidedSimd | OMPScheduleType::ModifierOrdered))
253 return OMPScheduleType::OrderedGuidedChunked;
254 else if (OrderingScheduleType == (OMPScheduleType::BaseRuntimeSimd |
255 OMPScheduleType::ModifierOrdered))
256 return OMPScheduleType::OrderedRuntime;
258 return OrderingScheduleType;
264 bool HasSimdModifier,
bool HasMonotonic,
265 bool HasNonmonotonic,
bool HasOrderedClause) {
266 assert((ScheduleType & OMPScheduleType::MonotonicityMask) ==
267 OMPScheduleType::None &&
268 "Must not have monotonicity flags already set");
269 assert((!HasMonotonic || !HasNonmonotonic) &&
270 "Monotonic and Nonmonotonic are contradicting each other");
273 return ScheduleType | OMPScheduleType::ModifierMonotonic;
274 }
else if (HasNonmonotonic) {
275 return ScheduleType | OMPScheduleType::ModifierNonmonotonic;
285 if ((BaseScheduleType == OMPScheduleType::BaseStatic) ||
286 (BaseScheduleType == OMPScheduleType::BaseStaticChunked) ||
292 return ScheduleType | OMPScheduleType::ModifierNonmonotonic;
300 bool HasSimdModifier,
bool HasMonotonicModifier,
301 bool HasNonmonotonicModifier,
bool HasOrderedClause,
302 bool HasDistScheduleChunks) {
304 ClauseKind, HasChunks, HasSimdModifier, HasDistScheduleChunks);
308 OrderedSchedule, HasSimdModifier, HasMonotonicModifier,
309 HasNonmonotonicModifier, HasOrderedClause);
317static std::optional<omp::OMPTgtExecModeFlags>
322 if (
Call->getCalledFunction()->getName() ==
"__kmpc_target_init") {
323 TargetInitCall =
Call;
348 std::optional<omp::OMPTgtExecModeFlags> ExecMode =
360 if (
Instruction *Term = Source->getTerminatorOrNull()) {
369 NewBr->setDebugLoc(
DL);
374 assert(New->getFirstInsertionPt() == New->begin() &&
375 "Target BB must not have PHI nodes");
391 New->splice(New->begin(), Old, IP, Old->
end());
395 NewBr->setDebugLoc(
DL);
407 Builder.SetInsertPoint(Old);
411 Builder.SetCurrentDebugLocation(
DebugLoc);
421 New->replaceSuccessorsPhiUsesWith(Old, New);
430 Builder.SetInsertPoint(Builder.GetInsertBlock()->getTerminator());
432 Builder.SetInsertPoint(Builder.GetInsertBlock());
435 Builder.SetCurrentDebugLocation(
DebugLoc);
444 Builder.SetInsertPoint(Builder.GetInsertBlock()->getTerminator());
446 Builder.SetInsertPoint(Builder.GetInsertBlock());
449 Builder.SetCurrentDebugLocation(
DebugLoc);
466 const Twine &Name =
"",
bool AsPtr =
true,
467 bool Is64Bit =
false) {
468 Builder.restoreIP(OuterAllocaIP);
472 Builder.CreateAlloca(IntTy,
nullptr, Name +
".addr");
476 FakeVal = FakeValAddr;
481 FakeValAddr, Builder.getPtrTy(), Name +
".ascast"));
485 FakeVal = Builder.CreateLoad(IntTy, FakeValAddr, Name +
".val");
490 Builder.restoreIP(InnerAllocaIP);
493 UseFakeVal = Builder.CreateLoad(IntTy, FakeVal, Name +
".use");
496 FakeVal, Is64Bit ? Builder.getInt64(10) : Builder.getInt32(10)));
509enum OpenMPOffloadingRequiresDirFlags {
511 OMP_REQ_UNDEFINED = 0x000,
513 OMP_REQ_NONE = 0x001,
515 OMP_REQ_REVERSE_OFFLOAD = 0x002,
517 OMP_REQ_UNIFIED_ADDRESS = 0x004,
519 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008,
521 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010,
528 DominatorTree *DT =
nullptr,
bool AggregateArgs =
false,
529 BlockFrequencyInfo *BFI =
nullptr,
530 BranchProbabilityInfo *BPI =
nullptr,
531 AssumptionCache *AC =
nullptr,
bool AllowVarArgs =
false,
532 bool AllowAlloca =
false,
533 BasicBlock *AllocationBlock =
nullptr,
535 std::string Suffix =
"",
bool ArgsInZeroAddressSpace =
false)
536 : CodeExtractor(BBs, DT, AggregateArgs, BFI, BPI, AC, AllowVarArgs,
537 AllowAlloca, AllocationBlock, DeallocationBlocks, Suffix,
538 ArgsInZeroAddressSpace),
539 OMPBuilder(OMPBuilder) {}
541 virtual ~OMPCodeExtractor() =
default;
544 OpenMPIRBuilder &OMPBuilder;
547class DeviceSharedMemCodeExtractor :
public OMPCodeExtractor {
549 using OMPCodeExtractor::OMPCodeExtractor;
550 virtual ~DeviceSharedMemCodeExtractor() =
default;
554 allocateVar(IRBuilder<>::InsertPoint AllocaIP,
DebugLoc DL,
Type *VarType,
555 const Twine &Name = Twine(
""),
556 AddrSpaceCastInst **CastedAlloc =
nullptr)
override {
557 return OMPBuilder.createOMPAllocShared({AllocaIP,
DL}, VarType,
Name);
560 virtual Instruction *deallocateVar(IRBuilder<>::InsertPoint DeallocIP,
562 Type *VarType)
override {
563 return OMPBuilder.createOMPFreeShared({DeallocIP,
DL}, Var, VarType);
570 OpenMPIRBuilder &OMPBuilder;
572 DeviceSharedMemOutlineInfo(OpenMPIRBuilder &OMPBuilder)
573 : OMPBuilder(OMPBuilder) {}
574 virtual ~DeviceSharedMemOutlineInfo() =
default;
576 virtual std::unique_ptr<CodeExtractor>
578 bool ArgsInZeroAddressSpace,
579 Twine Suffix = Twine(
""))
override;
585 : RequiresFlags(OMP_REQ_UNDEFINED) {}
589 bool HasRequiresReverseOffload,
bool HasRequiresUnifiedAddress,
590 bool HasRequiresUnifiedSharedMemory,
bool HasRequiresDynamicAllocators)
593 RequiresFlags(OMP_REQ_UNDEFINED) {
594 if (HasRequiresReverseOffload)
595 RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
596 if (HasRequiresUnifiedAddress)
597 RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
598 if (HasRequiresUnifiedSharedMemory)
599 RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
600 if (HasRequiresDynamicAllocators)
601 RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
605 return RequiresFlags & OMP_REQ_REVERSE_OFFLOAD;
609 return RequiresFlags & OMP_REQ_UNIFIED_ADDRESS;
613 return RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY;
617 return RequiresFlags & OMP_REQ_DYNAMIC_ALLOCATORS;
622 :
static_cast<int64_t
>(OMP_REQ_NONE);
627 RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
629 RequiresFlags &= ~OMP_REQ_REVERSE_OFFLOAD;
634 RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
636 RequiresFlags &= ~OMP_REQ_UNIFIED_ADDRESS;
641 RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
643 RequiresFlags &= ~OMP_REQ_UNIFIED_SHARED_MEMORY;
648 RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
650 RequiresFlags &= ~OMP_REQ_DYNAMIC_ALLOCATORS;
663 constexpr size_t MaxDim = 3;
668 Value *DynCGroupMemFallbackFlag =
670 DynCGroupMemFallbackFlag =
Builder.CreateShl(DynCGroupMemFallbackFlag, 2);
675 StrictBlocksFlag =
Builder.CreateShl(StrictBlocksFlag, 6);
676 StrictThreadsFlag =
Builder.CreateShl(StrictThreadsFlag, 7);
678 Value *Flags =
Builder.CreateOr(HasNoWaitFlag, DynCGroupMemFallbackFlag);
679 Flags =
Builder.CreateOr(Flags, StrictBlocksFlag);
680 Flags =
Builder.CreateOr(Flags, StrictThreadsFlag);
686 Value *NumThreads3D =
717 auto FnAttrs = Attrs.getFnAttrs();
718 auto RetAttrs = Attrs.getRetAttrs();
720 for (
size_t ArgNo = 0; ArgNo < Fn.
arg_size(); ++ArgNo)
725 bool Param =
true) ->
void {
726 bool HasSignExt = AS.hasAttribute(Attribute::SExt);
727 bool HasZeroExt = AS.hasAttribute(Attribute::ZExt);
728 if (HasSignExt || HasZeroExt) {
729 assert(AS.getNumAttributes() == 1 &&
730 "Currently not handling extension attr combined with others.");
732 if (
auto AK = TargetLibraryInfo::getExtAttrForI32Param(
T, HasSignExt))
735 TargetLibraryInfo::getExtAttrForI32Return(
T, HasSignExt))
742#define OMP_ATTRS_SET(VarName, AttrSet) AttributeSet VarName = AttrSet;
743#include "llvm/Frontend/OpenMP/OMPKinds.def"
747#define OMP_RTL_ATTRS(Enum, FnAttrSet, RetAttrSet, ArgAttrSets) \
749 FnAttrs = FnAttrs.addAttributes(Ctx, FnAttrSet); \
750 addAttrSet(RetAttrs, RetAttrSet, false); \
751 for (size_t ArgNo = 0; ArgNo < ArgAttrSets.size(); ++ArgNo) \
752 addAttrSet(ArgAttrs[ArgNo], ArgAttrSets[ArgNo]); \
753 Fn.setAttributes(AttributeList::get(Ctx, FnAttrs, RetAttrs, ArgAttrs)); \
755#include "llvm/Frontend/OpenMP/OMPKinds.def"
769#define OMP_RTL(Enum, Str, IsVarArg, ReturnType, ...) \
771 FnTy = FunctionType::get(ReturnType, ArrayRef<Type *>{__VA_ARGS__}, \
773 Fn = M.getFunction(Str); \
775#include "llvm/Frontend/OpenMP/OMPKinds.def"
781#define OMP_RTL(Enum, Str, ...) \
783 Fn = Function::Create(FnTy, GlobalValue::ExternalLinkage, Str, M); \
785#include "llvm/Frontend/OpenMP/OMPKinds.def"
789 if (FnID == OMPRTL___kmpc_fork_call || FnID == OMPRTL___kmpc_fork_teams) {
799 LLVMContext::MD_callback,
801 2, {-1, -1},
true)}));
814 assert(Fn &&
"Failed to create OpenMP runtime function");
825 Builder.SetInsertPoint(FiniBB);
837 FiniBB = OtherFiniBB;
839 Builder.SetInsertPoint(FiniBB->getFirstNonPHIIt());
847 auto EndIt = FiniBB->end();
848 if (FiniBB->size() >= 1)
849 if (
auto Prev = std::prev(EndIt); Prev->isTerminator())
854 FiniBB->replaceAllUsesWith(OtherFiniBB);
855 FiniBB->eraseFromParent();
856 FiniBB = OtherFiniBB;
863 assert(Fn &&
"Failed to create OpenMP runtime function pointer");
886 for (
auto Inst =
Block->getReverseIterator()->begin();
887 Inst !=
Block->getReverseIterator()->end();) {
916 Block.getParent()->getEntryBlock().getTerminator()->getIterator();
937 DeferredOutlines.
push_back(std::move(OI));
941 ParallelRegionBlockSet.
clear();
943 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
953 bool ArgsInZeroAddressSpace =
Config.isTargetDevice();
954 std::unique_ptr<CodeExtractor> Extractor =
955 OI->createCodeExtractor(Blocks, ArgsInZeroAddressSpace,
".omp_par");
959 <<
" Exit: " << OI->ExitBB->getName() <<
"\n");
960 assert(Extractor->isEligible() &&
961 "Expected OpenMP outlining to be possible!");
963 for (
auto *V : OI->ExcludeArgsFromAggregate)
964 Extractor->excludeArgFromAggregate(V);
967 Extractor->extractCodeRegion(CEAC, OI->Inputs, OI->Outputs);
971 if (TargetCpuAttr.isStringAttribute())
974 auto TargetFeaturesAttr = OuterFn->
getFnAttribute(
"target-features");
975 if (TargetFeaturesAttr.isStringAttribute())
976 OutlinedFn->
addFnAttr(TargetFeaturesAttr);
979 LLVM_DEBUG(
dbgs() <<
" Outlined function: " << *OutlinedFn <<
"\n");
981 "OpenMP outlined functions should not return a value!");
986 M.getFunctionList().insertAfter(OuterFn->
getIterator(), OutlinedFn);
993 assert(OI->EntryBB->getUniquePredecessor() == &ArtificialEntry);
1000 "Expected instructions to add in the outlined region entry");
1007 if (
I.isTerminator()) {
1009 if (
Instruction *TI = OI->EntryBB->getTerminatorOrNull())
1010 TI->adoptDbgRecords(&ArtificialEntry,
I.getIterator(),
false);
1014 I.moveBeforePreserving(*OI->EntryBB,
1015 OI->EntryBB->getFirstInsertionPt());
1018 OI->EntryBB->moveBefore(&ArtificialEntry);
1025 if (OI->PostOutlineCB)
1026 OI->PostOutlineCB(*OutlinedFn);
1028 if (OI->FixUpNonEntryAllocas)
1060 errs() <<
"Error of kind: " << Kind
1061 <<
" when emitting offload entries and metadata during "
1062 "OMPIRBuilder finalization \n";
1070 if (
Config.isTargetDevice())
1071 applyDeclareTargetGlobalReplacements();
1073 if (
Config.EmitLLVMUsedMetaInfo.value_or(
false)) {
1074 std::vector<WeakTrackingVH> LLVMCompilerUsed = {
1075 M.getGlobalVariable(
"__openmp_nvptx_data_transfer_temporary_storage")};
1076 emitUsed(
"llvm.compiler.used", LLVMCompilerUsed);
1086 assert(Original && Replacement &&
1087 "Null values provided to registerDeclareTargetGlobalReplacement");
1091void OpenMPIRBuilder::applyDeclareTargetGlobalReplacements() {
1097 "A null value was inserted into DeclareTargetGlobalReplacements");
1101 if (!OldGV || !NewGV)
1135 for (
unsigned I = 0, E =
PHI->getNumIncomingValues();
I < E; ++
I) {
1136 if (
PHI->getIncomingValue(
I) != OldGV)
1141 Builder.SetCurrentDebugLocation(
PHI->getDebugLoc());
1143 PHI->setIncomingValue(
I, EdgeLoad);
1149 Builder.SetCurrentDebugLocation(Insn->getDebugLoc());
1165 "Non-default address space declare target global");
1167 unsigned DestAS = ASC->getType()->getPointerAddressSpace();
1168 if (DestAS == 0 && NewGVAS != OldGVAS) {
1169 ASC->replaceAllUsesWith(
Load);
1170 ASC->eraseFromParent();
1175 Insn->replaceUsesOfWith(OldGV,
Load);
1191 ConstantInt::get(I32Ty,
Value), Name);
1204 for (
unsigned I = 0, E =
List.size();
I != E; ++
I)
1208 if (UsedArray.
empty())
1215 GV->setSection(
"llvm.metadata");
1221 auto *Int8Ty =
Builder.getInt8Ty();
1224 ConstantInt::get(Int8Ty, Mode),
Twine(KernelName,
"_exec_mode"));
1232 unsigned Reserve2Flags) {
1234 LocFlags |= OMP_IDENT_FLAG_KMPC;
1241 ConstantInt::get(Int32,
uint32_t(LocFlags)),
1242 ConstantInt::get(Int32, Reserve2Flags),
1243 ConstantInt::get(Int32, SrcLocStrSize), SrcLocStr};
1245 size_t SrcLocStrArgIdx = 4;
1246 if (OpenMPIRBuilder::Ident->getElementType(SrcLocStrArgIdx)
1250 SrcLocStr, OpenMPIRBuilder::Ident->getElementType(SrcLocStrArgIdx));
1257 if (
GV.getValueType() == OpenMPIRBuilder::Ident &&
GV.hasInitializer())
1258 if (
GV.getInitializer() == Initializer)
1263 M, OpenMPIRBuilder::Ident,
1266 M.getDataLayout().getDefaultGlobalsAddressSpace());
1278 SrcLocStrSize = LocStr.
size();
1287 if (
GV.isConstant() &&
GV.hasInitializer() &&
1288 GV.getInitializer() == Initializer)
1291 SrcLocStr =
Builder.CreateGlobalString(
1292 LocStr,
"",
M.getDataLayout().getDefaultGlobalsAddressSpace(),
1300 unsigned Line,
unsigned Column,
1306 Buffer.
append(FunctionName);
1308 Buffer.
append(std::to_string(Line));
1310 Buffer.
append(std::to_string(Column));
1318 StringRef UnknownLoc =
";unknown;unknown;0;0;;";
1329 !DIL->getFilename().empty() ? DIL->getFilename() :
M.getName();
1334 DIL->getColumn(), SrcLocStrSize);
1340 Loc.IP.getNodeParent()->getParent());
1346 "omp_global_thread_num");
1354 "expected one result pointer type per in_reduction item");
1357 if (OrigPtrs.
empty())
1358 return Builder.saveIP();
1377 for (
unsigned Idx = 0; Idx < OrigPtrs.
size(); ++Idx) {
1380 Value *OrigPtr = OrigPtrs[Idx];
1382 OrigPtrTy && OrigPtrTy->getAddressSpace() != 0)
1383 OrigPtr = Builder.CreateAddrSpaceCast(OrigPtr, PtrTy);
1385 Value *
Priv = Builder.CreateCall(GetThData, {Gtid, NullDesc, OrigPtr},
1391 ResPtrTy && ResPtrTy->getAddressSpace() != 0)
1392 Priv = Builder.CreateAddrSpaceCast(
Priv, ResultPtrTys[Idx]);
1394 MapPrivateCB(Idx,
Priv);
1401 bool ForceSimpleCall,
bool CheckCancelFlag) {
1411 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_FOR;
1414 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SECTIONS;
1417 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SINGLE;
1420 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_EXPL;
1423 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL;
1436 bool UseCancelBarrier =
1441 ? OMPRTL___kmpc_cancel_barrier
1442 : OMPRTL___kmpc_barrier),
1445 if (UseCancelBarrier && CheckCancelFlag)
1455 omp::Directive CanceledDirective) {
1460 auto *UI =
Builder.CreateUnreachable();
1468 Builder.SetInsertPoint(ElseTI);
1469 auto ElseIP =
Builder.saveIP();
1477 Builder.SetInsertPoint(ThenTI);
1479 Value *CancelKind =
nullptr;
1480 switch (CanceledDirective) {
1481#define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) \
1482 case DirectiveEnum: \
1483 CancelKind = Builder.getInt32(Value); \
1485#include "llvm/Frontend/OpenMP/OMPKinds.def"
1502 Builder.SetInsertPoint(UI->getParent());
1503 UI->eraseFromParent();
1510 omp::Directive CanceledDirective) {
1515 auto *UI =
Builder.CreateUnreachable();
1518 Value *CancelKind =
nullptr;
1519 switch (CanceledDirective) {
1520#define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) \
1521 case DirectiveEnum: \
1522 CancelKind = Builder.getInt32(Value); \
1524#include "llvm/Frontend/OpenMP/OMPKinds.def"
1541 Builder.SetInsertPoint(UI->getParent());
1542 UI->eraseFromParent();
1555 auto *KernelArgsPtr =
1556 Builder.CreateAlloca(OpenMPIRBuilder::KernelArgs,
nullptr,
"kernel_args");
1561 Builder.CreateStructGEP(OpenMPIRBuilder::KernelArgs, KernelArgsPtr,
I);
1564 M.getDataLayout().getPrefTypeAlign(KernelArgs[
I]->getType()));
1568 NumThreads, HostPtr, KernelArgsPtr};
1595 assert(OutlinedFnID &&
"Invalid outlined function ID!");
1599 Value *Return =
nullptr;
1619 Builder, AllocaIP, Return, RTLoc, DeviceID, Args.NumTeams.front(),
1620 Args.NumThreads.front(), OutlinedFnID, ArgsVector));
1627 Builder.CreateCondBr(
Failed, OffloadFailedBlock, OffloadContBlock);
1629 auto CurFn =
Builder.GetInsertBlock()->getParent();
1636 emitBlock(OffloadContBlock, CurFn,
true);
1641 Value *CancelFlag, omp::Directive CanceledDirective) {
1643 "Unexpected cancellation!");
1663 Builder.CreateCondBr(Cmp, NonCancellationBlock, CancellationBlock,
1672 Builder.SetInsertPoint(CancellationBlock);
1673 Builder.CreateBr(*FiniBBOrErr);
1688 size_t NumArgs = OutlinedFn.
arg_size();
1689 assert((NumArgs == 2 || NumArgs == 3) &&
1690 "expected a 2-3 argument parallel outlined function");
1691 bool UseArgStruct = NumArgs == 3;
1696 {Builder.getInt16Ty(), Builder.getInt32Ty()},
1700 OutlinedFn.
getName() +
".wrapper", OMPIRBuilder->
M);
1702 WrapperFn->addParamAttr(0, Attribute::NoUndef);
1703 WrapperFn->addParamAttr(0, Attribute::ZExt);
1704 WrapperFn->addParamAttr(1, Attribute::NoUndef);
1708 Builder.SetInsertPoint(EntryBB);
1711 Value *AddrAlloca = Builder.CreateAlloca(Builder.getInt32Ty(),
1713 AddrAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1714 AddrAlloca, Builder.getPtrTy(0),
1715 AddrAlloca->
getName() +
".ascast");
1717 Value *ZeroAlloca = Builder.CreateAlloca(Builder.getInt32Ty(),
1719 ZeroAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1720 ZeroAlloca, Builder.getPtrTy(0),
1721 ZeroAlloca->
getName() +
".ascast");
1723 Value *ArgsAlloca =
nullptr;
1725 ArgsAlloca = Builder.CreateAlloca(Builder.getPtrTy(),
1726 nullptr,
"global_args");
1727 ArgsAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1728 ArgsAlloca, Builder.getPtrTy(0),
1729 ArgsAlloca->
getName() +
".ascast");
1733 Builder.CreateStore(WrapperFn->getArg(1), AddrAlloca);
1734 Builder.CreateStore(Builder.getInt32(0), ZeroAlloca);
1738 llvm::omp::RuntimeFunction::OMPRTL___kmpc_get_shared_variables),
1746 Value *StructArg = Builder.CreateLoad(Builder.getPtrTy(), ArgsAlloca);
1747 StructArg = Builder.CreateInBoundsGEP(Builder.getPtrTy(), StructArg,
1748 {Builder.getInt64(0)});
1749 StructArg = Builder.CreateLoad(Builder.getPtrTy(), StructArg,
"structArg");
1750 Args.push_back(StructArg);
1754 Builder.CreateCall(&OutlinedFn, Args);
1755 Builder.CreateRetVoid();
1770 "Expected at least tid and bounded tid as arguments");
1771 unsigned NumCapturedVars = OutlinedFn.
arg_size() - 2;
1779 OutlinedFn.
addFnAttr(Attribute::NoUnwind);
1782 assert(CI &&
"Expected call instruction to outlined function");
1783 CI->
getParent()->setName(
"omp_parallel");
1785 Builder.SetInsertPoint(CI);
1786 Type *PtrTy = OMPIRBuilder->VoidPtr;
1789 OpenMPIRBuilder ::InsertPointTy CurrentIP = Builder.saveIP();
1793 Value *Args = ArgsAlloca;
1797 Args = Builder.CreatePointerCast(ArgsAlloca, PtrTy);
1798 Builder.restoreIP(CurrentIP);
1801 for (
unsigned Idx = 0; Idx < NumCapturedVars; Idx++) {
1803 Value *StoreAddress = Builder.CreateConstInBoundsGEP2_64(
1805 Builder.CreateStore(V, StoreAddress);
1809 IfCondition ? Builder.CreateSExtOrTrunc(IfCondition, OMPIRBuilder->Int32)
1810 : Builder.getInt32(1);
1811 Value *NumThreadsArg =
1812 NumThreads ? Builder.CreateZExtOrTrunc(NumThreads, OMPIRBuilder->Int32)
1813 : Builder.getInt32(-1);
1823 Value *Parallel60CallArgs[] = {
1828 Builder.getInt32(-1),
1832 Builder.getInt64(NumCapturedVars),
1833 Builder.getInt32(0)};
1841 << *Builder.GetInsertBlock()->getParent() <<
"\n");
1844 Builder.SetInsertPoint(PrivTID);
1846 Builder.CreateStore(Builder.CreateLoad(OMPIRBuilder->Int32, OutlinedAI),
1853 I->eraseFromParent();
1876 if (!
F->hasMetadata(LLVMContext::MD_callback)) {
1884 F->addMetadata(LLVMContext::MD_callback,
1893 OutlinedFn.
addFnAttr(Attribute::NoUnwind);
1896 "Expected at least tid and bounded tid as arguments");
1897 unsigned NumCapturedVars = OutlinedFn.
arg_size() - 2;
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");
2068 if (IP == IP.getNodeParent()->end()) {
2072 IP =
I->getIterator();
2074 assert(IP.getNodeParent()->getTerminator()->getNumSuccessors() == 1 &&
2075 IP.getNodeParent()->getTerminator()->getSuccessor(0) == PRegExitBB &&
2076 "Unexpected insertion point for finalization call!");
2088 Builder.CreateAlloca(Int32,
nullptr,
"tid.addr.local");
2094 Builder.CreateLoad(Int32, ZeroAddr,
"zero.addr.use");
2112 LLVM_DEBUG(
dbgs() <<
"Before body codegen: " << *OuterFn <<
"\n");
2115 assert(BodyGenCB &&
"Expected body generation callback!");
2117 if (
Error Err = BodyGenCB(InnerAllocaIP, CodeGenIP, PRegExitBB))
2120 LLVM_DEBUG(
dbgs() <<
"After body codegen: " << *OuterFn <<
"\n");
2124 bool UsesDeviceSharedMemory =
2126 std::unique_ptr<OutlineInfo> OI =
2127 UsesDeviceSharedMemory
2128 ? std::make_unique<DeviceSharedMemOutlineInfo>(*
this)
2129 : std::make_unique<OutlineInfo>();
2131 if (
Config.isTargetDevice()) {
2133 OI->PostOutlineCB = [=, ToBeDeletedVec =
2134 std::move(ToBeDeleted)](
Function &OutlinedFn) {
2136 IfCondition, NumThreads, PrivTID, PrivTIDAddr,
2137 ThreadID, ToBeDeletedVec);
2141 OI->PostOutlineCB = [=, ToBeDeletedVec =
2142 std::move(ToBeDeleted)](
Function &OutlinedFn) {
2144 PrivTID, PrivTIDAddr, ToBeDeletedVec);
2148 OI->FixUpNonEntryAllocas =
true;
2149 OI->OuterAllocBB = OuterAllocaBlock;
2150 OI->EntryBB = PRegEntryBB;
2151 OI->ExitBB = PRegExitBB;
2152 OI->OuterDeallocBBs.reserve(OuterDeallocBlocks.
size());
2153 copy(OuterDeallocBlocks, OI->OuterDeallocBBs.
end());
2157 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
2169 ".omp_par", ArgsInZeroAddressSpace);
2174 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
2176 Extractor.findInputsOutputs(Inputs, Outputs, SinkingCands,
2181 return GV->getValueType() == OpenMPIRBuilder::Ident;
2186 LLVM_DEBUG(
dbgs() <<
"Before privatization: " << *OuterFn <<
"\n");
2192 if (&V == TIDAddr || &V == ZeroAddr) {
2193 OI->ExcludeArgsFromAggregate.push_back(&V);
2198 for (
Use &U : V.uses())
2200 if (ParallelRegionBlockSet.
count(UserI->getParent()))
2210 if (!V.getType()->isPointerTy()) {
2214 Builder.restoreIP(OuterAllocIP);
2216 if (UsesDeviceSharedMemory) {
2219 V.getName() +
".reloaded");
2220 for (
BasicBlock *DeallocBlock : OuterDeallocBlocks) {
2221 assert(DeallocBlock->getParent() ==
2222 OuterAllocIP.getNodeParent()->getParent() &&
2223 "Dealloc block must be in the allocation's function to reuse "
2224 "its debug location");
2226 Builder.getCurrentDebugLocation()},
2230 Ptr =
Builder.CreateAlloca(V.getType(),
nullptr,
2231 V.getName() +
".reloaded");
2240 Builder.restoreIP(InnerAllocaIP);
2241 Inner =
Builder.CreateLoad(V.getType(), Ptr);
2244 Value *ReplacementValue =
nullptr;
2247 ReplacementValue = PrivTID;
2250 PrivCB(InnerAllocaIP,
Builder.saveIP(), V, *Inner, ReplacementValue);
2255 InnerAllocaIP.getNodeParent()->getTerminator()->getIterator();
2257 assert(ReplacementValue &&
2258 "Expected copy/create callback to set replacement value!");
2259 if (ReplacementValue == &V)
2264 UPtr->set(ReplacementValue);
2287 for (
Value *Output : Outputs)
2291 "OpenMP outlining should not produce live-out values!");
2293 LLVM_DEBUG(
dbgs() <<
"After privatization: " << *OuterFn <<
"\n");
2295 for (
auto *BB : Blocks)
2296 dbgs() <<
" PBR: " << BB->getName() <<
"\n";
2304 assert(FiniInfo.DK == OMPD_parallel &&
2305 "Unexpected finalization stack state!");
2316 Builder.CreateBr(*FiniBBOrErr);
2320 Term->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 auto OI = std::make_unique<OutlineInfo>();
2622 OI->EntryBB = TaskloopAllocaBB;
2623 OI->OuterAllocBB = AllocaIP.getNodeParent();
2624 OI->ExitBB = TaskloopExitBB;
2625 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2626 copy(DeallocBlocks, OI->OuterDeallocBBs.end());
2629 SmallVector<Instruction *> ToBeDeleted;
2632 Builder, AllocaIP, ToBeDeleted, TaskloopAllocaIP,
"global.tid",
false));
2634 TaskloopAllocaIP,
"lb",
false,
true);
2636 TaskloopAllocaIP,
"ub",
false,
true);
2638 TaskloopAllocaIP,
"step",
false,
true);
2641 OI->Inputs.insert(FakeLB);
2642 OI->Inputs.insert(FakeUB);
2643 OI->Inputs.insert(FakeStep);
2644 if (TaskContextStructPtrVal)
2645 OI->Inputs.insert(TaskContextStructPtrVal);
2646 assert(((TaskContextStructPtrVal && DupCB) ||
2647 (!TaskContextStructPtrVal && !DupCB)) &&
2648 "Task context struct ptr and duplication callback must be both set "
2654 unsigned ProgramAddressSpace =
M.getDataLayout().getProgramAddressSpace();
2658 {FakeLB->getType(), FakeUB->getType(), FakeStep->getType(), PointerTy});
2659 Expected<Value *> TaskDupFnOrErr = createTaskDuplicationFunction(
2662 if (!TaskDupFnOrErr) {
2665 Value *TaskDupFn = *TaskDupFnOrErr;
2667 OI->PostOutlineCB = [
this, Ident, LBVal, UBVal, StepVal, Untied,
2668 TaskloopAllocaBB, CLI, TaskDupFn, ToBeDeleted, IfCond,
2669 GrainSize, NoGroup, Sched, FakeLB, FakeUB, FakeStep,
2670 FakeSharedsTy, Final, Mergeable, Priority,
2672 FreeAgent](
Function &OutlinedFn)
mutable {
2674 assert(OutlinedFn.hasOneUse() &&
2675 "there must be a single user for the outlined function");
2682 Value *CastedLBVal =
2683 Builder.CreateIntCast(LBVal,
Builder.getInt64Ty(),
true,
"lb64");
2684 Value *CastedUBVal =
2685 Builder.CreateIntCast(UBVal,
Builder.getInt64Ty(),
true,
"ub64");
2686 Value *CastedStepVal =
2687 Builder.CreateIntCast(StepVal,
Builder.getInt64Ty(),
true,
"step64");
2689 Builder.SetInsertPoint(StaleCI);
2702 Builder.CreateCall(TaskgroupFn, {Ident, ThreadID});
2727 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
2729 AllocaInst *ArgStructAlloca =
2731 assert(ArgStructAlloca &&
2732 "Unable to find the alloca instruction corresponding to arguments "
2733 "for extracted function");
2734 std::optional<TypeSize> ArgAllocSize =
2737 "Unable to determine size of arguments for extracted function");
2738 Value *SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
2743 CallInst *TaskData =
Builder.CreateCall(
2744 TaskAllocFn, {Ident, ThreadID,
Flags,
2745 TaskSize, SharedsSize,
2750 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
2756 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(0)});
2759 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(1)});
2762 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(2)});
2768 IfCond ?
Builder.CreateIntCast(IfCond,
Builder.getInt32Ty(),
true)
2774 Value *GrainSizeVal =
2775 GrainSize ?
Builder.CreateIntCast(GrainSize,
Builder.getInt64Ty(),
true)
2777 Value *TaskDup = TaskDupFn;
2779 Value *
Args[] = {Ident, ThreadID, TaskData, IfCondVal, Lb, Ub,
2780 Loadstep, NoGroupVal, SchedVal, GrainSizeVal, TaskDup};
2785 Builder.CreateCall(TaskloopFn, Args);
2792 Builder.CreateCall(EndTaskgroupFn, {Ident, ThreadID});
2797 Builder.SetInsertPoint(TaskloopAllocaBB->begin());
2799 LoadInst *SharedsOutlined =
2800 Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
2801 OutlinedFn.getArg(1)->replaceUsesWithIf(
2803 [SharedsOutlined](Use &U) {
return U.getUser() != SharedsOutlined; });
2806 Type *IVTy =
IV->getType();
2812 Value *TaskLB =
nullptr;
2813 Value *TaskUB =
nullptr;
2814 Value *TaskStep =
nullptr;
2815 Value *LoadTaskLB =
nullptr;
2816 Value *LoadTaskUB =
nullptr;
2817 Value *LoadTaskStep =
nullptr;
2818 for (Instruction &
I : *TaskloopAllocaBB) {
2819 if (
I.getOpcode() == Instruction::GetElementPtr) {
2822 switch (CI->getZExtValue()) {
2834 }
else if (
I.getOpcode() == Instruction::Load) {
2836 if (
Load.getPointerOperand() == TaskLB) {
2837 assert(TaskLB !=
nullptr &&
"Expected value for TaskLB");
2839 }
else if (
Load.getPointerOperand() == TaskUB) {
2840 assert(TaskUB !=
nullptr &&
"Expected value for TaskUB");
2842 }
else if (
Load.getPointerOperand() == TaskStep) {
2843 assert(TaskStep !=
nullptr &&
"Expected value for TaskStep");
2849 Builder.SetInsertPoint(CLI->getPreheader()->getTerminator());
2851 assert(LoadTaskLB !=
nullptr &&
"Expected value for LoadTaskLB");
2852 assert(LoadTaskUB !=
nullptr &&
"Expected value for LoadTaskUB");
2853 assert(LoadTaskStep !=
nullptr &&
"Expected value for LoadTaskStep");
2855 Builder.CreateSub(LoadTaskUB, LoadTaskLB), LoadTaskStep);
2856 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One,
"trip_cnt");
2857 Value *CastedTripCount =
Builder.CreateIntCast(TripCount, IVTy,
true);
2858 Value *CastedTaskLB =
Builder.CreateIntCast(LoadTaskLB, IVTy,
true);
2860 CLI->setTripCount(CastedTripCount);
2862 Builder.SetInsertPoint(CLI->getBody()->getFirstInsertionPt());
2864 if (NumOfCollapseLoops > 1) {
2870 Builder.CreateSub(CastedTaskLB, ConstantInt::get(IVTy, 1)));
2873 for (
auto IVUse = CLI->getIndVar()->uses().begin();
2874 IVUse != CLI->getIndVar()->uses().end(); IVUse++) {
2875 User *IVUser = IVUse->getUser();
2877 if (
Op->getOpcode() == Instruction::URem ||
2878 Op->getOpcode() == Instruction::UDiv) {
2883 for (User *User : UsersToReplace) {
2884 User->replaceUsesOfWith(CLI->getIndVar(), IVPlusTaskLB);
2901 assert(CLI->getIndVar()->getNumUses() == 3 &&
2902 "Canonical loop should have exactly three uses of the ind var");
2903 for (User *IVUser : CLI->getIndVar()->users()) {
2905 if (
Mul->getOpcode() == Instruction::Mul) {
2906 for (User *MulUser :
Mul->users()) {
2908 if (
Add->getOpcode() == Instruction::Add) {
2909 Add->setOperand(1, CastedTaskLB);
2918 FakeLB->replaceAllUsesWith(CastedLBVal);
2919 FakeUB->replaceAllUsesWith(CastedUBVal);
2920 FakeStep->replaceAllUsesWith(CastedStepVal);
2922 I->eraseFromParent();
2933 M.getContext(),
M.getDataLayout().getPointerSizeInBits());
2943 bool Mergeable,
Value *EventHandle,
Value *Priority,
bool FreeAgent) {
2974 if (
Error Err = BodyGenCB(TaskAllocaIP, TaskBodyIP, TaskExitBB))
2977 auto OI = std::make_unique<OutlineInfo>();
2978 OI->EntryBB = TaskAllocaBB;
2979 OI->OuterAllocBB = AllocaIP.getNodeParent();
2980 OI->ExitBB = TaskExitBB;
2981 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2982 copy(DeallocBlocks, OI->OuterDeallocBBs.
end());
2987 Builder, AllocaIP, ToBeDeleted, TaskAllocaIP,
"global.tid",
false));
2989 OI->PostOutlineCB = [
this, Ident, Tied, Final, IfCondition, Dependencies,
2990 Affinities, Mergeable, Priority, EventHandle, FreeAgent,
2992 ToBeDeleted](
Function &OutlinedFn)
mutable {
2994 assert(OutlinedFn.hasOneUse() &&
2995 "there must be a single user for the outlined function");
3000 bool HasShareds = StaleCI->
arg_size() > 1;
3001 Builder.SetInsertPoint(StaleCI);
3028 bool UseMergedIf0Path = ConstIfCondition && ConstIfCondition->isZero();
3032 Flags =
Builder.CreateOr(FinalFlag, Flags);
3035 if (Mergeable || UseMergedIf0Path)
3049 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
3058 assert(ArgStructAlloca &&
3059 "Unable to find the alloca instruction corresponding to arguments "
3060 "for extracted function");
3061 std::optional<TypeSize> ArgAllocSize =
3064 "Unable to determine size of arguments for extracted function");
3065 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
3071 TaskAllocFn, {Ident, ThreadID, Flags,
3072 TaskSize, SharedsSize,
3075 if (Affinities.
Count && Affinities.
Info) {
3077 OMPRTL___kmpc_omp_reg_task_with_affinity);
3088 OMPRTL___kmpc_task_allow_completion_event);
3092 Builder.CreatePointerBitCastOrAddrSpaceCast(EventHandle,
3094 EventVal =
Builder.CreatePtrToInt(EventVal,
Builder.getInt64Ty());
3095 Builder.CreateStore(EventVal, EventHandleAddr);
3101 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
3116 Constant *Zero = ConstantInt::get(Int32Ty, 0);
3120 Builder.CreateInBoundsGEP(TaskPtr, TaskData, {Zero, Zero});
3123 VoidPtr, VoidPtr,
Builder.getInt32Ty(), VoidPtr, VoidPtr);
3125 TaskStructType, TaskGEP, {Zero, ConstantInt::get(Int32Ty, 4)});
3128 Value *CmplrData =
Builder.CreateInBoundsGEP(CmplrStructType,
3129 PriorityData, {Zero, Zero});
3130 Builder.CreateStore(Priority, CmplrData);
3133 Value *DepArray =
nullptr;
3134 Value *NumDeps =
nullptr;
3137 NumDeps = Dependencies.
NumDeps;
3138 }
else if (!Dependencies.
Deps.empty()) {
3140 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
3160 if (IfCondition && !UseMergedIf0Path) {
3165 Builder.GetInsertPoint()->getParent()->getTerminator();
3166 Instruction *ThenTI = IfTerminator, *ElseTI =
nullptr;
3167 Builder.SetInsertPoint(IfTerminator);
3170 Builder.SetInsertPoint(ElseTI);
3177 {Ident, ThreadID, NumDeps, DepArray,
3178 ConstantInt::get(
Builder.getInt32Ty(), 0),
3193 Builder.SetInsertPoint(ThenTI);
3201 {Ident, ThreadID, TaskData, NumDeps, DepArray,
3202 ConstantInt::get(
Builder.getInt32Ty(), 0),
3215 LoadInst *Shareds =
Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
3216 OutlinedFn.getArg(1)->replaceUsesWithIf(
3217 Shareds, [Shareds](
Use &U) {
return U.getUser() != Shareds; });
3223 Builder.ClearInsertionPoint();
3225 I->eraseFromParent();
3251 if (
Error Err = BodyGenCB(AllocaIP,
Builder.saveIP(), DeallocBlocks))
3254 Builder.SetInsertPoint(TaskgroupExitBB);
3297 unsigned CaseNumber = 0;
3298 for (
auto SectionCB : SectionCBs) {
3300 M.getContext(),
"omp_section_loop.body.case", CurFn,
Continue);
3302 Builder.SetInsertPoint(CaseBB);
3315 Value *LB = ConstantInt::get(I32Ty, 0);
3316 Value *UB = ConstantInt::get(I32Ty, SectionCBs.
size());
3317 Value *ST = ConstantInt::get(I32Ty, 1);
3319 Loc, LoopBodyGenCB, LB, UB, ST,
true,
false, AllocaIP,
"section_loop");
3324 applyStaticWorkshareLoop(
Loc.DL, *
LoopInfo, AllocaIP,
3325 WorksharingLoopType::ForStaticLoop, !IsNowait);
3331 assert(LoopFini &&
"Bad structure of static workshare loop finalization");
3335 assert(FiniInfo.DK == OMPD_sections &&
3336 "Unexpected finalization stack state!");
3337 if (
Error Err = FiniInfo.mergeFiniBB(
Builder, LoopFini))
3351 if (IP != IP.getNodeParent()->end())
3362 auto *CaseBB =
Loc.IP.getNodeParent();
3363 auto *CondBB = CaseBB->getSinglePredecessor()->getSinglePredecessor();
3364 auto *ExitBB = CondBB->getTerminator()->getSuccessor(1);
3366 IP =
I->getIterator();
3370 Directive OMPD = Directive::OMPD_sections;
3373 return EmitOMPInlinedRegion(OMPD,
nullptr,
nullptr, BodyGenCB, FiniCBWrapper,
3384Value *OpenMPIRBuilder::getGPUThreadID() {
3387 OMPRTL___kmpc_get_hardware_thread_id_in_block),
3391Value *OpenMPIRBuilder::getGPUWarpSize() {
3396Value *OpenMPIRBuilder::getNVPTXWarpID() {
3397 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3398 return Builder.CreateAShr(getGPUThreadID(), LaneIDBits,
"nvptx_warp_id");
3401Value *OpenMPIRBuilder::getNVPTXLaneID() {
3402 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3403 assert(LaneIDBits < 32 &&
"Invalid LaneIDBits size in NVPTX device.");
3404 unsigned LaneIDMask = ~0
u >> (32u - LaneIDBits);
3405 return Builder.CreateAnd(getGPUThreadID(),
Builder.getInt32(LaneIDMask),
3412 uint64_t FromSize =
M.getDataLayout().getTypeStoreSize(FromType);
3413 uint64_t ToSize =
M.getDataLayout().getTypeStoreSize(ToType);
3414 assert(FromSize > 0 &&
"From size must be greater than zero");
3415 assert(ToSize > 0 &&
"To size must be greater than zero");
3416 if (FromType == ToType)
3418 if (FromSize == ToSize)
3419 return Builder.CreateBitCast(From, ToType);
3421 return Builder.CreateIntCast(From, ToType,
true);
3427 Value *ValCastItem =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3428 CastItem,
Builder.getPtrTy(0));
3429 Builder.CreateStore(From, ValCastItem);
3430 return Builder.CreateLoad(ToType, CastItem);
3437 uint64_t Size =
M.getDataLayout().getTypeStoreSize(ElementType);
3438 assert(
Size <= 8 &&
"Unsupported bitwidth in shuffle instruction");
3442 Value *ElemCast = castValueToType(AllocaIP, Element, CastTy);
3444 Builder.CreateIntCast(getGPUWarpSize(),
Builder.getInt16Ty(),
true);
3446 Size <= 4 ? RuntimeFunction::OMPRTL___kmpc_shuffle_int32
3447 : RuntimeFunction::OMPRTL___kmpc_shuffle_int64);
3448 Value *WarpSizeCast =
3450 Value *ShuffleCall =
3455 return castValueToType(AllocaIP, ShuffleCall, ElementType);
3462 uint64_t Size =
M.getDataLayout().getTypeStoreSize(ElemType);
3474 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3475 Value *ElemPtr = DstAddr;
3476 Value *Ptr = SrcAddr;
3477 for (
unsigned IntSize = 8; IntSize >= 1; IntSize /= 2) {
3481 Ptr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3484 Builder.CreateGEP(ElemType, SrcAddr, {ConstantInt::get(IndexTy, 1)});
3485 ElemPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3489 if ((
Size / IntSize) > 1) {
3490 Value *PtrEnd =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3491 SrcAddrGEP,
Builder.getPtrTy());
3508 Builder.CreatePointerBitCastOrAddrSpaceCast(Ptr,
Builder.getPtrTy()));
3510 Builder.CreateICmpSGT(PtrDiff,
Builder.getInt64(IntSize - 1)), ThenBB,
3513 Value *Res = createRuntimeShuffleFunction(
3516 IntType, Ptr,
M.getDataLayout().getPrefTypeAlign(ElemType)),
3518 Builder.CreateAlignedStore(Res, ElemPtr,
3519 M.getDataLayout().getPrefTypeAlign(ElemType));
3521 Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3522 Value *LocalElemPtr =
3523 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3531 Value *Res = createRuntimeShuffleFunction(
3532 AllocaIP,
Builder.CreateLoad(IntType, Ptr), IntType,
Offset);
3533 Builder.CreateStore(Res, ElemPtr);
3534 Ptr =
Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3536 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3542Error OpenMPIRBuilder::emitReductionListCopy(
3547 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3548 Value *RemoteLaneOffset = CopyOptions.RemoteLaneOffset;
3552 for (
auto En :
enumerate(ReductionInfos)) {
3554 Value *SrcElementAddr =
nullptr;
3555 AllocaInst *DestAlloca =
nullptr;
3556 Value *DestElementAddr =
nullptr;
3557 Value *DestElementPtrAddr =
nullptr;
3559 bool ShuffleInElement =
false;
3562 bool UpdateDestListPtr =
false;
3566 ReductionArrayTy, SrcBase,
3567 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3568 SrcElementAddr =
Builder.CreateLoad(
Builder.getPtrTy(), SrcElementPtrAddr);
3572 DestElementPtrAddr =
Builder.CreateInBoundsGEP(
3573 ReductionArrayTy, DestBase,
3574 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3575 bool IsByRefElem = (!IsByRef.
empty() && IsByRef[En.index()]);
3581 Type *DestAllocaType =
3582 IsByRefElem ? RI.ByRefAllocatedType : RI.ElementType;
3583 DestAlloca =
Builder.CreateAlloca(DestAllocaType,
nullptr,
3584 ".omp.reduction.element");
3586 M.getDataLayout().getPrefTypeAlign(DestAllocaType));
3587 DestElementAddr = DestAlloca;
3590 DestElementAddr->
getName() +
".ascast");
3592 ShuffleInElement =
true;
3593 UpdateDestListPtr =
true;
3605 if (ShuffleInElement) {
3606 Type *ShuffleType = RI.ElementType;
3607 Value *ShuffleSrcAddr = SrcElementAddr;
3608 Value *ShuffleDestAddr = DestElementAddr;
3609 AllocaInst *LocalStorage =
nullptr;
3612 assert(RI.ByRefElementType &&
"Expected by-ref element type to be set");
3613 assert(RI.ByRefAllocatedType &&
3614 "Expected by-ref allocated type to be set");
3619 ShuffleType = RI.ByRefElementType;
3621 if (RI.DataPtrPtrGen) {
3624 Builder.saveIP(), ShuffleSrcAddr, ShuffleSrcAddr);
3627 return GenResult.takeError();
3636 LocalStorage =
Builder.CreateAlloca(ShuffleType);
3638 ShuffleDestAddr = LocalStorage;
3643 ShuffleDestAddr = DestElementAddr;
3647 shuffleAndStore(AllocaIP, ShuffleSrcAddr, ShuffleDestAddr, ShuffleType,
3648 RemoteLaneOffset, ReductionArrayTy, IsByRefElem);
3650 if (IsByRefElem && RI.DataPtrPtrGen) {
3652 Value *DestDescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3653 DestAlloca,
Builder.getPtrTy(),
".ascast");
3656 DestDescriptorAddr, LocalStorage, SrcElementAddr,
3657 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
3660 return GenResult.takeError();
3663 switch (RI.EvaluationKind) {
3665 Value *Elem =
Builder.CreateLoad(RI.ElementType, SrcElementAddr);
3667 Builder.CreateStore(Elem, DestElementAddr);
3671 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3672 RI.ElementType, SrcElementAddr, 0, 0,
".realp");
3674 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
3676 RI.ElementType, SrcElementAddr, 0, 1,
".imagp");
3678 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
3680 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3681 RI.ElementType, DestElementAddr, 0, 0,
".realp");
3682 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
3683 RI.ElementType, DestElementAddr, 0, 1,
".imagp");
3684 Builder.CreateStore(SrcReal, DestRealPtr);
3685 Builder.CreateStore(SrcImg, DestImgPtr);
3690 M.getDataLayout().getTypeStoreSize(RI.ElementType));
3692 DestElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3693 SrcElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3705 if (UpdateDestListPtr) {
3706 Value *CastDestAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3707 DestElementAddr,
Builder.getPtrTy(),
3708 DestElementAddr->
getName() +
".ascast");
3709 Builder.CreateStore(CastDestAddr, DestElementPtrAddr);
3716Expected<Function *> OpenMPIRBuilder::emitInterWarpCopyFunction(
3719 IRBuilder<>::InsertPointGuard IPG(
Builder);
3720 LLVMContext &Ctx =
M.getContext();
3722 Builder.getVoidTy(), {Builder.getPtrTy(), Builder.getInt32Ty()},
3726 "_omp_reduction_inter_warp_copy_func", &
M);
3732 Builder.SetInsertPoint(EntryBB);
3750 StringRef TransferMediumName =
3751 "__openmp_nvptx_data_transfer_temporary_storage";
3752 GlobalVariable *TransferMedium =
M.getGlobalVariable(TransferMediumName);
3753 unsigned WarpSize =
Config.getGridValue().GV_Warp_Size;
3755 if (!TransferMedium) {
3756 TransferMedium =
new GlobalVariable(
3764 Value *GPUThreadID = getGPUThreadID();
3766 Value *LaneID = getNVPTXLaneID();
3768 Value *WarpID = getNVPTXWarpID();
3774 AllocaInst *ReduceListAlloca =
Builder.CreateAlloca(
3775 Arg0Type,
nullptr, ReduceListArg->
getName() +
".addr");
3776 AllocaInst *NumWarpsAlloca =
3777 Builder.CreateAlloca(Arg1Type,
nullptr, NumWarpsArg->
getName() +
".addr");
3778 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3779 ReduceListAlloca, Arg0Type, ReduceListAlloca->
getName() +
".ascast");
3780 Value *NumWarpsAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3781 NumWarpsAlloca,
Builder.getPtrTy(0),
3782 NumWarpsAlloca->
getName() +
".ascast");
3783 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
3784 Builder.CreateStore(NumWarpsArg, NumWarpsAddrCast);
3793 for (
auto En :
enumerate(ReductionInfos)) {
3799 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
3800 unsigned RealTySize =
M.getDataLayout().getTypeAllocSize(
3801 IsByRefElem ? RI.ByRefElementType : RI.ElementType);
3802 for (
unsigned TySize = 4; TySize > 0 && RealTySize > 0; TySize /= 2) {
3805 unsigned NumIters = RealTySize / TySize;
3808 Value *Cnt =
nullptr;
3809 Value *CntAddr =
nullptr;
3816 Builder.CreateAlloca(
Builder.getInt32Ty(),
nullptr,
".cnt.addr");
3818 CntAddr =
Builder.CreateAddrSpaceCast(CntAddr,
Builder.getPtrTy(),
3819 CntAddr->
getName() +
".ascast");
3831 Cnt, ConstantInt::get(
Builder.getInt32Ty(), NumIters));
3832 Builder.CreateCondBr(Cmp, BodyBB, ExitBB);
3839 omp::Directive::OMPD_unknown,
3843 return BarrierIP1.takeError();
3849 Value *IsWarpMaster =
Builder.CreateIsNull(LaneID,
"warp_master");
3850 Builder.CreateCondBr(IsWarpMaster, ThenBB, ElseBB);
3854 auto *RedListArrayTy =
3857 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3859 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3860 {ConstantInt::get(IndexTy, 0),
3861 ConstantInt::get(IndexTy, En.index())});
3865 if (IsByRefElem && RI.DataPtrPtrGen) {
3867 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
3870 return GenRes.takeError();
3881 ArrayTy, TransferMedium, {
Builder.getInt64(0), WarpID});
3886 Builder.CreateStore(Elem, MediumPtr,
3898 omp::Directive::OMPD_unknown,
3902 return BarrierIP2.takeError();
3909 Value *NumWarpsVal =
3912 Value *IsActiveThread =
3913 Builder.CreateICmpULT(GPUThreadID, NumWarpsVal,
"is_active_thread");
3914 Builder.CreateCondBr(IsActiveThread, W0ThenBB, W0ElseBB);
3921 ArrayTy, TransferMedium, {
Builder.getInt64(0), GPUThreadID});
3923 Value *TargetElemPtrPtr =
3924 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3925 {ConstantInt::get(IndexTy, 0),
3926 ConstantInt::get(IndexTy, En.index())});
3927 Value *TargetElemPtrVal =
3929 Value *TargetElemPtr = TargetElemPtrVal;
3931 if (IsByRefElem && RI.DataPtrPtrGen) {
3933 RI.DataPtrPtrGen(
Builder.saveIP(), TargetElemPtr, TargetElemPtr);
3936 return GenRes.takeError();
3938 TargetElemPtr =
Builder.CreateLoad(
Builder.getPtrTy(), TargetElemPtr);
3946 Value *SrcMediumValue =
3947 Builder.CreateLoad(CType, SrcMediumPtrVal,
true);
3948 Builder.CreateStore(SrcMediumValue, TargetElemPtr);
3958 Cnt, ConstantInt::get(
Builder.getInt32Ty(), 1));
3959 Builder.CreateStore(Cnt, CntAddr,
false);
3961 auto *CurFn =
Builder.GetInsertBlock()->getParent();
3965 RealTySize %= TySize;
3974Expected<Function *> OpenMPIRBuilder::emitShuffleAndReduceFunction(
3977 LLVMContext &Ctx =
M.getContext();
3978 IRBuilder<>::InsertPointGuard IPG(
Builder);
3979 FunctionType *FuncTy =
3981 {Builder.getPtrTy(), Builder.getInt16Ty(),
3982 Builder.getInt16Ty(), Builder.getInt16Ty()},
3986 "_omp_reduction_shuffle_and_reduce_func", &
M);
3997 Builder.SetInsertPoint(EntryBB);
4009 Type *ReduceListArgType = ReduceListArg->
getType();
4013 ReduceListArgType,
nullptr, ReduceListArg->
getName() +
".addr");
4014 Value *LaneIdAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
4015 LaneIDArg->
getName() +
".addr");
4017 LaneIDArgType,
nullptr, RemoteLaneOffsetArg->
getName() +
".addr");
4018 Value *AlgoVerAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
4019 AlgoVerArg->
getName() +
".addr");
4026 RedListArrayTy,
nullptr,
".omp.reduction.remote_reduce_list");
4028 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4029 ReduceListAlloca, ReduceListArgType,
4030 ReduceListAlloca->
getName() +
".ascast");
4031 Value *LaneIdAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4032 LaneIdAlloca, LaneIDArgPtrType, LaneIdAlloca->
getName() +
".ascast");
4033 Value *RemoteLaneOffsetAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4034 RemoteLaneOffsetAlloca, LaneIDArgPtrType,
4035 RemoteLaneOffsetAlloca->
getName() +
".ascast");
4036 Value *AlgoVerAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4037 AlgoVerAlloca, LaneIDArgPtrType, AlgoVerAlloca->
getName() +
".ascast");
4038 Value *RemoteListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4039 RemoteReductionListAlloca,
Builder.getPtrTy(),
4040 RemoteReductionListAlloca->
getName() +
".ascast");
4042 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
4043 Builder.CreateStore(LaneIDArg, LaneIdAddrCast);
4044 Builder.CreateStore(RemoteLaneOffsetArg, RemoteLaneOffsetAddrCast);
4045 Builder.CreateStore(AlgoVerArg, AlgoVerAddrCast);
4047 Value *ReduceList =
Builder.CreateLoad(ReduceListArgType, ReduceListAddrCast);
4048 Value *LaneId =
Builder.CreateLoad(LaneIDArgType, LaneIdAddrCast);
4049 Value *RemoteLaneOffset =
4050 Builder.CreateLoad(LaneIDArgType, RemoteLaneOffsetAddrCast);
4051 Value *AlgoVer =
Builder.CreateLoad(LaneIDArgType, AlgoVerAddrCast);
4058 Error EmitRedLsCpRes = emitReductionListCopy(
4060 ReduceList, RemoteListAddrCast, IsByRef,
4061 {RemoteLaneOffset,
nullptr,
nullptr});
4064 return EmitRedLsCpRes;
4089 Value *LaneComp =
Builder.CreateICmpULT(LaneId, RemoteLaneOffset);
4094 Value *Algo2AndLaneIdComp =
Builder.CreateAnd(Algo2, LaneIdComp);
4095 Value *RemoteOffsetComp =
4097 Value *CondAlgo2 =
Builder.CreateAnd(Algo2AndLaneIdComp, RemoteOffsetComp);
4098 Value *CA0OrCA1 =
Builder.CreateOr(CondAlgo0, CondAlgo1);
4099 Value *CondReduce =
Builder.CreateOr(CA0OrCA1, CondAlgo2);
4105 Builder.CreateCondBr(CondReduce, ThenBB, ElseBB);
4107 Value *LocalReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4108 ReduceList,
Builder.getPtrTy());
4109 Value *RemoteReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4110 RemoteListAddrCast,
Builder.getPtrTy());
4112 ->addFnAttr(Attribute::NoUnwind);
4123 Value *LaneIdGtOffset =
Builder.CreateICmpUGE(LaneId, RemoteLaneOffset);
4124 Value *CondCopy =
Builder.CreateAnd(Algo1, LaneIdGtOffset);
4129 Builder.CreateCondBr(CondCopy, CpyThenBB, CpyElseBB);
4133 EmitRedLsCpRes = emitReductionListCopy(
4135 RemoteListAddrCast, ReduceList, IsByRef);
4138 return EmitRedLsCpRes;
4153OpenMPIRBuilder::generateReductionDescriptor(
4155 Type *DescriptorType,
4161 Value *DescriptorSize =
4162 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(DescriptorType));
4164 DescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4165 SrcDescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4169 Value *DataPtrField;
4171 DataPtrPtrGen(
Builder.saveIP(), DescriptorAddr, DataPtrField);
4174 return GenResult.takeError();
4177 DataPtr,
Builder.getPtrTy(),
".ascast"),
4183Expected<Value *> OpenMPIRBuilder::createReductionDescriptorCopy(
4185 Value *SrcDescriptorAddr,
Type *DescriptorPtrTy,
const Twine &Name) {
4189 AllocaInst *DescriptorAlloca =
4190 Builder.CreateAlloca(RI.ByRefAllocatedType,
nullptr, Name);
4192 M.getDataLayout().getPrefTypeAlign(RI.ByRefAllocatedType));
4193 Value *DescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4194 DescriptorAlloca, DescriptorPtrTy,
4195 DescriptorAlloca->
getName() +
".ascast");
4200 generateReductionDescriptor(DescriptorAddr, DataPtr, SrcDescriptorAddr,
4201 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
4203 return GenResult.takeError();
4205 return DescriptorAddr;
4208Expected<Function *> OpenMPIRBuilder::emitListToGlobalCopyFunction(
4211 IRBuilder<>::InsertPointGuard IPG(
Builder);
4212 LLVMContext &Ctx =
M.getContext();
4215 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4219 "_omp_reduction_list_to_global_copy_func", &
M);
4226 Builder.SetInsertPoint(EntryBlock);
4237 BufferArg->
getName() +
".addr");
4241 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4242 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4243 BufferArgAlloca,
Builder.getPtrTy(),
4244 BufferArgAlloca->
getName() +
".ascast");
4245 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4246 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4247 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4248 ReduceListArgAlloca,
Builder.getPtrTy(),
4249 ReduceListArgAlloca->
getName() +
".ascast");
4251 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4252 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4253 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4255 Value *LocalReduceList =
4257 Value *BufferArgVal =
4261 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4262 for (
auto En :
enumerate(ReductionInfos)) {
4264 auto *RedListArrayTy =
4268 RedListArrayTy, LocalReduceList,
4269 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4275 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferArgVal, Idxs);
4277 ReductionsBufferTy, BufferVD, 0, En.index());
4279 switch (RI.EvaluationKind) {
4281 Value *TargetElement;
4283 if (IsByRef.
empty() || !IsByRef[En.index()]) {
4284 TargetElement =
Builder.CreateLoad(RI.ElementType, ElemPtr);
4286 if (RI.DataPtrPtrGen) {
4288 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
4291 return GenResult.takeError();
4295 TargetElement =
Builder.CreateLoad(RI.ByRefElementType, ElemPtr);
4298 Builder.CreateStore(TargetElement, GlobVal);
4302 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4303 RI.ElementType, ElemPtr, 0, 0,
".realp");
4305 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
4307 RI.ElementType, ElemPtr, 0, 1,
".imagp");
4309 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
4311 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4312 RI.ElementType, GlobVal, 0, 0,
".realp");
4313 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4314 RI.ElementType, GlobVal, 0, 1,
".imagp");
4315 Builder.CreateStore(SrcReal, DestRealPtr);
4316 Builder.CreateStore(SrcImg, DestImgPtr);
4321 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(RI.ElementType));
4323 GlobVal,
M.getDataLayout().getPrefTypeAlign(RI.ElementType), ElemPtr,
4324 M.getDataLayout().getPrefTypeAlign(RI.ElementType), SizeVal,
false);
4334Expected<Function *> OpenMPIRBuilder::emitListToGlobalReduceFunction(
4337 IRBuilder<>::InsertPointGuard IPG(
Builder);
4338 LLVMContext &Ctx =
M.getContext();
4341 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4345 "_omp_reduction_list_to_global_reduce_func", &
M);
4352 Builder.SetInsertPoint(EntryBlock);
4363 BufferArg->
getName() +
".addr");
4367 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4368 auto *RedListArrayTy =
4373 Value *LocalReduceList =
4374 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4378 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4379 BufferArgAlloca,
Builder.getPtrTy(),
4380 BufferArgAlloca->
getName() +
".ascast");
4381 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4382 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4383 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4384 ReduceListArgAlloca,
Builder.getPtrTy(),
4385 ReduceListArgAlloca->
getName() +
".ascast");
4386 Value *LocalReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4387 LocalReduceList,
Builder.getPtrTy(),
4388 LocalReduceList->
getName() +
".ascast");
4390 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4391 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4392 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4397 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4398 for (
auto En :
enumerate(ReductionInfos)) {
4401 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4402 RedListArrayTy, LocalReduceListAddrCast,
4403 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4405 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4407 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4408 ReductionsBufferTy, BufferVD, 0, En.index());
4410 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4414 Value *SrcElementPtrPtr =
4415 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
4416 {ConstantInt::get(IndexTy, 0),
4417 ConstantInt::get(IndexTy, En.index())});
4418 Value *SrcDescriptorAddr =
4422 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4423 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4427 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4429 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4437 ->addFnAttr(Attribute::NoUnwind);
4442Expected<Function *> OpenMPIRBuilder::emitGlobalToListCopyFunction(
4445 IRBuilder<>::InsertPointGuard IPG(
Builder);
4446 LLVMContext &Ctx =
M.getContext();
4449 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4453 "_omp_reduction_global_to_list_copy_func", &
M);
4460 Builder.SetInsertPoint(EntryBlock);
4471 BufferArg->
getName() +
".addr");
4475 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4476 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4477 BufferArgAlloca,
Builder.getPtrTy(),
4478 BufferArgAlloca->
getName() +
".ascast");
4479 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4480 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4481 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4482 ReduceListArgAlloca,
Builder.getPtrTy(),
4483 ReduceListArgAlloca->
getName() +
".ascast");
4484 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4485 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4486 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4488 Value *LocalReduceList =
4493 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4494 for (
auto En :
enumerate(ReductionInfos)) {
4495 const OpenMPIRBuilder::ReductionInfo &RI = En.value();
4496 auto *RedListArrayTy =
4500 RedListArrayTy, LocalReduceList,
4501 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4506 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4507 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4508 ReductionsBufferTy, BufferVD, 0, En.index());
4514 if (!IsByRef.
empty() && IsByRef[En.index()]) {
4521 return GenResult.takeError();
4527 Value *TargetElement =
Builder.CreateLoad(ElemType, GlobValPtr);
4528 Builder.CreateStore(TargetElement, ElemPtr);
4532 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4541 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4543 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4545 Builder.CreateStore(SrcReal, DestRealPtr);
4546 Builder.CreateStore(SrcImg, DestImgPtr);
4553 ElemPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4554 GlobValPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4565Expected<Function *> OpenMPIRBuilder::emitGlobalToListReduceFunction(
4568 IRBuilder<>::InsertPointGuard IPG(
Builder);
4569 LLVMContext &Ctx =
M.getContext();
4572 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4576 "_omp_reduction_global_to_list_reduce_func", &
M);
4583 Builder.SetInsertPoint(EntryBlock);
4594 BufferArg->
getName() +
".addr");
4598 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4604 Value *LocalReduceList =
4605 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4609 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4610 BufferArgAlloca,
Builder.getPtrTy(),
4611 BufferArgAlloca->
getName() +
".ascast");
4612 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4613 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4614 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4615 ReduceListArgAlloca,
Builder.getPtrTy(),
4616 ReduceListArgAlloca->
getName() +
".ascast");
4617 Value *ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4618 LocalReduceList,
Builder.getPtrTy(),
4619 LocalReduceList->
getName() +
".ascast");
4621 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4622 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4623 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4628 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4629 for (
auto En :
enumerate(ReductionInfos)) {
4632 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4633 RedListArrayTy, ReductionList,
4634 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4637 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4638 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4639 ReductionsBufferTy, BufferVD, 0, En.index());
4641 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4643 Value *ReduceListVal =
4645 Value *SrcElementPtrPtr =
4646 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceListVal,
4647 {ConstantInt::get(IndexTy, 0),
4648 ConstantInt::get(IndexTy, En.index())});
4649 Value *SrcDescriptorAddr =
4653 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4654 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4658 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4660 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4668 ->addFnAttr(Attribute::NoUnwind);
4673std::string OpenMPIRBuilder::getReductionFuncName(StringRef Name)
const {
4674 std::string Suffix =
4676 return (Name + Suffix).str();
4679Expected<Function *> OpenMPIRBuilder::createReductionFunction(
4682 AttributeList FuncAttrs) {
4683 IRBuilder<>::InsertPointGuard IPG(
Builder);
4685 {Builder.getPtrTy(), Builder.getPtrTy()},
4687 std::string
Name = getReductionFuncName(ReducerName);
4696 Builder.SetInsertPoint(EntryBB);
4701 Value *LHSArrayPtr =
nullptr;
4702 Value *RHSArrayPtr =
nullptr;
4709 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
4711 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
4712 Value *LHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4713 LHSAlloca, Arg0Type, LHSAlloca->
getName() +
".ascast");
4714 Value *RHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4715 RHSAlloca, Arg1Type, RHSAlloca->
getName() +
".ascast");
4716 Builder.CreateStore(Arg0, LHSAddrCast);
4717 Builder.CreateStore(Arg1, RHSAddrCast);
4718 LHSArrayPtr =
Builder.CreateLoad(Arg0Type, LHSAddrCast);
4719 RHSArrayPtr =
Builder.CreateLoad(Arg1Type, RHSAddrCast);
4723 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4725 for (
auto En :
enumerate(ReductionInfos)) {
4728 RedArrayTy, RHSArrayPtr,
4729 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4731 Value *RHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4732 RHSI8Ptr, RI.PrivateVariable->getType(),
4733 RHSI8Ptr->
getName() +
".ascast");
4736 RedArrayTy, LHSArrayPtr,
4737 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4739 Value *LHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4740 LHSI8Ptr, RI.Variable->getType(), LHSI8Ptr->
getName() +
".ascast");
4749 if (!IsByRef.
empty() && !IsByRef[En.index()]) {
4750 LHS =
Builder.CreateLoad(RI.ElementType, LHSPtr);
4751 RHS =
Builder.CreateLoad(RI.ElementType, RHSPtr);
4758 return AfterIP.takeError();
4759 if (!
Builder.GetInsertBlock())
4760 return ReductionFunc;
4764 if (!IsByRef.
empty() && !IsByRef[En.index()])
4765 Builder.CreateStore(Reduced, LHSPtr);
4770 for (
auto En :
enumerate(ReductionInfos)) {
4771 unsigned Index = En.index();
4773 Value *LHSFixupPtr, *RHSFixupPtr;
4774 Builder.restoreIP(RI.ReductionGenClang(
4775 Builder.saveIP(), Index, &LHSFixupPtr, &RHSFixupPtr, ReductionFunc));
4780 LHSPtrs[Index], [ReductionFunc](
const Use &U) {
4785 RHSPtrs[Index], [ReductionFunc](
const Use &U) {
4799 return ReductionFunc;
4807 assert(RI.Variable &&
"expected non-null variable");
4808 assert(RI.PrivateVariable &&
"expected non-null private variable");
4809 assert((RI.ReductionGen || RI.ReductionGenClang) &&
4810 "expected non-null reduction generator callback");
4813 RI.Variable->getType() == RI.PrivateVariable->getType() &&
4814 "expected variables and their private equivalents to have the same "
4817 assert(RI.Variable->getType()->isPointerTy() &&
4818 "expected variables to be pointers");
4835 ArrayRef<bool> IsByRef,
bool IsNoWait,
bool IsTeamsReduction,
bool IsSPMD,
4837 Value *SrcLocInfo) {
4852 if (ReductionInfos.
size() == 0)
4866 AttrBuilder AttrBldr(Ctx);
4868 AttrBldr.addAttribute(Attr);
4869 AttrBldr.removeAttribute(Attribute::OptimizeNone);
4870 FuncAttrs = FuncAttrs.addFnAttributes(Ctx, AttrBldr);
4873 Builder.GetInsertBlock()->getParent()->getName(), ReductionInfos, IsByRef,
4875 if (!ReductionResult)
4877 Function *ReductionFunc = *ReductionResult;
4880 if (GridValue.has_value())
4881 Config.setGridValue(GridValue.value());
4896 Builder.getPtrTy(
M.getDataLayout().getProgramAddressSpace());
4898 Value *ReductionList;
4902 Value *ReductionListAlloca =
4903 Builder.CreateAlloca(RedArrayTy,
nullptr,
".omp.reduction.red_list");
4904 ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4905 ReductionListAlloca, PtrTy, ReductionListAlloca->
getName() +
".ascast");
4908 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4909 for (
auto En :
enumerate(ReductionInfos)) {
4912 RedArrayTy, ReductionList,
4913 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4916 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
4921 Builder.CreatePointerBitCastOrAddrSpaceCast(PrivateVar, PtrTy);
4922 Builder.CreateStore(CastElem, ElemPtr);
4925 ReductionInfos, ReductionFunc, FuncAttrs, IsByRef);
4931 emitInterWarpCopyFunction(
Loc, ReductionInfos, FuncAttrs, IsByRef);
4936 Value *RL =
Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList, PtrTy);
4945 unsigned MaxDataSize = 0;
4947 for (
auto En :
enumerate(ReductionInfos)) {
4951 Type *RedTypeArg = (!IsByRef.
empty() && IsByRef[En.index()])
4952 ? En.value().ByRefElementType
4953 : En.value().ElementType;
4954 auto Size =
M.getDataLayout().getTypeStoreSize(RedTypeArg);
4955 if (
Size > MaxDataSize)
4959 Value *ReductionDataSize =
4960 Builder.getInt64(MaxDataSize * ReductionInfos.
size());
4964 Function *CopyScratchToListFunc =
nullptr;
4966 Value *ScratchForCopyBack =
nullptr;
4969 Value *RLForCopyBack = RL;
4971 bool IsAtomicReduction =
4974 if (!IsTeamsReduction) {
4975 Value *SarFuncCast =
4976 Builder.CreatePointerBitCastOrAddrSpaceCast(*SarFunc, FuncPtrTy);
4978 Builder.CreatePointerBitCastOrAddrSpaceCast(WcFunc, FuncPtrTy);
4979 Value *Args[] = {SrcLocInfo, ReductionDataSize, RL, SarFuncCast,
4982 RuntimeFunction::OMPRTL___kmpc_nvptx_parallel_reduce_nowait_v2);
4984 }
else if (IsAtomicReduction) {
4988 RuntimeFunction::OMPRTL___kmpc_is_team_main_thread);
4992 Ctx, ReductionTypeArgs,
"struct._globalized_locals_ty");
4995 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
5000 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
5005 ReductionInfos, ReductionFunc, ReductionsBufferTy, FuncAttrs, IsByRef);
5026 Value *RuntimeRL = RL;
5029 Value *PerThreadScratch;
5035 Value *PerThreadScratchAlloca =
5036 Builder.CreateAlloca(ReductionsBufferTy,
nullptr,
5037 ".omp.reduction.scratch");
5038 PerThreadScratch =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5039 PerThreadScratchAlloca, PtrTy,
5040 PerThreadScratchAlloca->
getName() +
".ascast");
5043 Value *PerThreadRedListAlloca =
5044 Builder.CreateAlloca(RedArrayTy,
nullptr,
5045 ".omp.reduction.per_thread_red_list");
5046 RuntimeRL =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5047 PerThreadRedListAlloca, PtrTy,
5048 PerThreadRedListAlloca->
getName() +
".ascast");
5053 for (
auto En :
enumerate(ReductionInfos)) {
5055 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
5058 ReductionsBufferTy, PerThreadScratch, 0, En.index());
5059 Value *Slot =
Builder.CreateConstInBoundsGEP2_32(RedArrayTy, RuntimeRL,
5062 Value *RuntimeListEntry = FieldPtr;
5064 Value *SrcDescriptor =
5067 AllocaIP, RI, FieldPtr, SrcDescriptor, PtrTy);
5070 RuntimeListEntry = *Descriptor;
5072 Builder.CreateStore(RuntimeListEntry, Slot);
5078 Type *CopyArg0Ty = (*LtGCFunc)->getFunctionType()->getParamType(0);
5079 Type *CopyArg2Ty = (*LtGCFunc)->getFunctionType()->getParamType(2);
5080 ScratchForCopyBack =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5081 PerThreadScratch, CopyArg0Ty);
5083 Builder.CreatePointerBitCastOrAddrSpaceCast(RL, CopyArg2Ty);
5091 *LtGCFunc, {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
5092 CopyScratchToListFunc = *GtLCFunc;
5095 Value *Args3[] = {SrcLocInfo, RuntimeRL, *SarFunc, WcFunc,
5096 *LtGCFunc, *GtLCFunc, *GtLRFunc};
5099 RuntimeFunction::OMPRTL___kmpc_gpu_xteam_reduce_nowait);
5119 if (ScratchForCopyBack) {
5122 CopyScratchToListFunc,
5123 {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
5127 for (
auto En :
enumerate(ReductionInfos)) {
5133 if (IsAtomicReduction) {
5149 Value *LHSPtr, *RHSPtr;
5151 &LHSPtr, &RHSPtr, CurFunc));
5157 RedValue =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5159 if (RHSPtr->
getType() != RHS->getType())
5161 Builder.CreatePointerBitCastOrAddrSpaceCast(RHS, RHSPtr->
getType());
5172 if (IsByRef.
empty() || !IsByRef[En.index()]) {
5174 "red.value." +
Twine(En.index()));
5185 if (!IsByRef.
empty() && !IsByRef[En.index()])
5190 if (ContinuationBlock) {
5191 Builder.CreateBr(ContinuationBlock);
5192 Builder.SetInsertPoint(ContinuationBlock);
5194 Config.setEmitLLVMUsed();
5205 ".omp.reduction.func", &M);
5216 Builder.SetInsertPoint(ReductionFuncBlock);
5218 Value *LHSArrayPtr =
nullptr;
5219 Value *RHSArrayPtr =
nullptr;
5230 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
5232 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
5233 Value *LHSAddrCast =
5234 Builder.CreatePointerBitCastOrAddrSpaceCast(LHSAlloca, Arg0Type);
5235 Value *RHSAddrCast =
5236 Builder.CreatePointerBitCastOrAddrSpaceCast(RHSAlloca, Arg1Type);
5237 Builder.CreateStore(Arg0, LHSAddrCast);
5238 Builder.CreateStore(Arg1, RHSAddrCast);
5239 LHSArrayPtr = Builder.CreateLoad(Arg0Type, LHSAddrCast);
5240 RHSArrayPtr = Builder.CreateLoad(Arg1Type, RHSAddrCast);
5242 LHSArrayPtr = ReductionFunc->
getArg(0);
5243 RHSArrayPtr = ReductionFunc->
getArg(1);
5246 unsigned NumReductions = ReductionInfos.
size();
5249 for (
auto En :
enumerate(ReductionInfos)) {
5251 Value *LHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5252 RedArrayTy, LHSArrayPtr, 0, En.index());
5253 Value *LHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), LHSI8PtrPtr);
5254 Value *LHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5257 Value *RHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5258 RedArrayTy, RHSArrayPtr, 0, En.index());
5259 Value *RHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), RHSI8PtrPtr);
5260 Value *RHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5269 Builder.restoreIP(*AfterIP);
5271 if (!Builder.GetInsertBlock())
5275 if (!IsByRef[En.index()])
5276 Builder.CreateStore(Reduced, LHSPtr);
5278 Builder.CreateRetVoid();
5285 bool IsNoWait,
bool IsTeamsReduction) {
5289 IsByRef, IsNoWait, IsTeamsReduction);
5296 if (ReductionInfos.
size() == 0)
5306 unsigned NumReductions = ReductionInfos.
size();
5308 Builder.SetInsertPoint(AllocaIP.getNodeParent()->getTerminator());
5309 Value *RedArray =
Builder.CreateAlloca(RedArrayTy,
nullptr,
"red.array");
5316 for (
auto En :
enumerate(ReductionInfos)) {
5317 unsigned Index = En.index();
5319 Value *RedArrayElemPtr =
Builder.CreateConstInBoundsGEP2_64(
5320 RedArrayTy, RedArray, 0, Index,
"red.array.elem." +
Twine(Index));
5327 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
5337 ? IdentFlag::OMP_IDENT_FLAG_ATOMIC_REDUCE
5342 unsigned RedArrayByteSize =
DL.getTypeStoreSize(RedArrayTy);
5343 Constant *RedArraySize = ConstantInt::get(IndexTy, RedArrayByteSize);
5345 Value *Lock = getOMPCriticalRegionLock(
".reduction");
5347 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_reduce_nowait
5348 : RuntimeFunction::OMPRTL___kmpc_reduce);
5351 {Ident, ThreadId, NumVariables, RedArraySize,
5352 RedArray, ReductionFunc, Lock},
5363 Builder.CreateSwitch(ReduceCall, ContinuationBlock, 2);
5364 Switch->addCase(
Builder.getInt32(1), NonAtomicRedBlock);
5365 Switch->addCase(
Builder.getInt32(2), AtomicRedBlock);
5370 Builder.SetInsertPoint(NonAtomicRedBlock);
5371 for (
auto En :
enumerate(ReductionInfos)) {
5377 if (!IsByRef[En.index()]) {
5379 "red.value." +
Twine(En.index()));
5381 Value *PrivateRedValue =
5383 "red.private.value." +
Twine(En.index()));
5391 if (!
Builder.GetInsertBlock())
5394 if (!IsByRef[En.index()])
5398 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_end_reduce_nowait
5399 : RuntimeFunction::OMPRTL___kmpc_end_reduce);
5401 Builder.CreateBr(ContinuationBlock);
5406 Builder.SetInsertPoint(AtomicRedBlock);
5407 if (CanGenerateAtomic &&
llvm::none_of(IsByRef, [](
bool P) {
return P; })) {
5414 if (!
Builder.GetInsertBlock())
5417 Builder.CreateBr(ContinuationBlock);
5430 if (!
Builder.GetInsertBlock())
5433 Builder.SetInsertPoint(ContinuationBlock);
5444 Directive OMPD = Directive::OMPD_master;
5449 Value *Args[] = {Ident, ThreadId};
5457 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5469 Directive OMPD = Directive::OMPD_masked;
5475 Value *ArgsEnd[] = {Ident, ThreadId};
5483 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5493 Call->setDoesNotThrow();
5508 bool IsInclusive,
ScanInfo *ScanRedInfo) {
5510 llvm::Error Err = emitScanBasedDirectiveDeclsIR(AllocaIP, ScanVars,
5511 ScanVarsType, ScanRedInfo);
5522 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5525 Type *DestTy = ScanVarsType[i];
5526 Value *Val =
Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5529 Builder.CreateStore(Src, Val);
5534 Builder.GetInsertBlock()->getParent());
5537 IV = ScanRedInfo->
IV;
5540 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5543 Type *DestTy = ScanVarsType[i];
5545 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5547 Builder.CreateStore(Src, ScanVars[i]);
5561 Builder.GetInsertBlock()->getParent());
5566Error OpenMPIRBuilder::emitScanBasedDirectiveDeclsIR(
5570 Builder.restoreIP(AllocaIP);
5572 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5574 Builder.CreateAlloca(Builder.getPtrTy(),
nullptr,
"vla");
5581 Builder.restoreIP(CodeGenIP);
5583 Builder.CreateAdd(ScanRedInfo->
Span, Builder.getInt32(1));
5584 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5586 Value *Allocsize = Builder.CreateTypeSize(
5587 IntPtrTy, M.getDataLayout().getTypeAllocSize(ScanVarsType[i]));
5589 Builder.CreateMalloc(
IntPtrTy, Allocsize, AllocSpan,
nullptr,
"arr");
5590 Builder.CreateStore(Buff, (*(ScanRedInfo->
ScanBuffPtrs))[ScanVars[i]]);
5617Error OpenMPIRBuilder::emitScanBasedDirectiveFinalsIR(
5623 Value *PrivateVar = RedInfo.PrivateVariable;
5624 Value *OrigVar = RedInfo.Variable;
5628 Type *SrcTy = RedInfo.ElementType;
5633 Builder.CreateStore(Src, OrigVar);
5694 llvm::ConstantInt::get(ScanRedInfo->
Span->
getType(), 1));
5695 Builder.SetInsertPoint(InputBB);
5698 Builder.SetInsertPoint(LoopBB);
5714 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5716 Builder.SetInsertPoint(InnerLoopBB);
5720 Value *ReductionVal = RedInfo.PrivateVariable;
5723 Type *DestTy = RedInfo.ElementType;
5726 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5729 Builder.CreateInBoundsGEP(DestTy, Buff, OffsetIval,
"arrayOffset");
5734 RedInfo.ReductionGen(
Builder.saveIP(), LHS, RHS, Result);
5737 Builder.CreateStore(Result, LHSPtr);
5740 IVal, llvm::ConstantInt::get(
Builder.getInt32Ty(), 1));
5742 CmpI =
Builder.CreateICmpUGE(NextIVal, Pow2K);
5743 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5746 Counter, llvm::ConstantInt::get(Counter->
getType(), 1));
5752 Builder.CreateCondBr(Cmp, LoopBB, ExitBB);
5773 Error Err = emitScanBasedDirectiveFinalsIR(ReductionInfos, ScanRedInfo);
5780Error OpenMPIRBuilder::emitScanBasedDirectiveIR(
5792 Error Err = InputLoopGen();
5803 Error Err = ScanLoopGen(Builder);
5810void OpenMPIRBuilder::createScanBBs(ScanInfo *ScanRedInfo) {
5847 Builder.SetInsertPoint(Preheader);
5850 Builder.SetInsertPoint(Header);
5851 PHINode *IndVarPHI =
Builder.CreatePHI(IndVarTy, 2,
"omp_" + Name +
".iv");
5852 IndVarPHI->
addIncoming(ConstantInt::get(IndVarTy, 0), Preheader);
5857 Builder.CreateICmpULT(IndVarPHI, TripCount,
"omp_" + Name +
".cmp");
5858 Builder.CreateCondBr(Cmp, Body, Exit);
5863 Builder.SetInsertPoint(Latch);
5873 bool HasNSW =
Config.hasNoSignedWrap();
5876 unsigned BitWidth = CI->getType()->getIntegerBitWidth();
5878 if (CI->getValue().ugt(SignedMax))
5880 }
else if (IsCollapsed) {
5885 Builder.CreateAdd(IndVarPHI, ConstantInt::get(IndVarTy, 1),
5886 "omp_" + Name +
".next",
true, HasNSW);
5897 CL->Header = Header;
5916 NextBB, NextBB, Name);
5948 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
5957 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
5958 ScanRedInfo->
Span = TripCount;
5964 ScanRedInfo->
IV =
IV;
5965 createScanBBs(ScanRedInfo);
5968 assert(Terminator->getNumSuccessors() == 1);
5969 BasicBlock *ContinueBlock = Terminator->getSuccessor(0);
5972 Builder.GetInsertBlock()->getParent());
5975 Builder.GetInsertBlock()->getParent());
5976 Builder.CreateBr(ContinueBlock);
5982 const auto &&InputLoopGen = [&]() ->
Error {
5985 InclusiveStop, ComputeIP, Name,
true, ScanRedInfo);
5989 Builder.restoreIP((*LoopInfo)->getAfterIP());
5995 InclusiveStop, ComputeIP, Name,
true, ScanRedInfo);
5999 Builder.restoreIP((*LoopInfo)->getAfterIP());
6003 Error Err = emitScanBasedDirectiveIR(InputLoopGen, ScanLoopGen, ScanRedInfo);
6011 bool IsSigned,
bool InclusiveStop,
const Twine &Name) {
6021 assert(IndVarTy == Stop->
getType() &&
"Stop type mismatch");
6022 assert(IndVarTy == Step->
getType() &&
"Step type mismatch");
6026 ConstantInt *Zero = ConstantInt::get(IndVarTy, 0);
6042 Incr =
Builder.CreateSelect(IsNeg,
Builder.CreateNeg(Step), Step);
6045 Span =
Builder.CreateSub(UB, LB,
"",
false,
true);
6049 Span =
Builder.CreateSub(Stop, Start,
"",
true);
6054 Value *CountIfLooping;
6055 if (InclusiveStop) {
6056 CountIfLooping =
Builder.CreateAdd(
Builder.CreateUDiv(Span, Incr), One);
6062 CountIfLooping =
Builder.CreateSelect(OneCmp, One, CountIfTwo);
6065 return Builder.CreateSelect(ZeroCmp, Zero, CountIfLooping,
6066 "omp_" + Name +
".tripcount");
6071 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
6078 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
6083 Config.hasNoSignedWrap());
6084 Value *IndVar =
Builder.CreateAdd(Span, Start,
"",
false,
6085 Config.hasNoSignedWrap());
6087 ScanRedInfo->
IV = IndVar;
6088 return BodyGenCB(
Builder.saveIP(), IndVar);
6094 Builder.getCurrentDebugLocation());
6105 unsigned Bitwidth = Ty->getIntegerBitWidth();
6108 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_4u);
6111 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_8u);
6121 unsigned Bitwidth = Ty->getIntegerBitWidth();
6124 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_4u);
6127 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_8u);
6135 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6137 "Require dedicated allocate IP");
6143 uint32_t SrcLocStrSize;
6147 case WorksharingLoopType::ForStaticLoop:
6148 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6150 case WorksharingLoopType::DistributeStaticLoop:
6151 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6153 case WorksharingLoopType::DistributeForStaticLoop:
6154 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
6161 Type *IVTy =
IV->getType();
6162 FunctionCallee StaticInit =
6163 LoopType == WorksharingLoopType::DistributeForStaticLoop
6166 FunctionCallee StaticFini =
6171 AllocaIP.getNodeParent()->getFirstNonPHIOrDbgOrAlloca());
6174 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6175 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
6176 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
6177 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
6186 Constant *One = ConstantInt::get(IVTy, 1);
6187 Builder.CreateStore(Zero, PLowerBound);
6189 Builder.CreateStore(UpperBound, PUpperBound);
6190 Builder.CreateStore(One, PStride);
6196 (LoopType == WorksharingLoopType::DistributeStaticLoop)
6197 ? OMPScheduleType::OrderedDistribute
6200 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6204 auto BuildInitCall = [LoopType, SrcLoc, ThreadNum, PLastIter, PLowerBound,
6205 PUpperBound, IVTy, PStride, One,
Zero, StaticInit,
6208 PLowerBound, PUpperBound});
6209 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
6210 Value *PDistUpperBound =
6211 Builder.CreateAlloca(IVTy,
nullptr,
"p.distupperbound");
6212 Args.push_back(PDistUpperBound);
6217 BuildInitCall(SchedulingType,
Builder);
6218 if (HasDistSchedule &&
6219 LoopType != WorksharingLoopType::DistributeStaticLoop) {
6220 Constant *DistScheduleSchedType = ConstantInt::get(
6225 BuildInitCall(DistScheduleSchedType,
Builder);
6228 Value *InclusiveUpperBound =
Builder.CreateLoad(IVTy, PUpperBound);
6230 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One);
6231 CLI->setTripCount(TripCount);
6237 CLI->mapIndVar([&](Instruction *OldIV) ->
Value * {
6241 Config.hasNoSignedWrap());
6252 omp::Directive::OMPD_for,
false,
6255 return BarrierIP.takeError();
6282 Reachable.insert(
Block);
6296OpenMPIRBuilder::applyStaticChunkedWorkshareLoop(
6300 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6301 assert((ChunkSize || DistScheduleChunkSize) &&
"Chunk size is required");
6306 Type *IVTy =
IV->getType();
6308 "Max supported tripcount bitwidth is 64 bits");
6310 :
Type::getInt64Ty(Ctx);
6313 Constant *One = ConstantInt::get(InternalIVTy, 1);
6318 SmallVector<Instruction *> UIs;
6319 for (BasicBlock &BB : *
F)
6320 if (!BB.hasTerminator())
6321 UIs.
push_back(
new UnreachableInst(
F->getContext(), &BB));
6326 LoopInfo &&LI = LIA.
run(*
F,
FAM);
6327 for (Instruction *
I : UIs)
6328 I->eraseFromParent();
6331 if (ChunkSize || DistScheduleChunkSize)
6336 FunctionCallee StaticInit =
6338 FunctionCallee StaticFini =
6344 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6345 Value *PLowerBound =
6346 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.lowerbound");
6347 Value *PUpperBound =
6348 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.upperbound");
6349 Value *PStride =
Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.stride");
6358 ChunkSize ? ChunkSize : Zero, InternalIVTy,
"chunksize");
6359 Value *CastedDistScheduleChunkSize =
Builder.CreateZExtOrTrunc(
6360 DistScheduleChunkSize ? DistScheduleChunkSize : Zero, InternalIVTy,
6361 "distschedulechunksize");
6362 Value *CastedTripCount =
6363 Builder.CreateZExt(OrigTripCount, InternalIVTy,
"tripcount");
6366 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6368 ConstantInt::get(I32Type,
static_cast<int>(DistScheduleSchedType));
6369 Builder.CreateStore(Zero, PLowerBound);
6370 Value *OrigUpperBound =
Builder.CreateSub(CastedTripCount, One);
6371 Value *IsTripCountZero =
Builder.CreateICmpEQ(CastedTripCount, Zero);
6373 Builder.CreateSelect(IsTripCountZero, Zero, OrigUpperBound);
6374 Builder.CreateStore(UpperBound, PUpperBound);
6375 Builder.CreateStore(One, PStride);
6379 uint32_t SrcLocStrSize;
6382 if (DistScheduleSchedType != OMPScheduleType::None) {
6383 Flag |= OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6388 auto BuildInitCall = [StaticInit, SrcLoc, ThreadNum, PLastIter, PLowerBound,
6389 PUpperBound, PStride, One,
6390 this](
Value *SchedulingType,
Value *ChunkSize,
6393 StaticInit, {SrcLoc, ThreadNum,
6394 SchedulingType, PLastIter,
6395 PLowerBound, PUpperBound,
6399 BuildInitCall(SchedulingType, CastedChunkSize,
Builder);
6400 if (DistScheduleSchedType != OMPScheduleType::None &&
6401 SchedType != OMPScheduleType::OrderedDistributeChunked &&
6402 SchedType != OMPScheduleType::OrderedDistribute) {
6406 BuildInitCall(DistSchedulingType, CastedDistScheduleChunkSize,
Builder);
6410 Value *FirstChunkStart =
6411 Builder.CreateLoad(InternalIVTy, PLowerBound,
"omp_firstchunk.lb");
6412 Value *FirstChunkStop =
6413 Builder.CreateLoad(InternalIVTy, PUpperBound,
"omp_firstchunk.ub");
6414 Value *FirstChunkEnd =
Builder.CreateAdd(FirstChunkStop, One);
6416 Builder.CreateSub(FirstChunkEnd, FirstChunkStart,
"omp_chunk.range");
6417 Value *NextChunkStride =
6418 Builder.CreateLoad(InternalIVTy, PStride,
"omp_dispatch.stride");
6422 Value *DispatchCounter;
6430 DispatchCounter = Counter;
6433 FirstChunkStart, CastedTripCount, NextChunkStride,
6456 Value *ChunkEnd =
Builder.CreateAdd(DispatchCounter, ChunkRange);
6457 Value *IsLastChunk =
6458 Builder.CreateICmpUGE(ChunkEnd, CastedTripCount,
"omp_chunk.is_last");
6459 Value *CountUntilOrigTripCount =
6460 Builder.CreateSub(CastedTripCount, DispatchCounter);
6462 IsLastChunk, CountUntilOrigTripCount, ChunkRange,
"omp_chunk.tripcount");
6463 Value *BackcastedChunkTC =
6464 Builder.CreateTrunc(ChunkTripCount, IVTy,
"omp_chunk.tripcount.trunc");
6465 CLI->setTripCount(BackcastedChunkTC);
6470 Value *BackcastedDispatchCounter =
6471 Builder.CreateTrunc(DispatchCounter, IVTy,
"omp_dispatch.iv.trunc");
6472 CLI->mapIndVar([&](Instruction *) ->
Value * {
6474 return Builder.CreateAdd(
IV, BackcastedDispatchCounter);
6487 return AfterIP.takeError();
6502static FunctionCallee
6505 unsigned Bitwidth = Ty->getIntegerBitWidth();
6508 case WorksharingLoopType::ForStaticLoop:
6511 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_4u);
6514 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_8u);
6516 case WorksharingLoopType::DistributeStaticLoop:
6519 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_4u);
6522 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_8u);
6524 case WorksharingLoopType::DistributeForStaticLoop:
6527 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_4u);
6530 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_8u);
6533 if (Bitwidth != 32 && Bitwidth != 64) {
6545 Function &LoopBodyFn,
bool NoLoop) {
6556 if (LoopType == WorksharingLoopType::DistributeStaticLoop) {
6557 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6558 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6559 Builder.restoreIP(std::prev(InsertBlock->
end()));
6564 M, omp::RuntimeFunction::OMPRTL_omp_get_num_threads);
6565 Builder.restoreIP(std::prev(InsertBlock->
end()));
6569 Builder.CreateZExtOrTrunc(NumThreads, TripCountTy,
"num.threads.cast"));
6570 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6571 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
6572 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6573 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), NoLoop));
6575 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6599 Builder.restoreIP(Preheader->
end());
6602 Builder.CreateBr(CLI->
getExit());
6610 CleanUpInfo.
collectBlocks(RegionBlockSet, BlocksToBeRemoved);
6618 "Expected unique undroppable user of outlined function");
6620 assert(OutlinedFnCallInstruction &&
"Expected outlined function call");
6622 "Expected outlined function call to be located in loop preheader");
6624 if (OutlinedFnCallInstruction->
arg_size() > 1)
6631 LoopBodyArg, TripCount, OutlinedFn, NoLoop);
6633 for (
auto &ToBeDeletedItem : ToBeDeleted)
6634 ToBeDeletedItem->eraseFromParent();
6641 bool NeedsLastIter) {
6642 uint32_t SrcLocStrSize;
6646 if (NeedsLastIter) {
6649 AllocaInst *PLastIter =
6650 Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6654 Builder.CreateStore(ConstantInt::get(I32Type, 0), PLastIter);
6659 Builder.CreateSub(TripCount, ConstantInt::get(TripCount->
getType(), 1));
6662 Builder.CreateStore(
Builder.CreateZExt(IsLast, I32Type), PLastIter);
6667 case WorksharingLoopType::ForStaticLoop:
6668 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6670 case WorksharingLoopType::DistributeStaticLoop:
6671 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6673 case WorksharingLoopType::DistributeForStaticLoop:
6674 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
6679 auto OI = std::make_unique<OutlineInfo>();
6684 SmallVector<Instruction *, 4> ToBeDeleted;
6686 OI->OuterAllocBB = AllocaIP.getNodeParent();
6709 SmallPtrSet<BasicBlock *, 32> ParallelRegionBlockSet;
6711 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
6713 CodeExtractorAnalysisCache CEAC(*OuterFn);
6714 CodeExtractor Extractor(Blocks,
6728 SetVector<Value *> SinkingCands, HoistingCands;
6732 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
6739 for (
auto Use :
Users) {
6741 if (ParallelRegionBlockSet.
count(Inst->getParent())) {
6742 Inst->replaceUsesOfWith(CLI->
getIndVar(), NewLoopCntLoad);
6748 OI->ExcludeArgsFromAggregate.push_back(NewLoopCntLoad);
6755 OI->PostOutlineCB = [=, ToBeDeletedVec =
6756 std::move(ToBeDeleted)](
Function &OutlinedFn) {
6773 return BarrierIP.takeError();
6780 bool NeedsBarrier, omp::ScheduleKind SchedKind,
Value *ChunkSize,
6781 bool HasSimdModifier,
bool HasMonotonicModifier,
6782 bool HasNonmonotonicModifier,
bool HasOrderedClause,
6784 Value *DistScheduleChunkSize,
bool NeedsLastIter) {
6785 if (
Config.isTargetDevice())
6786 return applyWorkshareLoopTarget(
DL, CLI, AllocaIP, LoopType, NeedsBarrier,
6787 NoLoop, NeedsLastIter);
6789 SchedKind, ChunkSize, HasSimdModifier, HasMonotonicModifier,
6790 HasNonmonotonicModifier, HasOrderedClause, DistScheduleChunkSize);
6792 bool IsOrdered = (EffectiveScheduleType & OMPScheduleType::ModifierOrdered) ==
6793 OMPScheduleType::ModifierOrdered;
6795 if (HasDistSchedule) {
6796 DistScheduleSchedType = DistScheduleChunkSize
6797 ? OMPScheduleType::OrderedDistributeChunked
6798 : OMPScheduleType::OrderedDistribute;
6800 switch (EffectiveScheduleType & ~OMPScheduleType::ModifierMask) {
6801 case OMPScheduleType::BaseStatic:
6802 case OMPScheduleType::BaseDistribute:
6803 assert((!ChunkSize || !DistScheduleChunkSize) &&
6804 "No chunk size with static-chunked schedule");
6805 if (IsOrdered && !HasDistSchedule)
6806 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6807 NeedsBarrier, ChunkSize);
6809 if (DistScheduleChunkSize)
6810 return applyStaticChunkedWorkshareLoop(
6811 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6812 DistScheduleChunkSize, DistScheduleSchedType);
6813 return applyStaticWorkshareLoop(
DL, CLI, AllocaIP, LoopType, NeedsBarrier,
6816 case OMPScheduleType::BaseStaticChunked:
6817 case OMPScheduleType::BaseDistributeChunked:
6818 if (IsOrdered && !HasDistSchedule)
6819 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6820 NeedsBarrier, ChunkSize);
6822 return applyStaticChunkedWorkshareLoop(
6823 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6824 DistScheduleChunkSize, DistScheduleSchedType);
6826 case OMPScheduleType::BaseRuntime:
6827 case OMPScheduleType::BaseAuto:
6828 case OMPScheduleType::BaseGreedy:
6829 case OMPScheduleType::BaseBalanced:
6830 case OMPScheduleType::BaseSteal:
6831 case OMPScheduleType::BaseRuntimeSimd:
6833 "schedule type does not support user-defined chunk sizes");
6835 case OMPScheduleType::BaseGuidedSimd:
6836 case OMPScheduleType::BaseDynamicChunked:
6837 case OMPScheduleType::BaseGuidedChunked:
6838 case OMPScheduleType::BaseGuidedIterativeChunked:
6839 case OMPScheduleType::BaseGuidedAnalyticalChunked:
6840 case OMPScheduleType::BaseStaticBalancedChunked:
6841 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6842 NeedsBarrier, ChunkSize);
6855 unsigned Bitwidth = Ty->getIntegerBitWidth();
6858 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_4u);
6861 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_8u);
6869static FunctionCallee
6871 unsigned Bitwidth = Ty->getIntegerBitWidth();
6874 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_4u);
6877 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_8u);
6884static FunctionCallee
6886 unsigned Bitwidth = Ty->getIntegerBitWidth();
6889 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_4u);
6892 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_8u);
6897OpenMPIRBuilder::applyDynamicWorkshareLoop(
DebugLoc DL, CanonicalLoopInfo *CLI,
6900 bool NeedsBarrier,
Value *Chunk) {
6901 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6903 "Require dedicated allocate IP");
6905 "Require valid schedule type");
6907 bool Ordered = (SchedType & OMPScheduleType::ModifierOrdered) ==
6908 OMPScheduleType::ModifierOrdered;
6913 uint32_t SrcLocStrSize;
6920 Type *IVTy =
IV->getType();
6926 AllocaIP.getNodeParent()->getFirstNonPHIOrDbgOrAlloca());
6928 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6929 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
6930 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
6931 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
6940 Constant *One = ConstantInt::get(IVTy, 1);
6941 Builder.CreateStore(One, PLowerBound);
6943 Builder.CreateStore(UpperBound, PUpperBound);
6944 Builder.CreateStore(One, PStride);
6962 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6974 Builder.SetInsertPoint(OuterCond->getFirstInsertionPt());
6977 {SrcLoc, ThreadNum, PLastIter, PLowerBound, PUpperBound, PStride});
6978 Constant *Zero32 = ConstantInt::get(I32Type, 0);
6981 Builder.CreateSub(
Builder.CreateLoad(IVTy, PLowerBound), One,
"lb");
6982 Builder.CreateCondBr(MoreWork, Header, Exit);
6988 PI->setIncomingBlock(0, OuterCond);
6994 Br->setSuccessor(OuterCond);
6999 Builder.SetInsertPoint(
Cond->getFirstInsertionPt());
7000 UpperBound =
Builder.CreateLoad(IVTy, PUpperBound,
"ub");
7003 CI->setOperand(1, UpperBound);
7007 assert(BI->getSuccessor(1) == Exit);
7008 BI->setSuccessor(1, OuterCond);
7022 omp::Directive::OMPD_for,
false,
7025 return BarrierIP.takeError();
7077 assert(
Loops.size() >= 1 &&
"At least one loop required");
7078 size_t NumLoops =
Loops.size();
7082 return Loops.front();
7094 Loop->collectControlBlocks(OldControlBBs);
7098 if (ComputeIP.isValid())
7105 Value *CollapsedTripCount =
nullptr;
7108 "All loops to collapse must be valid canonical loops");
7109 Value *OrigTripCount = L->getTripCount();
7110 if (!CollapsedTripCount) {
7111 CollapsedTripCount = OrigTripCount;
7116 CollapsedTripCount =
7117 Builder.CreateNUWMul(CollapsedTripCount, OrigTripCount);
7123 OrigPreheader->
getNextNode(), OrigAfter,
"collapsed",
7130 Builder.restoreIP(Result->getBodyIP());
7132 Value *Leftover = Result->getIndVar();
7134 NewIndVars.
resize(NumLoops);
7135 for (
int i = NumLoops - 1; i >= 1; --i) {
7136 Value *OrigTripCount =
Loops[i]->getTripCount();
7138 Value *NewIndVar =
Builder.CreateURem(Leftover, OrigTripCount);
7139 NewIndVars[i] = NewIndVar;
7141 Leftover =
Builder.CreateUDiv(Leftover, OrigTripCount);
7144 NewIndVars[0] = Leftover;
7153 BasicBlock *ContinueBlock = Result->getBody();
7155 auto ContinueWith = [&ContinueBlock, &ContinuePred,
DL](
BasicBlock *Dest,
7162 ContinueBlock =
nullptr;
7163 ContinuePred = NextSrc;
7170 for (
size_t i = 0; i < NumLoops - 1; ++i)
7171 ContinueWith(
Loops[i]->getBody(),
Loops[i + 1]->getHeader());
7177 for (
size_t i = NumLoops - 1; i > 0; --i)
7178 ContinueWith(
Loops[i]->getAfter(),
Loops[i - 1]->getLatch());
7181 ContinueWith(Result->getLatch(),
nullptr);
7188 for (
size_t i = 0; i < NumLoops; ++i)
7189 Loops[i]->getIndVar()->replaceAllUsesWith(NewIndVars[i]);
7203std::vector<CanonicalLoopInfo *>
7207 "Must pass as many tile sizes as there are loops");
7208 int NumLoops =
Loops.size();
7209 assert(NumLoops >= 1 &&
"At least one loop to tile required");
7221 Loop->collectControlBlocks(OldControlBBs);
7229 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7230 OrigTripCounts.
push_back(L->getTripCount());
7241 for (
int i = 0; i < NumLoops - 1; ++i) {
7254 for (
int i = 0; i < NumLoops; ++i) {
7255 Value *TileSize = TileSizes[i];
7256 Value *OrigTripCount = OrigTripCounts[i];
7259 Value *FloorCompleteTripCount =
Builder.CreateUDiv(OrigTripCount, TileSize);
7260 Value *FloorTripRem =
Builder.CreateURem(OrigTripCount, TileSize);
7269 Value *FloorTripOverflow =
7270 Builder.CreateICmpNE(FloorTripRem, ConstantInt::get(IVType, 0));
7272 FloorTripOverflow =
Builder.CreateZExt(FloorTripOverflow, IVType);
7273 Value *FloorTripCount =
7274 Builder.CreateAdd(FloorCompleteTripCount, FloorTripOverflow,
7275 "omp_floor" +
Twine(i) +
".tripcount",
true);
7278 FloorCompleteCount.
push_back(FloorCompleteTripCount);
7284 std::vector<CanonicalLoopInfo *> Result;
7285 Result.reserve(NumLoops * 2);
7298 auto EmbeddNewLoop =
7299 [
this,
DL,
F, InnerEnter, &Enter, &
Continue, &OutroInsertBefore](
7302 DL, TripCount,
F, InnerEnter, OutroInsertBefore, Name);
7307 Enter = EmbeddedLoop->
getBody();
7309 OutroInsertBefore = EmbeddedLoop->
getLatch();
7310 return EmbeddedLoop;
7314 const Twine &NameBase) {
7317 EmbeddNewLoop(
P.value(), NameBase +
Twine(
P.index()));
7318 Result.push_back(EmbeddedLoop);
7322 EmbeddNewLoops(FloorCount,
"floor");
7328 for (
int i = 0; i < NumLoops; ++i) {
7330 Value *TileSize = TileSizes[i];
7332 Value *FloorIsEpilogue =
7334 Value *TileTripCount =
7335 Builder.CreateSelect(FloorIsEpilogue, FloorRems[i], TileSize);
7341 EmbeddNewLoops(TileCounts,
"tile");
7346 for (std::pair<BasicBlock *, BasicBlock *>
P : InbetweenCode) {
7355 BodyEnter =
nullptr;
7356 BodyEntered = ExitBB;
7368 Builder.restoreIP(Result.back()->getBodyIP());
7369 for (
int i = 0; i < NumLoops; ++i) {
7372 Value *OrigIndVar = OrigIndVars[i];
7423 assert(
Loop->isValid() &&
"Expecting a valid CanonicalLoopInfo");
7427 assert(Latch &&
"A valid CanonicalLoopInfo must have a unique latch");
7435 if (
I.mayReadOrWriteMemory()) {
7439 I.setMetadata(LLVMContext::MD_access_group,
AccessGroup);
7453 Loop->collectControlBlocks(oldControlBBs);
7458 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7459 origTripCounts.
push_back(L->getTripCount());
7468 Builder.SetInsertPoint(TCBlock);
7469 Value *fusedTripCount =
nullptr;
7471 assert(L->isValid() &&
"All loops to fuse must be valid canonical loops");
7472 Value *origTripCount = L->getTripCount();
7473 if (!fusedTripCount) {
7474 fusedTripCount = origTripCount;
7477 Value *condTP =
Builder.CreateICmpSGT(fusedTripCount, origTripCount);
7478 fusedTripCount =
Builder.CreateSelect(condTP, fusedTripCount, origTripCount,
7492 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7493 Loops[i]->getPreheader()->moveBefore(TCBlock);
7494 Loops[i]->getAfter()->moveBefore(TCBlock);
7498 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7510 for (
size_t i = 0; i <
Loops.size(); ++i) {
7512 F->getContext(),
"omp.fused.inner.cond",
F,
Loops[i]->getBody());
7513 Builder.SetInsertPoint(condBlock);
7521 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7522 Builder.SetInsertPoint(condBBs[i]);
7523 Builder.CreateCondBr(condValues[i],
Loops[i]->getBody(), condBBs[i + 1]);
7539 "omp.fused.pre_latch");
7572 const Twine &NamePrefix) {
7601 C, NamePrefix +
".if.then",
Cond->getParent(),
Cond->getNextNode());
7603 C, NamePrefix +
".if.else",
Cond->getParent(), CanonicalLoop->
getExit());
7606 Builder.SetInsertPoint(SplitBeforeIt);
7608 Builder.CreateCondBr(IfCond, ThenBlock, ElseBlock);
7611 spliceBB(IP, ThenBlock,
false, Builder.getCurrentDebugLocation());
7614 Builder.SetInsertPoint(ElseBlock);
7620 ExistingBlocks.
reserve(L->getNumBlocks() + 1);
7622 ExistingBlocks.
append(L->block_begin(), L->block_end());
7628 assert(LoopCond && LoopHeader &&
"Invalid loop structure");
7630 if (
Block == L->getLoopPreheader() ||
Block == L->getLoopLatch() ||
7637 if (
Block == ThenBlock)
7638 NewBB->
setName(NamePrefix +
".if.else");
7641 VMap[
Block] = NewBB;
7649 L->getLoopLatch()->splitBasicBlockBefore(
L->getLoopLatch()->begin(),
7650 NamePrefix +
".pre_latch");
7654 L->addBasicBlockToLoop(ThenBlock, LI);
7660 if (TargetTriple.
isX86()) {
7661 if (Features.
lookup(
"avx512f"))
7663 else if (Features.
lookup(
"avx"))
7667 if (TargetTriple.
isPPC())
7669 if (TargetTriple.
isWasm())
7678 Value *IfCond, OrderKind Order,
7688 if (!BB.hasTerminator())
7704 I->eraseFromParent();
7707 if (AlignedVars.
size()) {
7709 for (
auto &AlignedItem : AlignedVars) {
7710 Value *AlignedPtr = AlignedItem.first;
7714 Builder.CreateAlignmentAssumption(
F->getDataLayout(), AlignedPtr,
7722 createIfVersion(CanonicalLoop, IfCond, VMap, LIA, LI, L,
"simd");
7735 Reachable.insert(
Block);
7745 if ((Safelen ==
nullptr) || (Order == OrderKind::OMP_ORDER_concurrent))
7761 if (Simdlen || Safelen) {
7765 ConstantInt *VectorizeWidth = Simdlen ==
nullptr ? Safelen : Simdlen;
7791static std::unique_ptr<TargetMachine>
7795 StringRef CPU =
F->getFnAttribute(
"target-cpu").getValueAsString();
7796 StringRef Features =
F->getFnAttribute(
"target-features").getValueAsString();
7807 std::nullopt, OptLevel));
7825 if (!BB.hasTerminator())
7838 [&](
const Function &
F) {
return TM->getTargetTransformInfo(
F); });
7839 FAM.registerPass([&]() {
return TIRA; });
7853 I->eraseFromParent();
7856 assert(L &&
"Expecting CanonicalLoopInfo to be recognized as a loop");
7861 nullptr, ORE,
static_cast<int>(OptLevel),
7881 <<
" Threshold=" << UP.
Threshold <<
"\n"
7884 <<
" PartialOptSizeThreshold="
7904 Ptr =
Load->getPointerOperand();
7906 Ptr =
Store->getPointerOperand();
7913 if (Alloca->getParent() == &
F->getEntryBlock())
7933 int MaxTripCount = 0;
7934 bool MaxOrZero =
false;
7935 unsigned TripMultiple = 0;
7939 MaxTripCount, MaxOrZero, TripMultiple, UCE, UP, PP);
7940 LLVM_DEBUG(
dbgs() <<
"Suggesting unroll factor of " << Factor <<
"\n");
7951 assert(Factor >= 0 &&
"Unroll factor must not be negative");
7967 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst}));
7980 *UnrolledCLI =
Loop;
7985 "unrolling only makes sense with a factor of 2 or larger");
7987 Type *IndVarTy =
Loop->getIndVarType();
7994 std::vector<CanonicalLoopInfo *>
LoopNest =
8009 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst})});
8012 (*UnrolledCLI)->assertOK();
8030 Value *Args[] = {Ident, ThreadId, BufSize, CpyBuf, CpyFn, DidItLD};
8049 if (!CPVars.
empty()) {
8054 Directive OMPD = Directive::OMPD_single;
8059 Value *Args[] = {Ident, ThreadId};
8068 if (
Error Err = FiniCB(IP))
8089 EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCBWrapper,
8096 for (
size_t I = 0, E = CPVars.
size();
I < E; ++
I)
8099 ConstantInt::get(Int64, 0), CPVars[
I],
8102 }
else if (!IsNowait) {
8105 omp::Directive::OMPD_unknown,
false,
8123 Directive::OMPD_scope,
nullptr,
nullptr,
8124 BodyGenCB, FiniCB,
false,
true,
8132 omp::Directive::OMPD_unknown,
8148 Directive OMPD = Directive::OMPD_critical;
8153 Value *LockVar = getOMPCriticalRegionLock(CriticalName);
8154 Value *Args[] = {Ident, ThreadId, LockVar};
8171 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
8179 const Twine &Name,
bool IsDependSource) {
8182 [](
Value *SV) {
return SV->getType()->isIntegerTy(64); }) &&
8183 "OpenMP runtime requires depend vec with i64 type");
8196 for (
unsigned I = 0;
I < NumLoops; ++
I) {
8210 Value *Args[] = {Ident, ThreadId, DependBaseAddrGEP};
8228 Directive OMPD = Directive::OMPD_ordered_blockassoc;
8237 Value *Args[] = {Ident, ThreadId};
8247 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
8254 bool HasFinalize,
bool IsCancellable) {
8261 BasicBlock *EntryBB = Builder.GetInsertBlock();
8270 emitCommonDirectiveEntry(OMPD, EntryCall, ExitBB, Conditional);
8282 "Unexpected control flow graph state!!");
8284 emitCommonDirectiveExit(OMPD, FinIP, ExitCall, HasFinalize);
8286 return AfterIP.takeError();
8291 "Unexpected Insertion point location!");
8294 auto InsertBB = merged ? ExitPredBB : ExitBB;
8297 Builder.SetInsertPoint(InsertBB);
8299 return Builder.saveIP();
8303 Directive OMPD,
Value *EntryCall, BasicBlock *ExitBB,
bool Conditional) {
8305 if (!Conditional || !EntryCall)
8311 auto *UI =
new UnreachableInst(
Builder.getContext(), ThenBB);
8321 Builder.CreateCondBr(CallBool, ThenBB, ExitBB);
8325 UI->eraseFromParent();
8333 omp::Directive OMPD,
InsertPointTy FinIP, Instruction *ExitCall,
8341 "Unexpected finalization stack state!");
8344 assert(Fi.DK == OMPD &&
"Unexpected Directive for Finalization call!");
8348 return std::move(Err);
8395 "copyin.not.master.end");
8402 Builder.SetInsertPoint(OMP_Entry);
8405 Value *cmp =
Builder.CreateICmpNE(MasterPtr, PrivatePtr);
8406 Builder.CreateCondBr(cmp, CopyBegin, CopyEnd);
8408 Builder.SetInsertPoint(CopyBegin);
8426 Value *Args[] = {ThreadId,
Size, Allocator};
8449 return Builder.CreateCall(Fn, Args, Name);
8463 Value *Args[] = {ThreadId, Addr, Allocator};
8470 const Twine &Name) {
8478 M.getContext(),
M.getDataLayout().getPrefTypeAlign(Int64)));
8484 const Twine &Name) {
8486 Loc,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)), Name);
8491 const Twine &Name) {
8497 return Builder.CreateCall(Fn, Args, Name);
8502 const Twine &Name) {
8504 Loc, Addr,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)),
8511 Value *DependenceAddress,
bool HaveNowaitClause) {
8521 else if (
Device->getType() != Int32)
8524 if (NumDependences ==
nullptr) {
8525 NumDependences = ConstantInt::get(Int32, 0);
8529 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8531 Ident, ThreadId, InteropVar, InteropTypeVal,
8532 Device, NumDependences, DependenceAddress, HaveNowaitClauseVal};
8541 Value *NumDependences,
Value *DependenceAddress,
bool HaveNowaitClause) {
8551 else if (
Device->getType() != Int32)
8553 if (NumDependences ==
nullptr) {
8554 NumDependences = ConstantInt::get(Int32, 0);
8558 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8560 Ident, ThreadId, InteropVar,
Device,
8561 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8570 Value *NumDependences,
8571 Value *DependenceAddress,
8572 bool HaveNowaitClause) {
8581 else if (
Device->getType() != Int32)
8583 if (NumDependences ==
nullptr) {
8584 NumDependences = ConstantInt::get(Int32, 0);
8588 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8590 Ident, ThreadId, InteropVar,
Device,
8591 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8621 assert(!Attrs.MaxThreads.empty() && !Attrs.MaxTeams.empty() &&
8622 "expected num_threads and num_teams to be specified");
8642 const std::string DebugPrefix =
"_debug__";
8643 if (KernelName.
ends_with(DebugPrefix)) {
8644 KernelName = KernelName.
drop_back(DebugPrefix.length());
8645 Kernel =
M.getFunction(KernelName);
8651 if (Attrs.MinTeams.front() > 1 || Attrs.MaxTeams.front() > 0)
8653 Attrs.MaxTeams.front());
8656 int32_t MaxThreadsVal = Attrs.MaxThreads.front();
8666 Attrs.MinThreads.front());
8671 if (MaxThreadsVal > 0 &&
8674 MaxThreadsVal = int32_t(
8675 std::min<int64_t>(int64_t(MaxThreadsVal) + 64,
8678 if (MaxThreadsVal > 0)
8693 Twine DynamicEnvironmentName = KernelName +
"_dynamic_environment";
8694 Constant *DynamicEnvironmentInitializer =
8698 DynamicEnvironmentInitializer, DynamicEnvironmentName,
8700 DL.getDefaultGlobalsAddressSpace());
8704 DynamicEnvironmentGV->
getType() == DynamicEnvironmentPtr
8705 ? DynamicEnvironmentGV
8707 DynamicEnvironmentPtr);
8710 ConfigurationEnvironment, {
8711 UseGenericStateMachineVal,
8712 MayUseNestedParallelismVal,
8721 KernelEnvironment, {
8722 ConfigurationEnvironmentInitializer,
8726 std::string KernelEnvironmentName =
8727 (KernelName +
"_kernel_environment").str();
8730 KernelEnvironmentInitializer, KernelEnvironmentName,
8732 DL.getDefaultGlobalsAddressSpace());
8735 return KernelEnvironmentGV->
getType() == KernelEnvironmentPtr
8736 ? KernelEnvironmentGV
8738 KernelEnvironmentPtr);
8745 if (!KernelEnvironment)
8753 omp::RuntimeFunction::OMPRTL___kmpc_target_init);
8755 Value *KernelLaunchEnvironment =
8758 KernelLaunchEnvironment =
8759 KernelLaunchEnvironment->
getType() == KernelLaunchEnvParamTy
8760 ? KernelLaunchEnvironment
8761 :
Builder.CreateAddrSpaceCast(KernelLaunchEnvironment,
8762 KernelLaunchEnvParamTy);
8764 Fn, {KernelEnvironment, KernelLaunchEnvironment});
8776 auto *UI =
Builder.CreateUnreachable();
8782 Builder.SetInsertPoint(WorkerExitBB);
8786 Builder.SetInsertPoint(CheckBBTI);
8787 Builder.CreateCondBr(ExecUserCode, UI->getParent(), WorkerExitBB);
8789 CheckBBTI->eraseFromParent();
8790 UI->eraseFromParent();
8798 int32_t TeamsReductionDataSize) {
8803 omp::RuntimeFunction::OMPRTL___kmpc_target_deinit);
8807 if (!TeamsReductionDataSize)
8813 const std::string DebugPrefix =
"_debug__";
8815 KernelName = KernelName.
drop_back(DebugPrefix.length());
8816 auto *KernelEnvironmentGV =
8817 M.getNamedGlobal((KernelName +
"_kernel_environment").str());
8818 assert(KernelEnvironmentGV &&
"Expected kernel environment global\n");
8819 auto *KernelEnvironmentInitializer = KernelEnvironmentGV->getInitializer();
8821 KernelEnvironmentInitializer,
8822 ConstantInt::get(Int32, TeamsReductionDataSize), {0, 7});
8823 KernelEnvironmentGV->setInitializer(NewInitializer);
8828 if (
Kernel.hasFnAttribute(Name)) {
8829 int32_t OldLimit =
Kernel.getFnAttributeAsParsedInteger(Name);
8835std::pair<int32_t, int32_t>
8837 int32_t ThreadLimit =
8838 Kernel.getFnAttributeAsParsedInteger(
"omp_target_thread_limit");
8841 const auto &Attr =
Kernel.getFnAttribute(
"amdgpu-flat-work-group-size");
8842 if (!Attr.isValid() || !Attr.isStringAttribute())
8843 return {0, ThreadLimit};
8844 auto [LBStr, UBStr] = Attr.getValueAsString().split(
',');
8847 return {0, ThreadLimit};
8848 UB = ThreadLimit ? std::min(ThreadLimit, UB) : UB;
8856 return {0, ThreadLimit ? std::min(ThreadLimit, UB) : UB};
8858 return {0, ThreadLimit};
8864 Kernel.addFnAttr(
"omp_target_thread_limit", std::to_string(UB));
8867 Kernel.addFnAttr(
"amdgpu-flat-work-group-size",
8875std::pair<int32_t, int32_t>
8878 return {0,
Kernel.getFnAttributeAsParsedInteger(
"omp_target_num_teams")};
8882 int32_t LB, int32_t UB) {
8890 Kernel.addFnAttr(
"omp_target_num_teams", std::to_string(LB));
8893void OpenMPIRBuilder::setOutlinedTargetRegionFunctionAttributes(
8902 else if (
T.isNVPTX())
8904 else if (
T.isSPIRV())
8910 StringRef EntryFnIDName) {
8911 if (
Config.isTargetDevice()) {
8912 assert(OutlinedFn &&
"The outlined function must exist if embedded");
8916 return new GlobalVariable(
8921Constant *OpenMPIRBuilder::createTargetRegionEntryAddr(
Function *OutlinedFn,
8922 StringRef EntryFnName) {
8926 assert(!
M.getGlobalVariable(EntryFnName,
true) &&
8927 "Named kernel already exists?");
8928 return new GlobalVariable(
8941 if (
Config.isTargetDevice() || !
Config.openMPOffloadMandatory()) {
8945 OutlinedFn = *CBResult;
8947 OutlinedFn =
nullptr;
8953 if (!IsOffloadEntry)
8956 std::string EntryFnIDName =
8958 ? std::string(EntryFnName)
8962 EntryFnName, EntryFnIDName);
8970 setOutlinedTargetRegionFunctionAttributes(OutlinedFn);
8971 auto OutlinedFnID = createOutlinedFunctionID(OutlinedFn, EntryFnIDName);
8972 auto EntryAddr = createTargetRegionEntryAddr(OutlinedFn, EntryFnName);
8974 EntryInfo, EntryAddr, OutlinedFnID,
8976 return OutlinedFnID;
8994 bool IsStandAlone = !BodyGenCB;
9001 MapInfo = &GenMapInfoCB(
Builder.saveIP());
9003 AllocaIP,
Builder.saveIP(), *MapInfo, Info, CustomMapperCB,
9004 true, DeviceAddrCB))
9011 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
9021 SrcLocInfo, DeviceID,
9028 assert(MapperFunc &&
"MapperFunc missing for standalone target data");
9032 if (Info.HasNoWait) {
9042 if (Info.HasNoWait) {
9046 emitBlock(OffloadContBlock, CurFn,
true);
9052 bool RequiresOuterTargetTask = Info.HasNoWait;
9053 if (!RequiresOuterTargetTask)
9054 cantFail(TaskBodyCB(
nullptr,
nullptr,
9058 {}, RTArgs, Info.HasNoWait));
9061 omp::OMPRTL___tgt_target_data_begin_mapper);
9065 for (
auto DeviceMap : Info.DevicePtrInfoMap) {
9069 Builder.CreateStore(LI, DeviceMap.second.second);
9106 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
9115 Value *OffloadingArgs[] = {SrcLocInfo, DeviceID,
9138 return emitIfClause(IfCond, BeginThenGen, BeginElseGen, AllocaIP);
9139 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9154 return emitIfClause(IfCond, EndThenGen, EndElseGen, AllocaIP);
9155 return EndThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9158 return emitIfClause(IfCond, BeginThenGen, EndElseGen, AllocaIP);
9159 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9170 bool IsGPUDistribute) {
9171 assert((IVSize == 32 || IVSize == 64) &&
9172 "IV size is not compatible with the omp runtime");
9174 if (IsGPUDistribute)
9176 ? (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_4
9177 : omp::OMPRTL___kmpc_distribute_static_init_4u)
9178 : (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_8
9179 : omp::OMPRTL___kmpc_distribute_static_init_8u);
9181 Name = IVSize == 32 ? (IVSigned ? omp::OMPRTL___kmpc_for_static_init_4
9182 : omp::OMPRTL___kmpc_for_static_init_4u)
9183 : (IVSigned ? omp::OMPRTL___kmpc_for_static_init_8
9184 : omp::OMPRTL___kmpc_for_static_init_8u);
9191 assert((IVSize == 32 || IVSize == 64) &&
9192 "IV size is not compatible with the omp runtime");
9194 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_4
9195 : omp::OMPRTL___kmpc_dispatch_init_4u)
9196 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_8
9197 : omp::OMPRTL___kmpc_dispatch_init_8u);
9204 assert((IVSize == 32 || IVSize == 64) &&
9205 "IV size is not compatible with the omp runtime");
9207 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_4
9208 : omp::OMPRTL___kmpc_dispatch_next_4u)
9209 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_8
9210 : omp::OMPRTL___kmpc_dispatch_next_8u);
9217 assert((IVSize == 32 || IVSize == 64) &&
9218 "IV size is not compatible with the omp runtime");
9220 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_4
9221 : omp::OMPRTL___kmpc_dispatch_fini_4u)
9222 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_8
9223 : omp::OMPRTL___kmpc_dispatch_fini_8u);
9234 DenseMap<
Value *, std::tuple<Value *, unsigned>> &ValueReplacementMap) {
9242 auto GetUpdatedDIVariable = [&](
DILocalVariable *OldVar,
unsigned arg) {
9246 if (NewVar && (arg == NewVar->
getArg()))
9256 auto UpdateDebugRecord = [&](
auto *DR) {
9259 for (
auto Loc : DR->location_ops()) {
9260 auto Iter = ValueReplacementMap.find(
Loc);
9261 if (Iter != ValueReplacementMap.end()) {
9262 DR->replaceVariableLocationOp(
Loc, std::get<0>(Iter->second));
9263 ArgNo = std::get<1>(Iter->second) + 1;
9267 DR->setVariable(GetUpdatedDIVariable(OldVar, ArgNo));
9272 if (DVR->getNumVariableLocationOps() != 1u) {
9273 DVR->setKillLocation();
9276 Value *
Loc = DVR->getVariableLocationOp(0u);
9283 RequiredBB = &DVR->getFunction()->getEntryBlock();
9285 if (RequiredBB && RequiredBB != CurBB) {
9297 UpdateDebugRecord(&DVR);
9298 MoveDebugRecordToCorrectBlock(&DVR);
9301 for (
auto *DVR : DVRsToDelete)
9302 DVR->getMarker()->MarkedInstr->dropOneDbgRecord(DVR);
9306 Module *M = Func->getParent();
9309 DB.createQualifiedType(dwarf::DW_TAG_pointer_type,
nullptr);
9310 unsigned ArgNo = Func->arg_size();
9312 NewSP,
"dyn_ptr", ArgNo, NewSP->
getFile(), 0, VoidPtrTy,
9313 false, DINode::DIFlags::FlagArtificial);
9315 Argument *LastArg = Func->getArg(Func->arg_size() - 1);
9316 DB.insertDeclare(LastArg, Var, DB.createExpression(),
Loc,
9338 for (
auto &Arg : Inputs)
9339 ParameterTypes.
push_back(Arg->getType()->isPointerTy()
9343 for (
auto &Arg : Inputs)
9344 ParameterTypes.
push_back(Arg->getType());
9352 auto BB = Builder.GetInsertBlock();
9353 auto M = BB->getModule();
9364 if (TargetCpuAttr.isStringAttribute())
9365 Func->addFnAttr(TargetCpuAttr);
9367 auto TargetFeaturesAttr = ParentFn->
getFnAttribute(
"target-features");
9368 if (TargetFeaturesAttr.isStringAttribute())
9369 Func->addFnAttr(TargetFeaturesAttr);
9374 OMPBuilder.
emitUsed(
"llvm.compiler.used", {ExecMode});
9384 Builder.SetCurrentDebugLocation(OutlinedFnLoc);
9388 Builder.SetInsertPoint(EntryBB);
9399 BasicBlock *UserCodeEntryBB = Builder.GetInsertBlock();
9409 splitBB(Builder,
true,
"outlined.body");
9411 CBFunc(Builder.saveIP(), OutlinedBodyBB->
begin(), ExitBB);
9414 Builder.SetInsertPoint(ExitBB);
9422 Builder.SetCurrentDebugLocation(OutlinedFnLoc);
9429 Builder.CreateRetVoid();
9433 auto AllocaIP = Builder.saveIP();
9438 const auto &ArgRange =
make_range(Func->arg_begin(), Func->arg_end() - 1);
9470 if (Instr->getFunction() == Func)
9471 Instr->replaceUsesOfWith(
Input, InputCopy);
9477 for (
auto InArg :
zip(Inputs, ArgRange)) {
9479 Argument &Arg = std::get<1>(InArg);
9480 Value *InputCopy =
nullptr;
9483 Arg,
Input, InputCopy, AllocaIP, Builder.saveIP(), ExitBB->
begin());
9486 Builder.restoreIP(*AfterIP);
9487 ValueReplacementMap[
Input] = std::make_tuple(InputCopy, Arg.
getArgNo());
9507 DeferredReplacement.push_back(std::make_pair(
Input, InputCopy));
9514 ReplaceValue(
Input, InputCopy, Func);
9518 for (
auto Deferred : DeferredReplacement)
9519 ReplaceValue(std::get<0>(Deferred), std::get<1>(Deferred), Func);
9522 ValueReplacementMap);
9530 Value *TaskWithPrivates,
9531 Type *TaskWithPrivatesTy) {
9533 Type *TaskTy = OMPIRBuilder.Task;
9536 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 0);
9537 Value *Shareds = TaskT;
9547 if (TaskWithPrivatesTy != TaskTy)
9548 Shareds = Builder.CreateStructGEP(TaskTy, TaskT, 0);
9565 const size_t NumOffloadingArrays,
const int SharedArgsOperandNo) {
9570 assert((!NumOffloadingArrays || PrivatesTy) &&
9571 "PrivatesTy cannot be nullptr when there are offloadingArrays"
9601 Type *TaskPtrTy = OMPBuilder.TaskPtr;
9602 [[maybe_unused]]
Type *TaskTy = OMPBuilder.Task;
9608 ".omp_target_task_proxy_func", M);
9609 Value *ThreadId = ProxyFn->getArg(0);
9610 Value *TaskWithPrivates = ProxyFn->getArg(1);
9611 ThreadId->
setName(
"thread.id");
9612 TaskWithPrivates->
setName(
"task");
9614 bool HasShareds = SharedArgsOperandNo > 0;
9615 bool HasOffloadingArrays = NumOffloadingArrays > 0;
9619 Builder.SetInsertPoint(EntryBB);
9626 if (HasOffloadingArrays) {
9627 assert(TaskTy != TaskWithPrivatesTy &&
9628 "If there are offloading arrays to pass to the target"
9629 "TaskTy cannot be the same as TaskWithPrivatesTy");
9632 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 1);
9633 for (
unsigned int i = 0; i < NumOffloadingArrays; ++i)
9635 Builder.CreateStructGEP(PrivatesTy, Privates, i));
9639 auto *ArgStructAlloca =
9641 assert(ArgStructAlloca &&
9642 "Unable to find the alloca instruction corresponding to arguments "
9643 "for extracted function");
9645 std::optional<TypeSize> ArgAllocSize =
9647 assert(ArgStructType && ArgAllocSize &&
9648 "Unable to determine size of arguments for extracted function");
9649 uint64_t StructSize = ArgAllocSize->getFixedValue();
9652 Builder.CreateAlloca(ArgStructType,
nullptr,
"structArg");
9654 Value *SharedsSize = Builder.getInt64(StructSize);
9657 OMPBuilder, Builder, TaskWithPrivates, TaskWithPrivatesTy);
9659 Builder.CreateMemCpy(
9660 NewArgStructAlloca, NewArgStructAlloca->
getAlign(), LoadShared,
9662 KernelLaunchArgs.
push_back(NewArgStructAlloca);
9665 Builder.CreateRetVoid();
9671 return GEP->getSourceElementType();
9673 return Alloca->getAllocatedType();
9696 if (OffloadingArraysToPrivatize.
empty())
9697 return OMPIRBuilder.Task;
9700 for (
Value *V : OffloadingArraysToPrivatize) {
9701 assert(V->getType()->isPointerTy() &&
9702 "Expected pointer to array to privatize. Got a non-pointer value "
9705 assert(ArrayTy &&
"ArrayType cannot be nullptr");
9711 "struct.task_with_privates");
9726 EntryFnName, Inputs, CBFunc,
9727 ArgAccessorFuncCB, OutlinedFnLoc);
9731 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
9870 auto OI = std::make_unique<OutlineInfo>();
9871 OI->EntryBB = TargetTaskAllocaBB;
9872 OI->OuterAllocBB = AllocaIP.getNodeParent();
9877 Builder, AllocaIP, ToBeDeleted, TargetTaskAllocaIP,
"global.tid",
false));
9880 Builder.restoreIP(TargetTaskBodyIP);
9881 if (
Error Err = TaskBodyCB(DeviceID, RTLoc, TargetTaskAllocaIP))
9899 bool NeedsTargetTask = HasNoWait && DeviceID;
9900 if (NeedsTargetTask) {
9906 OffloadingArraysToPrivatize.
push_back(V);
9907 OI->ExcludeArgsFromAggregate.push_back(V);
9911 OI->PostOutlineCB = [
this, ToBeDeleted, Dependencies, NeedsTargetTask,
9912 DeviceID, OffloadingArraysToPrivatize](
9915 "there must be a single user for the outlined function");
9929 const unsigned int NumStaleCIArgs = StaleCI->
arg_size();
9930 bool HasShareds = NumStaleCIArgs > OffloadingArraysToPrivatize.
size() + 1;
9932 NumStaleCIArgs == (OffloadingArraysToPrivatize.
size() + 2)) &&
9933 "Wrong number of arguments for StaleCI when shareds are present");
9934 int SharedArgOperandNo =
9935 HasShareds ? OffloadingArraysToPrivatize.
size() + 1 : 0;
9941 if (!OffloadingArraysToPrivatize.
empty())
9946 *
this,
Builder, StaleCI, PrivatesTy, TaskWithPrivatesTy,
9947 OffloadingArraysToPrivatize.
size(), SharedArgOperandNo);
9949 LLVM_DEBUG(
dbgs() <<
"Proxy task entry function created: " << *ProxyFn
9952 Builder.SetInsertPoint(StaleCI);
9969 OMPRTL___kmpc_omp_target_task_alloc);
9981 M.getDataLayout().getTypeStoreSize(TaskWithPrivatesTy));
9988 auto *ArgStructAlloca =
9990 assert(ArgStructAlloca &&
9991 "Unable to find the alloca instruction corresponding to arguments "
9992 "for extracted function");
9993 std::optional<TypeSize> ArgAllocSize =
9996 "Unable to determine size of arguments for extracted function");
9997 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
10016 TaskSize, SharedsSize,
10019 if (NeedsTargetTask) {
10020 assert(DeviceID &&
"Expected non-empty device ID.");
10030 *
this,
Builder, TaskData, TaskWithPrivatesTy);
10034 if (!OffloadingArraysToPrivatize.
empty()) {
10036 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskData, 1);
10037 for (
unsigned int i = 0; i < OffloadingArraysToPrivatize.
size(); ++i) {
10038 Value *PtrToPrivatize = OffloadingArraysToPrivatize[i];
10045 "ElementType should match ArrayType");
10048 Value *Dst =
Builder.CreateStructGEP(PrivatesTy, Privates, i);
10051 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(ElementType)));
10055 Value *DepArray =
nullptr;
10056 Value *NumDeps =
nullptr;
10059 NumDeps = Dependencies.
NumDeps;
10060 }
else if (!Dependencies.
Deps.empty()) {
10062 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
10073 if (!NeedsTargetTask) {
10082 ConstantInt::get(
Builder.getInt32Ty(), 0),
10095 }
else if (DepArray) {
10103 {Ident, ThreadID, TaskData, NumDeps, DepArray,
10104 ConstantInt::get(
Builder.getInt32Ty(), 0),
10112 Builder.ClearInsertionPoint();
10115 I->eraseFromParent();
10120 << *(
Builder.GetInsertBlock()) <<
"\n");
10122 << *(
Builder.getModule()) <<
"\n");
10133 CustomMapperCB, IsNonContiguous, DeviceAddrCB))
10156 Builder.restoreIP(IP);
10162 return Builder.saveIP();
10165 bool HasDependencies = !Dependencies.
empty();
10166 bool RequiresOuterTargetTask = HasNoWait || HasDependencies;
10183 if (OutlinedFnID && DeviceID)
10185 EmitTargetCallFallbackCB, KArgs,
10186 DeviceID, RTLoc, TargetTaskAllocaIP);
10194 return EmitTargetCallFallbackCB(OMPBuilder.
Builder.
saveIP());
10201 auto &&EmitTargetCallElse =
10208 if (RequiresOuterTargetTask) {
10215 Dependencies, EmptyRTArgs, HasNoWait);
10217 return EmitTargetCallFallbackCB(Builder.saveIP());
10220 Builder.restoreIP(AfterIP);
10224 auto &&EmitTargetCallThen =
10228 Info.HasNoWait = HasNoWait;
10233 AllocaIP, Builder.saveIP(), Info, RTArgs, MapInfo, CustomMapperCB,
10239 for (
auto [DefaultVal, RuntimeVal] :
10241 NumTeamsC.
push_back(RuntimeVal ? RuntimeVal
10242 : Builder.getInt32(DefaultVal));
10246 auto InitMaxThreadsClause = [&Builder](
Value *
Clause) {
10248 Clause = Builder.CreateIntCast(
Clause, Builder.getInt32Ty(),
10252 auto CombineMaxThreadsClauses = [&Builder](
Value *
Clause,
Value *&Result) {
10255 Result ? Builder.CreateSelect(Builder.CreateICmpULT(Result,
Clause),
10263 Value *MaxThreadsClause =
10265 ? InitMaxThreadsClause(RuntimeAttrs.
MaxThreads.front())
10268 for (
auto [TeamsVal, TargetVal] :
zip_equal(
10270 Value *TeamsThreadLimitClause = InitMaxThreadsClause(TeamsVal);
10271 Value *NumThreads = InitMaxThreadsClause(TargetVal);
10273 CombineMaxThreadsClauses(TeamsThreadLimitClause, NumThreads);
10274 CombineMaxThreadsClauses(MaxThreadsClause, NumThreads);
10276 NumThreadsC.
push_back(NumThreads ? NumThreads : Builder.getInt32(0));
10279 unsigned NumTargetItems = Info.NumberOfPtrs;
10280 Value *RTLoc = RTLocOverride;
10291 Builder.getInt64Ty(),
10293 : Builder.getInt64(0);
10297 DynCGroupMem = Builder.getInt32(0);
10300 NumTargetItems, RTArgs, TripCount, NumTeamsC, NumThreadsC, DynCGroupMem,
10301 HasNoWait,
false,
false,
10302 DynCGroupMemFallback);
10309 if (RequiresOuterTargetTask)
10311 RTLoc, AllocaIP, Dependencies,
10312 KArgs.
RTArgs, Info.HasNoWait);
10315 Builder, OutlinedFnID, EmitTargetCallFallbackCB, KArgs,
10316 RuntimeAttrs.
DeviceID, RTLoc, AllocaIP);
10319 Builder.restoreIP(AfterIP);
10326 if (!OutlinedFnID) {
10327 cantFail(EmitTargetCallElse(AllocaIP, Builder.saveIP(), DeallocBlocks));
10333 cantFail(EmitTargetCallThen(AllocaIP, Builder.saveIP(), DeallocBlocks));
10338 EmitTargetCallElse, AllocaIP));
10351 bool HasNowait,
Value *DynCGroupMem,
10353 Value *RTLocOverride) {
10358 Builder.restoreIP(CodeGenIP);
10366 *
this,
Builder, IsOffloadEntry, EntryInfo, DefaultAttrs, OutlinedFn,
10367 OutlinedFnID, Inputs, CBFunc, ArgAccessorFuncCB, OutlinedFnLoc))
10373 if (!
Config.isTargetDevice())
10375 DefaultAttrs, RuntimeAttrs, IfCond, OutlinedFn, OutlinedFnID,
10376 Inputs, GenMapInfoCB, CustomMapperCB, Dependencies,
10377 HasNowait, DynCGroupMem, DynCGroupMemFallback);
10391 return OS.
str().str();
10396 return OpenMPIRBuilder::getNameWithSeparators(Parts,
Config.firstSeparator(),
10402 auto &Elem = *
InternalVars.try_emplace(Name,
nullptr).first;
10404 assert(Elem.second->getValueType() == Ty &&
10405 "OMP internal variable has different type than requested");
10418 :
M.getTargetTriple().isAMDGPU()
10420 :
DL.getDefaultGlobalsAddressSpace();
10421 auto Linkage = this->
M.getTargetTriple().isWasm()
10429 const llvm::Align PtrAlign =
DL.getPointerABIAlignment(AddressSpaceVal);
10430 GV->setAlignment(std::max(TypeAlign, PtrAlign));
10434 return Elem.second;
10437Value *OpenMPIRBuilder::getOMPCriticalRegionLock(
StringRef CriticalName) {
10438 std::string Prefix =
Twine(
"gomp_critical_user_", CriticalName).
str();
10439 std::string Name = getNameWithSeparators({Prefix,
"var"},
".",
".");
10450 return SizePtrToInt;
10455 std::string VarName) {
10463 return MaptypesArrayGlobal;
10468 unsigned NumOperands,
10477 ArrI8PtrTy,
nullptr,
".offload_baseptrs");
10481 ArrI64Ty,
nullptr,
".offload_sizes");
10492 int64_t DeviceID,
unsigned NumOperands) {
10498 Value *ArgsBaseGEP =
10500 {Builder.getInt32(0), Builder.getInt32(0)});
10503 {Builder.getInt32(0), Builder.getInt32(0)});
10504 Value *ArgSizesGEP =
10506 {Builder.getInt32(0), Builder.getInt32(0)});
10510 Builder.getInt32(NumOperands),
10511 ArgsBaseGEP, ArgsGEP, ArgSizesGEP,
10512 MaptypesArg, MapnamesArg, NullPtr});
10519 assert((!ForEndCall || Info.separateBeginEndCalls()) &&
10520 "expected region end call to runtime only when end call is separate");
10522 auto VoidPtrTy = UnqualPtrTy;
10523 auto VoidPtrPtrTy = UnqualPtrTy;
10525 auto Int64PtrTy = UnqualPtrTy;
10527 if (!Info.NumberOfPtrs) {
10539 Info.RTArgs.BasePointersArray,
10542 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray,
10546 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
10550 ForEndCall && Info.RTArgs.MapTypesArrayEnd ? Info.RTArgs.MapTypesArrayEnd
10551 : Info.RTArgs.MapTypesArray,
10557 if (!Info.EmitDebug)
10561 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.MapNamesArray,
10566 if (!Info.HasMapper)
10570 Builder.CreatePointerCast(Info.RTArgs.MappersArray, VoidPtrPtrTy);
10591 "struct.descriptor_dim");
10593 enum { OffsetFD = 0, CountFD, StrideFD };
10597 for (
unsigned I = 0, L = 0, E = NonContigInfo.
Dims.
size();
I < E; ++
I) {
10600 if (NonContigInfo.
Dims[
I] == 1)
10605 Builder.CreateAlloca(ArrayTy,
nullptr,
"dims");
10606 Builder.restoreIP(CodeGenIP);
10607 for (
unsigned II = 0, EE = NonContigInfo.
Dims[
I];
II < EE; ++
II) {
10608 unsigned RevIdx = EE -
II - 1;
10612 Value *OffsetLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, OffsetFD);
10614 NonContigInfo.
Offsets[L][RevIdx], OffsetLVal,
10615 M.getDataLayout().getPrefTypeAlign(OffsetLVal->
getType()));
10617 Value *CountLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, CountFD);
10619 NonContigInfo.
Counts[L][RevIdx], CountLVal,
10620 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10622 Value *StrideLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, StrideFD);
10624 NonContigInfo.
Strides[L][RevIdx], StrideLVal,
10625 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10628 Builder.restoreIP(CodeGenIP);
10629 Value *DAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
10630 DimsAddr,
Builder.getPtrTy());
10633 Info.RTArgs.PointersArray, 0,
I);
10635 DAddr,
P,
M.getDataLayout().getPrefTypeAlign(
Builder.getPtrTy()));
10640void OpenMPIRBuilder::emitUDMapperArrayInitOrDel(
10644 StringRef Prefix = IsInit ?
".init" :
".del";
10650 Builder.CreateICmpSGT(
Size, Builder.getInt64(1),
"omp.arrayinit.isarray");
10651 Value *DeleteBit = Builder.CreateAnd(
10654 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10655 OpenMPOffloadMappingFlags::OMP_MAP_DELETE)));
10660 Value *BaseIsBegin = Builder.CreateICmpNE(
Base, Begin);
10661 Cond = Builder.CreateOr(IsArray, BaseIsBegin);
10662 DeleteCond = Builder.CreateIsNull(
10667 DeleteCond =
Builder.CreateIsNotNull(
10683 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10684 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10685 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10686 MapTypeArg =
Builder.CreateOr(
10689 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10690 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT)));
10694 Value *OffloadingArgs[] = {MapperHandle,
Base, Begin,
10695 ArraySize, MapTypeArg, MapName};
10706 bool PreserveMemberOfFlags,
bool PropagatePresentToPointee) {
10722 MapperFn->
addFnAttr(Attribute::NoInline);
10723 MapperFn->
addFnAttr(Attribute::NoUnwind);
10734 Builder.SetInsertPoint(EntryBB);
10749 Value *PtrBegin = BeginIn;
10755 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
10756 MapType, MapName, ElementSize, HeadBB,
10767 Builder.CreateICmpEQ(PtrBegin, PtrEnd,
"omp.arraymap.isempty");
10768 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
10774 Builder.CreatePHI(PtrBegin->
getType(), 2,
"omp.arraymap.ptrcurrent");
10775 PtrPHI->addIncoming(PtrBegin, HeadBB);
10780 return Info.takeError();
10784 Value *OffloadingArgs[] = {MapperHandle};
10788 Value *ShiftedPreviousSize =
10792 for (
unsigned I = 0;
I < Info->BasePointers.size(); ++
I) {
10793 Value *CurBaseArg = Info->BasePointers[
I];
10794 Value *CurBeginArg = Info->Pointers[
I];
10795 Value *CurSizeArg = Info->Sizes[
I];
10796 Value *CurNameArg = Info->Names.size()
10801 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10804 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10806 constexpr uint64_t MemberOfMask =
10807 static_cast<uint64_t
>(OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
10808 constexpr uint64_t AttachBit =
10809 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10810 OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
10868 Value *MemberMapType;
10869 if (PreserveMemberOfFlags || (RawType & AttachBit) ||
10870 Info->HasAttachPtr[
I]) {
10871 if (RawType & MemberOfMask)
10872 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
10874 MemberMapType = OriMapType;
10876 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
10894 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10895 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10896 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10906 Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
10912 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10913 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10914 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10920 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10921 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
10922 Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
10928 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10929 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10935 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10936 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10937 Builder.CreateCondBr(IsFrom, FromBB, EndBB);
10943 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10944 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
10953 CurMapType->
addIncoming(MemberMapType, ToElseBB);
10990 uint64_t ModifierBits =
10991 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10992 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
10993 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
10994 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
10995 if (PropagatePresentToPointee && Info->HasAttachPtr[
I])
10997 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10998 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
10999 Value *ImportedModifierBits =
11002 CurMapType, ImportedModifierBits,
"omp.maptype.with.modifiers");
11007 Value *FinalMapType =
11008 (RawType & AttachBit) ? CurMapType : CurMapTypeWithModifiers;
11010 Value *OffloadingArgs[] = {MapperHandle, CurBaseArg, CurBeginArg,
11011 CurSizeArg, FinalMapType, CurNameArg};
11013 auto ChildMapperFn = CustomMapperCB(
I);
11014 if (!ChildMapperFn)
11015 return ChildMapperFn.takeError();
11016 if (*ChildMapperFn) {
11032 "omp.arraymap.next");
11033 PtrPHI->addIncoming(PtrNext, LastBB);
11034 Value *IsDone =
Builder.CreateICmpEQ(PtrNext, PtrEnd,
"omp.arraymap.isdone");
11036 Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
11041 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
11042 MapType, MapName, ElementSize, DoneBB,
11055 bool IsNonContiguous,
11059 Info.clearArrayInfo();
11062 if (Info.NumberOfPtrs == 0)
11071 Info.RTArgs.BasePointersArray =
Builder.CreateAlloca(
11072 PointerArrayType,
nullptr,
".offload_baseptrs");
11074 Info.RTArgs.PointersArray =
Builder.CreateAlloca(
11075 PointerArrayType,
nullptr,
".offload_ptrs");
11077 PointerArrayType,
nullptr,
".offload_mappers");
11078 Info.RTArgs.MappersArray = MappersArray;
11085 ConstantInt::get(Int64Ty, 0));
11087 for (
unsigned I = 0, E = CombinedInfo.
Sizes.
size();
I < E; ++
I) {
11088 bool IsNonContigEntry =
11090 (
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11092 OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG) != 0);
11095 if (IsNonContigEntry) {
11097 "Index must be in-bounds for NON_CONTIG Dims array");
11099 assert(DimCount > 0 &&
"NON_CONTIG DimCount must be > 0");
11100 ConstSizes[
I] = ConstantInt::get(Int64Ty, DimCount);
11105 ConstSizes[
I] = CI;
11109 RuntimeSizes.
set(
I);
11112 if (RuntimeSizes.
all()) {
11114 Info.RTArgs.SizesArray =
Builder.CreateAlloca(
11115 SizeArrayType,
nullptr,
".offload_sizes");
11121 auto *SizesArrayGbl =
11126 if (!RuntimeSizes.
any()) {
11127 Info.RTArgs.SizesArray = SizesArrayGbl;
11129 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
11130 Align OffloadSizeAlign =
M.getDataLayout().getABIIntegerTypeAlignment(64);
11133 SizeArrayType,
nullptr,
".offload_sizes");
11137 Buffer,
M.getDataLayout().getPrefTypeAlign(Buffer->
getType()),
11138 SizesArrayGbl, OffloadSizeAlign,
11143 Info.RTArgs.SizesArray = Buffer;
11151 for (
auto mapFlag : CombinedInfo.
Types)
11153 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11157 Info.RTArgs.MapTypesArray = MapTypesArrayGbl;
11163 Info.RTArgs.MapNamesArray = MapNamesArrayGbl;
11164 Info.EmitDebug =
true;
11166 Info.RTArgs.MapNamesArray =
11168 Info.EmitDebug =
false;
11173 if (Info.separateBeginEndCalls()) {
11174 bool EndMapTypesDiffer =
false;
11175 for (uint64_t &
Type : Mapping) {
11176 if (
Type &
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11177 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT)) {
11178 Type &= ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
11179 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
11180 EndMapTypesDiffer =
true;
11183 if (EndMapTypesDiffer) {
11185 Info.RTArgs.MapTypesArrayEnd = MapTypesArrayGbl;
11190 for (
unsigned I = 0;
I < Info.NumberOfPtrs; ++
I) {
11193 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.BasePointersArray,
11195 Builder.CreateAlignedStore(BPVal, BP,
11196 M.getDataLayout().getPrefTypeAlign(PtrTy));
11198 if (Info.requiresDevicePointerInfo()) {
11200 CodeGenIP =
Builder.saveIP();
11202 Info.DevicePtrInfoMap[BPVal] = {BP,
Builder.CreateAlloca(PtrTy)};
11205 DeviceAddrCB(
I, Info.DevicePtrInfoMap[BPVal].second);
11207 Info.DevicePtrInfoMap[BPVal] = {BP, BP};
11209 DeviceAddrCB(
I, BP);
11215 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray, 0,
11218 Builder.CreateAlignedStore(PVal,
P,
11219 M.getDataLayout().getPrefTypeAlign(PtrTy));
11221 if (RuntimeSizes.
test(
I)) {
11223 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
11229 S,
M.getDataLayout().getPrefTypeAlign(PtrTy));
11232 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
11235 auto CustomMFunc = CustomMapperCB(
I);
11237 return CustomMFunc.takeError();
11239 MFunc =
Builder.CreatePointerCast(*CustomMFunc, PtrTy);
11242 PointerArrayType, MappersArray,
11245 MFunc, MAddr,
M.getDataLayout().getPrefTypeAlign(MAddr->
getType()));
11249 Info.NumberOfPtrs == 0)
11266 Builder.ClearInsertionPoint();
11297 auto CondConstant = CI->getSExtValue();
11299 return ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
11301 return ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
11311 Builder.CreateCondBr(
Cond, ThenBlock, ElseBlock);
11314 if (
Error Err = ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks))
11320 if (
Error Err = ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks))
11329bool OpenMPIRBuilder::checkAndEmitFlushAfterAtomic(
11333 "Unexpected Atomic Ordering.");
11335 bool Flush =
false;
11397 assert(
X.Var->getType()->isPointerTy() &&
11398 "OMP Atomic expects a pointer to target memory");
11399 Type *XElemTy =
X.ElemTy;
11402 "OMP atomic read expected a scalar type");
11404 Value *XRead =
nullptr;
11408 Builder.CreateLoad(XElemTy,
X.Var,
X.IsVolatile,
"omp.atomic.read");
11417 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11420 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11422 XRead = AtomicLoadRes.first;
11429 Builder.CreateLoad(IntCastTy,
X.Var,
X.IsVolatile,
"omp.atomic.load");
11432 XRead =
Builder.CreateBitCast(XLoad, XElemTy,
"atomic.flt.cast");
11434 XRead =
Builder.CreateIntToPtr(XLoad, XElemTy,
"atomic.ptr.cast");
11437 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Read);
11438 Builder.CreateStore(XRead, V.Var, V.IsVolatile);
11449 assert(
X.Var->getType()->isPointerTy() &&
11450 "OMP Atomic expects a pointer to target memory");
11451 Type *XElemTy =
X.ElemTy;
11454 "OMP atomic write expected a scalar type");
11462 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11465 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11473 Builder.CreateBitCast(Expr, IntCastTy,
"atomic.src.int.cast");
11478 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Write);
11485 AtomicUpdateCallbackTy &UpdateOp,
bool IsXBinopExpr,
11486 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11492 Type *XTy =
X.Var->getType();
11494 "OMP Atomic expects a pointer to target memory");
11495 Type *XElemTy =
X.ElemTy;
11498 "OMP atomic update expected a scalar or struct type");
11501 "OpenMP atomic does not support LT or GT operations");
11505 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, RMWOp, UpdateOp,
X.IsVolatile,
11506 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11508 return AtomicResult.takeError();
11509 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Update);
11514Value *OpenMPIRBuilder::emitRMWOpAsInstruction(
Value *Src1,
Value *Src2,
11518 return Builder.CreateAdd(Src1, Src2);
11520 return Builder.CreateSub(Src1, Src2);
11522 return Builder.CreateAnd(Src1, Src2);
11524 return Builder.CreateNeg(Builder.CreateAnd(Src1, Src2));
11526 return Builder.CreateOr(Src1, Src2);
11528 return Builder.CreateXor(Src1, Src2);
11567Expected<std::pair<Value *, Value *>> OpenMPIRBuilder::emitAtomicUpdate(
11570 AtomicUpdateCallbackTy &UpdateOp,
bool VolatileX,
bool IsXBinopExpr,
11571 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11573 bool emitRMWOp =
false;
11581 emitRMWOp = XElemTy;
11584 emitRMWOp = (IsXBinopExpr && XElemTy);
11591 std::pair<Value *, Value *> Res;
11593 AtomicRMWInst *RMWInst =
11594 Builder.CreateAtomicRMW(RMWOp,
X, Expr, llvm::MaybeAlign(), AO);
11595 if (IsIgnoreDenormalMode)
11596 RMWInst->
setMetadata(llvm::LLVMContext::MD_atomic_ignore_denormal_mode,
11598 if (
T.isAMDGPU()) {
11599 if (!IsFineGrainedMemory)
11600 RMWInst->
setMetadata(
"amdgpu.no.fine.grained.memory",
11602 if (!IsRemoteMemory)
11606 Res.first = RMWInst;
11611 Res.second = Res.first;
11613 Res.second = emitRMWOpAsInstruction(Res.first, Expr, RMWOp);
11616 Builder.CreateLoad(XElemTy,
X,
X->getName() +
".atomic.load");
11622 OpenMPIRBuilder::AtomicInfo atomicInfo(
11624 OldVal->
getAlign(),
true , AllocaIP,
X);
11625 auto AtomicLoadRes = atomicInfo.EmitAtomicLoadLibcall(AO);
11628 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11635 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11636 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11637 Builder.SetInsertPoint(ContBB);
11639 PHI->addIncoming(AtomicLoadRes.first, CurBB);
11641 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11644 Value *Upd = *CBResult;
11645 Builder.CreateStore(Upd, NewAtomicAddr);
11648 auto Result = atomicInfo.EmitAtomicCompareExchangeLibcall(
11649 AtomicLoadRes.second, NewAtomicAddr, AO, Failure);
11650 LoadInst *PHILoad =
Builder.CreateLoad(XElemTy,
Result.first);
11651 PHI->addIncoming(PHILoad,
Builder.GetInsertBlock());
11654 Res.first = OldExprVal;
11657 if (UnreachableInst *ExitTI =
11660 Builder.SetInsertPoint(ExitBB);
11662 Builder.SetInsertPoint(ExitTI);
11665 IntegerType *IntCastTy =
11668 Builder.CreateLoad(IntCastTy,
X,
X->getName() +
".atomic.load");
11678 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11685 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11686 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11687 Builder.SetInsertPoint(ContBB);
11689 PHI->addIncoming(OldVal, CurBB);
11694 OldExprVal =
Builder.CreateBitCast(
PHI, XElemTy,
11695 X->getName() +
".atomic.fltCast");
11697 OldExprVal =
Builder.CreateIntToPtr(
PHI, XElemTy,
11698 X->getName() +
".atomic.ptrCast");
11702 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11705 Value *Upd = *CBResult;
11706 Builder.CreateStore(Upd, NewAtomicAddr);
11707 LoadInst *DesiredVal =
Builder.CreateLoad(IntCastTy, NewAtomicAddr);
11711 X,
PHI, DesiredVal, llvm::MaybeAlign(), AO, Failure);
11712 Result->setVolatile(VolatileX);
11713 Value *PreviousVal =
Builder.CreateExtractValue(Result, 0);
11714 Value *SuccessFailureVal =
Builder.CreateExtractValue(Result, 1);
11715 PHI->addIncoming(PreviousVal,
Builder.GetInsertBlock());
11716 Builder.CreateCondBr(SuccessFailureVal, ExitBB, ContBB);
11718 Res.first = OldExprVal;
11722 if (UnreachableInst *ExitTI =
11725 Builder.SetInsertPoint(ExitBB);
11727 Builder.SetInsertPoint(ExitTI);
11738 bool UpdateExpr,
bool IsPostfixUpdate,
bool IsXBinopExpr,
11739 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11744 Type *XTy =
X.Var->getType();
11746 "OMP Atomic expects a pointer to target memory");
11747 Type *XElemTy =
X.ElemTy;
11750 "OMP atomic capture expected a scalar or struct type");
11752 "OpenMP atomic does not support LT or GT operations");
11759 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, AtomicOp, UpdateOp,
X.IsVolatile,
11760 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11763 Value *CapturedVal =
11764 (IsPostfixUpdate ? AtomicResult->first : AtomicResult->second);
11765 Builder.CreateStore(CapturedVal, V.Var, V.IsVolatile);
11767 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Capture);
11775 bool IsFailOnly,
bool IsWeak) {
11779 IsPostfixUpdate, IsFailOnly, Failure, IsWeak);
11791 assert(
X.Var->getType()->isPointerTy() &&
11792 "OMP atomic expects a pointer to target memory");
11795 assert(V.Var->getType()->isPointerTy() &&
"v.var must be of pointer type");
11796 assert(V.ElemTy ==
X.ElemTy &&
"x and v must be of same type");
11799 bool IsInteger = E->getType()->isIntegerTy();
11801 if (
Op == OMPAtomicCompareOp::EQ) {
11804 Value *OldValue =
nullptr;
11805 Value *SuccessOrFail =
nullptr;
11843 X.Var->getName() +
".atomic.load");
11849 Value *EIsNaN =
Builder.CreateFCmpUNO(E, E,
"atomic.e.isnan");
11850 Value *XIsNaN =
Builder.CreateFCmpUNO(XFP, XFP,
"atomic.x.isnan");
11851 Value *EitherNaN =
Builder.CreateOr(EIsNaN, XIsNaN,
"atomic.either.nan");
11856 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11860 M.getContext(),
X.Var->getName() +
".atomic.nan",
F, ExitBB);
11862 M.getContext(),
X.Var->getName() +
".atomic.notnan",
F, ExitBB);
11864 M.getContext(),
X.Var->getName() +
".atomic.zero",
F, ExitBB);
11866 M.getContext(),
X.Var->getName() +
".atomic.normal",
F, ExitBB);
11870 Builder.SetInsertPoint(CurBB);
11871 Builder.CreateCondBr(EitherNaN, NaNBB, NotNaNBB);
11874 Builder.SetInsertPoint(NaNBB);
11878 Builder.SetInsertPoint(NotNaNBB);
11881 X.Var->getName() +
".atomic.xiszero");
11883 "atomic.e.iszero");
11884 Value *BothZero =
Builder.CreateAnd(XIsZero, EIsZero,
"atomic.both.zero");
11885 Builder.CreateCondBr(BothZero, ZeroBB, NormalBB);
11888 Builder.SetInsertPoint(ZeroBB);
11890 X.Var, XCurr, DBCast,
MaybeAlign(), AO, Failure);
11892 Value *OldZero =
Builder.CreateExtractValue(ResZero, 0);
11893 Value *OkZero =
Builder.CreateExtractValue(ResZero, 1);
11897 Builder.SetInsertPoint(NormalBB);
11899 X.Var, EBCast, DBCast,
MaybeAlign(), AO, Failure);
11901 Value *OldNormal =
Builder.CreateExtractValue(ResNormal, 0);
11902 Value *OkNormal =
Builder.CreateExtractValue(ResNormal, 1);
11908 Builder.CreatePHI(IntCastTy, 3,
X.Var->getName() +
".atomic.old");
11913 X.Var->getName() +
".atomic.ok");
11920 Builder.SetInsertPoint(ExitBB);
11925 OldValue =
Builder.CreateBitCast(OldIntPHI,
X.ElemTy,
11926 X.Var->getName() +
".atomic.old.fp");
11927 SuccessOrFail = SuccessPHI;
11935 Result =
Builder.CreateAtomicCmpXchg(
X.Var, EBCast, DBCast,
11941 Result->setWeak(IsWeak);
11944 OldValue =
Builder.CreateExtractValue(Result, 0);
11946 OldValue =
Builder.CreateBitCast(OldValue,
X.ElemTy);
11948 "OldValue and V must be of same type");
11949 if (IsPostfixUpdate) {
11950 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
11952 SuccessOrFail =
Builder.CreateExtractValue(Result, 1);
11956 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11958 CurBBTI,
X.Var->getName() +
".atomic.exit");
11964 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
11966 Builder.SetInsertPoint(ContBB);
11967 Builder.CreateStore(OldValue, V.Var);
11973 Builder.SetInsertPoint(ExitBB);
11975 Builder.SetInsertPoint(ExitTI);
11978 Value *CapturedValue =
11979 Builder.CreateSelect(SuccessOrFail, E, OldValue);
11980 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
11986 assert(R.Var->getType()->isPointerTy() &&
11987 "r.var must be of pointer type");
11988 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
11990 Value *SuccessFailureVal =
11991 Builder.CreateExtractValue(Result, 1);
11992 Value *ResultCast =
11993 R.IsSigned ?
Builder.CreateSExt(SuccessFailureVal, R.ElemTy)
11994 :
Builder.CreateZExt(SuccessFailureVal, R.ElemTy);
11995 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
12004 "OldValue and V must be of same type");
12005 if (IsPostfixUpdate) {
12006 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
12011 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
12013 CurBBTI,
X.Var->getName() +
".atomic.exit");
12019 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
12021 Builder.SetInsertPoint(ContBB);
12022 Builder.CreateStore(OldValue, V.Var);
12028 Builder.SetInsertPoint(ExitBB);
12030 Builder.SetInsertPoint(ExitTI);
12033 Value *CapturedValue =
12034 Builder.CreateSelect(SuccessOrFail, E, OldValue);
12035 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
12041 assert(R.Var->getType()->isPointerTy() &&
12042 "r.var must be of pointer type");
12043 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
12045 Value *ResultCast = R.IsSigned
12046 ?
Builder.CreateSExt(SuccessOrFail, R.ElemTy)
12047 :
Builder.CreateZExt(SuccessOrFail, R.ElemTy);
12048 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
12052 assert((
Op == OMPAtomicCompareOp::MAX ||
Op == OMPAtomicCompareOp::MIN) &&
12053 "Op should be either max or min at this point");
12054 assert(!IsFailOnly &&
"IsFailOnly is only valid when the comparison is ==");
12065 if (IsXBinopExpr) {
12094 Value *CapturedValue =
nullptr;
12095 if (IsPostfixUpdate) {
12096 CapturedValue = OldValue;
12121 Value *NonAtomicCmp =
Builder.CreateCmp(Pred, OldValue, E);
12122 CapturedValue =
Builder.CreateSelect(NonAtomicCmp, E, OldValue);
12124 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
12128 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Compare);
12148 if (&OuterAllocaBB ==
Builder.GetInsertBlock()) {
12175 bool SubClausesPresent =
12176 (NumTeamsLower || NumTeamsUpper || ThreadLimit || IfExpr);
12178 if (!
Config.isTargetDevice() && SubClausesPresent) {
12179 assert((NumTeamsLower ==
nullptr || NumTeamsUpper !=
nullptr) &&
12180 "if lowerbound is non-null, then upperbound must also be non-null "
12181 "for bounds on num_teams");
12183 if (NumTeamsUpper ==
nullptr)
12184 NumTeamsUpper =
Builder.getInt32(0);
12186 if (NumTeamsLower ==
nullptr)
12187 NumTeamsLower = NumTeamsUpper;
12191 "argument to if clause must be an integer value");
12195 IfExpr =
Builder.CreateICmpNE(IfExpr,
12196 ConstantInt::get(IfExpr->
getType(), 0));
12197 NumTeamsUpper =
Builder.CreateSelect(
12198 IfExpr, NumTeamsUpper,
Builder.getInt32(1),
"numTeamsUpper");
12201 NumTeamsLower =
Builder.CreateSelect(
12202 IfExpr, NumTeamsLower,
Builder.getInt32(1),
"numTeamsLower");
12205 if (ThreadLimit ==
nullptr)
12206 ThreadLimit =
Builder.getInt32(0);
12210 Value *NumTeamsLowerInt32 =
12212 Value *NumTeamsUpperInt32 =
12214 Value *ThreadLimitInt32 =
12221 {Ident, ThreadNum, NumTeamsLowerInt32, NumTeamsUpperInt32,
12222 ThreadLimitInt32});
12227 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
12230 auto OI = std::make_unique<OutlineInfo>();
12231 OI->EntryBB = AllocaBB;
12232 OI->ExitBB = ExitBB;
12233 OI->OuterAllocBB = &OuterAllocaBB;
12239 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"gid",
true));
12241 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"tid",
true));
12243 auto HostPostOutlineCB = [
this, Ident,
12244 ToBeDeleted](
Function &OutlinedFn)
mutable {
12249 "there must be a single user for the outlined function");
12254 "Outlined function must have two or three arguments only");
12256 bool HasShared = OutlinedFn.
arg_size() == 3;
12264 assert(StaleCI &&
"Error while outlining - no CallInst user found for the "
12265 "outlined function.");
12266 Builder.SetInsertPoint(StaleCI);
12273 omp::RuntimeFunction::OMPRTL___kmpc_fork_teams),
12276 Builder.ClearInsertionPoint();
12278 I->eraseFromParent();
12281 if (!
Config.isTargetDevice())
12282 OI->PostOutlineCB = HostPostOutlineCB;
12286 Builder.SetInsertPoint(ExitBB);
12297 BasicBlock *OuterAllocaBB = OuterAllocIP.getNodeParent();
12299 if (OuterAllocaBB ==
Builder.GetInsertBlock()) {
12314 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
12319 if (
Config.isTargetDevice()) {
12320 auto OI = std::make_unique<OutlineInfo>();
12321 OI->OuterAllocBB = OuterAllocIP.getNodeParent();
12322 OI->EntryBB = AllocaBB;
12323 OI->ExitBB = ExitBB;
12324 OI->OuterDeallocBBs.reserve(OuterDeallocBlocks.
size());
12325 copy(OuterDeallocBlocks, OI->OuterDeallocBBs.
end());
12329 Builder.SetInsertPoint(ExitBB);
12336 std::string VarName) {
12345 return MapNamesArrayGlobal;
12350void OpenMPIRBuilder::initializeTypes(
Module &M) {
12354 unsigned ProgramAS = M.getDataLayout().getProgramAddressSpace();
12355#define OMP_TYPE(VarName, InitValue) VarName = InitValue;
12356#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \
12357 VarName##Ty = ArrayType::get(ElemTy, ArraySize); \
12358 VarName##PtrTy = PointerType::get(Ctx, DefaultTargetAS);
12359#define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) \
12360 VarName = FunctionType::get(ReturnType, {__VA_ARGS__}, IsVarArg); \
12361 VarName##Ptr = PointerType::get(Ctx, ProgramAS);
12362#define OMP_STRUCT_TYPE(VarName, StructName, Packed, ...) \
12363 T = StructType::getTypeByName(Ctx, StructName); \
12365 T = StructType::create(Ctx, {__VA_ARGS__}, StructName, Packed); \
12367 VarName##Ptr = PointerType::get(Ctx, DefaultTargetAS);
12368#include "llvm/Frontend/OpenMP/OMPKinds.def"
12379 while (!Worklist.
empty()) {
12383 if (
BlockSet.insert(SuccBB).second)
12388std::unique_ptr<CodeExtractor>
12390 bool ArgsInZeroAddressSpace,
12392 return std::make_unique<CodeExtractor>(
12402 Suffix.
str(), ArgsInZeroAddressSpace);
12405std::unique_ptr<CodeExtractor> DeviceSharedMemOutlineInfo::createCodeExtractor(
12407 return std::make_unique<DeviceSharedMemCodeExtractor>(
12408 OMPBuilder, Blocks,
nullptr,
12416 OuterDeallocBBs.empty()
12419 Suffix.
str(), ArgsInZeroAddressSpace);
12423 uint64_t
Size, int32_t Flags,
12429 Name.empty() ? Addr->
getName() : Name,
Size, Flags, 0);
12441 Fn->
addFnAttr(
"uniform-work-group-size");
12442 Fn->
addFnAttr(Attribute::MustProgress);
12460 auto &&GetMDInt = [
this](
unsigned V) {
12467 NamedMDNode *MD =
M.getOrInsertNamedMetadata(
"omp_offload.info");
12468 auto &&TargetRegionMetadataEmitter =
12469 [&
C, MD, &OrderedEntries, &GetMDInt, &GetMDString](
12484 GetMDInt(E.getKind()), GetMDInt(EntryInfo.DeviceID),
12485 GetMDInt(EntryInfo.FileID), GetMDString(EntryInfo.ParentName),
12486 GetMDInt(EntryInfo.Line), GetMDInt(EntryInfo.Count),
12487 GetMDInt(E.getOrder())};
12490 OrderedEntries[E.getOrder()] = std::make_pair(&E, EntryInfo);
12499 auto &&DeviceGlobalVarMetadataEmitter =
12500 [&
C, &OrderedEntries, &GetMDInt, &GetMDString, MD](
12510 Metadata *
Ops[] = {GetMDInt(E.getKind()), GetMDString(MangledName),
12511 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
12515 OrderedEntries[E.getOrder()] = std::make_pair(&E, varInfo);
12522 DeviceGlobalVarMetadataEmitter);
12524 for (
const auto &E : OrderedEntries) {
12525 assert(E.first &&
"All ordered entries must exist!");
12526 if (
const auto *CE =
12529 if (!CE->getID() || !CE->getAddress()) {
12533 if (!
M.getNamedValue(FnName))
12541 }
else if (
const auto *CE =
dyn_cast<
12550 if (
Config.isTargetDevice() &&
Config.hasRequiresUnifiedSharedMemory())
12552 if (!CE->getAddress()) {
12557 if (CE->getVarSize() == 0)
12561 assert(((
Config.isTargetDevice() && !CE->getAddress()) ||
12562 (!
Config.isTargetDevice() && CE->getAddress())) &&
12563 "Declaret target link address is set.");
12564 if (
Config.isTargetDevice())
12566 if (!CE->getAddress()) {
12573 if (!CE->getAddress()) {
12586 if ((
GV->hasLocalLinkage() ||
GV->hasHiddenVisibility()) &&
12590 OMPTargetGlobalVarEntryIndirectVTable))
12599 Flags, CE->getLinkage(), CE->getVarName());
12602 Flags, CE->getLinkage());
12613 if (
Config.hasRequiresFlags() && !
Config.isTargetDevice())
12619 Config.getRequiresFlags());
12629 OS <<
"_" <<
Count;
12634 unsigned NewCount = getTargetRegionEntryInfoCount(EntryInfo);
12637 EntryInfo.
Line, NewCount);
12645 auto FileIDInfo = CallBack();
12646 uint64_t FileID = 0;
12648 ID =
Status->getUniqueID();
12649 FileID =
Status->getUniqueID().getFile();
12653 FileID =
hash_value(std::get<0>(FileIDInfo));
12657 std::get<1>(FileIDInfo));
12662 for (uint64_t Remain =
12663 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12665 !(Remain & 1); Remain = Remain >> 1)
12683 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12685 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12692 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12698 Flags &=
~omp::OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
12699 Flags |= MemberOfFlag;
12705 bool IsDeclaration,
bool IsExternallyVisible,
12707 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12708 std::vector<Triple> TargetTriple,
Type *LlvmPtrTy,
12709 std::function<
Constant *()> GlobalInitializer,
12720 Config.hasRequiresUnifiedSharedMemory())) {
12725 if (!IsExternallyVisible)
12727 OS <<
"_decl_tgt_ref_ptr";
12730 Value *Ptr =
M.getNamedValue(PtrName);
12739 if (!
Config.isTargetDevice()) {
12740 if (GlobalInitializer)
12741 GV->setInitializer(GlobalInitializer());
12747 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12748 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12749 GlobalInitializer, VariableLinkage, LlvmPtrTy,
cast<Constant>(Ptr));
12761 bool IsDeclaration,
bool IsExternallyVisible,
12763 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12764 std::vector<Triple> TargetTriple,
12765 std::function<
Constant *()> GlobalInitializer,
12769 (TargetTriple.empty() && !
Config.isTargetDevice()))
12780 !
Config.hasRequiresUnifiedSharedMemory()) {
12782 VarName = MangledName;
12785 if (!IsDeclaration)
12787 M.getDataLayout().getTypeSizeInBits(LlvmVal->
getValueType()), 8);
12790 Linkage = (VariableLinkage) ? VariableLinkage() : LlvmVal->
getLinkage();
12794 if (
Config.isTargetDevice() &&
12803 if (!
M.getNamedValue(RefName)) {
12807 GvAddrRef->setConstant(
true);
12809 GvAddrRef->setInitializer(Addr);
12810 GeneratedRefs.push_back(GvAddrRef);
12819 if (
Config.isTargetDevice()) {
12820 VarName = (Addr) ? Addr->
getName() :
"";
12824 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12825 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12826 LlvmPtrTy, GlobalInitializer, VariableLinkage);
12827 VarName = (Addr) ? Addr->
getName() :
"";
12829 VarSize =
M.getDataLayout().getPointerSize();
12848 auto &&GetMDInt = [MN](
unsigned Idx) {
12853 auto &&GetMDString = [MN](
unsigned Idx) {
12855 return V->getString();
12858 switch (GetMDInt(0)) {
12862 case OffloadEntriesInfoManager::OffloadEntryInfo::
12863 OffloadingEntryInfoTargetRegion: {
12873 case OffloadEntriesInfoManager::OffloadEntryInfo::
12874 OffloadingEntryInfoDeviceGlobalVar:
12887 if (HostFilePath.
empty())
12891 if (std::error_code Err = Buf.getError()) {
12893 "OpenMPIRBuilder: " +
12901 if (std::error_code Err =
M.getError()) {
12903 (
"error parsing host file inside of OpenMPIRBuilder: " + Err.message())
12917 "expected a valid insertion block for creating an iterator loop");
12921 if (SplitIP == CurBB->
end())
12923 SplitIP = Terminator->getIterator();
12927 Builder.getCurrentDebugLocation(),
"omp.it.cont");
12939 T->eraseFromParent();
12954 bool ReachesLatch =
false;
12957 while (!Worklist.
empty()) {
12962 "iterator bodygen must leave at most one unterminated block",
12968 if (Succ == Latch) {
12969 ReachesLatch =
true;
12974 "iterator bodygen must not branch out of the loop body",
12976 if (Visited.
insert(Succ).second)
12982 Builder.SetInsertPoint(OpenBB);
12984 }
else if (!ReachesLatch) {
12994 return ContBB->
begin();
13004 for (
const auto &
ParamAttr : ParamAttrs) {
13047 return std::string(Out.str());
13055 unsigned VecRegSize;
13057 ISADataTy ISAData[] = {
13076 for (
char Mask :
Masked) {
13077 for (
const ISADataTy &
Data : ISAData) {
13080 Out <<
"_ZGV" <<
Data.ISA << Mask;
13082 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
13096template <
typename T>
13099 StringRef MangledName,
bool OutputBecomesInput,
13103 Out << Prefix << ISA << LMask << VLEN;
13104 if (OutputBecomesInput)
13106 Out << ParSeq <<
'_' << MangledName;
13115 bool OutputBecomesInput,
13120 OutputBecomesInput, Fn);
13122 OutputBecomesInput, Fn);
13126 OutputBecomesInput, Fn);
13128 OutputBecomesInput, Fn);
13132 OutputBecomesInput, Fn);
13134 OutputBecomesInput, Fn);
13139 OutputBecomesInput, Fn);
13150 char ISA,
unsigned NarrowestDataSize,
bool OutputBecomesInput) {
13151 assert((ISA ==
'n' || ISA ==
's') &&
"Expected ISA either 's' or 'n'.");
13163 OutputBecomesInput, Fn);
13170 OutputBecomesInput, Fn);
13172 OutputBecomesInput, Fn);
13176 OutputBecomesInput, Fn);
13180 OutputBecomesInput, Fn);
13189 OutputBecomesInput, Fn);
13196 MangledName, OutputBecomesInput, Fn);
13198 MangledName, OutputBecomesInput, Fn);
13202 MangledName, OutputBecomesInput, Fn);
13206 MangledName, OutputBecomesInput, Fn);
13216 return OffloadEntriesTargetRegion.empty() &&
13217 OffloadEntriesDeviceGlobalVar.empty();
13220unsigned OffloadEntriesInfoManager::getTargetRegionEntryInfoCount(
13222 auto It = OffloadEntriesTargetRegionCount.find(
13223 getTargetRegionEntryCountKey(EntryInfo));
13224 if (It == OffloadEntriesTargetRegionCount.end())
13229void OffloadEntriesInfoManager::incrementTargetRegionEntryInfoCount(
13231 OffloadEntriesTargetRegionCount[getTargetRegionEntryCountKey(EntryInfo)] =
13232 EntryInfo.
Count + 1;
13238 OffloadEntriesTargetRegion[EntryInfo] =
13241 ++OffloadingEntriesNum;
13247 assert(EntryInfo.
Count == 0 &&
"expected default EntryInfo");
13250 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
13254 if (OMPBuilder->Config.isTargetDevice()) {
13259 auto &Entry = OffloadEntriesTargetRegion[EntryInfo];
13260 Entry.setAddress(Addr);
13262 Entry.setFlags(Flags);
13268 "Target region entry already registered!");
13270 OffloadEntriesTargetRegion[EntryInfo] = Entry;
13271 ++OffloadingEntriesNum;
13273 incrementTargetRegionEntryInfoCount(EntryInfo);
13280 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
13282 auto It = OffloadEntriesTargetRegion.find(EntryInfo);
13283 if (It == OffloadEntriesTargetRegion.end()) {
13287 if (!IgnoreAddressId && (It->second.getAddress() || It->second.getID()))
13295 for (
const auto &It : OffloadEntriesTargetRegion) {
13296 Action(It.first, It.second);
13302 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
13303 ++OffloadingEntriesNum;
13309 if (OMPBuilder->Config.isTargetDevice()) {
13313 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
13315 if (Entry.getVarSize() == 0) {
13316 Entry.setVarSize(VarSize);
13317 Entry.setLinkage(Linkage);
13321 Entry.setVarSize(VarSize);
13322 Entry.setLinkage(Linkage);
13323 Entry.setAddress(Addr);
13326 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
13327 assert(Entry.isValid() && Entry.getFlags() == Flags &&
13328 "Entry not initialized!");
13329 if (Entry.getVarSize() == 0) {
13330 Entry.setVarSize(VarSize);
13331 Entry.setLinkage(Linkage);
13338 OffloadEntriesDeviceGlobalVar.try_emplace(VarName, OffloadingEntriesNum,
13339 Addr, VarSize, Flags, Linkage,
13342 OffloadEntriesDeviceGlobalVar.try_emplace(
13343 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage,
"");
13344 ++OffloadingEntriesNum;
13351 for (
const auto &E : OffloadEntriesDeviceGlobalVar)
13352 Action(E.getKey(), E.getValue());
13359void CanonicalLoopInfo::collectControlBlocks(
13366 BBs.
append({getPreheader(), Header,
Cond, Latch, Exit, getAfter()});
13378void CanonicalLoopInfo::setTripCount(
Value *TripCount) {
13390void CanonicalLoopInfo::mapIndVar(
13400 for (
Use &U : OldIV->
uses()) {
13404 if (
User->getParent() == getCond())
13406 if (
User->getParent() == getLatch())
13412 Value *NewIV = Updater(OldIV);
13415 for (Use *U : ReplacableUses)
13436 "Preheader must terminate with unconditional branch");
13438 "Preheader must jump to header");
13442 "Header must terminate with unconditional branch");
13443 assert(Header->getSingleSuccessor() == Cond &&
13444 "Header must jump to exiting block");
13447 assert(Cond->getSinglePredecessor() == Header &&
13448 "Exiting block only reachable from header");
13451 "Exiting block must terminate with conditional branch");
13453 "Exiting block's first successor jump to the body");
13455 "Exiting block's second successor must exit the loop");
13459 "Body only reachable from exiting block");
13464 "Latch must terminate with unconditional branch");
13465 assert(Latch->getSingleSuccessor() == Header &&
"Latch must jump to header");
13468 assert(Latch->getSinglePredecessor() !=
nullptr);
13473 "Exit block must terminate with unconditional branch");
13474 assert(Exit->getSingleSuccessor() == After &&
13475 "Exit block must jump to after block");
13479 "After block only reachable from exit block");
13483 assert(IndVar &&
"Canonical induction variable not found?");
13485 "Induction variable must be an integer");
13487 "Induction variable must be a PHI in the loop header");
13493 auto *NextIndVar =
cast<PHINode>(IndVar)->getIncomingValue(1);
13501 assert(TripCount &&
"Loop trip count not found?");
13503 "Trip count and induction variable must have the same type");
13507 "Exit condition must be a signed less-than comparison");
13509 "Exit condition must compare the induction variable");
13511 "Exit condition must compare with the trip count");
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
Expand Atomic instructions
This file contains the simple types necessary to represent the attributes associated with functions a...
static const Function * getParent(const Value *V)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
This header defines various interfaces for pass management in LLVM.
iv Induction Variable Users
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
uint64_t IntrinsicInst * II
#define OMP_KERNEL_ARG_VERSION
Provides definitions for Target specific Grid Values.
static void emitTargetCall(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, Value *RTLocOverride, OpenMPIRBuilder::InsertPointTy AllocaIP, ArrayRef< BasicBlock * > DeallocBlocks, OpenMPIRBuilder::TargetDataInfo &Info, const OpenMPIRBuilder::TargetKernelDefaultAttrs &DefaultAttrs, const OpenMPIRBuilder::TargetKernelRuntimeAttrs &RuntimeAttrs, Value *IfCond, Function *OutlinedFn, Constant *OutlinedFnID, SmallVectorImpl< Value * > &Args, OpenMPIRBuilder::GenMapInfoCallbackTy GenMapInfoCB, OpenMPIRBuilder::CustomMapperCallbackTy CustomMapperCB, const OpenMPIRBuilder::DependenciesInfo &Dependencies, bool HasNoWait, Value *DynCGroupMem, OMPDynGroupprivateFallbackType DynCGroupMemFallback)
static Value * removeASCastIfPresent(Value *V)
static void createTargetLoopWorkshareCall(OpenMPIRBuilder *OMPBuilder, WorksharingLoopType LoopType, BasicBlock *InsertBlock, Value *Ident, Value *LoopBodyArg, Value *TripCount, Function &LoopBodyFn, bool NoLoop)
Value * createFakeIntVal(IRBuilderBase &Builder, OpenMPIRBuilder::InsertPointTy OuterAllocaIP, llvm::SmallVectorImpl< Instruction * > &ToBeDeleted, OpenMPIRBuilder::InsertPointTy InnerAllocaIP, const Twine &Name="", bool AsPtr=true, bool Is64Bit=false)
static Function * createTargetParallelWrapper(OpenMPIRBuilder *OMPIRBuilder, Function &OutlinedFn)
Create wrapper function used to gather the outlined function's argument structure from a shared buffe...
static void redirectTo(BasicBlock *Source, BasicBlock *Target, DebugLoc DL)
Make Source branch to Target.
static FunctionCallee getKmpcDistForStaticInitForType(Type *Ty, Module &M, OpenMPIRBuilder &OMPBuilder)
static void applyParallelAccessesMetadata(CanonicalLoopInfo *CLI, LLVMContext &Ctx, Loop *Loop, LoopInfo &LoopInfo, SmallVector< Metadata * > &LoopMDList)
static Expected< Function * > createOutlinedFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, const OpenMPIRBuilder::TargetKernelDefaultAttrs &DefaultAttrs, StringRef FuncName, SmallVectorImpl< Value * > &Inputs, OpenMPIRBuilder::TargetBodyGenCallbackTy &CBFunc, OpenMPIRBuilder::TargetGenArgAccessorsCallbackTy &ArgAccessorFuncCB, DebugLoc OutlinedFnLoc)
static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, char ISA, StringRef ParSeq, StringRef MangledName, bool OutputBecomesInput, llvm::Function *Fn)
static FunctionCallee getKmpcForDynamicFiniForType(Type *Ty, Module &M, OpenMPIRBuilder &OMPBuilder)
Returns an LLVM function to call for finalizing the dynamic loop using depending on type.
static void FixupDebugInfoForOutlinedFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, Function *Func, DenseMap< Value *, std::tuple< Value *, unsigned > > &ValueReplacementMap)
static OMPScheduleType getOpenMPOrderingScheduleType(OMPScheduleType BaseScheduleType, bool HasOrderedClause)
Adds ordering modifier flags to schedule type.
static OMPScheduleType getOpenMPMonotonicityScheduleType(OMPScheduleType ScheduleType, bool HasSimdModifier, bool HasMonotonic, bool HasNonmonotonic, bool HasOrderedClause)
Adds monotonicity modifier flags to schedule type.
static std::string mangleVectorParameters(ArrayRef< llvm::OpenMPIRBuilder::DeclareSimdAttrTy > ParamAttrs)
Mangle the parameter part of the vector function name according to their OpenMP classification.
static bool isGenericKernel(Function &Fn)
static void workshareLoopTargetCallback(OpenMPIRBuilder *OMPIRBuilder, CanonicalLoopInfo *CLI, Value *Ident, Function &OutlinedFn, const SmallVector< Instruction *, 4 > &ToBeDeleted, WorksharingLoopType LoopType, bool NoLoop)
static bool isValidWorkshareLoopScheduleType(OMPScheduleType SchedType)
static bool isAtomicableReductionSet(ArrayRef< OpenMPIRBuilder::ReductionInfo > ReductionInfos)
static llvm::CallInst * emitNoUnwindRuntimeCall(IRBuilder<> &Builder, llvm::FunctionCallee Callee, ArrayRef< llvm::Value * > Args, const llvm::Twine &Name)
static Error populateReductionFunction(Function *ReductionFunc, ArrayRef< OpenMPIRBuilder::ReductionInfo > ReductionInfos, IRBuilder<> &Builder, ArrayRef< bool > IsByRef, bool IsGPU)
static Function * getFreshReductionFunc(Module &M)
static void raiseUserConstantDataAllocasToEntryBlock(IRBuilderBase &Builder, Function *Function)
static FunctionCallee getKmpcForDynamicNextForType(Type *Ty, Module &M, OpenMPIRBuilder &OMPBuilder)
Returns an LLVM function to call for updating the next loop using OpenMP dynamic scheduling depending...
static bool isConflictIP(IRBuilder<>::InsertPoint IP1, IRBuilder<>::InsertPoint IP2)
Return whether IP1 and IP2 are ambiguous, i.e.
static void checkReductionInfos(ArrayRef< OpenMPIRBuilder::ReductionInfo > ReductionInfos, bool IsGPU)
static Type * getOffloadingArrayType(Value *V)
static OMPScheduleType getOpenMPBaseScheduleType(llvm::omp::ScheduleKind ClauseKind, bool HasChunks, bool HasSimdModifier, bool HasDistScheduleChunks)
Determine which scheduling algorithm to use, determined from schedule clause arguments.
static OMPScheduleType computeOpenMPScheduleType(ScheduleKind ClauseKind, bool HasChunks, bool HasSimdModifier, bool HasMonotonicModifier, bool HasNonmonotonicModifier, bool HasOrderedClause, bool HasDistScheduleChunks)
Determine the schedule type using schedule and ordering clause arguments.
static FunctionCallee getKmpcForDynamicInitForType(Type *Ty, Module &M, OpenMPIRBuilder &OMPBuilder)
Returns an LLVM function to call for initializing loop bounds using OpenMP dynamic scheduling dependi...
static std::optional< omp::OMPTgtExecModeFlags > getTargetKernelExecMode(Function &Kernel)
Given a function, if it represents the entry point of a target kernel, this returns the execution mod...
static StructType * createTaskWithPrivatesTy(OpenMPIRBuilder &OMPIRBuilder, ArrayRef< Value * > OffloadingArraysToPrivatize)
static cl::opt< double > UnrollThresholdFactor("openmp-ir-builder-unroll-threshold-factor", cl::Hidden, cl::desc("Factor for the unroll threshold to account for code " "simplifications still taking place"), cl::init(1.5))
static cl::opt< bool > UseDefaultMaxThreads("openmp-ir-builder-use-default-max-threads", cl::Hidden, cl::desc("Use a default max threads if none is provided."), cl::init(true))
static int32_t computeHeuristicUnrollFactor(CanonicalLoopInfo *CLI)
Heuristically determine the best-performant unroll factor for CLI.
static Error emitTargetOutlinedFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, bool IsOffloadEntry, TargetRegionEntryInfo &EntryInfo, const OpenMPIRBuilder::TargetKernelDefaultAttrs &DefaultAttrs, Function *&OutlinedFn, Constant *&OutlinedFnID, SmallVectorImpl< Value * > &Inputs, OpenMPIRBuilder::TargetBodyGenCallbackTy &CBFunc, OpenMPIRBuilder::TargetGenArgAccessorsCallbackTy &ArgAccessorFuncCB, DebugLoc OutlinedFnLoc)
static Value * emitTaskDependencies(OpenMPIRBuilder &OMPBuilder, const SmallVectorImpl< OpenMPIRBuilder::DependData > &Dependencies)
static void updateNVPTXAttr(Function &Kernel, StringRef Name, int32_t Value, bool Min)
static OpenMPIRBuilder::InsertPointTy getInsertPointAfterInstr(Instruction *I)
static void redirectAllPredecessorsTo(BasicBlock *OldTarget, BasicBlock *NewTarget, DebugLoc DL)
Redirect all edges that branch to OldTarget to NewTarget.
static void hoistNonEntryAllocasToEntryBlock(llvm::BasicBlock &Block)
static std::unique_ptr< TargetMachine > createTargetMachine(Function *F, CodeGenOptLevel OptLevel)
Create the TargetMachine object to query the backend for optimization preferences.
static FunctionCallee getKmpcForStaticInitForType(Type *Ty, Module &M, OpenMPIRBuilder &OMPBuilder)
static void addAccessGroupMetadata(BasicBlock *Block, MDNode *AccessGroup, LoopInfo &LI)
Attach llvm.access.group metadata to the memref instructions of Block.
static void addBasicBlockMetadata(BasicBlock *BB, ArrayRef< Metadata * > Properties)
Attach metadata Properties to the basic block described by BB.
static void restoreIPandDebugLoc(llvm::IRBuilderBase &Builder, llvm::IRBuilderBase::InsertPoint IP)
This is a wrapper over IRBuilderBase::restoreIP that also restores a current debug location when the ...
static LoadInst * loadSharedDataFromTaskDescriptor(OpenMPIRBuilder &OMPIRBuilder, IRBuilderBase &Builder, Value *TaskWithPrivates, Type *TaskWithPrivatesTy)
Given a task descriptor, TaskWithPrivates, return the pointer to the block of pointers containing sha...
static cl::opt< bool > OptimisticAttributes("openmp-ir-builder-optimistic-attributes", cl::Hidden, cl::desc("Use optimistic attributes describing " "'as-if' properties of runtime calls."), cl::init(false))
static bool hasGridValue(const Triple &T)
static FunctionCallee getKmpcForStaticLoopForType(Type *Ty, OpenMPIRBuilder *OMPBuilder, WorksharingLoopType LoopType)
static const omp::GV & getGridValue(const Triple &T, Function *Kernel)
static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, StringRef Prefix, char ISA, StringRef ParSeq, StringRef MangledName, bool OutputBecomesInput, llvm::Function *Fn)
static Function * emitTargetTaskProxyFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, CallInst *StaleCI, StructType *PrivatesTy, StructType *TaskWithPrivatesTy, const size_t NumOffloadingArrays, const int SharedArgsOperandNo)
Create an entry point for a target task with the following.
static void addLoopMetadata(CanonicalLoopInfo *Loop, ArrayRef< Metadata * > Properties)
Attach loop metadata Properties to the loop described by Loop.
static AtomicOrdering TransformReleaseAcquireRelease(AtomicOrdering AO)
static void removeUnusedBlocksFromParent(ArrayRef< BasicBlock * > BBs)
static void targetParallelCallback(OpenMPIRBuilder *OMPIRBuilder, Function &OutlinedFn, Function *OuterFn, BasicBlock *OuterAllocaBB, Value *Ident, Value *IfCondition, Value *NumThreads, Instruction *PrivTID, AllocaInst *PrivTIDAddr, Value *ThreadID, const SmallVector< Instruction *, 4 > &ToBeDeleted)
static void hostParallelCallback(OpenMPIRBuilder *OMPIRBuilder, Function &OutlinedFn, Function *OuterFn, Value *Ident, Value *IfCondition, Instruction *PrivTID, AllocaInst *PrivTIDAddr, const SmallVector< Instruction *, 4 > &ToBeDeleted)
FunctionAnalysisManager FAM
This file defines the Pass Instrumentation classes that provide instrumentation points into the pass ...
const SmallVectorImpl< MachineOperand > & Cond
Remove Loads Into Fake Uses
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
SmallPtrSet< BasicBlock *, 0 > BlockSet
This file implements the SmallBitVector class.
This file defines the SmallSet class.
static SymbolRef::Type getType(const Symbol *Sym)
Defines the virtual file system interface vfs::FileSystem.
static cl::opt< unsigned > MaxThreads("xcore-max-threads", cl::desc("Maximum number of threads (for emulation thread-local storage)"), cl::Hidden, cl::value_desc("number"), cl::init(8))
static const uint32_t IV[8]
Class for arbitrary precision integers.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
An arbitrary precision integer that knows its signedness.
static APSInt getUnsigned(uint64_t X)
This class represents a conversion between pointers from one address space to another.
an instruction to allocate memory on the stack
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
PointerType * getType() const
Overload to return most specific pointer type.
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
unsigned getAddressSpace() const
Return the address space for the allocation.
LLVM_ABI std::optional< TypeSize > getAllocationSize(const DataLayout &DL) const
Get allocation size in bytes.
LLVM_ABI bool isArrayAllocation() const
Return true if there is an allocation size parameter to the allocation instruction that is not 1.
void setAlignment(Align Align)
const Value * getArraySize() const
Get the number of elements allocated.
bool registerPass(PassBuilderT &&PassBuilder)
Register an analysis pass with the manager.
This class represents an incoming formal argument to a Function.
unsigned getArgNo() const
Return the index of this formal argument in its containing function.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
Class to represent array types.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
A function analysis which provides an AssumptionCache.
LLVM_ABI AssumptionCache run(Function &F, FunctionAnalysisManager &)
A cache of @llvm.assume calls within a function.
An instruction that atomically checks whether a specified value is in a memory location,...
void setWeak(bool IsWeak)
static AtomicOrdering getStrongestFailureOrdering(AtomicOrdering SuccessOrdering)
Returns the strongest permitted ordering on failure, given the desired ordering on success.
LLVM_ABI std::pair< LoadInst *, AllocaInst * > EmitAtomicLoadLibcall(AtomicOrdering AO)
LLVM_ABI void EmitAtomicStoreLibcall(AtomicOrdering AO, Value *Source)
an instruction that atomically reads a memory location, combines it with another value,...
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ FMinimum
*p = minimum(old, v) minimum matches the behavior of llvm.minimum.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ FMaximum
*p = maximum(old, v) maximum matches the behavior of llvm.maximum.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ FMin
*p = minnum(old, v) minnum matches the behavior of llvm.minnum.
@ UMax
*p = old >unsigned v ? old : v
@ FMaximumNum
*p = maximumnum(old, v) maximumnum matches the behavior of llvm.maximumnum.
@ FMax
*p = maxnum(old, v) maxnum matches the behavior of llvm.maxnum.
@ UDecWrap
Decrement one until a minimum value or zero.
@ FMinimumNum
*p = minimumnum(old, v) minimumnum matches the behavior of llvm.minimumnum.
This class holds the attributes for a particular argument, parameter, function, or return value.
LLVM_ABI AttributeSet addAttributes(LLVMContext &C, AttributeSet AS) const
Add attributes to the attribute set.
LLVM_ABI AttributeSet addAttribute(LLVMContext &C, Attribute::AttrKind Kind) const
Add an argument attribute.
static LLVM_ABI Attribute getWithAlignment(LLVMContext &Context, Align Alignment)
Return a uniquified Attribute object that has the specific alignment set.
LLVM Basic Block Representation.
LLVM_ABI void replaceSuccessorsPhiUsesWith(BasicBlock *Old, BasicBlock *New)
Update all phi nodes in this basic block's successors to refer to basic block New instead of basic bl...
iterator begin()
Instruction iterator methods.
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
reverse_iterator rbegin()
bool hasTerminator() const LLVM_READONLY
Returns whether the block has a terminator.
const Instruction & back() const
LLVM_ABI BasicBlock * splitBasicBlockBefore(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction and insert the new basic blo...
LLVM_ABI InstListType::const_iterator getFirstNonPHIIt() const
Returns an iterator to the first instruction in this block that is not a PHINode instruction.
LLVM_ABI void insertDbgRecordBefore(DbgRecord *DR, InstListType::iterator Here)
Insert a DbgRecord into a block at the position given by Here.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
LLVM_ABI InstListType::const_iterator getFirstNonPHIOrDbg(bool SkipPseudoOp=true) const
Returns a pointer to the first instruction in this block that is not a PHINode or a debug intrinsic,...
LLVM_ABI const BasicBlock * getUniqueSuccessor() const
Return the successor of this block if it has a unique successor.
LLVM_ABI const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
const Instruction & front() const
InstListType::reverse_iterator reverse_iterator
LLVM_ABI const BasicBlock * getUniquePredecessor() const
Return the predecessor of this block if it has a unique predecessor block.
const Instruction * getTerminatorOrNull() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
LLVM_ABI const BasicBlock * getSingleSuccessor() const
Return the successor of this block if it has a single successor.
LLVM_ABI SymbolTableList< BasicBlock >::iterator eraseFromParent()
Unlink 'this' from the containing function and delete it.
InstListType::iterator iterator
Instruction iterators...
LLVM_ABI LLVMContext & getContext() const
Get the context in which this basic block lives.
void moveBefore(BasicBlock *MovePos)
Unlink this basic block from its current function and insert it into the function that MovePos lives ...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
void splice(BasicBlock::iterator ToIt, BasicBlock *FromBB)
Transfer all instructions from FromBB to this basic block at ToIt.
LLVM_ABI void removePredecessor(BasicBlock *Pred, bool KeepOneInputPHIs=false)
Update PHI nodes in this BasicBlock before removal of predecessor Pred.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
User::op_iterator arg_begin()
Return the iterator pointing to the beginning of the argument list.
Value * getArgOperand(unsigned i) const
User::op_iterator arg_end()
Return the iterator pointing to the end of the argument list.
unsigned arg_size() const
This class represents a function call, abstracting a target machine's calling convention.
Class to represented the control flow structure of an OpenMP canonical loop.
Value * getTripCount() const
Returns the llvm::Value containing the number of loop iterations.
BasicBlock * getHeader() const
The header is the entry for each iteration.
LLVM_ABI void assertOK() const
Consistency self-check.
Type * getIndVarType() const
Return the type of the induction variable (and the trip count).
BasicBlock * getBody() const
The body block is the single entry for a loop iteration and not controlled by CanonicalLoopInfo.
bool isValid() const
Returns whether this object currently represents the IR of a loop.
void setLastIter(Value *IterVar)
Sets the last iteration variable for this loop.
OpenMPIRBuilder::InsertPointTy getAfterIP() const
Return the insertion point for user code after the loop.
OpenMPIRBuilder::InsertPointTy getBodyIP() const
Return the insertion point for user code in the body.
BasicBlock * getAfter() const
The after block is intended for clean-up code such as lifetime end markers.
Function * getFunction() const
LLVM_ABI void invalidate()
Invalidate this loop.
BasicBlock * getLatch() const
Reaching the latch indicates the end of the loop body code.
OpenMPIRBuilder::InsertPointTy getPreheaderIP() const
Return the insertion point for user code before the loop.
BasicBlock * getCond() const
The condition block computes whether there is another loop iteration.
BasicBlock * getExit() const
Reaching the exit indicates no more iterations are being executed.
LLVM_ABI BasicBlock * getPreheader() const
The preheader ensures that there is only a single edge entering the loop.
Instruction * getIndVar() const
Returns the instruction representing the current logical induction variable.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ ICMP_ULT
unsigned less than
@ ICMP_ULE
unsigned less or equal
static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)
get() constructor - Return a constant with array type with an element count and element type matching...
static LLVM_ABI Constant * getString(LLVMContext &Context, StringRef Initializer, bool AddNull=true, bool ByteString=false)
This method constructs a CDS and initializes it with a text string.
static LLVM_ABI Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
static LLVM_ABI Constant * getPointerBitCastOrAddrSpaceCast(Constant *C, Type *Ty)
Create a BitCast or AddrSpaceCast for a pointer type depending on the address space.
static LLVM_ABI Constant * getAddrSpaceCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static LLVM_ABI ConstantFP * getZero(Type *Ty, bool Negative=false)
This is the shared class of boolean and integer constants.
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static LLVM_ABI Constant * get(StructType *T, ArrayRef< Constant * > V)
This is an important base class in LLVM.
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
DILocalScope * getScope() const
Get the local scope for this variable.
DINodeArray getAnnotations() const
Subprogram description. Uses SubclassData1.
uint32_t getAlignInBits() const
StringRef getName() const
A parsed version of the target data layout string in and methods for querying it.
TypeSize getTypeStoreSize(Type *Ty) const
Returns the maximum number of bytes that may be overwritten by storing the specified type.
Record of a variable value-assignment, aka a non instruction representation of the dbg....
Analysis pass which computes a DominatorTree.
LLVM_ABI DominatorTree run(Function &F, FunctionAnalysisManager &)
Run the analysis pass over a function and produce a dominator tree.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Represents either an error or a value T.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
reference get()
Returns a reference to the stored T value.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
Class to represent function types.
Type * getParamType(unsigned i) const
Parameter type accessors.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
const BasicBlock & getEntryBlock() const
FunctionType * getFunctionType() const
Returns the FunctionType for me.
void removeFromParent()
removeFromParent - This method unlinks 'this' from the containing module, but does not delete it.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
DISubprogram * getSubprogram() const
Get the attached subprogram.
AttributeList getAttributes() const
Return the attribute list for this Function.
const Function & getFunction() const
void setAttributes(AttributeList Attrs)
Set the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
adds the attribute to the list of attributes for the given arg.
Function::iterator insert(Function::iterator Position, BasicBlock *BB)
Insert BB in the basic block list at Position.
Type * getReturnType() const
Returns the type of the ret val.
void setCallingConv(CallingConv::ID CC)
Argument * getArg(unsigned i) const
bool hasMetadata() const
Return true if this GlobalObject has any metadata attached to it.
LLVM_ABI void addMetadata(unsigned KindID, MDNode &MD)
Add a metadata attachment.
LinkageTypes getLinkage() const
void setLinkage(LinkageTypes LT)
Module * getParent()
Get the module that this global value is contained inside of...
void setDSOLocal(bool Local)
PointerType * getType() const
Global values are always pointers.
@ HiddenVisibility
The GV is hidden.
@ ProtectedVisibility
The GV is protected.
void setVisibility(VisibilityTypes V)
LinkageTypes
An enumeration for the kinds of linkage for global values.
@ PrivateLinkage
Like Internal, but omit from symbol table.
@ CommonLinkage
Tentative definitions.
@ InternalLinkage
Rename collisions when linking (static functions).
@ WeakODRLinkage
Same, but only replaced by something equivalent.
@ WeakAnyLinkage
Keep one copy of named function when linking (weak)
@ AppendingLinkage
Special purpose, only applies to global arrays.
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
Common base class shared among various IRBuilders.
InsertPoint saveIP() const
Returns the current insert point.
BasicBlock::iterator InsertPoint
InsertPoint - A saved insertion point.
void restoreIP(InsertPoint IP)
Sets the current insert point to a previously-saved location.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI void removeFromParent()
This method unlinks 'this' from the containing basic block, but does not delete it.
LLVM_ABI unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI void moveBefore(InstListType::iterator InsertPos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
LLVM_ABI BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY
Return the specified successor. This instruction must be a terminator.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
user_iterator user_begin()
LLVM_ABI void moveBeforePreserving(InstListType::iterator MovePos)
Perform a moveBefore operation, while signalling that the caller intends to preserve the original ord...
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI void insertAfter(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately after the specified instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
Class to represent integer types.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this load instruction.
Align getAlign() const
Return the alignment of the access that is being performed.
Analysis pass that exposes the LoopInfo for a function.
LLVM_ABI LoopInfo run(Function &F, FunctionAnalysisManager &AM)
ArrayRef< BlockT * > getBlocks() const
Get a list of the basic blocks which make up this loop.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
This class represents a loop nest and can be used to query its properties.
Represents a single loop in the control flow graph.
LLVM_ABI MDNode * createCallbackEncoding(unsigned CalleeArgNo, ArrayRef< int > Arguments, bool VarArgsArePassed)
Return metadata describing a callback (see llvm::AbstractCallSite).
LLVM_ABI void replaceOperandWith(unsigned I, Metadata *New)
Replace a specific operand.
static MDTuple * getDistinct(LLVMContext &Context, ArrayRef< Metadata * > MDs)
ArrayRef< MDOperand > operands() const
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
This class implements a map that also provides access to all stored values in a deterministic order.
A Module instance is used to store all the information related to an LLVM module.
LLVMContext & getContext() const
Get the global data context.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
iterator_range< op_iterator > operands()
LLVM_ABI void addOperand(MDNode *M)
Device global variable entries info.
Target region entries info.
Base class of the entries info.
Class that manages information about offload code regions and data.
function_ref< void(StringRef, const OffloadEntryInfoDeviceGlobalVar &)> OffloadDeviceGlobalVarEntryInfoActTy
Applies action Action on all registered entries.
OMPTargetDeviceClauseKind
Kind of device clause for declare target variables and functions NOTE: Currently not used as a part o...
@ OMPTargetDeviceClauseAny
The target is marked for all devices.
LLVM_ABI void registerDeviceGlobalVarEntryInfo(StringRef VarName, Constant *Addr, int64_t VarSize, OMPTargetGlobalVarEntryKind Flags, GlobalValue::LinkageTypes Linkage)
Register device global variable entry.
LLVM_ABI void initializeDeviceGlobalVarEntryInfo(StringRef Name, OMPTargetGlobalVarEntryKind Flags, unsigned Order)
Initialize device global variable entry.
LLVM_ABI void actOnDeviceGlobalVarEntriesInfo(const OffloadDeviceGlobalVarEntryInfoActTy &Action)
OMPTargetRegionEntryKind
Kind of the target registry entry.
@ OMPTargetRegionEntryTargetRegion
Mark the entry as target region.
LLVM_ABI void getTargetRegionEntryFnName(SmallVectorImpl< char > &Name, const TargetRegionEntryInfo &EntryInfo)
LLVM_ABI bool hasTargetRegionEntryInfo(TargetRegionEntryInfo EntryInfo, bool IgnoreAddressId=false) const
Return true if a target region entry with the provided information exists.
LLVM_ABI void registerTargetRegionEntryInfo(TargetRegionEntryInfo EntryInfo, Constant *Addr, Constant *ID, OMPTargetRegionEntryKind Flags)
Register target region entry.
LLVM_ABI void actOnTargetRegionEntriesInfo(const OffloadTargetRegionEntryInfoActTy &Action)
LLVM_ABI void initializeTargetRegionEntryInfo(const TargetRegionEntryInfo &EntryInfo, unsigned Order)
Initialize target region entry.
OMPTargetGlobalVarEntryKind
Kind of the global variable entry..
@ OMPTargetGlobalVarEntryEnter
Mark the entry as a declare target enter.
@ OMPTargetGlobalRegisterRequires
Mark the entry as a register requires global.
@ OMPTargetGlobalVarEntryIndirect
Mark the entry as a declare target indirect global.
@ OMPTargetGlobalVarEntryLink
Mark the entry as a to declare target link.
@ OMPTargetGlobalVarEntryTo
Mark the entry as a to declare target.
@ OMPTargetGlobalVarEntryIndirectVTable
Mark the entry as a declare target indirect vtable.
function_ref< void(const TargetRegionEntryInfo &EntryInfo, const OffloadEntryInfoTargetRegion &)> OffloadTargetRegionEntryInfoActTy
brief Applies action Action on all registered entries.
bool hasDeviceGlobalVarEntryInfo(StringRef VarName) const
Checks if the variable with the given name has been registered already.
LLVM_ABI bool empty() const
Return true if a there are no entries defined.
std::optional< bool > IsTargetDevice
Flag to define whether to generate code for the role of the OpenMP host (if set to false) or device (...
std::optional< bool > IsGPU
Flag for specifying if the compilation is done for an accelerator.
LLVM_ABI int64_t getRequiresFlags() const
Returns requires directive clauses as flags compatible with those expected by libomptarget.
std::optional< bool > OpenMPOffloadMandatory
Flag for specifying if offloading is mandatory.
LLVM_ABI void setHasRequiresReverseOffload(bool Value)
LLVM_ABI OpenMPIRBuilderConfig()
LLVM_ABI bool hasRequiresUnifiedSharedMemory() const
LLVM_ABI void setHasRequiresUnifiedSharedMemory(bool Value)
unsigned getDefaultTargetAS() const
LLVM_ABI bool hasRequiresDynamicAllocators() const
LLVM_ABI void setHasRequiresUnifiedAddress(bool Value)
bool isTargetDevice() const
LLVM_ABI void setHasRequiresDynamicAllocators(bool Value)
LLVM_ABI bool hasRequiresReverseOffload() const
bool hasRequiresFlags() const
LLVM_ABI bool hasRequiresUnifiedAddress() const
Struct that keeps the information that should be kept throughout a 'target data' region.
An interface to create LLVM-IR for OpenMP directives.
LLVM_ABI InsertPointOrErrorTy createOrderedThreadsSimd(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, bool IsThreads)
Generator for 'omp ordered [threads | simd]'.
LLVM_ABI void emitAArch64DeclareSimdFunction(llvm::Function *Fn, unsigned VLENVal, llvm::ArrayRef< DeclareSimdAttrTy > ParamAttrs, DeclareSimdBranch Branch, char ISA, unsigned NarrowestDataSize, bool OutputBecomesInput)
Emit AArch64 vector-function ABI attributes for a declare simd function.
LLVM_ABI Constant * getOrCreateIdent(Constant *SrcLocStr, uint32_t SrcLocStrSize, omp::IdentFlag Flags=omp::IdentFlag(0), unsigned Reserve2Flags=0)
Return an ident_t* encoding the source location SrcLocStr and Flags.
LLVM_ABI void registerDeclareTargetGlobalReplacement(GlobalValue *Original, GlobalValue *Replacement)
Register a module-scope replacement of a declare target global variable.
LLVM_ABI FunctionCallee getOrCreateRuntimeFunction(Module &M, omp::RuntimeFunction FnID)
Return the function declaration for the runtime function with FnID.
LLVM_ABI InsertPointOrErrorTy createCancel(const LocationDescription &Loc, Value *IfCondition, omp::Directive CanceledDirective)
Generator for 'omp cancel'.
std::function< Expected< Function * >(StringRef FunctionName)> FunctionGenCallback
Functions used to generate a function with the given name.
LLVM_ABI CallInst * createOMPAllocShared(const LocationDescription &Loc, Value *Size, const Twine &Name=Twine(""))
Create a runtime call for kmpc_alloc_shared.
ReductionGenCBKind
Enum class for the RedctionGen CallBack type to be used.
LLVM_ABI CanonicalLoopInfo * collapseLoops(DebugLoc DL, ArrayRef< CanonicalLoopInfo * > Loops, InsertPointTy ComputeIP)
Collapse a loop nest into a single loop.
LLVM_ABI void createTaskyield(const LocationDescription &Loc)
Generator for 'omp taskyield'.
std::function< Error(InsertPointTy CodeGenIP)> FinalizeCallbackTy
Callback type for variable finalization (think destructors).
LLVM_ABI void emitBranch(BasicBlock *Target)
LLVM_ABI Error emitCancelationCheckImpl(Value *CancelFlag, omp::Directive CanceledDirective)
Generate control flow and cleanup for cancellation.
static LLVM_ABI void writeThreadBoundsForKernel(const Triple &T, Function &Kernel, int32_t LB, int32_t UB)
LLVM_ABI void emitTaskwaitImpl(const LocationDescription &Loc)
Generate a taskwait runtime call.
LLVM_ABI Constant * registerTargetRegionFunction(TargetRegionEntryInfo &EntryInfo, Function *OutlinedFunction, StringRef EntryFnName, StringRef EntryFnIDName)
Registers the given function and sets up the attribtues of the function Returns the FunctionID.
LLVM_ABI GlobalVariable * emitKernelExecutionMode(StringRef KernelName, omp::OMPTgtExecModeFlags Mode)
Emit the kernel execution mode.
LLVM_ABI void initialize()
Initialize the internal state, this will put structures types and potentially other helpers into the ...
LLVM_ABI InsertPointTy createAtomicCompare(const LocationDescription &Loc, AtomicOpValue &X, AtomicOpValue &V, AtomicOpValue &R, Value *E, Value *D, AtomicOrdering AO, omp::OMPAtomicCompareOp Op, bool IsXBinopExpr, bool IsPostfixUpdate, bool IsFailOnly, bool IsWeak=false)
LLVM_ABI InsertPointTy createAtomicWrite(const LocationDescription &Loc, AtomicOpValue &X, Value *Expr, AtomicOrdering AO, InsertPointTy AllocaIP)
Emit atomic write for : X = Expr — Only Scalar data types.
LLVM_ABI void loadOffloadInfoMetadata(Module &M)
Loads all the offload entries information from the host IR metadata.
function_ref< MapInfosTy &(InsertPointTy CodeGenIP)> GenMapInfoCallbackTy
Callback type for creating the map infos for the kernel parameters.
LLVM_ABI Error emitOffloadingArrays(InsertPointTy AllocaIP, InsertPointTy CodeGenIP, MapInfosTy &CombinedInfo, TargetDataInfo &Info, CustomMapperCallbackTy CustomMapperCB, bool IsNonContiguous=false, function_ref< void(unsigned int, Value *)> DeviceAddrCB=nullptr)
Emit the arrays used to pass the captures and map information to the offloading runtime library.
LLVM_ABI void unrollLoopFull(DebugLoc DL, CanonicalLoopInfo *Loop)
Fully unroll a loop.
function_ref< Error(InsertPointTy CodeGenIP, Value *IndVar)> LoopBodyGenCallbackTy
Callback type for loop body code generation.
LLVM_ABI InsertPointOrErrorTy emitScanReduction(const LocationDescription &Loc, ArrayRef< llvm::OpenMPIRBuilder::ReductionInfo > ReductionInfos, ScanInfo *ScanRedInfo)
This function performs the scan reduction of the values updated in the input phase.
LLVM_ABI void emitFlush(const LocationDescription &Loc)
Generate a flush runtime call.
LLVM_ABI InsertPointOrErrorTy createScope(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, bool IsNowait)
Generator for 'omp scope'.
static LLVM_ABI std::pair< int32_t, int32_t > readThreadBoundsForKernel(const Triple &T, Function &Kernel)
}
OpenMPIRBuilderConfig Config
The OpenMPIRBuilder Configuration.
LLVM_ABI CallInst * createOMPInteropDestroy(const LocationDescription &Loc, Value *InteropVar, Value *Device, Value *NumDependences, Value *DependenceAddress, bool HaveNowaitClause)
Create a runtime call for __tgt_interop_destroy.
LLVM_ABI void emitUsed(StringRef Name, ArrayRef< llvm::WeakTrackingVH > List)
Emit the llvm.used metadata.
LLVM_ABI InsertPointOrErrorTy createSingle(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, bool IsNowait, ArrayRef< llvm::Value * > CPVars={}, ArrayRef< llvm::Function * > CPFuncs={})
Generator for 'omp single'.
LLVM_ABI InsertPointOrErrorTy createTarget(const LocationDescription &Loc, bool IsOffloadEntry, OpenMPIRBuilder::InsertPointTy AllocaIP, OpenMPIRBuilder::InsertPointTy CodeGenIP, ArrayRef< BasicBlock * > DeallocBlocks, TargetDataInfo &Info, TargetRegionEntryInfo &EntryInfo, const TargetKernelDefaultAttrs &DefaultAttrs, const TargetKernelRuntimeAttrs &RuntimeAttrs, Value *IfCond, SmallVectorImpl< Value * > &Inputs, GenMapInfoCallbackTy GenMapInfoCB, TargetBodyGenCallbackTy BodyGenCB, TargetGenArgAccessorsCallbackTy ArgAccessorFuncCB, CustomMapperCallbackTy CustomMapperCB, const DependenciesInfo &Dependencies={}, bool HasNowait=false, Value *DynCGroupMem=nullptr, omp::OMPDynGroupprivateFallbackType DynCGroupMemFallback=omp::OMPDynGroupprivateFallbackType::Abort, DebugLoc OutlinedFnLoc={}, Value *RTLocOverride=nullptr)
Generator for 'omp target'.
LLVM_ABI InsertPointOrErrorTy createTeams(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, Value *NumTeamsLower=nullptr, Value *NumTeamsUpper=nullptr, Value *ThreadLimit=nullptr, Value *IfExpr=nullptr)
Generator for #omp teams
std::forward_list< CanonicalLoopInfo > LoopInfos
Collection of owned canonical loop objects that eventually need to be free'd.
LLVM_ABI llvm::StructType * getKmpTaskAffinityInfoTy()
Return the LLVM struct type matching runtime kmp_task_affinity_info_t.
LLVM_ABI Constant * emitKernelEnvironment(const LocationDescription &Loc, const llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs)
The omp target interface.
LLVM_ABI std::string createPlatformSpecificName(ArrayRef< StringRef > Parts) const
Get the create a name using the platform specific separators.
LLVM_ABI FunctionCallee createDispatchNextFunction(unsigned IVSize, bool IVSigned)
Returns __kmpc_dispatch_next_* runtime function for the specified size IVSize and sign IVSigned.
static LLVM_ABI void getKernelArgsVector(TargetKernelArgs &KernelArgs, IRBuilderBase &Builder, SmallVector< Value * > &ArgsVector)
Create the kernel args vector used by emitTargetKernel.
LLVM_ABI void unrollLoopHeuristic(DebugLoc DL, CanonicalLoopInfo *Loop)
Fully or partially unroll a loop.
LLVM_ABI omp::OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position)
Get OMP_MAP_MEMBER_OF flag with extra bits reserved based on the position given.
LLVM_ABI void addAttributes(omp::RuntimeFunction FnID, Function &Fn)
Add attributes known for FnID to Fn.
Module & M
The underlying LLVM-IR module.
StringMap< Constant * > SrcLocStrMap
Map to remember source location strings.
LLVM_ABI void createMapperAllocas(const LocationDescription &Loc, InsertPointTy AllocaIP, unsigned NumOperands, struct MapperAllocas &MapperAllocas)
Create the allocas instruction used in call to mapper functions.
SmallVector< DeclareTargetGlobalReplacement, 8 > DeclareTargetGlobalReplacements
Collection of declare target globals to rewrite uses of during device module finalizaiton.
LLVM_ABI Constant * getOrCreateSrcLocStr(StringRef LocStr, uint32_t &SrcLocStrSize)
Return the (LLVM-IR) string describing the source location LocStr.
LLVM_ABI Error emitTargetRegionFunction(TargetRegionEntryInfo &EntryInfo, FunctionGenCallback &GenerateFunctionCallback, bool IsOffloadEntry, Function *&OutlinedFn, Constant *&OutlinedFnID)
Create a unique name for the entry function using the source location information of the current targ...
LLVM_ABI InsertPointOrErrorTy createIteratorLoop(LocationDescription Loc, llvm::Value *TripCount, IteratorBodyGenTy BodyGen, llvm::StringRef Name="iterator")
Create a canonical iterator loop at the current insertion point.
LLVM_ABI Expected< SmallVector< llvm::CanonicalLoopInfo * > > createCanonicalScanLoops(const LocationDescription &Loc, LoopBodyGenCallbackTy BodyGenCB, Value *Start, Value *Stop, Value *Step, bool IsSigned, bool InclusiveStop, InsertPointTy ComputeIP, const Twine &Name, ScanInfo *ScanRedInfo)
Generator for the control flow structure of an OpenMP canonical loops if the parent directive has an ...
LLVM_ABI FunctionCallee createDispatchFiniFunction(unsigned IVSize, bool IVSigned)
Returns __kmpc_dispatch_fini_* runtime function for the specified size IVSize and sign IVSigned.
function_ref< InsertPointOrErrorTy( InsertPointTy AllocaIP, InsertPointTy CodeGenIP, ArrayRef< BasicBlock * > DeallocBlocks)> TargetBodyGenCallbackTy
LLVM_ABI void unrollLoopPartial(DebugLoc DL, CanonicalLoopInfo *Loop, int32_t Factor, CanonicalLoopInfo **UnrolledCLI)
Partially unroll a loop.
function_ref< Error(Value *DeviceID, Value *RTLoc, IRBuilderBase::InsertPoint TargetTaskAllocaIP)> TargetTaskBodyCallbackTy
Callback type for generating the bodies of device directives that require outer target tasks (e....
Expected< MapInfosTy & > MapInfosOrErrorTy
bool HandleFPNegZero
Emit atomic compare for constructs: — Only scalar data types cond-expr-stmt: x = x ordop expr ?
LLVM_ABI void emitTaskyieldImpl(const LocationDescription &Loc)
Generate a taskyield runtime call.
LLVM_ABI void emitMapperCall(const LocationDescription &Loc, Function *MapperFunc, Value *SrcLocInfo, Value *MaptypesArg, Value *MapnamesArg, struct MapperAllocas &MapperAllocas, int64_t DeviceID, unsigned NumOperands)
Create the call for the target mapper function.
LLVM_ABI InsertPointOrErrorTy createDistribute(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< BasicBlock * > DeallocBlocks, BodyGenCallbackTy BodyGenCB)
Generator for #omp distribute
function_ref< Expected< Function * >(unsigned int)> CustomMapperCallbackTy
LLVM_ABI InsertPointTy createOrderedDepend(const LocationDescription &Loc, InsertPointTy AllocaIP, unsigned NumLoops, ArrayRef< llvm::Value * > StoreValues, const Twine &Name, bool IsDependSource)
Generator for 'omp ordered depend (source | sink)'.
LLVM_ABI InsertPointTy createCopyinClauseBlocks(InsertPointTy IP, Value *MasterAddr, Value *PrivateAddr, llvm::IntegerType *IntPtrTy, bool BranchtoEnd=true)
Generate conditional branch and relevant BasicBlocks through which private threads copy the 'copyin' ...
function_ref< InsertPointOrErrorTy( InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Value &Original, Value &Inner, Value *&ReplVal)> PrivatizeCallbackTy
Callback type for variable privatization (think copy & default constructor).
LLVM_ABI bool isFinalized()
Check whether the finalize function has already run.
SmallVector< FinalizationInfo, 8 > FinalizationStack
The finalization stack made up of finalize callbacks currently in-flight, wrapped into FinalizationIn...
LLVM_ABI std::vector< CanonicalLoopInfo * > tileLoops(DebugLoc DL, ArrayRef< CanonicalLoopInfo * > Loops, ArrayRef< Value * > TileSizes)
Tile a loop nest.
LLVM_ABI CallInst * createOMPInteropInit(const LocationDescription &Loc, Value *InteropVar, omp::OMPInteropType InteropType, Value *Device, Value *NumDependences, Value *DependenceAddress, bool HaveNowaitClause)
Create a runtime call for __tgt_interop_init.
LLVM_ABI Error emitIfClause(Value *Cond, BodyGenCallbackTy ThenGen, BodyGenCallbackTy ElseGen, InsertPointTy AllocaIP={}, ArrayRef< BasicBlock * > DeallocBlocks={})
Emits code for OpenMP 'if' clause using specified BodyGenCallbackTy Here is the logic: if (Cond) { Th...
LLVM_ABI void finalize(Function *Fn=nullptr)
Finalize the underlying module, e.g., by outlining regions.
LLVM_ABI Function * getOrCreateRuntimeFunctionPtr(omp::RuntimeFunction FnID)
void addOutlineInfo(std::unique_ptr< OutlineInfo > &&OI)
Add a new region that will be outlined later.
LLVM_ABI InsertPointTy createTargetInit(const LocationDescription &Loc, const llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs)
Create a runtime call for kmpc_target_init.
LLVM_ABI InsertPointOrErrorTy createReductions(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< ReductionInfo > ReductionInfos, ArrayRef< bool > IsByRef, bool IsNoWait=false, bool IsTeamsReduction=false)
Generator for 'omp reduction'.
const Triple T
The target triple of the underlying module.
DenseMap< std::pair< Constant *, uint64_t >, Constant * > IdentMap
Map to remember existing ident_t*.
LLVM_ABI CallInst * createOMPFree(const LocationDescription &Loc, Value *Addr, Value *Allocator, std::string Name="")
Create a runtime call for kmpc_free.
LLVM_ABI InsertPointOrErrorTy createReductionsGPU(const LocationDescription &Loc, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, ArrayRef< ReductionInfo > ReductionInfos, ArrayRef< bool > IsByRef, bool IsNoWait=false, bool IsTeamsReduction=false, bool IsSPMD=false, ReductionGenCBKind ReductionGenCBKind=ReductionGenCBKind::MLIR, std::optional< omp::GV > GridValue={}, Value *SrcLocInfo=nullptr)
Design of OpenMP reductions on the GPU.
LLVM_ABI FunctionCallee createForStaticInitFunction(unsigned IVSize, bool IVSigned, bool IsGPUDistribute)
Returns __kmpc_for_static_init_* runtime function for the specified size IVSize and sign IVSigned.
LLVM_ABI CallInst * createOMPAlloc(const LocationDescription &Loc, Value *Size, Value *Allocator, std::string Name="")
Create a runtime call for kmpc_alloc.
LLVM_ABI void emitNonContiguousDescriptor(InsertPointTy AllocaIP, InsertPointTy CodeGenIP, MapInfosTy &CombinedInfo, TargetDataInfo &Info)
Emit an array of struct descriptors to be assigned to the offload args.
LLVM_ABI InsertPointOrErrorTy createSection(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB)
Generator for 'omp section'.
LLVM_ABI InsertPointOrErrorTy createTaskgroup(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< BasicBlock * > DeallocBlocks, BodyGenCallbackTy BodyGenCB)
Generator for the taskgroup construct.
LLVM_ABI InsertPointOrErrorTy createParallel(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< BasicBlock * > DeallocBlocks, BodyGenCallbackTy BodyGenCB, PrivatizeCallbackTy PrivCB, FinalizeCallbackTy FiniCB, Value *IfCondition, Value *NumThreads, omp::ProcBindKind ProcBind, bool IsCancellable)
Generator for 'omp parallel'.
function_ref< InsertPointOrErrorTy(InsertPointTy)> EmitFallbackCallbackTy
Callback function type for functions emitting the host fallback code that is executed when the kernel...
static LLVM_ABI TargetRegionEntryInfo getTargetEntryUniqueInfo(FileIdentifierInfoCallbackTy CallBack, vfs::FileSystem &VFS, StringRef ParentName="")
Creates a unique info for a target entry when provided a filename and line number from.
LLVM_ABI void emitTaskDependency(IRBuilderBase &Builder, Value *Entry, const DependData &Dep)
Store one kmp_depend_info entry at the given Entry pointer.
LLVM_ABI void emitBlock(BasicBlock *BB, Function *CurFn, bool IsFinished=false)
LLVM_ABI Value * getOrCreateThreadID(Value *Ident)
Return the current thread ID.
LLVM_ABI InsertPointOrErrorTy createMaster(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB)
Generator for 'omp master'.
LLVM_ABI InsertPointOrErrorTy createTargetData(const LocationDescription &Loc, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, ArrayRef< BasicBlock * > DeallocBlocks, Value *DeviceID, Value *IfCond, TargetDataInfo &Info, GenMapInfoCallbackTy GenMapInfoCB, CustomMapperCallbackTy CustomMapperCB, omp::RuntimeFunction *MapperFunc=nullptr, function_ref< InsertPointOrErrorTy(InsertPointTy CodeGenIP, BodyGenTy BodyGenType)> BodyGenCB=nullptr, function_ref< void(unsigned int, Value *)> DeviceAddrCB=nullptr, Value *SrcLocInfo=nullptr)
Generator for 'omp target data'.
LLVM_ABI CallInst * createRuntimeFunctionCall(FunctionCallee Callee, ArrayRef< Value * > Args, StringRef Name="")
LLVM_ABI InsertPointOrErrorTy emitKernelLaunch(const LocationDescription &Loc, Value *OutlinedFnID, EmitFallbackCallbackTy EmitTargetCallFallbackCB, TargetKernelArgs &Args, Value *DeviceID, Value *RTLoc, InsertPointTy AllocaIP)
Generate a target region entry call and host fallback call.
StringMap< GlobalVariable *, BumpPtrAllocator > InternalVars
An ordered map of auto-generated variables to their unique names.
LLVM_ABI InsertPointOrErrorTy createCancellationPoint(const LocationDescription &Loc, omp::Directive CanceledDirective)
Generator for 'omp cancellation point'.
LLVM_ABI CallInst * createOMPAlignedAlloc(const LocationDescription &Loc, Value *Align, Value *Size, Value *Allocator, std::string Name="")
Create a runtime call for kmpc_align_alloc.
LLVM_ABI FunctionCallee createDispatchInitFunction(unsigned IVSize, bool IVSigned)
Returns __kmpc_dispatch_init_* runtime function for the specified size IVSize and sign IVSigned.
LLVM_ABI InsertPointOrErrorTy createScan(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< llvm::Value * > ScanVars, ArrayRef< llvm::Type * > ScanVarsType, bool IsInclusive, ScanInfo *ScanRedInfo)
This directive split and directs the control flow to input phase blocks or scan phase blocks based on...
LLVM_ABI CallInst * createOMPFreeShared(const LocationDescription &Loc, Value *Addr, Value *Size, const Twine &Name=Twine(""))
Create a runtime call for kmpc_free_shared.
LLVM_ABI CallInst * createOMPInteropUse(const LocationDescription &Loc, Value *InteropVar, Value *Device, Value *NumDependences, Value *DependenceAddress, bool HaveNowaitClause)
Create a runtime call for __tgt_interop_use.
IRBuilder<>::InsertPoint InsertPointTy
Type used throughout for insertion points.
LLVM_ABI GlobalVariable * getOrCreateInternalVariable(Type *Ty, const StringRef &Name, std::optional< unsigned > AddressSpace={})
Gets (if variable with the given name already exist) or creates internal global variable with the spe...
LLVM_ABI GlobalVariable * createOffloadMapnames(SmallVectorImpl< llvm::Constant * > &Names, std::string VarName)
Create the global variable holding the offload names information.
LLVM_ABI InsertPointOrErrorTy createTask(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< BasicBlock * > DeallocBlocks, BodyGenCallbackTy BodyGenCB, bool Tied=true, Value *Final=nullptr, Value *IfCondition=nullptr, const DependenciesInfo &Dependencies={}, const AffinityData &Affinities={}, bool Mergeable=false, Value *EventHandle=nullptr, Value *Priority=nullptr, bool FreeAgent=false)
Generator for #omp taskloop
std::forward_list< ScanInfo > ScanInfos
Collection of owned ScanInfo objects that eventually need to be free'd.
static LLVM_ABI void writeTeamsForKernel(const Triple &T, Function &Kernel, int32_t LB, int32_t UB)
LLVM_ABI Value * calculateCanonicalLoopTripCount(const LocationDescription &Loc, Value *Start, Value *Stop, Value *Step, bool IsSigned, bool InclusiveStop, const Twine &Name="loop")
Calculate the trip count of a canonical loop.
LLVM_ABI InsertPointOrErrorTy createBarrier(const LocationDescription &Loc, omp::Directive Kind, bool ForceSimpleCall=false, bool CheckCancelFlag=true)
Emitter methods for OpenMP directives.
LLVM_ABI void setCorrectMemberOfFlag(omp::OpenMPOffloadMappingFlags &Flags, omp::OpenMPOffloadMappingFlags MemberOfFlag)
Given an initial flag set, this function modifies it to contain the passed in MemberOfFlag generated ...
LLVM_ABI Error emitOffloadingArraysAndArgs(InsertPointTy AllocaIP, InsertPointTy CodeGenIP, TargetDataInfo &Info, TargetDataRTArgs &RTArgs, MapInfosTy &CombinedInfo, CustomMapperCallbackTy CustomMapperCB, bool IsNonContiguous=false, bool ForEndCall=false, function_ref< void(unsigned int, Value *)> DeviceAddrCB=nullptr)
Allocates memory for and populates the arrays required for offloading (offload_{baseptrs|ptrs|mappers...
LLVM_ABI Constant * getOrCreateDefaultSrcLocStr(uint32_t &SrcLocStrSize)
Return the (LLVM-IR) string describing the default source location.
LLVM_ABI InsertPointOrErrorTy createCritical(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, StringRef CriticalName, Value *HintInst)
Generator for 'omp critical'.
LLVM_ABI void createError(const LocationDescription &Loc, bool IsFatal, Value *Message)
Generate a call to the runtime to emit the diagnostic of an OpenMP error directive with at(execution)...
LLVM_ABI void createOffloadEntry(Constant *ID, Constant *Addr, uint64_t Size, int32_t Flags, GlobalValue::LinkageTypes, StringRef Name="")
Creates offloading entry for the provided entry ID ID, address Addr, size Size, and flags Flags.
static LLVM_ABI unsigned getOpenMPDefaultSimdAlign(const Triple &TargetTriple, const StringMap< bool > &Features)
Get the default alignment value for given target.
LLVM_ABI unsigned getFlagMemberOffset()
Get the offset of the OMP_MAP_MEMBER_OF field.
LLVM_ABI InsertPointOrErrorTy createAtomicCapture(const LocationDescription &Loc, InsertPointTy AllocaIP, AtomicOpValue &X, AtomicOpValue &V, Value *Expr, AtomicOrdering AO, AtomicRMWInst::BinOp RMWOp, AtomicUpdateCallbackTy &UpdateOp, bool UpdateExpr, bool IsPostfixUpdate, bool IsXBinopExpr, bool IsIgnoreDenormalMode=false, bool IsFineGrainedMemory=false, bool IsRemoteMemory=false)
Emit atomic update for constructs: — Only Scalar data types V = X; X = X BinOp Expr ,...
LLVM_ABI CanonicalLoopInfo * createLoopSkeleton(DebugLoc DL, Value *TripCount, Function *F, BasicBlock *PreInsertBefore, BasicBlock *PostInsertBefore, const Twine &Name={}, bool IsCollapsed=false)
Create the control flow structure of a canonical OpenMP loop.
LLVM_ABI void createOffloadEntriesAndInfoMetadata(EmitMetadataErrorReportFunctionTy &ErrorReportFunction)
LLVM_ABI void applySimd(CanonicalLoopInfo *Loop, MapVector< Value *, Value * > AlignedVars, Value *IfCond, omp::OrderKind Order, ConstantInt *Simdlen, ConstantInt *Safelen)
Add metadata to simd-ize a loop.
SmallVector< std::unique_ptr< OutlineInfo >, 16 > OutlineInfos
Collection of regions that need to be outlined during finalization.
LLVM_ABI InsertPointOrErrorTy createAtomicUpdate(const LocationDescription &Loc, InsertPointTy AllocaIP, AtomicOpValue &X, Value *Expr, AtomicOrdering AO, AtomicRMWInst::BinOp RMWOp, AtomicUpdateCallbackTy &UpdateOp, bool IsXBinopExpr, bool IsIgnoreDenormalMode=false, bool IsFineGrainedMemory=false, bool IsRemoteMemory=false)
Emit atomic update for constructs: X = X BinOp Expr ,or X = Expr BinOp X For complex Operations: X = ...
std::function< std::tuple< std::string, uint64_t >()> FileIdentifierInfoCallbackTy
bool isLastFinalizationInfoCancellable(omp::Directive DK)
Return true if the last entry in the finalization stack is of kind DK and cancellable.
LLVM_ABI InsertPointTy emitTargetKernel(const LocationDescription &Loc, InsertPointTy AllocaIP, Value *&Return, Value *Ident, Value *DeviceID, Value *NumTeams, Value *NumThreads, Value *HostPtr, ArrayRef< Value * > KernelArgs)
Generate a target region entry call.
LLVM_ABI GlobalVariable * createOffloadMaptypes(SmallVectorImpl< uint64_t > &Mappings, std::string VarName)
Create the global variable holding the offload mappings information.
LLVM_ABI ~OpenMPIRBuilder()
LLVM_ABI Expected< Function * > emitUserDefinedMapper(function_ref< MapInfosOrErrorTy(InsertPointTy CodeGenIP, llvm::Value *PtrPHI, llvm::Value *BeginArg)> PrivAndGenMapInfoCB, llvm::Type *ElemTy, StringRef FuncName, CustomMapperCallbackTy CustomMapperCB, bool PreserveMemberOfFlags=false, bool PropagatePresentToPointee=false)
Emit the user-defined mapper function.
LLVM_ABI CallInst * createCachedThreadPrivate(const LocationDescription &Loc, llvm::Value *Pointer, llvm::ConstantInt *Size, const llvm::Twine &Name=Twine(""))
Create a runtime call for kmpc_threadprivate_cached.
IRBuilder Builder
The LLVM-IR Builder used to create IR.
LLVM_ABI GlobalValue * createGlobalFlag(unsigned Value, StringRef Name)
Create a hidden global flag Name in the module with initial value Value.
LLVM_ABI void emitOffloadingArraysArgument(IRBuilderBase &Builder, OpenMPIRBuilder::TargetDataRTArgs &RTArgs, OpenMPIRBuilder::TargetDataInfo &Info, bool ForEndCall=false)
Emit the arguments to be passed to the runtime library based on the arrays of base pointers,...
LLVM_ABI InsertPointOrErrorTy createMasked(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, Value *Filter)
Generator for 'omp masked'.
LLVM_ABI Expected< CanonicalLoopInfo * > createCanonicalLoop(const LocationDescription &Loc, LoopBodyGenCallbackTy BodyGenCB, Value *TripCount, const Twine &Name="loop")
Generator for the control flow structure of an OpenMP canonical loop.
function_ref< Expected< InsertPointTy >( InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Value *DestPtr, Value *SrcPtr)> TaskDupCallbackTy
Callback type for task duplication function code generation.
LLVM_ABI Value * getSizeInBytes(Value *BasePtr)
Computes the size of type in bytes.
llvm::function_ref< llvm::Error( InsertPointTy BodyIP, llvm::Value *LinearIV)> IteratorBodyGenTy
LLVM_ABI FunctionCallee createDispatchDeinitFunction()
Returns __kmpc_dispatch_deinit runtime function.
LLVM_ABI void registerTargetGlobalVariable(OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind CaptureClause, OffloadEntriesInfoManager::OMPTargetDeviceClauseKind DeviceClause, bool IsDeclaration, bool IsExternallyVisible, TargetRegionEntryInfo EntryInfo, StringRef MangledName, std::vector< GlobalVariable * > &GeneratedRefs, bool OpenMPSIMD, std::vector< Triple > TargetTriple, std::function< Constant *()> GlobalInitializer, std::function< GlobalValue::LinkageTypes()> VariableLinkage, Type *LlvmPtrTy, Constant *Addr)
Registers a target variable for device or host.
LLVM_ABI void createTargetDeinit(const LocationDescription &Loc, int32_t TeamsReductionDataSize=0)
Create a runtime call for kmpc_target_deinit.
BodyGenTy
Type of BodyGen to use for region codegen.
LLVM_ABI CanonicalLoopInfo * fuseLoops(DebugLoc DL, ArrayRef< CanonicalLoopInfo * > Loops)
Fuse a sequence of loops.
LLVM_ABI void emitX86DeclareSimdFunction(llvm::Function *Fn, unsigned NumElements, const llvm::APSInt &VLENVal, llvm::ArrayRef< DeclareSimdAttrTy > ParamAttrs, DeclareSimdBranch Branch)
Emit x86 vector-function ABI attributes for a declare simd function.
SmallVector< llvm::Function *, 16 > ConstantAllocaRaiseCandidates
A collection of candidate target functions that's constant allocas will attempt to be raised on a cal...
OffloadEntriesInfoManager OffloadInfoManager
Info manager to keep track of target regions.
static LLVM_ABI std::pair< int32_t, int32_t > readTeamBoundsForKernel(const Triple &T, Function &Kernel)
Read/write a bounds on teams for Kernel.
const std::string ompOffloadInfoName
OMP Offload Info Metadata name string.
LLVM_ABI InsertPointOrErrorTy applyWorkshareLoop(DebugLoc DL, CanonicalLoopInfo *CLI, InsertPointTy AllocaIP, bool NeedsBarrier, llvm::omp::ScheduleKind SchedKind=llvm::omp::OMP_SCHEDULE_Default, Value *ChunkSize=nullptr, bool HasSimdModifier=false, bool HasMonotonicModifier=false, bool HasNonmonotonicModifier=false, bool HasOrderedClause=false, omp::WorksharingLoopType LoopType=omp::WorksharingLoopType::ForStaticLoop, bool NoLoop=false, bool HasDistSchedule=false, Value *DistScheduleChunkSize=nullptr, bool NeedsLastIter=false)
Modifies the canonical loop to be a workshare loop.
Expected< InsertPointTy > InsertPointOrErrorTy
Type used to represent an insertion point or an error value.
LLVM_ABI InsertPointTy createCopyPrivate(const LocationDescription &Loc, llvm::Value *BufSize, llvm::Value *CpyBuf, llvm::Value *CpyFn, llvm::Value *DidIt)
Generator for __kmpc_copyprivate.
LLVM_ABI InsertPointOrErrorTy createSections(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< StorableBodyGenCallbackTy > SectionCBs, PrivatizeCallbackTy PrivCB, FinalizeCallbackTy FiniCB, bool IsCancellable, bool IsNowait)
Generator for 'omp sections'.
std::function< void(EmitMetadataErrorKind, TargetRegionEntryInfo)> EmitMetadataErrorReportFunctionTy
Callback function type.
function_ref< InsertPointOrErrorTy( Argument &Arg, Value *Input, Value *&RetVal, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, ArrayRef< InsertPointTy > DeallocIPs)> TargetGenArgAccessorsCallbackTy
LLVM_ABI Expected< ScanInfo * > scanInfoInitialize()
Creates a ScanInfo object, allocates and returns the pointer.
LLVM_ABI InsertPointOrErrorTy emitTargetTask(TargetTaskBodyCallbackTy TaskBodyCB, Value *DeviceID, Value *RTLoc, OpenMPIRBuilder::InsertPointTy AllocaIP, const DependenciesInfo &Dependencies, const TargetDataRTArgs &RTArgs, bool HasNoWait)
Generate a target-task for the target construct.
LLVM_ABI InsertPointTy createAtomicRead(const LocationDescription &Loc, AtomicOpValue &X, AtomicOpValue &V, AtomicOrdering AO, InsertPointTy AllocaIP)
Emit atomic Read for : V = X — Only Scalar data types.
function_ref< Error(InsertPointTy AllocaIP, InsertPointTy CodeGenIP, ArrayRef< BasicBlock * > DeallocBlocks)> BodyGenCallbackTy
Callback type for body (=inner region) code generation.
bool updateToLocation(const LocationDescription &Loc)
Update the internal location to Loc.
LLVM_ABI void createFlush(const LocationDescription &Loc)
Generator for 'omp flush'.
LLVM_ABI Constant * getAddrOfDeclareTargetVar(OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind CaptureClause, OffloadEntriesInfoManager::OMPTargetDeviceClauseKind DeviceClause, bool IsDeclaration, bool IsExternallyVisible, TargetRegionEntryInfo EntryInfo, StringRef MangledName, std::vector< GlobalVariable * > &GeneratedRefs, bool OpenMPSIMD, std::vector< Triple > TargetTriple, Type *LlvmPtrTy, std::function< Constant *()> GlobalInitializer, std::function< GlobalValue::LinkageTypes()> VariableLinkage)
Retrieve (or create if non-existent) the address of a declare target variable, used in conjunction wi...
LLVM_ABI void createTaskwait(const LocationDescription &Loc, DependenciesInfo Dependencies={}, bool IsNowait=false)
Generator for 'omp taskwait'.
origPtr *with the address space normalization required by the runtime entry point *The NULL descriptor makes the runtime walk the enclosing taskgroups to *find the matching task_reduction registration for the item The lookups *are emitted at p Loc
EmitMetadataErrorKind
The kind of errors that can occur when emitting the offload entries and metadata.
@ EMIT_MD_DECLARE_TARGET_ERROR
@ EMIT_MD_GLOBAL_VAR_INDIRECT_ERROR
@ EMIT_MD_GLOBAL_VAR_LINK_ERROR
@ EMIT_MD_TARGET_REGION_ERROR
unsigned getOpcode() const
Return the opcode for this Instruction or ConstantExpr.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
Pseudo-analysis pass that exposes the PassInstrumentation to pass managers.
Class to represent pointers.
static PointerType * getUnqual(LLVMContext &C)
This constructs an opaque pointer to an object in the default address space (address space zero).
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
Analysis pass that exposes the ScalarEvolution for a function.
LLVM_ABI ScalarEvolution run(Function &F, FunctionAnalysisManager &AM)
The main scalar evolution driver.
ScanInfo holds the information to assist in lowering of Scan reduction.
llvm::SmallDenseMap< llvm::Value *, llvm::Value * > * ScanBuffPtrs
Maps the private reduction variable to the pointer of the temporary buffer.
llvm::BasicBlock * OMPScanLoopExit
Exit block of loop body.
llvm::Value * IV
Keeps track of value of iteration variable for input/scan loop to be used for Scan directive lowering...
llvm::BasicBlock * OMPAfterScanBlock
Dominates the body of the loop before scan directive.
llvm::BasicBlock * OMPScanInit
Block before loop body where scan initializations are done.
llvm::BasicBlock * OMPBeforeScanBlock
Dominates the body of the loop before scan directive.
llvm::BasicBlock * OMPScanFinish
Block after loop body where scan finalizations are done.
llvm::Value * Span
Stores the span of canonical loop being lowered to be used for temporary buffer allocation or Finaliz...
bool OMPFirstScanLoop
If true, it indicates Input phase is lowered; else it indicates ScanPhase is lowered.
llvm::BasicBlock * OMPScanDispatch
Controls the flow to before or after scan blocks.
A vector that has set insertion semantics.
bool remove_if(UnaryPredicate P)
Remove items from the set vector based on a predicate function.
bool empty() const
Determine if the SetVector is empty or not.
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
bool test(unsigned Idx) const
Returns true if bit Idx is set.
bool all() const
Returns true if all bits are set.
bool any() const
Returns true if any bit is set.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void append(StringRef RHS)
Append from a StringRef.
StringRef str() const
Explicit conversion to StringRef.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
void setAlignment(Align Align)
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this store instruction.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
ValueTy lookup(StringRef Key) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
Represent a constant reference to a string, i.e.
std::string str() const
Get the contents as an std::string.
constexpr bool empty() const
Check if the string is empty.
constexpr size_t size() const
Get the string size.
size_t count(char C) const
Return the number of occurrences of C in the string.
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
Class to represent struct types.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
static LLVM_ABI StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Type * getElementType(unsigned N) const
LLVM_ABI void addCase(ConstantInt *OnVal, BasicBlock *Dest)
Add an entry to the switch instruction.
Analysis pass providing the TargetTransformInfo.
LLVM_ABI Result run(const Function &F, FunctionAnalysisManager &)
TargetTransformInfo Result
Analysis pass providing the TargetLibraryInfo.
Target - Wrapper for Target specific information.
TargetMachine * createTargetMachine(const Triple &TT, StringRef CPU, StringRef Features, const TargetOptions &Options, std::optional< Reloc::Model > RM, std::optional< CodeModel::Model > CM=std::nullopt, CodeGenOptLevel OL=CodeGenOptLevel::Default, bool JIT=false) const
createTargetMachine - Create a target specific machine implementation for the specified Triple.
Triple - Helper class for working with autoconf configuration names.
bool isPPC() const
Tests whether the target is PowerPC (32- or 64-bit LE or BE).
bool isX86() const
Tests whether the target is x86 (32- or 64-bit).
bool isWasm() const
Tests whether the target is wasm (32- and 64-bit).
bool isSystemZ() const
Tests whether the target is SystemZ.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
LLVM_ABI unsigned getIntegerBitWidth() const
LLVM_ABI Type * getStructElementType(unsigned N) const
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isPointerTy() const
True if this is an instance of PointerType.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
bool isStructTy() const
True if this is an instance of StructType.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
bool isVoidTy() const
Return true if this is 'void'.
Unconditional Branch instruction.
static UncondBrInst * Create(BasicBlock *Target, InsertPosition InsertBefore=nullptr)
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
This function has undefined behavior.
Produce an estimate of the unrolled cost of the specified loop.
LLVM_ABI bool canUnroll(OptimizationRemarkEmitter *ORE=nullptr, const Loop *L=nullptr) const
Whether it is legal to unroll this loop.
uint64_t getRolledLoopSize() const
A Use represents the edge between a Value definition and its users.
void setOperand(unsigned i, Value *Val)
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
LLVM_ABI bool hasNUses(unsigned N) const
Return true if this Value has exactly N uses.
LLVM_ABI User * getUniqueUndroppableUser()
Return true if there is exactly one unique user of this value that cannot be dropped (that user can h...
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
LLVM_ABI bool replaceUsesWithIf(Value *New, llvm::function_ref< bool(Use &U)> ShouldReplace)
Go through the uses list for this definition and make each use point to "V" if the callback ShouldRep...
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
A raw_ostream that writes to an SmallVector or SmallString.
The virtual file system interface.
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(const Twine &Name, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatile=false, bool IsText=true)
This is a convenience method that opens a file, gets its content and then closes the file.
virtual llvm::ErrorOr< Status > status(const Twine &Path)=0
Get the status of the entry at Path, if one exists.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ SPIR_KERNEL
Used for SPIR kernel functions.
@ PTX_Kernel
Call to a PTX kernel. Passes all arguments in parameter space.
@ BasicBlock
Various leaf nodes.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
Flag
These should be considered private to the implementation of the MCInstrDesc class.
constexpr StringLiteral MaxNTID("nvvm.maxntid")
constexpr StringLiteral MaxClusterRank("nvvm.maxclusterrank")
initializer< Ty > init(const Ty &Val)
@ User
could "use" a pointer
LLVM_ABI GlobalVariable * emitOffloadingEntry(Module &M, object::OffloadKind Kind, Constant *Addr, StringRef Name, uint64_t Size, uint32_t Flags, uint64_t Data, Constant *AuxAddr=nullptr)
OpenMPOffloadMappingFlags
Values for bit flags used to specify the mapping type for offloading.
@ OMP_MAP_PTR_AND_OBJ
The element being mapped is a pointer-pointee pair; both the pointer and the pointee should be mapped...
@ OMP_MAP_MEMBER_OF
The 16 MSBs of the flags indicate whether the entry is member of some struct/class.
IdentFlag
IDs for all omp runtime library ident_t flag encodings (see their defintion in openmp/runtime/src/kmp...
RuntimeFunction
IDs for all omp runtime library (RTL) functions.
constexpr const GV & getAMDGPUGridValues()
static constexpr GV SPIRVGridValues
For generic SPIR-V GPUs.
OMPDynGroupprivateFallbackType
The fallback types for the dyn_groupprivate clause.
static constexpr GV NVPTXGridValues
For Nvidia GPUs.
@ OMP_TGT_EXEC_MODE_SPMD_NO_LOOP
@ OMP_TGT_EXEC_MODE_GENERIC
Function * Kernel
Summary of a kernel (=entry point for target offloading).
WorksharingLoopType
A type of worksharing loop construct.
OMPAtomicCompareOp
Atomic compare operations. Currently OpenMP only supports ==, >, and <.
EnumSet< Property > Properties
NodeAddr< PhiNode * > Phi
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
LLVM_ABI BasicBlock * splitBBWithSuffix(IRBuilderBase &Builder, bool CreateBranch, llvm::Twine Suffix=".split")
Like splitBB, but reuses the current block's name for the new name.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
LLVM_ABI unsigned computeUnrollCount(Loop *L, const TargetTransformInfo &TTI, DominatorTree &DT, LoopInfo *LI, AssumptionCache *AC, ScalarEvolution &SE, const SmallPtrSetImpl< const Value * > &EphValues, OptimizationRemarkEmitter *ORE, unsigned TripCount, unsigned MaxTripCount, bool MaxOrZero, unsigned TripMultiple, const UnrollCostEstimator &UCE, TargetTransformInfo::UnrollingPreferences &UP, TargetTransformInfo::PeelingPreferences &PP)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
hash_code hash_value(const FixedPointSemantics &Val)
LLVM_ABI Expected< std::unique_ptr< Module > > parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context, ParserCallbacks Callbacks={})
Read the specified bitcode file, returning the module.
detail::zippy< detail::zip_first, T, U, Args... > zip_equal(T &&t, U &&u, Args &&...args)
zip iterator that assumes that all iteratees have the same length.
@ LLVM_MARK_AS_BITMASK_ENUM
LLVM_ABI BasicBlock * CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap, const Twine &NameSuffix="", Function *F=nullptr, ClonedCodeInfo *CodeInfo=nullptr, bool MapAtoms=true)
Return a copy of the specified basic block, but without embedding the block into a particular functio...
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
unsigned getPointerAddressSpace(const Type *T)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto successors(const MachineBasicBlock *BB)
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
testing::Matcher< const detail::ErrorHolder & > Failed()
constexpr from_range_t from_range
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE()
LLVM_ABI BasicBlock * splitBB(IRBuilderBase::InsertPoint IP, bool CreateBranch, DebugLoc DL, llvm::Twine Name={})
Split a BasicBlock at an InsertPoint, even if the block is degenerate (missing the terminator).
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
LLVM_ABI TargetTransformInfo::UnrollingPreferences gatherUnrollingPreferences(Loop *L, ScalarEvolution &SE, const TargetTransformInfo &TTI, BlockFrequencyInfo *BFI, ProfileSummaryInfo *PSI, llvm::OptimizationRemarkEmitter &ORE, int OptLevel, std::optional< unsigned > UserThreshold, std::optional< bool > UserAllowPartial, std::optional< bool > UserRuntime, std::optional< bool > UserUpperBound, std::optional< unsigned > UserFullUnrollMaxCount)
Gather the various unrolling parameters based on the defaults, compiler flags, TTI overrides and user...
std::string utostr(uint64_t X, bool isNeg=false)
ErrorOr< T > expectedToErrorOrAndEmitErrors(LLVMContext &Ctx, Expected< T > Val)
bool isa_and_nonnull(const Y &Val)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto dyn_cast_or_null(const Y &Val)
LLVM_ABI bool convertUsersOfConstantsToInstructions(ArrayRef< Constant * > Consts, Function *RestrictToFunc=nullptr, bool RemoveDeadConstants=true, bool IncludeSelf=false)
Replace constant expressions users of the given constants with instructions.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
auto reverse(ContainerTy &&C)
LLVM_ABI TargetTransformInfo::PeelingPreferences gatherPeelingPreferences(Loop *L, ScalarEvolution &SE, const TargetTransformInfo &TTI, std::optional< bool > UserAllowPeeling, std::optional< bool > UserAllowProfileBasedPeeling, bool UnrollingSpecficValues=false)
LLVM_ABI void SplitBlockAndInsertIfThenElse(Value *Cond, BasicBlock::iterator SplitBefore, Instruction **ThenTerm, Instruction **ElseTerm, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr)
SplitBlockAndInsertIfThenElse is similar to SplitBlockAndInsertIfThen, but also creates the ElseBlock...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
CodeGenOptLevel
Code generation optimization level.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
AtomicOrdering
Atomic ordering for LLVM's memory model.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
LLVM_ABI bool MergeBlockIntoPredecessor(BasicBlock *BB, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, MemoryDependenceResults *MemDep=nullptr, bool PredecessorWithTwoSuccessors=false, DominatorTree *DT=nullptr)
Attempts to merge a block into its predecessor, if possible.
@ Mul
Product of integers.
LLVM_ABI BasicBlock * SplitBlock(BasicBlock *Old, BasicBlock::iterator SplitPt, DominatorTree *DT, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, const Twine &BBName="")
Split the specified block at the specified instruction.
DWARFExpression::Operation Op
LLVM_ABI void remapInstructionsInBlocks(ArrayRef< BasicBlock * > Blocks, ValueToValueMapTy &VMap)
Remaps instructions in Blocks using the mapping in VMap.
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
constexpr unsigned BitWidth
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
LLVM_ABI void spliceBB(IRBuilderBase::InsertPoint IP, BasicBlock *New, bool CreateBranch, DebugLoc DL)
Move the instruction after an InsertPoint to the beginning of another BasicBlock.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
auto predecessors(const MachineBasicBlock *BB)
auto filter_to_vector(ContainerTy &&C, PredicateFn &&Pred)
Filter a range to a SmallVector with the element types deduced.
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
LLVM_ABI Constant * ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val, ArrayRef< unsigned > Idxs)
Attempt to constant fold an insertvalue instruction with the specified operands and indices.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI void DeleteDeadBlocks(ArrayRef< BasicBlock * > BBs, DomTreeUpdater *DTU=nullptr, bool KeepOneInputPHIs=false)
Delete the specified blocks from BB.
bool to_integer(StringRef S, N &Num, unsigned Base=0)
Convert the string S to an integer of the specified type using the radix Base. If Base is 0,...
@ End
Run the machine verifier once, at the end of the pipeline.
static auto filterDbgVars(iterator_range< simple_ilist< DbgRecord >::iterator > R)
Filter the DbgRecord range to DbgVariableRecord types only and downcast.
This struct is a compact representation of a valid (non-zero power of two) alignment.
static LLVM_ABI void collectEphemeralValues(const Loop *L, AssumptionCache *AC, SmallPtrSetImpl< const Value * > &EphValues)
Collect a loop's ephemeral values (those used only by an assume or similar intrinsics in the loop).
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
A struct to pack the relevant information for an OpenMP affinity clause.
a struct to pack relevant information while generating atomic Ops
A struct to pack the relevant information for an OpenMP depend clause.
omp::RTLDependenceKindTy DepKind
A struct to pack static and dynamic dependency information for a task.
SmallVector< DependData > Deps
LLVM_ABI Error mergeFiniBB(IRBuilderBase &Builder, BasicBlock *ExistingFiniBB)
For cases where there is an unavoidable existing finalization block (e.g.
LLVM_ABI Expected< BasicBlock * > getFiniBB(IRBuilderBase &Builder)
The basic block to which control should be transferred to implement the FiniCB.
Description of a LLVM-IR insertion point (IP) and a debug/source location (filename,...
MapNonContiguousArrayTy Offsets
MapNonContiguousArrayTy Counts
MapNonContiguousArrayTy Strides
This structure contains combined information generated for mappable clauses, including base pointers,...
MapDeviceInfoArrayTy DevicePointers
MapValuesArrayTy BasePointers
MapValuesArrayTy Pointers
StructNonContiguousInfo NonContigInfo
Helper that contains information about regions we need to outline during finalization.
void collectBlocks(SmallPtrSetImpl< BasicBlock * > &BlockSet, SmallVectorImpl< BasicBlock * > &BlockVector)
Collect all blocks in between EntryBB and ExitBB in both the given vector and set.
BasicBlock * OuterAllocBB
virtual std::unique_ptr< CodeExtractor > createCodeExtractor(ArrayRef< BasicBlock * > Blocks, bool ArgsInZeroAddressSpace, Twine Suffix=Twine(""))
Create a CodeExtractor instance based on the information stored in this structure,...
Information about an OpenMP reduction.
EvalKind EvaluationKind
Reduction evaluation kind - scalar, complex or aggregate.
ReductionGenAtomicCBTy AtomicReductionGen
Callback for generating the atomic reduction body, may be null.
ReductionGenCBTy ReductionGen
Callback for generating the reduction body.
Value * Variable
Reduction variable of pointer type.
Value * PrivateVariable
Thread-private partial reduction variable.
ReductionGenClangCBTy ReductionGenClang
Clang callback for generating the reduction body.
Type * ElementType
Reduction element type, must match pointee type of variable.
ReductionGenDataPtrPtrCBTy DataPtrPtrGen
Container for the arguments used to pass data to the runtime library.
Value * SizesArray
The array of sizes passed to the runtime library.
Value * PointersArray
The array of section pointers passed to the runtime library.
Value * MappersArray
The array of user-defined mappers passed to the runtime library.
Value * MapTypesArrayEnd
The array of map types passed to the runtime library for the end of the region, or nullptr if there a...
Value * BasePointersArray
The array of base pointer passed to the runtime library.
Value * MapTypesArray
The array of map types passed to the runtime library for the beginning of the region or for the entir...
Value * MapNamesArray
The array of original declaration names of mapped pointers sent to the runtime library for debugging.
Data structure that contains the needed information to construct the kernel args vector.
bool StrictBlocks
True if the kernel strictly requires the number of blocks and threads above to run.
ArrayRef< Value * > NumThreads
The number of threads.
TargetDataRTArgs RTArgs
Arguments passed to the runtime library.
Value * NumIterations
The number of iterations.
Value * DynCGroupMem
The size of the dynamic shared memory.
unsigned NumTargetItems
Number of arguments passed to the runtime library.
bool HasNoWait
True if the kernel has 'no wait' clause.
ArrayRef< Value * > NumTeams
The number of teams.
omp::OMPDynGroupprivateFallbackType DynCGroupMemFallback
The fallback mechanism for the shared memory.
Container to pass the default attributes with which a kernel must be launched, used to set kernel att...
omp::OMPTgtExecModeFlags ExecFlags
SmallVector< int32_t, 3 > MaxTeams
Container to pass LLVM IR runtime values or constants related to the number of teams and threads with...
Value * DeviceID
Device ID value used in the kernel launch.
SmallVector< Value *, 3 > MaxTeams
Value * LoopTripCount
Total number of iterations of the SPMD or Generic-SPMD kernel or null if it is a generic kernel.
SmallVector< Value *, 3 > TargetThreadLimit
SmallVector< Value *, 3 > TeamsThreadLimit
SmallVector< Value * > MaxThreads
'parallel' construct 'num_threads' clause value, if present and it is an SPMD kernel.
Data structure to contain the information needed to uniquely identify a target entry.
static LLVM_ABI void getTargetRegionEntryFnName(SmallVectorImpl< char > &Name, StringRef ParentName, unsigned DeviceID, unsigned FileID, unsigned Line, unsigned Count)
static constexpr const char * KernelNamePrefix
The prefix used for kernel names.
static LLVM_ABI const Target * lookupTarget(const Triple &TheTriple, std::string &Error)
lookupTarget - Lookup a target based on a target triple.
Defines various target-specific GPU grid values that must be consistent between host RTL (plugin),...