70#define DEBUG_TYPE "openmp-ir-builder"
77 cl::desc(
"Use optimistic attributes describing "
78 "'as-if' properties of runtime calls."),
82 "openmp-ir-builder-unroll-threshold-factor",
cl::Hidden,
83 cl::desc(
"Factor for the unroll threshold to account for code "
84 "simplifications still taking place"),
88 "openmp-ir-builder-use-default-max-threads",
cl::Hidden,
99 if (!IP1.isSet() || !IP2.isSet())
101 return IP1.getBlock() == IP2.getBlock() && IP1.getPoint() == IP2.getPoint();
106 switch (SchedType & ~OMPScheduleType::MonotonicityMask) {
107 case OMPScheduleType::UnorderedStaticChunked:
108 case OMPScheduleType::UnorderedStatic:
109 case OMPScheduleType::UnorderedDynamicChunked:
110 case OMPScheduleType::UnorderedGuidedChunked:
111 case OMPScheduleType::UnorderedRuntime:
112 case OMPScheduleType::UnorderedAuto:
113 case OMPScheduleType::UnorderedTrapezoidal:
114 case OMPScheduleType::UnorderedGreedy:
115 case OMPScheduleType::UnorderedBalanced:
116 case OMPScheduleType::UnorderedGuidedIterativeChunked:
117 case OMPScheduleType::UnorderedGuidedAnalyticalChunked:
118 case OMPScheduleType::UnorderedSteal:
119 case OMPScheduleType::UnorderedStaticBalancedChunked:
120 case OMPScheduleType::UnorderedGuidedSimd:
121 case OMPScheduleType::UnorderedRuntimeSimd:
122 case OMPScheduleType::OrderedStaticChunked:
123 case OMPScheduleType::OrderedStatic:
124 case OMPScheduleType::OrderedDynamicChunked:
125 case OMPScheduleType::OrderedGuidedChunked:
126 case OMPScheduleType::OrderedRuntime:
127 case OMPScheduleType::OrderedAuto:
128 case OMPScheduleType::OrderdTrapezoidal:
129 case OMPScheduleType::NomergeUnorderedStaticChunked:
130 case OMPScheduleType::NomergeUnorderedStatic:
131 case OMPScheduleType::NomergeUnorderedDynamicChunked:
132 case OMPScheduleType::NomergeUnorderedGuidedChunked:
133 case OMPScheduleType::NomergeUnorderedRuntime:
134 case OMPScheduleType::NomergeUnorderedAuto:
135 case OMPScheduleType::NomergeUnorderedTrapezoidal:
136 case OMPScheduleType::NomergeUnorderedGreedy:
137 case OMPScheduleType::NomergeUnorderedBalanced:
138 case OMPScheduleType::NomergeUnorderedGuidedIterativeChunked:
139 case OMPScheduleType::NomergeUnorderedGuidedAnalyticalChunked:
140 case OMPScheduleType::NomergeUnorderedSteal:
141 case OMPScheduleType::NomergeOrderedStaticChunked:
142 case OMPScheduleType::NomergeOrderedStatic:
143 case OMPScheduleType::NomergeOrderedDynamicChunked:
144 case OMPScheduleType::NomergeOrderedGuidedChunked:
145 case OMPScheduleType::NomergeOrderedRuntime:
146 case OMPScheduleType::NomergeOrderedAuto:
147 case OMPScheduleType::NomergeOrderedTrapezoidal:
148 case OMPScheduleType::OrderedDistributeChunked:
149 case OMPScheduleType::OrderedDistribute:
157 SchedType & OMPScheduleType::MonotonicityMask;
158 if (MonotonicityFlags == OMPScheduleType::MonotonicityMask)
170 Builder.restoreIP(IP);
178 return T.isAMDGPU() ||
T.isNVPTX() ||
T.isSPIRV();
184 Kernel->getFnAttribute(
"target-features").getValueAsString();
185 if (Features.
count(
"+wavefrontsize64"))
200 bool HasSimdModifier,
bool HasDistScheduleChunks) {
202 switch (ClauseKind) {
203 case OMP_SCHEDULE_Default:
204 case OMP_SCHEDULE_Static:
205 return HasChunks ? OMPScheduleType::BaseStaticChunked
206 : OMPScheduleType::BaseStatic;
207 case OMP_SCHEDULE_Dynamic:
208 return OMPScheduleType::BaseDynamicChunked;
209 case OMP_SCHEDULE_Guided:
210 return HasSimdModifier ? OMPScheduleType::BaseGuidedSimd
211 : OMPScheduleType::BaseGuidedChunked;
212 case OMP_SCHEDULE_Auto:
214 case OMP_SCHEDULE_Runtime:
215 return HasSimdModifier ? OMPScheduleType::BaseRuntimeSimd
216 : OMPScheduleType::BaseRuntime;
217 case OMP_SCHEDULE_Distribute:
218 return HasDistScheduleChunks ? OMPScheduleType::BaseDistributeChunked
219 : OMPScheduleType::BaseDistribute;
227 bool HasOrderedClause) {
228 assert((BaseScheduleType & OMPScheduleType::ModifierMask) ==
229 OMPScheduleType::None &&
230 "Must not have ordering nor monotonicity flags already set");
233 ? OMPScheduleType::ModifierOrdered
234 : OMPScheduleType::ModifierUnordered;
235 OMPScheduleType OrderingScheduleType = BaseScheduleType | OrderingModifier;
238 if (OrderingScheduleType ==
239 (OMPScheduleType::BaseGuidedSimd | OMPScheduleType::ModifierOrdered))
240 return OMPScheduleType::OrderedGuidedChunked;
241 else if (OrderingScheduleType == (OMPScheduleType::BaseRuntimeSimd |
242 OMPScheduleType::ModifierOrdered))
243 return OMPScheduleType::OrderedRuntime;
245 return OrderingScheduleType;
251 bool HasSimdModifier,
bool HasMonotonic,
252 bool HasNonmonotonic,
bool HasOrderedClause) {
253 assert((ScheduleType & OMPScheduleType::MonotonicityMask) ==
254 OMPScheduleType::None &&
255 "Must not have monotonicity flags already set");
256 assert((!HasMonotonic || !HasNonmonotonic) &&
257 "Monotonic and Nonmonotonic are contradicting each other");
260 return ScheduleType | OMPScheduleType::ModifierMonotonic;
261 }
else if (HasNonmonotonic) {
262 return ScheduleType | OMPScheduleType::ModifierNonmonotonic;
272 if ((BaseScheduleType == OMPScheduleType::BaseStatic) ||
273 (BaseScheduleType == OMPScheduleType::BaseStaticChunked) ||
279 return ScheduleType | OMPScheduleType::ModifierNonmonotonic;
287 bool HasSimdModifier,
bool HasMonotonicModifier,
288 bool HasNonmonotonicModifier,
bool HasOrderedClause,
289 bool HasDistScheduleChunks) {
291 ClauseKind, HasChunks, HasSimdModifier, HasDistScheduleChunks);
295 OrderedSchedule, HasSimdModifier, HasMonotonicModifier,
296 HasNonmonotonicModifier, HasOrderedClause);
304static std::optional<omp::OMPTgtExecModeFlags>
309 if (
Call->getCalledFunction()->getName() ==
"__kmpc_target_init") {
310 TargetInitCall =
Call;
335 std::optional<omp::OMPTgtExecModeFlags> ExecMode =
347 if (
Instruction *Term = Source->getTerminatorOrNull()) {
356 NewBr->setDebugLoc(
DL);
361 assert(New->getFirstInsertionPt() == New->begin() &&
362 "Target BB must not have PHI nodes");
378 New->splice(New->begin(), Old, IP.
getPoint(), Old->
end());
382 NewBr->setDebugLoc(
DL);
394 Builder.SetInsertPoint(Old);
398 Builder.SetCurrentDebugLocation(
DebugLoc);
408 New->replaceSuccessorsPhiUsesWith(Old, New);
417 Builder.SetInsertPoint(Builder.GetInsertBlock()->getTerminator());
419 Builder.SetInsertPoint(Builder.GetInsertBlock());
422 Builder.SetCurrentDebugLocation(
DebugLoc);
431 Builder.SetInsertPoint(Builder.GetInsertBlock()->getTerminator());
433 Builder.SetInsertPoint(Builder.GetInsertBlock());
436 Builder.SetCurrentDebugLocation(
DebugLoc);
453 const Twine &Name =
"",
bool AsPtr =
true,
454 bool Is64Bit =
false) {
455 Builder.restoreIP(OuterAllocaIP);
459 Builder.CreateAlloca(IntTy,
nullptr, Name +
".addr");
463 FakeVal = FakeValAddr;
465 FakeVal = Builder.CreateLoad(IntTy, FakeValAddr, Name +
".val");
470 Builder.restoreIP(InnerAllocaIP);
473 UseFakeVal = Builder.CreateLoad(IntTy, FakeVal, Name +
".use");
476 FakeVal, Is64Bit ? Builder.getInt64(10) : Builder.getInt32(10)));
489enum OpenMPOffloadingRequiresDirFlags {
491 OMP_REQ_UNDEFINED = 0x000,
493 OMP_REQ_NONE = 0x001,
495 OMP_REQ_REVERSE_OFFLOAD = 0x002,
497 OMP_REQ_UNIFIED_ADDRESS = 0x004,
499 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008,
501 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010,
508 DominatorTree *DT =
nullptr,
bool AggregateArgs =
false,
509 BlockFrequencyInfo *BFI =
nullptr,
510 BranchProbabilityInfo *BPI =
nullptr,
511 AssumptionCache *AC =
nullptr,
bool AllowVarArgs =
false,
512 bool AllowAlloca =
false,
513 BasicBlock *AllocationBlock =
nullptr,
515 std::string Suffix =
"",
bool ArgsInZeroAddressSpace =
false)
516 : CodeExtractor(BBs, DT, AggregateArgs, BFI, BPI, AC, AllowVarArgs,
517 AllowAlloca, AllocationBlock, DeallocationBlocks, Suffix,
518 ArgsInZeroAddressSpace),
519 OMPBuilder(OMPBuilder) {}
521 virtual ~OMPCodeExtractor() =
default;
524 OpenMPIRBuilder &OMPBuilder;
527class DeviceSharedMemCodeExtractor :
public OMPCodeExtractor {
529 using OMPCodeExtractor::OMPCodeExtractor;
530 virtual ~DeviceSharedMemCodeExtractor() =
default;
534 allocateVar(IRBuilder<>::InsertPoint AllocaIP,
Type *VarType,
535 const Twine &Name = Twine(
""),
536 AddrSpaceCastInst **CastedAlloc =
nullptr)
override {
537 return OMPBuilder.createOMPAllocShared(AllocaIP, VarType, Name);
540 virtual Instruction *deallocateVar(IRBuilder<>::InsertPoint DeallocIP,
542 return OMPBuilder.createOMPFreeShared(DeallocIP, Var, VarType);
549 OpenMPIRBuilder &OMPBuilder;
551 DeviceSharedMemOutlineInfo(OpenMPIRBuilder &OMPBuilder)
552 : OMPBuilder(OMPBuilder) {}
553 virtual ~DeviceSharedMemOutlineInfo() =
default;
555 virtual std::unique_ptr<CodeExtractor>
557 bool ArgsInZeroAddressSpace,
558 Twine Suffix = Twine(
""))
override;
564 : RequiresFlags(OMP_REQ_UNDEFINED) {}
568 bool HasRequiresReverseOffload,
bool HasRequiresUnifiedAddress,
569 bool HasRequiresUnifiedSharedMemory,
bool HasRequiresDynamicAllocators)
572 RequiresFlags(OMP_REQ_UNDEFINED) {
573 if (HasRequiresReverseOffload)
574 RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
575 if (HasRequiresUnifiedAddress)
576 RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
577 if (HasRequiresUnifiedSharedMemory)
578 RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
579 if (HasRequiresDynamicAllocators)
580 RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
584 return RequiresFlags & OMP_REQ_REVERSE_OFFLOAD;
588 return RequiresFlags & OMP_REQ_UNIFIED_ADDRESS;
592 return RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY;
596 return RequiresFlags & OMP_REQ_DYNAMIC_ALLOCATORS;
601 :
static_cast<int64_t
>(OMP_REQ_NONE);
606 RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
608 RequiresFlags &= ~OMP_REQ_REVERSE_OFFLOAD;
613 RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
615 RequiresFlags &= ~OMP_REQ_UNIFIED_ADDRESS;
620 RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
622 RequiresFlags &= ~OMP_REQ_UNIFIED_SHARED_MEMORY;
627 RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
629 RequiresFlags &= ~OMP_REQ_DYNAMIC_ALLOCATORS;
642 constexpr size_t MaxDim = 3;
647 Value *DynCGroupMemFallbackFlag =
649 DynCGroupMemFallbackFlag =
Builder.CreateShl(DynCGroupMemFallbackFlag, 2);
652 StrictFlag =
Builder.CreateShl(StrictFlag, 6);
654 Value *Flags =
Builder.CreateOr(HasNoWaitFlag, DynCGroupMemFallbackFlag);
655 Flags =
Builder.CreateOr(Flags, StrictFlag);
661 Value *NumThreads3D =
692 auto FnAttrs = Attrs.getFnAttrs();
693 auto RetAttrs = Attrs.getRetAttrs();
695 for (
size_t ArgNo = 0; ArgNo < Fn.
arg_size(); ++ArgNo)
700 bool Param =
true) ->
void {
701 bool HasSignExt = AS.hasAttribute(Attribute::SExt);
702 bool HasZeroExt = AS.hasAttribute(Attribute::ZExt);
703 if (HasSignExt || HasZeroExt) {
704 assert(AS.getNumAttributes() == 1 &&
705 "Currently not handling extension attr combined with others.");
707 if (
auto AK = TargetLibraryInfo::getExtAttrForI32Param(
T, HasSignExt))
710 TargetLibraryInfo::getExtAttrForI32Return(
T, HasSignExt))
717#define OMP_ATTRS_SET(VarName, AttrSet) AttributeSet VarName = AttrSet;
718#include "llvm/Frontend/OpenMP/OMPKinds.def"
722#define OMP_RTL_ATTRS(Enum, FnAttrSet, RetAttrSet, ArgAttrSets) \
724 FnAttrs = FnAttrs.addAttributes(Ctx, FnAttrSet); \
725 addAttrSet(RetAttrs, RetAttrSet, false); \
726 for (size_t ArgNo = 0; ArgNo < ArgAttrSets.size(); ++ArgNo) \
727 addAttrSet(ArgAttrs[ArgNo], ArgAttrSets[ArgNo]); \
728 Fn.setAttributes(AttributeList::get(Ctx, FnAttrs, RetAttrs, ArgAttrs)); \
730#include "llvm/Frontend/OpenMP/OMPKinds.def"
744#define OMP_RTL(Enum, Str, IsVarArg, ReturnType, ...) \
746 FnTy = FunctionType::get(ReturnType, ArrayRef<Type *>{__VA_ARGS__}, \
748 Fn = M.getFunction(Str); \
750#include "llvm/Frontend/OpenMP/OMPKinds.def"
756#define OMP_RTL(Enum, Str, ...) \
758 Fn = Function::Create(FnTy, GlobalValue::ExternalLinkage, Str, M); \
760#include "llvm/Frontend/OpenMP/OMPKinds.def"
764 if (FnID == OMPRTL___kmpc_fork_call || FnID == OMPRTL___kmpc_fork_teams) {
774 LLVMContext::MD_callback,
776 2, {-1, -1},
true)}));
789 assert(Fn &&
"Failed to create OpenMP runtime function");
800 Builder.SetInsertPoint(FiniBB);
812 FiniBB = OtherFiniBB;
814 Builder.SetInsertPoint(FiniBB->getFirstNonPHIIt());
822 auto EndIt = FiniBB->end();
823 if (FiniBB->size() >= 1)
824 if (
auto Prev = std::prev(EndIt); Prev->isTerminator())
829 FiniBB->replaceAllUsesWith(OtherFiniBB);
830 FiniBB->eraseFromParent();
831 FiniBB = OtherFiniBB;
838 assert(Fn &&
"Failed to create OpenMP runtime function pointer");
861 for (
auto Inst =
Block->getReverseIterator()->begin();
862 Inst !=
Block->getReverseIterator()->end();) {
891 Block.getParent()->getEntryBlock().getTerminator()->getIterator();
912 DeferredOutlines.
push_back(std::move(OI));
916 ParallelRegionBlockSet.
clear();
918 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
928 bool ArgsInZeroAddressSpace =
Config.isTargetDevice();
929 std::unique_ptr<CodeExtractor> Extractor =
930 OI->createCodeExtractor(Blocks, ArgsInZeroAddressSpace,
".omp_par");
934 <<
" Exit: " << OI->ExitBB->getName() <<
"\n");
935 assert(Extractor->isEligible() &&
936 "Expected OpenMP outlining to be possible!");
938 for (
auto *V : OI->ExcludeArgsFromAggregate)
939 Extractor->excludeArgFromAggregate(V);
942 Extractor->extractCodeRegion(CEAC, OI->Inputs, OI->Outputs);
946 if (TargetCpuAttr.isStringAttribute())
949 auto TargetFeaturesAttr = OuterFn->
getFnAttribute(
"target-features");
950 if (TargetFeaturesAttr.isStringAttribute())
951 OutlinedFn->
addFnAttr(TargetFeaturesAttr);
954 LLVM_DEBUG(
dbgs() <<
" Outlined function: " << *OutlinedFn <<
"\n");
956 "OpenMP outlined functions should not return a value!");
961 M.getFunctionList().insertAfter(OuterFn->
getIterator(), OutlinedFn);
968 assert(OI->EntryBB->getUniquePredecessor() == &ArtificialEntry);
975 "Expected instructions to add in the outlined region entry");
977 End = ArtificialEntry.
rend();
982 if (
I.isTerminator()) {
984 if (
Instruction *TI = OI->EntryBB->getTerminatorOrNull())
985 TI->adoptDbgRecords(&ArtificialEntry,
I.getIterator(),
false);
989 I.moveBeforePreserving(*OI->EntryBB,
990 OI->EntryBB->getFirstInsertionPt());
993 OI->EntryBB->moveBefore(&ArtificialEntry);
1000 if (OI->PostOutlineCB)
1001 OI->PostOutlineCB(*OutlinedFn);
1003 if (OI->FixUpNonEntryAllocas)
1035 errs() <<
"Error of kind: " << Kind
1036 <<
" when emitting offload entries and metadata during "
1037 "OMPIRBuilder finalization \n";
1043 if (
Config.EmitLLVMUsedMetaInfo.value_or(
false)) {
1044 std::vector<WeakTrackingVH> LLVMCompilerUsed = {
1045 M.getGlobalVariable(
"__openmp_nvptx_data_transfer_temporary_storage")};
1046 emitUsed(
"llvm.compiler.used", LLVMCompilerUsed);
1063 ConstantInt::get(I32Ty,
Value), Name);
1076 for (
unsigned I = 0, E =
List.size();
I != E; ++
I)
1080 if (UsedArray.
empty())
1087 GV->setSection(
"llvm.metadata");
1093 auto *Int8Ty =
Builder.getInt8Ty();
1096 ConstantInt::get(Int8Ty, Mode),
Twine(KernelName,
"_exec_mode"));
1104 unsigned Reserve2Flags) {
1106 LocFlags |= OMP_IDENT_FLAG_KMPC;
1113 ConstantInt::get(Int32,
uint32_t(LocFlags)),
1114 ConstantInt::get(Int32, Reserve2Flags),
1115 ConstantInt::get(Int32, SrcLocStrSize), SrcLocStr};
1117 size_t SrcLocStrArgIdx = 4;
1118 if (OpenMPIRBuilder::Ident->getElementType(SrcLocStrArgIdx)
1122 SrcLocStr, OpenMPIRBuilder::Ident->getElementType(SrcLocStrArgIdx));
1129 if (
GV.getValueType() == OpenMPIRBuilder::Ident &&
GV.hasInitializer())
1130 if (
GV.getInitializer() == Initializer)
1135 M, OpenMPIRBuilder::Ident,
1138 M.getDataLayout().getDefaultGlobalsAddressSpace());
1150 SrcLocStrSize = LocStr.
size();
1159 if (
GV.isConstant() &&
GV.hasInitializer() &&
1160 GV.getInitializer() == Initializer)
1163 SrcLocStr =
Builder.CreateGlobalString(
1164 LocStr,
"",
M.getDataLayout().getDefaultGlobalsAddressSpace(),
1172 unsigned Line,
unsigned Column,
1178 Buffer.
append(FunctionName);
1180 Buffer.
append(std::to_string(Line));
1182 Buffer.
append(std::to_string(Column));
1190 StringRef UnknownLoc =
";unknown;unknown;0;0;;";
1201 !DIL->getFilename().empty() ? DIL->getFilename() :
M.getName();
1206 DIL->getColumn(), SrcLocStrSize);
1212 Loc.IP.getBlock()->getParent());
1218 "omp_global_thread_num");
1226 "expected one result pointer type per in_reduction item");
1229 if (OrigPtrs.
empty())
1230 return Builder.saveIP();
1249 for (
unsigned Idx = 0; Idx < OrigPtrs.
size(); ++Idx) {
1252 Value *OrigPtr = OrigPtrs[Idx];
1254 OrigPtrTy && OrigPtrTy->getAddressSpace() != 0)
1255 OrigPtr = Builder.CreateAddrSpaceCast(OrigPtr, PtrTy);
1257 Value *
Priv = Builder.CreateCall(GetThData, {Gtid, NullDesc, OrigPtr},
1263 ResPtrTy && ResPtrTy->getAddressSpace() != 0)
1264 Priv = Builder.CreateAddrSpaceCast(
Priv, ResultPtrTys[Idx]);
1266 MapPrivateCB(Idx,
Priv);
1273 bool ForceSimpleCall,
bool CheckCancelFlag) {
1283 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_FOR;
1286 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SECTIONS;
1289 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SINGLE;
1292 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_EXPL;
1295 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL;
1308 bool UseCancelBarrier =
1313 ? OMPRTL___kmpc_cancel_barrier
1314 : OMPRTL___kmpc_barrier),
1317 if (UseCancelBarrier && CheckCancelFlag)
1327 omp::Directive CanceledDirective) {
1332 auto *UI =
Builder.CreateUnreachable();
1340 Builder.SetInsertPoint(ElseTI);
1341 auto ElseIP =
Builder.saveIP();
1349 Builder.SetInsertPoint(ThenTI);
1351 Value *CancelKind =
nullptr;
1352 switch (CanceledDirective) {
1353#define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) \
1354 case DirectiveEnum: \
1355 CancelKind = Builder.getInt32(Value); \
1357#include "llvm/Frontend/OpenMP/OMPKinds.def"
1374 Builder.SetInsertPoint(UI->getParent());
1375 UI->eraseFromParent();
1382 omp::Directive CanceledDirective) {
1387 auto *UI =
Builder.CreateUnreachable();
1390 Value *CancelKind =
nullptr;
1391 switch (CanceledDirective) {
1392#define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) \
1393 case DirectiveEnum: \
1394 CancelKind = Builder.getInt32(Value); \
1396#include "llvm/Frontend/OpenMP/OMPKinds.def"
1413 Builder.SetInsertPoint(UI->getParent());
1414 UI->eraseFromParent();
1427 auto *KernelArgsPtr =
1428 Builder.CreateAlloca(OpenMPIRBuilder::KernelArgs,
nullptr,
"kernel_args");
1433 Builder.CreateStructGEP(OpenMPIRBuilder::KernelArgs, KernelArgsPtr,
I);
1436 M.getDataLayout().getPrefTypeAlign(KernelArgs[
I]->getType()));
1440 NumThreads, HostPtr, KernelArgsPtr};
1467 assert(OutlinedFnID &&
"Invalid outlined function ID!");
1471 Value *Return =
nullptr;
1491 Builder, AllocaIP, Return, RTLoc, DeviceID, Args.NumTeams.front(),
1492 Args.NumThreads.front(), OutlinedFnID, ArgsVector));
1499 Builder.CreateCondBr(
Failed, OffloadFailedBlock, OffloadContBlock);
1501 auto CurFn =
Builder.GetInsertBlock()->getParent();
1508 emitBlock(OffloadContBlock, CurFn,
true);
1513 Value *CancelFlag, omp::Directive CanceledDirective) {
1515 "Unexpected cancellation!");
1535 Builder.CreateCondBr(Cmp, NonCancellationBlock, CancellationBlock,
1544 Builder.SetInsertPoint(CancellationBlock);
1545 Builder.CreateBr(*FiniBBOrErr);
1548 Builder.SetInsertPoint(NonCancellationBlock, NonCancellationBlock->
begin());
1560 size_t NumArgs = OutlinedFn.
arg_size();
1561 assert((NumArgs == 2 || NumArgs == 3) &&
1562 "expected a 2-3 argument parallel outlined function");
1563 bool UseArgStruct = NumArgs == 3;
1568 {Builder.getInt16Ty(), Builder.getInt32Ty()},
1572 OutlinedFn.
getName() +
".wrapper", OMPIRBuilder->
M);
1574 WrapperFn->addParamAttr(0, Attribute::NoUndef);
1575 WrapperFn->addParamAttr(0, Attribute::ZExt);
1576 WrapperFn->addParamAttr(1, Attribute::NoUndef);
1580 Builder.SetInsertPoint(EntryBB);
1583 Value *AddrAlloca = Builder.CreateAlloca(Builder.getInt32Ty(),
1585 AddrAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1586 AddrAlloca, Builder.getPtrTy(0),
1587 AddrAlloca->
getName() +
".ascast");
1589 Value *ZeroAlloca = Builder.CreateAlloca(Builder.getInt32Ty(),
1591 ZeroAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1592 ZeroAlloca, Builder.getPtrTy(0),
1593 ZeroAlloca->
getName() +
".ascast");
1595 Value *ArgsAlloca =
nullptr;
1597 ArgsAlloca = Builder.CreateAlloca(Builder.getPtrTy(),
1598 nullptr,
"global_args");
1599 ArgsAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1600 ArgsAlloca, Builder.getPtrTy(0),
1601 ArgsAlloca->
getName() +
".ascast");
1605 Builder.CreateStore(WrapperFn->getArg(1), AddrAlloca);
1606 Builder.CreateStore(Builder.getInt32(0), ZeroAlloca);
1610 llvm::omp::RuntimeFunction::OMPRTL___kmpc_get_shared_variables),
1618 Value *StructArg = Builder.CreateLoad(Builder.getPtrTy(), ArgsAlloca);
1619 StructArg = Builder.CreateInBoundsGEP(Builder.getPtrTy(), StructArg,
1620 {Builder.getInt64(0)});
1621 StructArg = Builder.CreateLoad(Builder.getPtrTy(), StructArg,
"structArg");
1622 Args.push_back(StructArg);
1626 Builder.CreateCall(&OutlinedFn, Args);
1627 Builder.CreateRetVoid();
1642 "Expected at least tid and bounded tid as arguments");
1643 unsigned NumCapturedVars = OutlinedFn.
arg_size() - 2;
1651 OutlinedFn.
addFnAttr(Attribute::NoUnwind);
1654 assert(CI &&
"Expected call instruction to outlined function");
1655 CI->
getParent()->setName(
"omp_parallel");
1657 Builder.SetInsertPoint(CI);
1658 Type *PtrTy = OMPIRBuilder->VoidPtr;
1661 OpenMPIRBuilder ::InsertPointTy CurrentIP = Builder.saveIP();
1665 Value *Args = ArgsAlloca;
1669 Args = Builder.CreatePointerCast(ArgsAlloca, PtrTy);
1670 Builder.restoreIP(CurrentIP);
1673 for (
unsigned Idx = 0; Idx < NumCapturedVars; Idx++) {
1675 Value *StoreAddress = Builder.CreateConstInBoundsGEP2_64(
1677 Builder.CreateStore(V, StoreAddress);
1681 IfCondition ? Builder.CreateSExtOrTrunc(IfCondition, OMPIRBuilder->Int32)
1682 : Builder.getInt32(1);
1683 Value *NumThreadsArg =
1684 NumThreads ? Builder.CreateZExtOrTrunc(NumThreads, OMPIRBuilder->Int32)
1685 : Builder.getInt32(-1);
1695 Value *Parallel60CallArgs[] = {
1700 Builder.getInt32(-1),
1704 Builder.getInt64(NumCapturedVars),
1705 Builder.getInt32(0)};
1713 << *Builder.GetInsertBlock()->getParent() <<
"\n");
1716 Builder.SetInsertPoint(PrivTID);
1718 Builder.CreateStore(Builder.CreateLoad(OMPIRBuilder->Int32, OutlinedAI),
1725 I->eraseFromParent();
1748 if (!
F->hasMetadata(LLVMContext::MD_callback)) {
1756 F->addMetadata(LLVMContext::MD_callback,
1765 OutlinedFn.
addFnAttr(Attribute::NoUnwind);
1768 "Expected at least tid and bounded tid as arguments");
1769 unsigned NumCapturedVars = OutlinedFn.
arg_size() - 2;
1772 CI->
getParent()->setName(
"omp_parallel");
1773 Builder.SetInsertPoint(CI);
1776 Value *ForkCallArgs[] = {Ident, Builder.getInt32(NumCapturedVars),
1780 RealArgs.
append(std::begin(ForkCallArgs), std::end(ForkCallArgs));
1782 Value *
Cond = Builder.CreateSExtOrTrunc(IfCondition, OMPIRBuilder->Int32);
1789 auto PtrTy = OMPIRBuilder->VoidPtr;
1790 if (IfCondition && NumCapturedVars == 0) {
1798 << *Builder.GetInsertBlock()->getParent() <<
"\n");
1801 Builder.SetInsertPoint(PrivTID);
1803 Builder.CreateStore(Builder.CreateLoad(OMPIRBuilder->Int32, OutlinedAI),
1810 I->eraseFromParent();
1818 Value *NumThreads, omp::ProcBindKind ProcBind,
bool IsCancellable) {
1827 const bool NeedThreadID = NumThreads ||
Config.isTargetDevice() ||
1828 (ProcBind != OMP_PROC_BIND_default);
1835 bool ArgsInZeroAddressSpace =
Config.isTargetDevice();
1839 if (NumThreads && !
Config.isTargetDevice()) {
1842 Builder.CreateIntCast(NumThreads, Int32,
false)};
1847 if (ProcBind != OMP_PROC_BIND_default) {
1851 ConstantInt::get(Int32,
unsigned(ProcBind),
true)};
1873 Builder.CreateAlloca(Int32,
nullptr,
"zero.addr");
1876 if (ArgsInZeroAddressSpace &&
M.getDataLayout().getAllocaAddrSpace() != 0) {
1879 TIDAddrAlloca, PointerType ::get(
M.getContext(), 0),
"tid.addr.ascast");
1883 PointerType ::get(
M.getContext(), 0),
1884 "zero.addr.ascast");
1908 if (IP.getBlock()->end() == IP.getPoint()) {
1914 assert(IP.getBlock()->getTerminator()->getNumSuccessors() == 1 &&
1915 IP.getBlock()->getTerminator()->getSuccessor(0) == PRegExitBB &&
1916 "Unexpected insertion point for finalization call!");
1928 Builder.CreateAlloca(Int32,
nullptr,
"tid.addr.local");
1934 Builder.CreateLoad(Int32, ZeroAddr,
"zero.addr.use");
1952 LLVM_DEBUG(
dbgs() <<
"Before body codegen: " << *OuterFn <<
"\n");
1955 assert(BodyGenCB &&
"Expected body generation callback!");
1957 if (
Error Err = BodyGenCB(InnerAllocaIP, CodeGenIP, PRegExitBB))
1960 LLVM_DEBUG(
dbgs() <<
"After body codegen: " << *OuterFn <<
"\n");
1964 bool UsesDeviceSharedMemory =
1966 std::unique_ptr<OutlineInfo> OI =
1967 UsesDeviceSharedMemory
1968 ? std::make_unique<DeviceSharedMemOutlineInfo>(*
this)
1969 : std::make_unique<OutlineInfo>();
1971 if (
Config.isTargetDevice()) {
1973 OI->PostOutlineCB = [=, ToBeDeletedVec =
1974 std::move(ToBeDeleted)](
Function &OutlinedFn) {
1976 IfCondition, NumThreads, PrivTID, PrivTIDAddr,
1977 ThreadID, ToBeDeletedVec);
1981 OI->PostOutlineCB = [=, ToBeDeletedVec =
1982 std::move(ToBeDeleted)](
Function &OutlinedFn) {
1984 PrivTID, PrivTIDAddr, ToBeDeletedVec);
1988 OI->FixUpNonEntryAllocas =
true;
1989 OI->OuterAllocBB = OuterAllocaBlock;
1990 OI->EntryBB = PRegEntryBB;
1991 OI->ExitBB = PRegExitBB;
1992 OI->OuterDeallocBBs.reserve(OuterDeallocBlocks.
size());
1993 copy(OuterDeallocBlocks, OI->OuterDeallocBBs.
end());
1997 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
2009 ".omp_par", ArgsInZeroAddressSpace);
2014 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
2016 Extractor.findInputsOutputs(Inputs, Outputs, SinkingCands,
2021 return GV->getValueType() == OpenMPIRBuilder::Ident;
2026 LLVM_DEBUG(
dbgs() <<
"Before privatization: " << *OuterFn <<
"\n");
2032 if (&V == TIDAddr || &V == ZeroAddr) {
2033 OI->ExcludeArgsFromAggregate.push_back(&V);
2038 for (
Use &U : V.uses())
2040 if (ParallelRegionBlockSet.
count(UserI->getParent()))
2050 if (!V.getType()->isPointerTy()) {
2054 Builder.restoreIP(OuterAllocIP);
2056 if (UsesDeviceSharedMemory) {
2059 V.getName() +
".reloaded");
2060 for (
BasicBlock *DeallocBlock : OuterDeallocBlocks)
2062 InsertPointTy(DeallocBlock, DeallocBlock->getFirstInsertionPt()),
2065 Ptr =
Builder.CreateAlloca(V.getType(),
nullptr,
2066 V.getName() +
".reloaded");
2071 Builder.SetInsertPoint(InsertBB,
2076 Builder.restoreIP(InnerAllocaIP);
2077 Inner =
Builder.CreateLoad(V.getType(), Ptr);
2080 Value *ReplacementValue =
nullptr;
2083 ReplacementValue = PrivTID;
2086 PrivCB(InnerAllocaIP,
Builder.saveIP(), V, *Inner, ReplacementValue);
2094 assert(ReplacementValue &&
2095 "Expected copy/create callback to set replacement value!");
2096 if (ReplacementValue == &V)
2101 UPtr->set(ReplacementValue);
2126 for (
Value *Output : Outputs)
2130 "OpenMP outlining should not produce live-out values!");
2132 LLVM_DEBUG(
dbgs() <<
"After privatization: " << *OuterFn <<
"\n");
2134 for (
auto *BB : Blocks)
2135 dbgs() <<
" PBR: " << BB->getName() <<
"\n";
2143 assert(FiniInfo.DK == OMPD_parallel &&
2144 "Unexpected finalization stack state!");
2155 Builder.CreateBr(*FiniBBOrErr);
2159 Term->eraseFromParent();
2165 InsertPointTy AfterIP(UI->getParent(), UI->getParent()->end());
2166 UI->eraseFromParent();
2198 Value *Severity = ConstantInt::get(Int32, IsFatal ? 2 : 1);
2200 Value *Args[] = {Ident, Severity, MessageArg};
2229 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr));
2231 Builder.CreateStore(DepValPtr, Addr);
2234 DependInfo, Entry,
static_cast<unsigned int>(RTLDependInfoFields::Len));
2236 ConstantInt::get(SizeTy,
2241 DependInfo, Entry,
static_cast<unsigned int>(RTLDependInfoFields::Flags));
2243 static_cast<unsigned int>(Dep.
DepKind)),
2256 if (Dependencies.
empty())
2276 Type *DependInfo = OMPBuilder.DependInfo;
2278 Value *DepArray =
nullptr;
2280 Builder.SetInsertPoint(
2284 DepArray = Builder.CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
2286 Builder.restoreIP(OldIP);
2288 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies)) {
2290 Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
2314 Value *DepArray =
nullptr;
2315 Type *DepArrayTy =
nullptr;
2316 Value *NumDeps =
nullptr;
2319 NumDeps = Dependencies.
NumDeps;
2320 }
else if (!Dependencies.
Deps.empty()) {
2323 Builder.GetInsertBlock()->getParent()->getEntryBlock();
2327 DepArray =
Builder.CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
2328 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
2331 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies.
Deps)) {
2333 Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
2347 ConstantInt::get(
Builder.getInt32Ty(), 0),
2349 ConstantInt::get(
Builder.getInt32Ty(),
false)};
2352 omp::RuntimeFunction::OMPRTL___kmpc_omp_taskwait_deps_51),
2362 unsigned ProgramAddressSpace = M.getDataLayout().getProgramAddressSpace();
2374 auto *VoidPtrTy =
PointerType::get(Builder.getContext(), ProgramAddressSpace);
2377 Builder.getVoidTy(), {VoidPtrTy, VoidPtrTy, Builder.getInt32Ty()},
2381 "omp_taskloop_dup", M);
2384 Value *LastprivateFlagArg = DupFunction->
getArg(2);
2385 DestTaskArg->
setName(
"dest_task");
2386 SrcTaskArg->
setName(
"src_task");
2387 LastprivateFlagArg->
setName(
"lastprivate_flag");
2390 Builder.SetInsertPoint(
2393 auto GetTaskContextPtrFromArg = [&](
Value *Arg) ->
Value * {
2394 Type *TaskWithPrivatesTy =
2396 Value *TaskPrivates = Builder.CreateGEP(
2397 TaskWithPrivatesTy, Arg, {Builder.getInt32(0), Builder.getInt32(1)});
2398 Value *ContextPtr = Builder.CreateGEP(
2399 PrivatesTy, TaskPrivates,
2400 {Builder.getInt32(0), Builder.getInt32(PrivatesIndex)});
2404 Value *DestTaskContextPtr = GetTaskContextPtrFromArg(DestTaskArg);
2405 Value *SrcTaskContextPtr = GetTaskContextPtrFromArg(SrcTaskArg);
2407 DestTaskContextPtr->
setName(
"destPtr");
2408 SrcTaskContextPtr->
setName(
"srcPtr");
2413 Expected<IRBuilderBase::InsertPoint> AfterIPOrError =
2414 DupCB(AllocaIP, CodeGenIP, DestTaskContextPtr, SrcTaskContextPtr);
2415 if (!AfterIPOrError)
2417 Builder.restoreIP(*AfterIPOrError);
2427 llvm::function_ref<llvm::Expected<llvm::CanonicalLoopInfo *>()> LoopInfo,
2429 Value *GrainSize,
bool NoGroup,
int Sched,
Value *Final,
bool Mergeable,
2431 Value *TaskContextStructPtrVal) {
2436 uint32_t SrcLocStrSize;
2452 if (
Error Err = BodyGenCB(TaskloopAllocaIP, TaskloopBodyIP, TaskloopExitBB))
2455 llvm::Expected<llvm::CanonicalLoopInfo *> result = LoopInfo();
2460 llvm::CanonicalLoopInfo *CLI = result.
get();
2461 auto OI = std::make_unique<OutlineInfo>();
2462 OI->EntryBB = TaskloopAllocaBB;
2463 OI->OuterAllocBB = AllocaIP.getBlock();
2464 OI->ExitBB = TaskloopExitBB;
2465 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2466 copy(DeallocBlocks, OI->OuterDeallocBBs.end());
2469 SmallVector<Instruction *> ToBeDeleted;
2472 Builder, AllocaIP, ToBeDeleted, TaskloopAllocaIP,
"global.tid",
false));
2474 TaskloopAllocaIP,
"lb",
false,
true);
2476 TaskloopAllocaIP,
"ub",
false,
true);
2478 TaskloopAllocaIP,
"step",
false,
true);
2481 OI->Inputs.insert(FakeLB);
2482 OI->Inputs.insert(FakeUB);
2483 OI->Inputs.insert(FakeStep);
2484 if (TaskContextStructPtrVal)
2485 OI->Inputs.insert(TaskContextStructPtrVal);
2486 assert(((TaskContextStructPtrVal && DupCB) ||
2487 (!TaskContextStructPtrVal && !DupCB)) &&
2488 "Task context struct ptr and duplication callback must be both set "
2494 unsigned ProgramAddressSpace =
M.getDataLayout().getProgramAddressSpace();
2498 {FakeLB->getType(), FakeUB->getType(), FakeStep->getType(), PointerTy});
2499 Expected<Value *> TaskDupFnOrErr = createTaskDuplicationFunction(
2502 if (!TaskDupFnOrErr) {
2505 Value *TaskDupFn = *TaskDupFnOrErr;
2507 OI->PostOutlineCB = [
this, Ident, LBVal, UBVal, StepVal, Untied,
2508 TaskloopAllocaBB, CLI, TaskDupFn, ToBeDeleted, IfCond,
2509 GrainSize, NoGroup, Sched, FakeLB, FakeUB, FakeStep,
2510 FakeSharedsTy, Final, Mergeable, Priority,
2511 NumOfCollapseLoops](
Function &OutlinedFn)
mutable {
2513 assert(OutlinedFn.hasOneUse() &&
2514 "there must be a single user for the outlined function");
2521 Value *CastedLBVal =
2522 Builder.CreateIntCast(LBVal,
Builder.getInt64Ty(),
true,
"lb64");
2523 Value *CastedUBVal =
2524 Builder.CreateIntCast(UBVal,
Builder.getInt64Ty(),
true,
"ub64");
2525 Value *CastedStepVal =
2526 Builder.CreateIntCast(StepVal,
Builder.getInt64Ty(),
true,
"step64");
2528 Builder.SetInsertPoint(StaleCI);
2541 Builder.CreateCall(TaskgroupFn, {Ident, ThreadID});
2562 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
2564 AllocaInst *ArgStructAlloca =
2566 assert(ArgStructAlloca &&
2567 "Unable to find the alloca instruction corresponding to arguments "
2568 "for extracted function");
2569 std::optional<TypeSize> ArgAllocSize =
2572 "Unable to determine size of arguments for extracted function");
2573 Value *SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
2578 CallInst *TaskData =
Builder.CreateCall(
2579 TaskAllocFn, {Ident, ThreadID,
Flags,
2580 TaskSize, SharedsSize,
2585 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
2586 Builder.CreateMemCpy(TaskShareds, Alignment, Shareds, Alignment,
2591 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(0)});
2594 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(1)});
2597 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(2)});
2603 IfCond ?
Builder.CreateIntCast(IfCond,
Builder.getInt32Ty(),
true)
2609 Value *GrainSizeVal =
2610 GrainSize ?
Builder.CreateIntCast(GrainSize,
Builder.getInt64Ty(),
true)
2612 Value *TaskDup = TaskDupFn;
2614 Value *
Args[] = {Ident, ThreadID, TaskData, IfCondVal, Lb, Ub,
2615 Loadstep, NoGroupVal, SchedVal, GrainSizeVal, TaskDup};
2620 Builder.CreateCall(TaskloopFn, Args);
2627 Builder.CreateCall(EndTaskgroupFn, {Ident, ThreadID});
2632 Builder.SetInsertPoint(TaskloopAllocaBB, TaskloopAllocaBB->begin());
2634 LoadInst *SharedsOutlined =
2635 Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
2636 OutlinedFn.getArg(1)->replaceUsesWithIf(
2638 [SharedsOutlined](Use &U) {
return U.getUser() != SharedsOutlined; });
2641 Type *IVTy =
IV->getType();
2647 Value *TaskLB =
nullptr;
2648 Value *TaskUB =
nullptr;
2649 Value *TaskStep =
nullptr;
2650 Value *LoadTaskLB =
nullptr;
2651 Value *LoadTaskUB =
nullptr;
2652 Value *LoadTaskStep =
nullptr;
2653 for (Instruction &
I : *TaskloopAllocaBB) {
2654 if (
I.getOpcode() == Instruction::GetElementPtr) {
2657 switch (CI->getZExtValue()) {
2669 }
else if (
I.getOpcode() == Instruction::Load) {
2671 if (
Load.getPointerOperand() == TaskLB) {
2672 assert(TaskLB !=
nullptr &&
"Expected value for TaskLB");
2674 }
else if (
Load.getPointerOperand() == TaskUB) {
2675 assert(TaskUB !=
nullptr &&
"Expected value for TaskUB");
2677 }
else if (
Load.getPointerOperand() == TaskStep) {
2678 assert(TaskStep !=
nullptr &&
"Expected value for TaskStep");
2684 Builder.SetInsertPoint(CLI->getPreheader()->getTerminator());
2686 assert(LoadTaskLB !=
nullptr &&
"Expected value for LoadTaskLB");
2687 assert(LoadTaskUB !=
nullptr &&
"Expected value for LoadTaskUB");
2688 assert(LoadTaskStep !=
nullptr &&
"Expected value for LoadTaskStep");
2690 Builder.CreateSub(LoadTaskUB, LoadTaskLB), LoadTaskStep);
2691 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One,
"trip_cnt");
2692 Value *CastedTripCount =
Builder.CreateIntCast(TripCount, IVTy,
true);
2693 Value *CastedTaskLB =
Builder.CreateIntCast(LoadTaskLB, IVTy,
true);
2695 CLI->setTripCount(CastedTripCount);
2697 Builder.SetInsertPoint(CLI->getBody(),
2698 CLI->getBody()->getFirstInsertionPt());
2700 if (NumOfCollapseLoops > 1) {
2706 Builder.CreateSub(CastedTaskLB, ConstantInt::get(IVTy, 1)));
2709 for (
auto IVUse = CLI->getIndVar()->uses().begin();
2710 IVUse != CLI->getIndVar()->uses().end(); IVUse++) {
2711 User *IVUser = IVUse->getUser();
2713 if (
Op->getOpcode() == Instruction::URem ||
2714 Op->getOpcode() == Instruction::UDiv) {
2719 for (User *User : UsersToReplace) {
2720 User->replaceUsesOfWith(CLI->getIndVar(), IVPlusTaskLB);
2737 assert(CLI->getIndVar()->getNumUses() == 3 &&
2738 "Canonical loop should have exactly three uses of the ind var");
2739 for (User *IVUser : CLI->getIndVar()->users()) {
2741 if (
Mul->getOpcode() == Instruction::Mul) {
2742 for (User *MulUser :
Mul->users()) {
2744 if (
Add->getOpcode() == Instruction::Add) {
2745 Add->setOperand(1, CastedTaskLB);
2754 FakeLB->replaceAllUsesWith(CastedLBVal);
2755 FakeUB->replaceAllUsesWith(CastedUBVal);
2756 FakeStep->replaceAllUsesWith(CastedStepVal);
2758 I->eraseFromParent();
2763 Builder.SetInsertPoint(TaskloopExitBB, TaskloopExitBB->
begin());
2769 M.getContext(),
M.getDataLayout().getPointerSizeInBits());
2779 bool Mergeable,
Value *EventHandle,
Value *Priority) {
2811 if (
Error Err = BodyGenCB(TaskAllocaIP, TaskBodyIP, TaskExitBB))
2814 auto OI = std::make_unique<OutlineInfo>();
2815 OI->EntryBB = TaskAllocaBB;
2816 OI->OuterAllocBB = AllocaIP.
getBlock();
2817 OI->ExitBB = TaskExitBB;
2818 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2819 copy(DeallocBlocks, OI->OuterDeallocBBs.
end());
2824 Builder, AllocaIP, ToBeDeleted, TaskAllocaIP,
"global.tid",
false));
2826 OI->PostOutlineCB = [
this, Ident, Tied, Final, IfCondition, Dependencies,
2827 Affinities, Mergeable, Priority, EventHandle,
2829 ToBeDeleted](
Function &OutlinedFn)
mutable {
2831 assert(OutlinedFn.hasOneUse() &&
2832 "there must be a single user for the outlined function");
2837 bool HasShareds = StaleCI->
arg_size() > 1;
2838 Builder.SetInsertPoint(StaleCI);
2863 bool UseMergedIf0Path = ConstIfCondition && ConstIfCondition->isZero();
2867 Flags =
Builder.CreateOr(FinalFlag, Flags);
2870 if (Mergeable || UseMergedIf0Path)
2882 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
2891 assert(ArgStructAlloca &&
2892 "Unable to find the alloca instruction corresponding to arguments "
2893 "for extracted function");
2894 std::optional<TypeSize> ArgAllocSize =
2897 "Unable to determine size of arguments for extracted function");
2898 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
2904 TaskAllocFn, {Ident, ThreadID, Flags,
2905 TaskSize, SharedsSize,
2908 if (Affinities.
Count && Affinities.
Info) {
2910 OMPRTL___kmpc_omp_reg_task_with_affinity);
2921 OMPRTL___kmpc_task_allow_completion_event);
2925 Builder.CreatePointerBitCastOrAddrSpaceCast(EventHandle,
2927 EventVal =
Builder.CreatePtrToInt(EventVal,
Builder.getInt64Ty());
2928 Builder.CreateStore(EventVal, EventHandleAddr);
2934 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
2935 Builder.CreateMemCpy(TaskShareds, Alignment, Shareds, Alignment,
2949 Constant *Zero = ConstantInt::get(Int32Ty, 0);
2953 Builder.CreateInBoundsGEP(TaskPtr, TaskData, {Zero, Zero});
2956 VoidPtr, VoidPtr,
Builder.getInt32Ty(), VoidPtr, VoidPtr);
2958 TaskStructType, TaskGEP, {Zero, ConstantInt::get(Int32Ty, 4)});
2961 Value *CmplrData =
Builder.CreateInBoundsGEP(CmplrStructType,
2962 PriorityData, {Zero, Zero});
2963 Builder.CreateStore(Priority, CmplrData);
2966 Value *DepArray =
nullptr;
2967 Value *NumDeps =
nullptr;
2970 NumDeps = Dependencies.
NumDeps;
2971 }
else if (!Dependencies.
Deps.empty()) {
2973 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
2993 if (IfCondition && !UseMergedIf0Path) {
2998 Builder.GetInsertPoint()->getParent()->getTerminator();
2999 Instruction *ThenTI = IfTerminator, *ElseTI =
nullptr;
3000 Builder.SetInsertPoint(IfTerminator);
3003 Builder.SetInsertPoint(ElseTI);
3010 {Ident, ThreadID, NumDeps, DepArray,
3011 ConstantInt::get(
Builder.getInt32Ty(), 0),
3026 Builder.SetInsertPoint(ThenTI);
3034 {Ident, ThreadID, TaskData, NumDeps, DepArray,
3035 ConstantInt::get(
Builder.getInt32Ty(), 0),
3046 Builder.SetInsertPoint(TaskAllocaBB, TaskAllocaBB->
begin());
3048 LoadInst *Shareds =
Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
3049 OutlinedFn.getArg(1)->replaceUsesWithIf(
3050 Shareds, [Shareds](
Use &U) {
return U.getUser() != Shareds; });
3054 I->eraseFromParent();
3058 Builder.SetInsertPoint(TaskExitBB, TaskExitBB->
begin());
3080 if (
Error Err = BodyGenCB(AllocaIP,
Builder.saveIP(), DeallocBlocks))
3083 Builder.SetInsertPoint(TaskgroupExitBB);
3126 unsigned CaseNumber = 0;
3127 for (
auto SectionCB : SectionCBs) {
3129 M.getContext(),
"omp_section_loop.body.case", CurFn,
Continue);
3131 Builder.SetInsertPoint(CaseBB);
3135 {CaseEndBr->getParent(), CaseEndBr->getIterator()}, {}))
3146 Value *LB = ConstantInt::get(I32Ty, 0);
3147 Value *UB = ConstantInt::get(I32Ty, SectionCBs.
size());
3148 Value *ST = ConstantInt::get(I32Ty, 1);
3150 Loc, LoopBodyGenCB, LB, UB, ST,
true,
false, AllocaIP,
"section_loop");
3155 applyStaticWorkshareLoop(
Loc.DL, *
LoopInfo, AllocaIP,
3156 WorksharingLoopType::ForStaticLoop, !IsNowait);
3162 assert(LoopFini &&
"Bad structure of static workshare loop finalization");
3166 assert(FiniInfo.DK == OMPD_sections &&
3167 "Unexpected finalization stack state!");
3168 if (
Error Err = FiniInfo.mergeFiniBB(
Builder, LoopFini))
3182 if (IP.getBlock()->end() != IP.getPoint())
3193 auto *CaseBB =
Loc.IP.getBlock();
3194 auto *CondBB = CaseBB->getSinglePredecessor()->getSinglePredecessor();
3195 auto *ExitBB = CondBB->getTerminator()->getSuccessor(1);
3201 Directive OMPD = Directive::OMPD_sections;
3204 return EmitOMPInlinedRegion(OMPD,
nullptr,
nullptr, BodyGenCB, FiniCBWrapper,
3215Value *OpenMPIRBuilder::getGPUThreadID() {
3218 OMPRTL___kmpc_get_hardware_thread_id_in_block),
3222Value *OpenMPIRBuilder::getGPUWarpSize() {
3227Value *OpenMPIRBuilder::getNVPTXWarpID() {
3228 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3229 return Builder.CreateAShr(getGPUThreadID(), LaneIDBits,
"nvptx_warp_id");
3232Value *OpenMPIRBuilder::getNVPTXLaneID() {
3233 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3234 assert(LaneIDBits < 32 &&
"Invalid LaneIDBits size in NVPTX device.");
3235 unsigned LaneIDMask = ~0
u >> (32u - LaneIDBits);
3236 return Builder.CreateAnd(getGPUThreadID(),
Builder.getInt32(LaneIDMask),
3243 uint64_t FromSize =
M.getDataLayout().getTypeStoreSize(FromType);
3244 uint64_t ToSize =
M.getDataLayout().getTypeStoreSize(ToType);
3245 assert(FromSize > 0 &&
"From size must be greater than zero");
3246 assert(ToSize > 0 &&
"To size must be greater than zero");
3247 if (FromType == ToType)
3249 if (FromSize == ToSize)
3250 return Builder.CreateBitCast(From, ToType);
3252 return Builder.CreateIntCast(From, ToType,
true);
3258 Value *ValCastItem =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3259 CastItem,
Builder.getPtrTy(0));
3260 Builder.CreateStore(From, ValCastItem);
3261 return Builder.CreateLoad(ToType, CastItem);
3268 uint64_t
Size =
M.getDataLayout().getTypeStoreSize(ElementType);
3269 assert(
Size <= 8 &&
"Unsupported bitwidth in shuffle instruction");
3273 Value *ElemCast = castValueToType(AllocaIP, Element, CastTy);
3275 Builder.CreateIntCast(getGPUWarpSize(),
Builder.getInt16Ty(),
true);
3277 Size <= 4 ? RuntimeFunction::OMPRTL___kmpc_shuffle_int32
3278 : RuntimeFunction::OMPRTL___kmpc_shuffle_int64);
3279 Value *WarpSizeCast =
3281 Value *ShuffleCall =
3283 return castValueToType(AllocaIP, ShuffleCall, CastTy);
3290 uint64_t
Size =
M.getDataLayout().getTypeStoreSize(ElemType);
3302 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3303 Value *ElemPtr = DstAddr;
3304 Value *Ptr = SrcAddr;
3305 for (
unsigned IntSize = 8; IntSize >= 1; IntSize /= 2) {
3309 Ptr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3312 Builder.CreateGEP(ElemType, SrcAddr, {ConstantInt::get(IndexTy, 1)});
3313 ElemPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3317 if ((
Size / IntSize) > 1) {
3318 Value *PtrEnd =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3319 SrcAddrGEP,
Builder.getPtrTy());
3336 Builder.CreatePointerBitCastOrAddrSpaceCast(Ptr,
Builder.getPtrTy()));
3338 Builder.CreateICmpSGT(PtrDiff,
Builder.getInt64(IntSize - 1)), ThenBB,
3341 Value *Res = createRuntimeShuffleFunction(
3344 IntType, Ptr,
M.getDataLayout().getPrefTypeAlign(ElemType)),
3346 Builder.CreateAlignedStore(Res, ElemPtr,
3347 M.getDataLayout().getPrefTypeAlign(ElemType));
3349 Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3350 Value *LocalElemPtr =
3351 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3357 Value *Res = createRuntimeShuffleFunction(
3358 AllocaIP,
Builder.CreateLoad(IntType, Ptr), IntType,
Offset);
3361 Res =
Builder.CreateTrunc(Res, ElemType);
3362 Builder.CreateStore(Res, ElemPtr);
3363 Ptr =
Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3365 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3371Error OpenMPIRBuilder::emitReductionListCopy(
3376 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3377 Value *RemoteLaneOffset = CopyOptions.RemoteLaneOffset;
3381 for (
auto En :
enumerate(ReductionInfos)) {
3383 Value *SrcElementAddr =
nullptr;
3384 AllocaInst *DestAlloca =
nullptr;
3385 Value *DestElementAddr =
nullptr;
3386 Value *DestElementPtrAddr =
nullptr;
3388 bool ShuffleInElement =
false;
3391 bool UpdateDestListPtr =
false;
3395 ReductionArrayTy, SrcBase,
3396 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3397 SrcElementAddr =
Builder.CreateLoad(
Builder.getPtrTy(), SrcElementPtrAddr);
3401 DestElementPtrAddr =
Builder.CreateInBoundsGEP(
3402 ReductionArrayTy, DestBase,
3403 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3404 bool IsByRefElem = (!IsByRef.
empty() && IsByRef[En.index()]);
3410 Type *DestAllocaType =
3411 IsByRefElem ? RI.ByRefAllocatedType : RI.ElementType;
3412 DestAlloca =
Builder.CreateAlloca(DestAllocaType,
nullptr,
3413 ".omp.reduction.element");
3415 M.getDataLayout().getPrefTypeAlign(DestAllocaType));
3416 DestElementAddr = DestAlloca;
3419 DestElementAddr->
getName() +
".ascast");
3421 ShuffleInElement =
true;
3422 UpdateDestListPtr =
true;
3434 if (ShuffleInElement) {
3435 Type *ShuffleType = RI.ElementType;
3436 Value *ShuffleSrcAddr = SrcElementAddr;
3437 Value *ShuffleDestAddr = DestElementAddr;
3438 AllocaInst *LocalStorage =
nullptr;
3441 assert(RI.ByRefElementType &&
"Expected by-ref element type to be set");
3442 assert(RI.ByRefAllocatedType &&
3443 "Expected by-ref allocated type to be set");
3448 ShuffleType = RI.ByRefElementType;
3450 if (RI.DataPtrPtrGen) {
3453 Builder.saveIP(), ShuffleSrcAddr, ShuffleSrcAddr);
3456 return GenResult.takeError();
3465 LocalStorage =
Builder.CreateAlloca(ShuffleType);
3467 ShuffleDestAddr = LocalStorage;
3472 ShuffleDestAddr = DestElementAddr;
3476 shuffleAndStore(AllocaIP, ShuffleSrcAddr, ShuffleDestAddr, ShuffleType,
3477 RemoteLaneOffset, ReductionArrayTy, IsByRefElem);
3479 if (IsByRefElem && RI.DataPtrPtrGen) {
3481 Value *DestDescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3482 DestAlloca,
Builder.getPtrTy(),
".ascast");
3485 DestDescriptorAddr, LocalStorage, SrcElementAddr,
3486 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
3489 return GenResult.takeError();
3492 switch (RI.EvaluationKind) {
3494 Value *Elem =
Builder.CreateLoad(RI.ElementType, SrcElementAddr);
3496 Builder.CreateStore(Elem, DestElementAddr);
3500 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3501 RI.ElementType, SrcElementAddr, 0, 0,
".realp");
3503 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
3505 RI.ElementType, SrcElementAddr, 0, 1,
".imagp");
3507 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
3509 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3510 RI.ElementType, DestElementAddr, 0, 0,
".realp");
3511 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
3512 RI.ElementType, DestElementAddr, 0, 1,
".imagp");
3513 Builder.CreateStore(SrcReal, DestRealPtr);
3514 Builder.CreateStore(SrcImg, DestImgPtr);
3519 M.getDataLayout().getTypeStoreSize(RI.ElementType));
3521 DestElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3522 SrcElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3534 if (UpdateDestListPtr) {
3535 Value *CastDestAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3536 DestElementAddr,
Builder.getPtrTy(),
3537 DestElementAddr->
getName() +
".ascast");
3538 Builder.CreateStore(CastDestAddr, DestElementPtrAddr);
3545Expected<Function *> OpenMPIRBuilder::emitInterWarpCopyFunction(
3548 IRBuilder<>::InsertPointGuard IPG(
Builder);
3549 LLVMContext &Ctx =
M.getContext();
3551 Builder.getVoidTy(), {Builder.getPtrTy(), Builder.getInt32Ty()},
3555 "_omp_reduction_inter_warp_copy_func", &
M);
3561 Builder.SetInsertPoint(EntryBB);
3579 StringRef TransferMediumName =
3580 "__openmp_nvptx_data_transfer_temporary_storage";
3581 GlobalVariable *TransferMedium =
M.getGlobalVariable(TransferMediumName);
3582 unsigned WarpSize =
Config.getGridValue().GV_Warp_Size;
3584 if (!TransferMedium) {
3585 TransferMedium =
new GlobalVariable(
3593 Value *GPUThreadID = getGPUThreadID();
3595 Value *LaneID = getNVPTXLaneID();
3597 Value *WarpID = getNVPTXWarpID();
3601 Builder.GetInsertBlock()->getFirstInsertionPt());
3605 AllocaInst *ReduceListAlloca =
Builder.CreateAlloca(
3606 Arg0Type,
nullptr, ReduceListArg->
getName() +
".addr");
3607 AllocaInst *NumWarpsAlloca =
3608 Builder.CreateAlloca(Arg1Type,
nullptr, NumWarpsArg->
getName() +
".addr");
3609 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3610 ReduceListAlloca, Arg0Type, ReduceListAlloca->
getName() +
".ascast");
3611 Value *NumWarpsAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3612 NumWarpsAlloca,
Builder.getPtrTy(0),
3613 NumWarpsAlloca->
getName() +
".ascast");
3614 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
3615 Builder.CreateStore(NumWarpsArg, NumWarpsAddrCast);
3624 for (
auto En :
enumerate(ReductionInfos)) {
3630 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
3631 unsigned RealTySize =
M.getDataLayout().getTypeAllocSize(
3632 IsByRefElem ? RI.ByRefElementType : RI.ElementType);
3633 for (
unsigned TySize = 4; TySize > 0 && RealTySize > 0; TySize /= 2) {
3636 unsigned NumIters = RealTySize / TySize;
3639 Value *Cnt =
nullptr;
3640 Value *CntAddr =
nullptr;
3647 Builder.CreateAlloca(
Builder.getInt32Ty(),
nullptr,
".cnt.addr");
3649 CntAddr =
Builder.CreateAddrSpaceCast(CntAddr,
Builder.getPtrTy(),
3650 CntAddr->
getName() +
".ascast");
3662 Cnt, ConstantInt::get(
Builder.getInt32Ty(), NumIters));
3663 Builder.CreateCondBr(Cmp, BodyBB, ExitBB);
3670 omp::Directive::OMPD_unknown,
3674 return BarrierIP1.takeError();
3680 Value *IsWarpMaster =
Builder.CreateIsNull(LaneID,
"warp_master");
3681 Builder.CreateCondBr(IsWarpMaster, ThenBB, ElseBB);
3685 auto *RedListArrayTy =
3688 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3690 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3691 {ConstantInt::get(IndexTy, 0),
3692 ConstantInt::get(IndexTy, En.index())});
3696 if (IsByRefElem && RI.DataPtrPtrGen) {
3698 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
3701 return GenRes.takeError();
3712 ArrayTy, TransferMedium, {
Builder.getInt64(0), WarpID});
3717 Builder.CreateStore(Elem, MediumPtr,
3729 omp::Directive::OMPD_unknown,
3733 return BarrierIP2.takeError();
3740 Value *NumWarpsVal =
3743 Value *IsActiveThread =
3744 Builder.CreateICmpULT(GPUThreadID, NumWarpsVal,
"is_active_thread");
3745 Builder.CreateCondBr(IsActiveThread, W0ThenBB, W0ElseBB);
3752 ArrayTy, TransferMedium, {
Builder.getInt64(0), GPUThreadID});
3754 Value *TargetElemPtrPtr =
3755 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3756 {ConstantInt::get(IndexTy, 0),
3757 ConstantInt::get(IndexTy, En.index())});
3758 Value *TargetElemPtrVal =
3760 Value *TargetElemPtr = TargetElemPtrVal;
3762 if (IsByRefElem && RI.DataPtrPtrGen) {
3764 RI.DataPtrPtrGen(
Builder.saveIP(), TargetElemPtr, TargetElemPtr);
3767 return GenRes.takeError();
3769 TargetElemPtr =
Builder.CreateLoad(
Builder.getPtrTy(), TargetElemPtr);
3777 Value *SrcMediumValue =
3778 Builder.CreateLoad(CType, SrcMediumPtrVal,
true);
3779 Builder.CreateStore(SrcMediumValue, TargetElemPtr);
3789 Cnt, ConstantInt::get(
Builder.getInt32Ty(), 1));
3790 Builder.CreateStore(Cnt, CntAddr,
false);
3792 auto *CurFn =
Builder.GetInsertBlock()->getParent();
3796 RealTySize %= TySize;
3805Expected<Function *> OpenMPIRBuilder::emitShuffleAndReduceFunction(
3808 LLVMContext &Ctx =
M.getContext();
3809 IRBuilder<>::InsertPointGuard IPG(
Builder);
3810 FunctionType *FuncTy =
3812 {Builder.getPtrTy(), Builder.getInt16Ty(),
3813 Builder.getInt16Ty(), Builder.getInt16Ty()},
3817 "_omp_reduction_shuffle_and_reduce_func", &
M);
3828 Builder.SetInsertPoint(EntryBB);
3840 Type *ReduceListArgType = ReduceListArg->
getType();
3844 ReduceListArgType,
nullptr, ReduceListArg->
getName() +
".addr");
3845 Value *LaneIdAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
3846 LaneIDArg->
getName() +
".addr");
3848 LaneIDArgType,
nullptr, RemoteLaneOffsetArg->
getName() +
".addr");
3849 Value *AlgoVerAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
3850 AlgoVerArg->
getName() +
".addr");
3857 RedListArrayTy,
nullptr,
".omp.reduction.remote_reduce_list");
3859 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3860 ReduceListAlloca, ReduceListArgType,
3861 ReduceListAlloca->
getName() +
".ascast");
3862 Value *LaneIdAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3863 LaneIdAlloca, LaneIDArgPtrType, LaneIdAlloca->
getName() +
".ascast");
3864 Value *RemoteLaneOffsetAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3865 RemoteLaneOffsetAlloca, LaneIDArgPtrType,
3866 RemoteLaneOffsetAlloca->
getName() +
".ascast");
3867 Value *AlgoVerAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3868 AlgoVerAlloca, LaneIDArgPtrType, AlgoVerAlloca->
getName() +
".ascast");
3869 Value *RemoteListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3870 RemoteReductionListAlloca,
Builder.getPtrTy(),
3871 RemoteReductionListAlloca->
getName() +
".ascast");
3873 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
3874 Builder.CreateStore(LaneIDArg, LaneIdAddrCast);
3875 Builder.CreateStore(RemoteLaneOffsetArg, RemoteLaneOffsetAddrCast);
3876 Builder.CreateStore(AlgoVerArg, AlgoVerAddrCast);
3878 Value *ReduceList =
Builder.CreateLoad(ReduceListArgType, ReduceListAddrCast);
3879 Value *LaneId =
Builder.CreateLoad(LaneIDArgType, LaneIdAddrCast);
3880 Value *RemoteLaneOffset =
3881 Builder.CreateLoad(LaneIDArgType, RemoteLaneOffsetAddrCast);
3882 Value *AlgoVer =
Builder.CreateLoad(LaneIDArgType, AlgoVerAddrCast);
3889 Error EmitRedLsCpRes = emitReductionListCopy(
3891 ReduceList, RemoteListAddrCast, IsByRef,
3892 {RemoteLaneOffset,
nullptr,
nullptr});
3895 return EmitRedLsCpRes;
3920 Value *LaneComp =
Builder.CreateICmpULT(LaneId, RemoteLaneOffset);
3925 Value *Algo2AndLaneIdComp =
Builder.CreateAnd(Algo2, LaneIdComp);
3926 Value *RemoteOffsetComp =
3928 Value *CondAlgo2 =
Builder.CreateAnd(Algo2AndLaneIdComp, RemoteOffsetComp);
3929 Value *CA0OrCA1 =
Builder.CreateOr(CondAlgo0, CondAlgo1);
3930 Value *CondReduce =
Builder.CreateOr(CA0OrCA1, CondAlgo2);
3936 Builder.CreateCondBr(CondReduce, ThenBB, ElseBB);
3938 Value *LocalReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3939 ReduceList,
Builder.getPtrTy());
3940 Value *RemoteReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3941 RemoteListAddrCast,
Builder.getPtrTy());
3943 ->addFnAttr(Attribute::NoUnwind);
3954 Value *LaneIdGtOffset =
Builder.CreateICmpUGE(LaneId, RemoteLaneOffset);
3955 Value *CondCopy =
Builder.CreateAnd(Algo1, LaneIdGtOffset);
3960 Builder.CreateCondBr(CondCopy, CpyThenBB, CpyElseBB);
3964 EmitRedLsCpRes = emitReductionListCopy(
3966 RemoteListAddrCast, ReduceList, IsByRef);
3969 return EmitRedLsCpRes;
3984OpenMPIRBuilder::generateReductionDescriptor(
3986 Type *DescriptorType,
3992 Value *DescriptorSize =
3993 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(DescriptorType));
3995 DescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
3996 SrcDescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4000 Value *DataPtrField;
4002 DataPtrPtrGen(
Builder.saveIP(), DescriptorAddr, DataPtrField);
4005 return GenResult.takeError();
4008 DataPtr,
Builder.getPtrTy(),
".ascast"),
4014Expected<Value *> OpenMPIRBuilder::createReductionDescriptorCopy(
4016 Value *SrcDescriptorAddr,
Type *DescriptorPtrTy,
const Twine &Name) {
4020 AllocaInst *DescriptorAlloca =
4021 Builder.CreateAlloca(RI.ByRefAllocatedType,
nullptr, Name);
4023 M.getDataLayout().getPrefTypeAlign(RI.ByRefAllocatedType));
4024 Value *DescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4025 DescriptorAlloca, DescriptorPtrTy,
4026 DescriptorAlloca->
getName() +
".ascast");
4031 generateReductionDescriptor(DescriptorAddr, DataPtr, SrcDescriptorAddr,
4032 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
4034 return GenResult.takeError();
4036 return DescriptorAddr;
4039Expected<Function *> OpenMPIRBuilder::emitListToGlobalCopyFunction(
4042 IRBuilder<>::InsertPointGuard IPG(
Builder);
4043 LLVMContext &Ctx =
M.getContext();
4046 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4050 "_omp_reduction_list_to_global_copy_func", &
M);
4057 Builder.SetInsertPoint(EntryBlock);
4068 BufferArg->
getName() +
".addr");
4072 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4073 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4074 BufferArgAlloca,
Builder.getPtrTy(),
4075 BufferArgAlloca->
getName() +
".ascast");
4076 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4077 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4078 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4079 ReduceListArgAlloca,
Builder.getPtrTy(),
4080 ReduceListArgAlloca->
getName() +
".ascast");
4082 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4083 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4084 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4086 Value *LocalReduceList =
4088 Value *BufferArgVal =
4092 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4093 for (
auto En :
enumerate(ReductionInfos)) {
4095 auto *RedListArrayTy =
4099 RedListArrayTy, LocalReduceList,
4100 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4106 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferArgVal, Idxs);
4108 ReductionsBufferTy, BufferVD, 0, En.index());
4110 switch (RI.EvaluationKind) {
4112 Value *TargetElement;
4114 if (IsByRef.
empty() || !IsByRef[En.index()]) {
4115 TargetElement =
Builder.CreateLoad(RI.ElementType, ElemPtr);
4117 if (RI.DataPtrPtrGen) {
4119 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
4122 return GenResult.takeError();
4126 TargetElement =
Builder.CreateLoad(RI.ByRefElementType, ElemPtr);
4129 Builder.CreateStore(TargetElement, GlobVal);
4133 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4134 RI.ElementType, ElemPtr, 0, 0,
".realp");
4136 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
4138 RI.ElementType, ElemPtr, 0, 1,
".imagp");
4140 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
4142 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4143 RI.ElementType, GlobVal, 0, 0,
".realp");
4144 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4145 RI.ElementType, GlobVal, 0, 1,
".imagp");
4146 Builder.CreateStore(SrcReal, DestRealPtr);
4147 Builder.CreateStore(SrcImg, DestImgPtr);
4152 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(RI.ElementType));
4154 GlobVal,
M.getDataLayout().getPrefTypeAlign(RI.ElementType), ElemPtr,
4155 M.getDataLayout().getPrefTypeAlign(RI.ElementType), SizeVal,
false);
4165Expected<Function *> OpenMPIRBuilder::emitListToGlobalReduceFunction(
4168 IRBuilder<>::InsertPointGuard IPG(
Builder);
4169 LLVMContext &Ctx =
M.getContext();
4172 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4176 "_omp_reduction_list_to_global_reduce_func", &
M);
4183 Builder.SetInsertPoint(EntryBlock);
4194 BufferArg->
getName() +
".addr");
4198 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4199 auto *RedListArrayTy =
4204 Value *LocalReduceList =
4205 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4209 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4210 BufferArgAlloca,
Builder.getPtrTy(),
4211 BufferArgAlloca->
getName() +
".ascast");
4212 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4213 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4214 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4215 ReduceListArgAlloca,
Builder.getPtrTy(),
4216 ReduceListArgAlloca->
getName() +
".ascast");
4217 Value *LocalReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4218 LocalReduceList,
Builder.getPtrTy(),
4219 LocalReduceList->
getName() +
".ascast");
4221 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4222 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4223 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4228 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4229 for (
auto En :
enumerate(ReductionInfos)) {
4232 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4233 RedListArrayTy, LocalReduceListAddrCast,
4234 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4236 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4238 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4239 ReductionsBufferTy, BufferVD, 0, En.index());
4241 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4245 Value *SrcElementPtrPtr =
4246 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
4247 {ConstantInt::get(IndexTy, 0),
4248 ConstantInt::get(IndexTy, En.index())});
4249 Value *SrcDescriptorAddr =
4253 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4254 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4258 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4260 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4268 ->addFnAttr(Attribute::NoUnwind);
4273Expected<Function *> OpenMPIRBuilder::emitGlobalToListCopyFunction(
4276 IRBuilder<>::InsertPointGuard IPG(
Builder);
4277 LLVMContext &Ctx =
M.getContext();
4280 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4284 "_omp_reduction_global_to_list_copy_func", &
M);
4291 Builder.SetInsertPoint(EntryBlock);
4302 BufferArg->
getName() +
".addr");
4306 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4307 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4308 BufferArgAlloca,
Builder.getPtrTy(),
4309 BufferArgAlloca->
getName() +
".ascast");
4310 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4311 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4312 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4313 ReduceListArgAlloca,
Builder.getPtrTy(),
4314 ReduceListArgAlloca->
getName() +
".ascast");
4315 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4316 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4317 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4319 Value *LocalReduceList =
4324 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4325 for (
auto En :
enumerate(ReductionInfos)) {
4326 const OpenMPIRBuilder::ReductionInfo &RI = En.value();
4327 auto *RedListArrayTy =
4331 RedListArrayTy, LocalReduceList,
4332 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4337 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4338 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4339 ReductionsBufferTy, BufferVD, 0, En.index());
4345 if (!IsByRef.
empty() && IsByRef[En.index()]) {
4352 return GenResult.takeError();
4358 Value *TargetElement =
Builder.CreateLoad(ElemType, GlobValPtr);
4359 Builder.CreateStore(TargetElement, ElemPtr);
4363 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4372 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4374 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4376 Builder.CreateStore(SrcReal, DestRealPtr);
4377 Builder.CreateStore(SrcImg, DestImgPtr);
4384 ElemPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4385 GlobValPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4396Expected<Function *> OpenMPIRBuilder::emitGlobalToListReduceFunction(
4399 IRBuilder<>::InsertPointGuard IPG(
Builder);
4400 LLVMContext &Ctx =
M.getContext();
4403 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4407 "_omp_reduction_global_to_list_reduce_func", &
M);
4414 Builder.SetInsertPoint(EntryBlock);
4425 BufferArg->
getName() +
".addr");
4429 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4435 Value *LocalReduceList =
4436 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4440 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4441 BufferArgAlloca,
Builder.getPtrTy(),
4442 BufferArgAlloca->
getName() +
".ascast");
4443 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4444 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4445 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4446 ReduceListArgAlloca,
Builder.getPtrTy(),
4447 ReduceListArgAlloca->
getName() +
".ascast");
4448 Value *ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4449 LocalReduceList,
Builder.getPtrTy(),
4450 LocalReduceList->
getName() +
".ascast");
4452 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4453 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4454 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4459 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4460 for (
auto En :
enumerate(ReductionInfos)) {
4463 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4464 RedListArrayTy, ReductionList,
4465 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4468 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4469 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4470 ReductionsBufferTy, BufferVD, 0, En.index());
4472 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4474 Value *ReduceListVal =
4476 Value *SrcElementPtrPtr =
4477 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceListVal,
4478 {ConstantInt::get(IndexTy, 0),
4479 ConstantInt::get(IndexTy, En.index())});
4480 Value *SrcDescriptorAddr =
4484 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4485 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4489 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4491 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4499 ->addFnAttr(Attribute::NoUnwind);
4504std::string OpenMPIRBuilder::getReductionFuncName(StringRef Name)
const {
4505 std::string Suffix =
4507 return (Name + Suffix).str();
4510Expected<Function *> OpenMPIRBuilder::createReductionFunction(
4513 AttributeList FuncAttrs) {
4514 IRBuilder<>::InsertPointGuard IPG(
Builder);
4516 {Builder.getPtrTy(), Builder.getPtrTy()},
4518 std::string
Name = getReductionFuncName(ReducerName);
4527 Builder.SetInsertPoint(EntryBB);
4532 Value *LHSArrayPtr =
nullptr;
4533 Value *RHSArrayPtr =
nullptr;
4540 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
4542 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
4543 Value *LHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4544 LHSAlloca, Arg0Type, LHSAlloca->
getName() +
".ascast");
4545 Value *RHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4546 RHSAlloca, Arg1Type, RHSAlloca->
getName() +
".ascast");
4547 Builder.CreateStore(Arg0, LHSAddrCast);
4548 Builder.CreateStore(Arg1, RHSAddrCast);
4549 LHSArrayPtr =
Builder.CreateLoad(Arg0Type, LHSAddrCast);
4550 RHSArrayPtr =
Builder.CreateLoad(Arg1Type, RHSAddrCast);
4554 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4556 for (
auto En :
enumerate(ReductionInfos)) {
4559 RedArrayTy, RHSArrayPtr,
4560 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4562 Value *RHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4563 RHSI8Ptr, RI.PrivateVariable->getType(),
4564 RHSI8Ptr->
getName() +
".ascast");
4567 RedArrayTy, LHSArrayPtr,
4568 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4570 Value *LHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4571 LHSI8Ptr, RI.Variable->getType(), LHSI8Ptr->
getName() +
".ascast");
4580 if (!IsByRef.
empty() && !IsByRef[En.index()]) {
4581 LHS =
Builder.CreateLoad(RI.ElementType, LHSPtr);
4582 RHS =
Builder.CreateLoad(RI.ElementType, RHSPtr);
4589 return AfterIP.takeError();
4590 if (!
Builder.GetInsertBlock())
4591 return ReductionFunc;
4595 if (!IsByRef.
empty() && !IsByRef[En.index()])
4596 Builder.CreateStore(Reduced, LHSPtr);
4601 for (
auto En :
enumerate(ReductionInfos)) {
4602 unsigned Index = En.index();
4604 Value *LHSFixupPtr, *RHSFixupPtr;
4605 Builder.restoreIP(RI.ReductionGenClang(
4606 Builder.saveIP(), Index, &LHSFixupPtr, &RHSFixupPtr, ReductionFunc));
4611 LHSPtrs[Index], [ReductionFunc](
const Use &U) {
4616 RHSPtrs[Index], [ReductionFunc](
const Use &U) {
4630 return ReductionFunc;
4638 assert(RI.Variable &&
"expected non-null variable");
4639 assert(RI.PrivateVariable &&
"expected non-null private variable");
4640 assert((RI.ReductionGen || RI.ReductionGenClang) &&
4641 "expected non-null reduction generator callback");
4644 RI.Variable->getType() == RI.PrivateVariable->getType() &&
4645 "expected variables and their private equivalents to have the same "
4648 assert(RI.Variable->getType()->isPointerTy() &&
4649 "expected variables to be pointers");
4656 ArrayRef<bool> IsByRef,
bool IsNoWait,
bool IsTeamsReduction,
bool IsSPMD,
4658 Value *SrcLocInfo) {
4672 if (ReductionInfos.
size() == 0)
4682 Builder.SetInsertPoint(InsertBlock, InsertBlock->
end());
4686 AttributeList FuncAttrs;
4687 AttrBuilder AttrBldr(Ctx);
4689 AttrBldr.addAttribute(Attr);
4690 AttrBldr.removeAttribute(Attribute::OptimizeNone);
4691 FuncAttrs = FuncAttrs.addFnAttributes(Ctx, AttrBldr);
4695 Builder.GetInsertBlock()->getParent()->getName(), ReductionInfos, IsByRef,
4697 if (!ReductionResult)
4699 Function *ReductionFunc = *ReductionResult;
4703 if (GridValue.has_value())
4704 Config.setGridValue(GridValue.value());
4719 Builder.getPtrTy(
M.getDataLayout().getProgramAddressSpace());
4723 Value *ReductionListAlloca =
4724 Builder.CreateAlloca(RedArrayTy,
nullptr,
".omp.reduction.red_list");
4725 Value *ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4726 ReductionListAlloca, PtrTy, ReductionListAlloca->
getName() +
".ascast");
4729 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4730 for (
auto En :
enumerate(ReductionInfos)) {
4733 RedArrayTy, ReductionList,
4734 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4737 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
4742 Builder.CreatePointerBitCastOrAddrSpaceCast(PrivateVar, PtrTy);
4743 Builder.CreateStore(CastElem, ElemPtr);
4747 ReductionInfos, ReductionFunc, FuncAttrs, IsByRef);
4753 emitInterWarpCopyFunction(
Loc, ReductionInfos, FuncAttrs, IsByRef);
4759 Value *RL =
Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList, PtrTy);
4768 unsigned MaxDataSize = 0;
4770 for (
auto En :
enumerate(ReductionInfos)) {
4774 Type *RedTypeArg = (!IsByRef.
empty() && IsByRef[En.index()])
4775 ? En.value().ByRefElementType
4776 : En.value().ElementType;
4777 auto Size =
M.getDataLayout().getTypeStoreSize(RedTypeArg);
4778 if (
Size > MaxDataSize)
4782 Value *ReductionDataSize =
4783 Builder.getInt64(MaxDataSize * ReductionInfos.
size());
4787 Function *CopyScratchToListFunc =
nullptr;
4789 Value *ScratchForCopyBack =
nullptr;
4792 Value *RLForCopyBack = RL;
4794 if (!IsTeamsReduction) {
4795 Value *SarFuncCast =
4796 Builder.CreatePointerBitCastOrAddrSpaceCast(*SarFunc, FuncPtrTy);
4798 Builder.CreatePointerBitCastOrAddrSpaceCast(WcFunc, FuncPtrTy);
4799 Value *Args[] = {SrcLocInfo, ReductionDataSize, RL, SarFuncCast,
4802 RuntimeFunction::OMPRTL___kmpc_nvptx_parallel_reduce_nowait_v2);
4807 Ctx, ReductionTypeArgs,
"struct._globalized_locals_ty");
4810 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
4815 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
4820 ReductionInfos, ReductionFunc, ReductionsBufferTy, FuncAttrs, IsByRef);
4843 Value *RuntimeRL = RL;
4850 ReductionsBufferTy,
nullptr,
".omp.reduction.scratch");
4851 Value *PerThreadScratch =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4852 PerThreadScratchAlloca, PtrTy,
4853 PerThreadScratchAlloca->
getName() +
".ascast");
4856 Value *PerThreadRedListAlloca =
4857 Builder.CreateAlloca(RedArrayTy,
nullptr,
4858 ".omp.reduction.per_thread_red_list");
4859 RuntimeRL =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4860 PerThreadRedListAlloca, PtrTy,
4861 PerThreadRedListAlloca->
getName() +
".ascast");
4866 for (
auto En :
enumerate(ReductionInfos)) {
4868 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
4871 ReductionsBufferTy, PerThreadScratch, 0, En.index());
4872 Value *Slot =
Builder.CreateConstInBoundsGEP2_32(RedArrayTy, RuntimeRL,
4875 Value *RuntimeListEntry = FieldPtr;
4877 Value *SrcDescriptor =
4880 AllocaIP, RI, FieldPtr, SrcDescriptor, PtrTy);
4883 RuntimeListEntry = *Descriptor;
4885 Builder.CreateStore(RuntimeListEntry, Slot);
4891 Type *CopyArg0Ty = (*LtGCFunc)->getFunctionType()->getParamType(0);
4892 Type *CopyArg2Ty = (*LtGCFunc)->getFunctionType()->getParamType(2);
4893 ScratchForCopyBack =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4894 PerThreadScratch, CopyArg0Ty);
4896 Builder.CreatePointerBitCastOrAddrSpaceCast(RL, CopyArg2Ty);
4904 *LtGCFunc, {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
4905 CopyScratchToListFunc = *GtLCFunc;
4908 Value *Args3[] = {SrcLocInfo, RuntimeRL, *SarFunc, WcFunc,
4909 *LtGCFunc, *GtLCFunc, *GtLRFunc};
4912 RuntimeFunction::OMPRTL___kmpc_gpu_xteam_reduce_nowait);
4932 if (ScratchForCopyBack) {
4935 CopyScratchToListFunc,
4936 {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
4940 for (
auto En :
enumerate(ReductionInfos)) {
4949 Value *LHSPtr, *RHSPtr;
4951 &LHSPtr, &RHSPtr, CurFunc));
4957 RedValue =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4959 if (RHSPtr->
getType() != RHS->getType())
4961 Builder.CreatePointerBitCastOrAddrSpaceCast(RHS, RHSPtr->
getType());
4972 if (IsByRef.
empty() || !IsByRef[En.index()]) {
4974 "red.value." +
Twine(En.index()));
4985 if (!IsByRef.
empty() && !IsByRef[En.index()])
4990 if (ContinuationBlock) {
4991 Builder.CreateBr(ContinuationBlock);
4992 Builder.SetInsertPoint(ContinuationBlock);
4994 Config.setEmitLLVMUsed();
5005 ".omp.reduction.func", &M);
5016 Builder.SetInsertPoint(ReductionFuncBlock);
5018 Value *LHSArrayPtr =
nullptr;
5019 Value *RHSArrayPtr =
nullptr;
5030 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
5032 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
5033 Value *LHSAddrCast =
5034 Builder.CreatePointerBitCastOrAddrSpaceCast(LHSAlloca, Arg0Type);
5035 Value *RHSAddrCast =
5036 Builder.CreatePointerBitCastOrAddrSpaceCast(RHSAlloca, Arg1Type);
5037 Builder.CreateStore(Arg0, LHSAddrCast);
5038 Builder.CreateStore(Arg1, RHSAddrCast);
5039 LHSArrayPtr = Builder.CreateLoad(Arg0Type, LHSAddrCast);
5040 RHSArrayPtr = Builder.CreateLoad(Arg1Type, RHSAddrCast);
5042 LHSArrayPtr = ReductionFunc->
getArg(0);
5043 RHSArrayPtr = ReductionFunc->
getArg(1);
5046 unsigned NumReductions = ReductionInfos.
size();
5049 for (
auto En :
enumerate(ReductionInfos)) {
5051 Value *LHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5052 RedArrayTy, LHSArrayPtr, 0, En.index());
5053 Value *LHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), LHSI8PtrPtr);
5054 Value *LHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5057 Value *RHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5058 RedArrayTy, RHSArrayPtr, 0, En.index());
5059 Value *RHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), RHSI8PtrPtr);
5060 Value *RHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5069 Builder.restoreIP(*AfterIP);
5071 if (!Builder.GetInsertBlock())
5075 if (!IsByRef[En.index()])
5076 Builder.CreateStore(Reduced, LHSPtr);
5078 Builder.CreateRetVoid();
5085 bool IsNoWait,
bool IsTeamsReduction) {
5089 IsByRef, IsNoWait, IsTeamsReduction);
5096 if (ReductionInfos.
size() == 0)
5106 unsigned NumReductions = ReductionInfos.
size();
5109 Value *RedArray =
Builder.CreateAlloca(RedArrayTy,
nullptr,
"red.array");
5111 Builder.SetInsertPoint(InsertBlock, InsertBlock->
end());
5113 for (
auto En :
enumerate(ReductionInfos)) {
5114 unsigned Index = En.index();
5116 Value *RedArrayElemPtr =
Builder.CreateConstInBoundsGEP2_64(
5117 RedArrayTy, RedArray, 0, Index,
"red.array.elem." +
Twine(Index));
5124 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
5134 ? IdentFlag::OMP_IDENT_FLAG_ATOMIC_REDUCE
5139 unsigned RedArrayByteSize =
DL.getTypeStoreSize(RedArrayTy);
5140 Constant *RedArraySize = ConstantInt::get(IndexTy, RedArrayByteSize);
5142 Value *Lock = getOMPCriticalRegionLock(
".reduction");
5144 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_reduce_nowait
5145 : RuntimeFunction::OMPRTL___kmpc_reduce);
5148 {Ident, ThreadId, NumVariables, RedArraySize,
5149 RedArray, ReductionFunc, Lock},
5160 Builder.CreateSwitch(ReduceCall, ContinuationBlock, 2);
5161 Switch->addCase(
Builder.getInt32(1), NonAtomicRedBlock);
5162 Switch->addCase(
Builder.getInt32(2), AtomicRedBlock);
5167 Builder.SetInsertPoint(NonAtomicRedBlock);
5168 for (
auto En :
enumerate(ReductionInfos)) {
5174 if (!IsByRef[En.index()]) {
5176 "red.value." +
Twine(En.index()));
5178 Value *PrivateRedValue =
5180 "red.private.value." +
Twine(En.index()));
5188 if (!
Builder.GetInsertBlock())
5191 if (!IsByRef[En.index()])
5195 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_end_reduce_nowait
5196 : RuntimeFunction::OMPRTL___kmpc_end_reduce);
5198 Builder.CreateBr(ContinuationBlock);
5203 Builder.SetInsertPoint(AtomicRedBlock);
5204 if (CanGenerateAtomic &&
llvm::none_of(IsByRef, [](
bool P) {
return P; })) {
5211 if (!
Builder.GetInsertBlock())
5214 Builder.CreateBr(ContinuationBlock);
5227 if (!
Builder.GetInsertBlock())
5230 Builder.SetInsertPoint(ContinuationBlock);
5241 Directive OMPD = Directive::OMPD_master;
5246 Value *Args[] = {Ident, ThreadId};
5254 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5265 Directive OMPD = Directive::OMPD_masked;
5271 Value *ArgsEnd[] = {Ident, ThreadId};
5279 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5289 Call->setDoesNotThrow();
5304 bool IsInclusive,
ScanInfo *ScanRedInfo) {
5306 llvm::Error Err = emitScanBasedDirectiveDeclsIR(AllocaIP, ScanVars,
5307 ScanVarsType, ScanRedInfo);
5318 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5321 Type *DestTy = ScanVarsType[i];
5322 Value *Val =
Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5325 Builder.CreateStore(Src, Val);
5330 Builder.GetInsertBlock()->getParent());
5333 IV = ScanRedInfo->
IV;
5336 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5339 Type *DestTy = ScanVarsType[i];
5341 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5343 Builder.CreateStore(Src, ScanVars[i]);
5357 Builder.GetInsertBlock()->getParent());
5362Error OpenMPIRBuilder::emitScanBasedDirectiveDeclsIR(
5366 Builder.restoreIP(AllocaIP);
5368 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5370 Builder.CreateAlloca(Builder.getPtrTy(),
nullptr,
"vla");
5377 Builder.restoreIP(CodeGenIP);
5379 Builder.CreateAdd(ScanRedInfo->
Span, Builder.getInt32(1));
5380 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5384 Value *Buff = Builder.CreateMalloc(
IntPtrTy, ScanVarsType[i], Allocsize,
5385 AllocSpan,
nullptr,
"arr");
5386 Builder.CreateStore(Buff, (*(ScanRedInfo->
ScanBuffPtrs))[ScanVars[i]]);
5404 Builder.SetInsertPoint(
Builder.GetInsertBlock()->getTerminator());
5413Error OpenMPIRBuilder::emitScanBasedDirectiveFinalsIR(
5419 Value *PrivateVar = RedInfo.PrivateVariable;
5420 Value *OrigVar = RedInfo.Variable;
5424 Type *SrcTy = RedInfo.ElementType;
5429 Builder.CreateStore(Src, OrigVar);
5452 Builder.SetInsertPoint(
Builder.GetInsertBlock()->getTerminator());
5477 Builder.GetInsertBlock()->getModule(),
5484 Builder.GetInsertBlock()->getModule(),
5490 llvm::ConstantInt::get(ScanRedInfo->
Span->
getType(), 1));
5491 Builder.SetInsertPoint(InputBB);
5494 Builder.SetInsertPoint(LoopBB);
5510 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5512 Builder.SetInsertPoint(InnerLoopBB);
5516 Value *ReductionVal = RedInfo.PrivateVariable;
5519 Type *DestTy = RedInfo.ElementType;
5522 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5525 Builder.CreateInBoundsGEP(DestTy, Buff, OffsetIval,
"arrayOffset");
5530 RedInfo.ReductionGen(
Builder.saveIP(), LHS, RHS, Result);
5533 Builder.CreateStore(Result, LHSPtr);
5536 IVal, llvm::ConstantInt::get(
Builder.getInt32Ty(), 1));
5538 CmpI =
Builder.CreateICmpUGE(NextIVal, Pow2K);
5539 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5542 Counter, llvm::ConstantInt::get(Counter->
getType(), 1));
5548 Builder.CreateCondBr(Cmp, LoopBB, ExitBB);
5569 Error Err = emitScanBasedDirectiveFinalsIR(ReductionInfos, ScanRedInfo);
5576Error OpenMPIRBuilder::emitScanBasedDirectiveIR(
5588 Error Err = InputLoopGen();
5599 Error Err = ScanLoopGen(Builder.saveIP());
5606void OpenMPIRBuilder::createScanBBs(ScanInfo *ScanRedInfo) {
5643 Builder.SetInsertPoint(Preheader);
5646 Builder.SetInsertPoint(Header);
5647 PHINode *IndVarPHI =
Builder.CreatePHI(IndVarTy, 2,
"omp_" + Name +
".iv");
5648 IndVarPHI->
addIncoming(ConstantInt::get(IndVarTy, 0), Preheader);
5653 Builder.CreateICmpULT(IndVarPHI, TripCount,
"omp_" + Name +
".cmp");
5654 Builder.CreateCondBr(Cmp, Body, Exit);
5659 Builder.SetInsertPoint(Latch);
5661 "omp_" + Name +
".next",
true);
5672 CL->Header = Header;
5691 NextBB, NextBB, Name);
5723 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
5732 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
5733 ScanRedInfo->
Span = TripCount;
5739 ScanRedInfo->
IV =
IV;
5740 createScanBBs(ScanRedInfo);
5743 assert(Terminator->getNumSuccessors() == 1);
5744 BasicBlock *ContinueBlock = Terminator->getSuccessor(0);
5747 Builder.GetInsertBlock()->getParent());
5750 Builder.GetInsertBlock()->getParent());
5751 Builder.CreateBr(ContinueBlock);
5757 const auto &&InputLoopGen = [&]() ->
Error {
5759 Builder.saveIP(), BodyGen, Start, Stop, Step, IsSigned, InclusiveStop,
5760 ComputeIP, Name,
true, ScanRedInfo);
5764 Builder.restoreIP((*LoopInfo)->getAfterIP());
5770 InclusiveStop, ComputeIP, Name,
true, ScanRedInfo);
5774 Builder.restoreIP((*LoopInfo)->getAfterIP());
5778 Error Err = emitScanBasedDirectiveIR(InputLoopGen, ScanLoopGen, ScanRedInfo);
5786 bool IsSigned,
bool InclusiveStop,
const Twine &Name) {
5796 assert(IndVarTy == Stop->
getType() &&
"Stop type mismatch");
5797 assert(IndVarTy == Step->
getType() &&
"Step type mismatch");
5801 ConstantInt *Zero = ConstantInt::get(IndVarTy, 0);
5817 Incr =
Builder.CreateSelect(IsNeg,
Builder.CreateNeg(Step), Step);
5820 Span =
Builder.CreateSub(UB, LB,
"",
false,
true);
5824 Span =
Builder.CreateSub(Stop, Start,
"",
true);
5829 Value *CountIfLooping;
5830 if (InclusiveStop) {
5831 CountIfLooping =
Builder.CreateAdd(
Builder.CreateUDiv(Span, Incr), One);
5837 CountIfLooping =
Builder.CreateSelect(OneCmp, One, CountIfTwo);
5840 return Builder.CreateSelect(ZeroCmp, Zero, CountIfLooping,
5841 "omp_" + Name +
".tripcount");
5846 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
5853 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
5860 ScanRedInfo->
IV = IndVar;
5861 return BodyGenCB(
Builder.saveIP(), IndVar);
5867 Builder.getCurrentDebugLocation());
5878 unsigned Bitwidth = Ty->getIntegerBitWidth();
5881 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_4u);
5884 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_8u);
5894 unsigned Bitwidth = Ty->getIntegerBitWidth();
5897 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_4u);
5900 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_8u);
5908 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
5910 "Require dedicated allocate IP");
5916 uint32_t SrcLocStrSize;
5920 case WorksharingLoopType::ForStaticLoop:
5921 Flag = OMP_IDENT_FLAG_WORK_LOOP;
5923 case WorksharingLoopType::DistributeStaticLoop:
5924 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
5926 case WorksharingLoopType::DistributeForStaticLoop:
5927 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
5934 Type *IVTy =
IV->getType();
5935 FunctionCallee StaticInit =
5936 LoopType == WorksharingLoopType::DistributeForStaticLoop
5939 FunctionCallee StaticFini =
5943 Builder.SetInsertPoint(AllocaIP.getBlock()->getFirstNonPHIOrDbgOrAlloca());
5946 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
5947 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
5948 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
5949 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
5958 Constant *One = ConstantInt::get(IVTy, 1);
5959 Builder.CreateStore(Zero, PLowerBound);
5961 Builder.CreateStore(UpperBound, PUpperBound);
5962 Builder.CreateStore(One, PStride);
5968 (LoopType == WorksharingLoopType::DistributeStaticLoop)
5969 ? OMPScheduleType::OrderedDistribute
5972 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
5976 auto BuildInitCall = [LoopType, SrcLoc, ThreadNum, PLastIter, PLowerBound,
5977 PUpperBound, IVTy, PStride, One,
Zero, StaticInit,
5980 PLowerBound, PUpperBound});
5981 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
5982 Value *PDistUpperBound =
5983 Builder.CreateAlloca(IVTy,
nullptr,
"p.distupperbound");
5984 Args.push_back(PDistUpperBound);
5989 BuildInitCall(SchedulingType,
Builder);
5990 if (HasDistSchedule &&
5991 LoopType != WorksharingLoopType::DistributeStaticLoop) {
5992 Constant *DistScheduleSchedType = ConstantInt::get(
5997 BuildInitCall(DistScheduleSchedType,
Builder);
5999 Value *LowerBound =
Builder.CreateLoad(IVTy, PLowerBound);
6000 Value *InclusiveUpperBound =
Builder.CreateLoad(IVTy, PUpperBound);
6001 Value *TripCountMinusOne =
Builder.CreateSub(InclusiveUpperBound, LowerBound);
6002 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One);
6003 CLI->setTripCount(TripCount);
6009 CLI->mapIndVar([&](Instruction *OldIV) ->
Value * {
6013 return Builder.CreateAdd(OldIV, LowerBound);
6025 omp::Directive::OMPD_for,
false,
6028 return BarrierIP.takeError();
6055 Reachable.insert(
Block);
6065 Ctx, {
MDString::get(Ctx,
"llvm.loop.parallel_accesses"), AccessGroup}));
6069OpenMPIRBuilder::applyStaticChunkedWorkshareLoop(
6073 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6074 assert((ChunkSize || DistScheduleChunkSize) &&
"Chunk size is required");
6079 Type *IVTy =
IV->getType();
6081 "Max supported tripcount bitwidth is 64 bits");
6083 :
Type::getInt64Ty(Ctx);
6086 Constant *One = ConstantInt::get(InternalIVTy, 1);
6091 SmallVector<Instruction *> UIs;
6092 for (BasicBlock &BB : *
F)
6093 if (!BB.hasTerminator())
6094 UIs.
push_back(
new UnreachableInst(
F->getContext(), &BB));
6099 LoopInfo &&LI = LIA.
run(*
F,
FAM);
6100 for (Instruction *
I : UIs)
6101 I->eraseFromParent();
6104 if (ChunkSize || DistScheduleChunkSize)
6109 FunctionCallee StaticInit =
6111 FunctionCallee StaticFini =
6117 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6118 Value *PLowerBound =
6119 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.lowerbound");
6120 Value *PUpperBound =
6121 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.upperbound");
6122 Value *PStride =
Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.stride");
6131 ChunkSize ? ChunkSize : Zero, InternalIVTy,
"chunksize");
6132 Value *CastedDistScheduleChunkSize =
Builder.CreateZExtOrTrunc(
6133 DistScheduleChunkSize ? DistScheduleChunkSize : Zero, InternalIVTy,
6134 "distschedulechunksize");
6135 Value *CastedTripCount =
6136 Builder.CreateZExt(OrigTripCount, InternalIVTy,
"tripcount");
6139 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6141 ConstantInt::get(I32Type,
static_cast<int>(DistScheduleSchedType));
6142 Builder.CreateStore(Zero, PLowerBound);
6143 Value *OrigUpperBound =
Builder.CreateSub(CastedTripCount, One);
6144 Value *IsTripCountZero =
Builder.CreateICmpEQ(CastedTripCount, Zero);
6146 Builder.CreateSelect(IsTripCountZero, Zero, OrigUpperBound);
6147 Builder.CreateStore(UpperBound, PUpperBound);
6148 Builder.CreateStore(One, PStride);
6152 uint32_t SrcLocStrSize;
6155 if (DistScheduleSchedType != OMPScheduleType::None) {
6156 Flag |= OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6161 auto BuildInitCall = [StaticInit, SrcLoc, ThreadNum, PLastIter, PLowerBound,
6162 PUpperBound, PStride, One,
6163 this](
Value *SchedulingType,
Value *ChunkSize,
6166 StaticInit, {SrcLoc, ThreadNum,
6167 SchedulingType, PLastIter,
6168 PLowerBound, PUpperBound,
6172 BuildInitCall(SchedulingType, CastedChunkSize,
Builder);
6173 if (DistScheduleSchedType != OMPScheduleType::None &&
6174 SchedType != OMPScheduleType::OrderedDistributeChunked &&
6175 SchedType != OMPScheduleType::OrderedDistribute) {
6179 BuildInitCall(DistSchedulingType, CastedDistScheduleChunkSize,
Builder);
6183 Value *FirstChunkStart =
6184 Builder.CreateLoad(InternalIVTy, PLowerBound,
"omp_firstchunk.lb");
6185 Value *FirstChunkStop =
6186 Builder.CreateLoad(InternalIVTy, PUpperBound,
"omp_firstchunk.ub");
6187 Value *FirstChunkEnd =
Builder.CreateAdd(FirstChunkStop, One);
6189 Builder.CreateSub(FirstChunkEnd, FirstChunkStart,
"omp_chunk.range");
6190 Value *NextChunkStride =
6191 Builder.CreateLoad(InternalIVTy, PStride,
"omp_dispatch.stride");
6195 Value *DispatchCounter;
6203 DispatchCounter = Counter;
6206 FirstChunkStart, CastedTripCount, NextChunkStride,
6229 Value *ChunkEnd =
Builder.CreateAdd(DispatchCounter, ChunkRange);
6230 Value *IsLastChunk =
6231 Builder.CreateICmpUGE(ChunkEnd, CastedTripCount,
"omp_chunk.is_last");
6232 Value *CountUntilOrigTripCount =
6233 Builder.CreateSub(CastedTripCount, DispatchCounter);
6235 IsLastChunk, CountUntilOrigTripCount, ChunkRange,
"omp_chunk.tripcount");
6236 Value *BackcastedChunkTC =
6237 Builder.CreateTrunc(ChunkTripCount, IVTy,
"omp_chunk.tripcount.trunc");
6238 CLI->setTripCount(BackcastedChunkTC);
6243 Value *BackcastedDispatchCounter =
6244 Builder.CreateTrunc(DispatchCounter, IVTy,
"omp_dispatch.iv.trunc");
6245 CLI->mapIndVar([&](Instruction *) ->
Value * {
6247 return Builder.CreateAdd(
IV, BackcastedDispatchCounter);
6260 return AfterIP.takeError();
6275static FunctionCallee
6278 unsigned Bitwidth = Ty->getIntegerBitWidth();
6281 case WorksharingLoopType::ForStaticLoop:
6284 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_4u);
6287 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_8u);
6289 case WorksharingLoopType::DistributeStaticLoop:
6292 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_4u);
6295 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_8u);
6297 case WorksharingLoopType::DistributeForStaticLoop:
6300 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_4u);
6303 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_8u);
6306 if (Bitwidth != 32 && Bitwidth != 64) {
6318 Function &LoopBodyFn,
bool NoLoop) {
6329 if (LoopType == WorksharingLoopType::DistributeStaticLoop) {
6330 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6331 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6332 Builder.restoreIP({InsertBlock, std::prev(InsertBlock->
end())});
6337 M, omp::RuntimeFunction::OMPRTL_omp_get_num_threads);
6338 Builder.restoreIP({InsertBlock, std::prev(InsertBlock->
end())});
6342 Builder.CreateZExtOrTrunc(NumThreads, TripCountTy,
"num.threads.cast"));
6343 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6344 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
6345 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6346 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), NoLoop));
6348 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6372 Builder.restoreIP({Preheader, Preheader->
end()});
6375 Builder.CreateBr(CLI->
getExit());
6383 CleanUpInfo.
collectBlocks(RegionBlockSet, BlocksToBeRemoved);
6391 "Expected unique undroppable user of outlined function");
6393 assert(OutlinedFnCallInstruction &&
"Expected outlined function call");
6395 "Expected outlined function call to be located in loop preheader");
6397 if (OutlinedFnCallInstruction->
arg_size() > 1)
6404 LoopBodyArg, TripCount, OutlinedFn, NoLoop);
6406 for (
auto &ToBeDeletedItem : ToBeDeleted)
6407 ToBeDeletedItem->eraseFromParent();
6414 uint32_t SrcLocStrSize;
6418 case WorksharingLoopType::ForStaticLoop:
6419 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6421 case WorksharingLoopType::DistributeStaticLoop:
6422 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6424 case WorksharingLoopType::DistributeForStaticLoop:
6425 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
6430 auto OI = std::make_unique<OutlineInfo>();
6435 SmallVector<Instruction *, 4> ToBeDeleted;
6437 OI->OuterAllocBB = AllocaIP.getBlock();
6460 SmallPtrSet<BasicBlock *, 32> ParallelRegionBlockSet;
6462 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
6464 CodeExtractorAnalysisCache CEAC(*OuterFn);
6465 CodeExtractor Extractor(Blocks,
6479 SetVector<Value *> SinkingCands, HoistingCands;
6483 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
6490 for (
auto Use :
Users) {
6492 if (ParallelRegionBlockSet.
count(Inst->getParent())) {
6493 Inst->replaceUsesOfWith(CLI->
getIndVar(), NewLoopCntLoad);
6499 OI->ExcludeArgsFromAggregate.push_back(NewLoopCntLoad);
6506 OI->PostOutlineCB = [=, ToBeDeletedVec =
6507 std::move(ToBeDeleted)](
Function &OutlinedFn) {
6517 bool NeedsBarrier, omp::ScheduleKind SchedKind,
Value *ChunkSize,
6518 bool HasSimdModifier,
bool HasMonotonicModifier,
6519 bool HasNonmonotonicModifier,
bool HasOrderedClause,
6521 Value *DistScheduleChunkSize) {
6522 if (
Config.isTargetDevice())
6523 return applyWorkshareLoopTarget(
DL, CLI, AllocaIP, LoopType, NoLoop);
6525 SchedKind, ChunkSize, HasSimdModifier, HasMonotonicModifier,
6526 HasNonmonotonicModifier, HasOrderedClause, DistScheduleChunkSize);
6528 bool IsOrdered = (EffectiveScheduleType & OMPScheduleType::ModifierOrdered) ==
6529 OMPScheduleType::ModifierOrdered;
6531 if (HasDistSchedule) {
6532 DistScheduleSchedType = DistScheduleChunkSize
6533 ? OMPScheduleType::OrderedDistributeChunked
6534 : OMPScheduleType::OrderedDistribute;
6536 switch (EffectiveScheduleType & ~OMPScheduleType::ModifierMask) {
6537 case OMPScheduleType::BaseStatic:
6538 case OMPScheduleType::BaseDistribute:
6539 assert((!ChunkSize || !DistScheduleChunkSize) &&
6540 "No chunk size with static-chunked schedule");
6541 if (IsOrdered && !HasDistSchedule)
6542 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6543 NeedsBarrier, ChunkSize);
6545 if (DistScheduleChunkSize)
6546 return applyStaticChunkedWorkshareLoop(
6547 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6548 DistScheduleChunkSize, DistScheduleSchedType);
6549 return applyStaticWorkshareLoop(
DL, CLI, AllocaIP, LoopType, NeedsBarrier,
6552 case OMPScheduleType::BaseStaticChunked:
6553 case OMPScheduleType::BaseDistributeChunked:
6554 if (IsOrdered && !HasDistSchedule)
6555 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6556 NeedsBarrier, ChunkSize);
6558 return applyStaticChunkedWorkshareLoop(
6559 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6560 DistScheduleChunkSize, DistScheduleSchedType);
6562 case OMPScheduleType::BaseRuntime:
6563 case OMPScheduleType::BaseAuto:
6564 case OMPScheduleType::BaseGreedy:
6565 case OMPScheduleType::BaseBalanced:
6566 case OMPScheduleType::BaseSteal:
6567 case OMPScheduleType::BaseRuntimeSimd:
6569 "schedule type does not support user-defined chunk sizes");
6571 case OMPScheduleType::BaseGuidedSimd:
6572 case OMPScheduleType::BaseDynamicChunked:
6573 case OMPScheduleType::BaseGuidedChunked:
6574 case OMPScheduleType::BaseGuidedIterativeChunked:
6575 case OMPScheduleType::BaseGuidedAnalyticalChunked:
6576 case OMPScheduleType::BaseStaticBalancedChunked:
6577 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6578 NeedsBarrier, ChunkSize);
6591 unsigned Bitwidth = Ty->getIntegerBitWidth();
6594 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_4u);
6597 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_8u);
6605static FunctionCallee
6607 unsigned Bitwidth = Ty->getIntegerBitWidth();
6610 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_4u);
6613 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_8u);
6620static FunctionCallee
6622 unsigned Bitwidth = Ty->getIntegerBitWidth();
6625 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_4u);
6628 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_8u);
6633OpenMPIRBuilder::applyDynamicWorkshareLoop(
DebugLoc DL, CanonicalLoopInfo *CLI,
6636 bool NeedsBarrier,
Value *Chunk) {
6637 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6639 "Require dedicated allocate IP");
6641 "Require valid schedule type");
6643 bool Ordered = (SchedType & OMPScheduleType::ModifierOrdered) ==
6644 OMPScheduleType::ModifierOrdered;
6649 uint32_t SrcLocStrSize;
6656 Type *IVTy =
IV->getType();
6661 Builder.SetInsertPoint(AllocaIP.getBlock()->getFirstNonPHIOrDbgOrAlloca());
6663 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6664 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
6665 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
6666 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
6675 Constant *One = ConstantInt::get(IVTy, 1);
6676 Builder.CreateStore(One, PLowerBound);
6678 Builder.CreateStore(UpperBound, PUpperBound);
6679 Builder.CreateStore(One, PStride);
6697 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6709 Builder.SetInsertPoint(OuterCond, OuterCond->getFirstInsertionPt());
6712 {SrcLoc, ThreadNum, PLastIter, PLowerBound, PUpperBound, PStride});
6713 Constant *Zero32 = ConstantInt::get(I32Type, 0);
6716 Builder.CreateSub(
Builder.CreateLoad(IVTy, PLowerBound), One,
"lb");
6717 Builder.CreateCondBr(MoreWork, Header, Exit);
6723 PI->setIncomingBlock(0, OuterCond);
6724 PI->setIncomingValue(0, LowerBound);
6729 Br->setSuccessor(OuterCond);
6735 UpperBound =
Builder.CreateLoad(IVTy, PUpperBound,
"ub");
6738 CI->setOperand(1, UpperBound);
6742 assert(BI->getSuccessor(1) == Exit);
6743 BI->setSuccessor(1, OuterCond);
6757 omp::Directive::OMPD_for,
false,
6760 return BarrierIP.takeError();
6812 assert(
Loops.size() >= 1 &&
"At least one loop required");
6813 size_t NumLoops =
Loops.size();
6817 return Loops.front();
6829 Loop->collectControlBlocks(OldControlBBs);
6833 if (ComputeIP.
isSet())
6840 Value *CollapsedTripCount =
nullptr;
6843 "All loops to collapse must be valid canonical loops");
6844 Value *OrigTripCount = L->getTripCount();
6845 if (!CollapsedTripCount) {
6846 CollapsedTripCount = OrigTripCount;
6851 CollapsedTripCount =
6852 Builder.CreateNUWMul(CollapsedTripCount, OrigTripCount);
6858 OrigPreheader->
getNextNode(), OrigAfter,
"collapsed");
6864 Builder.restoreIP(Result->getBodyIP());
6866 Value *Leftover = Result->getIndVar();
6868 NewIndVars.
resize(NumLoops);
6869 for (
int i = NumLoops - 1; i >= 1; --i) {
6870 Value *OrigTripCount =
Loops[i]->getTripCount();
6872 Value *NewIndVar =
Builder.CreateURem(Leftover, OrigTripCount);
6873 NewIndVars[i] = NewIndVar;
6875 Leftover =
Builder.CreateUDiv(Leftover, OrigTripCount);
6878 NewIndVars[0] = Leftover;
6887 BasicBlock *ContinueBlock = Result->getBody();
6889 auto ContinueWith = [&ContinueBlock, &ContinuePred,
DL](
BasicBlock *Dest,
6896 ContinueBlock =
nullptr;
6897 ContinuePred = NextSrc;
6904 for (
size_t i = 0; i < NumLoops - 1; ++i)
6905 ContinueWith(
Loops[i]->getBody(),
Loops[i + 1]->getHeader());
6911 for (
size_t i = NumLoops - 1; i > 0; --i)
6912 ContinueWith(
Loops[i]->getAfter(),
Loops[i - 1]->getLatch());
6915 ContinueWith(Result->getLatch(),
nullptr);
6922 for (
size_t i = 0; i < NumLoops; ++i)
6923 Loops[i]->getIndVar()->replaceAllUsesWith(NewIndVars[i]);
6937std::vector<CanonicalLoopInfo *>
6941 "Must pass as many tile sizes as there are loops");
6942 int NumLoops =
Loops.size();
6943 assert(NumLoops >= 1 &&
"At least one loop to tile required");
6955 Loop->collectControlBlocks(OldControlBBs);
6963 assert(L->isValid() &&
"All input loops must be valid canonical loops");
6964 OrigTripCounts.
push_back(L->getTripCount());
6975 for (
int i = 0; i < NumLoops - 1; ++i) {
6988 for (
int i = 0; i < NumLoops; ++i) {
6990 Value *OrigTripCount = OrigTripCounts[i];
7003 Value *FloorTripOverflow =
7004 Builder.CreateICmpNE(FloorTripRem, ConstantInt::get(IVType, 0));
7006 FloorTripOverflow =
Builder.CreateZExt(FloorTripOverflow, IVType);
7007 Value *FloorTripCount =
7008 Builder.CreateAdd(FloorCompleteTripCount, FloorTripOverflow,
7009 "omp_floor" +
Twine(i) +
".tripcount",
true);
7012 FloorCompleteCount.
push_back(FloorCompleteTripCount);
7018 std::vector<CanonicalLoopInfo *> Result;
7019 Result.reserve(NumLoops * 2);
7032 auto EmbeddNewLoop =
7033 [
this,
DL,
F, InnerEnter, &Enter, &
Continue, &OutroInsertBefore](
7036 DL, TripCount,
F, InnerEnter, OutroInsertBefore, Name);
7041 Enter = EmbeddedLoop->
getBody();
7043 OutroInsertBefore = EmbeddedLoop->
getLatch();
7044 return EmbeddedLoop;
7048 const Twine &NameBase) {
7051 EmbeddNewLoop(
P.value(), NameBase +
Twine(
P.index()));
7052 Result.push_back(EmbeddedLoop);
7056 EmbeddNewLoops(FloorCount,
"floor");
7062 for (
int i = 0; i < NumLoops; ++i) {
7066 Value *FloorIsEpilogue =
7068 Value *TileTripCount =
7075 EmbeddNewLoops(TileCounts,
"tile");
7080 for (std::pair<BasicBlock *, BasicBlock *>
P : InbetweenCode) {
7089 BodyEnter =
nullptr;
7090 BodyEntered = ExitBB;
7102 Builder.restoreIP(Result.back()->getBodyIP());
7103 for (
int i = 0; i < NumLoops; ++i) {
7106 Value *OrigIndVar = OrigIndVars[i];
7134 if (Properties.
empty())
7157 assert(
Loop->isValid() &&
"Expecting a valid CanonicalLoopInfo");
7161 assert(Latch &&
"A valid CanonicalLoopInfo must have a unique latch");
7169 if (
I.mayReadOrWriteMemory()) {
7173 I.setMetadata(LLVMContext::MD_access_group, AccessGroup);
7187 Loop->collectControlBlocks(oldControlBBs);
7192 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7193 origTripCounts.
push_back(L->getTripCount());
7202 Builder.SetInsertPoint(TCBlock);
7203 Value *fusedTripCount =
nullptr;
7205 assert(L->isValid() &&
"All loops to fuse must be valid canonical loops");
7206 Value *origTripCount = L->getTripCount();
7207 if (!fusedTripCount) {
7208 fusedTripCount = origTripCount;
7211 Value *condTP =
Builder.CreateICmpSGT(fusedTripCount, origTripCount);
7212 fusedTripCount =
Builder.CreateSelect(condTP, fusedTripCount, origTripCount,
7226 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7227 Loops[i]->getPreheader()->moveBefore(TCBlock);
7228 Loops[i]->getAfter()->moveBefore(TCBlock);
7232 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7244 for (
size_t i = 0; i <
Loops.size(); ++i) {
7246 F->getContext(),
"omp.fused.inner.cond",
F,
Loops[i]->getBody());
7247 Builder.SetInsertPoint(condBlock);
7255 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7256 Builder.SetInsertPoint(condBBs[i]);
7257 Builder.CreateCondBr(condValues[i],
Loops[i]->getBody(), condBBs[i + 1]);
7273 "omp.fused.pre_latch");
7306 const Twine &NamePrefix) {
7335 C, NamePrefix +
".if.then",
Cond->getParent(),
Cond->getNextNode());
7337 C, NamePrefix +
".if.else",
Cond->getParent(), CanonicalLoop->
getExit());
7340 Builder.SetInsertPoint(SplitBeforeIt);
7342 Builder.CreateCondBr(IfCond, ThenBlock, ElseBlock);
7345 spliceBB(IP, ThenBlock,
false, Builder.getCurrentDebugLocation());
7348 Builder.SetInsertPoint(ElseBlock);
7354 ExistingBlocks.
reserve(L->getNumBlocks() + 1);
7356 ExistingBlocks.
append(L->block_begin(), L->block_end());
7362 assert(LoopCond && LoopHeader &&
"Invalid loop structure");
7364 if (
Block == L->getLoopPreheader() ||
Block == L->getLoopLatch() ||
7371 if (
Block == ThenBlock)
7372 NewBB->
setName(NamePrefix +
".if.else");
7375 VMap[
Block] = NewBB;
7383 L->getLoopLatch()->splitBasicBlockBefore(
L->getLoopLatch()->begin(),
7384 NamePrefix +
".pre_latch");
7388 L->addBasicBlockToLoop(ThenBlock, LI);
7394 if (TargetTriple.
isX86()) {
7395 if (Features.
lookup(
"avx512f"))
7397 else if (Features.
lookup(
"avx"))
7401 if (TargetTriple.
isPPC())
7403 if (TargetTriple.
isWasm())
7410 Value *IfCond, OrderKind Order,
7420 if (!BB.hasTerminator())
7436 I->eraseFromParent();
7439 if (AlignedVars.
size()) {
7441 for (
auto &AlignedItem : AlignedVars) {
7442 Value *AlignedPtr = AlignedItem.first;
7443 Value *Alignment = AlignedItem.second;
7446 Builder.CreateAlignmentAssumption(
F->getDataLayout(), AlignedPtr,
7454 createIfVersion(CanonicalLoop, IfCond, VMap, LIA, LI, L,
"simd");
7467 Reachable.insert(
Block);
7477 if ((Safelen ==
nullptr) || (Order == OrderKind::OMP_ORDER_concurrent))
7493 Ctx, {
MDString::get(Ctx,
"llvm.loop.vectorize.enable"), BoolConst}));
7495 if (Simdlen || Safelen) {
7499 ConstantInt *VectorizeWidth = Simdlen ==
nullptr ? Safelen : Simdlen;
7525static std::unique_ptr<TargetMachine>
7529 StringRef CPU =
F->getFnAttribute(
"target-cpu").getValueAsString();
7530 StringRef Features =
F->getFnAttribute(
"target-features").getValueAsString();
7541 std::nullopt, OptLevel));
7559 if (!BB.hasTerminator())
7572 [&](
const Function &
F) {
return TM->getTargetTransformInfo(
F); });
7573 FAM.registerPass([&]() {
return TIRA; });
7587 I->eraseFromParent();
7590 assert(L &&
"Expecting CanonicalLoopInfo to be recognized as a loop");
7595 nullptr, ORE,
static_cast<int>(OptLevel),
7615 <<
" Threshold=" << UP.
Threshold <<
"\n"
7618 <<
" PartialOptSizeThreshold="
7638 Ptr =
Load->getPointerOperand();
7640 Ptr =
Store->getPointerOperand();
7647 if (Alloca->getParent() == &
F->getEntryBlock())
7667 int MaxTripCount = 0;
7668 bool MaxOrZero =
false;
7669 unsigned TripMultiple = 0;
7673 MaxTripCount, MaxOrZero, TripMultiple, UCE, UP, PP);
7674 LLVM_DEBUG(
dbgs() <<
"Suggesting unroll factor of " << Factor <<
"\n");
7685 assert(Factor >= 0 &&
"Unroll factor must not be negative");
7701 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst}));
7714 *UnrolledCLI =
Loop;
7719 "unrolling only makes sense with a factor of 2 or larger");
7721 Type *IndVarTy =
Loop->getIndVarType();
7728 std::vector<CanonicalLoopInfo *>
LoopNest =
7743 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst})});
7746 (*UnrolledCLI)->assertOK();
7764 Value *Args[] = {Ident, ThreadId, BufSize, CpyBuf, CpyFn, DidItLD};
7783 if (!CPVars.
empty()) {
7788 Directive OMPD = Directive::OMPD_single;
7793 Value *Args[] = {Ident, ThreadId};
7802 if (
Error Err = FiniCB(IP))
7823 EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCBWrapper,
7830 for (
size_t I = 0, E = CPVars.
size();
I < E; ++
I)
7833 ConstantInt::get(Int64, 0), CPVars[
I],
7836 }
else if (!IsNowait) {
7839 omp::Directive::OMPD_unknown,
false,
7857 Directive::OMPD_scope,
nullptr,
nullptr,
7858 BodyGenCB, FiniCB,
false,
true,
7866 omp::Directive::OMPD_unknown,
7882 Directive OMPD = Directive::OMPD_critical;
7887 Value *LockVar = getOMPCriticalRegionLock(CriticalName);
7888 Value *Args[] = {Ident, ThreadId, LockVar};
7905 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
7913 const Twine &Name,
bool IsDependSource) {
7917 "OpenMP runtime requires depend vec with i64 type");
7930 for (
unsigned I = 0;
I < NumLoops; ++
I) {
7944 Value *Args[] = {Ident, ThreadId, DependBaseAddrGEP};
7962 Directive OMPD = Directive::OMPD_ordered;
7971 Value *Args[] = {Ident, ThreadId};
7981 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
7988 bool HasFinalize,
bool IsCancellable) {
7995 BasicBlock *EntryBB = Builder.GetInsertBlock();
8004 emitCommonDirectiveEntry(OMPD, EntryCall, ExitBB, Conditional);
8016 "Unexpected control flow graph state!!");
8018 emitCommonDirectiveExit(OMPD, FinIP, ExitCall, HasFinalize);
8020 return AfterIP.takeError();
8025 "Unexpected Insertion point location!");
8028 auto InsertBB = merged ? ExitPredBB : ExitBB;
8031 Builder.SetInsertPoint(InsertBB);
8033 return Builder.saveIP();
8037 Directive OMPD,
Value *EntryCall, BasicBlock *ExitBB,
bool Conditional) {
8039 if (!Conditional || !EntryCall)
8045 auto *UI =
new UnreachableInst(
Builder.getContext(), ThenBB);
8055 Builder.CreateCondBr(CallBool, ThenBB, ExitBB);
8059 UI->eraseFromParent();
8067 omp::Directive OMPD,
InsertPointTy FinIP, Instruction *ExitCall,
8075 "Unexpected finalization stack state!");
8078 assert(Fi.DK == OMPD &&
"Unexpected Directive for Finalization call!");
8080 if (
Error Err = Fi.mergeFiniBB(
Builder, FinIP.getBlock()))
8081 return std::move(Err);
8085 Builder.SetInsertPoint(FinIP.getBlock()->getTerminator());
8095 return IRBuilder<>::InsertPoint(ExitCall->
getParent(),
8129 "copyin.not.master.end");
8136 Builder.SetInsertPoint(OMP_Entry);
8139 Value *cmp =
Builder.CreateICmpNE(MasterPtr, PrivatePtr);
8140 Builder.CreateCondBr(cmp, CopyBegin, CopyEnd);
8142 Builder.SetInsertPoint(CopyBegin);
8160 Value *Args[] = {ThreadId,
Size, Allocator};
8183 return Builder.CreateCall(Fn, Args, Name);
8197 Value *Args[] = {ThreadId, Addr, Allocator};
8204 const Twine &Name) {
8212 M.getContext(),
M.getDataLayout().getPrefTypeAlign(Int64)));
8218 const Twine &Name) {
8220 Loc,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)), Name);
8225 const Twine &Name) {
8231 return Builder.CreateCall(Fn, Args, Name);
8236 const Twine &Name) {
8238 Loc, Addr,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)),
8245 Value *DependenceAddress,
bool HaveNowaitClause) {
8253 if (Device ==
nullptr)
8255 else if (Device->getType() != Int32)
8256 Device =
Builder.CreateIntCast(Device, Int32,
true);
8257 Constant *InteropTypeVal = ConstantInt::get(Int32, (
int)InteropType);
8258 if (NumDependences ==
nullptr) {
8259 NumDependences = ConstantInt::get(Int32, 0);
8263 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8265 Ident, ThreadId, InteropVar, InteropTypeVal,
8266 Device, NumDependences, DependenceAddress, HaveNowaitClauseVal};
8275 Value *NumDependences,
Value *DependenceAddress,
bool HaveNowaitClause) {
8283 if (Device ==
nullptr)
8285 else if (Device->getType() != Int32)
8286 Device =
Builder.CreateIntCast(Device, Int32,
true);
8287 if (NumDependences ==
nullptr) {
8288 NumDependences = ConstantInt::get(Int32, 0);
8292 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8294 Ident, ThreadId, InteropVar, Device,
8295 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8304 Value *NumDependences,
8305 Value *DependenceAddress,
8306 bool HaveNowaitClause) {
8313 if (Device ==
nullptr)
8315 else if (Device->getType() != Int32)
8316 Device =
Builder.CreateIntCast(Device, Int32,
true);
8317 if (NumDependences ==
nullptr) {
8318 NumDependences = ConstantInt::get(Int32, 0);
8322 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8324 Ident, ThreadId, InteropVar, Device,
8325 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8355 assert(!Attrs.MaxThreads.empty() && !Attrs.MaxTeams.empty() &&
8356 "expected num_threads and num_teams to be specified");
8376 const std::string DebugPrefix =
"_debug__";
8377 if (KernelName.
ends_with(DebugPrefix)) {
8378 KernelName = KernelName.
drop_back(DebugPrefix.length());
8379 Kernel =
M.getFunction(KernelName);
8385 if (Attrs.MinTeams > 1 || Attrs.MaxTeams.front() > 0)
8390 int32_t MaxThreadsVal = Attrs.MaxThreads.front();
8397 MaxThreadsVal = Attrs.MinThreads;
8401 if (MaxThreadsVal > 0)
8412 omp::RuntimeFunction::OMPRTL___kmpc_target_init);
8415 Twine DynamicEnvironmentName = KernelName +
"_dynamic_environment";
8416 Constant *DynamicEnvironmentInitializer =
8420 DynamicEnvironmentInitializer, DynamicEnvironmentName,
8422 DL.getDefaultGlobalsAddressSpace());
8426 DynamicEnvironmentGV->
getType() == DynamicEnvironmentPtr
8427 ? DynamicEnvironmentGV
8429 DynamicEnvironmentPtr);
8432 ConfigurationEnvironment, {
8433 UseGenericStateMachineVal,
8434 MayUseNestedParallelismVal,
8443 KernelEnvironment, {
8444 ConfigurationEnvironmentInitializer,
8448 std::string KernelEnvironmentName =
8449 (KernelName +
"_kernel_environment").str();
8452 KernelEnvironmentInitializer, KernelEnvironmentName,
8454 DL.getDefaultGlobalsAddressSpace());
8458 KernelEnvironmentGV->
getType() == KernelEnvironmentPtr
8459 ? KernelEnvironmentGV
8461 KernelEnvironmentPtr);
8462 Value *KernelLaunchEnvironment =
8465 KernelLaunchEnvironment =
8466 KernelLaunchEnvironment->
getType() == KernelLaunchEnvParamTy
8467 ? KernelLaunchEnvironment
8468 :
Builder.CreateAddrSpaceCast(KernelLaunchEnvironment,
8469 KernelLaunchEnvParamTy);
8471 Fn, {KernelEnvironment, KernelLaunchEnvironment});
8483 auto *UI =
Builder.CreateUnreachable();
8489 Builder.SetInsertPoint(WorkerExitBB);
8493 Builder.SetInsertPoint(CheckBBTI);
8494 Builder.CreateCondBr(ExecUserCode, UI->getParent(), WorkerExitBB);
8496 CheckBBTI->eraseFromParent();
8497 UI->eraseFromParent();
8505 int32_t TeamsReductionDataSize) {
8510 omp::RuntimeFunction::OMPRTL___kmpc_target_deinit);
8514 if (!TeamsReductionDataSize)
8520 const std::string DebugPrefix =
"_debug__";
8522 KernelName = KernelName.
drop_back(DebugPrefix.length());
8523 auto *KernelEnvironmentGV =
8524 M.getNamedGlobal((KernelName +
"_kernel_environment").str());
8525 assert(KernelEnvironmentGV &&
"Expected kernel environment global\n");
8526 auto *KernelEnvironmentInitializer = KernelEnvironmentGV->getInitializer();
8528 KernelEnvironmentInitializer,
8529 ConstantInt::get(Int32, TeamsReductionDataSize), {0, 7});
8530 KernelEnvironmentGV->setInitializer(NewInitializer);
8535 if (
Kernel.hasFnAttribute(Name)) {
8536 int32_t OldLimit =
Kernel.getFnAttributeAsParsedInteger(Name);
8542std::pair<int32_t, int32_t>
8544 int32_t ThreadLimit =
8545 Kernel.getFnAttributeAsParsedInteger(
"omp_target_thread_limit");
8548 const auto &Attr =
Kernel.getFnAttribute(
"amdgpu-flat-work-group-size");
8549 if (!Attr.isValid() || !Attr.isStringAttribute())
8550 return {0, ThreadLimit};
8551 auto [LBStr, UBStr] = Attr.getValueAsString().split(
',');
8554 return {0, ThreadLimit};
8555 UB = ThreadLimit ? std::min(ThreadLimit, UB) : UB;
8563 return {0, ThreadLimit ? std::min(ThreadLimit, UB) : UB};
8565 return {0, ThreadLimit};
8571 Kernel.addFnAttr(
"omp_target_thread_limit", std::to_string(UB));
8574 Kernel.addFnAttr(
"amdgpu-flat-work-group-size",
8582std::pair<int32_t, int32_t>
8585 return {0,
Kernel.getFnAttributeAsParsedInteger(
"omp_target_num_teams")};
8589 int32_t LB, int32_t UB) {
8597 Kernel.addFnAttr(
"omp_target_num_teams", std::to_string(LB));
8600void OpenMPIRBuilder::setOutlinedTargetRegionFunctionAttributes(
8609 else if (
T.isNVPTX())
8611 else if (
T.isSPIRV())
8616Constant *OpenMPIRBuilder::createOutlinedFunctionID(Function *OutlinedFn,
8617 StringRef EntryFnIDName) {
8618 if (
Config.isTargetDevice()) {
8619 assert(OutlinedFn &&
"The outlined function must exist if embedded");
8623 return new GlobalVariable(
8628Constant *OpenMPIRBuilder::createTargetRegionEntryAddr(Function *OutlinedFn,
8629 StringRef EntryFnName) {
8633 assert(!
M.getGlobalVariable(EntryFnName,
true) &&
8634 "Named kernel already exists?");
8635 return new GlobalVariable(
8648 if (
Config.isTargetDevice() || !
Config.openMPOffloadMandatory()) {
8652 OutlinedFn = *CBResult;
8654 OutlinedFn =
nullptr;
8660 if (!IsOffloadEntry)
8663 std::string EntryFnIDName =
8665 ? std::string(EntryFnName)
8669 EntryFnName, EntryFnIDName);
8677 setOutlinedTargetRegionFunctionAttributes(OutlinedFn);
8678 auto OutlinedFnID = createOutlinedFunctionID(OutlinedFn, EntryFnIDName);
8679 auto EntryAddr = createTargetRegionEntryAddr(OutlinedFn, EntryFnName);
8681 EntryInfo, EntryAddr, OutlinedFnID,
8683 return OutlinedFnID;
8701 bool IsStandAlone = !BodyGenCB;
8708 MapInfo = &GenMapInfoCB(
Builder.saveIP());
8710 AllocaIP,
Builder.saveIP(), *MapInfo, Info, CustomMapperCB,
8711 true, DeviceAddrCB))
8718 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
8728 SrcLocInfo, DeviceID,
8735 assert(MapperFunc &&
"MapperFunc missing for standalone target data");
8739 if (Info.HasNoWait) {
8749 if (Info.HasNoWait) {
8753 emitBlock(OffloadContBlock, CurFn,
true);
8759 bool RequiresOuterTargetTask = Info.HasNoWait;
8760 if (!RequiresOuterTargetTask)
8761 cantFail(TaskBodyCB(
nullptr,
nullptr,
8765 {}, RTArgs, Info.HasNoWait));
8768 omp::OMPRTL___tgt_target_data_begin_mapper);
8772 for (
auto DeviceMap : Info.DevicePtrInfoMap) {
8776 Builder.CreateStore(LI, DeviceMap.second.second);
8813 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
8822 Value *OffloadingArgs[] = {SrcLocInfo, DeviceID,
8845 return emitIfClause(IfCond, BeginThenGen, BeginElseGen, AllocaIP);
8846 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
8861 return emitIfClause(IfCond, EndThenGen, EndElseGen, AllocaIP);
8862 return EndThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
8865 return emitIfClause(IfCond, BeginThenGen, EndElseGen, AllocaIP);
8866 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
8877 bool IsGPUDistribute) {
8878 assert((IVSize == 32 || IVSize == 64) &&
8879 "IV size is not compatible with the omp runtime");
8881 if (IsGPUDistribute)
8883 ? (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_4
8884 : omp::OMPRTL___kmpc_distribute_static_init_4u)
8885 : (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_8
8886 : omp::OMPRTL___kmpc_distribute_static_init_8u);
8888 Name = IVSize == 32 ? (IVSigned ? omp::OMPRTL___kmpc_for_static_init_4
8889 : omp::OMPRTL___kmpc_for_static_init_4u)
8890 : (IVSigned ? omp::OMPRTL___kmpc_for_static_init_8
8891 : omp::OMPRTL___kmpc_for_static_init_8u);
8898 assert((IVSize == 32 || IVSize == 64) &&
8899 "IV size is not compatible with the omp runtime");
8901 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_4
8902 : omp::OMPRTL___kmpc_dispatch_init_4u)
8903 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_8
8904 : omp::OMPRTL___kmpc_dispatch_init_8u);
8911 assert((IVSize == 32 || IVSize == 64) &&
8912 "IV size is not compatible with the omp runtime");
8914 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_4
8915 : omp::OMPRTL___kmpc_dispatch_next_4u)
8916 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_8
8917 : omp::OMPRTL___kmpc_dispatch_next_8u);
8924 assert((IVSize == 32 || IVSize == 64) &&
8925 "IV size is not compatible with the omp runtime");
8927 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_4
8928 : omp::OMPRTL___kmpc_dispatch_fini_4u)
8929 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_8
8930 : omp::OMPRTL___kmpc_dispatch_fini_8u);
8941 DenseMap<
Value *, std::tuple<Value *, unsigned>> &ValueReplacementMap) {
8949 auto GetUpdatedDIVariable = [&](
DILocalVariable *OldVar,
unsigned arg) {
8953 if (NewVar && (arg == NewVar->
getArg()))
8963 auto UpdateDebugRecord = [&](
auto *DR) {
8966 for (
auto Loc : DR->location_ops()) {
8967 auto Iter = ValueReplacementMap.find(
Loc);
8968 if (Iter != ValueReplacementMap.end()) {
8969 DR->replaceVariableLocationOp(
Loc, std::get<0>(Iter->second));
8970 ArgNo = std::get<1>(Iter->second) + 1;
8974 DR->setVariable(GetUpdatedDIVariable(OldVar, ArgNo));
8979 if (DVR->getNumVariableLocationOps() != 1u) {
8980 DVR->setKillLocation();
8983 Value *
Loc = DVR->getVariableLocationOp(0u);
8990 RequiredBB = &DVR->getFunction()->getEntryBlock();
8992 if (RequiredBB && RequiredBB != CurBB) {
9004 "Unexpected debug intrinsic");
9006 UpdateDebugRecord(&DVR);
9007 MoveDebugRecordToCorrectBlock(&DVR);
9010 for (
auto *DVR : DVRsToDelete)
9011 DVR->getMarker()->MarkedInstr->dropOneDbgRecord(DVR);
9015 Module *M = Func->getParent();
9018 DB.createQualifiedType(dwarf::DW_TAG_pointer_type,
nullptr);
9019 unsigned ArgNo = Func->arg_size();
9021 NewSP,
"dyn_ptr", ArgNo, NewSP->
getFile(), 0, VoidPtrTy,
9022 false, DINode::DIFlags::FlagArtificial);
9024 Argument *LastArg = Func->getArg(Func->arg_size() - 1);
9025 DB.insertDeclare(LastArg, Var, DB.createExpression(),
Loc,
9046 for (
auto &Arg : Inputs)
9047 ParameterTypes.
push_back(Arg->getType()->isPointerTy()
9051 for (
auto &Arg : Inputs)
9052 ParameterTypes.
push_back(Arg->getType());
9060 auto BB = Builder.GetInsertBlock();
9061 auto M = BB->getModule();
9072 if (TargetCpuAttr.isStringAttribute())
9073 Func->addFnAttr(TargetCpuAttr);
9075 auto TargetFeaturesAttr = ParentFn->
getFnAttribute(
"target-features");
9076 if (TargetFeaturesAttr.isStringAttribute())
9077 Func->addFnAttr(TargetFeaturesAttr);
9082 OMPBuilder.
emitUsed(
"llvm.compiler.used", {ExecMode});
9093 Builder.SetInsertPoint(EntryBB);
9099 BasicBlock *UserCodeEntryBB = Builder.GetInsertBlock();
9109 splitBB(Builder,
true,
"outlined.body");
9116 Builder.SetInsertPoint(ExitBB);
9123 Builder.CreateRetVoid();
9127 auto AllocaIP = Builder.saveIP();
9132 const auto &ArgRange =
make_range(Func->arg_begin(), Func->arg_end() - 1);
9164 if (Instr->getFunction() == Func)
9165 Instr->replaceUsesOfWith(
Input, InputCopy);
9171 for (
auto InArg :
zip(Inputs, ArgRange)) {
9173 Argument &Arg = std::get<1>(InArg);
9174 Value *InputCopy =
nullptr;
9177 Arg,
Input, InputCopy, AllocaIP, Builder.saveIP(),
9181 Builder.restoreIP(*AfterIP);
9182 ValueReplacementMap[
Input] = std::make_tuple(InputCopy, Arg.
getArgNo());
9202 DeferredReplacement.push_back(std::make_pair(
Input, InputCopy));
9209 ReplaceValue(
Input, InputCopy, Func);
9213 for (
auto Deferred : DeferredReplacement)
9214 ReplaceValue(std::get<0>(Deferred), std::get<1>(Deferred), Func);
9217 ValueReplacementMap);
9225 Value *TaskWithPrivates,
9226 Type *TaskWithPrivatesTy) {
9228 Type *TaskTy = OMPIRBuilder.Task;
9231 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 0);
9232 Value *Shareds = TaskT;
9242 if (TaskWithPrivatesTy != TaskTy)
9243 Shareds = Builder.CreateStructGEP(TaskTy, TaskT, 0);
9260 const size_t NumOffloadingArrays,
const int SharedArgsOperandNo) {
9265 assert((!NumOffloadingArrays || PrivatesTy) &&
9266 "PrivatesTy cannot be nullptr when there are offloadingArrays"
9299 Type *TaskPtrTy = OMPBuilder.TaskPtr;
9300 [[maybe_unused]]
Type *TaskTy = OMPBuilder.Task;
9306 ".omp_target_task_proxy_func",
9307 Builder.GetInsertBlock()->getModule());
9308 Value *ThreadId = ProxyFn->getArg(0);
9309 Value *TaskWithPrivates = ProxyFn->getArg(1);
9310 ThreadId->
setName(
"thread.id");
9311 TaskWithPrivates->
setName(
"task");
9313 bool HasShareds = SharedArgsOperandNo > 0;
9314 bool HasOffloadingArrays = NumOffloadingArrays > 0;
9317 Builder.SetInsertPoint(EntryBB);
9323 if (HasOffloadingArrays) {
9324 assert(TaskTy != TaskWithPrivatesTy &&
9325 "If there are offloading arrays to pass to the target"
9326 "TaskTy cannot be the same as TaskWithPrivatesTy");
9329 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 1);
9330 for (
unsigned int i = 0; i < NumOffloadingArrays; ++i)
9332 Builder.CreateStructGEP(PrivatesTy, Privates, i));
9336 auto *ArgStructAlloca =
9338 assert(ArgStructAlloca &&
9339 "Unable to find the alloca instruction corresponding to arguments "
9340 "for extracted function");
9342 std::optional<TypeSize> ArgAllocSize =
9344 assert(ArgStructType && ArgAllocSize &&
9345 "Unable to determine size of arguments for extracted function");
9346 uint64_t StructSize = ArgAllocSize->getFixedValue();
9349 Builder.CreateAlloca(ArgStructType,
nullptr,
"structArg");
9351 Value *SharedsSize = Builder.getInt64(StructSize);
9354 OMPBuilder, Builder, TaskWithPrivates, TaskWithPrivatesTy);
9356 Builder.CreateMemCpy(
9357 NewArgStructAlloca, NewArgStructAlloca->
getAlign(), LoadShared,
9359 KernelLaunchArgs.
push_back(NewArgStructAlloca);
9362 Builder.CreateRetVoid();
9368 return GEP->getSourceElementType();
9370 return Alloca->getAllocatedType();
9393 if (OffloadingArraysToPrivatize.
empty())
9394 return OMPIRBuilder.Task;
9397 for (
Value *V : OffloadingArraysToPrivatize) {
9398 assert(V->getType()->isPointerTy() &&
9399 "Expected pointer to array to privatize. Got a non-pointer value "
9402 assert(ArrayTy &&
"ArrayType cannot be nullptr");
9408 "struct.task_with_privates");
9422 EntryFnName, Inputs, CBFunc,
9427 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
9564 TargetTaskAllocaBB->
begin());
9567 auto OI = std::make_unique<OutlineInfo>();
9568 OI->EntryBB = TargetTaskAllocaBB;
9569 OI->OuterAllocBB = AllocaIP.
getBlock();
9574 Builder, AllocaIP, ToBeDeleted, TargetTaskAllocaIP,
"global.tid",
false));
9577 Builder.restoreIP(TargetTaskBodyIP);
9578 if (
Error Err = TaskBodyCB(DeviceID, RTLoc, TargetTaskAllocaIP))
9596 bool NeedsTargetTask = HasNoWait && DeviceID;
9597 if (NeedsTargetTask) {
9603 OffloadingArraysToPrivatize.
push_back(V);
9604 OI->ExcludeArgsFromAggregate.push_back(V);
9608 OI->PostOutlineCB = [
this, ToBeDeleted, Dependencies, NeedsTargetTask,
9609 DeviceID, OffloadingArraysToPrivatize](
9612 "there must be a single user for the outlined function");
9626 const unsigned int NumStaleCIArgs = StaleCI->
arg_size();
9627 bool HasShareds = NumStaleCIArgs > OffloadingArraysToPrivatize.
size() + 1;
9629 NumStaleCIArgs == (OffloadingArraysToPrivatize.
size() + 2)) &&
9630 "Wrong number of arguments for StaleCI when shareds are present");
9631 int SharedArgOperandNo =
9632 HasShareds ? OffloadingArraysToPrivatize.
size() + 1 : 0;
9638 if (!OffloadingArraysToPrivatize.
empty())
9643 *
this,
Builder, StaleCI, PrivatesTy, TaskWithPrivatesTy,
9644 OffloadingArraysToPrivatize.
size(), SharedArgOperandNo);
9646 LLVM_DEBUG(
dbgs() <<
"Proxy task entry function created: " << *ProxyFn
9649 Builder.SetInsertPoint(StaleCI);
9666 OMPRTL___kmpc_omp_target_task_alloc);
9678 M.getDataLayout().getTypeStoreSize(TaskWithPrivatesTy));
9685 auto *ArgStructAlloca =
9687 assert(ArgStructAlloca &&
9688 "Unable to find the alloca instruction corresponding to arguments "
9689 "for extracted function");
9690 std::optional<TypeSize> ArgAllocSize =
9693 "Unable to determine size of arguments for extracted function");
9694 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
9713 TaskSize, SharedsSize,
9716 if (NeedsTargetTask) {
9717 assert(DeviceID &&
"Expected non-empty device ID.");
9727 *
this,
Builder, TaskData, TaskWithPrivatesTy);
9728 Builder.CreateMemCpy(TaskShareds, Alignment, Shareds, Alignment,
9731 if (!OffloadingArraysToPrivatize.
empty()) {
9733 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskData, 1);
9734 for (
unsigned int i = 0; i < OffloadingArraysToPrivatize.
size(); ++i) {
9735 Value *PtrToPrivatize = OffloadingArraysToPrivatize[i];
9742 "ElementType should match ArrayType");
9745 Value *Dst =
Builder.CreateStructGEP(PrivatesTy, Privates, i);
9747 Dst, Alignment, PtrToPrivatize, Alignment,
9748 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(ElementType)));
9752 Value *DepArray =
nullptr;
9753 Value *NumDeps =
nullptr;
9756 NumDeps = Dependencies.
NumDeps;
9757 }
else if (!Dependencies.
Deps.empty()) {
9759 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
9770 if (!NeedsTargetTask) {
9779 ConstantInt::get(
Builder.getInt32Ty(), 0),
9792 }
else if (DepArray) {
9800 {Ident, ThreadID, TaskData, NumDeps, DepArray,
9801 ConstantInt::get(
Builder.getInt32Ty(), 0),
9811 I->eraseFromParent();
9816 << *(
Builder.GetInsertBlock()) <<
"\n");
9818 << *(
Builder.GetInsertBlock()->getParent()->getParent())
9830 CustomMapperCB, IsNonContiguous, DeviceAddrCB))
9853 Builder.restoreIP(IP);
9859 return Builder.saveIP();
9862 bool HasDependencies = !Dependencies.
empty();
9863 bool RequiresOuterTargetTask = HasNoWait || HasDependencies;
9880 if (OutlinedFnID && DeviceID)
9882 EmitTargetCallFallbackCB, KArgs,
9883 DeviceID, RTLoc, TargetTaskAllocaIP);
9891 return EmitTargetCallFallbackCB(OMPBuilder.
Builder.
saveIP());
9898 auto &&EmitTargetCallElse =
9905 if (RequiresOuterTargetTask) {
9912 Dependencies, EmptyRTArgs, HasNoWait);
9914 return EmitTargetCallFallbackCB(Builder.saveIP());
9917 Builder.restoreIP(AfterIP);
9921 auto &&EmitTargetCallThen =
9925 Info.HasNoWait = HasNoWait;
9930 AllocaIP, Builder.saveIP(), Info, RTArgs, MapInfo, CustomMapperCB,
9936 for (
auto [DefaultVal, RuntimeVal] :
9938 NumTeamsC.
push_back(RuntimeVal ? RuntimeVal
9939 : Builder.getInt32(DefaultVal));
9943 auto InitMaxThreadsClause = [&Builder](
Value *
Clause) {
9945 Clause = Builder.CreateIntCast(
Clause, Builder.getInt32Ty(),
9949 auto CombineMaxThreadsClauses = [&Builder](
Value *
Clause,
Value *&Result) {
9952 Result ? Builder.CreateSelect(Builder.CreateICmpULT(Result,
Clause),
9960 Value *MaxThreadsClause =
9962 ? InitMaxThreadsClause(RuntimeAttrs.
MaxThreads)
9965 for (
auto [TeamsVal, TargetVal] :
zip_equal(
9967 Value *TeamsThreadLimitClause = InitMaxThreadsClause(TeamsVal);
9968 Value *NumThreads = InitMaxThreadsClause(TargetVal);
9970 CombineMaxThreadsClauses(TeamsThreadLimitClause, NumThreads);
9971 CombineMaxThreadsClauses(MaxThreadsClause, NumThreads);
9973 NumThreadsC.
push_back(NumThreads ? NumThreads : Builder.getInt32(0));
9976 unsigned NumTargetItems = Info.NumberOfPtrs;
9984 Builder.getInt64Ty(),
9986 : Builder.getInt64(0);
9990 DynCGroupMem = Builder.getInt32(0);
9993 NumTargetItems, RTArgs, TripCount, NumTeamsC, NumThreadsC, DynCGroupMem,
9994 HasNoWait,
false, DynCGroupMemFallback);
10001 if (RequiresOuterTargetTask)
10003 RTLoc, AllocaIP, Dependencies,
10004 KArgs.
RTArgs, Info.HasNoWait);
10007 Builder, OutlinedFnID, EmitTargetCallFallbackCB, KArgs,
10008 RuntimeAttrs.
DeviceID, RTLoc, AllocaIP);
10011 Builder.restoreIP(AfterIP);
10018 if (!OutlinedFnID) {
10019 cantFail(EmitTargetCallElse(AllocaIP, Builder.saveIP(), DeallocBlocks));
10025 cantFail(EmitTargetCallThen(AllocaIP, Builder.saveIP(), DeallocBlocks));
10030 EmitTargetCallElse, AllocaIP));
10043 bool HasNowait,
Value *DynCGroupMem,
10049 Builder.restoreIP(CodeGenIP);
10057 *
this,
Builder, IsOffloadEntry, EntryInfo, DefaultAttrs, OutlinedFn,
10058 OutlinedFnID, Inputs, CBFunc, ArgAccessorFuncCB))
10064 if (!
Config.isTargetDevice())
10066 RuntimeAttrs, IfCond, OutlinedFn, OutlinedFnID, Inputs,
10067 GenMapInfoCB, CustomMapperCB, Dependencies, HasNowait,
10068 DynCGroupMem, DynCGroupMemFallback);
10082 return OS.
str().str();
10087 return OpenMPIRBuilder::getNameWithSeparators(Parts,
Config.firstSeparator(),
10093 auto &Elem = *
InternalVars.try_emplace(Name,
nullptr).first;
10095 assert(Elem.second->getValueType() == Ty &&
10096 "OMP internal variable has different type than requested");
10109 :
M.getTargetTriple().isAMDGPU()
10111 :
DL.getDefaultGlobalsAddressSpace();
10120 const llvm::Align PtrAlign =
DL.getPointerABIAlignment(AddressSpaceVal);
10121 GV->setAlignment(std::max(TypeAlign, PtrAlign));
10125 return Elem.second;
10128Value *OpenMPIRBuilder::getOMPCriticalRegionLock(
StringRef CriticalName) {
10129 std::string Prefix =
Twine(
"gomp_critical_user_", CriticalName).
str();
10130 std::string Name = getNameWithSeparators({Prefix,
"var"},
".",
".");
10141 return SizePtrToInt;
10146 std::string VarName) {
10154 return MaptypesArrayGlobal;
10159 unsigned NumOperands,
10168 ArrI8PtrTy,
nullptr,
".offload_baseptrs");
10172 ArrI64Ty,
nullptr,
".offload_sizes");
10183 int64_t DeviceID,
unsigned NumOperands) {
10189 Value *ArgsBaseGEP =
10191 {Builder.getInt32(0), Builder.getInt32(0)});
10194 {Builder.getInt32(0), Builder.getInt32(0)});
10195 Value *ArgSizesGEP =
10197 {Builder.getInt32(0), Builder.getInt32(0)});
10201 Builder.getInt32(NumOperands),
10202 ArgsBaseGEP, ArgsGEP, ArgSizesGEP,
10203 MaptypesArg, MapnamesArg, NullPtr});
10210 assert((!ForEndCall || Info.separateBeginEndCalls()) &&
10211 "expected region end call to runtime only when end call is separate");
10213 auto VoidPtrTy = UnqualPtrTy;
10214 auto VoidPtrPtrTy = UnqualPtrTy;
10216 auto Int64PtrTy = UnqualPtrTy;
10218 if (!Info.NumberOfPtrs) {
10230 Info.RTArgs.BasePointersArray,
10233 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray,
10237 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
10241 ForEndCall && Info.RTArgs.MapTypesArrayEnd ? Info.RTArgs.MapTypesArrayEnd
10242 : Info.RTArgs.MapTypesArray,
10248 if (!Info.EmitDebug)
10252 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.MapNamesArray,
10257 if (!Info.HasMapper)
10261 Builder.CreatePointerCast(Info.RTArgs.MappersArray, VoidPtrPtrTy);
10282 "struct.descriptor_dim");
10284 enum { OffsetFD = 0, CountFD, StrideFD };
10288 for (
unsigned I = 0, L = 0, E = NonContigInfo.
Dims.
size();
I < E; ++
I) {
10291 if (NonContigInfo.
Dims[
I] == 1)
10296 Builder.CreateAlloca(ArrayTy,
nullptr,
"dims");
10297 Builder.restoreIP(CodeGenIP);
10298 for (
unsigned II = 0, EE = NonContigInfo.
Dims[
I];
II < EE; ++
II) {
10299 unsigned RevIdx = EE -
II - 1;
10303 Value *OffsetLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, OffsetFD);
10305 NonContigInfo.
Offsets[L][RevIdx], OffsetLVal,
10306 M.getDataLayout().getPrefTypeAlign(OffsetLVal->
getType()));
10308 Value *CountLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, CountFD);
10310 NonContigInfo.
Counts[L][RevIdx], CountLVal,
10311 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10313 Value *StrideLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, StrideFD);
10315 NonContigInfo.
Strides[L][RevIdx], StrideLVal,
10316 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10319 Builder.restoreIP(CodeGenIP);
10320 Value *DAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
10321 DimsAddr,
Builder.getPtrTy());
10324 Info.RTArgs.PointersArray, 0,
I);
10326 DAddr,
P,
M.getDataLayout().getPrefTypeAlign(
Builder.getPtrTy()));
10331void OpenMPIRBuilder::emitUDMapperArrayInitOrDel(
10335 StringRef Prefix = IsInit ?
".init" :
".del";
10341 Builder.CreateICmpSGT(
Size, Builder.getInt64(1),
"omp.arrayinit.isarray");
10342 Value *DeleteBit = Builder.CreateAnd(
10345 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10346 OpenMPOffloadMappingFlags::OMP_MAP_DELETE)));
10351 Value *BaseIsBegin = Builder.CreateICmpNE(
Base, Begin);
10352 Cond = Builder.CreateOr(IsArray, BaseIsBegin);
10353 DeleteCond = Builder.CreateIsNull(
10358 DeleteCond =
Builder.CreateIsNotNull(
10374 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10375 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10376 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10377 MapTypeArg =
Builder.CreateOr(
10380 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10381 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT)));
10385 Value *OffloadingArgs[] = {MapperHandle,
Base, Begin,
10386 ArraySize, MapTypeArg, MapName};
10397 bool PreserveMemberOfFlags) {
10413 MapperFn->
addFnAttr(Attribute::NoInline);
10414 MapperFn->
addFnAttr(Attribute::NoUnwind);
10424 auto SavedIP =
Builder.saveIP();
10425 Builder.SetInsertPoint(EntryBB);
10437 TypeSize ElementSize =
M.getDataLayout().getTypeStoreSize(ElemTy);
10439 Value *PtrBegin = BeginIn;
10445 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
10446 MapType, MapName, ElementSize, HeadBB,
10457 Builder.CreateICmpEQ(PtrBegin, PtrEnd,
"omp.arraymap.isempty");
10458 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
10464 Builder.CreatePHI(PtrBegin->
getType(), 2,
"omp.arraymap.ptrcurrent");
10465 PtrPHI->addIncoming(PtrBegin, HeadBB);
10470 return Info.takeError();
10474 Value *OffloadingArgs[] = {MapperHandle};
10478 Value *ShiftedPreviousSize =
10482 for (
unsigned I = 0;
I < Info->BasePointers.size(); ++
I) {
10483 Value *CurBaseArg = Info->BasePointers[
I];
10484 Value *CurBeginArg = Info->Pointers[
I];
10485 Value *CurSizeArg = Info->Sizes[
I];
10486 Value *CurNameArg = Info->Names.size()
10492 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10494 Value *MemberMapType;
10495 if (PreserveMemberOfFlags) {
10497 static_cast<uint64_t>(OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
10499 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10501 bool HasMemberOf = (OrigFlags & MemberOfMask) != 0;
10503 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
10505 MemberMapType = OriMapType;
10507 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
10525 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10526 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10527 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10537 Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
10543 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10544 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10545 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10551 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10552 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
10553 Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
10559 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10560 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10566 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10567 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10568 Builder.CreateCondBr(IsFrom, FromBB, EndBB);
10574 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10575 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
10584 CurMapType->
addIncoming(MemberMapType, ToElseBB);
10586 Value *OffloadingArgs[] = {MapperHandle, CurBaseArg, CurBeginArg,
10587 CurSizeArg, CurMapType, CurNameArg};
10589 auto ChildMapperFn = CustomMapperCB(
I);
10590 if (!ChildMapperFn)
10591 return ChildMapperFn.takeError();
10592 if (*ChildMapperFn) {
10607 Value *PtrNext =
Builder.CreateConstGEP1_32(ElemTy, PtrPHI, 1,
10608 "omp.arraymap.next");
10609 PtrPHI->addIncoming(PtrNext, LastBB);
10610 Value *IsDone =
Builder.CreateICmpEQ(PtrNext, PtrEnd,
"omp.arraymap.isdone");
10612 Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
10617 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
10618 MapType, MapName, ElementSize, DoneBB,
10632 bool IsNonContiguous,
10636 Info.clearArrayInfo();
10639 if (Info.NumberOfPtrs == 0)
10648 Info.RTArgs.BasePointersArray =
Builder.CreateAlloca(
10649 PointerArrayType,
nullptr,
".offload_baseptrs");
10651 Info.RTArgs.PointersArray =
Builder.CreateAlloca(
10652 PointerArrayType,
nullptr,
".offload_ptrs");
10654 PointerArrayType,
nullptr,
".offload_mappers");
10655 Info.RTArgs.MappersArray = MappersArray;
10662 ConstantInt::get(Int64Ty, 0));
10664 for (
unsigned I = 0, E = CombinedInfo.
Sizes.
size();
I < E; ++
I) {
10665 bool IsNonContigEntry =
10667 (
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10669 OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG) != 0);
10672 if (IsNonContigEntry) {
10674 "Index must be in-bounds for NON_CONTIG Dims array");
10676 assert(DimCount > 0 &&
"NON_CONTIG DimCount must be > 0");
10677 ConstSizes[
I] = ConstantInt::get(Int64Ty, DimCount);
10682 ConstSizes[
I] = CI;
10686 RuntimeSizes.
set(
I);
10689 if (RuntimeSizes.
all()) {
10691 Info.RTArgs.SizesArray =
Builder.CreateAlloca(
10692 SizeArrayType,
nullptr,
".offload_sizes");
10698 auto *SizesArrayGbl =
10703 if (!RuntimeSizes.
any()) {
10704 Info.RTArgs.SizesArray = SizesArrayGbl;
10706 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
10707 Align OffloadSizeAlign =
M.getDataLayout().getABIIntegerTypeAlignment(64);
10710 SizeArrayType,
nullptr,
".offload_sizes");
10714 Buffer,
M.getDataLayout().getPrefTypeAlign(Buffer->
getType()),
10715 SizesArrayGbl, OffloadSizeAlign,
10720 Info.RTArgs.SizesArray = Buffer;
10728 for (
auto mapFlag : CombinedInfo.
Types)
10730 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10734 Info.RTArgs.MapTypesArray = MapTypesArrayGbl;
10740 Info.RTArgs.MapNamesArray = MapNamesArrayGbl;
10741 Info.EmitDebug =
true;
10743 Info.RTArgs.MapNamesArray =
10745 Info.EmitDebug =
false;
10750 if (Info.separateBeginEndCalls()) {
10751 bool EndMapTypesDiffer =
false;
10753 if (
Type &
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10754 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT)) {
10755 Type &= ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
10756 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
10757 EndMapTypesDiffer =
true;
10760 if (EndMapTypesDiffer) {
10762 Info.RTArgs.MapTypesArrayEnd = MapTypesArrayGbl;
10767 for (
unsigned I = 0;
I < Info.NumberOfPtrs; ++
I) {
10770 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.BasePointersArray,
10772 Builder.CreateAlignedStore(BPVal, BP,
10773 M.getDataLayout().getPrefTypeAlign(PtrTy));
10775 if (Info.requiresDevicePointerInfo()) {
10777 CodeGenIP =
Builder.saveIP();
10779 Info.DevicePtrInfoMap[BPVal] = {BP,
Builder.CreateAlloca(PtrTy)};
10780 Builder.restoreIP(CodeGenIP);
10782 DeviceAddrCB(
I, Info.DevicePtrInfoMap[BPVal].second);
10784 Info.DevicePtrInfoMap[BPVal] = {BP, BP};
10786 DeviceAddrCB(
I, BP);
10792 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray, 0,
10795 Builder.CreateAlignedStore(PVal,
P,
10796 M.getDataLayout().getPrefTypeAlign(PtrTy));
10798 if (RuntimeSizes.
test(
I)) {
10800 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
10806 S,
M.getDataLayout().getPrefTypeAlign(PtrTy));
10809 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
10812 auto CustomMFunc = CustomMapperCB(
I);
10814 return CustomMFunc.takeError();
10816 MFunc =
Builder.CreatePointerCast(*CustomMFunc, PtrTy);
10819 PointerArrayType, MappersArray,
10822 MFunc, MAddr,
M.getDataLayout().getPrefTypeAlign(MAddr->
getType()));
10826 Info.NumberOfPtrs == 0)
10843 Builder.ClearInsertionPoint();
10874 auto CondConstant = CI->getSExtValue();
10876 return ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
10878 return ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
10888 Builder.CreateCondBr(
Cond, ThenBlock, ElseBlock);
10891 if (
Error Err = ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks))
10897 if (
Error Err = ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks))
10906bool OpenMPIRBuilder::checkAndEmitFlushAfterAtomic(
10910 "Unexpected Atomic Ordering.");
10912 bool Flush =
false;
10974 assert(
X.Var->getType()->isPointerTy() &&
10975 "OMP Atomic expects a pointer to target memory");
10976 Type *XElemTy =
X.ElemTy;
10979 "OMP atomic read expected a scalar type");
10981 Value *XRead =
nullptr;
10985 Builder.CreateLoad(XElemTy,
X.Var,
X.IsVolatile,
"omp.atomic.read");
10994 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
10997 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
10999 XRead = AtomicLoadRes.first;
11006 Builder.CreateLoad(IntCastTy,
X.Var,
X.IsVolatile,
"omp.atomic.load");
11009 XRead =
Builder.CreateBitCast(XLoad, XElemTy,
"atomic.flt.cast");
11011 XRead =
Builder.CreateIntToPtr(XLoad, XElemTy,
"atomic.ptr.cast");
11014 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Read);
11015 Builder.CreateStore(XRead, V.Var, V.IsVolatile);
11026 assert(
X.Var->getType()->isPointerTy() &&
11027 "OMP Atomic expects a pointer to target memory");
11028 Type *XElemTy =
X.ElemTy;
11031 "OMP atomic write expected a scalar type");
11039 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11042 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11050 Builder.CreateBitCast(Expr, IntCastTy,
"atomic.src.int.cast");
11055 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Write);
11062 AtomicUpdateCallbackTy &UpdateOp,
bool IsXBinopExpr,
11063 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11069 Type *XTy =
X.Var->getType();
11071 "OMP Atomic expects a pointer to target memory");
11072 Type *XElemTy =
X.ElemTy;
11075 "OMP atomic update expected a scalar or struct type");
11078 "OpenMP atomic does not support LT or GT operations");
11082 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, RMWOp, UpdateOp,
X.IsVolatile,
11083 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11085 return AtomicResult.takeError();
11086 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Update);
11091Value *OpenMPIRBuilder::emitRMWOpAsInstruction(
Value *Src1,
Value *Src2,
11095 return Builder.CreateAdd(Src1, Src2);
11097 return Builder.CreateSub(Src1, Src2);
11099 return Builder.CreateAnd(Src1, Src2);
11101 return Builder.CreateNeg(Builder.CreateAnd(Src1, Src2));
11103 return Builder.CreateOr(Src1, Src2);
11105 return Builder.CreateXor(Src1, Src2);
11144Expected<std::pair<Value *, Value *>> OpenMPIRBuilder::emitAtomicUpdate(
11147 AtomicUpdateCallbackTy &UpdateOp,
bool VolatileX,
bool IsXBinopExpr,
11148 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11150 bool emitRMWOp =
false;
11158 emitRMWOp = XElemTy;
11161 emitRMWOp = (IsXBinopExpr && XElemTy);
11168 std::pair<Value *, Value *> Res;
11170 AtomicRMWInst *RMWInst =
11171 Builder.CreateAtomicRMW(RMWOp,
X, Expr, llvm::MaybeAlign(), AO);
11172 if (
T.isAMDGPU()) {
11173 if (IsIgnoreDenormalMode)
11174 RMWInst->
setMetadata(
"amdgpu.ignore.denormal.mode",
11176 if (!IsFineGrainedMemory)
11177 RMWInst->
setMetadata(
"amdgpu.no.fine.grained.memory",
11179 if (!IsRemoteMemory)
11183 Res.first = RMWInst;
11188 Res.second = Res.first;
11190 Res.second = emitRMWOpAsInstruction(Res.first, Expr, RMWOp);
11193 Builder.CreateLoad(XElemTy,
X,
X->getName() +
".atomic.load");
11199 OpenMPIRBuilder::AtomicInfo atomicInfo(
11201 OldVal->
getAlign(),
true , AllocaIP,
X);
11202 auto AtomicLoadRes = atomicInfo.EmitAtomicLoadLibcall(AO);
11205 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11212 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11213 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11214 Builder.SetInsertPoint(ContBB);
11216 PHI->addIncoming(AtomicLoadRes.first, CurBB);
11218 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11221 Value *Upd = *CBResult;
11222 Builder.CreateStore(Upd, NewAtomicAddr);
11225 auto Result = atomicInfo.EmitAtomicCompareExchangeLibcall(
11226 AtomicLoadRes.second, NewAtomicAddr, AO, Failure);
11227 LoadInst *PHILoad =
Builder.CreateLoad(XElemTy,
Result.first);
11228 PHI->addIncoming(PHILoad,
Builder.GetInsertBlock());
11231 Res.first = OldExprVal;
11234 if (UnreachableInst *ExitTI =
11237 Builder.SetInsertPoint(ExitBB);
11239 Builder.SetInsertPoint(ExitTI);
11242 IntegerType *IntCastTy =
11245 Builder.CreateLoad(IntCastTy,
X,
X->getName() +
".atomic.load");
11255 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11262 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11263 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11264 Builder.SetInsertPoint(ContBB);
11266 PHI->addIncoming(OldVal, CurBB);
11271 OldExprVal =
Builder.CreateBitCast(
PHI, XElemTy,
11272 X->getName() +
".atomic.fltCast");
11274 OldExprVal =
Builder.CreateIntToPtr(
PHI, XElemTy,
11275 X->getName() +
".atomic.ptrCast");
11279 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11282 Value *Upd = *CBResult;
11283 Builder.CreateStore(Upd, NewAtomicAddr);
11284 LoadInst *DesiredVal =
Builder.CreateLoad(IntCastTy, NewAtomicAddr);
11288 X,
PHI, DesiredVal, llvm::MaybeAlign(), AO, Failure);
11289 Result->setVolatile(VolatileX);
11290 Value *PreviousVal =
Builder.CreateExtractValue(Result, 0);
11291 Value *SuccessFailureVal =
Builder.CreateExtractValue(Result, 1);
11292 PHI->addIncoming(PreviousVal,
Builder.GetInsertBlock());
11293 Builder.CreateCondBr(SuccessFailureVal, ExitBB, ContBB);
11295 Res.first = OldExprVal;
11299 if (UnreachableInst *ExitTI =
11302 Builder.SetInsertPoint(ExitBB);
11304 Builder.SetInsertPoint(ExitTI);
11315 bool UpdateExpr,
bool IsPostfixUpdate,
bool IsXBinopExpr,
11316 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11321 Type *XTy =
X.Var->getType();
11323 "OMP Atomic expects a pointer to target memory");
11324 Type *XElemTy =
X.ElemTy;
11327 "OMP atomic capture expected a scalar or struct type");
11329 "OpenMP atomic does not support LT or GT operations");
11336 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, AtomicOp, UpdateOp,
X.IsVolatile,
11337 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11340 Value *CapturedVal =
11341 (IsPostfixUpdate ? AtomicResult->first : AtomicResult->second);
11342 Builder.CreateStore(CapturedVal, V.Var, V.IsVolatile);
11344 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Capture);
11352 bool IsFailOnly,
bool IsWeak) {
11356 IsPostfixUpdate, IsFailOnly, Failure, IsWeak);
11368 assert(
X.Var->getType()->isPointerTy() &&
11369 "OMP atomic expects a pointer to target memory");
11372 assert(V.Var->getType()->isPointerTy() &&
"v.var must be of pointer type");
11373 assert(V.ElemTy ==
X.ElemTy &&
"x and v must be of same type");
11376 bool IsInteger = E->getType()->isIntegerTy();
11378 if (
Op == OMPAtomicCompareOp::EQ) {
11381 Value *OldValue =
nullptr;
11382 Value *SuccessOrFail =
nullptr;
11420 X.Var->getName() +
".atomic.load");
11426 Value *EIsNaN =
Builder.CreateFCmpUNO(E, E,
"atomic.e.isnan");
11427 Value *XIsNaN =
Builder.CreateFCmpUNO(XFP, XFP,
"atomic.x.isnan");
11428 Value *EitherNaN =
Builder.CreateOr(EIsNaN, XIsNaN,
"atomic.either.nan");
11433 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11437 M.getContext(),
X.Var->getName() +
".atomic.nan",
F, ExitBB);
11439 M.getContext(),
X.Var->getName() +
".atomic.notnan",
F, ExitBB);
11441 M.getContext(),
X.Var->getName() +
".atomic.zero",
F, ExitBB);
11443 M.getContext(),
X.Var->getName() +
".atomic.normal",
F, ExitBB);
11447 Builder.SetInsertPoint(CurBB);
11448 Builder.CreateCondBr(EitherNaN, NaNBB, NotNaNBB);
11451 Builder.SetInsertPoint(NaNBB);
11455 Builder.SetInsertPoint(NotNaNBB);
11458 X.Var->getName() +
".atomic.xiszero");
11460 "atomic.e.iszero");
11461 Value *BothZero =
Builder.CreateAnd(XIsZero, EIsZero,
"atomic.both.zero");
11462 Builder.CreateCondBr(BothZero, ZeroBB, NormalBB);
11465 Builder.SetInsertPoint(ZeroBB);
11467 X.Var, XCurr, DBCast,
MaybeAlign(), AO, Failure);
11469 Value *OldZero =
Builder.CreateExtractValue(ResZero, 0);
11470 Value *OkZero =
Builder.CreateExtractValue(ResZero, 1);
11474 Builder.SetInsertPoint(NormalBB);
11476 X.Var, EBCast, DBCast,
MaybeAlign(), AO, Failure);
11478 Value *OldNormal =
Builder.CreateExtractValue(ResNormal, 0);
11479 Value *OkNormal =
Builder.CreateExtractValue(ResNormal, 1);
11485 Builder.CreatePHI(IntCastTy, 3,
X.Var->getName() +
".atomic.old");
11490 X.Var->getName() +
".atomic.ok");
11497 Builder.SetInsertPoint(ExitBB);
11502 OldValue =
Builder.CreateBitCast(OldIntPHI,
X.ElemTy,
11503 X.Var->getName() +
".atomic.old.fp");
11504 SuccessOrFail = SuccessPHI;
11512 Result =
Builder.CreateAtomicCmpXchg(
X.Var, EBCast, DBCast,
11518 Result->setWeak(IsWeak);
11521 OldValue =
Builder.CreateExtractValue(Result, 0);
11523 OldValue =
Builder.CreateBitCast(OldValue,
X.ElemTy);
11525 "OldValue and V must be of same type");
11526 if (IsPostfixUpdate) {
11527 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
11529 SuccessOrFail =
Builder.CreateExtractValue(Result, 1);
11533 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11535 CurBBTI,
X.Var->getName() +
".atomic.exit");
11541 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
11543 Builder.SetInsertPoint(ContBB);
11544 Builder.CreateStore(OldValue, V.Var);
11550 Builder.SetInsertPoint(ExitBB);
11552 Builder.SetInsertPoint(ExitTI);
11555 Value *CapturedValue =
11556 Builder.CreateSelect(SuccessOrFail, E, OldValue);
11557 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
11563 assert(R.Var->getType()->isPointerTy() &&
11564 "r.var must be of pointer type");
11565 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
11567 Value *SuccessFailureVal =
11568 Builder.CreateExtractValue(Result, 1);
11569 Value *ResultCast =
11570 R.IsSigned ?
Builder.CreateSExt(SuccessFailureVal, R.ElemTy)
11571 :
Builder.CreateZExt(SuccessFailureVal, R.ElemTy);
11572 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
11581 "OldValue and V must be of same type");
11582 if (IsPostfixUpdate) {
11583 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
11588 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11590 CurBBTI,
X.Var->getName() +
".atomic.exit");
11596 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
11598 Builder.SetInsertPoint(ContBB);
11599 Builder.CreateStore(OldValue, V.Var);
11605 Builder.SetInsertPoint(ExitBB);
11607 Builder.SetInsertPoint(ExitTI);
11610 Value *CapturedValue =
11611 Builder.CreateSelect(SuccessOrFail, E, OldValue);
11612 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
11618 assert(R.Var->getType()->isPointerTy() &&
11619 "r.var must be of pointer type");
11620 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
11622 Value *ResultCast = R.IsSigned
11623 ?
Builder.CreateSExt(SuccessOrFail, R.ElemTy)
11624 :
Builder.CreateZExt(SuccessOrFail, R.ElemTy);
11625 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
11629 assert((
Op == OMPAtomicCompareOp::MAX ||
Op == OMPAtomicCompareOp::MIN) &&
11630 "Op should be either max or min at this point");
11631 assert(!IsFailOnly &&
"IsFailOnly is only valid when the comparison is ==");
11642 if (IsXBinopExpr) {
11671 Value *CapturedValue =
nullptr;
11672 if (IsPostfixUpdate) {
11673 CapturedValue = OldValue;
11698 Value *NonAtomicCmp =
Builder.CreateCmp(Pred, OldValue, E);
11699 CapturedValue =
Builder.CreateSelect(NonAtomicCmp, E, OldValue);
11701 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
11705 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Compare);
11725 if (&OuterAllocaBB ==
Builder.GetInsertBlock()) {
11752 bool SubClausesPresent =
11753 (NumTeamsLower || NumTeamsUpper || ThreadLimit || IfExpr);
11755 if (!
Config.isTargetDevice() && SubClausesPresent) {
11756 assert((NumTeamsLower ==
nullptr || NumTeamsUpper !=
nullptr) &&
11757 "if lowerbound is non-null, then upperbound must also be non-null "
11758 "for bounds on num_teams");
11760 if (NumTeamsUpper ==
nullptr)
11761 NumTeamsUpper =
Builder.getInt32(0);
11763 if (NumTeamsLower ==
nullptr)
11764 NumTeamsLower = NumTeamsUpper;
11768 "argument to if clause must be an integer value");
11772 IfExpr =
Builder.CreateICmpNE(IfExpr,
11773 ConstantInt::get(IfExpr->
getType(), 0));
11774 NumTeamsUpper =
Builder.CreateSelect(
11775 IfExpr, NumTeamsUpper,
Builder.getInt32(1),
"numTeamsUpper");
11778 NumTeamsLower =
Builder.CreateSelect(
11779 IfExpr, NumTeamsLower,
Builder.getInt32(1),
"numTeamsLower");
11782 if (ThreadLimit ==
nullptr)
11783 ThreadLimit =
Builder.getInt32(0);
11787 Value *NumTeamsLowerInt32 =
11789 Value *NumTeamsUpperInt32 =
11791 Value *ThreadLimitInt32 =
11798 {Ident, ThreadNum, NumTeamsLowerInt32, NumTeamsUpperInt32,
11799 ThreadLimitInt32});
11804 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
11807 auto OI = std::make_unique<OutlineInfo>();
11808 OI->EntryBB = AllocaBB;
11809 OI->ExitBB = ExitBB;
11810 OI->OuterAllocBB = &OuterAllocaBB;
11816 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"gid",
true));
11818 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"tid",
true));
11820 auto HostPostOutlineCB = [
this, Ident,
11821 ToBeDeleted](
Function &OutlinedFn)
mutable {
11826 "there must be a single user for the outlined function");
11831 "Outlined function must have two or three arguments only");
11833 bool HasShared = OutlinedFn.
arg_size() == 3;
11841 assert(StaleCI &&
"Error while outlining - no CallInst user found for the "
11842 "outlined function.");
11843 Builder.SetInsertPoint(StaleCI);
11850 omp::RuntimeFunction::OMPRTL___kmpc_fork_teams),
11854 I->eraseFromParent();
11857 if (!
Config.isTargetDevice())
11858 OI->PostOutlineCB = HostPostOutlineCB;
11862 Builder.SetInsertPoint(ExitBB);
11875 if (OuterAllocaBB ==
Builder.GetInsertBlock()) {
11890 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
11895 if (
Config.isTargetDevice()) {
11896 auto OI = std::make_unique<OutlineInfo>();
11897 OI->OuterAllocBB = OuterAllocIP.
getBlock();
11898 OI->EntryBB = AllocaBB;
11899 OI->ExitBB = ExitBB;
11900 OI->OuterDeallocBBs.reserve(OuterDeallocBlocks.
size());
11901 copy(OuterDeallocBlocks, OI->OuterDeallocBBs.
end());
11905 Builder.SetInsertPoint(ExitBB);
11912 std::string VarName) {
11921 return MapNamesArrayGlobal;
11926void OpenMPIRBuilder::initializeTypes(
Module &M) {
11930 unsigned ProgramAS = M.getDataLayout().getProgramAddressSpace();
11931#define OMP_TYPE(VarName, InitValue) VarName = InitValue;
11932#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \
11933 VarName##Ty = ArrayType::get(ElemTy, ArraySize); \
11934 VarName##PtrTy = PointerType::get(Ctx, DefaultTargetAS);
11935#define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) \
11936 VarName = FunctionType::get(ReturnType, {__VA_ARGS__}, IsVarArg); \
11937 VarName##Ptr = PointerType::get(Ctx, ProgramAS);
11938#define OMP_STRUCT_TYPE(VarName, StructName, Packed, ...) \
11939 T = StructType::getTypeByName(Ctx, StructName); \
11941 T = StructType::create(Ctx, {__VA_ARGS__}, StructName, Packed); \
11943 VarName##Ptr = PointerType::get(Ctx, DefaultTargetAS);
11944#include "llvm/Frontend/OpenMP/OMPKinds.def"
11955 while (!Worklist.
empty()) {
11959 if (
BlockSet.insert(SuccBB).second)
11964std::unique_ptr<CodeExtractor>
11966 bool ArgsInZeroAddressSpace,
11968 return std::make_unique<CodeExtractor>(
11978 Suffix.
str(), ArgsInZeroAddressSpace);
11981std::unique_ptr<CodeExtractor> DeviceSharedMemOutlineInfo::createCodeExtractor(
11983 return std::make_unique<DeviceSharedMemCodeExtractor>(
11984 OMPBuilder, Blocks,
nullptr,
11992 OuterDeallocBBs.empty()
11995 Suffix.
str(), ArgsInZeroAddressSpace);
12005 Name.empty() ? Addr->
getName() : Name,
Size, Flags, 0);
12017 Fn->
addFnAttr(
"uniform-work-group-size");
12018 Fn->
addFnAttr(Attribute::MustProgress);
12036 auto &&GetMDInt = [
this](
unsigned V) {
12043 NamedMDNode *MD =
M.getOrInsertNamedMetadata(
"omp_offload.info");
12044 auto &&TargetRegionMetadataEmitter =
12045 [&
C, MD, &OrderedEntries, &GetMDInt, &GetMDString](
12060 GetMDInt(E.getKind()), GetMDInt(EntryInfo.DeviceID),
12061 GetMDInt(EntryInfo.FileID), GetMDString(EntryInfo.ParentName),
12062 GetMDInt(EntryInfo.Line), GetMDInt(EntryInfo.Count),
12063 GetMDInt(E.getOrder())};
12066 OrderedEntries[E.getOrder()] = std::make_pair(&E, EntryInfo);
12075 auto &&DeviceGlobalVarMetadataEmitter =
12076 [&
C, &OrderedEntries, &GetMDInt, &GetMDString, MD](
12086 Metadata *
Ops[] = {GetMDInt(E.getKind()), GetMDString(MangledName),
12087 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
12091 OrderedEntries[E.getOrder()] = std::make_pair(&E, varInfo);
12098 DeviceGlobalVarMetadataEmitter);
12100 for (
const auto &E : OrderedEntries) {
12101 assert(E.first &&
"All ordered entries must exist!");
12102 if (
const auto *CE =
12105 if (!CE->getID() || !CE->getAddress()) {
12109 if (!
M.getNamedValue(FnName))
12117 }
else if (
const auto *CE =
dyn_cast<
12126 if (
Config.isTargetDevice() &&
Config.hasRequiresUnifiedSharedMemory())
12128 if (!CE->getAddress()) {
12133 if (CE->getVarSize() == 0)
12137 assert(((
Config.isTargetDevice() && !CE->getAddress()) ||
12138 (!
Config.isTargetDevice() && CE->getAddress())) &&
12139 "Declaret target link address is set.");
12140 if (
Config.isTargetDevice())
12142 if (!CE->getAddress()) {
12149 if (!CE->getAddress()) {
12162 if ((
GV->hasLocalLinkage() ||
GV->hasHiddenVisibility()) &&
12166 OMPTargetGlobalVarEntryIndirectVTable))
12175 Flags, CE->getLinkage(), CE->getVarName());
12178 Flags, CE->getLinkage());
12189 if (
Config.hasRequiresFlags() && !
Config.isTargetDevice())
12195 Config.getRequiresFlags());
12205 OS <<
"_" <<
Count;
12210 unsigned NewCount = getTargetRegionEntryInfoCount(EntryInfo);
12213 EntryInfo.
Line, NewCount);
12221 auto FileIDInfo = CallBack();
12225 FileID =
Status->getUniqueID().getFile();
12229 FileID =
hash_value(std::get<0>(FileIDInfo));
12233 std::get<1>(FileIDInfo));
12239 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12241 !(Remain & 1); Remain = Remain >> 1)
12259 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12261 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12268 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12274 Flags &=
~omp::OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
12275 Flags |= MemberOfFlag;
12281 bool IsDeclaration,
bool IsExternallyVisible,
12283 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12284 std::vector<Triple> TargetTriple,
Type *LlvmPtrTy,
12285 std::function<
Constant *()> GlobalInitializer,
12296 Config.hasRequiresUnifiedSharedMemory())) {
12301 if (!IsExternallyVisible)
12303 OS <<
"_decl_tgt_ref_ptr";
12306 Value *Ptr =
M.getNamedValue(PtrName);
12315 if (!
Config.isTargetDevice()) {
12316 if (GlobalInitializer)
12317 GV->setInitializer(GlobalInitializer());
12323 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12324 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12325 GlobalInitializer, VariableLinkage, LlvmPtrTy,
cast<Constant>(Ptr));
12337 bool IsDeclaration,
bool IsExternallyVisible,
12339 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12340 std::vector<Triple> TargetTriple,
12341 std::function<
Constant *()> GlobalInitializer,
12345 (TargetTriple.empty() && !
Config.isTargetDevice()))
12356 !
Config.hasRequiresUnifiedSharedMemory()) {
12358 VarName = MangledName;
12361 if (!IsDeclaration)
12363 M.getDataLayout().getTypeSizeInBits(LlvmVal->
getValueType()), 8);
12366 Linkage = (VariableLinkage) ? VariableLinkage() : LlvmVal->
getLinkage();
12370 if (
Config.isTargetDevice() &&
12379 if (!
M.getNamedValue(RefName)) {
12383 GvAddrRef->setConstant(
true);
12385 GvAddrRef->setInitializer(Addr);
12386 GeneratedRefs.push_back(GvAddrRef);
12395 if (
Config.isTargetDevice()) {
12396 VarName = (Addr) ? Addr->
getName() :
"";
12400 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12401 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12402 LlvmPtrTy, GlobalInitializer, VariableLinkage);
12403 VarName = (Addr) ? Addr->
getName() :
"";
12405 VarSize =
M.getDataLayout().getPointerSize();
12424 auto &&GetMDInt = [MN](
unsigned Idx) {
12429 auto &&GetMDString = [MN](
unsigned Idx) {
12431 return V->getString();
12434 switch (GetMDInt(0)) {
12438 case OffloadEntriesInfoManager::OffloadEntryInfo::
12439 OffloadingEntryInfoTargetRegion: {
12449 case OffloadEntriesInfoManager::OffloadEntryInfo::
12450 OffloadingEntryInfoDeviceGlobalVar:
12463 if (HostFilePath.
empty())
12467 if (std::error_code Err = Buf.getError()) {
12469 "OpenMPIRBuilder: " +
12477 if (std::error_code Err =
M.getError()) {
12479 (
"error parsing host file inside of OpenMPIRBuilder: " + Err.message())
12493 "expected a valid insertion block for creating an iterator loop");
12503 Builder.getCurrentDebugLocation(),
"omp.it.cont");
12515 T->eraseFromParent();
12524 if (!BodyBr || BodyBr->getSuccessor() != CLI->
getLatch()) {
12526 "iterator bodygen must terminate the canonical body with an "
12527 "unconditional branch to the loop latch",
12551 for (
const auto &
ParamAttr : ParamAttrs) {
12594 return std::string(Out.
str());
12602 unsigned VecRegSize;
12604 ISADataTy ISAData[] = {
12623 for (
char Mask :
Masked) {
12624 for (
const ISADataTy &
Data : ISAData) {
12627 Out <<
"_ZGV" <<
Data.ISA << Mask;
12629 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
12643template <
typename T>
12646 StringRef MangledName,
bool OutputBecomesInput,
12650 Out << Prefix << ISA << LMask << VLEN;
12651 if (OutputBecomesInput)
12653 Out << ParSeq <<
'_' << MangledName;
12662 bool OutputBecomesInput,
12667 OutputBecomesInput, Fn);
12669 OutputBecomesInput, Fn);
12673 OutputBecomesInput, Fn);
12675 OutputBecomesInput, Fn);
12679 OutputBecomesInput, Fn);
12681 OutputBecomesInput, Fn);
12686 OutputBecomesInput, Fn);
12697 char ISA,
unsigned NarrowestDataSize,
bool OutputBecomesInput) {
12698 assert((ISA ==
'n' || ISA ==
's') &&
"Expected ISA either 's' or 'n'.");
12710 OutputBecomesInput, Fn);
12717 OutputBecomesInput, Fn);
12719 OutputBecomesInput, Fn);
12723 OutputBecomesInput, Fn);
12727 OutputBecomesInput, Fn);
12736 OutputBecomesInput, Fn);
12743 MangledName, OutputBecomesInput, Fn);
12745 MangledName, OutputBecomesInput, Fn);
12749 MangledName, OutputBecomesInput, Fn);
12753 MangledName, OutputBecomesInput, Fn);
12763 return OffloadEntriesTargetRegion.empty() &&
12764 OffloadEntriesDeviceGlobalVar.empty();
12767unsigned OffloadEntriesInfoManager::getTargetRegionEntryInfoCount(
12769 auto It = OffloadEntriesTargetRegionCount.find(
12770 getTargetRegionEntryCountKey(EntryInfo));
12771 if (It == OffloadEntriesTargetRegionCount.end())
12776void OffloadEntriesInfoManager::incrementTargetRegionEntryInfoCount(
12778 OffloadEntriesTargetRegionCount[getTargetRegionEntryCountKey(EntryInfo)] =
12779 EntryInfo.
Count + 1;
12785 OffloadEntriesTargetRegion[EntryInfo] =
12788 ++OffloadingEntriesNum;
12794 assert(EntryInfo.
Count == 0 &&
"expected default EntryInfo");
12797 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
12801 if (OMPBuilder->Config.isTargetDevice()) {
12806 auto &Entry = OffloadEntriesTargetRegion[EntryInfo];
12807 Entry.setAddress(Addr);
12809 Entry.setFlags(Flags);
12815 "Target region entry already registered!");
12817 OffloadEntriesTargetRegion[EntryInfo] = Entry;
12818 ++OffloadingEntriesNum;
12820 incrementTargetRegionEntryInfoCount(EntryInfo);
12827 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
12829 auto It = OffloadEntriesTargetRegion.find(EntryInfo);
12830 if (It == OffloadEntriesTargetRegion.end()) {
12834 if (!IgnoreAddressId && (It->second.getAddress() || It->second.getID()))
12842 for (
const auto &It : OffloadEntriesTargetRegion) {
12843 Action(It.first, It.second);
12849 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
12850 ++OffloadingEntriesNum;
12856 if (OMPBuilder->Config.isTargetDevice()) {
12860 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
12862 if (Entry.getVarSize() == 0) {
12863 Entry.setVarSize(VarSize);
12864 Entry.setLinkage(Linkage);
12868 Entry.setVarSize(VarSize);
12869 Entry.setLinkage(Linkage);
12870 Entry.setAddress(Addr);
12873 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
12874 assert(Entry.isValid() && Entry.getFlags() == Flags &&
12875 "Entry not initialized!");
12876 if (Entry.getVarSize() == 0) {
12877 Entry.setVarSize(VarSize);
12878 Entry.setLinkage(Linkage);
12885 OffloadEntriesDeviceGlobalVar.try_emplace(VarName, OffloadingEntriesNum,
12886 Addr, VarSize, Flags, Linkage,
12889 OffloadEntriesDeviceGlobalVar.try_emplace(
12890 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage,
"");
12891 ++OffloadingEntriesNum;
12898 for (
const auto &E : OffloadEntriesDeviceGlobalVar)
12899 Action(E.getKey(), E.getValue());
12906void CanonicalLoopInfo::collectControlBlocks(
12913 BBs.
append({getPreheader(), Header,
Cond, Latch, Exit, getAfter()});
12925void CanonicalLoopInfo::setTripCount(
Value *TripCount) {
12937void CanonicalLoopInfo::mapIndVar(
12947 for (
Use &U : OldIV->
uses()) {
12951 if (
User->getParent() == getCond())
12953 if (
User->getParent() == getLatch())
12959 Value *NewIV = Updater(OldIV);
12962 for (Use *U : ReplacableUses)
12983 "Preheader must terminate with unconditional branch");
12985 "Preheader must jump to header");
12989 "Header must terminate with unconditional branch");
12990 assert(Header->getSingleSuccessor() == Cond &&
12991 "Header must jump to exiting block");
12994 assert(Cond->getSinglePredecessor() == Header &&
12995 "Exiting block only reachable from header");
12998 "Exiting block must terminate with conditional branch");
13000 "Exiting block's first successor jump to the body");
13002 "Exiting block's second successor must exit the loop");
13006 "Body only reachable from exiting block");
13011 "Latch must terminate with unconditional branch");
13012 assert(Latch->getSingleSuccessor() == Header &&
"Latch must jump to header");
13015 assert(Latch->getSinglePredecessor() !=
nullptr);
13020 "Exit block must terminate with unconditional branch");
13021 assert(Exit->getSingleSuccessor() == After &&
13022 "Exit block must jump to after block");
13026 "After block only reachable from exit block");
13030 assert(IndVar &&
"Canonical induction variable not found?");
13032 "Induction variable must be an integer");
13034 "Induction variable must be a PHI in the loop header");
13040 auto *NextIndVar =
cast<PHINode>(IndVar)->getIncomingValue(1);
13048 assert(TripCount &&
"Loop trip count not found?");
13050 "Trip count and induction variable must have the same type");
13054 "Exit condition must be a signed less-than comparison");
13056 "Exit condition must compare the induction variable");
13058 "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< 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)
static cl::opt< unsigned > TileSize("fuse-matrix-tile-size", cl::init(4), cl::Hidden, cl::desc("Tile size for matrix instruction fusion using square-shaped tiles."))
uint64_t IntrinsicInst * II
#define OMP_KERNEL_ARG_VERSION
Provides definitions for Target specific Grid Values.
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 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 Expected< Function * > createOutlinedFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, const OpenMPIRBuilder::TargetKernelDefaultAttrs &DefaultAttrs, StringRef FuncName, SmallVectorImpl< Value * > &Inputs, OpenMPIRBuilder::TargetBodyGenCallbackTy &CBFunc, OpenMPIRBuilder::TargetGenArgAccessorsCallbackTy &ArgAccessorFuncCB)
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 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 void emitTargetCall(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, 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 * emitTaskDependencies(OpenMPIRBuilder &OMPBuilder, const SmallVectorImpl< OpenMPIRBuilder::DependData > &Dependencies)
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)
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 wrapper over IRBuilderBase::restoreIP that also restores the current debug location to the la...
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::Optional, 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.
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 * getTruncOrBitCast(Constant *C, Type *Ty)
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 * getSizeOf(Type *Ty)
getSizeOf constant expr - computes the (alloc) size of a type (in address-units, not bits) in a targe...
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 LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
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.
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
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.
InsertPoint - A saved insertion point.
BasicBlock * getBlock() const
bool isSet() const
Returns true if this insert point is set.
BasicBlock::iterator getPoint() const
Common base class shared among various IRBuilders.
InsertPoint saveIP() const
Returns the current insert 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 const DebugLoc & getStableDebugLoc() const
Fetch the debug location for this node, unless this is a debug intrinsic, in which case fetch the deb...
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 const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
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.
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.
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 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 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 CanonicalLoopInfo * createLoopSkeleton(DebugLoc DL, Value *TripCount, Function *F, BasicBlock *PreInsertBefore, BasicBlock *PostInsertBefore, const Twine &Name={})
Create the control flow structure of a canonical OpenMP loop.
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 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)
Generator for 'omp target'.
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.
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
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)
Emit the user-defined mapper function.
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)
Generator for #omp taskloop
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)
The omp target interface.
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.
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 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)
Modifies the canonical loop to be a workshare loop.
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 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 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.
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 void createTaskwait(const LocationDescription &Loc, DependenciesInfo Dependencies={})
Generator for 'omp taskwait'.
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...
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(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type 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).
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.
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.
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
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.
user_iterator user_begin()
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.
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.
StringRef str() const
Return a StringRef for the vector contents.
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ 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.
@ C
The default llvm calling convention, compatible with C.
@ 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 <.
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)
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,...
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.
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 StrictBlocksAndThreads
True if the kernel strictly requires the number of blocks and threads above to run.
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 * MaxThreads
'parallel' construct 'num_threads' clause value, if present and it is an SPMD kernel.
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
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),...