69#define DEBUG_TYPE "openmp-ir-builder"
76 cl::desc(
"Use optimistic attributes describing "
77 "'as-if' properties of runtime calls."),
81 "openmp-ir-builder-unroll-threshold-factor",
cl::Hidden,
82 cl::desc(
"Factor for the unroll threshold to account for code "
83 "simplifications still taking place"),
87 "openmp-ir-builder-use-default-max-threads",
cl::Hidden,
98 if (!IP1.isSet() || !IP2.isSet())
100 return IP1.getBlock() == IP2.getBlock() && IP1.getPoint() == IP2.getPoint();
105 switch (SchedType & ~OMPScheduleType::MonotonicityMask) {
106 case OMPScheduleType::UnorderedStaticChunked:
107 case OMPScheduleType::UnorderedStatic:
108 case OMPScheduleType::UnorderedDynamicChunked:
109 case OMPScheduleType::UnorderedGuidedChunked:
110 case OMPScheduleType::UnorderedRuntime:
111 case OMPScheduleType::UnorderedAuto:
112 case OMPScheduleType::UnorderedTrapezoidal:
113 case OMPScheduleType::UnorderedGreedy:
114 case OMPScheduleType::UnorderedBalanced:
115 case OMPScheduleType::UnorderedGuidedIterativeChunked:
116 case OMPScheduleType::UnorderedGuidedAnalyticalChunked:
117 case OMPScheduleType::UnorderedSteal:
118 case OMPScheduleType::UnorderedStaticBalancedChunked:
119 case OMPScheduleType::UnorderedGuidedSimd:
120 case OMPScheduleType::UnorderedRuntimeSimd:
121 case OMPScheduleType::OrderedStaticChunked:
122 case OMPScheduleType::OrderedStatic:
123 case OMPScheduleType::OrderedDynamicChunked:
124 case OMPScheduleType::OrderedGuidedChunked:
125 case OMPScheduleType::OrderedRuntime:
126 case OMPScheduleType::OrderedAuto:
127 case OMPScheduleType::OrderdTrapezoidal:
128 case OMPScheduleType::NomergeUnorderedStaticChunked:
129 case OMPScheduleType::NomergeUnorderedStatic:
130 case OMPScheduleType::NomergeUnorderedDynamicChunked:
131 case OMPScheduleType::NomergeUnorderedGuidedChunked:
132 case OMPScheduleType::NomergeUnorderedRuntime:
133 case OMPScheduleType::NomergeUnorderedAuto:
134 case OMPScheduleType::NomergeUnorderedTrapezoidal:
135 case OMPScheduleType::NomergeUnorderedGreedy:
136 case OMPScheduleType::NomergeUnorderedBalanced:
137 case OMPScheduleType::NomergeUnorderedGuidedIterativeChunked:
138 case OMPScheduleType::NomergeUnorderedGuidedAnalyticalChunked:
139 case OMPScheduleType::NomergeUnorderedSteal:
140 case OMPScheduleType::NomergeOrderedStaticChunked:
141 case OMPScheduleType::NomergeOrderedStatic:
142 case OMPScheduleType::NomergeOrderedDynamicChunked:
143 case OMPScheduleType::NomergeOrderedGuidedChunked:
144 case OMPScheduleType::NomergeOrderedRuntime:
145 case OMPScheduleType::NomergeOrderedAuto:
146 case OMPScheduleType::NomergeOrderedTrapezoidal:
147 case OMPScheduleType::OrderedDistributeChunked:
148 case OMPScheduleType::OrderedDistribute:
156 SchedType & OMPScheduleType::MonotonicityMask;
157 if (MonotonicityFlags == OMPScheduleType::MonotonicityMask)
171 Builder.restoreIP(IP);
175 if (Builder.GetInsertPoint() != BB->
end())
185 unsigned Line = FSP->getScopeLine() ? FSP->getScopeLine() : FSP->getLine();
186 Builder.SetCurrentDebugLocation(
192 return T.isAMDGPU() ||
T.isNVPTX() ||
T.isSPIRV();
198 Kernel->getFnAttribute(
"target-features").getValueAsString();
199 if (Features.
count(
"+wavefrontsize64"))
214 bool HasSimdModifier,
bool HasDistScheduleChunks) {
216 switch (ClauseKind) {
217 case OMP_SCHEDULE_Default:
218 case OMP_SCHEDULE_Static:
219 return HasChunks ? OMPScheduleType::BaseStaticChunked
220 : OMPScheduleType::BaseStatic;
221 case OMP_SCHEDULE_Dynamic:
222 return OMPScheduleType::BaseDynamicChunked;
223 case OMP_SCHEDULE_Guided:
224 return HasSimdModifier ? OMPScheduleType::BaseGuidedSimd
225 : OMPScheduleType::BaseGuidedChunked;
226 case OMP_SCHEDULE_Auto:
228 case OMP_SCHEDULE_Runtime:
229 return HasSimdModifier ? OMPScheduleType::BaseRuntimeSimd
230 : OMPScheduleType::BaseRuntime;
231 case OMP_SCHEDULE_Distribute:
232 return HasDistScheduleChunks ? OMPScheduleType::BaseDistributeChunked
233 : OMPScheduleType::BaseDistribute;
241 bool HasOrderedClause) {
242 assert((BaseScheduleType & OMPScheduleType::ModifierMask) ==
243 OMPScheduleType::None &&
244 "Must not have ordering nor monotonicity flags already set");
247 ? OMPScheduleType::ModifierOrdered
248 : OMPScheduleType::ModifierUnordered;
252 if (OrderingScheduleType ==
253 (OMPScheduleType::BaseGuidedSimd | OMPScheduleType::ModifierOrdered))
254 return OMPScheduleType::OrderedGuidedChunked;
255 else if (OrderingScheduleType == (OMPScheduleType::BaseRuntimeSimd |
256 OMPScheduleType::ModifierOrdered))
257 return OMPScheduleType::OrderedRuntime;
259 return OrderingScheduleType;
265 bool HasSimdModifier,
bool HasMonotonic,
266 bool HasNonmonotonic,
bool HasOrderedClause) {
267 assert((ScheduleType & OMPScheduleType::MonotonicityMask) ==
268 OMPScheduleType::None &&
269 "Must not have monotonicity flags already set");
270 assert((!HasMonotonic || !HasNonmonotonic) &&
271 "Monotonic and Nonmonotonic are contradicting each other");
274 return ScheduleType | OMPScheduleType::ModifierMonotonic;
275 }
else if (HasNonmonotonic) {
276 return ScheduleType | OMPScheduleType::ModifierNonmonotonic;
286 if ((BaseScheduleType == OMPScheduleType::BaseStatic) ||
287 (BaseScheduleType == OMPScheduleType::BaseStaticChunked) ||
293 return ScheduleType | OMPScheduleType::ModifierNonmonotonic;
301 bool HasSimdModifier,
bool HasMonotonicModifier,
302 bool HasNonmonotonicModifier,
bool HasOrderedClause,
303 bool HasDistScheduleChunks) {
305 ClauseKind, HasChunks, HasSimdModifier, HasDistScheduleChunks);
309 OrderedSchedule, HasSimdModifier, HasMonotonicModifier,
310 HasNonmonotonicModifier, HasOrderedClause);
318static std::optional<omp::OMPTgtExecModeFlags>
323 if (
Call->getCalledFunction()->getName() ==
"__kmpc_target_init") {
324 TargetInitCall =
Call;
349 std::optional<omp::OMPTgtExecModeFlags> ExecMode =
361 if (
Instruction *Term = Source->getTerminatorOrNull()) {
370 NewBr->setDebugLoc(
DL);
375 assert(New->getFirstInsertionPt() == New->begin() &&
376 "Target BB must not have PHI nodes");
392 New->splice(New->begin(), Old, IP.
getPoint(), Old->
end());
396 NewBr->setDebugLoc(
DL);
408 Builder.SetInsertPoint(Old);
412 Builder.SetCurrentDebugLocation(
DebugLoc);
422 New->replaceSuccessorsPhiUsesWith(Old, New);
431 Builder.SetInsertPoint(Builder.GetInsertBlock()->getTerminator());
433 Builder.SetInsertPoint(Builder.GetInsertBlock());
436 Builder.SetCurrentDebugLocation(
DebugLoc);
445 Builder.SetInsertPoint(Builder.GetInsertBlock()->getTerminator());
447 Builder.SetInsertPoint(Builder.GetInsertBlock());
450 Builder.SetCurrentDebugLocation(
DebugLoc);
467 const Twine &Name =
"",
bool AsPtr =
true,
468 bool Is64Bit =
false) {
469 Builder.restoreIP(OuterAllocaIP);
473 Builder.CreateAlloca(IntTy,
nullptr, Name +
".addr");
477 FakeVal = FakeValAddr;
479 FakeVal = Builder.CreateLoad(IntTy, FakeValAddr, Name +
".val");
484 Builder.restoreIP(InnerAllocaIP);
487 UseFakeVal = Builder.CreateLoad(IntTy, FakeVal, Name +
".use");
490 FakeVal, Is64Bit ? Builder.getInt64(10) : Builder.getInt32(10)));
503enum OpenMPOffloadingRequiresDirFlags {
505 OMP_REQ_UNDEFINED = 0x000,
507 OMP_REQ_NONE = 0x001,
509 OMP_REQ_REVERSE_OFFLOAD = 0x002,
511 OMP_REQ_UNIFIED_ADDRESS = 0x004,
513 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008,
515 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010,
522 DominatorTree *DT =
nullptr,
bool AggregateArgs =
false,
523 BlockFrequencyInfo *BFI =
nullptr,
524 BranchProbabilityInfo *BPI =
nullptr,
525 AssumptionCache *AC =
nullptr,
bool AllowVarArgs =
false,
526 bool AllowAlloca =
false,
527 BasicBlock *AllocationBlock =
nullptr,
529 std::string Suffix =
"",
bool ArgsInZeroAddressSpace =
false)
530 : CodeExtractor(BBs, DT, AggregateArgs, BFI, BPI, AC, AllowVarArgs,
531 AllowAlloca, AllocationBlock, DeallocationBlocks, Suffix,
532 ArgsInZeroAddressSpace),
533 OMPBuilder(OMPBuilder) {}
535 virtual ~OMPCodeExtractor() =
default;
538 OpenMPIRBuilder &OMPBuilder;
541class DeviceSharedMemCodeExtractor :
public OMPCodeExtractor {
543 using OMPCodeExtractor::OMPCodeExtractor;
544 virtual ~DeviceSharedMemCodeExtractor() =
default;
548 allocateVar(IRBuilder<>::InsertPoint AllocaIP,
Type *VarType,
549 const Twine &Name = Twine(
""),
550 AddrSpaceCastInst **CastedAlloc =
nullptr)
override {
551 return OMPBuilder.createOMPAllocShared(AllocaIP, VarType, Name);
554 virtual Instruction *deallocateVar(IRBuilder<>::InsertPoint DeallocIP,
556 return OMPBuilder.createOMPFreeShared(DeallocIP, Var, VarType);
563 OpenMPIRBuilder &OMPBuilder;
565 DeviceSharedMemOutlineInfo(OpenMPIRBuilder &OMPBuilder)
566 : OMPBuilder(OMPBuilder) {}
567 virtual ~DeviceSharedMemOutlineInfo() =
default;
569 virtual std::unique_ptr<CodeExtractor>
571 bool ArgsInZeroAddressSpace,
572 Twine Suffix = Twine(
""))
override;
578 : RequiresFlags(OMP_REQ_UNDEFINED) {}
582 bool HasRequiresReverseOffload,
bool HasRequiresUnifiedAddress,
583 bool HasRequiresUnifiedSharedMemory,
bool HasRequiresDynamicAllocators)
586 RequiresFlags(OMP_REQ_UNDEFINED) {
587 if (HasRequiresReverseOffload)
588 RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
589 if (HasRequiresUnifiedAddress)
590 RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
591 if (HasRequiresUnifiedSharedMemory)
592 RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
593 if (HasRequiresDynamicAllocators)
594 RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
598 return RequiresFlags & OMP_REQ_REVERSE_OFFLOAD;
602 return RequiresFlags & OMP_REQ_UNIFIED_ADDRESS;
606 return RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY;
610 return RequiresFlags & OMP_REQ_DYNAMIC_ALLOCATORS;
615 :
static_cast<int64_t
>(OMP_REQ_NONE);
620 RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
622 RequiresFlags &= ~OMP_REQ_REVERSE_OFFLOAD;
627 RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
629 RequiresFlags &= ~OMP_REQ_UNIFIED_ADDRESS;
634 RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
636 RequiresFlags &= ~OMP_REQ_UNIFIED_SHARED_MEMORY;
641 RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
643 RequiresFlags &= ~OMP_REQ_DYNAMIC_ALLOCATORS;
656 constexpr size_t MaxDim = 3;
661 Value *DynCGroupMemFallbackFlag =
663 DynCGroupMemFallbackFlag =
Builder.CreateShl(DynCGroupMemFallbackFlag, 2);
668 StrictBlocksFlag =
Builder.CreateShl(StrictBlocksFlag, 6);
669 StrictThreadsFlag =
Builder.CreateShl(StrictThreadsFlag, 7);
671 Value *Flags =
Builder.CreateOr(HasNoWaitFlag, DynCGroupMemFallbackFlag);
672 Flags =
Builder.CreateOr(Flags, StrictBlocksFlag);
673 Flags =
Builder.CreateOr(Flags, StrictThreadsFlag);
679 Value *NumThreads3D =
710 auto FnAttrs = Attrs.getFnAttrs();
711 auto RetAttrs = Attrs.getRetAttrs();
713 for (
size_t ArgNo = 0; ArgNo < Fn.
arg_size(); ++ArgNo)
718 bool Param =
true) ->
void {
719 bool HasSignExt = AS.hasAttribute(Attribute::SExt);
720 bool HasZeroExt = AS.hasAttribute(Attribute::ZExt);
721 if (HasSignExt || HasZeroExt) {
722 assert(AS.getNumAttributes() == 1 &&
723 "Currently not handling extension attr combined with others.");
725 if (
auto AK = TargetLibraryInfo::getExtAttrForI32Param(
T, HasSignExt))
728 TargetLibraryInfo::getExtAttrForI32Return(
T, HasSignExt))
735#define OMP_ATTRS_SET(VarName, AttrSet) AttributeSet VarName = AttrSet;
736#include "llvm/Frontend/OpenMP/OMPKinds.def"
740#define OMP_RTL_ATTRS(Enum, FnAttrSet, RetAttrSet, ArgAttrSets) \
742 FnAttrs = FnAttrs.addAttributes(Ctx, FnAttrSet); \
743 addAttrSet(RetAttrs, RetAttrSet, false); \
744 for (size_t ArgNo = 0; ArgNo < ArgAttrSets.size(); ++ArgNo) \
745 addAttrSet(ArgAttrs[ArgNo], ArgAttrSets[ArgNo]); \
746 Fn.setAttributes(AttributeList::get(Ctx, FnAttrs, RetAttrs, ArgAttrs)); \
748#include "llvm/Frontend/OpenMP/OMPKinds.def"
762#define OMP_RTL(Enum, Str, IsVarArg, ReturnType, ...) \
764 FnTy = FunctionType::get(ReturnType, ArrayRef<Type *>{__VA_ARGS__}, \
766 Fn = M.getFunction(Str); \
768#include "llvm/Frontend/OpenMP/OMPKinds.def"
774#define OMP_RTL(Enum, Str, ...) \
776 Fn = Function::Create(FnTy, GlobalValue::ExternalLinkage, Str, M); \
778#include "llvm/Frontend/OpenMP/OMPKinds.def"
782 if (FnID == OMPRTL___kmpc_fork_call || FnID == OMPRTL___kmpc_fork_teams) {
792 LLVMContext::MD_callback,
794 2, {-1, -1},
true)}));
807 assert(Fn &&
"Failed to create OpenMP runtime function");
818 Builder.SetInsertPoint(FiniBB);
830 FiniBB = OtherFiniBB;
832 Builder.SetInsertPoint(FiniBB->getFirstNonPHIIt());
840 auto EndIt = FiniBB->end();
841 if (FiniBB->size() >= 1)
842 if (
auto Prev = std::prev(EndIt); Prev->isTerminator())
847 FiniBB->replaceAllUsesWith(OtherFiniBB);
848 FiniBB->eraseFromParent();
849 FiniBB = OtherFiniBB;
856 assert(Fn &&
"Failed to create OpenMP runtime function pointer");
879 for (
auto Inst =
Block->getReverseIterator()->begin();
880 Inst !=
Block->getReverseIterator()->end();) {
909 Block.getParent()->getEntryBlock().getTerminator()->getIterator();
930 DeferredOutlines.
push_back(std::move(OI));
934 ParallelRegionBlockSet.
clear();
936 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
946 bool ArgsInZeroAddressSpace =
Config.isTargetDevice();
947 std::unique_ptr<CodeExtractor> Extractor =
948 OI->createCodeExtractor(Blocks, ArgsInZeroAddressSpace,
".omp_par");
952 <<
" Exit: " << OI->ExitBB->getName() <<
"\n");
953 assert(Extractor->isEligible() &&
954 "Expected OpenMP outlining to be possible!");
956 for (
auto *V : OI->ExcludeArgsFromAggregate)
957 Extractor->excludeArgFromAggregate(V);
960 Extractor->extractCodeRegion(CEAC, OI->Inputs, OI->Outputs);
964 if (TargetCpuAttr.isStringAttribute())
967 auto TargetFeaturesAttr = OuterFn->
getFnAttribute(
"target-features");
968 if (TargetFeaturesAttr.isStringAttribute())
969 OutlinedFn->
addFnAttr(TargetFeaturesAttr);
972 LLVM_DEBUG(
dbgs() <<
" Outlined function: " << *OutlinedFn <<
"\n");
974 "OpenMP outlined functions should not return a value!");
979 M.getFunctionList().insertAfter(OuterFn->
getIterator(), OutlinedFn);
986 assert(OI->EntryBB->getUniquePredecessor() == &ArtificialEntry);
993 "Expected instructions to add in the outlined region entry");
995 End = ArtificialEntry.
rend();
1000 if (
I.isTerminator()) {
1002 if (
Instruction *TI = OI->EntryBB->getTerminatorOrNull())
1003 TI->adoptDbgRecords(&ArtificialEntry,
I.getIterator(),
false);
1007 I.moveBeforePreserving(*OI->EntryBB,
1008 OI->EntryBB->getFirstInsertionPt());
1011 OI->EntryBB->moveBefore(&ArtificialEntry);
1018 if (OI->PostOutlineCB)
1019 OI->PostOutlineCB(*OutlinedFn);
1021 if (OI->FixUpNonEntryAllocas)
1053 errs() <<
"Error of kind: " << Kind
1054 <<
" when emitting offload entries and metadata during "
1055 "OMPIRBuilder finalization \n";
1063 if (
Config.isTargetDevice())
1064 applyDeclareTargetGlobalReplacements();
1066 if (
Config.EmitLLVMUsedMetaInfo.value_or(
false)) {
1067 std::vector<WeakTrackingVH> LLVMCompilerUsed = {
1068 M.getGlobalVariable(
"__openmp_nvptx_data_transfer_temporary_storage")};
1069 emitUsed(
"llvm.compiler.used", LLVMCompilerUsed);
1079 assert(Original && Replacement &&
1080 "Null values provided to registerDeclareTargetGlobalReplacement");
1084void OpenMPIRBuilder::applyDeclareTargetGlobalReplacements() {
1090 "A null value was inserted into DeclareTargetGlobalReplacements");
1094 if (!OldGV || !NewGV)
1128 for (
unsigned I = 0, E =
PHI->getNumIncomingValues();
I < E; ++
I) {
1129 if (
PHI->getIncomingValue(
I) != OldGV)
1134 Builder.SetCurrentDebugLocation(
PHI->getDebugLoc());
1136 PHI->setIncomingValue(
I, EdgeLoad);
1142 Builder.SetCurrentDebugLocation(Insn->getDebugLoc());
1158 "Non-default address space declare target global");
1160 unsigned DestAS = ASC->getType()->getPointerAddressSpace();
1161 if (DestAS == 0 && NewGVAS != OldGVAS) {
1162 ASC->replaceAllUsesWith(
Load);
1163 ASC->eraseFromParent();
1168 Insn->replaceUsesOfWith(OldGV,
Load);
1184 ConstantInt::get(I32Ty,
Value), Name);
1197 for (
unsigned I = 0, E =
List.size();
I != E; ++
I)
1201 if (UsedArray.
empty())
1208 GV->setSection(
"llvm.metadata");
1214 auto *Int8Ty =
Builder.getInt8Ty();
1217 ConstantInt::get(Int8Ty, Mode),
Twine(KernelName,
"_exec_mode"));
1225 unsigned Reserve2Flags) {
1227 LocFlags |= OMP_IDENT_FLAG_KMPC;
1234 ConstantInt::get(Int32,
uint32_t(LocFlags)),
1235 ConstantInt::get(Int32, Reserve2Flags),
1236 ConstantInt::get(Int32, SrcLocStrSize), SrcLocStr};
1238 size_t SrcLocStrArgIdx = 4;
1239 if (OpenMPIRBuilder::Ident->getElementType(SrcLocStrArgIdx)
1243 SrcLocStr, OpenMPIRBuilder::Ident->getElementType(SrcLocStrArgIdx));
1250 if (
GV.getValueType() == OpenMPIRBuilder::Ident &&
GV.hasInitializer())
1251 if (
GV.getInitializer() == Initializer)
1256 M, OpenMPIRBuilder::Ident,
1259 M.getDataLayout().getDefaultGlobalsAddressSpace());
1271 SrcLocStrSize = LocStr.
size();
1280 if (
GV.isConstant() &&
GV.hasInitializer() &&
1281 GV.getInitializer() == Initializer)
1284 SrcLocStr =
Builder.CreateGlobalString(
1285 LocStr,
"",
M.getDataLayout().getDefaultGlobalsAddressSpace(),
1293 unsigned Line,
unsigned Column,
1299 Buffer.
append(FunctionName);
1301 Buffer.
append(std::to_string(Line));
1303 Buffer.
append(std::to_string(Column));
1311 StringRef UnknownLoc =
";unknown;unknown;0;0;;";
1322 !DIL->getFilename().empty() ? DIL->getFilename() :
M.getName();
1327 DIL->getColumn(), SrcLocStrSize);
1333 Loc.IP.getBlock()->getParent());
1339 "omp_global_thread_num");
1347 "expected one result pointer type per in_reduction item");
1350 if (OrigPtrs.
empty())
1351 return Builder.saveIP();
1370 for (
unsigned Idx = 0; Idx < OrigPtrs.
size(); ++Idx) {
1373 Value *OrigPtr = OrigPtrs[Idx];
1375 OrigPtrTy && OrigPtrTy->getAddressSpace() != 0)
1376 OrigPtr = Builder.CreateAddrSpaceCast(OrigPtr, PtrTy);
1378 Value *
Priv = Builder.CreateCall(GetThData, {Gtid, NullDesc, OrigPtr},
1384 ResPtrTy && ResPtrTy->getAddressSpace() != 0)
1385 Priv = Builder.CreateAddrSpaceCast(
Priv, ResultPtrTys[Idx]);
1387 MapPrivateCB(Idx,
Priv);
1394 bool ForceSimpleCall,
bool CheckCancelFlag) {
1404 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_FOR;
1407 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SECTIONS;
1410 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SINGLE;
1413 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_EXPL;
1416 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL;
1429 bool UseCancelBarrier =
1434 ? OMPRTL___kmpc_cancel_barrier
1435 : OMPRTL___kmpc_barrier),
1438 if (UseCancelBarrier && CheckCancelFlag)
1448 omp::Directive CanceledDirective) {
1453 auto *UI =
Builder.CreateUnreachable();
1461 Builder.SetInsertPoint(ElseTI);
1462 auto ElseIP =
Builder.saveIP();
1470 Builder.SetInsertPoint(ThenTI);
1472 Value *CancelKind =
nullptr;
1473 switch (CanceledDirective) {
1474#define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) \
1475 case DirectiveEnum: \
1476 CancelKind = Builder.getInt32(Value); \
1478#include "llvm/Frontend/OpenMP/OMPKinds.def"
1495 Builder.SetInsertPoint(UI->getParent());
1496 UI->eraseFromParent();
1503 omp::Directive CanceledDirective) {
1508 auto *UI =
Builder.CreateUnreachable();
1511 Value *CancelKind =
nullptr;
1512 switch (CanceledDirective) {
1513#define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) \
1514 case DirectiveEnum: \
1515 CancelKind = Builder.getInt32(Value); \
1517#include "llvm/Frontend/OpenMP/OMPKinds.def"
1534 Builder.SetInsertPoint(UI->getParent());
1535 UI->eraseFromParent();
1548 auto *KernelArgsPtr =
1549 Builder.CreateAlloca(OpenMPIRBuilder::KernelArgs,
nullptr,
"kernel_args");
1554 Builder.CreateStructGEP(OpenMPIRBuilder::KernelArgs, KernelArgsPtr,
I);
1557 M.getDataLayout().getPrefTypeAlign(KernelArgs[
I]->getType()));
1561 NumThreads, HostPtr, KernelArgsPtr};
1588 assert(OutlinedFnID &&
"Invalid outlined function ID!");
1592 Value *Return =
nullptr;
1612 Builder, AllocaIP, Return, RTLoc, DeviceID, Args.NumTeams.front(),
1613 Args.NumThreads.front(), OutlinedFnID, ArgsVector));
1620 Builder.CreateCondBr(
Failed, OffloadFailedBlock, OffloadContBlock);
1622 auto CurFn =
Builder.GetInsertBlock()->getParent();
1629 emitBlock(OffloadContBlock, CurFn,
true);
1634 Value *CancelFlag, omp::Directive CanceledDirective) {
1636 "Unexpected cancellation!");
1656 Builder.CreateCondBr(Cmp, NonCancellationBlock, CancellationBlock,
1665 Builder.SetInsertPoint(CancellationBlock);
1666 Builder.CreateBr(*FiniBBOrErr);
1669 Builder.SetInsertPoint(NonCancellationBlock, NonCancellationBlock->
begin());
1681 size_t NumArgs = OutlinedFn.
arg_size();
1682 assert((NumArgs == 2 || NumArgs == 3) &&
1683 "expected a 2-3 argument parallel outlined function");
1684 bool UseArgStruct = NumArgs == 3;
1689 {Builder.getInt16Ty(), Builder.getInt32Ty()},
1693 OutlinedFn.
getName() +
".wrapper", OMPIRBuilder->
M);
1695 WrapperFn->addParamAttr(0, Attribute::NoUndef);
1696 WrapperFn->addParamAttr(0, Attribute::ZExt);
1697 WrapperFn->addParamAttr(1, Attribute::NoUndef);
1701 Builder.SetInsertPoint(EntryBB);
1704 Value *AddrAlloca = Builder.CreateAlloca(Builder.getInt32Ty(),
1706 AddrAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1707 AddrAlloca, Builder.getPtrTy(0),
1708 AddrAlloca->
getName() +
".ascast");
1710 Value *ZeroAlloca = Builder.CreateAlloca(Builder.getInt32Ty(),
1712 ZeroAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1713 ZeroAlloca, Builder.getPtrTy(0),
1714 ZeroAlloca->
getName() +
".ascast");
1716 Value *ArgsAlloca =
nullptr;
1718 ArgsAlloca = Builder.CreateAlloca(Builder.getPtrTy(),
1719 nullptr,
"global_args");
1720 ArgsAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1721 ArgsAlloca, Builder.getPtrTy(0),
1722 ArgsAlloca->
getName() +
".ascast");
1726 Builder.CreateStore(WrapperFn->getArg(1), AddrAlloca);
1727 Builder.CreateStore(Builder.getInt32(0), ZeroAlloca);
1731 llvm::omp::RuntimeFunction::OMPRTL___kmpc_get_shared_variables),
1739 Value *StructArg = Builder.CreateLoad(Builder.getPtrTy(), ArgsAlloca);
1740 StructArg = Builder.CreateInBoundsGEP(Builder.getPtrTy(), StructArg,
1741 {Builder.getInt64(0)});
1742 StructArg = Builder.CreateLoad(Builder.getPtrTy(), StructArg,
"structArg");
1743 Args.push_back(StructArg);
1747 Builder.CreateCall(&OutlinedFn, Args);
1748 Builder.CreateRetVoid();
1763 "Expected at least tid and bounded tid as arguments");
1764 unsigned NumCapturedVars = OutlinedFn.
arg_size() - 2;
1772 OutlinedFn.
addFnAttr(Attribute::NoUnwind);
1775 assert(CI &&
"Expected call instruction to outlined function");
1776 CI->
getParent()->setName(
"omp_parallel");
1778 Builder.SetInsertPoint(CI);
1779 Type *PtrTy = OMPIRBuilder->VoidPtr;
1782 OpenMPIRBuilder ::InsertPointTy CurrentIP = Builder.saveIP();
1786 Value *Args = ArgsAlloca;
1790 Args = Builder.CreatePointerCast(ArgsAlloca, PtrTy);
1791 Builder.restoreIP(CurrentIP);
1794 for (
unsigned Idx = 0; Idx < NumCapturedVars; Idx++) {
1796 Value *StoreAddress = Builder.CreateConstInBoundsGEP2_64(
1798 Builder.CreateStore(V, StoreAddress);
1802 IfCondition ? Builder.CreateSExtOrTrunc(IfCondition, OMPIRBuilder->Int32)
1803 : Builder.getInt32(1);
1804 Value *NumThreadsArg =
1805 NumThreads ? Builder.CreateZExtOrTrunc(NumThreads, OMPIRBuilder->Int32)
1806 : Builder.getInt32(-1);
1816 Value *Parallel60CallArgs[] = {
1821 Builder.getInt32(-1),
1825 Builder.getInt64(NumCapturedVars),
1826 Builder.getInt32(0)};
1834 << *Builder.GetInsertBlock()->getParent() <<
"\n");
1837 Builder.SetInsertPoint(PrivTID);
1839 Builder.CreateStore(Builder.CreateLoad(OMPIRBuilder->Int32, OutlinedAI),
1846 I->eraseFromParent();
1869 if (!
F->hasMetadata(LLVMContext::MD_callback)) {
1877 F->addMetadata(LLVMContext::MD_callback,
1886 OutlinedFn.
addFnAttr(Attribute::NoUnwind);
1889 "Expected at least tid and bounded tid as arguments");
1890 unsigned NumCapturedVars = OutlinedFn.
arg_size() - 2;
1893 CI->
getParent()->setName(
"omp_parallel");
1894 Builder.SetInsertPoint(CI);
1897 Value *ForkCallArgs[] = {Ident, Builder.getInt32(NumCapturedVars),
1901 RealArgs.
append(std::begin(ForkCallArgs), std::end(ForkCallArgs));
1903 Value *
Cond = Builder.CreateSExtOrTrunc(IfCondition, OMPIRBuilder->Int32);
1910 auto PtrTy = OMPIRBuilder->VoidPtr;
1911 if (IfCondition && NumCapturedVars == 0) {
1919 << *Builder.GetInsertBlock()->getParent() <<
"\n");
1922 Builder.SetInsertPoint(PrivTID);
1924 Builder.CreateStore(Builder.CreateLoad(OMPIRBuilder->Int32, OutlinedAI),
1931 I->eraseFromParent();
1939 Value *NumThreads, omp::ProcBindKind ProcBind,
bool IsCancellable) {
1948 const bool NeedThreadID = NumThreads ||
Config.isTargetDevice() ||
1949 (ProcBind != OMP_PROC_BIND_default);
1956 bool ArgsInZeroAddressSpace =
Config.isTargetDevice();
1960 if (NumThreads && !
Config.isTargetDevice()) {
1963 Builder.CreateIntCast(NumThreads, Int32,
false)};
1968 if (ProcBind != OMP_PROC_BIND_default) {
1972 ConstantInt::get(Int32,
unsigned(ProcBind),
true)};
1994 Builder.CreateAlloca(Int32,
nullptr,
"zero.addr");
1997 if (ArgsInZeroAddressSpace &&
M.getDataLayout().getAllocaAddrSpace() != 0) {
2000 TIDAddrAlloca, PointerType ::get(
M.getContext(), 0),
"tid.addr.ascast");
2004 PointerType ::get(
M.getContext(), 0),
2005 "zero.addr.ascast");
2029 if (IP.getBlock()->end() == IP.getPoint()) {
2035 assert(IP.getBlock()->getTerminator()->getNumSuccessors() == 1 &&
2036 IP.getBlock()->getTerminator()->getSuccessor(0) == PRegExitBB &&
2037 "Unexpected insertion point for finalization call!");
2049 Builder.CreateAlloca(Int32,
nullptr,
"tid.addr.local");
2055 Builder.CreateLoad(Int32, ZeroAddr,
"zero.addr.use");
2073 LLVM_DEBUG(
dbgs() <<
"Before body codegen: " << *OuterFn <<
"\n");
2076 assert(BodyGenCB &&
"Expected body generation callback!");
2078 if (
Error Err = BodyGenCB(InnerAllocaIP, CodeGenIP, PRegExitBB))
2081 LLVM_DEBUG(
dbgs() <<
"After body codegen: " << *OuterFn <<
"\n");
2085 bool UsesDeviceSharedMemory =
2087 std::unique_ptr<OutlineInfo> OI =
2088 UsesDeviceSharedMemory
2089 ? std::make_unique<DeviceSharedMemOutlineInfo>(*
this)
2090 : std::make_unique<OutlineInfo>();
2092 if (
Config.isTargetDevice()) {
2094 OI->PostOutlineCB = [=, ToBeDeletedVec =
2095 std::move(ToBeDeleted)](
Function &OutlinedFn) {
2097 IfCondition, NumThreads, PrivTID, PrivTIDAddr,
2098 ThreadID, ToBeDeletedVec);
2102 OI->PostOutlineCB = [=, ToBeDeletedVec =
2103 std::move(ToBeDeleted)](
Function &OutlinedFn) {
2105 PrivTID, PrivTIDAddr, ToBeDeletedVec);
2109 OI->FixUpNonEntryAllocas =
true;
2110 OI->OuterAllocBB = OuterAllocaBlock;
2111 OI->EntryBB = PRegEntryBB;
2112 OI->ExitBB = PRegExitBB;
2113 OI->OuterDeallocBBs.reserve(OuterDeallocBlocks.
size());
2114 copy(OuterDeallocBlocks, OI->OuterDeallocBBs.
end());
2118 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
2130 ".omp_par", ArgsInZeroAddressSpace);
2135 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
2137 Extractor.findInputsOutputs(Inputs, Outputs, SinkingCands,
2142 return GV->getValueType() == OpenMPIRBuilder::Ident;
2147 LLVM_DEBUG(
dbgs() <<
"Before privatization: " << *OuterFn <<
"\n");
2153 if (&V == TIDAddr || &V == ZeroAddr) {
2154 OI->ExcludeArgsFromAggregate.push_back(&V);
2159 for (
Use &U : V.uses())
2161 if (ParallelRegionBlockSet.
count(UserI->getParent()))
2171 if (!V.getType()->isPointerTy()) {
2175 Builder.restoreIP(OuterAllocIP);
2177 if (UsesDeviceSharedMemory) {
2180 V.getName() +
".reloaded");
2181 for (
BasicBlock *DeallocBlock : OuterDeallocBlocks)
2183 InsertPointTy(DeallocBlock, DeallocBlock->getFirstInsertionPt()),
2186 Ptr =
Builder.CreateAlloca(V.getType(),
nullptr,
2187 V.getName() +
".reloaded");
2192 Builder.SetInsertPoint(InsertBB,
2197 Builder.restoreIP(InnerAllocaIP);
2198 Inner =
Builder.CreateLoad(V.getType(), Ptr);
2201 Value *ReplacementValue =
nullptr;
2204 ReplacementValue = PrivTID;
2207 PrivCB(InnerAllocaIP,
Builder.saveIP(), V, *Inner, ReplacementValue);
2215 assert(ReplacementValue &&
2216 "Expected copy/create callback to set replacement value!");
2217 if (ReplacementValue == &V)
2222 UPtr->set(ReplacementValue);
2247 for (
Value *Output : Outputs)
2251 "OpenMP outlining should not produce live-out values!");
2253 LLVM_DEBUG(
dbgs() <<
"After privatization: " << *OuterFn <<
"\n");
2255 for (
auto *BB : Blocks)
2256 dbgs() <<
" PBR: " << BB->getName() <<
"\n";
2264 assert(FiniInfo.DK == OMPD_parallel &&
2265 "Unexpected finalization stack state!");
2276 Builder.CreateBr(*FiniBBOrErr);
2280 Term->eraseFromParent();
2286 InsertPointTy AfterIP(UI->getParent(), UI->getParent()->end());
2287 UI->eraseFromParent();
2319 Value *Severity = ConstantInt::get(Int32, IsFatal ? 2 : 1);
2321 Value *Args[] = {Ident, Severity, MessageArg};
2350 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr));
2352 Builder.CreateStore(DepValPtr, Addr);
2355 DependInfo, Entry,
static_cast<unsigned int>(RTLDependInfoFields::Len));
2357 ConstantInt::get(SizeTy,
2362 DependInfo, Entry,
static_cast<unsigned int>(RTLDependInfoFields::Flags));
2364 static_cast<unsigned int>(Dep.
DepKind)),
2377 if (Dependencies.
empty())
2397 Type *DependInfo = OMPBuilder.DependInfo;
2399 Value *DepArray =
nullptr;
2401 Builder.SetInsertPoint(
2405 DepArray = Builder.CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
2407 Builder.restoreIP(OldIP);
2409 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies)) {
2411 Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
2435 Value *DepArray =
nullptr;
2436 Type *DepArrayTy =
nullptr;
2437 Value *NumDeps =
nullptr;
2440 NumDeps = Dependencies.
NumDeps;
2441 }
else if (!Dependencies.
Deps.empty()) {
2444 Builder.GetInsertBlock()->getParent()->getEntryBlock();
2448 DepArray =
Builder.CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
2449 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
2452 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies.
Deps)) {
2454 Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
2468 ConstantInt::get(
Builder.getInt32Ty(), 0),
2470 ConstantInt::get(
Builder.getInt32Ty(),
false)};
2473 omp::RuntimeFunction::OMPRTL___kmpc_omp_taskwait_deps_51),
2483 unsigned ProgramAddressSpace = M.getDataLayout().getProgramAddressSpace();
2495 auto *VoidPtrTy =
PointerType::get(Builder.getContext(), ProgramAddressSpace);
2498 Builder.getVoidTy(), {VoidPtrTy, VoidPtrTy, Builder.getInt32Ty()},
2502 "omp_taskloop_dup", M);
2505 Value *LastprivateFlagArg = DupFunction->
getArg(2);
2506 DestTaskArg->
setName(
"dest_task");
2507 SrcTaskArg->
setName(
"src_task");
2508 LastprivateFlagArg->
setName(
"lastprivate_flag");
2511 Builder.SetInsertPoint(
2514 auto GetTaskContextPtrFromArg = [&](
Value *Arg) ->
Value * {
2515 Type *TaskWithPrivatesTy =
2517 Value *TaskPrivates = Builder.CreateGEP(
2518 TaskWithPrivatesTy, Arg, {Builder.getInt32(0), Builder.getInt32(1)});
2519 Value *ContextPtr = Builder.CreateGEP(
2520 PrivatesTy, TaskPrivates,
2521 {Builder.getInt32(0), Builder.getInt32(PrivatesIndex)});
2525 Value *DestTaskContextPtr = GetTaskContextPtrFromArg(DestTaskArg);
2526 Value *SrcTaskContextPtr = GetTaskContextPtrFromArg(SrcTaskArg);
2528 DestTaskContextPtr->
setName(
"destPtr");
2529 SrcTaskContextPtr->
setName(
"srcPtr");
2534 Expected<IRBuilderBase::InsertPoint> AfterIPOrError =
2535 DupCB(AllocaIP, CodeGenIP, DestTaskContextPtr, SrcTaskContextPtr);
2536 if (!AfterIPOrError)
2538 Builder.restoreIP(*AfterIPOrError);
2548 llvm::function_ref<llvm::Expected<llvm::CanonicalLoopInfo *>()> LoopInfo,
2550 Value *GrainSize,
bool NoGroup,
int Sched,
Value *Final,
bool Mergeable,
2552 Value *TaskContextStructPtrVal) {
2557 uint32_t SrcLocStrSize;
2573 if (
Error Err = BodyGenCB(TaskloopAllocaIP, TaskloopBodyIP, TaskloopExitBB))
2576 llvm::Expected<llvm::CanonicalLoopInfo *> result = LoopInfo();
2581 llvm::CanonicalLoopInfo *CLI = result.
get();
2582 auto OI = std::make_unique<OutlineInfo>();
2583 OI->EntryBB = TaskloopAllocaBB;
2584 OI->OuterAllocBB = AllocaIP.getBlock();
2585 OI->ExitBB = TaskloopExitBB;
2586 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2587 copy(DeallocBlocks, OI->OuterDeallocBBs.end());
2590 SmallVector<Instruction *> ToBeDeleted;
2593 Builder, AllocaIP, ToBeDeleted, TaskloopAllocaIP,
"global.tid",
false));
2595 TaskloopAllocaIP,
"lb",
false,
true);
2597 TaskloopAllocaIP,
"ub",
false,
true);
2599 TaskloopAllocaIP,
"step",
false,
true);
2602 OI->Inputs.insert(FakeLB);
2603 OI->Inputs.insert(FakeUB);
2604 OI->Inputs.insert(FakeStep);
2605 if (TaskContextStructPtrVal)
2606 OI->Inputs.insert(TaskContextStructPtrVal);
2607 assert(((TaskContextStructPtrVal && DupCB) ||
2608 (!TaskContextStructPtrVal && !DupCB)) &&
2609 "Task context struct ptr and duplication callback must be both set "
2615 unsigned ProgramAddressSpace =
M.getDataLayout().getProgramAddressSpace();
2619 {FakeLB->getType(), FakeUB->getType(), FakeStep->getType(), PointerTy});
2620 Expected<Value *> TaskDupFnOrErr = createTaskDuplicationFunction(
2623 if (!TaskDupFnOrErr) {
2626 Value *TaskDupFn = *TaskDupFnOrErr;
2628 OI->PostOutlineCB = [
this, Ident, LBVal, UBVal, StepVal, Untied,
2629 TaskloopAllocaBB, CLI, TaskDupFn, ToBeDeleted, IfCond,
2630 GrainSize, NoGroup, Sched, FakeLB, FakeUB, FakeStep,
2631 FakeSharedsTy, Final, Mergeable, Priority,
2632 NumOfCollapseLoops](
Function &OutlinedFn)
mutable {
2634 assert(OutlinedFn.hasOneUse() &&
2635 "there must be a single user for the outlined function");
2642 Value *CastedLBVal =
2643 Builder.CreateIntCast(LBVal,
Builder.getInt64Ty(),
true,
"lb64");
2644 Value *CastedUBVal =
2645 Builder.CreateIntCast(UBVal,
Builder.getInt64Ty(),
true,
"ub64");
2646 Value *CastedStepVal =
2647 Builder.CreateIntCast(StepVal,
Builder.getInt64Ty(),
true,
"step64");
2649 Builder.SetInsertPoint(StaleCI);
2662 Builder.CreateCall(TaskgroupFn, {Ident, ThreadID});
2683 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
2685 AllocaInst *ArgStructAlloca =
2687 assert(ArgStructAlloca &&
2688 "Unable to find the alloca instruction corresponding to arguments "
2689 "for extracted function");
2690 std::optional<TypeSize> ArgAllocSize =
2693 "Unable to determine size of arguments for extracted function");
2694 Value *SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
2699 CallInst *TaskData =
Builder.CreateCall(
2700 TaskAllocFn, {Ident, ThreadID,
Flags,
2701 TaskSize, SharedsSize,
2706 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
2712 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(0)});
2715 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(1)});
2718 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(2)});
2724 IfCond ?
Builder.CreateIntCast(IfCond,
Builder.getInt32Ty(),
true)
2730 Value *GrainSizeVal =
2731 GrainSize ?
Builder.CreateIntCast(GrainSize,
Builder.getInt64Ty(),
true)
2733 Value *TaskDup = TaskDupFn;
2735 Value *
Args[] = {Ident, ThreadID, TaskData, IfCondVal, Lb, Ub,
2736 Loadstep, NoGroupVal, SchedVal, GrainSizeVal, TaskDup};
2741 Builder.CreateCall(TaskloopFn, Args);
2748 Builder.CreateCall(EndTaskgroupFn, {Ident, ThreadID});
2753 Builder.SetInsertPoint(TaskloopAllocaBB, TaskloopAllocaBB->begin());
2755 LoadInst *SharedsOutlined =
2756 Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
2757 OutlinedFn.getArg(1)->replaceUsesWithIf(
2759 [SharedsOutlined](Use &U) {
return U.getUser() != SharedsOutlined; });
2762 Type *IVTy =
IV->getType();
2768 Value *TaskLB =
nullptr;
2769 Value *TaskUB =
nullptr;
2770 Value *TaskStep =
nullptr;
2771 Value *LoadTaskLB =
nullptr;
2772 Value *LoadTaskUB =
nullptr;
2773 Value *LoadTaskStep =
nullptr;
2774 for (Instruction &
I : *TaskloopAllocaBB) {
2775 if (
I.getOpcode() == Instruction::GetElementPtr) {
2778 switch (CI->getZExtValue()) {
2790 }
else if (
I.getOpcode() == Instruction::Load) {
2792 if (
Load.getPointerOperand() == TaskLB) {
2793 assert(TaskLB !=
nullptr &&
"Expected value for TaskLB");
2795 }
else if (
Load.getPointerOperand() == TaskUB) {
2796 assert(TaskUB !=
nullptr &&
"Expected value for TaskUB");
2798 }
else if (
Load.getPointerOperand() == TaskStep) {
2799 assert(TaskStep !=
nullptr &&
"Expected value for TaskStep");
2805 Builder.SetInsertPoint(CLI->getPreheader()->getTerminator());
2807 assert(LoadTaskLB !=
nullptr &&
"Expected value for LoadTaskLB");
2808 assert(LoadTaskUB !=
nullptr &&
"Expected value for LoadTaskUB");
2809 assert(LoadTaskStep !=
nullptr &&
"Expected value for LoadTaskStep");
2811 Builder.CreateSub(LoadTaskUB, LoadTaskLB), LoadTaskStep);
2812 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One,
"trip_cnt");
2813 Value *CastedTripCount =
Builder.CreateIntCast(TripCount, IVTy,
true);
2814 Value *CastedTaskLB =
Builder.CreateIntCast(LoadTaskLB, IVTy,
true);
2816 CLI->setTripCount(CastedTripCount);
2818 Builder.SetInsertPoint(CLI->getBody(),
2819 CLI->getBody()->getFirstInsertionPt());
2821 if (NumOfCollapseLoops > 1) {
2827 Builder.CreateSub(CastedTaskLB, ConstantInt::get(IVTy, 1)));
2830 for (
auto IVUse = CLI->getIndVar()->uses().begin();
2831 IVUse != CLI->getIndVar()->uses().end(); IVUse++) {
2832 User *IVUser = IVUse->getUser();
2834 if (
Op->getOpcode() == Instruction::URem ||
2835 Op->getOpcode() == Instruction::UDiv) {
2840 for (User *User : UsersToReplace) {
2841 User->replaceUsesOfWith(CLI->getIndVar(), IVPlusTaskLB);
2858 assert(CLI->getIndVar()->getNumUses() == 3 &&
2859 "Canonical loop should have exactly three uses of the ind var");
2860 for (User *IVUser : CLI->getIndVar()->users()) {
2862 if (
Mul->getOpcode() == Instruction::Mul) {
2863 for (User *MulUser :
Mul->users()) {
2865 if (
Add->getOpcode() == Instruction::Add) {
2866 Add->setOperand(1, CastedTaskLB);
2875 FakeLB->replaceAllUsesWith(CastedLBVal);
2876 FakeUB->replaceAllUsesWith(CastedUBVal);
2877 FakeStep->replaceAllUsesWith(CastedStepVal);
2879 I->eraseFromParent();
2884 Builder.SetInsertPoint(TaskloopExitBB, TaskloopExitBB->
begin());
2890 M.getContext(),
M.getDataLayout().getPointerSizeInBits());
2900 bool Mergeable,
Value *EventHandle,
Value *Priority) {
2932 if (
Error Err = BodyGenCB(TaskAllocaIP, TaskBodyIP, TaskExitBB))
2935 auto OI = std::make_unique<OutlineInfo>();
2936 OI->EntryBB = TaskAllocaBB;
2937 OI->OuterAllocBB = AllocaIP.
getBlock();
2938 OI->ExitBB = TaskExitBB;
2939 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2940 copy(DeallocBlocks, OI->OuterDeallocBBs.
end());
2945 Builder, AllocaIP, ToBeDeleted, TaskAllocaIP,
"global.tid",
false));
2947 OI->PostOutlineCB = [
this, Ident, Tied, Final, IfCondition, Dependencies,
2948 Affinities, Mergeable, Priority, EventHandle,
2950 ToBeDeleted](
Function &OutlinedFn)
mutable {
2952 assert(OutlinedFn.hasOneUse() &&
2953 "there must be a single user for the outlined function");
2958 bool HasShareds = StaleCI->
arg_size() > 1;
2959 Builder.SetInsertPoint(StaleCI);
2984 bool UseMergedIf0Path = ConstIfCondition && ConstIfCondition->isZero();
2988 Flags =
Builder.CreateOr(FinalFlag, Flags);
2991 if (Mergeable || UseMergedIf0Path)
3003 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
3012 assert(ArgStructAlloca &&
3013 "Unable to find the alloca instruction corresponding to arguments "
3014 "for extracted function");
3015 std::optional<TypeSize> ArgAllocSize =
3018 "Unable to determine size of arguments for extracted function");
3019 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
3025 TaskAllocFn, {Ident, ThreadID, Flags,
3026 TaskSize, SharedsSize,
3029 if (Affinities.
Count && Affinities.
Info) {
3031 OMPRTL___kmpc_omp_reg_task_with_affinity);
3042 OMPRTL___kmpc_task_allow_completion_event);
3046 Builder.CreatePointerBitCastOrAddrSpaceCast(EventHandle,
3048 EventVal =
Builder.CreatePtrToInt(EventVal,
Builder.getInt64Ty());
3049 Builder.CreateStore(EventVal, EventHandleAddr);
3055 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
3070 Constant *Zero = ConstantInt::get(Int32Ty, 0);
3074 Builder.CreateInBoundsGEP(TaskPtr, TaskData, {Zero, Zero});
3077 VoidPtr, VoidPtr,
Builder.getInt32Ty(), VoidPtr, VoidPtr);
3079 TaskStructType, TaskGEP, {Zero, ConstantInt::get(Int32Ty, 4)});
3082 Value *CmplrData =
Builder.CreateInBoundsGEP(CmplrStructType,
3083 PriorityData, {Zero, Zero});
3084 Builder.CreateStore(Priority, CmplrData);
3087 Value *DepArray =
nullptr;
3088 Value *NumDeps =
nullptr;
3091 NumDeps = Dependencies.
NumDeps;
3092 }
else if (!Dependencies.
Deps.empty()) {
3094 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
3114 if (IfCondition && !UseMergedIf0Path) {
3119 Builder.GetInsertPoint()->getParent()->getTerminator();
3120 Instruction *ThenTI = IfTerminator, *ElseTI =
nullptr;
3121 Builder.SetInsertPoint(IfTerminator);
3124 Builder.SetInsertPoint(ElseTI);
3131 {Ident, ThreadID, NumDeps, DepArray,
3132 ConstantInt::get(
Builder.getInt32Ty(), 0),
3147 Builder.SetInsertPoint(ThenTI);
3155 {Ident, ThreadID, TaskData, NumDeps, DepArray,
3156 ConstantInt::get(
Builder.getInt32Ty(), 0),
3167 Builder.SetInsertPoint(TaskAllocaBB, TaskAllocaBB->
begin());
3169 LoadInst *Shareds =
Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
3170 OutlinedFn.getArg(1)->replaceUsesWithIf(
3171 Shareds, [Shareds](
Use &U) {
return U.getUser() != Shareds; });
3177 Builder.ClearInsertionPoint();
3179 I->eraseFromParent();
3183 Builder.SetInsertPoint(TaskExitBB, TaskExitBB->
begin());
3205 if (
Error Err = BodyGenCB(AllocaIP,
Builder.saveIP(), DeallocBlocks))
3208 Builder.SetInsertPoint(TaskgroupExitBB);
3251 unsigned CaseNumber = 0;
3252 for (
auto SectionCB : SectionCBs) {
3254 M.getContext(),
"omp_section_loop.body.case", CurFn,
Continue);
3256 Builder.SetInsertPoint(CaseBB);
3271 Value *LB = ConstantInt::get(I32Ty, 0);
3272 Value *UB = ConstantInt::get(I32Ty, SectionCBs.
size());
3273 Value *ST = ConstantInt::get(I32Ty, 1);
3275 Loc, LoopBodyGenCB, LB, UB, ST,
true,
false, AllocaIP,
"section_loop");
3280 applyStaticWorkshareLoop(
Loc.DL, *
LoopInfo, AllocaIP,
3281 WorksharingLoopType::ForStaticLoop, !IsNowait);
3287 assert(LoopFini &&
"Bad structure of static workshare loop finalization");
3291 assert(FiniInfo.DK == OMPD_sections &&
3292 "Unexpected finalization stack state!");
3293 if (
Error Err = FiniInfo.mergeFiniBB(
Builder, LoopFini))
3307 if (IP.getBlock()->end() != IP.getPoint())
3318 auto *CaseBB =
Loc.IP.getBlock();
3319 auto *CondBB = CaseBB->getSinglePredecessor()->getSinglePredecessor();
3320 auto *ExitBB = CondBB->getTerminator()->getSuccessor(1);
3326 Directive OMPD = Directive::OMPD_sections;
3329 return EmitOMPInlinedRegion(OMPD,
nullptr,
nullptr, BodyGenCB, FiniCBWrapper,
3340Value *OpenMPIRBuilder::getGPUThreadID() {
3343 OMPRTL___kmpc_get_hardware_thread_id_in_block),
3347Value *OpenMPIRBuilder::getGPUWarpSize() {
3352Value *OpenMPIRBuilder::getNVPTXWarpID() {
3353 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3354 return Builder.CreateAShr(getGPUThreadID(), LaneIDBits,
"nvptx_warp_id");
3357Value *OpenMPIRBuilder::getNVPTXLaneID() {
3358 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3359 assert(LaneIDBits < 32 &&
"Invalid LaneIDBits size in NVPTX device.");
3360 unsigned LaneIDMask = ~0
u >> (32u - LaneIDBits);
3361 return Builder.CreateAnd(getGPUThreadID(),
Builder.getInt32(LaneIDMask),
3368 uint64_t FromSize =
M.getDataLayout().getTypeStoreSize(FromType);
3369 uint64_t ToSize =
M.getDataLayout().getTypeStoreSize(ToType);
3370 assert(FromSize > 0 &&
"From size must be greater than zero");
3371 assert(ToSize > 0 &&
"To size must be greater than zero");
3372 if (FromType == ToType)
3374 if (FromSize == ToSize)
3375 return Builder.CreateBitCast(From, ToType);
3377 return Builder.CreateIntCast(From, ToType,
true);
3383 Value *ValCastItem =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3384 CastItem,
Builder.getPtrTy(0));
3385 Builder.CreateStore(From, ValCastItem);
3386 return Builder.CreateLoad(ToType, CastItem);
3393 uint64_t Size =
M.getDataLayout().getTypeStoreSize(ElementType);
3394 assert(
Size <= 8 &&
"Unsupported bitwidth in shuffle instruction");
3398 Value *ElemCast = castValueToType(AllocaIP, Element, CastTy);
3400 Builder.CreateIntCast(getGPUWarpSize(),
Builder.getInt16Ty(),
true);
3402 Size <= 4 ? RuntimeFunction::OMPRTL___kmpc_shuffle_int32
3403 : RuntimeFunction::OMPRTL___kmpc_shuffle_int64);
3404 Value *WarpSizeCast =
3406 Value *ShuffleCall =
3411 return castValueToType(AllocaIP, ShuffleCall, ElementType);
3418 uint64_t Size =
M.getDataLayout().getTypeStoreSize(ElemType);
3430 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3431 Value *ElemPtr = DstAddr;
3432 Value *Ptr = SrcAddr;
3433 for (
unsigned IntSize = 8; IntSize >= 1; IntSize /= 2) {
3437 Ptr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3440 Builder.CreateGEP(ElemType, SrcAddr, {ConstantInt::get(IndexTy, 1)});
3441 ElemPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3445 if ((
Size / IntSize) > 1) {
3446 Value *PtrEnd =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3447 SrcAddrGEP,
Builder.getPtrTy());
3464 Builder.CreatePointerBitCastOrAddrSpaceCast(Ptr,
Builder.getPtrTy()));
3466 Builder.CreateICmpSGT(PtrDiff,
Builder.getInt64(IntSize - 1)), ThenBB,
3469 Value *Res = createRuntimeShuffleFunction(
3472 IntType, Ptr,
M.getDataLayout().getPrefTypeAlign(ElemType)),
3474 Builder.CreateAlignedStore(Res, ElemPtr,
3475 M.getDataLayout().getPrefTypeAlign(ElemType));
3477 Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3478 Value *LocalElemPtr =
3479 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3487 Value *Res = createRuntimeShuffleFunction(
3488 AllocaIP,
Builder.CreateLoad(IntType, Ptr), IntType,
Offset);
3489 Builder.CreateStore(Res, ElemPtr);
3490 Ptr =
Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3492 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3498Error OpenMPIRBuilder::emitReductionListCopy(
3503 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3504 Value *RemoteLaneOffset = CopyOptions.RemoteLaneOffset;
3508 for (
auto En :
enumerate(ReductionInfos)) {
3510 Value *SrcElementAddr =
nullptr;
3511 AllocaInst *DestAlloca =
nullptr;
3512 Value *DestElementAddr =
nullptr;
3513 Value *DestElementPtrAddr =
nullptr;
3515 bool ShuffleInElement =
false;
3518 bool UpdateDestListPtr =
false;
3522 ReductionArrayTy, SrcBase,
3523 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3524 SrcElementAddr =
Builder.CreateLoad(
Builder.getPtrTy(), SrcElementPtrAddr);
3528 DestElementPtrAddr =
Builder.CreateInBoundsGEP(
3529 ReductionArrayTy, DestBase,
3530 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3531 bool IsByRefElem = (!IsByRef.
empty() && IsByRef[En.index()]);
3537 Type *DestAllocaType =
3538 IsByRefElem ? RI.ByRefAllocatedType : RI.ElementType;
3539 DestAlloca =
Builder.CreateAlloca(DestAllocaType,
nullptr,
3540 ".omp.reduction.element");
3542 M.getDataLayout().getPrefTypeAlign(DestAllocaType));
3543 DestElementAddr = DestAlloca;
3546 DestElementAddr->
getName() +
".ascast");
3548 ShuffleInElement =
true;
3549 UpdateDestListPtr =
true;
3561 if (ShuffleInElement) {
3562 Type *ShuffleType = RI.ElementType;
3563 Value *ShuffleSrcAddr = SrcElementAddr;
3564 Value *ShuffleDestAddr = DestElementAddr;
3565 AllocaInst *LocalStorage =
nullptr;
3568 assert(RI.ByRefElementType &&
"Expected by-ref element type to be set");
3569 assert(RI.ByRefAllocatedType &&
3570 "Expected by-ref allocated type to be set");
3575 ShuffleType = RI.ByRefElementType;
3577 if (RI.DataPtrPtrGen) {
3580 Builder.saveIP(), ShuffleSrcAddr, ShuffleSrcAddr);
3583 return GenResult.takeError();
3592 LocalStorage =
Builder.CreateAlloca(ShuffleType);
3594 ShuffleDestAddr = LocalStorage;
3599 ShuffleDestAddr = DestElementAddr;
3603 shuffleAndStore(AllocaIP, ShuffleSrcAddr, ShuffleDestAddr, ShuffleType,
3604 RemoteLaneOffset, ReductionArrayTy, IsByRefElem);
3606 if (IsByRefElem && RI.DataPtrPtrGen) {
3608 Value *DestDescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3609 DestAlloca,
Builder.getPtrTy(),
".ascast");
3612 DestDescriptorAddr, LocalStorage, SrcElementAddr,
3613 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
3616 return GenResult.takeError();
3619 switch (RI.EvaluationKind) {
3621 Value *Elem =
Builder.CreateLoad(RI.ElementType, SrcElementAddr);
3623 Builder.CreateStore(Elem, DestElementAddr);
3627 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3628 RI.ElementType, SrcElementAddr, 0, 0,
".realp");
3630 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
3632 RI.ElementType, SrcElementAddr, 0, 1,
".imagp");
3634 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
3636 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3637 RI.ElementType, DestElementAddr, 0, 0,
".realp");
3638 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
3639 RI.ElementType, DestElementAddr, 0, 1,
".imagp");
3640 Builder.CreateStore(SrcReal, DestRealPtr);
3641 Builder.CreateStore(SrcImg, DestImgPtr);
3646 M.getDataLayout().getTypeStoreSize(RI.ElementType));
3648 DestElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3649 SrcElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3661 if (UpdateDestListPtr) {
3662 Value *CastDestAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3663 DestElementAddr,
Builder.getPtrTy(),
3664 DestElementAddr->
getName() +
".ascast");
3665 Builder.CreateStore(CastDestAddr, DestElementPtrAddr);
3672Expected<Function *> OpenMPIRBuilder::emitInterWarpCopyFunction(
3675 IRBuilder<>::InsertPointGuard IPG(
Builder);
3676 LLVMContext &Ctx =
M.getContext();
3678 Builder.getVoidTy(), {Builder.getPtrTy(), Builder.getInt32Ty()},
3682 "_omp_reduction_inter_warp_copy_func", &
M);
3688 Builder.SetInsertPoint(EntryBB);
3706 StringRef TransferMediumName =
3707 "__openmp_nvptx_data_transfer_temporary_storage";
3708 GlobalVariable *TransferMedium =
M.getGlobalVariable(TransferMediumName);
3709 unsigned WarpSize =
Config.getGridValue().GV_Warp_Size;
3711 if (!TransferMedium) {
3712 TransferMedium =
new GlobalVariable(
3720 Value *GPUThreadID = getGPUThreadID();
3722 Value *LaneID = getNVPTXLaneID();
3724 Value *WarpID = getNVPTXWarpID();
3728 Builder.GetInsertBlock()->getFirstInsertionPt());
3732 AllocaInst *ReduceListAlloca =
Builder.CreateAlloca(
3733 Arg0Type,
nullptr, ReduceListArg->
getName() +
".addr");
3734 AllocaInst *NumWarpsAlloca =
3735 Builder.CreateAlloca(Arg1Type,
nullptr, NumWarpsArg->
getName() +
".addr");
3736 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3737 ReduceListAlloca, Arg0Type, ReduceListAlloca->
getName() +
".ascast");
3738 Value *NumWarpsAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3739 NumWarpsAlloca,
Builder.getPtrTy(0),
3740 NumWarpsAlloca->
getName() +
".ascast");
3741 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
3742 Builder.CreateStore(NumWarpsArg, NumWarpsAddrCast);
3751 for (
auto En :
enumerate(ReductionInfos)) {
3757 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
3758 unsigned RealTySize =
M.getDataLayout().getTypeAllocSize(
3759 IsByRefElem ? RI.ByRefElementType : RI.ElementType);
3760 for (
unsigned TySize = 4; TySize > 0 && RealTySize > 0; TySize /= 2) {
3763 unsigned NumIters = RealTySize / TySize;
3766 Value *Cnt =
nullptr;
3767 Value *CntAddr =
nullptr;
3774 Builder.CreateAlloca(
Builder.getInt32Ty(),
nullptr,
".cnt.addr");
3776 CntAddr =
Builder.CreateAddrSpaceCast(CntAddr,
Builder.getPtrTy(),
3777 CntAddr->
getName() +
".ascast");
3789 Cnt, ConstantInt::get(
Builder.getInt32Ty(), NumIters));
3790 Builder.CreateCondBr(Cmp, BodyBB, ExitBB);
3797 omp::Directive::OMPD_unknown,
3801 return BarrierIP1.takeError();
3807 Value *IsWarpMaster =
Builder.CreateIsNull(LaneID,
"warp_master");
3808 Builder.CreateCondBr(IsWarpMaster, ThenBB, ElseBB);
3812 auto *RedListArrayTy =
3815 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3817 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3818 {ConstantInt::get(IndexTy, 0),
3819 ConstantInt::get(IndexTy, En.index())});
3823 if (IsByRefElem && RI.DataPtrPtrGen) {
3825 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
3828 return GenRes.takeError();
3839 ArrayTy, TransferMedium, {
Builder.getInt64(0), WarpID});
3844 Builder.CreateStore(Elem, MediumPtr,
3856 omp::Directive::OMPD_unknown,
3860 return BarrierIP2.takeError();
3867 Value *NumWarpsVal =
3870 Value *IsActiveThread =
3871 Builder.CreateICmpULT(GPUThreadID, NumWarpsVal,
"is_active_thread");
3872 Builder.CreateCondBr(IsActiveThread, W0ThenBB, W0ElseBB);
3879 ArrayTy, TransferMedium, {
Builder.getInt64(0), GPUThreadID});
3881 Value *TargetElemPtrPtr =
3882 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3883 {ConstantInt::get(IndexTy, 0),
3884 ConstantInt::get(IndexTy, En.index())});
3885 Value *TargetElemPtrVal =
3887 Value *TargetElemPtr = TargetElemPtrVal;
3889 if (IsByRefElem && RI.DataPtrPtrGen) {
3891 RI.DataPtrPtrGen(
Builder.saveIP(), TargetElemPtr, TargetElemPtr);
3894 return GenRes.takeError();
3896 TargetElemPtr =
Builder.CreateLoad(
Builder.getPtrTy(), TargetElemPtr);
3904 Value *SrcMediumValue =
3905 Builder.CreateLoad(CType, SrcMediumPtrVal,
true);
3906 Builder.CreateStore(SrcMediumValue, TargetElemPtr);
3916 Cnt, ConstantInt::get(
Builder.getInt32Ty(), 1));
3917 Builder.CreateStore(Cnt, CntAddr,
false);
3919 auto *CurFn =
Builder.GetInsertBlock()->getParent();
3923 RealTySize %= TySize;
3932Expected<Function *> OpenMPIRBuilder::emitShuffleAndReduceFunction(
3935 LLVMContext &Ctx =
M.getContext();
3936 IRBuilder<>::InsertPointGuard IPG(
Builder);
3937 FunctionType *FuncTy =
3939 {Builder.getPtrTy(), Builder.getInt16Ty(),
3940 Builder.getInt16Ty(), Builder.getInt16Ty()},
3944 "_omp_reduction_shuffle_and_reduce_func", &
M);
3955 Builder.SetInsertPoint(EntryBB);
3967 Type *ReduceListArgType = ReduceListArg->
getType();
3971 ReduceListArgType,
nullptr, ReduceListArg->
getName() +
".addr");
3972 Value *LaneIdAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
3973 LaneIDArg->
getName() +
".addr");
3975 LaneIDArgType,
nullptr, RemoteLaneOffsetArg->
getName() +
".addr");
3976 Value *AlgoVerAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
3977 AlgoVerArg->
getName() +
".addr");
3984 RedListArrayTy,
nullptr,
".omp.reduction.remote_reduce_list");
3986 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3987 ReduceListAlloca, ReduceListArgType,
3988 ReduceListAlloca->
getName() +
".ascast");
3989 Value *LaneIdAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3990 LaneIdAlloca, LaneIDArgPtrType, LaneIdAlloca->
getName() +
".ascast");
3991 Value *RemoteLaneOffsetAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3992 RemoteLaneOffsetAlloca, LaneIDArgPtrType,
3993 RemoteLaneOffsetAlloca->
getName() +
".ascast");
3994 Value *AlgoVerAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3995 AlgoVerAlloca, LaneIDArgPtrType, AlgoVerAlloca->
getName() +
".ascast");
3996 Value *RemoteListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3997 RemoteReductionListAlloca,
Builder.getPtrTy(),
3998 RemoteReductionListAlloca->
getName() +
".ascast");
4000 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
4001 Builder.CreateStore(LaneIDArg, LaneIdAddrCast);
4002 Builder.CreateStore(RemoteLaneOffsetArg, RemoteLaneOffsetAddrCast);
4003 Builder.CreateStore(AlgoVerArg, AlgoVerAddrCast);
4005 Value *ReduceList =
Builder.CreateLoad(ReduceListArgType, ReduceListAddrCast);
4006 Value *LaneId =
Builder.CreateLoad(LaneIDArgType, LaneIdAddrCast);
4007 Value *RemoteLaneOffset =
4008 Builder.CreateLoad(LaneIDArgType, RemoteLaneOffsetAddrCast);
4009 Value *AlgoVer =
Builder.CreateLoad(LaneIDArgType, AlgoVerAddrCast);
4016 Error EmitRedLsCpRes = emitReductionListCopy(
4018 ReduceList, RemoteListAddrCast, IsByRef,
4019 {RemoteLaneOffset,
nullptr,
nullptr});
4022 return EmitRedLsCpRes;
4047 Value *LaneComp =
Builder.CreateICmpULT(LaneId, RemoteLaneOffset);
4052 Value *Algo2AndLaneIdComp =
Builder.CreateAnd(Algo2, LaneIdComp);
4053 Value *RemoteOffsetComp =
4055 Value *CondAlgo2 =
Builder.CreateAnd(Algo2AndLaneIdComp, RemoteOffsetComp);
4056 Value *CA0OrCA1 =
Builder.CreateOr(CondAlgo0, CondAlgo1);
4057 Value *CondReduce =
Builder.CreateOr(CA0OrCA1, CondAlgo2);
4063 Builder.CreateCondBr(CondReduce, ThenBB, ElseBB);
4065 Value *LocalReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4066 ReduceList,
Builder.getPtrTy());
4067 Value *RemoteReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4068 RemoteListAddrCast,
Builder.getPtrTy());
4070 ->addFnAttr(Attribute::NoUnwind);
4081 Value *LaneIdGtOffset =
Builder.CreateICmpUGE(LaneId, RemoteLaneOffset);
4082 Value *CondCopy =
Builder.CreateAnd(Algo1, LaneIdGtOffset);
4087 Builder.CreateCondBr(CondCopy, CpyThenBB, CpyElseBB);
4091 EmitRedLsCpRes = emitReductionListCopy(
4093 RemoteListAddrCast, ReduceList, IsByRef);
4096 return EmitRedLsCpRes;
4111OpenMPIRBuilder::generateReductionDescriptor(
4113 Type *DescriptorType,
4119 Value *DescriptorSize =
4120 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(DescriptorType));
4122 DescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4123 SrcDescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4127 Value *DataPtrField;
4129 DataPtrPtrGen(
Builder.saveIP(), DescriptorAddr, DataPtrField);
4132 return GenResult.takeError();
4135 DataPtr,
Builder.getPtrTy(),
".ascast"),
4141Expected<Value *> OpenMPIRBuilder::createReductionDescriptorCopy(
4143 Value *SrcDescriptorAddr,
Type *DescriptorPtrTy,
const Twine &Name) {
4147 AllocaInst *DescriptorAlloca =
4148 Builder.CreateAlloca(RI.ByRefAllocatedType,
nullptr, Name);
4150 M.getDataLayout().getPrefTypeAlign(RI.ByRefAllocatedType));
4151 Value *DescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4152 DescriptorAlloca, DescriptorPtrTy,
4153 DescriptorAlloca->
getName() +
".ascast");
4158 generateReductionDescriptor(DescriptorAddr, DataPtr, SrcDescriptorAddr,
4159 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
4161 return GenResult.takeError();
4163 return DescriptorAddr;
4166Expected<Function *> OpenMPIRBuilder::emitListToGlobalCopyFunction(
4169 IRBuilder<>::InsertPointGuard IPG(
Builder);
4170 LLVMContext &Ctx =
M.getContext();
4173 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4177 "_omp_reduction_list_to_global_copy_func", &
M);
4184 Builder.SetInsertPoint(EntryBlock);
4195 BufferArg->
getName() +
".addr");
4199 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4200 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4201 BufferArgAlloca,
Builder.getPtrTy(),
4202 BufferArgAlloca->
getName() +
".ascast");
4203 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4204 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4205 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4206 ReduceListArgAlloca,
Builder.getPtrTy(),
4207 ReduceListArgAlloca->
getName() +
".ascast");
4209 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4210 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4211 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4213 Value *LocalReduceList =
4215 Value *BufferArgVal =
4219 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4220 for (
auto En :
enumerate(ReductionInfos)) {
4222 auto *RedListArrayTy =
4226 RedListArrayTy, LocalReduceList,
4227 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4233 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferArgVal, Idxs);
4235 ReductionsBufferTy, BufferVD, 0, En.index());
4237 switch (RI.EvaluationKind) {
4239 Value *TargetElement;
4241 if (IsByRef.
empty() || !IsByRef[En.index()]) {
4242 TargetElement =
Builder.CreateLoad(RI.ElementType, ElemPtr);
4244 if (RI.DataPtrPtrGen) {
4246 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
4249 return GenResult.takeError();
4253 TargetElement =
Builder.CreateLoad(RI.ByRefElementType, ElemPtr);
4256 Builder.CreateStore(TargetElement, GlobVal);
4260 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4261 RI.ElementType, ElemPtr, 0, 0,
".realp");
4263 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
4265 RI.ElementType, ElemPtr, 0, 1,
".imagp");
4267 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
4269 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4270 RI.ElementType, GlobVal, 0, 0,
".realp");
4271 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4272 RI.ElementType, GlobVal, 0, 1,
".imagp");
4273 Builder.CreateStore(SrcReal, DestRealPtr);
4274 Builder.CreateStore(SrcImg, DestImgPtr);
4279 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(RI.ElementType));
4281 GlobVal,
M.getDataLayout().getPrefTypeAlign(RI.ElementType), ElemPtr,
4282 M.getDataLayout().getPrefTypeAlign(RI.ElementType), SizeVal,
false);
4292Expected<Function *> OpenMPIRBuilder::emitListToGlobalReduceFunction(
4295 IRBuilder<>::InsertPointGuard IPG(
Builder);
4296 LLVMContext &Ctx =
M.getContext();
4299 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4303 "_omp_reduction_list_to_global_reduce_func", &
M);
4310 Builder.SetInsertPoint(EntryBlock);
4321 BufferArg->
getName() +
".addr");
4325 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4326 auto *RedListArrayTy =
4331 Value *LocalReduceList =
4332 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4336 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4337 BufferArgAlloca,
Builder.getPtrTy(),
4338 BufferArgAlloca->
getName() +
".ascast");
4339 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4340 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4341 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4342 ReduceListArgAlloca,
Builder.getPtrTy(),
4343 ReduceListArgAlloca->
getName() +
".ascast");
4344 Value *LocalReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4345 LocalReduceList,
Builder.getPtrTy(),
4346 LocalReduceList->
getName() +
".ascast");
4348 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4349 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4350 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4355 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4356 for (
auto En :
enumerate(ReductionInfos)) {
4359 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4360 RedListArrayTy, LocalReduceListAddrCast,
4361 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4363 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4365 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4366 ReductionsBufferTy, BufferVD, 0, En.index());
4368 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4372 Value *SrcElementPtrPtr =
4373 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
4374 {ConstantInt::get(IndexTy, 0),
4375 ConstantInt::get(IndexTy, En.index())});
4376 Value *SrcDescriptorAddr =
4380 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4381 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4385 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4387 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4395 ->addFnAttr(Attribute::NoUnwind);
4400Expected<Function *> OpenMPIRBuilder::emitGlobalToListCopyFunction(
4403 IRBuilder<>::InsertPointGuard IPG(
Builder);
4404 LLVMContext &Ctx =
M.getContext();
4407 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4411 "_omp_reduction_global_to_list_copy_func", &
M);
4418 Builder.SetInsertPoint(EntryBlock);
4429 BufferArg->
getName() +
".addr");
4433 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4434 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4435 BufferArgAlloca,
Builder.getPtrTy(),
4436 BufferArgAlloca->
getName() +
".ascast");
4437 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4438 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4439 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4440 ReduceListArgAlloca,
Builder.getPtrTy(),
4441 ReduceListArgAlloca->
getName() +
".ascast");
4442 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4443 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4444 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4446 Value *LocalReduceList =
4451 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4452 for (
auto En :
enumerate(ReductionInfos)) {
4453 const OpenMPIRBuilder::ReductionInfo &RI = En.value();
4454 auto *RedListArrayTy =
4458 RedListArrayTy, LocalReduceList,
4459 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4464 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4465 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4466 ReductionsBufferTy, BufferVD, 0, En.index());
4472 if (!IsByRef.
empty() && IsByRef[En.index()]) {
4479 return GenResult.takeError();
4485 Value *TargetElement =
Builder.CreateLoad(ElemType, GlobValPtr);
4486 Builder.CreateStore(TargetElement, ElemPtr);
4490 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4499 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4501 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4503 Builder.CreateStore(SrcReal, DestRealPtr);
4504 Builder.CreateStore(SrcImg, DestImgPtr);
4511 ElemPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4512 GlobValPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4523Expected<Function *> OpenMPIRBuilder::emitGlobalToListReduceFunction(
4526 IRBuilder<>::InsertPointGuard IPG(
Builder);
4527 LLVMContext &Ctx =
M.getContext();
4530 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4534 "_omp_reduction_global_to_list_reduce_func", &
M);
4541 Builder.SetInsertPoint(EntryBlock);
4552 BufferArg->
getName() +
".addr");
4556 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4562 Value *LocalReduceList =
4563 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4567 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4568 BufferArgAlloca,
Builder.getPtrTy(),
4569 BufferArgAlloca->
getName() +
".ascast");
4570 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4571 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4572 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4573 ReduceListArgAlloca,
Builder.getPtrTy(),
4574 ReduceListArgAlloca->
getName() +
".ascast");
4575 Value *ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4576 LocalReduceList,
Builder.getPtrTy(),
4577 LocalReduceList->
getName() +
".ascast");
4579 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4580 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4581 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4586 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4587 for (
auto En :
enumerate(ReductionInfos)) {
4590 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4591 RedListArrayTy, ReductionList,
4592 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4595 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4596 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4597 ReductionsBufferTy, BufferVD, 0, En.index());
4599 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4601 Value *ReduceListVal =
4603 Value *SrcElementPtrPtr =
4604 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceListVal,
4605 {ConstantInt::get(IndexTy, 0),
4606 ConstantInt::get(IndexTy, En.index())});
4607 Value *SrcDescriptorAddr =
4611 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4612 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4616 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4618 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4626 ->addFnAttr(Attribute::NoUnwind);
4631std::string OpenMPIRBuilder::getReductionFuncName(StringRef Name)
const {
4632 std::string Suffix =
4634 return (Name + Suffix).str();
4637Expected<Function *> OpenMPIRBuilder::createReductionFunction(
4640 AttributeList FuncAttrs) {
4641 IRBuilder<>::InsertPointGuard IPG(
Builder);
4643 {Builder.getPtrTy(), Builder.getPtrTy()},
4645 std::string
Name = getReductionFuncName(ReducerName);
4654 Builder.SetInsertPoint(EntryBB);
4659 Value *LHSArrayPtr =
nullptr;
4660 Value *RHSArrayPtr =
nullptr;
4667 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
4669 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
4670 Value *LHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4671 LHSAlloca, Arg0Type, LHSAlloca->
getName() +
".ascast");
4672 Value *RHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4673 RHSAlloca, Arg1Type, RHSAlloca->
getName() +
".ascast");
4674 Builder.CreateStore(Arg0, LHSAddrCast);
4675 Builder.CreateStore(Arg1, RHSAddrCast);
4676 LHSArrayPtr =
Builder.CreateLoad(Arg0Type, LHSAddrCast);
4677 RHSArrayPtr =
Builder.CreateLoad(Arg1Type, RHSAddrCast);
4681 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4683 for (
auto En :
enumerate(ReductionInfos)) {
4686 RedArrayTy, RHSArrayPtr,
4687 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4689 Value *RHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4690 RHSI8Ptr, RI.PrivateVariable->getType(),
4691 RHSI8Ptr->
getName() +
".ascast");
4694 RedArrayTy, LHSArrayPtr,
4695 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4697 Value *LHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4698 LHSI8Ptr, RI.Variable->getType(), LHSI8Ptr->
getName() +
".ascast");
4707 if (!IsByRef.
empty() && !IsByRef[En.index()]) {
4708 LHS =
Builder.CreateLoad(RI.ElementType, LHSPtr);
4709 RHS =
Builder.CreateLoad(RI.ElementType, RHSPtr);
4716 return AfterIP.takeError();
4717 if (!
Builder.GetInsertBlock())
4718 return ReductionFunc;
4722 if (!IsByRef.
empty() && !IsByRef[En.index()])
4723 Builder.CreateStore(Reduced, LHSPtr);
4728 for (
auto En :
enumerate(ReductionInfos)) {
4729 unsigned Index = En.index();
4731 Value *LHSFixupPtr, *RHSFixupPtr;
4732 Builder.restoreIP(RI.ReductionGenClang(
4733 Builder.saveIP(), Index, &LHSFixupPtr, &RHSFixupPtr, ReductionFunc));
4738 LHSPtrs[Index], [ReductionFunc](
const Use &U) {
4743 RHSPtrs[Index], [ReductionFunc](
const Use &U) {
4757 return ReductionFunc;
4765 assert(RI.Variable &&
"expected non-null variable");
4766 assert(RI.PrivateVariable &&
"expected non-null private variable");
4767 assert((RI.ReductionGen || RI.ReductionGenClang) &&
4768 "expected non-null reduction generator callback");
4771 RI.Variable->getType() == RI.PrivateVariable->getType() &&
4772 "expected variables and their private equivalents to have the same "
4775 assert(RI.Variable->getType()->isPointerTy() &&
4776 "expected variables to be pointers");
4793 ArrayRef<bool> IsByRef,
bool IsNoWait,
bool IsTeamsReduction,
bool IsSPMD,
4795 Value *SrcLocInfo) {
4809 if (ReductionInfos.
size() == 0)
4819 Builder.SetInsertPoint(InsertBlock, InsertBlock->
end());
4823 AttributeList FuncAttrs;
4824 AttrBuilder AttrBldr(Ctx);
4826 AttrBldr.addAttribute(Attr);
4827 AttrBldr.removeAttribute(Attribute::OptimizeNone);
4828 FuncAttrs = FuncAttrs.addFnAttributes(Ctx, AttrBldr);
4832 Builder.GetInsertBlock()->getParent()->getName(), ReductionInfos, IsByRef,
4834 if (!ReductionResult)
4836 Function *ReductionFunc = *ReductionResult;
4840 if (GridValue.has_value())
4841 Config.setGridValue(GridValue.value());
4856 Builder.getPtrTy(
M.getDataLayout().getProgramAddressSpace());
4860 Value *ReductionListAlloca =
4861 Builder.CreateAlloca(RedArrayTy,
nullptr,
".omp.reduction.red_list");
4862 Value *ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4863 ReductionListAlloca, PtrTy, ReductionListAlloca->
getName() +
".ascast");
4866 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4867 for (
auto En :
enumerate(ReductionInfos)) {
4870 RedArrayTy, ReductionList,
4871 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4874 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
4879 Builder.CreatePointerBitCastOrAddrSpaceCast(PrivateVar, PtrTy);
4880 Builder.CreateStore(CastElem, ElemPtr);
4884 ReductionInfos, ReductionFunc, FuncAttrs, IsByRef);
4890 emitInterWarpCopyFunction(
Loc, ReductionInfos, FuncAttrs, IsByRef);
4896 Value *RL =
Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList, PtrTy);
4905 unsigned MaxDataSize = 0;
4907 for (
auto En :
enumerate(ReductionInfos)) {
4911 Type *RedTypeArg = (!IsByRef.
empty() && IsByRef[En.index()])
4912 ? En.value().ByRefElementType
4913 : En.value().ElementType;
4914 auto Size =
M.getDataLayout().getTypeStoreSize(RedTypeArg);
4915 if (
Size > MaxDataSize)
4919 Value *ReductionDataSize =
4920 Builder.getInt64(MaxDataSize * ReductionInfos.
size());
4924 Function *CopyScratchToListFunc =
nullptr;
4926 Value *ScratchForCopyBack =
nullptr;
4929 Value *RLForCopyBack = RL;
4931 bool IsAtomicReduction =
4934 if (!IsTeamsReduction) {
4935 Value *SarFuncCast =
4936 Builder.CreatePointerBitCastOrAddrSpaceCast(*SarFunc, FuncPtrTy);
4938 Builder.CreatePointerBitCastOrAddrSpaceCast(WcFunc, FuncPtrTy);
4939 Value *Args[] = {SrcLocInfo, ReductionDataSize, RL, SarFuncCast,
4942 RuntimeFunction::OMPRTL___kmpc_nvptx_parallel_reduce_nowait_v2);
4944 }
else if (IsAtomicReduction) {
4948 RuntimeFunction::OMPRTL___kmpc_is_team_main_thread);
4953 Ctx, ReductionTypeArgs,
"struct._globalized_locals_ty");
4956 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
4961 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
4966 ReductionInfos, ReductionFunc, ReductionsBufferTy, FuncAttrs, IsByRef);
4989 Value *RuntimeRL = RL;
4996 ReductionsBufferTy,
nullptr,
".omp.reduction.scratch");
4997 Value *PerThreadScratch =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4998 PerThreadScratchAlloca, PtrTy,
4999 PerThreadScratchAlloca->
getName() +
".ascast");
5002 Value *PerThreadRedListAlloca =
5003 Builder.CreateAlloca(RedArrayTy,
nullptr,
5004 ".omp.reduction.per_thread_red_list");
5005 RuntimeRL =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5006 PerThreadRedListAlloca, PtrTy,
5007 PerThreadRedListAlloca->
getName() +
".ascast");
5012 for (
auto En :
enumerate(ReductionInfos)) {
5014 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
5017 ReductionsBufferTy, PerThreadScratch, 0, En.index());
5018 Value *Slot =
Builder.CreateConstInBoundsGEP2_32(RedArrayTy, RuntimeRL,
5021 Value *RuntimeListEntry = FieldPtr;
5023 Value *SrcDescriptor =
5026 AllocaIP, RI, FieldPtr, SrcDescriptor, PtrTy);
5029 RuntimeListEntry = *Descriptor;
5031 Builder.CreateStore(RuntimeListEntry, Slot);
5037 Type *CopyArg0Ty = (*LtGCFunc)->getFunctionType()->getParamType(0);
5038 Type *CopyArg2Ty = (*LtGCFunc)->getFunctionType()->getParamType(2);
5039 ScratchForCopyBack =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5040 PerThreadScratch, CopyArg0Ty);
5042 Builder.CreatePointerBitCastOrAddrSpaceCast(RL, CopyArg2Ty);
5050 *LtGCFunc, {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
5051 CopyScratchToListFunc = *GtLCFunc;
5054 Value *Args3[] = {SrcLocInfo, RuntimeRL, *SarFunc, WcFunc,
5055 *LtGCFunc, *GtLCFunc, *GtLRFunc};
5058 RuntimeFunction::OMPRTL___kmpc_gpu_xteam_reduce_nowait);
5078 if (ScratchForCopyBack) {
5081 CopyScratchToListFunc,
5082 {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
5086 for (
auto En :
enumerate(ReductionInfos)) {
5092 if (IsAtomicReduction) {
5108 Value *LHSPtr, *RHSPtr;
5110 &LHSPtr, &RHSPtr, CurFunc));
5116 RedValue =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5118 if (RHSPtr->
getType() != RHS->getType())
5120 Builder.CreatePointerBitCastOrAddrSpaceCast(RHS, RHSPtr->
getType());
5131 if (IsByRef.
empty() || !IsByRef[En.index()]) {
5133 "red.value." +
Twine(En.index()));
5144 if (!IsByRef.
empty() && !IsByRef[En.index()])
5149 if (ContinuationBlock) {
5150 Builder.CreateBr(ContinuationBlock);
5151 Builder.SetInsertPoint(ContinuationBlock);
5153 Config.setEmitLLVMUsed();
5164 ".omp.reduction.func", &M);
5175 Builder.SetInsertPoint(ReductionFuncBlock);
5177 Value *LHSArrayPtr =
nullptr;
5178 Value *RHSArrayPtr =
nullptr;
5189 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
5191 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
5192 Value *LHSAddrCast =
5193 Builder.CreatePointerBitCastOrAddrSpaceCast(LHSAlloca, Arg0Type);
5194 Value *RHSAddrCast =
5195 Builder.CreatePointerBitCastOrAddrSpaceCast(RHSAlloca, Arg1Type);
5196 Builder.CreateStore(Arg0, LHSAddrCast);
5197 Builder.CreateStore(Arg1, RHSAddrCast);
5198 LHSArrayPtr = Builder.CreateLoad(Arg0Type, LHSAddrCast);
5199 RHSArrayPtr = Builder.CreateLoad(Arg1Type, RHSAddrCast);
5201 LHSArrayPtr = ReductionFunc->
getArg(0);
5202 RHSArrayPtr = ReductionFunc->
getArg(1);
5205 unsigned NumReductions = ReductionInfos.
size();
5208 for (
auto En :
enumerate(ReductionInfos)) {
5210 Value *LHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5211 RedArrayTy, LHSArrayPtr, 0, En.index());
5212 Value *LHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), LHSI8PtrPtr);
5213 Value *LHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5216 Value *RHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5217 RedArrayTy, RHSArrayPtr, 0, En.index());
5218 Value *RHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), RHSI8PtrPtr);
5219 Value *RHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5228 Builder.restoreIP(*AfterIP);
5230 if (!Builder.GetInsertBlock())
5234 if (!IsByRef[En.index()])
5235 Builder.CreateStore(Reduced, LHSPtr);
5237 Builder.CreateRetVoid();
5244 bool IsNoWait,
bool IsTeamsReduction) {
5248 IsByRef, IsNoWait, IsTeamsReduction);
5255 if (ReductionInfos.
size() == 0)
5265 unsigned NumReductions = ReductionInfos.
size();
5268 Value *RedArray =
Builder.CreateAlloca(RedArrayTy,
nullptr,
"red.array");
5270 Builder.SetInsertPoint(InsertBlock, InsertBlock->
end());
5272 for (
auto En :
enumerate(ReductionInfos)) {
5273 unsigned Index = En.index();
5275 Value *RedArrayElemPtr =
Builder.CreateConstInBoundsGEP2_64(
5276 RedArrayTy, RedArray, 0, Index,
"red.array.elem." +
Twine(Index));
5283 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
5293 ? IdentFlag::OMP_IDENT_FLAG_ATOMIC_REDUCE
5298 unsigned RedArrayByteSize =
DL.getTypeStoreSize(RedArrayTy);
5299 Constant *RedArraySize = ConstantInt::get(IndexTy, RedArrayByteSize);
5301 Value *Lock = getOMPCriticalRegionLock(
".reduction");
5303 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_reduce_nowait
5304 : RuntimeFunction::OMPRTL___kmpc_reduce);
5307 {Ident, ThreadId, NumVariables, RedArraySize,
5308 RedArray, ReductionFunc, Lock},
5319 Builder.CreateSwitch(ReduceCall, ContinuationBlock, 2);
5320 Switch->addCase(
Builder.getInt32(1), NonAtomicRedBlock);
5321 Switch->addCase(
Builder.getInt32(2), AtomicRedBlock);
5326 Builder.SetInsertPoint(NonAtomicRedBlock);
5327 for (
auto En :
enumerate(ReductionInfos)) {
5333 if (!IsByRef[En.index()]) {
5335 "red.value." +
Twine(En.index()));
5337 Value *PrivateRedValue =
5339 "red.private.value." +
Twine(En.index()));
5347 if (!
Builder.GetInsertBlock())
5350 if (!IsByRef[En.index()])
5354 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_end_reduce_nowait
5355 : RuntimeFunction::OMPRTL___kmpc_end_reduce);
5357 Builder.CreateBr(ContinuationBlock);
5362 Builder.SetInsertPoint(AtomicRedBlock);
5363 if (CanGenerateAtomic &&
llvm::none_of(IsByRef, [](
bool P) {
return P; })) {
5370 if (!
Builder.GetInsertBlock())
5373 Builder.CreateBr(ContinuationBlock);
5386 if (!
Builder.GetInsertBlock())
5389 Builder.SetInsertPoint(ContinuationBlock);
5400 Directive OMPD = Directive::OMPD_master;
5405 Value *Args[] = {Ident, ThreadId};
5413 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5425 Directive OMPD = Directive::OMPD_masked;
5431 Value *ArgsEnd[] = {Ident, ThreadId};
5439 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5449 Call->setDoesNotThrow();
5464 bool IsInclusive,
ScanInfo *ScanRedInfo) {
5466 llvm::Error Err = emitScanBasedDirectiveDeclsIR(AllocaIP, ScanVars,
5467 ScanVarsType, ScanRedInfo);
5478 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5481 Type *DestTy = ScanVarsType[i];
5482 Value *Val =
Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5485 Builder.CreateStore(Src, Val);
5490 Builder.GetInsertBlock()->getParent());
5493 IV = ScanRedInfo->
IV;
5496 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5499 Type *DestTy = ScanVarsType[i];
5501 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5503 Builder.CreateStore(Src, ScanVars[i]);
5517 Builder.GetInsertBlock()->getParent());
5522Error OpenMPIRBuilder::emitScanBasedDirectiveDeclsIR(
5526 Builder.restoreIP(AllocaIP);
5528 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5530 Builder.CreateAlloca(Builder.getPtrTy(),
nullptr,
"vla");
5537 Builder.restoreIP(CodeGenIP);
5539 Builder.CreateAdd(ScanRedInfo->
Span, Builder.getInt32(1));
5540 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5544 Value *Buff = Builder.CreateMalloc(
IntPtrTy, ScanVarsType[i], Allocsize,
5545 AllocSpan,
nullptr,
"arr");
5546 Builder.CreateStore(Buff, (*(ScanRedInfo->
ScanBuffPtrs))[ScanVars[i]]);
5573Error OpenMPIRBuilder::emitScanBasedDirectiveFinalsIR(
5579 Value *PrivateVar = RedInfo.PrivateVariable;
5580 Value *OrigVar = RedInfo.Variable;
5584 Type *SrcTy = RedInfo.ElementType;
5589 Builder.CreateStore(Src, OrigVar);
5637 Builder.GetInsertBlock()->getModule(),
5644 Builder.GetInsertBlock()->getModule(),
5650 llvm::ConstantInt::get(ScanRedInfo->
Span->
getType(), 1));
5651 Builder.SetInsertPoint(InputBB);
5654 Builder.SetInsertPoint(LoopBB);
5670 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5672 Builder.SetInsertPoint(InnerLoopBB);
5676 Value *ReductionVal = RedInfo.PrivateVariable;
5679 Type *DestTy = RedInfo.ElementType;
5682 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5685 Builder.CreateInBoundsGEP(DestTy, Buff, OffsetIval,
"arrayOffset");
5690 RedInfo.ReductionGen(
Builder.saveIP(), LHS, RHS, Result);
5693 Builder.CreateStore(Result, LHSPtr);
5696 IVal, llvm::ConstantInt::get(
Builder.getInt32Ty(), 1));
5698 CmpI =
Builder.CreateICmpUGE(NextIVal, Pow2K);
5699 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5702 Counter, llvm::ConstantInt::get(Counter->
getType(), 1));
5708 Builder.CreateCondBr(Cmp, LoopBB, ExitBB);
5729 Error Err = emitScanBasedDirectiveFinalsIR(ReductionInfos, ScanRedInfo);
5736Error OpenMPIRBuilder::emitScanBasedDirectiveIR(
5748 Error Err = InputLoopGen();
5759 Error Err = ScanLoopGen(Builder);
5766void OpenMPIRBuilder::createScanBBs(ScanInfo *ScanRedInfo) {
5803 Builder.SetInsertPoint(Preheader);
5806 Builder.SetInsertPoint(Header);
5807 PHINode *IndVarPHI =
Builder.CreatePHI(IndVarTy, 2,
"omp_" + Name +
".iv");
5808 IndVarPHI->
addIncoming(ConstantInt::get(IndVarTy, 0), Preheader);
5813 Builder.CreateICmpULT(IndVarPHI, TripCount,
"omp_" + Name +
".cmp");
5814 Builder.CreateCondBr(Cmp, Body, Exit);
5819 Builder.SetInsertPoint(Latch);
5829 bool HasNSW =
Config.hasNoSignedWrap();
5832 unsigned BitWidth = CI->getType()->getIntegerBitWidth();
5834 if (CI->getValue().ugt(SignedMax))
5836 }
else if (IsCollapsed) {
5841 Builder.CreateAdd(IndVarPHI, ConstantInt::get(IndVarTy, 1),
5842 "omp_" + Name +
".next",
true, HasNSW);
5853 CL->Header = Header;
5872 NextBB, NextBB, Name);
5904 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
5913 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
5914 ScanRedInfo->
Span = TripCount;
5920 ScanRedInfo->
IV =
IV;
5921 createScanBBs(ScanRedInfo);
5924 assert(Terminator->getNumSuccessors() == 1);
5925 BasicBlock *ContinueBlock = Terminator->getSuccessor(0);
5928 Builder.GetInsertBlock()->getParent());
5931 Builder.GetInsertBlock()->getParent());
5932 Builder.CreateBr(ContinueBlock);
5938 const auto &&InputLoopGen = [&]() ->
Error {
5941 InclusiveStop, ComputeIP, Name,
true, ScanRedInfo);
5945 Builder.restoreIP((*LoopInfo)->getAfterIP());
5951 InclusiveStop, ComputeIP, Name,
true, ScanRedInfo);
5955 Builder.restoreIP((*LoopInfo)->getAfterIP());
5959 Error Err = emitScanBasedDirectiveIR(InputLoopGen, ScanLoopGen, ScanRedInfo);
5967 bool IsSigned,
bool InclusiveStop,
const Twine &Name) {
5977 assert(IndVarTy == Stop->
getType() &&
"Stop type mismatch");
5978 assert(IndVarTy == Step->
getType() &&
"Step type mismatch");
5982 ConstantInt *Zero = ConstantInt::get(IndVarTy, 0);
5998 Incr =
Builder.CreateSelect(IsNeg,
Builder.CreateNeg(Step), Step);
6001 Span =
Builder.CreateSub(UB, LB,
"",
false,
true);
6005 Span =
Builder.CreateSub(Stop, Start,
"",
true);
6010 Value *CountIfLooping;
6011 if (InclusiveStop) {
6012 CountIfLooping =
Builder.CreateAdd(
Builder.CreateUDiv(Span, Incr), One);
6018 CountIfLooping =
Builder.CreateSelect(OneCmp, One, CountIfTwo);
6021 return Builder.CreateSelect(ZeroCmp, Zero, CountIfLooping,
6022 "omp_" + Name +
".tripcount");
6027 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
6034 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
6039 Config.hasNoSignedWrap());
6040 Value *IndVar =
Builder.CreateAdd(Span, Start,
"",
false,
6041 Config.hasNoSignedWrap());
6043 ScanRedInfo->
IV = IndVar;
6044 return BodyGenCB(
Builder.saveIP(), IndVar);
6050 Builder.getCurrentDebugLocation());
6061 unsigned Bitwidth = Ty->getIntegerBitWidth();
6064 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_4u);
6067 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_8u);
6077 unsigned Bitwidth = Ty->getIntegerBitWidth();
6080 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_4u);
6083 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_8u);
6091 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6093 "Require dedicated allocate IP");
6099 uint32_t SrcLocStrSize;
6103 case WorksharingLoopType::ForStaticLoop:
6104 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6106 case WorksharingLoopType::DistributeStaticLoop:
6107 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6109 case WorksharingLoopType::DistributeForStaticLoop:
6110 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
6117 Type *IVTy =
IV->getType();
6118 FunctionCallee StaticInit =
6119 LoopType == WorksharingLoopType::DistributeForStaticLoop
6122 FunctionCallee StaticFini =
6126 Builder.SetInsertPoint(AllocaIP.getBlock()->getFirstNonPHIOrDbgOrAlloca());
6129 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6130 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
6131 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
6132 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
6141 Constant *One = ConstantInt::get(IVTy, 1);
6142 Builder.CreateStore(Zero, PLowerBound);
6144 Builder.CreateStore(UpperBound, PUpperBound);
6145 Builder.CreateStore(One, PStride);
6151 (LoopType == WorksharingLoopType::DistributeStaticLoop)
6152 ? OMPScheduleType::OrderedDistribute
6155 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6159 auto BuildInitCall = [LoopType, SrcLoc, ThreadNum, PLastIter, PLowerBound,
6160 PUpperBound, IVTy, PStride, One,
Zero, StaticInit,
6163 PLowerBound, PUpperBound});
6164 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
6165 Value *PDistUpperBound =
6166 Builder.CreateAlloca(IVTy,
nullptr,
"p.distupperbound");
6167 Args.push_back(PDistUpperBound);
6172 BuildInitCall(SchedulingType,
Builder);
6173 if (HasDistSchedule &&
6174 LoopType != WorksharingLoopType::DistributeStaticLoop) {
6175 Constant *DistScheduleSchedType = ConstantInt::get(
6180 BuildInitCall(DistScheduleSchedType,
Builder);
6183 Value *InclusiveUpperBound =
Builder.CreateLoad(IVTy, PUpperBound);
6185 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One);
6186 CLI->setTripCount(TripCount);
6192 CLI->mapIndVar([&](Instruction *OldIV) ->
Value * {
6197 Config.hasNoSignedWrap());
6209 omp::Directive::OMPD_for,
false,
6212 return BarrierIP.takeError();
6239 Reachable.insert(
Block);
6253OpenMPIRBuilder::applyStaticChunkedWorkshareLoop(
6257 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6258 assert((ChunkSize || DistScheduleChunkSize) &&
"Chunk size is required");
6263 Type *IVTy =
IV->getType();
6265 "Max supported tripcount bitwidth is 64 bits");
6267 :
Type::getInt64Ty(Ctx);
6270 Constant *One = ConstantInt::get(InternalIVTy, 1);
6275 SmallVector<Instruction *> UIs;
6276 for (BasicBlock &BB : *
F)
6277 if (!BB.hasTerminator())
6278 UIs.
push_back(
new UnreachableInst(
F->getContext(), &BB));
6283 LoopInfo &&LI = LIA.
run(*
F,
FAM);
6284 for (Instruction *
I : UIs)
6285 I->eraseFromParent();
6288 if (ChunkSize || DistScheduleChunkSize)
6293 FunctionCallee StaticInit =
6295 FunctionCallee StaticFini =
6301 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6302 Value *PLowerBound =
6303 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.lowerbound");
6304 Value *PUpperBound =
6305 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.upperbound");
6306 Value *PStride =
Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.stride");
6315 ChunkSize ? ChunkSize : Zero, InternalIVTy,
"chunksize");
6316 Value *CastedDistScheduleChunkSize =
Builder.CreateZExtOrTrunc(
6317 DistScheduleChunkSize ? DistScheduleChunkSize : Zero, InternalIVTy,
6318 "distschedulechunksize");
6319 Value *CastedTripCount =
6320 Builder.CreateZExt(OrigTripCount, InternalIVTy,
"tripcount");
6323 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6325 ConstantInt::get(I32Type,
static_cast<int>(DistScheduleSchedType));
6326 Builder.CreateStore(Zero, PLowerBound);
6327 Value *OrigUpperBound =
Builder.CreateSub(CastedTripCount, One);
6328 Value *IsTripCountZero =
Builder.CreateICmpEQ(CastedTripCount, Zero);
6330 Builder.CreateSelect(IsTripCountZero, Zero, OrigUpperBound);
6331 Builder.CreateStore(UpperBound, PUpperBound);
6332 Builder.CreateStore(One, PStride);
6336 uint32_t SrcLocStrSize;
6339 if (DistScheduleSchedType != OMPScheduleType::None) {
6340 Flag |= OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6345 auto BuildInitCall = [StaticInit, SrcLoc, ThreadNum, PLastIter, PLowerBound,
6346 PUpperBound, PStride, One,
6347 this](
Value *SchedulingType,
Value *ChunkSize,
6350 StaticInit, {SrcLoc, ThreadNum,
6351 SchedulingType, PLastIter,
6352 PLowerBound, PUpperBound,
6356 BuildInitCall(SchedulingType, CastedChunkSize,
Builder);
6357 if (DistScheduleSchedType != OMPScheduleType::None &&
6358 SchedType != OMPScheduleType::OrderedDistributeChunked &&
6359 SchedType != OMPScheduleType::OrderedDistribute) {
6363 BuildInitCall(DistSchedulingType, CastedDistScheduleChunkSize,
Builder);
6367 Value *FirstChunkStart =
6368 Builder.CreateLoad(InternalIVTy, PLowerBound,
"omp_firstchunk.lb");
6369 Value *FirstChunkStop =
6370 Builder.CreateLoad(InternalIVTy, PUpperBound,
"omp_firstchunk.ub");
6371 Value *FirstChunkEnd =
Builder.CreateAdd(FirstChunkStop, One);
6373 Builder.CreateSub(FirstChunkEnd, FirstChunkStart,
"omp_chunk.range");
6374 Value *NextChunkStride =
6375 Builder.CreateLoad(InternalIVTy, PStride,
"omp_dispatch.stride");
6379 Value *DispatchCounter;
6387 DispatchCounter = Counter;
6390 FirstChunkStart, CastedTripCount, NextChunkStride,
6413 Value *ChunkEnd =
Builder.CreateAdd(DispatchCounter, ChunkRange);
6414 Value *IsLastChunk =
6415 Builder.CreateICmpUGE(ChunkEnd, CastedTripCount,
"omp_chunk.is_last");
6416 Value *CountUntilOrigTripCount =
6417 Builder.CreateSub(CastedTripCount, DispatchCounter);
6419 IsLastChunk, CountUntilOrigTripCount, ChunkRange,
"omp_chunk.tripcount");
6420 Value *BackcastedChunkTC =
6421 Builder.CreateTrunc(ChunkTripCount, IVTy,
"omp_chunk.tripcount.trunc");
6422 CLI->setTripCount(BackcastedChunkTC);
6427 Value *BackcastedDispatchCounter =
6428 Builder.CreateTrunc(DispatchCounter, IVTy,
"omp_dispatch.iv.trunc");
6429 CLI->mapIndVar([&](Instruction *) ->
Value * {
6431 return Builder.CreateAdd(
IV, BackcastedDispatchCounter);
6444 return AfterIP.takeError();
6459static FunctionCallee
6462 unsigned Bitwidth = Ty->getIntegerBitWidth();
6465 case WorksharingLoopType::ForStaticLoop:
6468 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_4u);
6471 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_8u);
6473 case WorksharingLoopType::DistributeStaticLoop:
6476 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_4u);
6479 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_8u);
6481 case WorksharingLoopType::DistributeForStaticLoop:
6484 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_4u);
6487 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_8u);
6490 if (Bitwidth != 32 && Bitwidth != 64) {
6502 Function &LoopBodyFn,
bool NoLoop) {
6513 if (LoopType == WorksharingLoopType::DistributeStaticLoop) {
6514 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6515 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6516 Builder.restoreIP({InsertBlock, std::prev(InsertBlock->
end())});
6521 M, omp::RuntimeFunction::OMPRTL_omp_get_num_threads);
6522 Builder.restoreIP({InsertBlock, std::prev(InsertBlock->
end())});
6526 Builder.CreateZExtOrTrunc(NumThreads, TripCountTy,
"num.threads.cast"));
6527 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6528 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
6529 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6530 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), NoLoop));
6532 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6556 Builder.restoreIP({Preheader, Preheader->
end()});
6559 Builder.CreateBr(CLI->
getExit());
6567 CleanUpInfo.
collectBlocks(RegionBlockSet, BlocksToBeRemoved);
6575 "Expected unique undroppable user of outlined function");
6577 assert(OutlinedFnCallInstruction &&
"Expected outlined function call");
6579 "Expected outlined function call to be located in loop preheader");
6581 if (OutlinedFnCallInstruction->
arg_size() > 1)
6588 LoopBodyArg, TripCount, OutlinedFn, NoLoop);
6590 for (
auto &ToBeDeletedItem : ToBeDeleted)
6591 ToBeDeletedItem->eraseFromParent();
6598 uint32_t SrcLocStrSize;
6602 case WorksharingLoopType::ForStaticLoop:
6603 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6605 case WorksharingLoopType::DistributeStaticLoop:
6606 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6608 case WorksharingLoopType::DistributeForStaticLoop:
6609 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
6614 auto OI = std::make_unique<OutlineInfo>();
6619 SmallVector<Instruction *, 4> ToBeDeleted;
6621 OI->OuterAllocBB = AllocaIP.getBlock();
6644 SmallPtrSet<BasicBlock *, 32> ParallelRegionBlockSet;
6646 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
6648 CodeExtractorAnalysisCache CEAC(*OuterFn);
6649 CodeExtractor Extractor(Blocks,
6663 SetVector<Value *> SinkingCands, HoistingCands;
6667 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
6674 for (
auto Use :
Users) {
6676 if (ParallelRegionBlockSet.
count(Inst->getParent())) {
6677 Inst->replaceUsesOfWith(CLI->
getIndVar(), NewLoopCntLoad);
6683 OI->ExcludeArgsFromAggregate.push_back(NewLoopCntLoad);
6690 OI->PostOutlineCB = [=, ToBeDeletedVec =
6691 std::move(ToBeDeleted)](
Function &OutlinedFn) {
6701 bool NeedsBarrier, omp::ScheduleKind SchedKind,
Value *ChunkSize,
6702 bool HasSimdModifier,
bool HasMonotonicModifier,
6703 bool HasNonmonotonicModifier,
bool HasOrderedClause,
6705 Value *DistScheduleChunkSize) {
6706 if (
Config.isTargetDevice())
6707 return applyWorkshareLoopTarget(
DL, CLI, AllocaIP, LoopType, NoLoop);
6709 SchedKind, ChunkSize, HasSimdModifier, HasMonotonicModifier,
6710 HasNonmonotonicModifier, HasOrderedClause, DistScheduleChunkSize);
6712 bool IsOrdered = (EffectiveScheduleType & OMPScheduleType::ModifierOrdered) ==
6713 OMPScheduleType::ModifierOrdered;
6715 if (HasDistSchedule) {
6716 DistScheduleSchedType = DistScheduleChunkSize
6717 ? OMPScheduleType::OrderedDistributeChunked
6718 : OMPScheduleType::OrderedDistribute;
6720 switch (EffectiveScheduleType & ~OMPScheduleType::ModifierMask) {
6721 case OMPScheduleType::BaseStatic:
6722 case OMPScheduleType::BaseDistribute:
6723 assert((!ChunkSize || !DistScheduleChunkSize) &&
6724 "No chunk size with static-chunked schedule");
6725 if (IsOrdered && !HasDistSchedule)
6726 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6727 NeedsBarrier, ChunkSize);
6729 if (DistScheduleChunkSize)
6730 return applyStaticChunkedWorkshareLoop(
6731 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6732 DistScheduleChunkSize, DistScheduleSchedType);
6733 return applyStaticWorkshareLoop(
DL, CLI, AllocaIP, LoopType, NeedsBarrier,
6736 case OMPScheduleType::BaseStaticChunked:
6737 case OMPScheduleType::BaseDistributeChunked:
6738 if (IsOrdered && !HasDistSchedule)
6739 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6740 NeedsBarrier, ChunkSize);
6742 return applyStaticChunkedWorkshareLoop(
6743 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6744 DistScheduleChunkSize, DistScheduleSchedType);
6746 case OMPScheduleType::BaseRuntime:
6747 case OMPScheduleType::BaseAuto:
6748 case OMPScheduleType::BaseGreedy:
6749 case OMPScheduleType::BaseBalanced:
6750 case OMPScheduleType::BaseSteal:
6751 case OMPScheduleType::BaseRuntimeSimd:
6753 "schedule type does not support user-defined chunk sizes");
6755 case OMPScheduleType::BaseGuidedSimd:
6756 case OMPScheduleType::BaseDynamicChunked:
6757 case OMPScheduleType::BaseGuidedChunked:
6758 case OMPScheduleType::BaseGuidedIterativeChunked:
6759 case OMPScheduleType::BaseGuidedAnalyticalChunked:
6760 case OMPScheduleType::BaseStaticBalancedChunked:
6761 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6762 NeedsBarrier, ChunkSize);
6775 unsigned Bitwidth = Ty->getIntegerBitWidth();
6778 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_4u);
6781 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_8u);
6789static FunctionCallee
6791 unsigned Bitwidth = Ty->getIntegerBitWidth();
6794 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_4u);
6797 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_8u);
6804static FunctionCallee
6806 unsigned Bitwidth = Ty->getIntegerBitWidth();
6809 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_4u);
6812 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_8u);
6817OpenMPIRBuilder::applyDynamicWorkshareLoop(
DebugLoc DL, CanonicalLoopInfo *CLI,
6820 bool NeedsBarrier,
Value *Chunk) {
6821 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6823 "Require dedicated allocate IP");
6825 "Require valid schedule type");
6827 bool Ordered = (SchedType & OMPScheduleType::ModifierOrdered) ==
6828 OMPScheduleType::ModifierOrdered;
6833 uint32_t SrcLocStrSize;
6840 Type *IVTy =
IV->getType();
6845 Builder.SetInsertPoint(AllocaIP.getBlock()->getFirstNonPHIOrDbgOrAlloca());
6847 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6848 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
6849 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
6850 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
6859 Constant *One = ConstantInt::get(IVTy, 1);
6860 Builder.CreateStore(One, PLowerBound);
6862 Builder.CreateStore(UpperBound, PUpperBound);
6863 Builder.CreateStore(One, PStride);
6881 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6893 Builder.SetInsertPoint(OuterCond, OuterCond->getFirstInsertionPt());
6896 {SrcLoc, ThreadNum, PLastIter, PLowerBound, PUpperBound, PStride});
6897 Constant *Zero32 = ConstantInt::get(I32Type, 0);
6900 Builder.CreateSub(
Builder.CreateLoad(IVTy, PLowerBound), One,
"lb");
6901 Builder.CreateCondBr(MoreWork, Header, Exit);
6907 PI->setIncomingBlock(0, OuterCond);
6913 Br->setSuccessor(OuterCond);
6919 UpperBound =
Builder.CreateLoad(IVTy, PUpperBound,
"ub");
6922 CI->setOperand(1, UpperBound);
6926 assert(BI->getSuccessor(1) == Exit);
6927 BI->setSuccessor(1, OuterCond);
6941 omp::Directive::OMPD_for,
false,
6944 return BarrierIP.takeError();
6996 assert(
Loops.size() >= 1 &&
"At least one loop required");
6997 size_t NumLoops =
Loops.size();
7001 return Loops.front();
7013 Loop->collectControlBlocks(OldControlBBs);
7017 if (ComputeIP.
isSet())
7024 Value *CollapsedTripCount =
nullptr;
7027 "All loops to collapse must be valid canonical loops");
7028 Value *OrigTripCount = L->getTripCount();
7029 if (!CollapsedTripCount) {
7030 CollapsedTripCount = OrigTripCount;
7035 CollapsedTripCount =
7036 Builder.CreateNUWMul(CollapsedTripCount, OrigTripCount);
7042 OrigPreheader->
getNextNode(), OrigAfter,
"collapsed",
7049 Builder.restoreIP(Result->getBodyIP());
7051 Value *Leftover = Result->getIndVar();
7053 NewIndVars.
resize(NumLoops);
7054 for (
int i = NumLoops - 1; i >= 1; --i) {
7055 Value *OrigTripCount =
Loops[i]->getTripCount();
7057 Value *NewIndVar =
Builder.CreateURem(Leftover, OrigTripCount);
7058 NewIndVars[i] = NewIndVar;
7060 Leftover =
Builder.CreateUDiv(Leftover, OrigTripCount);
7063 NewIndVars[0] = Leftover;
7072 BasicBlock *ContinueBlock = Result->getBody();
7074 auto ContinueWith = [&ContinueBlock, &ContinuePred,
DL](
BasicBlock *Dest,
7081 ContinueBlock =
nullptr;
7082 ContinuePred = NextSrc;
7089 for (
size_t i = 0; i < NumLoops - 1; ++i)
7090 ContinueWith(
Loops[i]->getBody(),
Loops[i + 1]->getHeader());
7096 for (
size_t i = NumLoops - 1; i > 0; --i)
7097 ContinueWith(
Loops[i]->getAfter(),
Loops[i - 1]->getLatch());
7100 ContinueWith(Result->getLatch(),
nullptr);
7107 for (
size_t i = 0; i < NumLoops; ++i)
7108 Loops[i]->getIndVar()->replaceAllUsesWith(NewIndVars[i]);
7122std::vector<CanonicalLoopInfo *>
7126 "Must pass as many tile sizes as there are loops");
7127 int NumLoops =
Loops.size();
7128 assert(NumLoops >= 1 &&
"At least one loop to tile required");
7140 Loop->collectControlBlocks(OldControlBBs);
7148 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7149 OrigTripCounts.
push_back(L->getTripCount());
7160 for (
int i = 0; i < NumLoops - 1; ++i) {
7173 for (
int i = 0; i < NumLoops; ++i) {
7175 Value *OrigTripCount = OrigTripCounts[i];
7188 Value *FloorTripOverflow =
7189 Builder.CreateICmpNE(FloorTripRem, ConstantInt::get(IVType, 0));
7191 FloorTripOverflow =
Builder.CreateZExt(FloorTripOverflow, IVType);
7192 Value *FloorTripCount =
7193 Builder.CreateAdd(FloorCompleteTripCount, FloorTripOverflow,
7194 "omp_floor" +
Twine(i) +
".tripcount",
true);
7197 FloorCompleteCount.
push_back(FloorCompleteTripCount);
7203 std::vector<CanonicalLoopInfo *> Result;
7204 Result.reserve(NumLoops * 2);
7217 auto EmbeddNewLoop =
7218 [
this,
DL,
F, InnerEnter, &Enter, &
Continue, &OutroInsertBefore](
7221 DL, TripCount,
F, InnerEnter, OutroInsertBefore, Name);
7226 Enter = EmbeddedLoop->
getBody();
7228 OutroInsertBefore = EmbeddedLoop->
getLatch();
7229 return EmbeddedLoop;
7233 const Twine &NameBase) {
7236 EmbeddNewLoop(
P.value(), NameBase +
Twine(
P.index()));
7237 Result.push_back(EmbeddedLoop);
7241 EmbeddNewLoops(FloorCount,
"floor");
7247 for (
int i = 0; i < NumLoops; ++i) {
7251 Value *FloorIsEpilogue =
7253 Value *TileTripCount =
7260 EmbeddNewLoops(TileCounts,
"tile");
7265 for (std::pair<BasicBlock *, BasicBlock *>
P : InbetweenCode) {
7274 BodyEnter =
nullptr;
7275 BodyEntered = ExitBB;
7287 Builder.restoreIP(Result.back()->getBodyIP());
7288 for (
int i = 0; i < NumLoops; ++i) {
7291 Value *OrigIndVar = OrigIndVars[i];
7342 assert(
Loop->isValid() &&
"Expecting a valid CanonicalLoopInfo");
7346 assert(Latch &&
"A valid CanonicalLoopInfo must have a unique latch");
7354 if (
I.mayReadOrWriteMemory()) {
7358 I.setMetadata(LLVMContext::MD_access_group,
AccessGroup);
7372 Loop->collectControlBlocks(oldControlBBs);
7377 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7378 origTripCounts.
push_back(L->getTripCount());
7387 Builder.SetInsertPoint(TCBlock);
7388 Value *fusedTripCount =
nullptr;
7390 assert(L->isValid() &&
"All loops to fuse must be valid canonical loops");
7391 Value *origTripCount = L->getTripCount();
7392 if (!fusedTripCount) {
7393 fusedTripCount = origTripCount;
7396 Value *condTP =
Builder.CreateICmpSGT(fusedTripCount, origTripCount);
7397 fusedTripCount =
Builder.CreateSelect(condTP, fusedTripCount, origTripCount,
7411 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7412 Loops[i]->getPreheader()->moveBefore(TCBlock);
7413 Loops[i]->getAfter()->moveBefore(TCBlock);
7417 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7429 for (
size_t i = 0; i <
Loops.size(); ++i) {
7431 F->getContext(),
"omp.fused.inner.cond",
F,
Loops[i]->getBody());
7432 Builder.SetInsertPoint(condBlock);
7440 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7441 Builder.SetInsertPoint(condBBs[i]);
7442 Builder.CreateCondBr(condValues[i],
Loops[i]->getBody(), condBBs[i + 1]);
7458 "omp.fused.pre_latch");
7491 const Twine &NamePrefix) {
7520 C, NamePrefix +
".if.then",
Cond->getParent(),
Cond->getNextNode());
7522 C, NamePrefix +
".if.else",
Cond->getParent(), CanonicalLoop->
getExit());
7525 Builder.SetInsertPoint(SplitBeforeIt);
7527 Builder.CreateCondBr(IfCond, ThenBlock, ElseBlock);
7530 spliceBB(IP, ThenBlock,
false, Builder.getCurrentDebugLocation());
7533 Builder.SetInsertPoint(ElseBlock);
7539 ExistingBlocks.
reserve(L->getNumBlocks() + 1);
7541 ExistingBlocks.
append(L->block_begin(), L->block_end());
7547 assert(LoopCond && LoopHeader &&
"Invalid loop structure");
7549 if (
Block == L->getLoopPreheader() ||
Block == L->getLoopLatch() ||
7556 if (
Block == ThenBlock)
7557 NewBB->
setName(NamePrefix +
".if.else");
7560 VMap[
Block] = NewBB;
7568 L->getLoopLatch()->splitBasicBlockBefore(
L->getLoopLatch()->begin(),
7569 NamePrefix +
".pre_latch");
7573 L->addBasicBlockToLoop(ThenBlock, LI);
7579 if (TargetTriple.
isX86()) {
7580 if (Features.
lookup(
"avx512f"))
7582 else if (Features.
lookup(
"avx"))
7586 if (TargetTriple.
isPPC())
7588 if (TargetTriple.
isWasm())
7597 Value *IfCond, OrderKind Order,
7607 if (!BB.hasTerminator())
7623 I->eraseFromParent();
7626 if (AlignedVars.
size()) {
7628 for (
auto &AlignedItem : AlignedVars) {
7629 Value *AlignedPtr = AlignedItem.first;
7633 Builder.CreateAlignmentAssumption(
F->getDataLayout(), AlignedPtr,
7641 createIfVersion(CanonicalLoop, IfCond, VMap, LIA, LI, L,
"simd");
7654 Reachable.insert(
Block);
7664 if ((Safelen ==
nullptr) || (Order == OrderKind::OMP_ORDER_concurrent))
7680 if (Simdlen || Safelen) {
7684 ConstantInt *VectorizeWidth = Simdlen ==
nullptr ? Safelen : Simdlen;
7710static std::unique_ptr<TargetMachine>
7714 StringRef CPU =
F->getFnAttribute(
"target-cpu").getValueAsString();
7715 StringRef Features =
F->getFnAttribute(
"target-features").getValueAsString();
7726 std::nullopt, OptLevel));
7744 if (!BB.hasTerminator())
7757 [&](
const Function &
F) {
return TM->getTargetTransformInfo(
F); });
7758 FAM.registerPass([&]() {
return TIRA; });
7772 I->eraseFromParent();
7775 assert(L &&
"Expecting CanonicalLoopInfo to be recognized as a loop");
7780 nullptr, ORE,
static_cast<int>(OptLevel),
7800 <<
" Threshold=" << UP.
Threshold <<
"\n"
7803 <<
" PartialOptSizeThreshold="
7823 Ptr =
Load->getPointerOperand();
7825 Ptr =
Store->getPointerOperand();
7832 if (Alloca->getParent() == &
F->getEntryBlock())
7852 int MaxTripCount = 0;
7853 bool MaxOrZero =
false;
7854 unsigned TripMultiple = 0;
7858 MaxTripCount, MaxOrZero, TripMultiple, UCE, UP, PP);
7859 LLVM_DEBUG(
dbgs() <<
"Suggesting unroll factor of " << Factor <<
"\n");
7870 assert(Factor >= 0 &&
"Unroll factor must not be negative");
7886 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst}));
7899 *UnrolledCLI =
Loop;
7904 "unrolling only makes sense with a factor of 2 or larger");
7906 Type *IndVarTy =
Loop->getIndVarType();
7913 std::vector<CanonicalLoopInfo *>
LoopNest =
7928 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst})});
7931 (*UnrolledCLI)->assertOK();
7949 Value *Args[] = {Ident, ThreadId, BufSize, CpyBuf, CpyFn, DidItLD};
7968 if (!CPVars.
empty()) {
7973 Directive OMPD = Directive::OMPD_single;
7978 Value *Args[] = {Ident, ThreadId};
7987 if (
Error Err = FiniCB(IP))
8008 EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCBWrapper,
8015 for (
size_t I = 0, E = CPVars.
size();
I < E; ++
I)
8018 ConstantInt::get(Int64, 0), CPVars[
I],
8021 }
else if (!IsNowait) {
8024 omp::Directive::OMPD_unknown,
false,
8042 Directive::OMPD_scope,
nullptr,
nullptr,
8043 BodyGenCB, FiniCB,
false,
true,
8051 omp::Directive::OMPD_unknown,
8067 Directive OMPD = Directive::OMPD_critical;
8072 Value *LockVar = getOMPCriticalRegionLock(CriticalName);
8073 Value *Args[] = {Ident, ThreadId, LockVar};
8090 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
8098 const Twine &Name,
bool IsDependSource) {
8102 "OpenMP runtime requires depend vec with i64 type");
8115 for (
unsigned I = 0;
I < NumLoops; ++
I) {
8129 Value *Args[] = {Ident, ThreadId, DependBaseAddrGEP};
8147 Directive OMPD = Directive::OMPD_ordered_blockassoc;
8156 Value *Args[] = {Ident, ThreadId};
8166 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
8173 bool HasFinalize,
bool IsCancellable) {
8180 BasicBlock *EntryBB = Builder.GetInsertBlock();
8189 emitCommonDirectiveEntry(OMPD, EntryCall, ExitBB, Conditional);
8201 "Unexpected control flow graph state!!");
8203 emitCommonDirectiveExit(OMPD, FinIP, ExitCall, HasFinalize);
8205 return AfterIP.takeError();
8210 "Unexpected Insertion point location!");
8213 auto InsertBB = merged ? ExitPredBB : ExitBB;
8216 Builder.SetInsertPoint(InsertBB);
8218 return Builder.saveIP();
8222 Directive OMPD,
Value *EntryCall, BasicBlock *ExitBB,
bool Conditional) {
8224 if (!Conditional || !EntryCall)
8230 auto *UI =
new UnreachableInst(
Builder.getContext(), ThenBB);
8240 Builder.CreateCondBr(CallBool, ThenBB, ExitBB);
8244 UI->eraseFromParent();
8252 omp::Directive OMPD,
InsertPointTy FinIP, Instruction *ExitCall,
8260 "Unexpected finalization stack state!");
8263 assert(Fi.DK == OMPD &&
"Unexpected Directive for Finalization call!");
8265 if (
Error Err = Fi.mergeFiniBB(
Builder, FinIP.getBlock()))
8266 return std::move(Err);
8270 Builder.SetInsertPoint(FinIP.getBlock()->getTerminator());
8280 return IRBuilder<>::InsertPoint(ExitCall->
getParent(),
8314 "copyin.not.master.end");
8321 Builder.SetInsertPoint(OMP_Entry);
8324 Value *cmp =
Builder.CreateICmpNE(MasterPtr, PrivatePtr);
8325 Builder.CreateCondBr(cmp, CopyBegin, CopyEnd);
8327 Builder.SetInsertPoint(CopyBegin);
8345 Value *Args[] = {ThreadId,
Size, Allocator};
8368 return Builder.CreateCall(Fn, Args, Name);
8382 Value *Args[] = {ThreadId, Addr, Allocator};
8389 const Twine &Name) {
8397 M.getContext(),
M.getDataLayout().getPrefTypeAlign(Int64)));
8403 const Twine &Name) {
8405 Loc,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)), Name);
8410 const Twine &Name) {
8416 return Builder.CreateCall(Fn, Args, Name);
8421 const Twine &Name) {
8423 Loc, Addr,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)),
8430 Value *DependenceAddress,
bool HaveNowaitClause) {
8440 else if (
Device->getType() != Int32)
8443 if (NumDependences ==
nullptr) {
8444 NumDependences = ConstantInt::get(Int32, 0);
8448 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8450 Ident, ThreadId, InteropVar, InteropTypeVal,
8451 Device, NumDependences, DependenceAddress, HaveNowaitClauseVal};
8460 Value *NumDependences,
Value *DependenceAddress,
bool HaveNowaitClause) {
8470 else if (
Device->getType() != Int32)
8472 if (NumDependences ==
nullptr) {
8473 NumDependences = ConstantInt::get(Int32, 0);
8477 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8479 Ident, ThreadId, InteropVar,
Device,
8480 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8489 Value *NumDependences,
8490 Value *DependenceAddress,
8491 bool HaveNowaitClause) {
8500 else if (
Device->getType() != Int32)
8502 if (NumDependences ==
nullptr) {
8503 NumDependences = ConstantInt::get(Int32, 0);
8507 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8509 Ident, ThreadId, InteropVar,
Device,
8510 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8540 assert(!Attrs.MaxThreads.empty() && !Attrs.MaxTeams.empty() &&
8541 "expected num_threads and num_teams to be specified");
8561 const std::string DebugPrefix =
"_debug__";
8562 if (KernelName.
ends_with(DebugPrefix)) {
8563 KernelName = KernelName.
drop_back(DebugPrefix.length());
8564 Kernel =
M.getFunction(KernelName);
8570 if (Attrs.MinTeams.front() > 1 || Attrs.MaxTeams.front() > 0)
8572 Attrs.MaxTeams.front());
8576 int32_t MaxThreadsVal = Attrs.MaxThreads.front();
8581 Attrs.MinThreads.front());
8583 MaxThreadsVal = Attrs.MinThreads.front();
8587 if (MaxThreadsVal > 0)
8600 omp::RuntimeFunction::OMPRTL___kmpc_target_init);
8603 Twine DynamicEnvironmentName = KernelName +
"_dynamic_environment";
8604 Constant *DynamicEnvironmentInitializer =
8608 DynamicEnvironmentInitializer, DynamicEnvironmentName,
8610 DL.getDefaultGlobalsAddressSpace());
8614 DynamicEnvironmentGV->
getType() == DynamicEnvironmentPtr
8615 ? DynamicEnvironmentGV
8617 DynamicEnvironmentPtr);
8620 ConfigurationEnvironment, {
8621 UseGenericStateMachineVal,
8622 MayUseNestedParallelismVal,
8631 KernelEnvironment, {
8632 ConfigurationEnvironmentInitializer,
8636 std::string KernelEnvironmentName =
8637 (KernelName +
"_kernel_environment").str();
8640 KernelEnvironmentInitializer, KernelEnvironmentName,
8642 DL.getDefaultGlobalsAddressSpace());
8646 KernelEnvironmentGV->
getType() == KernelEnvironmentPtr
8647 ? KernelEnvironmentGV
8649 KernelEnvironmentPtr);
8650 Value *KernelLaunchEnvironment =
8653 KernelLaunchEnvironment =
8654 KernelLaunchEnvironment->
getType() == KernelLaunchEnvParamTy
8655 ? KernelLaunchEnvironment
8656 :
Builder.CreateAddrSpaceCast(KernelLaunchEnvironment,
8657 KernelLaunchEnvParamTy);
8659 Fn, {KernelEnvironment, KernelLaunchEnvironment});
8671 auto *UI =
Builder.CreateUnreachable();
8677 Builder.SetInsertPoint(WorkerExitBB);
8681 Builder.SetInsertPoint(CheckBBTI);
8682 Builder.CreateCondBr(ExecUserCode, UI->getParent(), WorkerExitBB);
8684 CheckBBTI->eraseFromParent();
8685 UI->eraseFromParent();
8693 int32_t TeamsReductionDataSize) {
8698 omp::RuntimeFunction::OMPRTL___kmpc_target_deinit);
8702 if (!TeamsReductionDataSize)
8708 const std::string DebugPrefix =
"_debug__";
8710 KernelName = KernelName.
drop_back(DebugPrefix.length());
8711 auto *KernelEnvironmentGV =
8712 M.getNamedGlobal((KernelName +
"_kernel_environment").str());
8713 assert(KernelEnvironmentGV &&
"Expected kernel environment global\n");
8714 auto *KernelEnvironmentInitializer = KernelEnvironmentGV->getInitializer();
8716 KernelEnvironmentInitializer,
8717 ConstantInt::get(Int32, TeamsReductionDataSize), {0, 7});
8718 KernelEnvironmentGV->setInitializer(NewInitializer);
8723 if (
Kernel.hasFnAttribute(Name)) {
8724 int32_t OldLimit =
Kernel.getFnAttributeAsParsedInteger(Name);
8730std::pair<int32_t, int32_t>
8732 int32_t ThreadLimit =
8733 Kernel.getFnAttributeAsParsedInteger(
"omp_target_thread_limit");
8736 const auto &Attr =
Kernel.getFnAttribute(
"amdgpu-flat-work-group-size");
8737 if (!Attr.isValid() || !Attr.isStringAttribute())
8738 return {0, ThreadLimit};
8739 auto [LBStr, UBStr] = Attr.getValueAsString().split(
',');
8742 return {0, ThreadLimit};
8743 UB = ThreadLimit ? std::min(ThreadLimit, UB) : UB;
8751 return {0, ThreadLimit ? std::min(ThreadLimit, UB) : UB};
8753 return {0, ThreadLimit};
8759 Kernel.addFnAttr(
"omp_target_thread_limit", std::to_string(UB));
8762 Kernel.addFnAttr(
"amdgpu-flat-work-group-size",
8770std::pair<int32_t, int32_t>
8773 return {0,
Kernel.getFnAttributeAsParsedInteger(
"omp_target_num_teams")};
8777 int32_t LB, int32_t UB) {
8785 Kernel.addFnAttr(
"omp_target_num_teams", std::to_string(LB));
8788void OpenMPIRBuilder::setOutlinedTargetRegionFunctionAttributes(
8797 else if (
T.isNVPTX())
8799 else if (
T.isSPIRV())
8805 StringRef EntryFnIDName) {
8806 if (
Config.isTargetDevice()) {
8807 assert(OutlinedFn &&
"The outlined function must exist if embedded");
8811 return new GlobalVariable(
8816Constant *OpenMPIRBuilder::createTargetRegionEntryAddr(
Function *OutlinedFn,
8817 StringRef EntryFnName) {
8821 assert(!
M.getGlobalVariable(EntryFnName,
true) &&
8822 "Named kernel already exists?");
8823 return new GlobalVariable(
8836 if (
Config.isTargetDevice() || !
Config.openMPOffloadMandatory()) {
8840 OutlinedFn = *CBResult;
8842 OutlinedFn =
nullptr;
8848 if (!IsOffloadEntry)
8851 std::string EntryFnIDName =
8853 ? std::string(EntryFnName)
8857 EntryFnName, EntryFnIDName);
8865 setOutlinedTargetRegionFunctionAttributes(OutlinedFn);
8866 auto OutlinedFnID = createOutlinedFunctionID(OutlinedFn, EntryFnIDName);
8867 auto EntryAddr = createTargetRegionEntryAddr(OutlinedFn, EntryFnName);
8869 EntryInfo, EntryAddr, OutlinedFnID,
8871 return OutlinedFnID;
8889 bool IsStandAlone = !BodyGenCB;
8896 MapInfo = &GenMapInfoCB(
Builder.saveIP());
8898 AllocaIP,
Builder.saveIP(), *MapInfo, Info, CustomMapperCB,
8899 true, DeviceAddrCB))
8906 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
8916 SrcLocInfo, DeviceID,
8923 assert(MapperFunc &&
"MapperFunc missing for standalone target data");
8927 if (Info.HasNoWait) {
8937 if (Info.HasNoWait) {
8941 emitBlock(OffloadContBlock, CurFn,
true);
8947 bool RequiresOuterTargetTask = Info.HasNoWait;
8948 if (!RequiresOuterTargetTask)
8949 cantFail(TaskBodyCB(
nullptr,
nullptr,
8953 {}, RTArgs, Info.HasNoWait));
8956 omp::OMPRTL___tgt_target_data_begin_mapper);
8960 for (
auto DeviceMap : Info.DevicePtrInfoMap) {
8964 Builder.CreateStore(LI, DeviceMap.second.second);
9001 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
9010 Value *OffloadingArgs[] = {SrcLocInfo, DeviceID,
9033 return emitIfClause(IfCond, BeginThenGen, BeginElseGen, AllocaIP);
9034 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9049 return emitIfClause(IfCond, EndThenGen, EndElseGen, AllocaIP);
9050 return EndThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9053 return emitIfClause(IfCond, BeginThenGen, EndElseGen, AllocaIP);
9054 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9065 bool IsGPUDistribute) {
9066 assert((IVSize == 32 || IVSize == 64) &&
9067 "IV size is not compatible with the omp runtime");
9069 if (IsGPUDistribute)
9071 ? (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_4
9072 : omp::OMPRTL___kmpc_distribute_static_init_4u)
9073 : (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_8
9074 : omp::OMPRTL___kmpc_distribute_static_init_8u);
9076 Name = IVSize == 32 ? (IVSigned ? omp::OMPRTL___kmpc_for_static_init_4
9077 : omp::OMPRTL___kmpc_for_static_init_4u)
9078 : (IVSigned ? omp::OMPRTL___kmpc_for_static_init_8
9079 : omp::OMPRTL___kmpc_for_static_init_8u);
9086 assert((IVSize == 32 || IVSize == 64) &&
9087 "IV size is not compatible with the omp runtime");
9089 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_4
9090 : omp::OMPRTL___kmpc_dispatch_init_4u)
9091 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_8
9092 : omp::OMPRTL___kmpc_dispatch_init_8u);
9099 assert((IVSize == 32 || IVSize == 64) &&
9100 "IV size is not compatible with the omp runtime");
9102 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_4
9103 : omp::OMPRTL___kmpc_dispatch_next_4u)
9104 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_8
9105 : omp::OMPRTL___kmpc_dispatch_next_8u);
9112 assert((IVSize == 32 || IVSize == 64) &&
9113 "IV size is not compatible with the omp runtime");
9115 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_4
9116 : omp::OMPRTL___kmpc_dispatch_fini_4u)
9117 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_8
9118 : omp::OMPRTL___kmpc_dispatch_fini_8u);
9129 DenseMap<
Value *, std::tuple<Value *, unsigned>> &ValueReplacementMap) {
9137 auto GetUpdatedDIVariable = [&](
DILocalVariable *OldVar,
unsigned arg) {
9141 if (NewVar && (arg == NewVar->
getArg()))
9151 auto UpdateDebugRecord = [&](
auto *DR) {
9154 for (
auto Loc : DR->location_ops()) {
9155 auto Iter = ValueReplacementMap.find(
Loc);
9156 if (Iter != ValueReplacementMap.end()) {
9157 DR->replaceVariableLocationOp(
Loc, std::get<0>(Iter->second));
9158 ArgNo = std::get<1>(Iter->second) + 1;
9162 DR->setVariable(GetUpdatedDIVariable(OldVar, ArgNo));
9167 if (DVR->getNumVariableLocationOps() != 1u) {
9168 DVR->setKillLocation();
9171 Value *
Loc = DVR->getVariableLocationOp(0u);
9178 RequiredBB = &DVR->getFunction()->getEntryBlock();
9180 if (RequiredBB && RequiredBB != CurBB) {
9192 "Unexpected debug intrinsic");
9194 UpdateDebugRecord(&DVR);
9195 MoveDebugRecordToCorrectBlock(&DVR);
9198 for (
auto *DVR : DVRsToDelete)
9199 DVR->getMarker()->MarkedInstr->dropOneDbgRecord(DVR);
9203 Module *M = Func->getParent();
9206 DB.createQualifiedType(dwarf::DW_TAG_pointer_type,
nullptr);
9207 unsigned ArgNo = Func->arg_size();
9209 NewSP,
"dyn_ptr", ArgNo, NewSP->
getFile(), 0, VoidPtrTy,
9210 false, DINode::DIFlags::FlagArtificial);
9212 Argument *LastArg = Func->getArg(Func->arg_size() - 1);
9213 DB.insertDeclare(LastArg, Var, DB.createExpression(),
Loc,
9235 for (
auto &Arg : Inputs)
9236 ParameterTypes.
push_back(Arg->getType()->isPointerTy()
9240 for (
auto &Arg : Inputs)
9241 ParameterTypes.
push_back(Arg->getType());
9249 auto BB = Builder.GetInsertBlock();
9250 auto M = BB->getModule();
9261 if (TargetCpuAttr.isStringAttribute())
9262 Func->addFnAttr(TargetCpuAttr);
9264 auto TargetFeaturesAttr = ParentFn->
getFnAttribute(
"target-features");
9265 if (TargetFeaturesAttr.isStringAttribute())
9266 Func->addFnAttr(TargetFeaturesAttr);
9271 OMPBuilder.
emitUsed(
"llvm.compiler.used", {ExecMode});
9281 Builder.SetCurrentDebugLocation(OutlinedFnLoc);
9285 Builder.SetInsertPoint(EntryBB);
9291 BasicBlock *UserCodeEntryBB = Builder.GetInsertBlock();
9301 splitBB(Builder,
true,
"outlined.body");
9308 Builder.SetInsertPoint(ExitBB);
9315 Builder.CreateRetVoid();
9319 auto AllocaIP = Builder.saveIP();
9324 const auto &ArgRange =
make_range(Func->arg_begin(), Func->arg_end() - 1);
9356 if (Instr->getFunction() == Func)
9357 Instr->replaceUsesOfWith(
Input, InputCopy);
9363 for (
auto InArg :
zip(Inputs, ArgRange)) {
9365 Argument &Arg = std::get<1>(InArg);
9366 Value *InputCopy =
nullptr;
9369 Arg,
Input, InputCopy, AllocaIP, Builder.saveIP(),
9373 Builder.restoreIP(*AfterIP);
9374 ValueReplacementMap[
Input] = std::make_tuple(InputCopy, Arg.
getArgNo());
9394 DeferredReplacement.push_back(std::make_pair(
Input, InputCopy));
9401 ReplaceValue(
Input, InputCopy, Func);
9405 for (
auto Deferred : DeferredReplacement)
9406 ReplaceValue(std::get<0>(Deferred), std::get<1>(Deferred), Func);
9409 ValueReplacementMap);
9417 Value *TaskWithPrivates,
9418 Type *TaskWithPrivatesTy) {
9420 Type *TaskTy = OMPIRBuilder.Task;
9423 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 0);
9424 Value *Shareds = TaskT;
9434 if (TaskWithPrivatesTy != TaskTy)
9435 Shareds = Builder.CreateStructGEP(TaskTy, TaskT, 0);
9452 const size_t NumOffloadingArrays,
const int SharedArgsOperandNo) {
9457 assert((!NumOffloadingArrays || PrivatesTy) &&
9458 "PrivatesTy cannot be nullptr when there are offloadingArrays"
9491 Type *TaskPtrTy = OMPBuilder.TaskPtr;
9492 [[maybe_unused]]
Type *TaskTy = OMPBuilder.Task;
9498 ".omp_target_task_proxy_func", M);
9499 Value *ThreadId = ProxyFn->getArg(0);
9500 Value *TaskWithPrivates = ProxyFn->getArg(1);
9501 ThreadId->
setName(
"thread.id");
9502 TaskWithPrivates->
setName(
"task");
9504 bool HasShareds = SharedArgsOperandNo > 0;
9505 bool HasOffloadingArrays = NumOffloadingArrays > 0;
9509 Builder.SetInsertPoint(EntryBB);
9516 if (HasOffloadingArrays) {
9517 assert(TaskTy != TaskWithPrivatesTy &&
9518 "If there are offloading arrays to pass to the target"
9519 "TaskTy cannot be the same as TaskWithPrivatesTy");
9522 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 1);
9523 for (
unsigned int i = 0; i < NumOffloadingArrays; ++i)
9525 Builder.CreateStructGEP(PrivatesTy, Privates, i));
9529 auto *ArgStructAlloca =
9531 assert(ArgStructAlloca &&
9532 "Unable to find the alloca instruction corresponding to arguments "
9533 "for extracted function");
9535 std::optional<TypeSize> ArgAllocSize =
9537 assert(ArgStructType && ArgAllocSize &&
9538 "Unable to determine size of arguments for extracted function");
9539 uint64_t StructSize = ArgAllocSize->getFixedValue();
9542 Builder.CreateAlloca(ArgStructType,
nullptr,
"structArg");
9544 Value *SharedsSize = Builder.getInt64(StructSize);
9547 OMPBuilder, Builder, TaskWithPrivates, TaskWithPrivatesTy);
9549 Builder.CreateMemCpy(
9550 NewArgStructAlloca, NewArgStructAlloca->
getAlign(), LoadShared,
9552 KernelLaunchArgs.
push_back(NewArgStructAlloca);
9555 Builder.CreateRetVoid();
9561 return GEP->getSourceElementType();
9563 return Alloca->getAllocatedType();
9586 if (OffloadingArraysToPrivatize.
empty())
9587 return OMPIRBuilder.Task;
9590 for (
Value *V : OffloadingArraysToPrivatize) {
9591 assert(V->getType()->isPointerTy() &&
9592 "Expected pointer to array to privatize. Got a non-pointer value "
9595 assert(ArrayTy &&
"ArrayType cannot be nullptr");
9601 "struct.task_with_privates");
9616 EntryFnName, Inputs, CBFunc,
9617 ArgAccessorFuncCB, OutlinedFnLoc);
9621 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
9758 TargetTaskAllocaBB->
begin());
9761 auto OI = std::make_unique<OutlineInfo>();
9762 OI->EntryBB = TargetTaskAllocaBB;
9763 OI->OuterAllocBB = AllocaIP.
getBlock();
9768 Builder, AllocaIP, ToBeDeleted, TargetTaskAllocaIP,
"global.tid",
false));
9771 Builder.restoreIP(TargetTaskBodyIP);
9772 if (
Error Err = TaskBodyCB(DeviceID, RTLoc, TargetTaskAllocaIP))
9790 bool NeedsTargetTask = HasNoWait && DeviceID;
9791 if (NeedsTargetTask) {
9797 OffloadingArraysToPrivatize.
push_back(V);
9798 OI->ExcludeArgsFromAggregate.push_back(V);
9802 OI->PostOutlineCB = [
this, ToBeDeleted, Dependencies, NeedsTargetTask,
9803 DeviceID, OffloadingArraysToPrivatize](
9806 "there must be a single user for the outlined function");
9820 const unsigned int NumStaleCIArgs = StaleCI->
arg_size();
9821 bool HasShareds = NumStaleCIArgs > OffloadingArraysToPrivatize.
size() + 1;
9823 NumStaleCIArgs == (OffloadingArraysToPrivatize.
size() + 2)) &&
9824 "Wrong number of arguments for StaleCI when shareds are present");
9825 int SharedArgOperandNo =
9826 HasShareds ? OffloadingArraysToPrivatize.
size() + 1 : 0;
9832 if (!OffloadingArraysToPrivatize.
empty())
9837 *
this,
Builder, StaleCI, PrivatesTy, TaskWithPrivatesTy,
9838 OffloadingArraysToPrivatize.
size(), SharedArgOperandNo);
9840 LLVM_DEBUG(
dbgs() <<
"Proxy task entry function created: " << *ProxyFn
9843 Builder.SetInsertPoint(StaleCI);
9860 OMPRTL___kmpc_omp_target_task_alloc);
9872 M.getDataLayout().getTypeStoreSize(TaskWithPrivatesTy));
9879 auto *ArgStructAlloca =
9881 assert(ArgStructAlloca &&
9882 "Unable to find the alloca instruction corresponding to arguments "
9883 "for extracted function");
9884 std::optional<TypeSize> ArgAllocSize =
9887 "Unable to determine size of arguments for extracted function");
9888 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
9907 TaskSize, SharedsSize,
9910 if (NeedsTargetTask) {
9911 assert(DeviceID &&
"Expected non-empty device ID.");
9921 *
this,
Builder, TaskData, TaskWithPrivatesTy);
9925 if (!OffloadingArraysToPrivatize.
empty()) {
9927 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskData, 1);
9928 for (
unsigned int i = 0; i < OffloadingArraysToPrivatize.
size(); ++i) {
9929 Value *PtrToPrivatize = OffloadingArraysToPrivatize[i];
9936 "ElementType should match ArrayType");
9939 Value *Dst =
Builder.CreateStructGEP(PrivatesTy, Privates, i);
9942 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(ElementType)));
9946 Value *DepArray =
nullptr;
9947 Value *NumDeps =
nullptr;
9950 NumDeps = Dependencies.
NumDeps;
9951 }
else if (!Dependencies.
Deps.empty()) {
9953 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
9964 if (!NeedsTargetTask) {
9973 ConstantInt::get(
Builder.getInt32Ty(), 0),
9986 }
else if (DepArray) {
9994 {Ident, ThreadID, TaskData, NumDeps, DepArray,
9995 ConstantInt::get(
Builder.getInt32Ty(), 0),
10003 Builder.ClearInsertionPoint();
10006 I->eraseFromParent();
10011 << *(
Builder.GetInsertBlock()) <<
"\n");
10013 << *(
Builder.GetInsertBlock()->getParent()->getParent())
10025 CustomMapperCB, IsNonContiguous, DeviceAddrCB))
10048 Builder.restoreIP(IP);
10054 return Builder.saveIP();
10057 bool HasDependencies = !Dependencies.
empty();
10058 bool RequiresOuterTargetTask = HasNoWait || HasDependencies;
10075 if (OutlinedFnID && DeviceID)
10077 EmitTargetCallFallbackCB, KArgs,
10078 DeviceID, RTLoc, TargetTaskAllocaIP);
10086 return EmitTargetCallFallbackCB(OMPBuilder.
Builder.
saveIP());
10093 auto &&EmitTargetCallElse =
10100 if (RequiresOuterTargetTask) {
10107 Dependencies, EmptyRTArgs, HasNoWait);
10109 return EmitTargetCallFallbackCB(Builder.saveIP());
10112 Builder.restoreIP(AfterIP);
10116 auto &&EmitTargetCallThen =
10120 Info.HasNoWait = HasNoWait;
10125 AllocaIP, Builder.saveIP(), Info, RTArgs, MapInfo, CustomMapperCB,
10131 for (
auto [DefaultVal, RuntimeVal] :
10133 NumTeamsC.
push_back(RuntimeVal ? RuntimeVal
10134 : Builder.getInt32(DefaultVal));
10138 auto InitMaxThreadsClause = [&Builder](
Value *
Clause) {
10140 Clause = Builder.CreateIntCast(
Clause, Builder.getInt32Ty(),
10144 auto CombineMaxThreadsClauses = [&Builder](
Value *
Clause,
Value *&Result) {
10147 Result ? Builder.CreateSelect(Builder.CreateICmpULT(Result,
Clause),
10155 Value *MaxThreadsClause =
10157 ? InitMaxThreadsClause(RuntimeAttrs.
MaxThreads.front())
10160 for (
auto [TeamsVal, TargetVal] :
zip_equal(
10162 Value *TeamsThreadLimitClause = InitMaxThreadsClause(TeamsVal);
10163 Value *NumThreads = InitMaxThreadsClause(TargetVal);
10165 CombineMaxThreadsClauses(TeamsThreadLimitClause, NumThreads);
10166 CombineMaxThreadsClauses(MaxThreadsClause, NumThreads);
10168 NumThreadsC.
push_back(NumThreads ? NumThreads : Builder.getInt32(0));
10171 unsigned NumTargetItems = Info.NumberOfPtrs;
10179 Builder.getInt64Ty(),
10181 : Builder.getInt64(0);
10185 DynCGroupMem = Builder.getInt32(0);
10188 NumTargetItems, RTArgs, TripCount, NumTeamsC, NumThreadsC, DynCGroupMem,
10189 HasNoWait,
false,
false,
10190 DynCGroupMemFallback);
10197 if (RequiresOuterTargetTask)
10199 RTLoc, AllocaIP, Dependencies,
10200 KArgs.
RTArgs, Info.HasNoWait);
10203 Builder, OutlinedFnID, EmitTargetCallFallbackCB, KArgs,
10204 RuntimeAttrs.
DeviceID, RTLoc, AllocaIP);
10207 Builder.restoreIP(AfterIP);
10214 if (!OutlinedFnID) {
10215 cantFail(EmitTargetCallElse(AllocaIP, Builder.saveIP(), DeallocBlocks));
10221 cantFail(EmitTargetCallThen(AllocaIP, Builder.saveIP(), DeallocBlocks));
10226 EmitTargetCallElse, AllocaIP));
10239 bool HasNowait,
Value *DynCGroupMem,
10246 Builder.restoreIP(CodeGenIP);
10254 *
this,
Builder, IsOffloadEntry, EntryInfo, DefaultAttrs, OutlinedFn,
10255 OutlinedFnID, Inputs, CBFunc, ArgAccessorFuncCB, OutlinedFnLoc))
10261 if (!
Config.isTargetDevice())
10263 RuntimeAttrs, IfCond, OutlinedFn, OutlinedFnID, Inputs,
10264 GenMapInfoCB, CustomMapperCB, Dependencies, HasNowait,
10265 DynCGroupMem, DynCGroupMemFallback);
10279 return OS.
str().str();
10284 return OpenMPIRBuilder::getNameWithSeparators(Parts,
Config.firstSeparator(),
10290 auto &Elem = *
InternalVars.try_emplace(Name,
nullptr).first;
10292 assert(Elem.second->getValueType() == Ty &&
10293 "OMP internal variable has different type than requested");
10306 :
M.getTargetTriple().isAMDGPU()
10308 :
DL.getDefaultGlobalsAddressSpace();
10309 auto Linkage = this->
M.getTargetTriple().isWasm()
10317 const llvm::Align PtrAlign =
DL.getPointerABIAlignment(AddressSpaceVal);
10318 GV->setAlignment(std::max(TypeAlign, PtrAlign));
10322 return Elem.second;
10325Value *OpenMPIRBuilder::getOMPCriticalRegionLock(
StringRef CriticalName) {
10326 std::string Prefix =
Twine(
"gomp_critical_user_", CriticalName).
str();
10327 std::string Name = getNameWithSeparators({Prefix,
"var"},
".",
".");
10338 return SizePtrToInt;
10343 std::string VarName) {
10351 return MaptypesArrayGlobal;
10356 unsigned NumOperands,
10365 ArrI8PtrTy,
nullptr,
".offload_baseptrs");
10369 ArrI64Ty,
nullptr,
".offload_sizes");
10380 int64_t DeviceID,
unsigned NumOperands) {
10386 Value *ArgsBaseGEP =
10388 {Builder.getInt32(0), Builder.getInt32(0)});
10391 {Builder.getInt32(0), Builder.getInt32(0)});
10392 Value *ArgSizesGEP =
10394 {Builder.getInt32(0), Builder.getInt32(0)});
10398 Builder.getInt32(NumOperands),
10399 ArgsBaseGEP, ArgsGEP, ArgSizesGEP,
10400 MaptypesArg, MapnamesArg, NullPtr});
10407 assert((!ForEndCall || Info.separateBeginEndCalls()) &&
10408 "expected region end call to runtime only when end call is separate");
10410 auto VoidPtrTy = UnqualPtrTy;
10411 auto VoidPtrPtrTy = UnqualPtrTy;
10413 auto Int64PtrTy = UnqualPtrTy;
10415 if (!Info.NumberOfPtrs) {
10427 Info.RTArgs.BasePointersArray,
10430 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray,
10434 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
10438 ForEndCall && Info.RTArgs.MapTypesArrayEnd ? Info.RTArgs.MapTypesArrayEnd
10439 : Info.RTArgs.MapTypesArray,
10445 if (!Info.EmitDebug)
10449 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.MapNamesArray,
10454 if (!Info.HasMapper)
10458 Builder.CreatePointerCast(Info.RTArgs.MappersArray, VoidPtrPtrTy);
10479 "struct.descriptor_dim");
10481 enum { OffsetFD = 0, CountFD, StrideFD };
10485 for (
unsigned I = 0, L = 0, E = NonContigInfo.
Dims.
size();
I < E; ++
I) {
10488 if (NonContigInfo.
Dims[
I] == 1)
10493 Builder.CreateAlloca(ArrayTy,
nullptr,
"dims");
10494 Builder.restoreIP(CodeGenIP);
10495 for (
unsigned II = 0, EE = NonContigInfo.
Dims[
I];
II < EE; ++
II) {
10496 unsigned RevIdx = EE -
II - 1;
10500 Value *OffsetLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, OffsetFD);
10502 NonContigInfo.
Offsets[L][RevIdx], OffsetLVal,
10503 M.getDataLayout().getPrefTypeAlign(OffsetLVal->
getType()));
10505 Value *CountLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, CountFD);
10507 NonContigInfo.
Counts[L][RevIdx], CountLVal,
10508 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10510 Value *StrideLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, StrideFD);
10512 NonContigInfo.
Strides[L][RevIdx], StrideLVal,
10513 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10516 Builder.restoreIP(CodeGenIP);
10517 Value *DAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
10518 DimsAddr,
Builder.getPtrTy());
10521 Info.RTArgs.PointersArray, 0,
I);
10523 DAddr,
P,
M.getDataLayout().getPrefTypeAlign(
Builder.getPtrTy()));
10528void OpenMPIRBuilder::emitUDMapperArrayInitOrDel(
10532 StringRef Prefix = IsInit ?
".init" :
".del";
10538 Builder.CreateICmpSGT(
Size, Builder.getInt64(1),
"omp.arrayinit.isarray");
10539 Value *DeleteBit = Builder.CreateAnd(
10542 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10543 OpenMPOffloadMappingFlags::OMP_MAP_DELETE)));
10548 Value *BaseIsBegin = Builder.CreateICmpNE(
Base, Begin);
10549 Cond = Builder.CreateOr(IsArray, BaseIsBegin);
10550 DeleteCond = Builder.CreateIsNull(
10555 DeleteCond =
Builder.CreateIsNotNull(
10571 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10572 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10573 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10574 MapTypeArg =
Builder.CreateOr(
10577 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10578 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT)));
10582 Value *OffloadingArgs[] = {MapperHandle,
Base, Begin,
10583 ArraySize, MapTypeArg, MapName};
10594 bool PreserveMemberOfFlags,
bool PropagatePresentToPointee) {
10610 MapperFn->
addFnAttr(Attribute::NoInline);
10611 MapperFn->
addFnAttr(Attribute::NoUnwind);
10622 Builder.SetInsertPoint(EntryBB);
10635 TypeSize ElementSize =
M.getDataLayout().getTypeStoreSize(ElemTy);
10637 Value *PtrBegin = BeginIn;
10643 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
10644 MapType, MapName, ElementSize, HeadBB,
10655 Builder.CreateICmpEQ(PtrBegin, PtrEnd,
"omp.arraymap.isempty");
10656 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
10662 Builder.CreatePHI(PtrBegin->
getType(), 2,
"omp.arraymap.ptrcurrent");
10663 PtrPHI->addIncoming(PtrBegin, HeadBB);
10668 return Info.takeError();
10672 Value *OffloadingArgs[] = {MapperHandle};
10676 Value *ShiftedPreviousSize =
10680 for (
unsigned I = 0;
I < Info->BasePointers.size(); ++
I) {
10681 Value *CurBaseArg = Info->BasePointers[
I];
10682 Value *CurBeginArg = Info->Pointers[
I];
10683 Value *CurSizeArg = Info->Sizes[
I];
10684 Value *CurNameArg = Info->Names.size()
10689 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10692 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10694 constexpr uint64_t MemberOfMask =
10695 static_cast<uint64_t
>(OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
10696 constexpr uint64_t AttachBit =
10697 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10698 OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
10756 Value *MemberMapType;
10757 if (PreserveMemberOfFlags || (RawType & AttachBit) ||
10758 Info->HasAttachPtr[
I]) {
10759 if (RawType & MemberOfMask)
10760 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
10762 MemberMapType = OriMapType;
10764 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
10782 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10783 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10784 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10794 Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
10800 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10801 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10802 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10808 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10809 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
10810 Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
10816 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10817 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10823 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10824 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10825 Builder.CreateCondBr(IsFrom, FromBB, EndBB);
10831 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10832 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
10841 CurMapType->
addIncoming(MemberMapType, ToElseBB);
10878 uint64_t ModifierBits =
10879 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10880 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
10881 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
10882 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
10883 if (PropagatePresentToPointee && Info->HasAttachPtr[
I])
10885 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10886 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
10887 Value *ImportedModifierBits =
10890 CurMapType, ImportedModifierBits,
"omp.maptype.with.modifiers");
10895 Value *FinalMapType =
10896 (RawType & AttachBit) ? CurMapType : CurMapTypeWithModifiers;
10898 Value *OffloadingArgs[] = {MapperHandle, CurBaseArg, CurBeginArg,
10899 CurSizeArg, FinalMapType, CurNameArg};
10901 auto ChildMapperFn = CustomMapperCB(
I);
10902 if (!ChildMapperFn)
10903 return ChildMapperFn.takeError();
10904 if (*ChildMapperFn) {
10919 Value *PtrNext =
Builder.CreateConstGEP1_32(ElemTy, PtrPHI, 1,
10920 "omp.arraymap.next");
10921 PtrPHI->addIncoming(PtrNext, LastBB);
10922 Value *IsDone =
Builder.CreateICmpEQ(PtrNext, PtrEnd,
"omp.arraymap.isdone");
10924 Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
10929 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
10930 MapType, MapName, ElementSize, DoneBB,
10943 bool IsNonContiguous,
10947 Info.clearArrayInfo();
10950 if (Info.NumberOfPtrs == 0)
10959 Info.RTArgs.BasePointersArray =
Builder.CreateAlloca(
10960 PointerArrayType,
nullptr,
".offload_baseptrs");
10962 Info.RTArgs.PointersArray =
Builder.CreateAlloca(
10963 PointerArrayType,
nullptr,
".offload_ptrs");
10965 PointerArrayType,
nullptr,
".offload_mappers");
10966 Info.RTArgs.MappersArray = MappersArray;
10973 ConstantInt::get(Int64Ty, 0));
10975 for (
unsigned I = 0, E = CombinedInfo.
Sizes.
size();
I < E; ++
I) {
10976 bool IsNonContigEntry =
10978 (
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10980 OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG) != 0);
10983 if (IsNonContigEntry) {
10985 "Index must be in-bounds for NON_CONTIG Dims array");
10987 assert(DimCount > 0 &&
"NON_CONTIG DimCount must be > 0");
10988 ConstSizes[
I] = ConstantInt::get(Int64Ty, DimCount);
10993 ConstSizes[
I] = CI;
10997 RuntimeSizes.
set(
I);
11000 if (RuntimeSizes.
all()) {
11002 Info.RTArgs.SizesArray =
Builder.CreateAlloca(
11003 SizeArrayType,
nullptr,
".offload_sizes");
11009 auto *SizesArrayGbl =
11014 if (!RuntimeSizes.
any()) {
11015 Info.RTArgs.SizesArray = SizesArrayGbl;
11017 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
11018 Align OffloadSizeAlign =
M.getDataLayout().getABIIntegerTypeAlignment(64);
11021 SizeArrayType,
nullptr,
".offload_sizes");
11025 Buffer,
M.getDataLayout().getPrefTypeAlign(Buffer->
getType()),
11026 SizesArrayGbl, OffloadSizeAlign,
11031 Info.RTArgs.SizesArray = Buffer;
11039 for (
auto mapFlag : CombinedInfo.
Types)
11041 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11045 Info.RTArgs.MapTypesArray = MapTypesArrayGbl;
11051 Info.RTArgs.MapNamesArray = MapNamesArrayGbl;
11052 Info.EmitDebug =
true;
11054 Info.RTArgs.MapNamesArray =
11056 Info.EmitDebug =
false;
11061 if (Info.separateBeginEndCalls()) {
11062 bool EndMapTypesDiffer =
false;
11063 for (uint64_t &
Type : Mapping) {
11064 if (
Type &
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11065 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT)) {
11066 Type &= ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
11067 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
11068 EndMapTypesDiffer =
true;
11071 if (EndMapTypesDiffer) {
11073 Info.RTArgs.MapTypesArrayEnd = MapTypesArrayGbl;
11078 for (
unsigned I = 0;
I < Info.NumberOfPtrs; ++
I) {
11081 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.BasePointersArray,
11083 Builder.CreateAlignedStore(BPVal, BP,
11084 M.getDataLayout().getPrefTypeAlign(PtrTy));
11086 if (Info.requiresDevicePointerInfo()) {
11088 CodeGenIP =
Builder.saveIP();
11090 Info.DevicePtrInfoMap[BPVal] = {BP,
Builder.CreateAlloca(PtrTy)};
11093 DeviceAddrCB(
I, Info.DevicePtrInfoMap[BPVal].second);
11095 Info.DevicePtrInfoMap[BPVal] = {BP, BP};
11097 DeviceAddrCB(
I, BP);
11103 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray, 0,
11106 Builder.CreateAlignedStore(PVal,
P,
11107 M.getDataLayout().getPrefTypeAlign(PtrTy));
11109 if (RuntimeSizes.
test(
I)) {
11111 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
11117 S,
M.getDataLayout().getPrefTypeAlign(PtrTy));
11120 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
11123 auto CustomMFunc = CustomMapperCB(
I);
11125 return CustomMFunc.takeError();
11127 MFunc =
Builder.CreatePointerCast(*CustomMFunc, PtrTy);
11130 PointerArrayType, MappersArray,
11133 MFunc, MAddr,
M.getDataLayout().getPrefTypeAlign(MAddr->
getType()));
11137 Info.NumberOfPtrs == 0)
11154 Builder.ClearInsertionPoint();
11185 auto CondConstant = CI->getSExtValue();
11187 return ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
11189 return ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
11199 Builder.CreateCondBr(
Cond, ThenBlock, ElseBlock);
11202 if (
Error Err = ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks))
11208 if (
Error Err = ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks))
11217bool OpenMPIRBuilder::checkAndEmitFlushAfterAtomic(
11221 "Unexpected Atomic Ordering.");
11223 bool Flush =
false;
11285 assert(
X.Var->getType()->isPointerTy() &&
11286 "OMP Atomic expects a pointer to target memory");
11287 Type *XElemTy =
X.ElemTy;
11290 "OMP atomic read expected a scalar type");
11292 Value *XRead =
nullptr;
11296 Builder.CreateLoad(XElemTy,
X.Var,
X.IsVolatile,
"omp.atomic.read");
11305 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11308 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11310 XRead = AtomicLoadRes.first;
11317 Builder.CreateLoad(IntCastTy,
X.Var,
X.IsVolatile,
"omp.atomic.load");
11320 XRead =
Builder.CreateBitCast(XLoad, XElemTy,
"atomic.flt.cast");
11322 XRead =
Builder.CreateIntToPtr(XLoad, XElemTy,
"atomic.ptr.cast");
11325 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Read);
11326 Builder.CreateStore(XRead, V.Var, V.IsVolatile);
11337 assert(
X.Var->getType()->isPointerTy() &&
11338 "OMP Atomic expects a pointer to target memory");
11339 Type *XElemTy =
X.ElemTy;
11342 "OMP atomic write expected a scalar type");
11350 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11353 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11361 Builder.CreateBitCast(Expr, IntCastTy,
"atomic.src.int.cast");
11366 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Write);
11373 AtomicUpdateCallbackTy &UpdateOp,
bool IsXBinopExpr,
11374 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11380 Type *XTy =
X.Var->getType();
11382 "OMP Atomic expects a pointer to target memory");
11383 Type *XElemTy =
X.ElemTy;
11386 "OMP atomic update expected a scalar or struct type");
11389 "OpenMP atomic does not support LT or GT operations");
11393 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, RMWOp, UpdateOp,
X.IsVolatile,
11394 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11396 return AtomicResult.takeError();
11397 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Update);
11402Value *OpenMPIRBuilder::emitRMWOpAsInstruction(
Value *Src1,
Value *Src2,
11406 return Builder.CreateAdd(Src1, Src2);
11408 return Builder.CreateSub(Src1, Src2);
11410 return Builder.CreateAnd(Src1, Src2);
11412 return Builder.CreateNeg(Builder.CreateAnd(Src1, Src2));
11414 return Builder.CreateOr(Src1, Src2);
11416 return Builder.CreateXor(Src1, Src2);
11455Expected<std::pair<Value *, Value *>> OpenMPIRBuilder::emitAtomicUpdate(
11458 AtomicUpdateCallbackTy &UpdateOp,
bool VolatileX,
bool IsXBinopExpr,
11459 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11461 bool emitRMWOp =
false;
11469 emitRMWOp = XElemTy;
11472 emitRMWOp = (IsXBinopExpr && XElemTy);
11479 std::pair<Value *, Value *> Res;
11481 AtomicRMWInst *RMWInst =
11482 Builder.CreateAtomicRMW(RMWOp,
X, Expr, llvm::MaybeAlign(), AO);
11483 if (
T.isAMDGPU()) {
11484 if (IsIgnoreDenormalMode)
11485 RMWInst->
setMetadata(
"amdgpu.ignore.denormal.mode",
11487 if (!IsFineGrainedMemory)
11488 RMWInst->
setMetadata(
"amdgpu.no.fine.grained.memory",
11490 if (!IsRemoteMemory)
11494 Res.first = RMWInst;
11499 Res.second = Res.first;
11501 Res.second = emitRMWOpAsInstruction(Res.first, Expr, RMWOp);
11504 Builder.CreateLoad(XElemTy,
X,
X->getName() +
".atomic.load");
11510 OpenMPIRBuilder::AtomicInfo atomicInfo(
11512 OldVal->
getAlign(),
true , AllocaIP,
X);
11513 auto AtomicLoadRes = atomicInfo.EmitAtomicLoadLibcall(AO);
11516 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11523 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11524 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11525 Builder.SetInsertPoint(ContBB);
11527 PHI->addIncoming(AtomicLoadRes.first, CurBB);
11529 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11532 Value *Upd = *CBResult;
11533 Builder.CreateStore(Upd, NewAtomicAddr);
11536 auto Result = atomicInfo.EmitAtomicCompareExchangeLibcall(
11537 AtomicLoadRes.second, NewAtomicAddr, AO, Failure);
11538 LoadInst *PHILoad =
Builder.CreateLoad(XElemTy,
Result.first);
11539 PHI->addIncoming(PHILoad,
Builder.GetInsertBlock());
11542 Res.first = OldExprVal;
11545 if (UnreachableInst *ExitTI =
11548 Builder.SetInsertPoint(ExitBB);
11550 Builder.SetInsertPoint(ExitTI);
11553 IntegerType *IntCastTy =
11556 Builder.CreateLoad(IntCastTy,
X,
X->getName() +
".atomic.load");
11566 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11573 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11574 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11575 Builder.SetInsertPoint(ContBB);
11577 PHI->addIncoming(OldVal, CurBB);
11582 OldExprVal =
Builder.CreateBitCast(
PHI, XElemTy,
11583 X->getName() +
".atomic.fltCast");
11585 OldExprVal =
Builder.CreateIntToPtr(
PHI, XElemTy,
11586 X->getName() +
".atomic.ptrCast");
11590 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11593 Value *Upd = *CBResult;
11594 Builder.CreateStore(Upd, NewAtomicAddr);
11595 LoadInst *DesiredVal =
Builder.CreateLoad(IntCastTy, NewAtomicAddr);
11599 X,
PHI, DesiredVal, llvm::MaybeAlign(), AO, Failure);
11600 Result->setVolatile(VolatileX);
11601 Value *PreviousVal =
Builder.CreateExtractValue(Result, 0);
11602 Value *SuccessFailureVal =
Builder.CreateExtractValue(Result, 1);
11603 PHI->addIncoming(PreviousVal,
Builder.GetInsertBlock());
11604 Builder.CreateCondBr(SuccessFailureVal, ExitBB, ContBB);
11606 Res.first = OldExprVal;
11610 if (UnreachableInst *ExitTI =
11613 Builder.SetInsertPoint(ExitBB);
11615 Builder.SetInsertPoint(ExitTI);
11626 bool UpdateExpr,
bool IsPostfixUpdate,
bool IsXBinopExpr,
11627 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11632 Type *XTy =
X.Var->getType();
11634 "OMP Atomic expects a pointer to target memory");
11635 Type *XElemTy =
X.ElemTy;
11638 "OMP atomic capture expected a scalar or struct type");
11640 "OpenMP atomic does not support LT or GT operations");
11647 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, AtomicOp, UpdateOp,
X.IsVolatile,
11648 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11651 Value *CapturedVal =
11652 (IsPostfixUpdate ? AtomicResult->first : AtomicResult->second);
11653 Builder.CreateStore(CapturedVal, V.Var, V.IsVolatile);
11655 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Capture);
11663 bool IsFailOnly,
bool IsWeak) {
11667 IsPostfixUpdate, IsFailOnly, Failure, IsWeak);
11679 assert(
X.Var->getType()->isPointerTy() &&
11680 "OMP atomic expects a pointer to target memory");
11683 assert(V.Var->getType()->isPointerTy() &&
"v.var must be of pointer type");
11684 assert(V.ElemTy ==
X.ElemTy &&
"x and v must be of same type");
11687 bool IsInteger = E->getType()->isIntegerTy();
11689 if (
Op == OMPAtomicCompareOp::EQ) {
11692 Value *OldValue =
nullptr;
11693 Value *SuccessOrFail =
nullptr;
11731 X.Var->getName() +
".atomic.load");
11737 Value *EIsNaN =
Builder.CreateFCmpUNO(E, E,
"atomic.e.isnan");
11738 Value *XIsNaN =
Builder.CreateFCmpUNO(XFP, XFP,
"atomic.x.isnan");
11739 Value *EitherNaN =
Builder.CreateOr(EIsNaN, XIsNaN,
"atomic.either.nan");
11744 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11748 M.getContext(),
X.Var->getName() +
".atomic.nan",
F, ExitBB);
11750 M.getContext(),
X.Var->getName() +
".atomic.notnan",
F, ExitBB);
11752 M.getContext(),
X.Var->getName() +
".atomic.zero",
F, ExitBB);
11754 M.getContext(),
X.Var->getName() +
".atomic.normal",
F, ExitBB);
11758 Builder.SetInsertPoint(CurBB);
11759 Builder.CreateCondBr(EitherNaN, NaNBB, NotNaNBB);
11762 Builder.SetInsertPoint(NaNBB);
11766 Builder.SetInsertPoint(NotNaNBB);
11769 X.Var->getName() +
".atomic.xiszero");
11771 "atomic.e.iszero");
11772 Value *BothZero =
Builder.CreateAnd(XIsZero, EIsZero,
"atomic.both.zero");
11773 Builder.CreateCondBr(BothZero, ZeroBB, NormalBB);
11776 Builder.SetInsertPoint(ZeroBB);
11778 X.Var, XCurr, DBCast,
MaybeAlign(), AO, Failure);
11780 Value *OldZero =
Builder.CreateExtractValue(ResZero, 0);
11781 Value *OkZero =
Builder.CreateExtractValue(ResZero, 1);
11785 Builder.SetInsertPoint(NormalBB);
11787 X.Var, EBCast, DBCast,
MaybeAlign(), AO, Failure);
11789 Value *OldNormal =
Builder.CreateExtractValue(ResNormal, 0);
11790 Value *OkNormal =
Builder.CreateExtractValue(ResNormal, 1);
11796 Builder.CreatePHI(IntCastTy, 3,
X.Var->getName() +
".atomic.old");
11801 X.Var->getName() +
".atomic.ok");
11808 Builder.SetInsertPoint(ExitBB);
11813 OldValue =
Builder.CreateBitCast(OldIntPHI,
X.ElemTy,
11814 X.Var->getName() +
".atomic.old.fp");
11815 SuccessOrFail = SuccessPHI;
11823 Result =
Builder.CreateAtomicCmpXchg(
X.Var, EBCast, DBCast,
11829 Result->setWeak(IsWeak);
11832 OldValue =
Builder.CreateExtractValue(Result, 0);
11834 OldValue =
Builder.CreateBitCast(OldValue,
X.ElemTy);
11836 "OldValue and V must be of same type");
11837 if (IsPostfixUpdate) {
11838 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
11840 SuccessOrFail =
Builder.CreateExtractValue(Result, 1);
11844 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11846 CurBBTI,
X.Var->getName() +
".atomic.exit");
11852 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
11854 Builder.SetInsertPoint(ContBB);
11855 Builder.CreateStore(OldValue, V.Var);
11861 Builder.SetInsertPoint(ExitBB);
11863 Builder.SetInsertPoint(ExitTI);
11866 Value *CapturedValue =
11867 Builder.CreateSelect(SuccessOrFail, E, OldValue);
11868 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
11874 assert(R.Var->getType()->isPointerTy() &&
11875 "r.var must be of pointer type");
11876 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
11878 Value *SuccessFailureVal =
11879 Builder.CreateExtractValue(Result, 1);
11880 Value *ResultCast =
11881 R.IsSigned ?
Builder.CreateSExt(SuccessFailureVal, R.ElemTy)
11882 :
Builder.CreateZExt(SuccessFailureVal, R.ElemTy);
11883 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
11892 "OldValue and V must be of same type");
11893 if (IsPostfixUpdate) {
11894 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
11899 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11901 CurBBTI,
X.Var->getName() +
".atomic.exit");
11907 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
11909 Builder.SetInsertPoint(ContBB);
11910 Builder.CreateStore(OldValue, V.Var);
11916 Builder.SetInsertPoint(ExitBB);
11918 Builder.SetInsertPoint(ExitTI);
11921 Value *CapturedValue =
11922 Builder.CreateSelect(SuccessOrFail, E, OldValue);
11923 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
11929 assert(R.Var->getType()->isPointerTy() &&
11930 "r.var must be of pointer type");
11931 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
11933 Value *ResultCast = R.IsSigned
11934 ?
Builder.CreateSExt(SuccessOrFail, R.ElemTy)
11935 :
Builder.CreateZExt(SuccessOrFail, R.ElemTy);
11936 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
11940 assert((
Op == OMPAtomicCompareOp::MAX ||
Op == OMPAtomicCompareOp::MIN) &&
11941 "Op should be either max or min at this point");
11942 assert(!IsFailOnly &&
"IsFailOnly is only valid when the comparison is ==");
11953 if (IsXBinopExpr) {
11982 Value *CapturedValue =
nullptr;
11983 if (IsPostfixUpdate) {
11984 CapturedValue = OldValue;
12009 Value *NonAtomicCmp =
Builder.CreateCmp(Pred, OldValue, E);
12010 CapturedValue =
Builder.CreateSelect(NonAtomicCmp, E, OldValue);
12012 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
12016 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Compare);
12036 if (&OuterAllocaBB ==
Builder.GetInsertBlock()) {
12063 bool SubClausesPresent =
12064 (NumTeamsLower || NumTeamsUpper || ThreadLimit || IfExpr);
12066 if (!
Config.isTargetDevice() && SubClausesPresent) {
12067 assert((NumTeamsLower ==
nullptr || NumTeamsUpper !=
nullptr) &&
12068 "if lowerbound is non-null, then upperbound must also be non-null "
12069 "for bounds on num_teams");
12071 if (NumTeamsUpper ==
nullptr)
12072 NumTeamsUpper =
Builder.getInt32(0);
12074 if (NumTeamsLower ==
nullptr)
12075 NumTeamsLower = NumTeamsUpper;
12079 "argument to if clause must be an integer value");
12083 IfExpr =
Builder.CreateICmpNE(IfExpr,
12084 ConstantInt::get(IfExpr->
getType(), 0));
12085 NumTeamsUpper =
Builder.CreateSelect(
12086 IfExpr, NumTeamsUpper,
Builder.getInt32(1),
"numTeamsUpper");
12089 NumTeamsLower =
Builder.CreateSelect(
12090 IfExpr, NumTeamsLower,
Builder.getInt32(1),
"numTeamsLower");
12093 if (ThreadLimit ==
nullptr)
12094 ThreadLimit =
Builder.getInt32(0);
12098 Value *NumTeamsLowerInt32 =
12100 Value *NumTeamsUpperInt32 =
12102 Value *ThreadLimitInt32 =
12109 {Ident, ThreadNum, NumTeamsLowerInt32, NumTeamsUpperInt32,
12110 ThreadLimitInt32});
12115 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
12118 auto OI = std::make_unique<OutlineInfo>();
12119 OI->EntryBB = AllocaBB;
12120 OI->ExitBB = ExitBB;
12121 OI->OuterAllocBB = &OuterAllocaBB;
12127 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"gid",
true));
12129 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"tid",
true));
12131 auto HostPostOutlineCB = [
this, Ident,
12132 ToBeDeleted](
Function &OutlinedFn)
mutable {
12137 "there must be a single user for the outlined function");
12142 "Outlined function must have two or three arguments only");
12144 bool HasShared = OutlinedFn.
arg_size() == 3;
12152 assert(StaleCI &&
"Error while outlining - no CallInst user found for the "
12153 "outlined function.");
12154 Builder.SetInsertPoint(StaleCI);
12161 omp::RuntimeFunction::OMPRTL___kmpc_fork_teams),
12164 Builder.ClearInsertionPoint();
12166 I->eraseFromParent();
12169 if (!
Config.isTargetDevice())
12170 OI->PostOutlineCB = HostPostOutlineCB;
12174 Builder.SetInsertPoint(ExitBB);
12187 if (OuterAllocaBB ==
Builder.GetInsertBlock()) {
12202 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
12207 if (
Config.isTargetDevice()) {
12208 auto OI = std::make_unique<OutlineInfo>();
12209 OI->OuterAllocBB = OuterAllocIP.
getBlock();
12210 OI->EntryBB = AllocaBB;
12211 OI->ExitBB = ExitBB;
12212 OI->OuterDeallocBBs.reserve(OuterDeallocBlocks.
size());
12213 copy(OuterDeallocBlocks, OI->OuterDeallocBBs.
end());
12217 Builder.SetInsertPoint(ExitBB);
12224 std::string VarName) {
12233 return MapNamesArrayGlobal;
12238void OpenMPIRBuilder::initializeTypes(
Module &M) {
12242 unsigned ProgramAS = M.getDataLayout().getProgramAddressSpace();
12243#define OMP_TYPE(VarName, InitValue) VarName = InitValue;
12244#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \
12245 VarName##Ty = ArrayType::get(ElemTy, ArraySize); \
12246 VarName##PtrTy = PointerType::get(Ctx, DefaultTargetAS);
12247#define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) \
12248 VarName = FunctionType::get(ReturnType, {__VA_ARGS__}, IsVarArg); \
12249 VarName##Ptr = PointerType::get(Ctx, ProgramAS);
12250#define OMP_STRUCT_TYPE(VarName, StructName, Packed, ...) \
12251 T = StructType::getTypeByName(Ctx, StructName); \
12253 T = StructType::create(Ctx, {__VA_ARGS__}, StructName, Packed); \
12255 VarName##Ptr = PointerType::get(Ctx, DefaultTargetAS);
12256#include "llvm/Frontend/OpenMP/OMPKinds.def"
12267 while (!Worklist.
empty()) {
12271 if (
BlockSet.insert(SuccBB).second)
12276std::unique_ptr<CodeExtractor>
12278 bool ArgsInZeroAddressSpace,
12280 return std::make_unique<CodeExtractor>(
12290 Suffix.
str(), ArgsInZeroAddressSpace);
12293std::unique_ptr<CodeExtractor> DeviceSharedMemOutlineInfo::createCodeExtractor(
12295 return std::make_unique<DeviceSharedMemCodeExtractor>(
12296 OMPBuilder, Blocks,
nullptr,
12304 OuterDeallocBBs.empty()
12307 Suffix.
str(), ArgsInZeroAddressSpace);
12311 uint64_t
Size, int32_t Flags,
12317 Name.empty() ? Addr->
getName() : Name,
Size, Flags, 0);
12329 Fn->
addFnAttr(
"uniform-work-group-size");
12330 Fn->
addFnAttr(Attribute::MustProgress);
12348 auto &&GetMDInt = [
this](
unsigned V) {
12355 NamedMDNode *MD =
M.getOrInsertNamedMetadata(
"omp_offload.info");
12356 auto &&TargetRegionMetadataEmitter =
12357 [&
C, MD, &OrderedEntries, &GetMDInt, &GetMDString](
12372 GetMDInt(E.getKind()), GetMDInt(EntryInfo.DeviceID),
12373 GetMDInt(EntryInfo.FileID), GetMDString(EntryInfo.ParentName),
12374 GetMDInt(EntryInfo.Line), GetMDInt(EntryInfo.Count),
12375 GetMDInt(E.getOrder())};
12378 OrderedEntries[E.getOrder()] = std::make_pair(&E, EntryInfo);
12387 auto &&DeviceGlobalVarMetadataEmitter =
12388 [&
C, &OrderedEntries, &GetMDInt, &GetMDString, MD](
12398 Metadata *
Ops[] = {GetMDInt(E.getKind()), GetMDString(MangledName),
12399 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
12403 OrderedEntries[E.getOrder()] = std::make_pair(&E, varInfo);
12410 DeviceGlobalVarMetadataEmitter);
12412 for (
const auto &E : OrderedEntries) {
12413 assert(E.first &&
"All ordered entries must exist!");
12414 if (
const auto *CE =
12417 if (!CE->getID() || !CE->getAddress()) {
12421 if (!
M.getNamedValue(FnName))
12429 }
else if (
const auto *CE =
dyn_cast<
12438 if (
Config.isTargetDevice() &&
Config.hasRequiresUnifiedSharedMemory())
12440 if (!CE->getAddress()) {
12445 if (CE->getVarSize() == 0)
12449 assert(((
Config.isTargetDevice() && !CE->getAddress()) ||
12450 (!
Config.isTargetDevice() && CE->getAddress())) &&
12451 "Declaret target link address is set.");
12452 if (
Config.isTargetDevice())
12454 if (!CE->getAddress()) {
12461 if (!CE->getAddress()) {
12474 if ((
GV->hasLocalLinkage() ||
GV->hasHiddenVisibility()) &&
12478 OMPTargetGlobalVarEntryIndirectVTable))
12487 Flags, CE->getLinkage(), CE->getVarName());
12490 Flags, CE->getLinkage());
12501 if (
Config.hasRequiresFlags() && !
Config.isTargetDevice())
12507 Config.getRequiresFlags());
12517 OS <<
"_" <<
Count;
12522 unsigned NewCount = getTargetRegionEntryInfoCount(EntryInfo);
12525 EntryInfo.
Line, NewCount);
12533 auto FileIDInfo = CallBack();
12534 uint64_t FileID = 0;
12536 ID =
Status->getUniqueID();
12537 FileID =
Status->getUniqueID().getFile();
12541 FileID =
hash_value(std::get<0>(FileIDInfo));
12545 std::get<1>(FileIDInfo));
12550 for (uint64_t Remain =
12551 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12553 !(Remain & 1); Remain = Remain >> 1)
12571 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12573 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12580 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12586 Flags &=
~omp::OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
12587 Flags |= MemberOfFlag;
12593 bool IsDeclaration,
bool IsExternallyVisible,
12595 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12596 std::vector<Triple> TargetTriple,
Type *LlvmPtrTy,
12597 std::function<
Constant *()> GlobalInitializer,
12608 Config.hasRequiresUnifiedSharedMemory())) {
12613 if (!IsExternallyVisible)
12615 OS <<
"_decl_tgt_ref_ptr";
12618 Value *Ptr =
M.getNamedValue(PtrName);
12627 if (!
Config.isTargetDevice()) {
12628 if (GlobalInitializer)
12629 GV->setInitializer(GlobalInitializer());
12635 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12636 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12637 GlobalInitializer, VariableLinkage, LlvmPtrTy,
cast<Constant>(Ptr));
12649 bool IsDeclaration,
bool IsExternallyVisible,
12651 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12652 std::vector<Triple> TargetTriple,
12653 std::function<
Constant *()> GlobalInitializer,
12657 (TargetTriple.empty() && !
Config.isTargetDevice()))
12668 !
Config.hasRequiresUnifiedSharedMemory()) {
12670 VarName = MangledName;
12673 if (!IsDeclaration)
12675 M.getDataLayout().getTypeSizeInBits(LlvmVal->
getValueType()), 8);
12678 Linkage = (VariableLinkage) ? VariableLinkage() : LlvmVal->
getLinkage();
12682 if (
Config.isTargetDevice() &&
12691 if (!
M.getNamedValue(RefName)) {
12695 GvAddrRef->setConstant(
true);
12697 GvAddrRef->setInitializer(Addr);
12698 GeneratedRefs.push_back(GvAddrRef);
12707 if (
Config.isTargetDevice()) {
12708 VarName = (Addr) ? Addr->
getName() :
"";
12712 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12713 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12714 LlvmPtrTy, GlobalInitializer, VariableLinkage);
12715 VarName = (Addr) ? Addr->
getName() :
"";
12717 VarSize =
M.getDataLayout().getPointerSize();
12736 auto &&GetMDInt = [MN](
unsigned Idx) {
12741 auto &&GetMDString = [MN](
unsigned Idx) {
12743 return V->getString();
12746 switch (GetMDInt(0)) {
12750 case OffloadEntriesInfoManager::OffloadEntryInfo::
12751 OffloadingEntryInfoTargetRegion: {
12761 case OffloadEntriesInfoManager::OffloadEntryInfo::
12762 OffloadingEntryInfoDeviceGlobalVar:
12775 if (HostFilePath.
empty())
12779 if (std::error_code Err = Buf.getError()) {
12781 "OpenMPIRBuilder: " +
12789 if (std::error_code Err =
M.getError()) {
12791 (
"error parsing host file inside of OpenMPIRBuilder: " + Err.message())
12805 "expected a valid insertion block for creating an iterator loop");
12815 Builder.getCurrentDebugLocation(),
"omp.it.cont");
12827 T->eraseFromParent();
12836 if (!BodyBr || BodyBr->getSuccessor() != CLI->
getLatch()) {
12838 "iterator bodygen must terminate the canonical body with an "
12839 "unconditional branch to the loop latch",
12863 for (
const auto &
ParamAttr : ParamAttrs) {
12906 return std::string(Out.
str());
12914 unsigned VecRegSize;
12916 ISADataTy ISAData[] = {
12935 for (
char Mask :
Masked) {
12936 for (
const ISADataTy &
Data : ISAData) {
12939 Out <<
"_ZGV" <<
Data.ISA << Mask;
12941 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
12955template <
typename T>
12958 StringRef MangledName,
bool OutputBecomesInput,
12962 Out << Prefix << ISA << LMask << VLEN;
12963 if (OutputBecomesInput)
12965 Out << ParSeq <<
'_' << MangledName;
12974 bool OutputBecomesInput,
12979 OutputBecomesInput, Fn);
12981 OutputBecomesInput, Fn);
12985 OutputBecomesInput, Fn);
12987 OutputBecomesInput, Fn);
12991 OutputBecomesInput, Fn);
12993 OutputBecomesInput, Fn);
12998 OutputBecomesInput, Fn);
13009 char ISA,
unsigned NarrowestDataSize,
bool OutputBecomesInput) {
13010 assert((ISA ==
'n' || ISA ==
's') &&
"Expected ISA either 's' or 'n'.");
13022 OutputBecomesInput, Fn);
13029 OutputBecomesInput, Fn);
13031 OutputBecomesInput, Fn);
13035 OutputBecomesInput, Fn);
13039 OutputBecomesInput, Fn);
13048 OutputBecomesInput, Fn);
13055 MangledName, OutputBecomesInput, Fn);
13057 MangledName, OutputBecomesInput, Fn);
13061 MangledName, OutputBecomesInput, Fn);
13065 MangledName, OutputBecomesInput, Fn);
13075 return OffloadEntriesTargetRegion.empty() &&
13076 OffloadEntriesDeviceGlobalVar.empty();
13079unsigned OffloadEntriesInfoManager::getTargetRegionEntryInfoCount(
13081 auto It = OffloadEntriesTargetRegionCount.find(
13082 getTargetRegionEntryCountKey(EntryInfo));
13083 if (It == OffloadEntriesTargetRegionCount.end())
13088void OffloadEntriesInfoManager::incrementTargetRegionEntryInfoCount(
13090 OffloadEntriesTargetRegionCount[getTargetRegionEntryCountKey(EntryInfo)] =
13091 EntryInfo.
Count + 1;
13097 OffloadEntriesTargetRegion[EntryInfo] =
13100 ++OffloadingEntriesNum;
13106 assert(EntryInfo.
Count == 0 &&
"expected default EntryInfo");
13109 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
13113 if (OMPBuilder->Config.isTargetDevice()) {
13118 auto &Entry = OffloadEntriesTargetRegion[EntryInfo];
13119 Entry.setAddress(Addr);
13121 Entry.setFlags(Flags);
13127 "Target region entry already registered!");
13129 OffloadEntriesTargetRegion[EntryInfo] = Entry;
13130 ++OffloadingEntriesNum;
13132 incrementTargetRegionEntryInfoCount(EntryInfo);
13139 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
13141 auto It = OffloadEntriesTargetRegion.find(EntryInfo);
13142 if (It == OffloadEntriesTargetRegion.end()) {
13146 if (!IgnoreAddressId && (It->second.getAddress() || It->second.getID()))
13154 for (
const auto &It : OffloadEntriesTargetRegion) {
13155 Action(It.first, It.second);
13161 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
13162 ++OffloadingEntriesNum;
13168 if (OMPBuilder->Config.isTargetDevice()) {
13172 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
13174 if (Entry.getVarSize() == 0) {
13175 Entry.setVarSize(VarSize);
13176 Entry.setLinkage(Linkage);
13180 Entry.setVarSize(VarSize);
13181 Entry.setLinkage(Linkage);
13182 Entry.setAddress(Addr);
13185 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
13186 assert(Entry.isValid() && Entry.getFlags() == Flags &&
13187 "Entry not initialized!");
13188 if (Entry.getVarSize() == 0) {
13189 Entry.setVarSize(VarSize);
13190 Entry.setLinkage(Linkage);
13197 OffloadEntriesDeviceGlobalVar.try_emplace(VarName, OffloadingEntriesNum,
13198 Addr, VarSize, Flags, Linkage,
13201 OffloadEntriesDeviceGlobalVar.try_emplace(
13202 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage,
"");
13203 ++OffloadingEntriesNum;
13210 for (
const auto &E : OffloadEntriesDeviceGlobalVar)
13211 Action(E.getKey(), E.getValue());
13218void CanonicalLoopInfo::collectControlBlocks(
13225 BBs.
append({getPreheader(), Header,
Cond, Latch, Exit, getAfter()});
13237void CanonicalLoopInfo::setTripCount(
Value *TripCount) {
13249void CanonicalLoopInfo::mapIndVar(
13259 for (
Use &U : OldIV->
uses()) {
13263 if (
User->getParent() == getCond())
13265 if (
User->getParent() == getLatch())
13271 Value *NewIV = Updater(OldIV);
13274 for (Use *U : ReplacableUses)
13295 "Preheader must terminate with unconditional branch");
13297 "Preheader must jump to header");
13301 "Header must terminate with unconditional branch");
13302 assert(Header->getSingleSuccessor() == Cond &&
13303 "Header must jump to exiting block");
13306 assert(Cond->getSinglePredecessor() == Header &&
13307 "Exiting block only reachable from header");
13310 "Exiting block must terminate with conditional branch");
13312 "Exiting block's first successor jump to the body");
13314 "Exiting block's second successor must exit the loop");
13318 "Body only reachable from exiting block");
13323 "Latch must terminate with unconditional branch");
13324 assert(Latch->getSingleSuccessor() == Header &&
"Latch must jump to header");
13327 assert(Latch->getSinglePredecessor() !=
nullptr);
13332 "Exit block must terminate with unconditional branch");
13333 assert(Exit->getSingleSuccessor() == After &&
13334 "Exit block must jump to after block");
13338 "After block only reachable from exit block");
13342 assert(IndVar &&
"Canonical induction variable not found?");
13344 "Induction variable must be an integer");
13346 "Induction variable must be a PHI in the loop header");
13352 auto *NextIndVar =
cast<PHINode>(IndVar)->getIncomingValue(1);
13360 assert(TripCount &&
"Loop trip count not found?");
13362 "Trip count and induction variable must have the same type");
13366 "Exit condition must be a signed less-than comparison");
13368 "Exit condition must compare the induction variable");
13370 "Exit condition must compare with the trip count");
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
Expand Atomic instructions
This file contains the simple types necessary to represent the attributes associated with functions a...
static const Function * getParent(const Value *V)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
This header defines various interfaces for pass management in LLVM.
iv Induction Variable Users
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
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 Expected< Function * > createOutlinedFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, const OpenMPIRBuilder::TargetKernelDefaultAttrs &DefaultAttrs, StringRef FuncName, SmallVectorImpl< Value * > &Inputs, OpenMPIRBuilder::TargetBodyGenCallbackTy &CBFunc, OpenMPIRBuilder::TargetGenArgAccessorsCallbackTy &ArgAccessorFuncCB, DebugLoc OutlinedFnLoc)
static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, char ISA, StringRef ParSeq, StringRef MangledName, bool OutputBecomesInput, llvm::Function *Fn)
static FunctionCallee getKmpcForDynamicFiniForType(Type *Ty, Module &M, OpenMPIRBuilder &OMPBuilder)
Returns an LLVM function to call for finalizing the dynamic loop using depending on type.
static void FixupDebugInfoForOutlinedFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, Function *Func, DenseMap< Value *, std::tuple< Value *, unsigned > > &ValueReplacementMap)
static OMPScheduleType getOpenMPOrderingScheduleType(OMPScheduleType BaseScheduleType, bool HasOrderedClause)
Adds ordering modifier flags to schedule type.
static OMPScheduleType getOpenMPMonotonicityScheduleType(OMPScheduleType ScheduleType, bool HasSimdModifier, bool HasMonotonic, bool HasNonmonotonic, bool HasOrderedClause)
Adds monotonicity modifier flags to schedule type.
static std::string mangleVectorParameters(ArrayRef< llvm::OpenMPIRBuilder::DeclareSimdAttrTy > ParamAttrs)
Mangle the parameter part of the vector function name according to their OpenMP classification.
static bool isGenericKernel(Function &Fn)
static void workshareLoopTargetCallback(OpenMPIRBuilder *OMPIRBuilder, CanonicalLoopInfo *CLI, Value *Ident, Function &OutlinedFn, const SmallVector< Instruction *, 4 > &ToBeDeleted, WorksharingLoopType LoopType, bool NoLoop)
static bool isValidWorkshareLoopScheduleType(OMPScheduleType SchedType)
static bool isAtomicableReductionSet(ArrayRef< OpenMPIRBuilder::ReductionInfo > ReductionInfos)
static llvm::CallInst * emitNoUnwindRuntimeCall(IRBuilder<> &Builder, llvm::FunctionCallee Callee, ArrayRef< llvm::Value * > Args, const llvm::Twine &Name)
static Error populateReductionFunction(Function *ReductionFunc, ArrayRef< OpenMPIRBuilder::ReductionInfo > ReductionInfos, IRBuilder<> &Builder, ArrayRef< bool > IsByRef, bool IsGPU)
static Function * getFreshReductionFunc(Module &M)
static void raiseUserConstantDataAllocasToEntryBlock(IRBuilderBase &Builder, Function *Function)
static FunctionCallee getKmpcForDynamicNextForType(Type *Ty, Module &M, OpenMPIRBuilder &OMPBuilder)
Returns an LLVM function to call for updating the next loop using OpenMP dynamic scheduling depending...
static bool isConflictIP(IRBuilder<>::InsertPoint IP1, IRBuilder<>::InsertPoint IP2)
Return whether IP1 and IP2 are ambiguous, i.e.
static void checkReductionInfos(ArrayRef< OpenMPIRBuilder::ReductionInfo > ReductionInfos, bool IsGPU)
static Type * getOffloadingArrayType(Value *V)
static OMPScheduleType getOpenMPBaseScheduleType(llvm::omp::ScheduleKind ClauseKind, bool HasChunks, bool HasSimdModifier, bool HasDistScheduleChunks)
Determine which scheduling algorithm to use, determined from schedule clause arguments.
static OMPScheduleType computeOpenMPScheduleType(ScheduleKind ClauseKind, bool HasChunks, bool HasSimdModifier, bool HasMonotonicModifier, bool HasNonmonotonicModifier, bool HasOrderedClause, bool HasDistScheduleChunks)
Determine the schedule type using schedule and ordering clause arguments.
static FunctionCallee getKmpcForDynamicInitForType(Type *Ty, Module &M, OpenMPIRBuilder &OMPBuilder)
Returns an LLVM function to call for initializing loop bounds using OpenMP dynamic scheduling dependi...
static std::optional< omp::OMPTgtExecModeFlags > getTargetKernelExecMode(Function &Kernel)
Given a function, if it represents the entry point of a target kernel, this returns the execution mod...
static StructType * createTaskWithPrivatesTy(OpenMPIRBuilder &OMPIRBuilder, ArrayRef< Value * > OffloadingArraysToPrivatize)
static cl::opt< double > UnrollThresholdFactor("openmp-ir-builder-unroll-threshold-factor", cl::Hidden, cl::desc("Factor for the unroll threshold to account for code " "simplifications still taking place"), cl::init(1.5))
static cl::opt< bool > UseDefaultMaxThreads("openmp-ir-builder-use-default-max-threads", cl::Hidden, cl::desc("Use a default max threads if none is provided."), cl::init(true))
static int32_t computeHeuristicUnrollFactor(CanonicalLoopInfo *CLI)
Heuristically determine the best-performant unroll factor for CLI.
static Error emitTargetOutlinedFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, bool IsOffloadEntry, TargetRegionEntryInfo &EntryInfo, const OpenMPIRBuilder::TargetKernelDefaultAttrs &DefaultAttrs, Function *&OutlinedFn, Constant *&OutlinedFnID, SmallVectorImpl< Value * > &Inputs, OpenMPIRBuilder::TargetBodyGenCallbackTy &CBFunc, OpenMPIRBuilder::TargetGenArgAccessorsCallbackTy &ArgAccessorFuncCB, DebugLoc OutlinedFnLoc)
static 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 void updateNVPTXAttr(Function &Kernel, StringRef Name, int32_t Value, bool Min)
static OpenMPIRBuilder::InsertPointTy getInsertPointAfterInstr(Instruction *I)
static void redirectAllPredecessorsTo(BasicBlock *OldTarget, BasicBlock *NewTarget, DebugLoc DL)
Redirect all edges that branch to OldTarget to NewTarget.
static void hoistNonEntryAllocasToEntryBlock(llvm::BasicBlock &Block)
static std::unique_ptr< TargetMachine > createTargetMachine(Function *F, CodeGenOptLevel OptLevel)
Create the TargetMachine object to query the backend for optimization preferences.
static FunctionCallee getKmpcForStaticInitForType(Type *Ty, Module &M, OpenMPIRBuilder &OMPBuilder)
static void addAccessGroupMetadata(BasicBlock *Block, MDNode *AccessGroup, LoopInfo &LI)
Attach llvm.access.group metadata to the memref instructions of Block.
static void addBasicBlockMetadata(BasicBlock *BB, ArrayRef< Metadata * > Properties)
Attach metadata Properties to the basic block described by BB.
static void restoreIPandDebugLoc(llvm::IRBuilderBase &Builder, llvm::IRBuilderBase::InsertPoint IP)
This is a wrapper over IRBuilderBase::restoreIP that also restores a current debug location when the ...
static LoadInst * loadSharedDataFromTaskDescriptor(OpenMPIRBuilder &OMPIRBuilder, IRBuilderBase &Builder, Value *TaskWithPrivates, Type *TaskWithPrivatesTy)
Given a task descriptor, TaskWithPrivates, return the pointer to the block of pointers containing sha...
static cl::opt< bool > OptimisticAttributes("openmp-ir-builder-optimistic-attributes", cl::Hidden, cl::desc("Use optimistic attributes describing " "'as-if' properties of runtime calls."), cl::init(false))
static bool hasGridValue(const Triple &T)
static FunctionCallee getKmpcForStaticLoopForType(Type *Ty, OpenMPIRBuilder *OMPBuilder, WorksharingLoopType LoopType)
static const omp::GV & getGridValue(const Triple &T, Function *Kernel)
static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, StringRef Prefix, char ISA, StringRef ParSeq, StringRef MangledName, bool OutputBecomesInput, llvm::Function *Fn)
static Function * emitTargetTaskProxyFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, CallInst *StaleCI, StructType *PrivatesTy, StructType *TaskWithPrivatesTy, const size_t NumOffloadingArrays, const int SharedArgsOperandNo)
Create an entry point for a target task with the following.
static void addLoopMetadata(CanonicalLoopInfo *Loop, ArrayRef< Metadata * > Properties)
Attach loop metadata Properties to the loop described by Loop.
static AtomicOrdering TransformReleaseAcquireRelease(AtomicOrdering AO)
static void removeUnusedBlocksFromParent(ArrayRef< BasicBlock * > BBs)
static void targetParallelCallback(OpenMPIRBuilder *OMPIRBuilder, Function &OutlinedFn, Function *OuterFn, BasicBlock *OuterAllocaBB, Value *Ident, Value *IfCondition, Value *NumThreads, Instruction *PrivTID, AllocaInst *PrivTIDAddr, Value *ThreadID, const SmallVector< Instruction *, 4 > &ToBeDeleted)
static void hostParallelCallback(OpenMPIRBuilder *OMPIRBuilder, Function &OutlinedFn, Function *OuterFn, Value *Ident, Value *IfCondition, Instruction *PrivTID, AllocaInst *PrivTIDAddr, const SmallVector< Instruction *, 4 > &ToBeDeleted)
FunctionAnalysisManager FAM
This file defines the Pass Instrumentation classes that provide instrumentation points into the pass ...
const SmallVectorImpl< MachineOperand > & Cond
Remove Loads Into Fake Uses
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
SmallPtrSet< BasicBlock *, 0 > BlockSet
This file implements the SmallBitVector class.
This file defines the SmallSet class.
static SymbolRef::Type getType(const Symbol *Sym)
Defines the virtual file system interface vfs::FileSystem.
static cl::opt< unsigned > MaxThreads("xcore-max-threads", cl::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.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
An arbitrary precision integer that knows its signedness.
static APSInt getUnsigned(uint64_t X)
This class represents a conversion between pointers from one address space to another.
an instruction to allocate memory on the stack
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
PointerType * getType() const
Overload to return most specific pointer type.
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
unsigned getAddressSpace() const
Return the address space for the allocation.
LLVM_ABI std::optional< TypeSize > getAllocationSize(const DataLayout &DL) const
Get allocation size in bytes.
LLVM_ABI bool isArrayAllocation() const
Return true if there is an allocation size parameter to the allocation instruction that is not 1.
void setAlignment(Align Align)
const Value * getArraySize() const
Get the number of elements allocated.
bool registerPass(PassBuilderT &&PassBuilder)
Register an analysis pass with the manager.
This class represents an incoming formal argument to a Function.
unsigned getArgNo() const
Return the index of this formal argument in its containing function.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
Class to represent array types.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
A function analysis which provides an AssumptionCache.
LLVM_ABI AssumptionCache run(Function &F, FunctionAnalysisManager &)
A cache of @llvm.assume calls within a function.
An instruction that atomically checks whether a specified value is in a memory location,...
void setWeak(bool IsWeak)
static AtomicOrdering getStrongestFailureOrdering(AtomicOrdering SuccessOrdering)
Returns the strongest permitted ordering on failure, given the desired ordering on success.
LLVM_ABI std::pair< LoadInst *, AllocaInst * > EmitAtomicLoadLibcall(AtomicOrdering AO)
LLVM_ABI void EmitAtomicStoreLibcall(AtomicOrdering AO, Value *Source)
an instruction that atomically reads a memory location, combines it with another value,...
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ FMinimum
*p = minimum(old, v) minimum matches the behavior of llvm.minimum.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ FMaximum
*p = maximum(old, v) maximum matches the behavior of llvm.maximum.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ FMin
*p = minnum(old, v) minnum matches the behavior of llvm.minnum.
@ UMax
*p = old >unsigned v ? old : v
@ FMaximumNum
*p = maximumnum(old, v) maximumnum matches the behavior of llvm.maximumnum.
@ FMax
*p = maxnum(old, v) maxnum matches the behavior of llvm.maxnum.
@ UDecWrap
Decrement one until a minimum value or zero.
@ FMinimumNum
*p = minimumnum(old, v) minimumnum matches the behavior of llvm.minimumnum.
This class holds the attributes for a particular argument, parameter, function, or return value.
LLVM_ABI AttributeSet addAttributes(LLVMContext &C, AttributeSet AS) const
Add attributes to the attribute set.
LLVM_ABI AttributeSet addAttribute(LLVMContext &C, Attribute::AttrKind Kind) const
Add an argument attribute.
static LLVM_ABI Attribute getWithAlignment(LLVMContext &Context, Align Alignment)
Return a uniquified Attribute object that has the specific alignment set.
LLVM Basic Block Representation.
LLVM_ABI void replaceSuccessorsPhiUsesWith(BasicBlock *Old, BasicBlock *New)
Update all phi nodes in this basic block's successors to refer to basic block New instead of basic bl...
iterator begin()
Instruction iterator methods.
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
reverse_iterator rbegin()
bool hasTerminator() const LLVM_READONLY
Returns whether the block has a terminator.
const Instruction & back() const
LLVM_ABI BasicBlock * splitBasicBlockBefore(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction and insert the new basic blo...
LLVM_ABI InstListType::const_iterator getFirstNonPHIIt() const
Returns an iterator to the first instruction in this block that is not a PHINode instruction.
LLVM_ABI void insertDbgRecordBefore(DbgRecord *DR, InstListType::iterator Here)
Insert a DbgRecord into a block at the position given by Here.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
LLVM_ABI InstListType::const_iterator getFirstNonPHIOrDbg(bool SkipPseudoOp=true) const
Returns a pointer to the first instruction in this block that is not a PHINode or a debug intrinsic,...
LLVM_ABI const BasicBlock * getUniqueSuccessor() const
Return the successor of this block if it has a unique successor.
LLVM_ABI const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
const Instruction & front() const
InstListType::reverse_iterator reverse_iterator
LLVM_ABI const BasicBlock * getUniquePredecessor() const
Return the predecessor of this block if it has a unique predecessor block.
const Instruction * getTerminatorOrNull() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
LLVM_ABI const BasicBlock * getSingleSuccessor() const
Return the successor of this block if it has a single successor.
LLVM_ABI SymbolTableList< BasicBlock >::iterator eraseFromParent()
Unlink 'this' from the containing function and delete it.
InstListType::iterator iterator
Instruction iterators...
LLVM_ABI LLVMContext & getContext() const
Get the context in which this basic block lives.
void moveBefore(BasicBlock *MovePos)
Unlink this basic block from its current function and insert it into the function that MovePos lives ...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
void splice(BasicBlock::iterator ToIt, BasicBlock *FromBB)
Transfer all instructions from FromBB to this basic block at ToIt.
LLVM_ABI void removePredecessor(BasicBlock *Pred, bool KeepOneInputPHIs=false)
Update PHI nodes in this BasicBlock before removal of predecessor Pred.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
User::op_iterator arg_begin()
Return the iterator pointing to the beginning of the argument list.
Value * getArgOperand(unsigned i) const
User::op_iterator arg_end()
Return the iterator pointing to the end of the argument list.
unsigned arg_size() const
This class represents a function call, abstracting a target machine's calling convention.
Class to represented the control flow structure of an OpenMP canonical loop.
Value * getTripCount() const
Returns the llvm::Value containing the number of loop iterations.
BasicBlock * getHeader() const
The header is the entry for each iteration.
LLVM_ABI void assertOK() const
Consistency self-check.
Type * getIndVarType() const
Return the type of the induction variable (and the trip count).
BasicBlock * getBody() const
The body block is the single entry for a loop iteration and not controlled by CanonicalLoopInfo.
bool isValid() const
Returns whether this object currently represents the IR of a loop.
void setLastIter(Value *IterVar)
Sets the last iteration variable for this loop.
OpenMPIRBuilder::InsertPointTy getAfterIP() const
Return the insertion point for user code after the loop.
OpenMPIRBuilder::InsertPointTy getBodyIP() const
Return the insertion point for user code in the body.
BasicBlock * getAfter() const
The after block is intended for clean-up code such as lifetime end markers.
Function * getFunction() const
LLVM_ABI void invalidate()
Invalidate this loop.
BasicBlock * getLatch() const
Reaching the latch indicates the end of the loop body code.
OpenMPIRBuilder::InsertPointTy getPreheaderIP() const
Return the insertion point for user code before the loop.
BasicBlock * getCond() const
The condition block computes whether there is another loop iteration.
BasicBlock * getExit() const
Reaching the exit indicates no more iterations are being executed.
LLVM_ABI BasicBlock * getPreheader() const
The preheader ensures that there is only a single edge entering the loop.
Instruction * getIndVar() const
Returns the instruction representing the current logical induction variable.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ ICMP_ULT
unsigned less than
@ ICMP_ULE
unsigned less or equal
static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)
get() constructor - Return a constant with array type with an element count and element type matching...
static LLVM_ABI Constant * getString(LLVMContext &Context, StringRef Initializer, bool AddNull=true, bool ByteString=false)
This method constructs a CDS and initializes it with a text string.
static LLVM_ABI Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
static LLVM_ABI Constant * 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 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.
DISubprogram * getSubprogram() const
Get the attached subprogram.
AttributeList getAttributes() const
Return the attribute list for this Function.
const Function & getFunction() const
void setAttributes(AttributeList Attrs)
Set the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
adds the attribute to the list of attributes for the given arg.
Function::iterator insert(Function::iterator Position, BasicBlock *BB)
Insert BB in the basic block list at Position.
Type * getReturnType() const
Returns the type of the ret val.
void setCallingConv(CallingConv::ID CC)
Argument * getArg(unsigned i) const
bool hasMetadata() const
Return true if this GlobalObject has any metadata attached to it.
LLVM_ABI void addMetadata(unsigned KindID, MDNode &MD)
Add a metadata attachment.
LinkageTypes getLinkage() const
void setLinkage(LinkageTypes LT)
Module * getParent()
Get the module that this global value is contained inside of...
void setDSOLocal(bool Local)
PointerType * getType() const
Global values are always pointers.
@ HiddenVisibility
The GV is hidden.
@ ProtectedVisibility
The GV is protected.
void setVisibility(VisibilityTypes V)
LinkageTypes
An enumeration for the kinds of linkage for global values.
@ PrivateLinkage
Like Internal, but omit from symbol table.
@ CommonLinkage
Tentative definitions.
@ InternalLinkage
Rename collisions when linking (static functions).
@ WeakODRLinkage
Same, but only replaced by something equivalent.
@ WeakAnyLinkage
Keep one copy of named function when linking (weak)
@ AppendingLinkage
Special purpose, only applies to global arrays.
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
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 void registerDeclareTargetGlobalReplacement(GlobalValue *Original, GlobalValue *Replacement)
Register a module-scope replacement of a declare target global variable.
LLVM_ABI FunctionCallee getOrCreateRuntimeFunction(Module &M, omp::RuntimeFunction FnID)
Return the function declaration for the runtime function with FnID.
LLVM_ABI InsertPointOrErrorTy createCancel(const LocationDescription &Loc, Value *IfCondition, omp::Directive CanceledDirective)
Generator for 'omp cancel'.
std::function< Expected< Function * >(StringRef FunctionName)> FunctionGenCallback
Functions used to generate a function with the given name.
LLVM_ABI CallInst * createOMPAllocShared(const LocationDescription &Loc, Value *Size, const Twine &Name=Twine(""))
Create a runtime call for kmpc_alloc_shared.
ReductionGenCBKind
Enum class for the RedctionGen CallBack type to be used.
LLVM_ABI CanonicalLoopInfo * collapseLoops(DebugLoc DL, ArrayRef< CanonicalLoopInfo * > Loops, InsertPointTy ComputeIP)
Collapse a loop nest into a single loop.
LLVM_ABI void createTaskyield(const LocationDescription &Loc)
Generator for 'omp taskyield'.
std::function< Error(InsertPointTy CodeGenIP)> FinalizeCallbackTy
Callback type for variable finalization (think destructors).
LLVM_ABI void emitBranch(BasicBlock *Target)
LLVM_ABI Error emitCancelationCheckImpl(Value *CancelFlag, omp::Directive CanceledDirective)
Generate control flow and cleanup for cancellation.
static LLVM_ABI void writeThreadBoundsForKernel(const Triple &T, Function &Kernel, int32_t LB, int32_t UB)
LLVM_ABI void emitTaskwaitImpl(const LocationDescription &Loc)
Generate a taskwait runtime call.
LLVM_ABI Constant * registerTargetRegionFunction(TargetRegionEntryInfo &EntryInfo, Function *OutlinedFunction, StringRef EntryFnName, StringRef EntryFnIDName)
Registers the given function and sets up the attribtues of the function Returns the FunctionID.
LLVM_ABI GlobalVariable * emitKernelExecutionMode(StringRef KernelName, omp::OMPTgtExecModeFlags Mode)
Emit the kernel execution mode.
LLVM_ABI void initialize()
Initialize the internal state, this will put structures types and potentially other helpers into the ...
LLVM_ABI InsertPointTy createAtomicCompare(const LocationDescription &Loc, AtomicOpValue &X, AtomicOpValue &V, AtomicOpValue &R, Value *E, Value *D, AtomicOrdering AO, omp::OMPAtomicCompareOp Op, bool IsXBinopExpr, bool IsPostfixUpdate, bool IsFailOnly, bool IsWeak=false)
LLVM_ABI InsertPointTy createAtomicWrite(const LocationDescription &Loc, AtomicOpValue &X, Value *Expr, AtomicOrdering AO, InsertPointTy AllocaIP)
Emit atomic write for : X = Expr — Only Scalar data types.
LLVM_ABI void loadOffloadInfoMetadata(Module &M)
Loads all the offload entries information from the host IR metadata.
function_ref< MapInfosTy &(InsertPointTy CodeGenIP)> GenMapInfoCallbackTy
Callback type for creating the map infos for the kernel parameters.
LLVM_ABI Error emitOffloadingArrays(InsertPointTy AllocaIP, InsertPointTy CodeGenIP, MapInfosTy &CombinedInfo, TargetDataInfo &Info, CustomMapperCallbackTy CustomMapperCB, bool IsNonContiguous=false, function_ref< void(unsigned int, Value *)> DeviceAddrCB=nullptr)
Emit the arrays used to pass the captures and map information to the offloading runtime library.
LLVM_ABI void unrollLoopFull(DebugLoc DL, CanonicalLoopInfo *Loop)
Fully unroll a loop.
function_ref< Error(InsertPointTy CodeGenIP, Value *IndVar)> LoopBodyGenCallbackTy
Callback type for loop body code generation.
LLVM_ABI InsertPointOrErrorTy emitScanReduction(const LocationDescription &Loc, ArrayRef< llvm::OpenMPIRBuilder::ReductionInfo > ReductionInfos, ScanInfo *ScanRedInfo)
This function performs the scan reduction of the values updated in the input phase.
LLVM_ABI void emitFlush(const LocationDescription &Loc)
Generate a flush runtime call.
LLVM_ABI InsertPointOrErrorTy createScope(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, bool IsNowait)
Generator for 'omp scope'.
static LLVM_ABI std::pair< int32_t, int32_t > readThreadBoundsForKernel(const Triple &T, Function &Kernel)
}
OpenMPIRBuilderConfig Config
The OpenMPIRBuilder Configuration.
LLVM_ABI CallInst * createOMPInteropDestroy(const LocationDescription &Loc, Value *InteropVar, Value *Device, Value *NumDependences, Value *DependenceAddress, bool HaveNowaitClause)
Create a runtime call for __tgt_interop_destroy.
LLVM_ABI void emitUsed(StringRef Name, ArrayRef< llvm::WeakTrackingVH > List)
Emit the llvm.used metadata.
LLVM_ABI InsertPointOrErrorTy createSingle(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, bool IsNowait, ArrayRef< llvm::Value * > CPVars={}, ArrayRef< llvm::Function * > CPFuncs={})
Generator for 'omp single'.
LLVM_ABI InsertPointOrErrorTy 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 std::string createPlatformSpecificName(ArrayRef< StringRef > Parts) const
Get the create a name using the platform specific separators.
LLVM_ABI FunctionCallee createDispatchNextFunction(unsigned IVSize, bool IVSigned)
Returns __kmpc_dispatch_next_* runtime function for the specified size IVSize and sign IVSigned.
static LLVM_ABI void getKernelArgsVector(TargetKernelArgs &KernelArgs, IRBuilderBase &Builder, SmallVector< Value * > &ArgsVector)
Create the kernel args vector used by emitTargetKernel.
LLVM_ABI void unrollLoopHeuristic(DebugLoc DL, CanonicalLoopInfo *Loop)
Fully or partially unroll a loop.
LLVM_ABI omp::OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position)
Get OMP_MAP_MEMBER_OF flag with extra bits reserved based on the position given.
LLVM_ABI void addAttributes(omp::RuntimeFunction FnID, Function &Fn)
Add attributes known for FnID to Fn.
Module & M
The underlying LLVM-IR module.
StringMap< Constant * > SrcLocStrMap
Map to remember source location strings.
LLVM_ABI void createMapperAllocas(const LocationDescription &Loc, InsertPointTy AllocaIP, unsigned NumOperands, struct MapperAllocas &MapperAllocas)
Create the allocas instruction used in call to mapper functions.
SmallVector< DeclareTargetGlobalReplacement, 8 > DeclareTargetGlobalReplacements
Collection of declare target globals to rewrite uses of during device module finalizaiton.
LLVM_ABI Constant * getOrCreateSrcLocStr(StringRef LocStr, uint32_t &SrcLocStrSize)
Return the (LLVM-IR) string describing the source location LocStr.
LLVM_ABI Error emitTargetRegionFunction(TargetRegionEntryInfo &EntryInfo, FunctionGenCallback &GenerateFunctionCallback, bool IsOffloadEntry, Function *&OutlinedFn, Constant *&OutlinedFnID)
Create a unique name for the entry function using the source location information of the current targ...
LLVM_ABI InsertPointOrErrorTy createIteratorLoop(LocationDescription Loc, llvm::Value *TripCount, IteratorBodyGenTy BodyGen, llvm::StringRef Name="iterator")
Create a canonical iterator loop at the current insertion point.
LLVM_ABI Expected< SmallVector< llvm::CanonicalLoopInfo * > > createCanonicalScanLoops(const LocationDescription &Loc, LoopBodyGenCallbackTy BodyGenCB, Value *Start, Value *Stop, Value *Step, bool IsSigned, bool InclusiveStop, InsertPointTy ComputeIP, const Twine &Name, ScanInfo *ScanRedInfo)
Generator for the control flow structure of an OpenMP canonical loops if the parent directive has an ...
LLVM_ABI FunctionCallee createDispatchFiniFunction(unsigned IVSize, bool IVSigned)
Returns __kmpc_dispatch_fini_* runtime function for the specified size IVSize and sign IVSigned.
function_ref< InsertPointOrErrorTy( InsertPointTy AllocaIP, InsertPointTy CodeGenIP, ArrayRef< BasicBlock * > DeallocBlocks)> TargetBodyGenCallbackTy
LLVM_ABI void unrollLoopPartial(DebugLoc DL, CanonicalLoopInfo *Loop, int32_t Factor, CanonicalLoopInfo **UnrolledCLI)
Partially unroll a loop.
function_ref< Error(Value *DeviceID, Value *RTLoc, IRBuilderBase::InsertPoint TargetTaskAllocaIP)> TargetTaskBodyCallbackTy
Callback type for generating the bodies of device directives that require outer target tasks (e....
Expected< MapInfosTy & > MapInfosOrErrorTy
bool HandleFPNegZero
Emit atomic compare for constructs: — Only scalar data types cond-expr-stmt: x = x ordop expr ?
LLVM_ABI void emitTaskyieldImpl(const LocationDescription &Loc)
Generate a taskyield runtime call.
LLVM_ABI void emitMapperCall(const LocationDescription &Loc, Function *MapperFunc, Value *SrcLocInfo, Value *MaptypesArg, Value *MapnamesArg, struct MapperAllocas &MapperAllocas, int64_t DeviceID, unsigned NumOperands)
Create the call for the target mapper function.
LLVM_ABI InsertPointOrErrorTy createDistribute(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< BasicBlock * > DeallocBlocks, BodyGenCallbackTy BodyGenCB)
Generator for #omp distribute
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 createTarget(const LocationDescription &Loc, bool IsOffloadEntry, OpenMPIRBuilder::InsertPointTy AllocaIP, OpenMPIRBuilder::InsertPointTy CodeGenIP, ArrayRef< BasicBlock * > DeallocBlocks, TargetDataInfo &Info, TargetRegionEntryInfo &EntryInfo, const TargetKernelDefaultAttrs &DefaultAttrs, const TargetKernelRuntimeAttrs &RuntimeAttrs, Value *IfCond, SmallVectorImpl< Value * > &Inputs, GenMapInfoCallbackTy GenMapInfoCB, TargetBodyGenCallbackTy BodyGenCB, TargetGenArgAccessorsCallbackTy ArgAccessorFuncCB, CustomMapperCallbackTy CustomMapperCB, const DependenciesInfo &Dependencies={}, bool HasNowait=false, Value *DynCGroupMem=nullptr, omp::OMPDynGroupprivateFallbackType DynCGroupMemFallback=omp::OMPDynGroupprivateFallbackType::Abort, DebugLoc OutlinedFnLoc={})
Generator for 'omp target'.
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 CanonicalLoopInfo * createLoopSkeleton(DebugLoc DL, Value *TripCount, Function *F, BasicBlock *PreInsertBefore, BasicBlock *PostInsertBefore, const Twine &Name={}, bool IsCollapsed=false)
Create the control flow structure of a canonical OpenMP loop.
LLVM_ABI void createOffloadEntriesAndInfoMetadata(EmitMetadataErrorReportFunctionTy &ErrorReportFunction)
LLVM_ABI void applySimd(CanonicalLoopInfo *Loop, MapVector< Value *, Value * > AlignedVars, Value *IfCond, omp::OrderKind Order, ConstantInt *Simdlen, ConstantInt *Safelen)
Add metadata to simd-ize a loop.
SmallVector< std::unique_ptr< OutlineInfo >, 16 > OutlineInfos
Collection of regions that need to be outlined during finalization.
LLVM_ABI InsertPointOrErrorTy createAtomicUpdate(const LocationDescription &Loc, InsertPointTy AllocaIP, AtomicOpValue &X, Value *Expr, AtomicOrdering AO, AtomicRMWInst::BinOp RMWOp, AtomicUpdateCallbackTy &UpdateOp, bool IsXBinopExpr, bool IsIgnoreDenormalMode=false, bool IsFineGrainedMemory=false, bool IsRemoteMemory=false)
Emit atomic update for constructs: X = X BinOp Expr ,or X = Expr BinOp X For complex Operations: X = ...
std::function< std::tuple< std::string, uint64_t >()> FileIdentifierInfoCallbackTy
bool isLastFinalizationInfoCancellable(omp::Directive DK)
Return true if the last entry in the finalization stack is of kind DK and cancellable.
LLVM_ABI InsertPointTy emitTargetKernel(const LocationDescription &Loc, InsertPointTy AllocaIP, Value *&Return, Value *Ident, Value *DeviceID, Value *NumTeams, Value *NumThreads, Value *HostPtr, ArrayRef< Value * > KernelArgs)
Generate a target region entry call.
LLVM_ABI GlobalVariable * createOffloadMaptypes(SmallVectorImpl< uint64_t > &Mappings, std::string VarName)
Create the global variable holding the offload mappings information.
LLVM_ABI ~OpenMPIRBuilder()
LLVM_ABI Expected< Function * > emitUserDefinedMapper(function_ref< MapInfosOrErrorTy(InsertPointTy CodeGenIP, llvm::Value *PtrPHI, llvm::Value *BeginArg)> PrivAndGenMapInfoCB, llvm::Type *ElemTy, StringRef FuncName, CustomMapperCallbackTy CustomMapperCB, bool PreserveMemberOfFlags=false, bool PropagatePresentToPointee=false)
Emit the user-defined mapper function.
LLVM_ABI CallInst * createCachedThreadPrivate(const LocationDescription &Loc, llvm::Value *Pointer, llvm::ConstantInt *Size, const llvm::Twine &Name=Twine(""))
Create a runtime call for kmpc_threadprivate_cached.
IRBuilder Builder
The LLVM-IR Builder used to create IR.
LLVM_ABI GlobalValue * createGlobalFlag(unsigned Value, StringRef Name)
Create a hidden global flag Name in the module with initial value Value.
LLVM_ABI void emitOffloadingArraysArgument(IRBuilderBase &Builder, OpenMPIRBuilder::TargetDataRTArgs &RTArgs, OpenMPIRBuilder::TargetDataInfo &Info, bool ForEndCall=false)
Emit the arguments to be passed to the runtime library based on the arrays of base pointers,...
LLVM_ABI InsertPointOrErrorTy createMasked(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, Value *Filter)
Generator for 'omp masked'.
LLVM_ABI Expected< CanonicalLoopInfo * > createCanonicalLoop(const LocationDescription &Loc, LoopBodyGenCallbackTy BodyGenCB, Value *TripCount, const Twine &Name="loop")
Generator for the control flow structure of an OpenMP canonical loop.
function_ref< Expected< InsertPointTy >( InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Value *DestPtr, Value *SrcPtr)> TaskDupCallbackTy
Callback type for task duplication function code generation.
LLVM_ABI Value * getSizeInBytes(Value *BasePtr)
Computes the size of type in bytes.
llvm::function_ref< llvm::Error( InsertPointTy BodyIP, llvm::Value *LinearIV)> IteratorBodyGenTy
LLVM_ABI FunctionCallee createDispatchDeinitFunction()
Returns __kmpc_dispatch_deinit runtime function.
LLVM_ABI void registerTargetGlobalVariable(OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind CaptureClause, OffloadEntriesInfoManager::OMPTargetDeviceClauseKind DeviceClause, bool IsDeclaration, bool IsExternallyVisible, TargetRegionEntryInfo EntryInfo, StringRef MangledName, std::vector< GlobalVariable * > &GeneratedRefs, bool OpenMPSIMD, std::vector< Triple > TargetTriple, std::function< Constant *()> GlobalInitializer, std::function< GlobalValue::LinkageTypes()> VariableLinkage, Type *LlvmPtrTy, Constant *Addr)
Registers a target variable for device or host.
LLVM_ABI void createTargetDeinit(const LocationDescription &Loc, int32_t TeamsReductionDataSize=0)
Create a runtime call for kmpc_target_deinit.
BodyGenTy
Type of BodyGen to use for region codegen.
LLVM_ABI CanonicalLoopInfo * fuseLoops(DebugLoc DL, ArrayRef< CanonicalLoopInfo * > Loops)
Fuse a sequence of loops.
LLVM_ABI void emitX86DeclareSimdFunction(llvm::Function *Fn, unsigned NumElements, const llvm::APSInt &VLENVal, llvm::ArrayRef< DeclareSimdAttrTy > ParamAttrs, DeclareSimdBranch Branch)
Emit x86 vector-function ABI attributes for a declare simd function.
SmallVector< llvm::Function *, 16 > ConstantAllocaRaiseCandidates
A collection of candidate target functions that's constant allocas will attempt to be raised on a cal...
OffloadEntriesInfoManager OffloadInfoManager
Info manager to keep track of target regions.
static LLVM_ABI std::pair< int32_t, int32_t > readTeamBoundsForKernel(const Triple &T, Function &Kernel)
Read/write a bounds on teams for Kernel.
const std::string ompOffloadInfoName
OMP Offload Info Metadata name string.
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(LLVMContext &C)
This constructs an opaque pointer to an object in the default address space (address space zero).
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
Analysis pass that exposes the ScalarEvolution for a function.
LLVM_ABI ScalarEvolution run(Function &F, FunctionAnalysisManager &AM)
The main scalar evolution driver.
ScanInfo holds the information to assist in lowering of Scan reduction.
llvm::SmallDenseMap< llvm::Value *, llvm::Value * > * ScanBuffPtrs
Maps the private reduction variable to the pointer of the temporary buffer.
llvm::BasicBlock * OMPScanLoopExit
Exit block of loop body.
llvm::Value * IV
Keeps track of value of iteration variable for input/scan loop to be used for Scan directive lowering...
llvm::BasicBlock * OMPAfterScanBlock
Dominates the body of the loop before scan directive.
llvm::BasicBlock * OMPScanInit
Block before loop body where scan initializations are done.
llvm::BasicBlock * OMPBeforeScanBlock
Dominates the body of the loop before scan directive.
llvm::BasicBlock * OMPScanFinish
Block after loop body where scan finalizations are done.
llvm::Value * Span
Stores the span of canonical loop being lowered to be used for temporary buffer allocation or Finaliz...
bool OMPFirstScanLoop
If true, it indicates Input phase is lowered; else it indicates ScanPhase is lowered.
llvm::BasicBlock * OMPScanDispatch
Controls the flow to before or after scan blocks.
A vector that has set insertion semantics.
bool remove_if(UnaryPredicate P)
Remove items from the set vector based on a predicate function.
bool empty() const
Determine if the SetVector is empty or not.
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
bool test(unsigned Idx) const
Returns true if bit Idx is set.
bool all() const
Returns true if all bits are set.
bool any() const
Returns true if any bit is set.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void append(StringRef RHS)
Append from a StringRef.
StringRef str() const
Explicit conversion to StringRef.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
void setAlignment(Align Align)
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this store instruction.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
ValueTy lookup(StringRef Key) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
Represent a constant reference to a string, i.e.
std::string str() const
Get the contents as an std::string.
constexpr bool empty() const
Check if the string is empty.
constexpr size_t size() const
Get the string size.
size_t count(char C) const
Return the number of occurrences of C in the string.
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
Class to represent struct types.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
static LLVM_ABI StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Type * getElementType(unsigned N) const
LLVM_ABI void addCase(ConstantInt *OnVal, BasicBlock *Dest)
Add an entry to the switch instruction.
Analysis pass providing the TargetTransformInfo.
LLVM_ABI Result run(const Function &F, FunctionAnalysisManager &)
TargetTransformInfo Result
Analysis pass providing the TargetLibraryInfo.
Target - Wrapper for Target specific information.
TargetMachine * createTargetMachine(const Triple &TT, StringRef CPU, StringRef Features, const TargetOptions &Options, std::optional< Reloc::Model > RM, std::optional< CodeModel::Model > CM=std::nullopt, CodeGenOptLevel OL=CodeGenOptLevel::Default, bool JIT=false) const
createTargetMachine - Create a target specific machine implementation for the specified Triple.
Triple - Helper class for working with autoconf configuration names.
bool isPPC() const
Tests whether the target is PowerPC (32- or 64-bit LE or BE).
bool isX86() const
Tests whether the target is x86 (32- or 64-bit).
bool isWasm() const
Tests whether the target is wasm (32- and 64-bit).
bool isSystemZ() const
Tests whether the target is SystemZ.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
LLVM_ABI unsigned getIntegerBitWidth() const
LLVM_ABI Type * getStructElementType(unsigned N) const
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isPointerTy() const
True if this is an instance of PointerType.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
bool isStructTy() const
True if this is an instance of StructType.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
bool isVoidTy() const
Return true if this is 'void'.
Unconditional Branch instruction.
static UncondBrInst * Create(BasicBlock *Target, InsertPosition InsertBefore=nullptr)
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
This function has undefined behavior.
Produce an estimate of the unrolled cost of the specified loop.
LLVM_ABI bool canUnroll(OptimizationRemarkEmitter *ORE=nullptr, const Loop *L=nullptr) const
Whether it is legal to unroll this loop.
uint64_t getRolledLoopSize() const
A Use represents the edge between a Value definition and its users.
void setOperand(unsigned i, Value *Val)
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
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.
iterator_range< user_iterator > users()
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
LLVM_ABI bool hasNUses(unsigned N) const
Return true if this Value has exactly N uses.
LLVM_ABI User * getUniqueUndroppableUser()
Return true if there is exactly one unique user of this value that cannot be dropped (that user can h...
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
LLVM_ABI bool replaceUsesWithIf(Value *New, llvm::function_ref< bool(Use &U)> ShouldReplace)
Go through the uses list for this definition and make each use point to "V" if the callback ShouldRep...
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
A raw_ostream that writes to an SmallVector or SmallString.
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.
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ SPIR_KERNEL
Used for SPIR kernel functions.
@ PTX_Kernel
Call to a PTX kernel. Passes all arguments in parameter space.
@ BasicBlock
Various leaf nodes.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
Flag
These should be considered private to the implementation of the MCInstrDesc class.
constexpr StringLiteral MaxNTID("nvvm.maxntid")
constexpr StringLiteral MaxClusterRank("nvvm.maxclusterrank")
initializer< Ty > init(const Ty &Val)
@ User
could "use" a pointer
LLVM_ABI GlobalVariable * emitOffloadingEntry(Module &M, object::OffloadKind Kind, Constant *Addr, StringRef Name, uint64_t Size, uint32_t Flags, uint64_t Data, Constant *AuxAddr=nullptr)
OpenMPOffloadMappingFlags
Values for bit flags used to specify the mapping type for offloading.
@ OMP_MAP_PTR_AND_OBJ
The element being mapped is a pointer-pointee pair; both the pointer and the pointee should be mapped...
@ OMP_MAP_MEMBER_OF
The 16 MSBs of the flags indicate whether the entry is member of some struct/class.
IdentFlag
IDs for all omp runtime library ident_t flag encodings (see their defintion in openmp/runtime/src/kmp...
RuntimeFunction
IDs for all omp runtime library (RTL) functions.
constexpr const GV & getAMDGPUGridValues()
static constexpr GV SPIRVGridValues
For generic SPIR-V GPUs.
OMPDynGroupprivateFallbackType
The fallback types for the dyn_groupprivate clause.
static constexpr GV NVPTXGridValues
For Nvidia GPUs.
@ OMP_TGT_EXEC_MODE_SPMD_NO_LOOP
@ OMP_TGT_EXEC_MODE_GENERIC
Function * Kernel
Summary of a kernel (=entry point for target offloading).
WorksharingLoopType
A type of worksharing loop construct.
EnumSet< Property, Property_enumSize > Properties
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)
constexpr unsigned BitWidth
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
LLVM_ABI void spliceBB(IRBuilderBase::InsertPoint IP, BasicBlock *New, bool CreateBranch, DebugLoc DL)
Move the instruction after an InsertPoint to the beginning of another BasicBlock.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
auto predecessors(const MachineBasicBlock *BB)
auto filter_to_vector(ContainerTy &&C, PredicateFn &&Pred)
Filter a range to a SmallVector with the element types deduced.
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
LLVM_ABI Constant * ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val, ArrayRef< unsigned > Idxs)
Attempt to constant fold an insertvalue instruction with the specified operands and indices.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI void DeleteDeadBlocks(ArrayRef< BasicBlock * > BBs, DomTreeUpdater *DTU=nullptr, bool KeepOneInputPHIs=false)
Delete the specified blocks from BB.
bool to_integer(StringRef S, N &Num, unsigned Base=0)
Convert the string S to an integer of the specified type using the radix Base. If Base is 0,...
static auto filterDbgVars(iterator_range< simple_ilist< DbgRecord >::iterator > R)
Filter the DbgRecord range to DbgVariableRecord types only and downcast.
This struct is a compact representation of a valid (non-zero power of two) alignment.
static LLVM_ABI void collectEphemeralValues(const Loop *L, AssumptionCache *AC, SmallPtrSetImpl< const Value * > &EphValues)
Collect a loop's ephemeral values (those used only by an assume or similar intrinsics in the loop).
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
A struct to pack the relevant information for an OpenMP affinity clause.
a struct to pack relevant information while generating atomic Ops
A struct to pack the relevant information for an OpenMP depend clause.
omp::RTLDependenceKindTy DepKind
A struct to pack static and dynamic dependency information for a task.
SmallVector< DependData > Deps
LLVM_ABI Error mergeFiniBB(IRBuilderBase &Builder, BasicBlock *ExistingFiniBB)
For cases where there is an unavoidable existing finalization block (e.g.
LLVM_ABI Expected< BasicBlock * > getFiniBB(IRBuilderBase &Builder)
The basic block to which control should be transferred to implement the FiniCB.
Description of a LLVM-IR insertion point (IP) and a debug/source location (filename,...
MapNonContiguousArrayTy Offsets
MapNonContiguousArrayTy Counts
MapNonContiguousArrayTy Strides
This structure contains combined information generated for mappable clauses, including base pointers,...
MapDeviceInfoArrayTy DevicePointers
MapValuesArrayTy BasePointers
MapValuesArrayTy Pointers
StructNonContiguousInfo NonContigInfo
Helper that contains information about regions we need to outline during finalization.
void collectBlocks(SmallPtrSetImpl< BasicBlock * > &BlockSet, SmallVectorImpl< BasicBlock * > &BlockVector)
Collect all blocks in between EntryBB and ExitBB in both the given vector and set.
BasicBlock * OuterAllocBB
virtual std::unique_ptr< CodeExtractor > createCodeExtractor(ArrayRef< BasicBlock * > Blocks, bool ArgsInZeroAddressSpace, Twine Suffix=Twine(""))
Create a CodeExtractor instance based on the information stored in this structure,...
Information about an OpenMP reduction.
EvalKind EvaluationKind
Reduction evaluation kind - scalar, complex or aggregate.
ReductionGenAtomicCBTy AtomicReductionGen
Callback for generating the atomic reduction body, may be null.
ReductionGenCBTy ReductionGen
Callback for generating the reduction body.
Value * Variable
Reduction variable of pointer type.
Value * PrivateVariable
Thread-private partial reduction variable.
ReductionGenClangCBTy ReductionGenClang
Clang callback for generating the reduction body.
Type * ElementType
Reduction element type, must match pointee type of variable.
ReductionGenDataPtrPtrCBTy DataPtrPtrGen
Container for the arguments used to pass data to the runtime library.
Value * SizesArray
The array of sizes passed to the runtime library.
Value * PointersArray
The array of section pointers passed to the runtime library.
Value * MappersArray
The array of user-defined mappers passed to the runtime library.
Value * MapTypesArrayEnd
The array of map types passed to the runtime library for the end of the region, or nullptr if there a...
Value * BasePointersArray
The array of base pointer passed to the runtime library.
Value * MapTypesArray
The array of map types passed to the runtime library for the beginning of the region or for the entir...
Value * MapNamesArray
The array of original declaration names of mapped pointers sent to the runtime library for debugging.
Data structure that contains the needed information to construct the kernel args vector.
bool StrictBlocks
True if the kernel strictly requires the number of blocks and threads above to run.
ArrayRef< Value * > NumThreads
The number of threads.
TargetDataRTArgs RTArgs
Arguments passed to the runtime library.
Value * NumIterations
The number of iterations.
Value * DynCGroupMem
The size of the dynamic shared memory.
unsigned NumTargetItems
Number of arguments passed to the runtime library.
bool HasNoWait
True if the kernel has 'no wait' clause.
ArrayRef< Value * > NumTeams
The number of teams.
omp::OMPDynGroupprivateFallbackType DynCGroupMemFallback
The fallback mechanism for the shared memory.
Container to pass the default attributes with which a kernel must be launched, used to set kernel att...
omp::OMPTgtExecModeFlags ExecFlags
SmallVector< int32_t, 3 > MaxTeams
Container to pass LLVM IR runtime values or constants related to the number of teams and threads with...
Value * DeviceID
Device ID value used in the kernel launch.
SmallVector< Value *, 3 > MaxTeams
Value * LoopTripCount
Total number of iterations of the SPMD or Generic-SPMD kernel or null if it is a generic kernel.
SmallVector< Value *, 3 > TargetThreadLimit
SmallVector< Value *, 3 > TeamsThreadLimit
SmallVector< Value * > MaxThreads
'parallel' construct 'num_threads' clause value, if present and it is an SPMD kernel.
Data structure to contain the information needed to uniquely identify a target entry.
static LLVM_ABI void getTargetRegionEntryFnName(SmallVectorImpl< char > &Name, StringRef ParentName, unsigned DeviceID, unsigned FileID, unsigned Line, unsigned Count)
static constexpr const char * KernelNamePrefix
The prefix used for kernel names.
static LLVM_ABI const Target * lookupTarget(const Triple &TheTriple, std::string &Error)
lookupTarget - Lookup a target based on a target triple.
Defines various target-specific GPU grid values that must be consistent between host RTL (plugin),...