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,
DebugLoc DL,
Type *VarType,
549 const Twine &Name = Twine(
""),
550 AddrSpaceCastInst **CastedAlloc =
nullptr)
override {
551 return OMPBuilder.createOMPAllocShared({AllocaIP,
DL}, VarType,
Name);
554 virtual Instruction *deallocateVar(IRBuilder<>::InsertPoint DeallocIP,
556 Type *VarType)
override {
557 return OMPBuilder.createOMPFreeShared({DeallocIP,
DL}, Var, VarType);
564 OpenMPIRBuilder &OMPBuilder;
566 DeviceSharedMemOutlineInfo(OpenMPIRBuilder &OMPBuilder)
567 : OMPBuilder(OMPBuilder) {}
568 virtual ~DeviceSharedMemOutlineInfo() =
default;
570 virtual std::unique_ptr<CodeExtractor>
572 bool ArgsInZeroAddressSpace,
573 Twine Suffix = Twine(
""))
override;
579 : RequiresFlags(OMP_REQ_UNDEFINED) {}
583 bool HasRequiresReverseOffload,
bool HasRequiresUnifiedAddress,
584 bool HasRequiresUnifiedSharedMemory,
bool HasRequiresDynamicAllocators)
587 RequiresFlags(OMP_REQ_UNDEFINED) {
588 if (HasRequiresReverseOffload)
589 RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
590 if (HasRequiresUnifiedAddress)
591 RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
592 if (HasRequiresUnifiedSharedMemory)
593 RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
594 if (HasRequiresDynamicAllocators)
595 RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
599 return RequiresFlags & OMP_REQ_REVERSE_OFFLOAD;
603 return RequiresFlags & OMP_REQ_UNIFIED_ADDRESS;
607 return RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY;
611 return RequiresFlags & OMP_REQ_DYNAMIC_ALLOCATORS;
616 :
static_cast<int64_t
>(OMP_REQ_NONE);
621 RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
623 RequiresFlags &= ~OMP_REQ_REVERSE_OFFLOAD;
628 RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
630 RequiresFlags &= ~OMP_REQ_UNIFIED_ADDRESS;
635 RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
637 RequiresFlags &= ~OMP_REQ_UNIFIED_SHARED_MEMORY;
642 RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
644 RequiresFlags &= ~OMP_REQ_DYNAMIC_ALLOCATORS;
657 constexpr size_t MaxDim = 3;
662 Value *DynCGroupMemFallbackFlag =
664 DynCGroupMemFallbackFlag =
Builder.CreateShl(DynCGroupMemFallbackFlag, 2);
669 StrictBlocksFlag =
Builder.CreateShl(StrictBlocksFlag, 6);
670 StrictThreadsFlag =
Builder.CreateShl(StrictThreadsFlag, 7);
672 Value *Flags =
Builder.CreateOr(HasNoWaitFlag, DynCGroupMemFallbackFlag);
673 Flags =
Builder.CreateOr(Flags, StrictBlocksFlag);
674 Flags =
Builder.CreateOr(Flags, StrictThreadsFlag);
680 Value *NumThreads3D =
711 auto FnAttrs = Attrs.getFnAttrs();
712 auto RetAttrs = Attrs.getRetAttrs();
714 for (
size_t ArgNo = 0; ArgNo < Fn.
arg_size(); ++ArgNo)
719 bool Param =
true) ->
void {
720 bool HasSignExt = AS.hasAttribute(Attribute::SExt);
721 bool HasZeroExt = AS.hasAttribute(Attribute::ZExt);
722 if (HasSignExt || HasZeroExt) {
723 assert(AS.getNumAttributes() == 1 &&
724 "Currently not handling extension attr combined with others.");
726 if (
auto AK = TargetLibraryInfo::getExtAttrForI32Param(
T, HasSignExt))
729 TargetLibraryInfo::getExtAttrForI32Return(
T, HasSignExt))
736#define OMP_ATTRS_SET(VarName, AttrSet) AttributeSet VarName = AttrSet;
737#include "llvm/Frontend/OpenMP/OMPKinds.def"
741#define OMP_RTL_ATTRS(Enum, FnAttrSet, RetAttrSet, ArgAttrSets) \
743 FnAttrs = FnAttrs.addAttributes(Ctx, FnAttrSet); \
744 addAttrSet(RetAttrs, RetAttrSet, false); \
745 for (size_t ArgNo = 0; ArgNo < ArgAttrSets.size(); ++ArgNo) \
746 addAttrSet(ArgAttrs[ArgNo], ArgAttrSets[ArgNo]); \
747 Fn.setAttributes(AttributeList::get(Ctx, FnAttrs, RetAttrs, ArgAttrs)); \
749#include "llvm/Frontend/OpenMP/OMPKinds.def"
763#define OMP_RTL(Enum, Str, IsVarArg, ReturnType, ...) \
765 FnTy = FunctionType::get(ReturnType, ArrayRef<Type *>{__VA_ARGS__}, \
767 Fn = M.getFunction(Str); \
769#include "llvm/Frontend/OpenMP/OMPKinds.def"
775#define OMP_RTL(Enum, Str, ...) \
777 Fn = Function::Create(FnTy, GlobalValue::ExternalLinkage, Str, M); \
779#include "llvm/Frontend/OpenMP/OMPKinds.def"
783 if (FnID == OMPRTL___kmpc_fork_call || FnID == OMPRTL___kmpc_fork_teams) {
793 LLVMContext::MD_callback,
795 2, {-1, -1},
true)}));
808 assert(Fn &&
"Failed to create OpenMP runtime function");
819 Builder.SetInsertPoint(FiniBB);
831 FiniBB = OtherFiniBB;
833 Builder.SetInsertPoint(FiniBB->getFirstNonPHIIt());
841 auto EndIt = FiniBB->end();
842 if (FiniBB->size() >= 1)
843 if (
auto Prev = std::prev(EndIt); Prev->isTerminator())
848 FiniBB->replaceAllUsesWith(OtherFiniBB);
849 FiniBB->eraseFromParent();
850 FiniBB = OtherFiniBB;
857 assert(Fn &&
"Failed to create OpenMP runtime function pointer");
880 for (
auto Inst =
Block->getReverseIterator()->begin();
881 Inst !=
Block->getReverseIterator()->end();) {
910 Block.getParent()->getEntryBlock().getTerminator()->getIterator();
931 DeferredOutlines.
push_back(std::move(OI));
935 ParallelRegionBlockSet.
clear();
937 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
947 bool ArgsInZeroAddressSpace =
Config.isTargetDevice();
948 std::unique_ptr<CodeExtractor> Extractor =
949 OI->createCodeExtractor(Blocks, ArgsInZeroAddressSpace,
".omp_par");
953 <<
" Exit: " << OI->ExitBB->getName() <<
"\n");
954 assert(Extractor->isEligible() &&
955 "Expected OpenMP outlining to be possible!");
957 for (
auto *V : OI->ExcludeArgsFromAggregate)
958 Extractor->excludeArgFromAggregate(V);
961 Extractor->extractCodeRegion(CEAC, OI->Inputs, OI->Outputs);
965 if (TargetCpuAttr.isStringAttribute())
968 auto TargetFeaturesAttr = OuterFn->
getFnAttribute(
"target-features");
969 if (TargetFeaturesAttr.isStringAttribute())
970 OutlinedFn->
addFnAttr(TargetFeaturesAttr);
973 LLVM_DEBUG(
dbgs() <<
" Outlined function: " << *OutlinedFn <<
"\n");
975 "OpenMP outlined functions should not return a value!");
980 M.getFunctionList().insertAfter(OuterFn->
getIterator(), OutlinedFn);
987 assert(OI->EntryBB->getUniquePredecessor() == &ArtificialEntry);
994 "Expected instructions to add in the outlined region entry");
996 End = ArtificialEntry.
rend();
1001 if (
I.isTerminator()) {
1003 if (
Instruction *TI = OI->EntryBB->getTerminatorOrNull())
1004 TI->adoptDbgRecords(&ArtificialEntry,
I.getIterator(),
false);
1008 I.moveBeforePreserving(*OI->EntryBB,
1009 OI->EntryBB->getFirstInsertionPt());
1012 OI->EntryBB->moveBefore(&ArtificialEntry);
1019 if (OI->PostOutlineCB)
1020 OI->PostOutlineCB(*OutlinedFn);
1022 if (OI->FixUpNonEntryAllocas)
1054 errs() <<
"Error of kind: " << Kind
1055 <<
" when emitting offload entries and metadata during "
1056 "OMPIRBuilder finalization \n";
1064 if (
Config.isTargetDevice())
1065 applyDeclareTargetGlobalReplacements();
1067 if (
Config.EmitLLVMUsedMetaInfo.value_or(
false)) {
1068 std::vector<WeakTrackingVH> LLVMCompilerUsed = {
1069 M.getGlobalVariable(
"__openmp_nvptx_data_transfer_temporary_storage")};
1070 emitUsed(
"llvm.compiler.used", LLVMCompilerUsed);
1080 assert(Original && Replacement &&
1081 "Null values provided to registerDeclareTargetGlobalReplacement");
1085void OpenMPIRBuilder::applyDeclareTargetGlobalReplacements() {
1091 "A null value was inserted into DeclareTargetGlobalReplacements");
1095 if (!OldGV || !NewGV)
1129 for (
unsigned I = 0, E =
PHI->getNumIncomingValues();
I < E; ++
I) {
1130 if (
PHI->getIncomingValue(
I) != OldGV)
1135 Builder.SetCurrentDebugLocation(
PHI->getDebugLoc());
1137 PHI->setIncomingValue(
I, EdgeLoad);
1143 Builder.SetCurrentDebugLocation(Insn->getDebugLoc());
1159 "Non-default address space declare target global");
1161 unsigned DestAS = ASC->getType()->getPointerAddressSpace();
1162 if (DestAS == 0 && NewGVAS != OldGVAS) {
1163 ASC->replaceAllUsesWith(
Load);
1164 ASC->eraseFromParent();
1169 Insn->replaceUsesOfWith(OldGV,
Load);
1185 ConstantInt::get(I32Ty,
Value), Name);
1198 for (
unsigned I = 0, E =
List.size();
I != E; ++
I)
1202 if (UsedArray.
empty())
1209 GV->setSection(
"llvm.metadata");
1215 auto *Int8Ty =
Builder.getInt8Ty();
1218 ConstantInt::get(Int8Ty, Mode),
Twine(KernelName,
"_exec_mode"));
1226 unsigned Reserve2Flags) {
1228 LocFlags |= OMP_IDENT_FLAG_KMPC;
1235 ConstantInt::get(Int32,
uint32_t(LocFlags)),
1236 ConstantInt::get(Int32, Reserve2Flags),
1237 ConstantInt::get(Int32, SrcLocStrSize), SrcLocStr};
1239 size_t SrcLocStrArgIdx = 4;
1240 if (OpenMPIRBuilder::Ident->getElementType(SrcLocStrArgIdx)
1244 SrcLocStr, OpenMPIRBuilder::Ident->getElementType(SrcLocStrArgIdx));
1251 if (
GV.getValueType() == OpenMPIRBuilder::Ident &&
GV.hasInitializer())
1252 if (
GV.getInitializer() == Initializer)
1257 M, OpenMPIRBuilder::Ident,
1260 M.getDataLayout().getDefaultGlobalsAddressSpace());
1272 SrcLocStrSize = LocStr.
size();
1281 if (
GV.isConstant() &&
GV.hasInitializer() &&
1282 GV.getInitializer() == Initializer)
1285 SrcLocStr =
Builder.CreateGlobalString(
1286 LocStr,
"",
M.getDataLayout().getDefaultGlobalsAddressSpace(),
1294 unsigned Line,
unsigned Column,
1300 Buffer.
append(FunctionName);
1302 Buffer.
append(std::to_string(Line));
1304 Buffer.
append(std::to_string(Column));
1312 StringRef UnknownLoc =
";unknown;unknown;0;0;;";
1323 !DIL->getFilename().empty() ? DIL->getFilename() :
M.getName();
1328 DIL->getColumn(), SrcLocStrSize);
1334 Loc.IP.getBlock()->getParent());
1340 "omp_global_thread_num");
1348 "expected one result pointer type per in_reduction item");
1351 if (OrigPtrs.
empty())
1352 return Builder.saveIP();
1371 for (
unsigned Idx = 0; Idx < OrigPtrs.
size(); ++Idx) {
1374 Value *OrigPtr = OrigPtrs[Idx];
1376 OrigPtrTy && OrigPtrTy->getAddressSpace() != 0)
1377 OrigPtr = Builder.CreateAddrSpaceCast(OrigPtr, PtrTy);
1379 Value *
Priv = Builder.CreateCall(GetThData, {Gtid, NullDesc, OrigPtr},
1385 ResPtrTy && ResPtrTy->getAddressSpace() != 0)
1386 Priv = Builder.CreateAddrSpaceCast(
Priv, ResultPtrTys[Idx]);
1388 MapPrivateCB(Idx,
Priv);
1395 bool ForceSimpleCall,
bool CheckCancelFlag) {
1405 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_FOR;
1408 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SECTIONS;
1411 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SINGLE;
1414 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_EXPL;
1417 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL;
1430 bool UseCancelBarrier =
1435 ? OMPRTL___kmpc_cancel_barrier
1436 : OMPRTL___kmpc_barrier),
1439 if (UseCancelBarrier && CheckCancelFlag)
1449 omp::Directive CanceledDirective) {
1454 auto *UI =
Builder.CreateUnreachable();
1462 Builder.SetInsertPoint(ElseTI);
1463 auto ElseIP =
Builder.saveIP();
1471 Builder.SetInsertPoint(ThenTI);
1473 Value *CancelKind =
nullptr;
1474 switch (CanceledDirective) {
1475#define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) \
1476 case DirectiveEnum: \
1477 CancelKind = Builder.getInt32(Value); \
1479#include "llvm/Frontend/OpenMP/OMPKinds.def"
1496 Builder.SetInsertPoint(UI->getParent());
1497 UI->eraseFromParent();
1504 omp::Directive CanceledDirective) {
1509 auto *UI =
Builder.CreateUnreachable();
1512 Value *CancelKind =
nullptr;
1513 switch (CanceledDirective) {
1514#define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) \
1515 case DirectiveEnum: \
1516 CancelKind = Builder.getInt32(Value); \
1518#include "llvm/Frontend/OpenMP/OMPKinds.def"
1535 Builder.SetInsertPoint(UI->getParent());
1536 UI->eraseFromParent();
1549 auto *KernelArgsPtr =
1550 Builder.CreateAlloca(OpenMPIRBuilder::KernelArgs,
nullptr,
"kernel_args");
1555 Builder.CreateStructGEP(OpenMPIRBuilder::KernelArgs, KernelArgsPtr,
I);
1558 M.getDataLayout().getPrefTypeAlign(KernelArgs[
I]->getType()));
1562 NumThreads, HostPtr, KernelArgsPtr};
1589 assert(OutlinedFnID &&
"Invalid outlined function ID!");
1593 Value *Return =
nullptr;
1613 Builder, AllocaIP, Return, RTLoc, DeviceID, Args.NumTeams.front(),
1614 Args.NumThreads.front(), OutlinedFnID, ArgsVector));
1621 Builder.CreateCondBr(
Failed, OffloadFailedBlock, OffloadContBlock);
1623 auto CurFn =
Builder.GetInsertBlock()->getParent();
1630 emitBlock(OffloadContBlock, CurFn,
true);
1635 Value *CancelFlag, omp::Directive CanceledDirective) {
1637 "Unexpected cancellation!");
1657 Builder.CreateCondBr(Cmp, NonCancellationBlock, CancellationBlock,
1666 Builder.SetInsertPoint(CancellationBlock);
1667 Builder.CreateBr(*FiniBBOrErr);
1670 Builder.SetInsertPoint(NonCancellationBlock, NonCancellationBlock->
begin());
1682 size_t NumArgs = OutlinedFn.
arg_size();
1683 assert((NumArgs == 2 || NumArgs == 3) &&
1684 "expected a 2-3 argument parallel outlined function");
1685 bool UseArgStruct = NumArgs == 3;
1690 {Builder.getInt16Ty(), Builder.getInt32Ty()},
1694 OutlinedFn.
getName() +
".wrapper", OMPIRBuilder->
M);
1696 WrapperFn->addParamAttr(0, Attribute::NoUndef);
1697 WrapperFn->addParamAttr(0, Attribute::ZExt);
1698 WrapperFn->addParamAttr(1, Attribute::NoUndef);
1702 Builder.SetInsertPoint(EntryBB);
1705 Value *AddrAlloca = Builder.CreateAlloca(Builder.getInt32Ty(),
1707 AddrAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1708 AddrAlloca, Builder.getPtrTy(0),
1709 AddrAlloca->
getName() +
".ascast");
1711 Value *ZeroAlloca = Builder.CreateAlloca(Builder.getInt32Ty(),
1713 ZeroAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1714 ZeroAlloca, Builder.getPtrTy(0),
1715 ZeroAlloca->
getName() +
".ascast");
1717 Value *ArgsAlloca =
nullptr;
1719 ArgsAlloca = Builder.CreateAlloca(Builder.getPtrTy(),
1720 nullptr,
"global_args");
1721 ArgsAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1722 ArgsAlloca, Builder.getPtrTy(0),
1723 ArgsAlloca->
getName() +
".ascast");
1727 Builder.CreateStore(WrapperFn->getArg(1), AddrAlloca);
1728 Builder.CreateStore(Builder.getInt32(0), ZeroAlloca);
1732 llvm::omp::RuntimeFunction::OMPRTL___kmpc_get_shared_variables),
1740 Value *StructArg = Builder.CreateLoad(Builder.getPtrTy(), ArgsAlloca);
1741 StructArg = Builder.CreateInBoundsGEP(Builder.getPtrTy(), StructArg,
1742 {Builder.getInt64(0)});
1743 StructArg = Builder.CreateLoad(Builder.getPtrTy(), StructArg,
"structArg");
1744 Args.push_back(StructArg);
1748 Builder.CreateCall(&OutlinedFn, Args);
1749 Builder.CreateRetVoid();
1764 "Expected at least tid and bounded tid as arguments");
1765 unsigned NumCapturedVars = OutlinedFn.
arg_size() - 2;
1773 OutlinedFn.
addFnAttr(Attribute::NoUnwind);
1776 assert(CI &&
"Expected call instruction to outlined function");
1777 CI->
getParent()->setName(
"omp_parallel");
1779 Builder.SetInsertPoint(CI);
1780 Type *PtrTy = OMPIRBuilder->VoidPtr;
1783 OpenMPIRBuilder ::InsertPointTy CurrentIP = Builder.saveIP();
1787 Value *Args = ArgsAlloca;
1791 Args = Builder.CreatePointerCast(ArgsAlloca, PtrTy);
1792 Builder.restoreIP(CurrentIP);
1795 for (
unsigned Idx = 0; Idx < NumCapturedVars; Idx++) {
1797 Value *StoreAddress = Builder.CreateConstInBoundsGEP2_64(
1799 Builder.CreateStore(V, StoreAddress);
1803 IfCondition ? Builder.CreateSExtOrTrunc(IfCondition, OMPIRBuilder->Int32)
1804 : Builder.getInt32(1);
1805 Value *NumThreadsArg =
1806 NumThreads ? Builder.CreateZExtOrTrunc(NumThreads, OMPIRBuilder->Int32)
1807 : Builder.getInt32(-1);
1817 Value *Parallel60CallArgs[] = {
1822 Builder.getInt32(-1),
1826 Builder.getInt64(NumCapturedVars),
1827 Builder.getInt32(0)};
1835 << *Builder.GetInsertBlock()->getParent() <<
"\n");
1838 Builder.SetInsertPoint(PrivTID);
1840 Builder.CreateStore(Builder.CreateLoad(OMPIRBuilder->Int32, OutlinedAI),
1847 I->eraseFromParent();
1870 if (!
F->hasMetadata(LLVMContext::MD_callback)) {
1878 F->addMetadata(LLVMContext::MD_callback,
1887 OutlinedFn.
addFnAttr(Attribute::NoUnwind);
1890 "Expected at least tid and bounded tid as arguments");
1891 unsigned NumCapturedVars = OutlinedFn.
arg_size() - 2;
1894 CI->
getParent()->setName(
"omp_parallel");
1895 Builder.SetInsertPoint(CI);
1898 Value *ForkCallArgs[] = {Ident, Builder.getInt32(NumCapturedVars),
1902 RealArgs.
append(std::begin(ForkCallArgs), std::end(ForkCallArgs));
1904 Value *
Cond = Builder.CreateSExtOrTrunc(IfCondition, OMPIRBuilder->Int32);
1911 auto PtrTy = OMPIRBuilder->VoidPtr;
1912 if (IfCondition && NumCapturedVars == 0) {
1920 << *Builder.GetInsertBlock()->getParent() <<
"\n");
1923 Builder.SetInsertPoint(PrivTID);
1925 Builder.CreateStore(Builder.CreateLoad(OMPIRBuilder->Int32, OutlinedAI),
1932 I->eraseFromParent();
1940 Value *NumThreads, omp::ProcBindKind ProcBind,
bool IsCancellable) {
1949 const bool NeedThreadID = NumThreads ||
Config.isTargetDevice() ||
1950 (ProcBind != OMP_PROC_BIND_default);
1957 bool ArgsInZeroAddressSpace =
Config.isTargetDevice();
1961 if (NumThreads && !
Config.isTargetDevice()) {
1964 Builder.CreateIntCast(NumThreads, Int32,
false)};
1969 if (ProcBind != OMP_PROC_BIND_default) {
1973 ConstantInt::get(Int32,
unsigned(ProcBind),
true)};
1995 Builder.CreateAlloca(Int32,
nullptr,
"zero.addr");
1998 if (ArgsInZeroAddressSpace &&
M.getDataLayout().getAllocaAddrSpace() != 0) {
2001 TIDAddrAlloca, PointerType ::get(
M.getContext(), 0),
"tid.addr.ascast");
2005 PointerType ::get(
M.getContext(), 0),
2006 "zero.addr.ascast");
2030 if (IP.getBlock()->end() == IP.getPoint()) {
2036 assert(IP.getBlock()->getTerminator()->getNumSuccessors() == 1 &&
2037 IP.getBlock()->getTerminator()->getSuccessor(0) == PRegExitBB &&
2038 "Unexpected insertion point for finalization call!");
2050 Builder.CreateAlloca(Int32,
nullptr,
"tid.addr.local");
2056 Builder.CreateLoad(Int32, ZeroAddr,
"zero.addr.use");
2074 LLVM_DEBUG(
dbgs() <<
"Before body codegen: " << *OuterFn <<
"\n");
2077 assert(BodyGenCB &&
"Expected body generation callback!");
2079 if (
Error Err = BodyGenCB(InnerAllocaIP, CodeGenIP, PRegExitBB))
2082 LLVM_DEBUG(
dbgs() <<
"After body codegen: " << *OuterFn <<
"\n");
2086 bool UsesDeviceSharedMemory =
2088 std::unique_ptr<OutlineInfo> OI =
2089 UsesDeviceSharedMemory
2090 ? std::make_unique<DeviceSharedMemOutlineInfo>(*
this)
2091 : std::make_unique<OutlineInfo>();
2093 if (
Config.isTargetDevice()) {
2095 OI->PostOutlineCB = [=, ToBeDeletedVec =
2096 std::move(ToBeDeleted)](
Function &OutlinedFn) {
2098 IfCondition, NumThreads, PrivTID, PrivTIDAddr,
2099 ThreadID, ToBeDeletedVec);
2103 OI->PostOutlineCB = [=, ToBeDeletedVec =
2104 std::move(ToBeDeleted)](
Function &OutlinedFn) {
2106 PrivTID, PrivTIDAddr, ToBeDeletedVec);
2110 OI->FixUpNonEntryAllocas =
true;
2111 OI->OuterAllocBB = OuterAllocaBlock;
2112 OI->EntryBB = PRegEntryBB;
2113 OI->ExitBB = PRegExitBB;
2114 OI->OuterDeallocBBs.reserve(OuterDeallocBlocks.
size());
2115 copy(OuterDeallocBlocks, OI->OuterDeallocBBs.
end());
2119 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
2131 ".omp_par", ArgsInZeroAddressSpace);
2136 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
2138 Extractor.findInputsOutputs(Inputs, Outputs, SinkingCands,
2143 return GV->getValueType() == OpenMPIRBuilder::Ident;
2148 LLVM_DEBUG(
dbgs() <<
"Before privatization: " << *OuterFn <<
"\n");
2154 if (&V == TIDAddr || &V == ZeroAddr) {
2155 OI->ExcludeArgsFromAggregate.push_back(&V);
2160 for (
Use &U : V.uses())
2162 if (ParallelRegionBlockSet.
count(UserI->getParent()))
2172 if (!V.getType()->isPointerTy()) {
2176 Builder.restoreIP(OuterAllocIP);
2178 if (UsesDeviceSharedMemory) {
2181 V.getName() +
".reloaded");
2182 for (
BasicBlock *DeallocBlock : OuterDeallocBlocks) {
2183 assert(DeallocBlock->getParent() ==
2185 "Dealloc block must be in the allocation's function to reuse "
2186 "its debug location");
2188 {
InsertPointTy(DeallocBlock, DeallocBlock->getFirstInsertionPt()),
2189 Builder.getCurrentDebugLocation()},
2193 Ptr =
Builder.CreateAlloca(V.getType(),
nullptr,
2194 V.getName() +
".reloaded");
2199 Builder.SetInsertPoint(InsertBB,
2204 Builder.restoreIP(InnerAllocaIP);
2205 Inner =
Builder.CreateLoad(V.getType(), Ptr);
2208 Value *ReplacementValue =
nullptr;
2211 ReplacementValue = PrivTID;
2214 PrivCB(InnerAllocaIP,
Builder.saveIP(), V, *Inner, ReplacementValue);
2222 assert(ReplacementValue &&
2223 "Expected copy/create callback to set replacement value!");
2224 if (ReplacementValue == &V)
2229 UPtr->set(ReplacementValue);
2254 for (
Value *Output : Outputs)
2258 "OpenMP outlining should not produce live-out values!");
2260 LLVM_DEBUG(
dbgs() <<
"After privatization: " << *OuterFn <<
"\n");
2262 for (
auto *BB : Blocks)
2263 dbgs() <<
" PBR: " << BB->getName() <<
"\n";
2271 assert(FiniInfo.DK == OMPD_parallel &&
2272 "Unexpected finalization stack state!");
2283 Builder.CreateBr(*FiniBBOrErr);
2287 Term->eraseFromParent();
2293 InsertPointTy AfterIP(UI->getParent(), UI->getParent()->end());
2294 UI->eraseFromParent();
2326 Value *Severity = ConstantInt::get(Int32, IsFatal ? 2 : 1);
2328 Value *Args[] = {Ident, Severity, MessageArg};
2357 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr));
2359 Builder.CreateStore(DepValPtr, Addr);
2362 DependInfo, Entry,
static_cast<unsigned int>(RTLDependInfoFields::Len));
2364 ConstantInt::get(SizeTy,
2369 DependInfo, Entry,
static_cast<unsigned int>(RTLDependInfoFields::Flags));
2371 static_cast<unsigned int>(Dep.
DepKind)),
2384 if (Dependencies.
empty())
2404 Type *DependInfo = OMPBuilder.DependInfo;
2406 Value *DepArray =
nullptr;
2412 Builder.SetInsertPoint(
2413 Builder.GetInsertBlock()->getParent()->getEntryBlock().getTerminator());
2414 DepArray = Builder.CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
2417 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies)) {
2419 Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
2443 Value *DepArray =
nullptr;
2444 Type *DepArrayTy =
nullptr;
2445 Value *NumDeps =
nullptr;
2448 NumDeps = Dependencies.
NumDeps;
2449 }
else if (!Dependencies.
Deps.empty()) {
2451 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
2455 Builder.GetInsertBlock()->getParent()->getEntryBlock();
2457 DepArray =
Builder.CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
2460 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies.
Deps)) {
2462 Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
2476 ConstantInt::get(
Builder.getInt32Ty(), 0),
2478 ConstantInt::get(
Builder.getInt32Ty(),
false)};
2481 omp::RuntimeFunction::OMPRTL___kmpc_omp_taskwait_deps_51),
2491 unsigned ProgramAddressSpace = M.getDataLayout().getProgramAddressSpace();
2503 auto *VoidPtrTy =
PointerType::get(Builder.getContext(), ProgramAddressSpace);
2506 Builder.getVoidTy(), {VoidPtrTy, VoidPtrTy, Builder.getInt32Ty()},
2510 "omp_taskloop_dup", M);
2513 Value *LastprivateFlagArg = DupFunction->
getArg(2);
2514 DestTaskArg->
setName(
"dest_task");
2515 SrcTaskArg->
setName(
"src_task");
2516 LastprivateFlagArg->
setName(
"lastprivate_flag");
2519 Builder.SetInsertPoint(
2522 auto GetTaskContextPtrFromArg = [&](
Value *Arg) ->
Value * {
2523 Type *TaskWithPrivatesTy =
2525 Value *TaskPrivates = Builder.CreateGEP(
2526 TaskWithPrivatesTy, Arg, {Builder.getInt32(0), Builder.getInt32(1)});
2527 Value *ContextPtr = Builder.CreateGEP(
2528 PrivatesTy, TaskPrivates,
2529 {Builder.getInt32(0), Builder.getInt32(PrivatesIndex)});
2533 Value *DestTaskContextPtr = GetTaskContextPtrFromArg(DestTaskArg);
2534 Value *SrcTaskContextPtr = GetTaskContextPtrFromArg(SrcTaskArg);
2536 DestTaskContextPtr->
setName(
"destPtr");
2537 SrcTaskContextPtr->
setName(
"srcPtr");
2542 Expected<IRBuilderBase::InsertPoint> AfterIPOrError =
2543 DupCB(AllocaIP, CodeGenIP, DestTaskContextPtr, SrcTaskContextPtr);
2544 if (!AfterIPOrError)
2546 Builder.restoreIP(*AfterIPOrError);
2556 llvm::function_ref<llvm::Expected<llvm::CanonicalLoopInfo *>()> LoopInfo,
2558 Value *GrainSize,
bool NoGroup,
int Sched,
Value *Final,
bool Mergeable,
2560 Value *TaskContextStructPtrVal,
bool FreeAgent) {
2565 uint32_t SrcLocStrSize;
2581 if (
Error Err = BodyGenCB(TaskloopAllocaIP, TaskloopBodyIP, TaskloopExitBB))
2584 llvm::Expected<llvm::CanonicalLoopInfo *> result = LoopInfo();
2589 llvm::CanonicalLoopInfo *CLI = result.
get();
2590 auto OI = std::make_unique<OutlineInfo>();
2591 OI->EntryBB = TaskloopAllocaBB;
2592 OI->OuterAllocBB = AllocaIP.getBlock();
2593 OI->ExitBB = TaskloopExitBB;
2594 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2595 copy(DeallocBlocks, OI->OuterDeallocBBs.end());
2598 SmallVector<Instruction *> ToBeDeleted;
2601 Builder, AllocaIP, ToBeDeleted, TaskloopAllocaIP,
"global.tid",
false));
2603 TaskloopAllocaIP,
"lb",
false,
true);
2605 TaskloopAllocaIP,
"ub",
false,
true);
2607 TaskloopAllocaIP,
"step",
false,
true);
2610 OI->Inputs.insert(FakeLB);
2611 OI->Inputs.insert(FakeUB);
2612 OI->Inputs.insert(FakeStep);
2613 if (TaskContextStructPtrVal)
2614 OI->Inputs.insert(TaskContextStructPtrVal);
2615 assert(((TaskContextStructPtrVal && DupCB) ||
2616 (!TaskContextStructPtrVal && !DupCB)) &&
2617 "Task context struct ptr and duplication callback must be both set "
2623 unsigned ProgramAddressSpace =
M.getDataLayout().getProgramAddressSpace();
2627 {FakeLB->getType(), FakeUB->getType(), FakeStep->getType(), PointerTy});
2628 Expected<Value *> TaskDupFnOrErr = createTaskDuplicationFunction(
2631 if (!TaskDupFnOrErr) {
2634 Value *TaskDupFn = *TaskDupFnOrErr;
2636 OI->PostOutlineCB = [
this, Ident, LBVal, UBVal, StepVal, Untied,
2637 TaskloopAllocaBB, CLI, TaskDupFn, ToBeDeleted, IfCond,
2638 GrainSize, NoGroup, Sched, FakeLB, FakeUB, FakeStep,
2639 FakeSharedsTy, Final, Mergeable, Priority,
2641 FreeAgent](
Function &OutlinedFn)
mutable {
2643 assert(OutlinedFn.hasOneUse() &&
2644 "there must be a single user for the outlined function");
2651 Value *CastedLBVal =
2652 Builder.CreateIntCast(LBVal,
Builder.getInt64Ty(),
true,
"lb64");
2653 Value *CastedUBVal =
2654 Builder.CreateIntCast(UBVal,
Builder.getInt64Ty(),
true,
"ub64");
2655 Value *CastedStepVal =
2656 Builder.CreateIntCast(StepVal,
Builder.getInt64Ty(),
true,
"step64");
2658 Builder.SetInsertPoint(StaleCI);
2671 Builder.CreateCall(TaskgroupFn, {Ident, ThreadID});
2696 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
2698 AllocaInst *ArgStructAlloca =
2700 assert(ArgStructAlloca &&
2701 "Unable to find the alloca instruction corresponding to arguments "
2702 "for extracted function");
2703 std::optional<TypeSize> ArgAllocSize =
2706 "Unable to determine size of arguments for extracted function");
2707 Value *SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
2712 CallInst *TaskData =
Builder.CreateCall(
2713 TaskAllocFn, {Ident, ThreadID,
Flags,
2714 TaskSize, SharedsSize,
2719 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
2725 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(0)});
2728 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(1)});
2731 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(2)});
2737 IfCond ?
Builder.CreateIntCast(IfCond,
Builder.getInt32Ty(),
true)
2743 Value *GrainSizeVal =
2744 GrainSize ?
Builder.CreateIntCast(GrainSize,
Builder.getInt64Ty(),
true)
2746 Value *TaskDup = TaskDupFn;
2748 Value *
Args[] = {Ident, ThreadID, TaskData, IfCondVal, Lb, Ub,
2749 Loadstep, NoGroupVal, SchedVal, GrainSizeVal, TaskDup};
2754 Builder.CreateCall(TaskloopFn, Args);
2761 Builder.CreateCall(EndTaskgroupFn, {Ident, ThreadID});
2766 Builder.SetInsertPoint(TaskloopAllocaBB, TaskloopAllocaBB->begin());
2768 LoadInst *SharedsOutlined =
2769 Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
2770 OutlinedFn.getArg(1)->replaceUsesWithIf(
2772 [SharedsOutlined](Use &U) {
return U.getUser() != SharedsOutlined; });
2775 Type *IVTy =
IV->getType();
2781 Value *TaskLB =
nullptr;
2782 Value *TaskUB =
nullptr;
2783 Value *TaskStep =
nullptr;
2784 Value *LoadTaskLB =
nullptr;
2785 Value *LoadTaskUB =
nullptr;
2786 Value *LoadTaskStep =
nullptr;
2787 for (Instruction &
I : *TaskloopAllocaBB) {
2788 if (
I.getOpcode() == Instruction::GetElementPtr) {
2791 switch (CI->getZExtValue()) {
2803 }
else if (
I.getOpcode() == Instruction::Load) {
2805 if (
Load.getPointerOperand() == TaskLB) {
2806 assert(TaskLB !=
nullptr &&
"Expected value for TaskLB");
2808 }
else if (
Load.getPointerOperand() == TaskUB) {
2809 assert(TaskUB !=
nullptr &&
"Expected value for TaskUB");
2811 }
else if (
Load.getPointerOperand() == TaskStep) {
2812 assert(TaskStep !=
nullptr &&
"Expected value for TaskStep");
2818 Builder.SetInsertPoint(CLI->getPreheader()->getTerminator());
2820 assert(LoadTaskLB !=
nullptr &&
"Expected value for LoadTaskLB");
2821 assert(LoadTaskUB !=
nullptr &&
"Expected value for LoadTaskUB");
2822 assert(LoadTaskStep !=
nullptr &&
"Expected value for LoadTaskStep");
2824 Builder.CreateSub(LoadTaskUB, LoadTaskLB), LoadTaskStep);
2825 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One,
"trip_cnt");
2826 Value *CastedTripCount =
Builder.CreateIntCast(TripCount, IVTy,
true);
2827 Value *CastedTaskLB =
Builder.CreateIntCast(LoadTaskLB, IVTy,
true);
2829 CLI->setTripCount(CastedTripCount);
2831 Builder.SetInsertPoint(CLI->getBody(),
2832 CLI->getBody()->getFirstInsertionPt());
2834 if (NumOfCollapseLoops > 1) {
2840 Builder.CreateSub(CastedTaskLB, ConstantInt::get(IVTy, 1)));
2843 for (
auto IVUse = CLI->getIndVar()->uses().begin();
2844 IVUse != CLI->getIndVar()->uses().end(); IVUse++) {
2845 User *IVUser = IVUse->getUser();
2847 if (
Op->getOpcode() == Instruction::URem ||
2848 Op->getOpcode() == Instruction::UDiv) {
2853 for (User *User : UsersToReplace) {
2854 User->replaceUsesOfWith(CLI->getIndVar(), IVPlusTaskLB);
2871 assert(CLI->getIndVar()->getNumUses() == 3 &&
2872 "Canonical loop should have exactly three uses of the ind var");
2873 for (User *IVUser : CLI->getIndVar()->users()) {
2875 if (
Mul->getOpcode() == Instruction::Mul) {
2876 for (User *MulUser :
Mul->users()) {
2878 if (
Add->getOpcode() == Instruction::Add) {
2879 Add->setOperand(1, CastedTaskLB);
2888 FakeLB->replaceAllUsesWith(CastedLBVal);
2889 FakeUB->replaceAllUsesWith(CastedUBVal);
2890 FakeStep->replaceAllUsesWith(CastedStepVal);
2892 I->eraseFromParent();
2897 Builder.SetInsertPoint(TaskloopExitBB, TaskloopExitBB->
begin());
2903 M.getContext(),
M.getDataLayout().getPointerSizeInBits());
2913 bool Mergeable,
Value *EventHandle,
Value *Priority,
bool FreeAgent) {
2945 if (
Error Err = BodyGenCB(TaskAllocaIP, TaskBodyIP, TaskExitBB))
2948 auto OI = std::make_unique<OutlineInfo>();
2949 OI->EntryBB = TaskAllocaBB;
2950 OI->OuterAllocBB = AllocaIP.
getBlock();
2951 OI->ExitBB = TaskExitBB;
2952 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2953 copy(DeallocBlocks, OI->OuterDeallocBBs.
end());
2958 Builder, AllocaIP, ToBeDeleted, TaskAllocaIP,
"global.tid",
false));
2960 OI->PostOutlineCB = [
this, Ident, Tied, Final, IfCondition, Dependencies,
2961 Affinities, Mergeable, Priority, EventHandle, FreeAgent,
2963 ToBeDeleted](
Function &OutlinedFn)
mutable {
2965 assert(OutlinedFn.hasOneUse() &&
2966 "there must be a single user for the outlined function");
2971 bool HasShareds = StaleCI->
arg_size() > 1;
2972 Builder.SetInsertPoint(StaleCI);
2999 bool UseMergedIf0Path = ConstIfCondition && ConstIfCondition->isZero();
3003 Flags =
Builder.CreateOr(FinalFlag, Flags);
3006 if (Mergeable || UseMergedIf0Path)
3020 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
3029 assert(ArgStructAlloca &&
3030 "Unable to find the alloca instruction corresponding to arguments "
3031 "for extracted function");
3032 std::optional<TypeSize> ArgAllocSize =
3035 "Unable to determine size of arguments for extracted function");
3036 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
3042 TaskAllocFn, {Ident, ThreadID, Flags,
3043 TaskSize, SharedsSize,
3046 if (Affinities.
Count && Affinities.
Info) {
3048 OMPRTL___kmpc_omp_reg_task_with_affinity);
3059 OMPRTL___kmpc_task_allow_completion_event);
3063 Builder.CreatePointerBitCastOrAddrSpaceCast(EventHandle,
3065 EventVal =
Builder.CreatePtrToInt(EventVal,
Builder.getInt64Ty());
3066 Builder.CreateStore(EventVal, EventHandleAddr);
3072 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
3087 Constant *Zero = ConstantInt::get(Int32Ty, 0);
3091 Builder.CreateInBoundsGEP(TaskPtr, TaskData, {Zero, Zero});
3094 VoidPtr, VoidPtr,
Builder.getInt32Ty(), VoidPtr, VoidPtr);
3096 TaskStructType, TaskGEP, {Zero, ConstantInt::get(Int32Ty, 4)});
3099 Value *CmplrData =
Builder.CreateInBoundsGEP(CmplrStructType,
3100 PriorityData, {Zero, Zero});
3101 Builder.CreateStore(Priority, CmplrData);
3104 Value *DepArray =
nullptr;
3105 Value *NumDeps =
nullptr;
3108 NumDeps = Dependencies.
NumDeps;
3109 }
else if (!Dependencies.
Deps.empty()) {
3111 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
3131 if (IfCondition && !UseMergedIf0Path) {
3136 Builder.GetInsertPoint()->getParent()->getTerminator();
3137 Instruction *ThenTI = IfTerminator, *ElseTI =
nullptr;
3138 Builder.SetInsertPoint(IfTerminator);
3141 Builder.SetInsertPoint(ElseTI);
3148 {Ident, ThreadID, NumDeps, DepArray,
3149 ConstantInt::get(
Builder.getInt32Ty(), 0),
3164 Builder.SetInsertPoint(ThenTI);
3172 {Ident, ThreadID, TaskData, NumDeps, DepArray,
3173 ConstantInt::get(
Builder.getInt32Ty(), 0),
3184 Builder.SetInsertPoint(TaskAllocaBB, TaskAllocaBB->
begin());
3186 LoadInst *Shareds =
Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
3187 OutlinedFn.getArg(1)->replaceUsesWithIf(
3188 Shareds, [Shareds](
Use &U) {
return U.getUser() != Shareds; });
3194 Builder.ClearInsertionPoint();
3196 I->eraseFromParent();
3200 Builder.SetInsertPoint(TaskExitBB, TaskExitBB->
begin());
3222 if (
Error Err = BodyGenCB(AllocaIP,
Builder.saveIP(), DeallocBlocks))
3225 Builder.SetInsertPoint(TaskgroupExitBB);
3268 unsigned CaseNumber = 0;
3269 for (
auto SectionCB : SectionCBs) {
3271 M.getContext(),
"omp_section_loop.body.case", CurFn,
Continue);
3273 Builder.SetInsertPoint(CaseBB);
3288 Value *LB = ConstantInt::get(I32Ty, 0);
3289 Value *UB = ConstantInt::get(I32Ty, SectionCBs.
size());
3290 Value *ST = ConstantInt::get(I32Ty, 1);
3292 Loc, LoopBodyGenCB, LB, UB, ST,
true,
false, AllocaIP,
"section_loop");
3297 applyStaticWorkshareLoop(
Loc.DL, *
LoopInfo, AllocaIP,
3298 WorksharingLoopType::ForStaticLoop, !IsNowait);
3304 assert(LoopFini &&
"Bad structure of static workshare loop finalization");
3308 assert(FiniInfo.DK == OMPD_sections &&
3309 "Unexpected finalization stack state!");
3310 if (
Error Err = FiniInfo.mergeFiniBB(
Builder, LoopFini))
3324 if (IP.getBlock()->end() != IP.getPoint())
3335 auto *CaseBB =
Loc.IP.getBlock();
3336 auto *CondBB = CaseBB->getSinglePredecessor()->getSinglePredecessor();
3337 auto *ExitBB = CondBB->getTerminator()->getSuccessor(1);
3343 Directive OMPD = Directive::OMPD_sections;
3346 return EmitOMPInlinedRegion(OMPD,
nullptr,
nullptr, BodyGenCB, FiniCBWrapper,
3357Value *OpenMPIRBuilder::getGPUThreadID() {
3360 OMPRTL___kmpc_get_hardware_thread_id_in_block),
3364Value *OpenMPIRBuilder::getGPUWarpSize() {
3369Value *OpenMPIRBuilder::getNVPTXWarpID() {
3370 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3371 return Builder.CreateAShr(getGPUThreadID(), LaneIDBits,
"nvptx_warp_id");
3374Value *OpenMPIRBuilder::getNVPTXLaneID() {
3375 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3376 assert(LaneIDBits < 32 &&
"Invalid LaneIDBits size in NVPTX device.");
3377 unsigned LaneIDMask = ~0
u >> (32u - LaneIDBits);
3378 return Builder.CreateAnd(getGPUThreadID(),
Builder.getInt32(LaneIDMask),
3385 uint64_t FromSize =
M.getDataLayout().getTypeStoreSize(FromType);
3386 uint64_t ToSize =
M.getDataLayout().getTypeStoreSize(ToType);
3387 assert(FromSize > 0 &&
"From size must be greater than zero");
3388 assert(ToSize > 0 &&
"To size must be greater than zero");
3389 if (FromType == ToType)
3391 if (FromSize == ToSize)
3392 return Builder.CreateBitCast(From, ToType);
3394 return Builder.CreateIntCast(From, ToType,
true);
3400 Value *ValCastItem =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3401 CastItem,
Builder.getPtrTy(0));
3402 Builder.CreateStore(From, ValCastItem);
3403 return Builder.CreateLoad(ToType, CastItem);
3410 uint64_t Size =
M.getDataLayout().getTypeStoreSize(ElementType);
3411 assert(
Size <= 8 &&
"Unsupported bitwidth in shuffle instruction");
3415 Value *ElemCast = castValueToType(AllocaIP, Element, CastTy);
3417 Builder.CreateIntCast(getGPUWarpSize(),
Builder.getInt16Ty(),
true);
3419 Size <= 4 ? RuntimeFunction::OMPRTL___kmpc_shuffle_int32
3420 : RuntimeFunction::OMPRTL___kmpc_shuffle_int64);
3421 Value *WarpSizeCast =
3423 Value *ShuffleCall =
3428 return castValueToType(AllocaIP, ShuffleCall, ElementType);
3435 uint64_t Size =
M.getDataLayout().getTypeStoreSize(ElemType);
3447 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3448 Value *ElemPtr = DstAddr;
3449 Value *Ptr = SrcAddr;
3450 for (
unsigned IntSize = 8; IntSize >= 1; IntSize /= 2) {
3454 Ptr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3457 Builder.CreateGEP(ElemType, SrcAddr, {ConstantInt::get(IndexTy, 1)});
3458 ElemPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3462 if ((
Size / IntSize) > 1) {
3463 Value *PtrEnd =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3464 SrcAddrGEP,
Builder.getPtrTy());
3481 Builder.CreatePointerBitCastOrAddrSpaceCast(Ptr,
Builder.getPtrTy()));
3483 Builder.CreateICmpSGT(PtrDiff,
Builder.getInt64(IntSize - 1)), ThenBB,
3486 Value *Res = createRuntimeShuffleFunction(
3489 IntType, Ptr,
M.getDataLayout().getPrefTypeAlign(ElemType)),
3491 Builder.CreateAlignedStore(Res, ElemPtr,
3492 M.getDataLayout().getPrefTypeAlign(ElemType));
3494 Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3495 Value *LocalElemPtr =
3496 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3504 Value *Res = createRuntimeShuffleFunction(
3505 AllocaIP,
Builder.CreateLoad(IntType, Ptr), IntType,
Offset);
3506 Builder.CreateStore(Res, ElemPtr);
3507 Ptr =
Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3509 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3515Error OpenMPIRBuilder::emitReductionListCopy(
3520 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3521 Value *RemoteLaneOffset = CopyOptions.RemoteLaneOffset;
3525 for (
auto En :
enumerate(ReductionInfos)) {
3527 Value *SrcElementAddr =
nullptr;
3528 AllocaInst *DestAlloca =
nullptr;
3529 Value *DestElementAddr =
nullptr;
3530 Value *DestElementPtrAddr =
nullptr;
3532 bool ShuffleInElement =
false;
3535 bool UpdateDestListPtr =
false;
3539 ReductionArrayTy, SrcBase,
3540 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3541 SrcElementAddr =
Builder.CreateLoad(
Builder.getPtrTy(), SrcElementPtrAddr);
3545 DestElementPtrAddr =
Builder.CreateInBoundsGEP(
3546 ReductionArrayTy, DestBase,
3547 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3548 bool IsByRefElem = (!IsByRef.
empty() && IsByRef[En.index()]);
3554 Type *DestAllocaType =
3555 IsByRefElem ? RI.ByRefAllocatedType : RI.ElementType;
3556 DestAlloca =
Builder.CreateAlloca(DestAllocaType,
nullptr,
3557 ".omp.reduction.element");
3559 M.getDataLayout().getPrefTypeAlign(DestAllocaType));
3560 DestElementAddr = DestAlloca;
3563 DestElementAddr->
getName() +
".ascast");
3565 ShuffleInElement =
true;
3566 UpdateDestListPtr =
true;
3578 if (ShuffleInElement) {
3579 Type *ShuffleType = RI.ElementType;
3580 Value *ShuffleSrcAddr = SrcElementAddr;
3581 Value *ShuffleDestAddr = DestElementAddr;
3582 AllocaInst *LocalStorage =
nullptr;
3585 assert(RI.ByRefElementType &&
"Expected by-ref element type to be set");
3586 assert(RI.ByRefAllocatedType &&
3587 "Expected by-ref allocated type to be set");
3592 ShuffleType = RI.ByRefElementType;
3594 if (RI.DataPtrPtrGen) {
3597 Builder.saveIP(), ShuffleSrcAddr, ShuffleSrcAddr);
3600 return GenResult.takeError();
3609 LocalStorage =
Builder.CreateAlloca(ShuffleType);
3611 ShuffleDestAddr = LocalStorage;
3616 ShuffleDestAddr = DestElementAddr;
3620 shuffleAndStore(AllocaIP, ShuffleSrcAddr, ShuffleDestAddr, ShuffleType,
3621 RemoteLaneOffset, ReductionArrayTy, IsByRefElem);
3623 if (IsByRefElem && RI.DataPtrPtrGen) {
3625 Value *DestDescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3626 DestAlloca,
Builder.getPtrTy(),
".ascast");
3629 DestDescriptorAddr, LocalStorage, SrcElementAddr,
3630 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
3633 return GenResult.takeError();
3636 switch (RI.EvaluationKind) {
3638 Value *Elem =
Builder.CreateLoad(RI.ElementType, SrcElementAddr);
3640 Builder.CreateStore(Elem, DestElementAddr);
3644 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3645 RI.ElementType, SrcElementAddr, 0, 0,
".realp");
3647 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
3649 RI.ElementType, SrcElementAddr, 0, 1,
".imagp");
3651 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
3653 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3654 RI.ElementType, DestElementAddr, 0, 0,
".realp");
3655 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
3656 RI.ElementType, DestElementAddr, 0, 1,
".imagp");
3657 Builder.CreateStore(SrcReal, DestRealPtr);
3658 Builder.CreateStore(SrcImg, DestImgPtr);
3663 M.getDataLayout().getTypeStoreSize(RI.ElementType));
3665 DestElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3666 SrcElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3678 if (UpdateDestListPtr) {
3679 Value *CastDestAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3680 DestElementAddr,
Builder.getPtrTy(),
3681 DestElementAddr->
getName() +
".ascast");
3682 Builder.CreateStore(CastDestAddr, DestElementPtrAddr);
3689Expected<Function *> OpenMPIRBuilder::emitInterWarpCopyFunction(
3692 IRBuilder<>::InsertPointGuard IPG(
Builder);
3693 LLVMContext &Ctx =
M.getContext();
3695 Builder.getVoidTy(), {Builder.getPtrTy(), Builder.getInt32Ty()},
3699 "_omp_reduction_inter_warp_copy_func", &
M);
3705 Builder.SetInsertPoint(EntryBB);
3723 StringRef TransferMediumName =
3724 "__openmp_nvptx_data_transfer_temporary_storage";
3725 GlobalVariable *TransferMedium =
M.getGlobalVariable(TransferMediumName);
3726 unsigned WarpSize =
Config.getGridValue().GV_Warp_Size;
3728 if (!TransferMedium) {
3729 TransferMedium =
new GlobalVariable(
3737 Value *GPUThreadID = getGPUThreadID();
3739 Value *LaneID = getNVPTXLaneID();
3741 Value *WarpID = getNVPTXWarpID();
3745 Builder.GetInsertBlock()->getFirstInsertionPt());
3749 AllocaInst *ReduceListAlloca =
Builder.CreateAlloca(
3750 Arg0Type,
nullptr, ReduceListArg->
getName() +
".addr");
3751 AllocaInst *NumWarpsAlloca =
3752 Builder.CreateAlloca(Arg1Type,
nullptr, NumWarpsArg->
getName() +
".addr");
3753 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3754 ReduceListAlloca, Arg0Type, ReduceListAlloca->
getName() +
".ascast");
3755 Value *NumWarpsAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3756 NumWarpsAlloca,
Builder.getPtrTy(0),
3757 NumWarpsAlloca->
getName() +
".ascast");
3758 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
3759 Builder.CreateStore(NumWarpsArg, NumWarpsAddrCast);
3768 for (
auto En :
enumerate(ReductionInfos)) {
3774 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
3775 unsigned RealTySize =
M.getDataLayout().getTypeAllocSize(
3776 IsByRefElem ? RI.ByRefElementType : RI.ElementType);
3777 for (
unsigned TySize = 4; TySize > 0 && RealTySize > 0; TySize /= 2) {
3780 unsigned NumIters = RealTySize / TySize;
3783 Value *Cnt =
nullptr;
3784 Value *CntAddr =
nullptr;
3791 Builder.CreateAlloca(
Builder.getInt32Ty(),
nullptr,
".cnt.addr");
3793 CntAddr =
Builder.CreateAddrSpaceCast(CntAddr,
Builder.getPtrTy(),
3794 CntAddr->
getName() +
".ascast");
3806 Cnt, ConstantInt::get(
Builder.getInt32Ty(), NumIters));
3807 Builder.CreateCondBr(Cmp, BodyBB, ExitBB);
3814 omp::Directive::OMPD_unknown,
3818 return BarrierIP1.takeError();
3824 Value *IsWarpMaster =
Builder.CreateIsNull(LaneID,
"warp_master");
3825 Builder.CreateCondBr(IsWarpMaster, ThenBB, ElseBB);
3829 auto *RedListArrayTy =
3832 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3834 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3835 {ConstantInt::get(IndexTy, 0),
3836 ConstantInt::get(IndexTy, En.index())});
3840 if (IsByRefElem && RI.DataPtrPtrGen) {
3842 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
3845 return GenRes.takeError();
3856 ArrayTy, TransferMedium, {
Builder.getInt64(0), WarpID});
3861 Builder.CreateStore(Elem, MediumPtr,
3873 omp::Directive::OMPD_unknown,
3877 return BarrierIP2.takeError();
3884 Value *NumWarpsVal =
3887 Value *IsActiveThread =
3888 Builder.CreateICmpULT(GPUThreadID, NumWarpsVal,
"is_active_thread");
3889 Builder.CreateCondBr(IsActiveThread, W0ThenBB, W0ElseBB);
3896 ArrayTy, TransferMedium, {
Builder.getInt64(0), GPUThreadID});
3898 Value *TargetElemPtrPtr =
3899 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3900 {ConstantInt::get(IndexTy, 0),
3901 ConstantInt::get(IndexTy, En.index())});
3902 Value *TargetElemPtrVal =
3904 Value *TargetElemPtr = TargetElemPtrVal;
3906 if (IsByRefElem && RI.DataPtrPtrGen) {
3908 RI.DataPtrPtrGen(
Builder.saveIP(), TargetElemPtr, TargetElemPtr);
3911 return GenRes.takeError();
3913 TargetElemPtr =
Builder.CreateLoad(
Builder.getPtrTy(), TargetElemPtr);
3921 Value *SrcMediumValue =
3922 Builder.CreateLoad(CType, SrcMediumPtrVal,
true);
3923 Builder.CreateStore(SrcMediumValue, TargetElemPtr);
3933 Cnt, ConstantInt::get(
Builder.getInt32Ty(), 1));
3934 Builder.CreateStore(Cnt, CntAddr,
false);
3936 auto *CurFn =
Builder.GetInsertBlock()->getParent();
3940 RealTySize %= TySize;
3949Expected<Function *> OpenMPIRBuilder::emitShuffleAndReduceFunction(
3952 LLVMContext &Ctx =
M.getContext();
3953 IRBuilder<>::InsertPointGuard IPG(
Builder);
3954 FunctionType *FuncTy =
3956 {Builder.getPtrTy(), Builder.getInt16Ty(),
3957 Builder.getInt16Ty(), Builder.getInt16Ty()},
3961 "_omp_reduction_shuffle_and_reduce_func", &
M);
3972 Builder.SetInsertPoint(EntryBB);
3984 Type *ReduceListArgType = ReduceListArg->
getType();
3988 ReduceListArgType,
nullptr, ReduceListArg->
getName() +
".addr");
3989 Value *LaneIdAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
3990 LaneIDArg->
getName() +
".addr");
3992 LaneIDArgType,
nullptr, RemoteLaneOffsetArg->
getName() +
".addr");
3993 Value *AlgoVerAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
3994 AlgoVerArg->
getName() +
".addr");
4001 RedListArrayTy,
nullptr,
".omp.reduction.remote_reduce_list");
4003 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4004 ReduceListAlloca, ReduceListArgType,
4005 ReduceListAlloca->
getName() +
".ascast");
4006 Value *LaneIdAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4007 LaneIdAlloca, LaneIDArgPtrType, LaneIdAlloca->
getName() +
".ascast");
4008 Value *RemoteLaneOffsetAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4009 RemoteLaneOffsetAlloca, LaneIDArgPtrType,
4010 RemoteLaneOffsetAlloca->
getName() +
".ascast");
4011 Value *AlgoVerAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4012 AlgoVerAlloca, LaneIDArgPtrType, AlgoVerAlloca->
getName() +
".ascast");
4013 Value *RemoteListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4014 RemoteReductionListAlloca,
Builder.getPtrTy(),
4015 RemoteReductionListAlloca->
getName() +
".ascast");
4017 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
4018 Builder.CreateStore(LaneIDArg, LaneIdAddrCast);
4019 Builder.CreateStore(RemoteLaneOffsetArg, RemoteLaneOffsetAddrCast);
4020 Builder.CreateStore(AlgoVerArg, AlgoVerAddrCast);
4022 Value *ReduceList =
Builder.CreateLoad(ReduceListArgType, ReduceListAddrCast);
4023 Value *LaneId =
Builder.CreateLoad(LaneIDArgType, LaneIdAddrCast);
4024 Value *RemoteLaneOffset =
4025 Builder.CreateLoad(LaneIDArgType, RemoteLaneOffsetAddrCast);
4026 Value *AlgoVer =
Builder.CreateLoad(LaneIDArgType, AlgoVerAddrCast);
4033 Error EmitRedLsCpRes = emitReductionListCopy(
4035 ReduceList, RemoteListAddrCast, IsByRef,
4036 {RemoteLaneOffset,
nullptr,
nullptr});
4039 return EmitRedLsCpRes;
4064 Value *LaneComp =
Builder.CreateICmpULT(LaneId, RemoteLaneOffset);
4069 Value *Algo2AndLaneIdComp =
Builder.CreateAnd(Algo2, LaneIdComp);
4070 Value *RemoteOffsetComp =
4072 Value *CondAlgo2 =
Builder.CreateAnd(Algo2AndLaneIdComp, RemoteOffsetComp);
4073 Value *CA0OrCA1 =
Builder.CreateOr(CondAlgo0, CondAlgo1);
4074 Value *CondReduce =
Builder.CreateOr(CA0OrCA1, CondAlgo2);
4080 Builder.CreateCondBr(CondReduce, ThenBB, ElseBB);
4082 Value *LocalReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4083 ReduceList,
Builder.getPtrTy());
4084 Value *RemoteReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4085 RemoteListAddrCast,
Builder.getPtrTy());
4087 ->addFnAttr(Attribute::NoUnwind);
4098 Value *LaneIdGtOffset =
Builder.CreateICmpUGE(LaneId, RemoteLaneOffset);
4099 Value *CondCopy =
Builder.CreateAnd(Algo1, LaneIdGtOffset);
4104 Builder.CreateCondBr(CondCopy, CpyThenBB, CpyElseBB);
4108 EmitRedLsCpRes = emitReductionListCopy(
4110 RemoteListAddrCast, ReduceList, IsByRef);
4113 return EmitRedLsCpRes;
4128OpenMPIRBuilder::generateReductionDescriptor(
4130 Type *DescriptorType,
4136 Value *DescriptorSize =
4137 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(DescriptorType));
4139 DescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4140 SrcDescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4144 Value *DataPtrField;
4146 DataPtrPtrGen(
Builder.saveIP(), DescriptorAddr, DataPtrField);
4149 return GenResult.takeError();
4152 DataPtr,
Builder.getPtrTy(),
".ascast"),
4158Expected<Value *> OpenMPIRBuilder::createReductionDescriptorCopy(
4160 Value *SrcDescriptorAddr,
Type *DescriptorPtrTy,
const Twine &Name) {
4164 AllocaInst *DescriptorAlloca =
4165 Builder.CreateAlloca(RI.ByRefAllocatedType,
nullptr, Name);
4167 M.getDataLayout().getPrefTypeAlign(RI.ByRefAllocatedType));
4168 Value *DescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4169 DescriptorAlloca, DescriptorPtrTy,
4170 DescriptorAlloca->
getName() +
".ascast");
4175 generateReductionDescriptor(DescriptorAddr, DataPtr, SrcDescriptorAddr,
4176 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
4178 return GenResult.takeError();
4180 return DescriptorAddr;
4183Expected<Function *> OpenMPIRBuilder::emitListToGlobalCopyFunction(
4186 IRBuilder<>::InsertPointGuard IPG(
Builder);
4187 LLVMContext &Ctx =
M.getContext();
4190 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4194 "_omp_reduction_list_to_global_copy_func", &
M);
4201 Builder.SetInsertPoint(EntryBlock);
4212 BufferArg->
getName() +
".addr");
4216 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4217 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4218 BufferArgAlloca,
Builder.getPtrTy(),
4219 BufferArgAlloca->
getName() +
".ascast");
4220 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4221 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4222 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4223 ReduceListArgAlloca,
Builder.getPtrTy(),
4224 ReduceListArgAlloca->
getName() +
".ascast");
4226 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4227 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4228 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4230 Value *LocalReduceList =
4232 Value *BufferArgVal =
4236 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4237 for (
auto En :
enumerate(ReductionInfos)) {
4239 auto *RedListArrayTy =
4243 RedListArrayTy, LocalReduceList,
4244 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4250 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferArgVal, Idxs);
4252 ReductionsBufferTy, BufferVD, 0, En.index());
4254 switch (RI.EvaluationKind) {
4256 Value *TargetElement;
4258 if (IsByRef.
empty() || !IsByRef[En.index()]) {
4259 TargetElement =
Builder.CreateLoad(RI.ElementType, ElemPtr);
4261 if (RI.DataPtrPtrGen) {
4263 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
4266 return GenResult.takeError();
4270 TargetElement =
Builder.CreateLoad(RI.ByRefElementType, ElemPtr);
4273 Builder.CreateStore(TargetElement, GlobVal);
4277 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4278 RI.ElementType, ElemPtr, 0, 0,
".realp");
4280 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
4282 RI.ElementType, ElemPtr, 0, 1,
".imagp");
4284 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
4286 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4287 RI.ElementType, GlobVal, 0, 0,
".realp");
4288 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4289 RI.ElementType, GlobVal, 0, 1,
".imagp");
4290 Builder.CreateStore(SrcReal, DestRealPtr);
4291 Builder.CreateStore(SrcImg, DestImgPtr);
4296 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(RI.ElementType));
4298 GlobVal,
M.getDataLayout().getPrefTypeAlign(RI.ElementType), ElemPtr,
4299 M.getDataLayout().getPrefTypeAlign(RI.ElementType), SizeVal,
false);
4309Expected<Function *> OpenMPIRBuilder::emitListToGlobalReduceFunction(
4312 IRBuilder<>::InsertPointGuard IPG(
Builder);
4313 LLVMContext &Ctx =
M.getContext();
4316 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4320 "_omp_reduction_list_to_global_reduce_func", &
M);
4327 Builder.SetInsertPoint(EntryBlock);
4338 BufferArg->
getName() +
".addr");
4342 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4343 auto *RedListArrayTy =
4348 Value *LocalReduceList =
4349 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4353 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4354 BufferArgAlloca,
Builder.getPtrTy(),
4355 BufferArgAlloca->
getName() +
".ascast");
4356 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4357 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4358 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4359 ReduceListArgAlloca,
Builder.getPtrTy(),
4360 ReduceListArgAlloca->
getName() +
".ascast");
4361 Value *LocalReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4362 LocalReduceList,
Builder.getPtrTy(),
4363 LocalReduceList->
getName() +
".ascast");
4365 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4366 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4367 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4372 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4373 for (
auto En :
enumerate(ReductionInfos)) {
4376 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4377 RedListArrayTy, LocalReduceListAddrCast,
4378 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4380 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4382 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4383 ReductionsBufferTy, BufferVD, 0, En.index());
4385 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4389 Value *SrcElementPtrPtr =
4390 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
4391 {ConstantInt::get(IndexTy, 0),
4392 ConstantInt::get(IndexTy, En.index())});
4393 Value *SrcDescriptorAddr =
4397 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4398 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4402 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4404 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4412 ->addFnAttr(Attribute::NoUnwind);
4417Expected<Function *> OpenMPIRBuilder::emitGlobalToListCopyFunction(
4420 IRBuilder<>::InsertPointGuard IPG(
Builder);
4421 LLVMContext &Ctx =
M.getContext();
4424 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4428 "_omp_reduction_global_to_list_copy_func", &
M);
4435 Builder.SetInsertPoint(EntryBlock);
4446 BufferArg->
getName() +
".addr");
4450 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4451 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4452 BufferArgAlloca,
Builder.getPtrTy(),
4453 BufferArgAlloca->
getName() +
".ascast");
4454 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4455 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4456 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4457 ReduceListArgAlloca,
Builder.getPtrTy(),
4458 ReduceListArgAlloca->
getName() +
".ascast");
4459 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4460 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4461 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4463 Value *LocalReduceList =
4468 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4469 for (
auto En :
enumerate(ReductionInfos)) {
4470 const OpenMPIRBuilder::ReductionInfo &RI = En.value();
4471 auto *RedListArrayTy =
4475 RedListArrayTy, LocalReduceList,
4476 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4481 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4482 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4483 ReductionsBufferTy, BufferVD, 0, En.index());
4489 if (!IsByRef.
empty() && IsByRef[En.index()]) {
4496 return GenResult.takeError();
4502 Value *TargetElement =
Builder.CreateLoad(ElemType, GlobValPtr);
4503 Builder.CreateStore(TargetElement, ElemPtr);
4507 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4516 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4518 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4520 Builder.CreateStore(SrcReal, DestRealPtr);
4521 Builder.CreateStore(SrcImg, DestImgPtr);
4528 ElemPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4529 GlobValPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4540Expected<Function *> OpenMPIRBuilder::emitGlobalToListReduceFunction(
4543 IRBuilder<>::InsertPointGuard IPG(
Builder);
4544 LLVMContext &Ctx =
M.getContext();
4547 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4551 "_omp_reduction_global_to_list_reduce_func", &
M);
4558 Builder.SetInsertPoint(EntryBlock);
4569 BufferArg->
getName() +
".addr");
4573 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4579 Value *LocalReduceList =
4580 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4584 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4585 BufferArgAlloca,
Builder.getPtrTy(),
4586 BufferArgAlloca->
getName() +
".ascast");
4587 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4588 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4589 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4590 ReduceListArgAlloca,
Builder.getPtrTy(),
4591 ReduceListArgAlloca->
getName() +
".ascast");
4592 Value *ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4593 LocalReduceList,
Builder.getPtrTy(),
4594 LocalReduceList->
getName() +
".ascast");
4596 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4597 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4598 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4603 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4604 for (
auto En :
enumerate(ReductionInfos)) {
4607 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4608 RedListArrayTy, ReductionList,
4609 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4612 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4613 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4614 ReductionsBufferTy, BufferVD, 0, En.index());
4616 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4618 Value *ReduceListVal =
4620 Value *SrcElementPtrPtr =
4621 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceListVal,
4622 {ConstantInt::get(IndexTy, 0),
4623 ConstantInt::get(IndexTy, En.index())});
4624 Value *SrcDescriptorAddr =
4628 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4629 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4633 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4635 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4643 ->addFnAttr(Attribute::NoUnwind);
4648std::string OpenMPIRBuilder::getReductionFuncName(StringRef Name)
const {
4649 std::string Suffix =
4651 return (Name + Suffix).str();
4654Expected<Function *> OpenMPIRBuilder::createReductionFunction(
4657 AttributeList FuncAttrs) {
4658 IRBuilder<>::InsertPointGuard IPG(
Builder);
4660 {Builder.getPtrTy(), Builder.getPtrTy()},
4662 std::string
Name = getReductionFuncName(ReducerName);
4671 Builder.SetInsertPoint(EntryBB);
4676 Value *LHSArrayPtr =
nullptr;
4677 Value *RHSArrayPtr =
nullptr;
4684 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
4686 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
4687 Value *LHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4688 LHSAlloca, Arg0Type, LHSAlloca->
getName() +
".ascast");
4689 Value *RHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4690 RHSAlloca, Arg1Type, RHSAlloca->
getName() +
".ascast");
4691 Builder.CreateStore(Arg0, LHSAddrCast);
4692 Builder.CreateStore(Arg1, RHSAddrCast);
4693 LHSArrayPtr =
Builder.CreateLoad(Arg0Type, LHSAddrCast);
4694 RHSArrayPtr =
Builder.CreateLoad(Arg1Type, RHSAddrCast);
4698 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4700 for (
auto En :
enumerate(ReductionInfos)) {
4703 RedArrayTy, RHSArrayPtr,
4704 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4706 Value *RHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4707 RHSI8Ptr, RI.PrivateVariable->getType(),
4708 RHSI8Ptr->
getName() +
".ascast");
4711 RedArrayTy, LHSArrayPtr,
4712 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4714 Value *LHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4715 LHSI8Ptr, RI.Variable->getType(), LHSI8Ptr->
getName() +
".ascast");
4724 if (!IsByRef.
empty() && !IsByRef[En.index()]) {
4725 LHS =
Builder.CreateLoad(RI.ElementType, LHSPtr);
4726 RHS =
Builder.CreateLoad(RI.ElementType, RHSPtr);
4733 return AfterIP.takeError();
4734 if (!
Builder.GetInsertBlock())
4735 return ReductionFunc;
4739 if (!IsByRef.
empty() && !IsByRef[En.index()])
4740 Builder.CreateStore(Reduced, LHSPtr);
4745 for (
auto En :
enumerate(ReductionInfos)) {
4746 unsigned Index = En.index();
4748 Value *LHSFixupPtr, *RHSFixupPtr;
4749 Builder.restoreIP(RI.ReductionGenClang(
4750 Builder.saveIP(), Index, &LHSFixupPtr, &RHSFixupPtr, ReductionFunc));
4755 LHSPtrs[Index], [ReductionFunc](
const Use &U) {
4760 RHSPtrs[Index], [ReductionFunc](
const Use &U) {
4774 return ReductionFunc;
4782 assert(RI.Variable &&
"expected non-null variable");
4783 assert(RI.PrivateVariable &&
"expected non-null private variable");
4784 assert((RI.ReductionGen || RI.ReductionGenClang) &&
4785 "expected non-null reduction generator callback");
4788 RI.Variable->getType() == RI.PrivateVariable->getType() &&
4789 "expected variables and their private equivalents to have the same "
4792 assert(RI.Variable->getType()->isPointerTy() &&
4793 "expected variables to be pointers");
4810 ArrayRef<bool> IsByRef,
bool IsNoWait,
bool IsTeamsReduction,
bool IsSPMD,
4812 Value *SrcLocInfo) {
4826 if (ReductionInfos.
size() == 0)
4836 Builder.SetInsertPoint(InsertBlock, InsertBlock->
end());
4841 AttrBuilder AttrBldr(Ctx);
4843 AttrBldr.addAttribute(Attr);
4844 AttrBldr.removeAttribute(Attribute::OptimizeNone);
4845 FuncAttrs = FuncAttrs.addFnAttributes(Ctx, AttrBldr);
4849 Builder.GetInsertBlock()->getParent()->getName(), ReductionInfos, IsByRef,
4851 if (!ReductionResult)
4853 Function *ReductionFunc = *ReductionResult;
4857 if (GridValue.has_value())
4858 Config.setGridValue(GridValue.value());
4873 Builder.getPtrTy(
M.getDataLayout().getProgramAddressSpace());
4877 Value *ReductionListAlloca =
4878 Builder.CreateAlloca(RedArrayTy,
nullptr,
".omp.reduction.red_list");
4879 Value *ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4880 ReductionListAlloca, PtrTy, ReductionListAlloca->
getName() +
".ascast");
4883 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4884 for (
auto En :
enumerate(ReductionInfos)) {
4887 RedArrayTy, ReductionList,
4888 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4891 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
4896 Builder.CreatePointerBitCastOrAddrSpaceCast(PrivateVar, PtrTy);
4897 Builder.CreateStore(CastElem, ElemPtr);
4901 ReductionInfos, ReductionFunc, FuncAttrs, IsByRef);
4907 emitInterWarpCopyFunction(
Loc, ReductionInfos, FuncAttrs, IsByRef);
4913 Value *RL =
Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList, PtrTy);
4922 unsigned MaxDataSize = 0;
4924 for (
auto En :
enumerate(ReductionInfos)) {
4928 Type *RedTypeArg = (!IsByRef.
empty() && IsByRef[En.index()])
4929 ? En.value().ByRefElementType
4930 : En.value().ElementType;
4931 auto Size =
M.getDataLayout().getTypeStoreSize(RedTypeArg);
4932 if (
Size > MaxDataSize)
4936 Value *ReductionDataSize =
4937 Builder.getInt64(MaxDataSize * ReductionInfos.
size());
4941 Function *CopyScratchToListFunc =
nullptr;
4943 Value *ScratchForCopyBack =
nullptr;
4946 Value *RLForCopyBack = RL;
4948 bool IsAtomicReduction =
4951 if (!IsTeamsReduction) {
4952 Value *SarFuncCast =
4953 Builder.CreatePointerBitCastOrAddrSpaceCast(*SarFunc, FuncPtrTy);
4955 Builder.CreatePointerBitCastOrAddrSpaceCast(WcFunc, FuncPtrTy);
4956 Value *Args[] = {SrcLocInfo, ReductionDataSize, RL, SarFuncCast,
4959 RuntimeFunction::OMPRTL___kmpc_nvptx_parallel_reduce_nowait_v2);
4961 }
else if (IsAtomicReduction) {
4965 RuntimeFunction::OMPRTL___kmpc_is_team_main_thread);
4970 Ctx, ReductionTypeArgs,
"struct._globalized_locals_ty");
4973 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
4978 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
4983 ReductionInfos, ReductionFunc, ReductionsBufferTy, FuncAttrs, IsByRef);
5006 Value *RuntimeRL = RL;
5013 ReductionsBufferTy,
nullptr,
".omp.reduction.scratch");
5014 Value *PerThreadScratch =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5015 PerThreadScratchAlloca, PtrTy,
5016 PerThreadScratchAlloca->
getName() +
".ascast");
5019 Value *PerThreadRedListAlloca =
5020 Builder.CreateAlloca(RedArrayTy,
nullptr,
5021 ".omp.reduction.per_thread_red_list");
5022 RuntimeRL =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5023 PerThreadRedListAlloca, PtrTy,
5024 PerThreadRedListAlloca->
getName() +
".ascast");
5029 for (
auto En :
enumerate(ReductionInfos)) {
5031 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
5034 ReductionsBufferTy, PerThreadScratch, 0, En.index());
5035 Value *Slot =
Builder.CreateConstInBoundsGEP2_32(RedArrayTy, RuntimeRL,
5038 Value *RuntimeListEntry = FieldPtr;
5040 Value *SrcDescriptor =
5043 AllocaIP, RI, FieldPtr, SrcDescriptor, PtrTy);
5046 RuntimeListEntry = *Descriptor;
5048 Builder.CreateStore(RuntimeListEntry, Slot);
5054 Type *CopyArg0Ty = (*LtGCFunc)->getFunctionType()->getParamType(0);
5055 Type *CopyArg2Ty = (*LtGCFunc)->getFunctionType()->getParamType(2);
5056 ScratchForCopyBack =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5057 PerThreadScratch, CopyArg0Ty);
5059 Builder.CreatePointerBitCastOrAddrSpaceCast(RL, CopyArg2Ty);
5067 *LtGCFunc, {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
5068 CopyScratchToListFunc = *GtLCFunc;
5071 Value *Args3[] = {SrcLocInfo, RuntimeRL, *SarFunc, WcFunc,
5072 *LtGCFunc, *GtLCFunc, *GtLRFunc};
5075 RuntimeFunction::OMPRTL___kmpc_gpu_xteam_reduce_nowait);
5095 if (ScratchForCopyBack) {
5098 CopyScratchToListFunc,
5099 {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
5103 for (
auto En :
enumerate(ReductionInfos)) {
5109 if (IsAtomicReduction) {
5125 Value *LHSPtr, *RHSPtr;
5127 &LHSPtr, &RHSPtr, CurFunc));
5133 RedValue =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5135 if (RHSPtr->
getType() != RHS->getType())
5137 Builder.CreatePointerBitCastOrAddrSpaceCast(RHS, RHSPtr->
getType());
5148 if (IsByRef.
empty() || !IsByRef[En.index()]) {
5150 "red.value." +
Twine(En.index()));
5161 if (!IsByRef.
empty() && !IsByRef[En.index()])
5166 if (ContinuationBlock) {
5167 Builder.CreateBr(ContinuationBlock);
5168 Builder.SetInsertPoint(ContinuationBlock);
5170 Config.setEmitLLVMUsed();
5181 ".omp.reduction.func", &M);
5192 Builder.SetInsertPoint(ReductionFuncBlock);
5194 Value *LHSArrayPtr =
nullptr;
5195 Value *RHSArrayPtr =
nullptr;
5206 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
5208 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
5209 Value *LHSAddrCast =
5210 Builder.CreatePointerBitCastOrAddrSpaceCast(LHSAlloca, Arg0Type);
5211 Value *RHSAddrCast =
5212 Builder.CreatePointerBitCastOrAddrSpaceCast(RHSAlloca, Arg1Type);
5213 Builder.CreateStore(Arg0, LHSAddrCast);
5214 Builder.CreateStore(Arg1, RHSAddrCast);
5215 LHSArrayPtr = Builder.CreateLoad(Arg0Type, LHSAddrCast);
5216 RHSArrayPtr = Builder.CreateLoad(Arg1Type, RHSAddrCast);
5218 LHSArrayPtr = ReductionFunc->
getArg(0);
5219 RHSArrayPtr = ReductionFunc->
getArg(1);
5222 unsigned NumReductions = ReductionInfos.
size();
5225 for (
auto En :
enumerate(ReductionInfos)) {
5227 Value *LHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5228 RedArrayTy, LHSArrayPtr, 0, En.index());
5229 Value *LHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), LHSI8PtrPtr);
5230 Value *LHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5233 Value *RHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5234 RedArrayTy, RHSArrayPtr, 0, En.index());
5235 Value *RHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), RHSI8PtrPtr);
5236 Value *RHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5245 Builder.restoreIP(*AfterIP);
5247 if (!Builder.GetInsertBlock())
5251 if (!IsByRef[En.index()])
5252 Builder.CreateStore(Reduced, LHSPtr);
5254 Builder.CreateRetVoid();
5261 bool IsNoWait,
bool IsTeamsReduction) {
5265 IsByRef, IsNoWait, IsTeamsReduction);
5272 if (ReductionInfos.
size() == 0)
5282 unsigned NumReductions = ReductionInfos.
size();
5285 Value *RedArray =
Builder.CreateAlloca(RedArrayTy,
nullptr,
"red.array");
5287 Builder.SetInsertPoint(InsertBlock, InsertBlock->
end());
5292 for (
auto En :
enumerate(ReductionInfos)) {
5293 unsigned Index = En.index();
5295 Value *RedArrayElemPtr =
Builder.CreateConstInBoundsGEP2_64(
5296 RedArrayTy, RedArray, 0, Index,
"red.array.elem." +
Twine(Index));
5303 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
5313 ? IdentFlag::OMP_IDENT_FLAG_ATOMIC_REDUCE
5318 unsigned RedArrayByteSize =
DL.getTypeStoreSize(RedArrayTy);
5319 Constant *RedArraySize = ConstantInt::get(IndexTy, RedArrayByteSize);
5321 Value *Lock = getOMPCriticalRegionLock(
".reduction");
5323 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_reduce_nowait
5324 : RuntimeFunction::OMPRTL___kmpc_reduce);
5327 {Ident, ThreadId, NumVariables, RedArraySize,
5328 RedArray, ReductionFunc, Lock},
5339 Builder.CreateSwitch(ReduceCall, ContinuationBlock, 2);
5340 Switch->addCase(
Builder.getInt32(1), NonAtomicRedBlock);
5341 Switch->addCase(
Builder.getInt32(2), AtomicRedBlock);
5346 Builder.SetInsertPoint(NonAtomicRedBlock);
5347 for (
auto En :
enumerate(ReductionInfos)) {
5353 if (!IsByRef[En.index()]) {
5355 "red.value." +
Twine(En.index()));
5357 Value *PrivateRedValue =
5359 "red.private.value." +
Twine(En.index()));
5367 if (!
Builder.GetInsertBlock())
5370 if (!IsByRef[En.index()])
5374 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_end_reduce_nowait
5375 : RuntimeFunction::OMPRTL___kmpc_end_reduce);
5377 Builder.CreateBr(ContinuationBlock);
5382 Builder.SetInsertPoint(AtomicRedBlock);
5383 if (CanGenerateAtomic &&
llvm::none_of(IsByRef, [](
bool P) {
return P; })) {
5390 if (!
Builder.GetInsertBlock())
5393 Builder.CreateBr(ContinuationBlock);
5406 if (!
Builder.GetInsertBlock())
5409 Builder.SetInsertPoint(ContinuationBlock);
5420 Directive OMPD = Directive::OMPD_master;
5425 Value *Args[] = {Ident, ThreadId};
5433 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5445 Directive OMPD = Directive::OMPD_masked;
5451 Value *ArgsEnd[] = {Ident, ThreadId};
5459 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5469 Call->setDoesNotThrow();
5484 bool IsInclusive,
ScanInfo *ScanRedInfo) {
5486 llvm::Error Err = emitScanBasedDirectiveDeclsIR(AllocaIP, ScanVars,
5487 ScanVarsType, ScanRedInfo);
5498 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5501 Type *DestTy = ScanVarsType[i];
5502 Value *Val =
Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5505 Builder.CreateStore(Src, Val);
5510 Builder.GetInsertBlock()->getParent());
5513 IV = ScanRedInfo->
IV;
5516 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5519 Type *DestTy = ScanVarsType[i];
5521 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5523 Builder.CreateStore(Src, ScanVars[i]);
5537 Builder.GetInsertBlock()->getParent());
5542Error OpenMPIRBuilder::emitScanBasedDirectiveDeclsIR(
5546 Builder.restoreIP(AllocaIP);
5548 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5550 Builder.CreateAlloca(Builder.getPtrTy(),
nullptr,
"vla");
5557 Builder.restoreIP(CodeGenIP);
5559 Builder.CreateAdd(ScanRedInfo->
Span, Builder.getInt32(1));
5560 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5565 Builder.CreateMalloc(
IntPtrTy, Allocsize, AllocSpan,
nullptr,
"arr");
5566 Builder.CreateStore(Buff, (*(ScanRedInfo->
ScanBuffPtrs))[ScanVars[i]]);
5593Error OpenMPIRBuilder::emitScanBasedDirectiveFinalsIR(
5599 Value *PrivateVar = RedInfo.PrivateVariable;
5600 Value *OrigVar = RedInfo.Variable;
5604 Type *SrcTy = RedInfo.ElementType;
5609 Builder.CreateStore(Src, OrigVar);
5657 Builder.GetInsertBlock()->getModule(),
5664 Builder.GetInsertBlock()->getModule(),
5670 llvm::ConstantInt::get(ScanRedInfo->
Span->
getType(), 1));
5671 Builder.SetInsertPoint(InputBB);
5674 Builder.SetInsertPoint(LoopBB);
5690 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5692 Builder.SetInsertPoint(InnerLoopBB);
5696 Value *ReductionVal = RedInfo.PrivateVariable;
5699 Type *DestTy = RedInfo.ElementType;
5702 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5705 Builder.CreateInBoundsGEP(DestTy, Buff, OffsetIval,
"arrayOffset");
5710 RedInfo.ReductionGen(
Builder.saveIP(), LHS, RHS, Result);
5713 Builder.CreateStore(Result, LHSPtr);
5716 IVal, llvm::ConstantInt::get(
Builder.getInt32Ty(), 1));
5718 CmpI =
Builder.CreateICmpUGE(NextIVal, Pow2K);
5719 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5722 Counter, llvm::ConstantInt::get(Counter->
getType(), 1));
5728 Builder.CreateCondBr(Cmp, LoopBB, ExitBB);
5749 Error Err = emitScanBasedDirectiveFinalsIR(ReductionInfos, ScanRedInfo);
5756Error OpenMPIRBuilder::emitScanBasedDirectiveIR(
5768 Error Err = InputLoopGen();
5779 Error Err = ScanLoopGen(Builder);
5786void OpenMPIRBuilder::createScanBBs(ScanInfo *ScanRedInfo) {
5823 Builder.SetInsertPoint(Preheader);
5826 Builder.SetInsertPoint(Header);
5827 PHINode *IndVarPHI =
Builder.CreatePHI(IndVarTy, 2,
"omp_" + Name +
".iv");
5828 IndVarPHI->
addIncoming(ConstantInt::get(IndVarTy, 0), Preheader);
5833 Builder.CreateICmpULT(IndVarPHI, TripCount,
"omp_" + Name +
".cmp");
5834 Builder.CreateCondBr(Cmp, Body, Exit);
5839 Builder.SetInsertPoint(Latch);
5849 bool HasNSW =
Config.hasNoSignedWrap();
5852 unsigned BitWidth = CI->getType()->getIntegerBitWidth();
5854 if (CI->getValue().ugt(SignedMax))
5856 }
else if (IsCollapsed) {
5861 Builder.CreateAdd(IndVarPHI, ConstantInt::get(IndVarTy, 1),
5862 "omp_" + Name +
".next",
true, HasNSW);
5873 CL->Header = Header;
5892 NextBB, NextBB, Name);
5924 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
5933 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
5934 ScanRedInfo->
Span = TripCount;
5940 ScanRedInfo->
IV =
IV;
5941 createScanBBs(ScanRedInfo);
5944 assert(Terminator->getNumSuccessors() == 1);
5945 BasicBlock *ContinueBlock = Terminator->getSuccessor(0);
5948 Builder.GetInsertBlock()->getParent());
5951 Builder.GetInsertBlock()->getParent());
5952 Builder.CreateBr(ContinueBlock);
5958 const auto &&InputLoopGen = [&]() ->
Error {
5961 InclusiveStop, ComputeIP, Name,
true, ScanRedInfo);
5965 Builder.restoreIP((*LoopInfo)->getAfterIP());
5971 InclusiveStop, ComputeIP, Name,
true, ScanRedInfo);
5975 Builder.restoreIP((*LoopInfo)->getAfterIP());
5979 Error Err = emitScanBasedDirectiveIR(InputLoopGen, ScanLoopGen, ScanRedInfo);
5987 bool IsSigned,
bool InclusiveStop,
const Twine &Name) {
5997 assert(IndVarTy == Stop->
getType() &&
"Stop type mismatch");
5998 assert(IndVarTy == Step->
getType() &&
"Step type mismatch");
6002 ConstantInt *Zero = ConstantInt::get(IndVarTy, 0);
6018 Incr =
Builder.CreateSelect(IsNeg,
Builder.CreateNeg(Step), Step);
6021 Span =
Builder.CreateSub(UB, LB,
"",
false,
true);
6025 Span =
Builder.CreateSub(Stop, Start,
"",
true);
6030 Value *CountIfLooping;
6031 if (InclusiveStop) {
6032 CountIfLooping =
Builder.CreateAdd(
Builder.CreateUDiv(Span, Incr), One);
6038 CountIfLooping =
Builder.CreateSelect(OneCmp, One, CountIfTwo);
6041 return Builder.CreateSelect(ZeroCmp, Zero, CountIfLooping,
6042 "omp_" + Name +
".tripcount");
6047 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
6054 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
6059 Config.hasNoSignedWrap());
6060 Value *IndVar =
Builder.CreateAdd(Span, Start,
"",
false,
6061 Config.hasNoSignedWrap());
6063 ScanRedInfo->
IV = IndVar;
6064 return BodyGenCB(
Builder.saveIP(), IndVar);
6070 Builder.getCurrentDebugLocation());
6081 unsigned Bitwidth = Ty->getIntegerBitWidth();
6084 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_4u);
6087 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_8u);
6097 unsigned Bitwidth = Ty->getIntegerBitWidth();
6100 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_4u);
6103 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_8u);
6111 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6113 "Require dedicated allocate IP");
6119 uint32_t SrcLocStrSize;
6123 case WorksharingLoopType::ForStaticLoop:
6124 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6126 case WorksharingLoopType::DistributeStaticLoop:
6127 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6129 case WorksharingLoopType::DistributeForStaticLoop:
6130 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
6137 Type *IVTy =
IV->getType();
6138 FunctionCallee StaticInit =
6139 LoopType == WorksharingLoopType::DistributeForStaticLoop
6142 FunctionCallee StaticFini =
6146 Builder.SetInsertPoint(AllocaIP.getBlock()->getFirstNonPHIOrDbgOrAlloca());
6149 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6150 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
6151 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
6152 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
6161 Constant *One = ConstantInt::get(IVTy, 1);
6162 Builder.CreateStore(Zero, PLowerBound);
6164 Builder.CreateStore(UpperBound, PUpperBound);
6165 Builder.CreateStore(One, PStride);
6171 (LoopType == WorksharingLoopType::DistributeStaticLoop)
6172 ? OMPScheduleType::OrderedDistribute
6175 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6179 auto BuildInitCall = [LoopType, SrcLoc, ThreadNum, PLastIter, PLowerBound,
6180 PUpperBound, IVTy, PStride, One,
Zero, StaticInit,
6183 PLowerBound, PUpperBound});
6184 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
6185 Value *PDistUpperBound =
6186 Builder.CreateAlloca(IVTy,
nullptr,
"p.distupperbound");
6187 Args.push_back(PDistUpperBound);
6192 BuildInitCall(SchedulingType,
Builder);
6193 if (HasDistSchedule &&
6194 LoopType != WorksharingLoopType::DistributeStaticLoop) {
6195 Constant *DistScheduleSchedType = ConstantInt::get(
6200 BuildInitCall(DistScheduleSchedType,
Builder);
6203 Value *InclusiveUpperBound =
Builder.CreateLoad(IVTy, PUpperBound);
6205 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One);
6206 CLI->setTripCount(TripCount);
6212 CLI->mapIndVar([&](Instruction *OldIV) ->
Value * {
6217 Config.hasNoSignedWrap());
6229 omp::Directive::OMPD_for,
false,
6232 return BarrierIP.takeError();
6259 Reachable.insert(
Block);
6273OpenMPIRBuilder::applyStaticChunkedWorkshareLoop(
6277 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6278 assert((ChunkSize || DistScheduleChunkSize) &&
"Chunk size is required");
6283 Type *IVTy =
IV->getType();
6285 "Max supported tripcount bitwidth is 64 bits");
6287 :
Type::getInt64Ty(Ctx);
6290 Constant *One = ConstantInt::get(InternalIVTy, 1);
6295 SmallVector<Instruction *> UIs;
6296 for (BasicBlock &BB : *
F)
6297 if (!BB.hasTerminator())
6298 UIs.
push_back(
new UnreachableInst(
F->getContext(), &BB));
6303 LoopInfo &&LI = LIA.
run(*
F,
FAM);
6304 for (Instruction *
I : UIs)
6305 I->eraseFromParent();
6308 if (ChunkSize || DistScheduleChunkSize)
6313 FunctionCallee StaticInit =
6315 FunctionCallee StaticFini =
6321 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6322 Value *PLowerBound =
6323 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.lowerbound");
6324 Value *PUpperBound =
6325 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.upperbound");
6326 Value *PStride =
Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.stride");
6335 ChunkSize ? ChunkSize : Zero, InternalIVTy,
"chunksize");
6336 Value *CastedDistScheduleChunkSize =
Builder.CreateZExtOrTrunc(
6337 DistScheduleChunkSize ? DistScheduleChunkSize : Zero, InternalIVTy,
6338 "distschedulechunksize");
6339 Value *CastedTripCount =
6340 Builder.CreateZExt(OrigTripCount, InternalIVTy,
"tripcount");
6343 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6345 ConstantInt::get(I32Type,
static_cast<int>(DistScheduleSchedType));
6346 Builder.CreateStore(Zero, PLowerBound);
6347 Value *OrigUpperBound =
Builder.CreateSub(CastedTripCount, One);
6348 Value *IsTripCountZero =
Builder.CreateICmpEQ(CastedTripCount, Zero);
6350 Builder.CreateSelect(IsTripCountZero, Zero, OrigUpperBound);
6351 Builder.CreateStore(UpperBound, PUpperBound);
6352 Builder.CreateStore(One, PStride);
6356 uint32_t SrcLocStrSize;
6359 if (DistScheduleSchedType != OMPScheduleType::None) {
6360 Flag |= OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6365 auto BuildInitCall = [StaticInit, SrcLoc, ThreadNum, PLastIter, PLowerBound,
6366 PUpperBound, PStride, One,
6367 this](
Value *SchedulingType,
Value *ChunkSize,
6370 StaticInit, {SrcLoc, ThreadNum,
6371 SchedulingType, PLastIter,
6372 PLowerBound, PUpperBound,
6376 BuildInitCall(SchedulingType, CastedChunkSize,
Builder);
6377 if (DistScheduleSchedType != OMPScheduleType::None &&
6378 SchedType != OMPScheduleType::OrderedDistributeChunked &&
6379 SchedType != OMPScheduleType::OrderedDistribute) {
6383 BuildInitCall(DistSchedulingType, CastedDistScheduleChunkSize,
Builder);
6387 Value *FirstChunkStart =
6388 Builder.CreateLoad(InternalIVTy, PLowerBound,
"omp_firstchunk.lb");
6389 Value *FirstChunkStop =
6390 Builder.CreateLoad(InternalIVTy, PUpperBound,
"omp_firstchunk.ub");
6391 Value *FirstChunkEnd =
Builder.CreateAdd(FirstChunkStop, One);
6393 Builder.CreateSub(FirstChunkEnd, FirstChunkStart,
"omp_chunk.range");
6394 Value *NextChunkStride =
6395 Builder.CreateLoad(InternalIVTy, PStride,
"omp_dispatch.stride");
6399 Value *DispatchCounter;
6407 DispatchCounter = Counter;
6410 FirstChunkStart, CastedTripCount, NextChunkStride,
6433 Value *ChunkEnd =
Builder.CreateAdd(DispatchCounter, ChunkRange);
6434 Value *IsLastChunk =
6435 Builder.CreateICmpUGE(ChunkEnd, CastedTripCount,
"omp_chunk.is_last");
6436 Value *CountUntilOrigTripCount =
6437 Builder.CreateSub(CastedTripCount, DispatchCounter);
6439 IsLastChunk, CountUntilOrigTripCount, ChunkRange,
"omp_chunk.tripcount");
6440 Value *BackcastedChunkTC =
6441 Builder.CreateTrunc(ChunkTripCount, IVTy,
"omp_chunk.tripcount.trunc");
6442 CLI->setTripCount(BackcastedChunkTC);
6447 Value *BackcastedDispatchCounter =
6448 Builder.CreateTrunc(DispatchCounter, IVTy,
"omp_dispatch.iv.trunc");
6449 CLI->mapIndVar([&](Instruction *) ->
Value * {
6451 return Builder.CreateAdd(
IV, BackcastedDispatchCounter);
6464 return AfterIP.takeError();
6479static FunctionCallee
6482 unsigned Bitwidth = Ty->getIntegerBitWidth();
6485 case WorksharingLoopType::ForStaticLoop:
6488 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_4u);
6491 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_8u);
6493 case WorksharingLoopType::DistributeStaticLoop:
6496 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_4u);
6499 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_8u);
6501 case WorksharingLoopType::DistributeForStaticLoop:
6504 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_4u);
6507 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_8u);
6510 if (Bitwidth != 32 && Bitwidth != 64) {
6522 Function &LoopBodyFn,
bool NoLoop) {
6533 if (LoopType == WorksharingLoopType::DistributeStaticLoop) {
6534 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6535 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6536 Builder.restoreIP({InsertBlock, std::prev(InsertBlock->
end())});
6541 M, omp::RuntimeFunction::OMPRTL_omp_get_num_threads);
6542 Builder.restoreIP({InsertBlock, std::prev(InsertBlock->
end())});
6546 Builder.CreateZExtOrTrunc(NumThreads, TripCountTy,
"num.threads.cast"));
6547 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6548 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
6549 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6550 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), NoLoop));
6552 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6576 Builder.restoreIP({Preheader, Preheader->
end()});
6579 Builder.CreateBr(CLI->
getExit());
6587 CleanUpInfo.
collectBlocks(RegionBlockSet, BlocksToBeRemoved);
6595 "Expected unique undroppable user of outlined function");
6597 assert(OutlinedFnCallInstruction &&
"Expected outlined function call");
6599 "Expected outlined function call to be located in loop preheader");
6601 if (OutlinedFnCallInstruction->
arg_size() > 1)
6608 LoopBodyArg, TripCount, OutlinedFn, NoLoop);
6610 for (
auto &ToBeDeletedItem : ToBeDeleted)
6611 ToBeDeletedItem->eraseFromParent();
6618 uint32_t SrcLocStrSize;
6622 case WorksharingLoopType::ForStaticLoop:
6623 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6625 case WorksharingLoopType::DistributeStaticLoop:
6626 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6628 case WorksharingLoopType::DistributeForStaticLoop:
6629 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
6634 auto OI = std::make_unique<OutlineInfo>();
6639 SmallVector<Instruction *, 4> ToBeDeleted;
6641 OI->OuterAllocBB = AllocaIP.getBlock();
6664 SmallPtrSet<BasicBlock *, 32> ParallelRegionBlockSet;
6666 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
6668 CodeExtractorAnalysisCache CEAC(*OuterFn);
6669 CodeExtractor Extractor(Blocks,
6683 SetVector<Value *> SinkingCands, HoistingCands;
6687 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
6694 for (
auto Use :
Users) {
6696 if (ParallelRegionBlockSet.
count(Inst->getParent())) {
6697 Inst->replaceUsesOfWith(CLI->
getIndVar(), NewLoopCntLoad);
6703 OI->ExcludeArgsFromAggregate.push_back(NewLoopCntLoad);
6710 OI->PostOutlineCB = [=, ToBeDeletedVec =
6711 std::move(ToBeDeleted)](
Function &OutlinedFn) {
6721 bool NeedsBarrier, omp::ScheduleKind SchedKind,
Value *ChunkSize,
6722 bool HasSimdModifier,
bool HasMonotonicModifier,
6723 bool HasNonmonotonicModifier,
bool HasOrderedClause,
6725 Value *DistScheduleChunkSize) {
6726 if (
Config.isTargetDevice())
6727 return applyWorkshareLoopTarget(
DL, CLI, AllocaIP, LoopType, NoLoop);
6729 SchedKind, ChunkSize, HasSimdModifier, HasMonotonicModifier,
6730 HasNonmonotonicModifier, HasOrderedClause, DistScheduleChunkSize);
6732 bool IsOrdered = (EffectiveScheduleType & OMPScheduleType::ModifierOrdered) ==
6733 OMPScheduleType::ModifierOrdered;
6735 if (HasDistSchedule) {
6736 DistScheduleSchedType = DistScheduleChunkSize
6737 ? OMPScheduleType::OrderedDistributeChunked
6738 : OMPScheduleType::OrderedDistribute;
6740 switch (EffectiveScheduleType & ~OMPScheduleType::ModifierMask) {
6741 case OMPScheduleType::BaseStatic:
6742 case OMPScheduleType::BaseDistribute:
6743 assert((!ChunkSize || !DistScheduleChunkSize) &&
6744 "No chunk size with static-chunked schedule");
6745 if (IsOrdered && !HasDistSchedule)
6746 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6747 NeedsBarrier, ChunkSize);
6749 if (DistScheduleChunkSize)
6750 return applyStaticChunkedWorkshareLoop(
6751 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6752 DistScheduleChunkSize, DistScheduleSchedType);
6753 return applyStaticWorkshareLoop(
DL, CLI, AllocaIP, LoopType, NeedsBarrier,
6756 case OMPScheduleType::BaseStaticChunked:
6757 case OMPScheduleType::BaseDistributeChunked:
6758 if (IsOrdered && !HasDistSchedule)
6759 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6760 NeedsBarrier, ChunkSize);
6762 return applyStaticChunkedWorkshareLoop(
6763 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6764 DistScheduleChunkSize, DistScheduleSchedType);
6766 case OMPScheduleType::BaseRuntime:
6767 case OMPScheduleType::BaseAuto:
6768 case OMPScheduleType::BaseGreedy:
6769 case OMPScheduleType::BaseBalanced:
6770 case OMPScheduleType::BaseSteal:
6771 case OMPScheduleType::BaseRuntimeSimd:
6773 "schedule type does not support user-defined chunk sizes");
6775 case OMPScheduleType::BaseGuidedSimd:
6776 case OMPScheduleType::BaseDynamicChunked:
6777 case OMPScheduleType::BaseGuidedChunked:
6778 case OMPScheduleType::BaseGuidedIterativeChunked:
6779 case OMPScheduleType::BaseGuidedAnalyticalChunked:
6780 case OMPScheduleType::BaseStaticBalancedChunked:
6781 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6782 NeedsBarrier, ChunkSize);
6795 unsigned Bitwidth = Ty->getIntegerBitWidth();
6798 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_4u);
6801 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_8u);
6809static FunctionCallee
6811 unsigned Bitwidth = Ty->getIntegerBitWidth();
6814 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_4u);
6817 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_8u);
6824static FunctionCallee
6826 unsigned Bitwidth = Ty->getIntegerBitWidth();
6829 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_4u);
6832 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_8u);
6837OpenMPIRBuilder::applyDynamicWorkshareLoop(
DebugLoc DL, CanonicalLoopInfo *CLI,
6840 bool NeedsBarrier,
Value *Chunk) {
6841 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6843 "Require dedicated allocate IP");
6845 "Require valid schedule type");
6847 bool Ordered = (SchedType & OMPScheduleType::ModifierOrdered) ==
6848 OMPScheduleType::ModifierOrdered;
6853 uint32_t SrcLocStrSize;
6860 Type *IVTy =
IV->getType();
6865 Builder.SetInsertPoint(AllocaIP.getBlock()->getFirstNonPHIOrDbgOrAlloca());
6867 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6868 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
6869 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
6870 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
6879 Constant *One = ConstantInt::get(IVTy, 1);
6880 Builder.CreateStore(One, PLowerBound);
6882 Builder.CreateStore(UpperBound, PUpperBound);
6883 Builder.CreateStore(One, PStride);
6901 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6913 Builder.SetInsertPoint(OuterCond, OuterCond->getFirstInsertionPt());
6916 {SrcLoc, ThreadNum, PLastIter, PLowerBound, PUpperBound, PStride});
6917 Constant *Zero32 = ConstantInt::get(I32Type, 0);
6920 Builder.CreateSub(
Builder.CreateLoad(IVTy, PLowerBound), One,
"lb");
6921 Builder.CreateCondBr(MoreWork, Header, Exit);
6927 PI->setIncomingBlock(0, OuterCond);
6933 Br->setSuccessor(OuterCond);
6939 UpperBound =
Builder.CreateLoad(IVTy, PUpperBound,
"ub");
6942 CI->setOperand(1, UpperBound);
6946 assert(BI->getSuccessor(1) == Exit);
6947 BI->setSuccessor(1, OuterCond);
6961 omp::Directive::OMPD_for,
false,
6964 return BarrierIP.takeError();
7016 assert(
Loops.size() >= 1 &&
"At least one loop required");
7017 size_t NumLoops =
Loops.size();
7021 return Loops.front();
7033 Loop->collectControlBlocks(OldControlBBs);
7037 if (ComputeIP.
isSet())
7044 Value *CollapsedTripCount =
nullptr;
7047 "All loops to collapse must be valid canonical loops");
7048 Value *OrigTripCount = L->getTripCount();
7049 if (!CollapsedTripCount) {
7050 CollapsedTripCount = OrigTripCount;
7055 CollapsedTripCount =
7056 Builder.CreateNUWMul(CollapsedTripCount, OrigTripCount);
7062 OrigPreheader->
getNextNode(), OrigAfter,
"collapsed",
7069 Builder.restoreIP(Result->getBodyIP());
7071 Value *Leftover = Result->getIndVar();
7073 NewIndVars.
resize(NumLoops);
7074 for (
int i = NumLoops - 1; i >= 1; --i) {
7075 Value *OrigTripCount =
Loops[i]->getTripCount();
7077 Value *NewIndVar =
Builder.CreateURem(Leftover, OrigTripCount);
7078 NewIndVars[i] = NewIndVar;
7080 Leftover =
Builder.CreateUDiv(Leftover, OrigTripCount);
7083 NewIndVars[0] = Leftover;
7092 BasicBlock *ContinueBlock = Result->getBody();
7094 auto ContinueWith = [&ContinueBlock, &ContinuePred,
DL](
BasicBlock *Dest,
7101 ContinueBlock =
nullptr;
7102 ContinuePred = NextSrc;
7109 for (
size_t i = 0; i < NumLoops - 1; ++i)
7110 ContinueWith(
Loops[i]->getBody(),
Loops[i + 1]->getHeader());
7116 for (
size_t i = NumLoops - 1; i > 0; --i)
7117 ContinueWith(
Loops[i]->getAfter(),
Loops[i - 1]->getLatch());
7120 ContinueWith(Result->getLatch(),
nullptr);
7127 for (
size_t i = 0; i < NumLoops; ++i)
7128 Loops[i]->getIndVar()->replaceAllUsesWith(NewIndVars[i]);
7142std::vector<CanonicalLoopInfo *>
7146 "Must pass as many tile sizes as there are loops");
7147 int NumLoops =
Loops.size();
7148 assert(NumLoops >= 1 &&
"At least one loop to tile required");
7160 Loop->collectControlBlocks(OldControlBBs);
7168 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7169 OrigTripCounts.
push_back(L->getTripCount());
7180 for (
int i = 0; i < NumLoops - 1; ++i) {
7193 for (
int i = 0; i < NumLoops; ++i) {
7195 Value *OrigTripCount = OrigTripCounts[i];
7208 Value *FloorTripOverflow =
7209 Builder.CreateICmpNE(FloorTripRem, ConstantInt::get(IVType, 0));
7211 FloorTripOverflow =
Builder.CreateZExt(FloorTripOverflow, IVType);
7212 Value *FloorTripCount =
7213 Builder.CreateAdd(FloorCompleteTripCount, FloorTripOverflow,
7214 "omp_floor" +
Twine(i) +
".tripcount",
true);
7217 FloorCompleteCount.
push_back(FloorCompleteTripCount);
7223 std::vector<CanonicalLoopInfo *> Result;
7224 Result.reserve(NumLoops * 2);
7237 auto EmbeddNewLoop =
7238 [
this,
DL,
F, InnerEnter, &Enter, &
Continue, &OutroInsertBefore](
7241 DL, TripCount,
F, InnerEnter, OutroInsertBefore, Name);
7246 Enter = EmbeddedLoop->
getBody();
7248 OutroInsertBefore = EmbeddedLoop->
getLatch();
7249 return EmbeddedLoop;
7253 const Twine &NameBase) {
7256 EmbeddNewLoop(
P.value(), NameBase +
Twine(
P.index()));
7257 Result.push_back(EmbeddedLoop);
7261 EmbeddNewLoops(FloorCount,
"floor");
7267 for (
int i = 0; i < NumLoops; ++i) {
7271 Value *FloorIsEpilogue =
7273 Value *TileTripCount =
7280 EmbeddNewLoops(TileCounts,
"tile");
7285 for (std::pair<BasicBlock *, BasicBlock *>
P : InbetweenCode) {
7294 BodyEnter =
nullptr;
7295 BodyEntered = ExitBB;
7307 Builder.restoreIP(Result.back()->getBodyIP());
7308 for (
int i = 0; i < NumLoops; ++i) {
7311 Value *OrigIndVar = OrigIndVars[i];
7362 assert(
Loop->isValid() &&
"Expecting a valid CanonicalLoopInfo");
7366 assert(Latch &&
"A valid CanonicalLoopInfo must have a unique latch");
7374 if (
I.mayReadOrWriteMemory()) {
7378 I.setMetadata(LLVMContext::MD_access_group,
AccessGroup);
7392 Loop->collectControlBlocks(oldControlBBs);
7397 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7398 origTripCounts.
push_back(L->getTripCount());
7407 Builder.SetInsertPoint(TCBlock);
7408 Value *fusedTripCount =
nullptr;
7410 assert(L->isValid() &&
"All loops to fuse must be valid canonical loops");
7411 Value *origTripCount = L->getTripCount();
7412 if (!fusedTripCount) {
7413 fusedTripCount = origTripCount;
7416 Value *condTP =
Builder.CreateICmpSGT(fusedTripCount, origTripCount);
7417 fusedTripCount =
Builder.CreateSelect(condTP, fusedTripCount, origTripCount,
7431 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7432 Loops[i]->getPreheader()->moveBefore(TCBlock);
7433 Loops[i]->getAfter()->moveBefore(TCBlock);
7437 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7449 for (
size_t i = 0; i <
Loops.size(); ++i) {
7451 F->getContext(),
"omp.fused.inner.cond",
F,
Loops[i]->getBody());
7452 Builder.SetInsertPoint(condBlock);
7460 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7461 Builder.SetInsertPoint(condBBs[i]);
7462 Builder.CreateCondBr(condValues[i],
Loops[i]->getBody(), condBBs[i + 1]);
7478 "omp.fused.pre_latch");
7511 const Twine &NamePrefix) {
7540 C, NamePrefix +
".if.then",
Cond->getParent(),
Cond->getNextNode());
7542 C, NamePrefix +
".if.else",
Cond->getParent(), CanonicalLoop->
getExit());
7545 Builder.SetInsertPoint(SplitBeforeIt);
7547 Builder.CreateCondBr(IfCond, ThenBlock, ElseBlock);
7550 spliceBB(IP, ThenBlock,
false, Builder.getCurrentDebugLocation());
7553 Builder.SetInsertPoint(ElseBlock);
7559 ExistingBlocks.
reserve(L->getNumBlocks() + 1);
7561 ExistingBlocks.
append(L->block_begin(), L->block_end());
7567 assert(LoopCond && LoopHeader &&
"Invalid loop structure");
7569 if (
Block == L->getLoopPreheader() ||
Block == L->getLoopLatch() ||
7576 if (
Block == ThenBlock)
7577 NewBB->
setName(NamePrefix +
".if.else");
7580 VMap[
Block] = NewBB;
7588 L->getLoopLatch()->splitBasicBlockBefore(
L->getLoopLatch()->begin(),
7589 NamePrefix +
".pre_latch");
7593 L->addBasicBlockToLoop(ThenBlock, LI);
7599 if (TargetTriple.
isX86()) {
7600 if (Features.
lookup(
"avx512f"))
7602 else if (Features.
lookup(
"avx"))
7606 if (TargetTriple.
isPPC())
7608 if (TargetTriple.
isWasm())
7617 Value *IfCond, OrderKind Order,
7627 if (!BB.hasTerminator())
7643 I->eraseFromParent();
7646 if (AlignedVars.
size()) {
7648 for (
auto &AlignedItem : AlignedVars) {
7649 Value *AlignedPtr = AlignedItem.first;
7653 Builder.CreateAlignmentAssumption(
F->getDataLayout(), AlignedPtr,
7661 createIfVersion(CanonicalLoop, IfCond, VMap, LIA, LI, L,
"simd");
7674 Reachable.insert(
Block);
7684 if ((Safelen ==
nullptr) || (Order == OrderKind::OMP_ORDER_concurrent))
7700 if (Simdlen || Safelen) {
7704 ConstantInt *VectorizeWidth = Simdlen ==
nullptr ? Safelen : Simdlen;
7730static std::unique_ptr<TargetMachine>
7734 StringRef CPU =
F->getFnAttribute(
"target-cpu").getValueAsString();
7735 StringRef Features =
F->getFnAttribute(
"target-features").getValueAsString();
7746 std::nullopt, OptLevel));
7764 if (!BB.hasTerminator())
7777 [&](
const Function &
F) {
return TM->getTargetTransformInfo(
F); });
7778 FAM.registerPass([&]() {
return TIRA; });
7792 I->eraseFromParent();
7795 assert(L &&
"Expecting CanonicalLoopInfo to be recognized as a loop");
7800 nullptr, ORE,
static_cast<int>(OptLevel),
7820 <<
" Threshold=" << UP.
Threshold <<
"\n"
7823 <<
" PartialOptSizeThreshold="
7843 Ptr =
Load->getPointerOperand();
7845 Ptr =
Store->getPointerOperand();
7852 if (Alloca->getParent() == &
F->getEntryBlock())
7872 int MaxTripCount = 0;
7873 bool MaxOrZero =
false;
7874 unsigned TripMultiple = 0;
7878 MaxTripCount, MaxOrZero, TripMultiple, UCE, UP, PP);
7879 LLVM_DEBUG(
dbgs() <<
"Suggesting unroll factor of " << Factor <<
"\n");
7890 assert(Factor >= 0 &&
"Unroll factor must not be negative");
7906 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst}));
7919 *UnrolledCLI =
Loop;
7924 "unrolling only makes sense with a factor of 2 or larger");
7926 Type *IndVarTy =
Loop->getIndVarType();
7933 std::vector<CanonicalLoopInfo *>
LoopNest =
7948 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst})});
7951 (*UnrolledCLI)->assertOK();
7969 Value *Args[] = {Ident, ThreadId, BufSize, CpyBuf, CpyFn, DidItLD};
7988 if (!CPVars.
empty()) {
7993 Directive OMPD = Directive::OMPD_single;
7998 Value *Args[] = {Ident, ThreadId};
8007 if (
Error Err = FiniCB(IP))
8028 EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCBWrapper,
8035 for (
size_t I = 0, E = CPVars.
size();
I < E; ++
I)
8038 ConstantInt::get(Int64, 0), CPVars[
I],
8041 }
else if (!IsNowait) {
8044 omp::Directive::OMPD_unknown,
false,
8062 Directive::OMPD_scope,
nullptr,
nullptr,
8063 BodyGenCB, FiniCB,
false,
true,
8071 omp::Directive::OMPD_unknown,
8087 Directive OMPD = Directive::OMPD_critical;
8092 Value *LockVar = getOMPCriticalRegionLock(CriticalName);
8093 Value *Args[] = {Ident, ThreadId, LockVar};
8110 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
8118 const Twine &Name,
bool IsDependSource) {
8121 [](
Value *SV) {
return SV->getType()->isIntegerTy(64); }) &&
8122 "OpenMP runtime requires depend vec with i64 type");
8135 for (
unsigned I = 0;
I < NumLoops; ++
I) {
8149 Value *Args[] = {Ident, ThreadId, DependBaseAddrGEP};
8167 Directive OMPD = Directive::OMPD_ordered_blockassoc;
8176 Value *Args[] = {Ident, ThreadId};
8186 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
8193 bool HasFinalize,
bool IsCancellable) {
8200 BasicBlock *EntryBB = Builder.GetInsertBlock();
8209 emitCommonDirectiveEntry(OMPD, EntryCall, ExitBB, Conditional);
8221 "Unexpected control flow graph state!!");
8223 emitCommonDirectiveExit(OMPD, FinIP, ExitCall, HasFinalize);
8225 return AfterIP.takeError();
8230 "Unexpected Insertion point location!");
8233 auto InsertBB = merged ? ExitPredBB : ExitBB;
8236 Builder.SetInsertPoint(InsertBB);
8238 return Builder.saveIP();
8242 Directive OMPD,
Value *EntryCall, BasicBlock *ExitBB,
bool Conditional) {
8244 if (!Conditional || !EntryCall)
8250 auto *UI =
new UnreachableInst(
Builder.getContext(), ThenBB);
8260 Builder.CreateCondBr(CallBool, ThenBB, ExitBB);
8264 UI->eraseFromParent();
8272 omp::Directive OMPD,
InsertPointTy FinIP, Instruction *ExitCall,
8280 "Unexpected finalization stack state!");
8283 assert(Fi.DK == OMPD &&
"Unexpected Directive for Finalization call!");
8285 if (
Error Err = Fi.mergeFiniBB(
Builder, FinIP.getBlock()))
8286 return std::move(Err);
8290 Builder.SetInsertPoint(FinIP.getBlock()->getTerminator());
8300 return IRBuilder<>::InsertPoint(ExitCall->
getParent(),
8334 "copyin.not.master.end");
8341 Builder.SetInsertPoint(OMP_Entry);
8344 Value *cmp =
Builder.CreateICmpNE(MasterPtr, PrivatePtr);
8345 Builder.CreateCondBr(cmp, CopyBegin, CopyEnd);
8347 Builder.SetInsertPoint(CopyBegin);
8365 Value *Args[] = {ThreadId,
Size, Allocator};
8388 return Builder.CreateCall(Fn, Args, Name);
8402 Value *Args[] = {ThreadId, Addr, Allocator};
8409 const Twine &Name) {
8417 M.getContext(),
M.getDataLayout().getPrefTypeAlign(Int64)));
8423 const Twine &Name) {
8425 Loc,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)), Name);
8430 const Twine &Name) {
8436 return Builder.CreateCall(Fn, Args, Name);
8441 const Twine &Name) {
8443 Loc, Addr,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)),
8450 Value *DependenceAddress,
bool HaveNowaitClause) {
8460 else if (
Device->getType() != Int32)
8463 if (NumDependences ==
nullptr) {
8464 NumDependences = ConstantInt::get(Int32, 0);
8468 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8470 Ident, ThreadId, InteropVar, InteropTypeVal,
8471 Device, NumDependences, DependenceAddress, HaveNowaitClauseVal};
8480 Value *NumDependences,
Value *DependenceAddress,
bool HaveNowaitClause) {
8490 else if (
Device->getType() != Int32)
8492 if (NumDependences ==
nullptr) {
8493 NumDependences = ConstantInt::get(Int32, 0);
8497 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8499 Ident, ThreadId, InteropVar,
Device,
8500 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8509 Value *NumDependences,
8510 Value *DependenceAddress,
8511 bool HaveNowaitClause) {
8520 else if (
Device->getType() != Int32)
8522 if (NumDependences ==
nullptr) {
8523 NumDependences = ConstantInt::get(Int32, 0);
8527 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8529 Ident, ThreadId, InteropVar,
Device,
8530 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8560 assert(!Attrs.MaxThreads.empty() && !Attrs.MaxTeams.empty() &&
8561 "expected num_threads and num_teams to be specified");
8581 const std::string DebugPrefix =
"_debug__";
8582 if (KernelName.
ends_with(DebugPrefix)) {
8583 KernelName = KernelName.
drop_back(DebugPrefix.length());
8584 Kernel =
M.getFunction(KernelName);
8590 if (Attrs.MinTeams.front() > 1 || Attrs.MaxTeams.front() > 0)
8592 Attrs.MaxTeams.front());
8596 int32_t MaxThreadsVal = Attrs.MaxThreads.front();
8601 Attrs.MinThreads.front());
8603 MaxThreadsVal = Attrs.MinThreads.front();
8612 MaxThreadsVal = int32_t(
8613 std::min<int64_t>(int64_t(MaxThreadsVal) + 64,
8616 if (MaxThreadsVal > 0)
8629 omp::RuntimeFunction::OMPRTL___kmpc_target_init);
8632 Twine DynamicEnvironmentName = KernelName +
"_dynamic_environment";
8633 Constant *DynamicEnvironmentInitializer =
8637 DynamicEnvironmentInitializer, DynamicEnvironmentName,
8639 DL.getDefaultGlobalsAddressSpace());
8643 DynamicEnvironmentGV->
getType() == DynamicEnvironmentPtr
8644 ? DynamicEnvironmentGV
8646 DynamicEnvironmentPtr);
8649 ConfigurationEnvironment, {
8650 UseGenericStateMachineVal,
8651 MayUseNestedParallelismVal,
8660 KernelEnvironment, {
8661 ConfigurationEnvironmentInitializer,
8665 std::string KernelEnvironmentName =
8666 (KernelName +
"_kernel_environment").str();
8669 KernelEnvironmentInitializer, KernelEnvironmentName,
8671 DL.getDefaultGlobalsAddressSpace());
8675 KernelEnvironmentGV->
getType() == KernelEnvironmentPtr
8676 ? KernelEnvironmentGV
8678 KernelEnvironmentPtr);
8679 Value *KernelLaunchEnvironment =
8682 KernelLaunchEnvironment =
8683 KernelLaunchEnvironment->
getType() == KernelLaunchEnvParamTy
8684 ? KernelLaunchEnvironment
8685 :
Builder.CreateAddrSpaceCast(KernelLaunchEnvironment,
8686 KernelLaunchEnvParamTy);
8688 Fn, {KernelEnvironment, KernelLaunchEnvironment});
8700 auto *UI =
Builder.CreateUnreachable();
8706 Builder.SetInsertPoint(WorkerExitBB);
8710 Builder.SetInsertPoint(CheckBBTI);
8711 Builder.CreateCondBr(ExecUserCode, UI->getParent(), WorkerExitBB);
8713 CheckBBTI->eraseFromParent();
8714 UI->eraseFromParent();
8722 int32_t TeamsReductionDataSize) {
8727 omp::RuntimeFunction::OMPRTL___kmpc_target_deinit);
8731 if (!TeamsReductionDataSize)
8737 const std::string DebugPrefix =
"_debug__";
8739 KernelName = KernelName.
drop_back(DebugPrefix.length());
8740 auto *KernelEnvironmentGV =
8741 M.getNamedGlobal((KernelName +
"_kernel_environment").str());
8742 assert(KernelEnvironmentGV &&
"Expected kernel environment global\n");
8743 auto *KernelEnvironmentInitializer = KernelEnvironmentGV->getInitializer();
8745 KernelEnvironmentInitializer,
8746 ConstantInt::get(Int32, TeamsReductionDataSize), {0, 7});
8747 KernelEnvironmentGV->setInitializer(NewInitializer);
8752 if (
Kernel.hasFnAttribute(Name)) {
8753 int32_t OldLimit =
Kernel.getFnAttributeAsParsedInteger(Name);
8759std::pair<int32_t, int32_t>
8761 int32_t ThreadLimit =
8762 Kernel.getFnAttributeAsParsedInteger(
"omp_target_thread_limit");
8765 const auto &Attr =
Kernel.getFnAttribute(
"amdgpu-flat-work-group-size");
8766 if (!Attr.isValid() || !Attr.isStringAttribute())
8767 return {0, ThreadLimit};
8768 auto [LBStr, UBStr] = Attr.getValueAsString().split(
',');
8771 return {0, ThreadLimit};
8772 UB = ThreadLimit ? std::min(ThreadLimit, UB) : UB;
8780 return {0, ThreadLimit ? std::min(ThreadLimit, UB) : UB};
8782 return {0, ThreadLimit};
8788 Kernel.addFnAttr(
"omp_target_thread_limit", std::to_string(UB));
8791 Kernel.addFnAttr(
"amdgpu-flat-work-group-size",
8799std::pair<int32_t, int32_t>
8802 return {0,
Kernel.getFnAttributeAsParsedInteger(
"omp_target_num_teams")};
8806 int32_t LB, int32_t UB) {
8814 Kernel.addFnAttr(
"omp_target_num_teams", std::to_string(LB));
8817void OpenMPIRBuilder::setOutlinedTargetRegionFunctionAttributes(
8826 else if (
T.isNVPTX())
8828 else if (
T.isSPIRV())
8834 StringRef EntryFnIDName) {
8835 if (
Config.isTargetDevice()) {
8836 assert(OutlinedFn &&
"The outlined function must exist if embedded");
8840 return new GlobalVariable(
8845Constant *OpenMPIRBuilder::createTargetRegionEntryAddr(
Function *OutlinedFn,
8846 StringRef EntryFnName) {
8850 assert(!
M.getGlobalVariable(EntryFnName,
true) &&
8851 "Named kernel already exists?");
8852 return new GlobalVariable(
8865 if (
Config.isTargetDevice() || !
Config.openMPOffloadMandatory()) {
8869 OutlinedFn = *CBResult;
8871 OutlinedFn =
nullptr;
8877 if (!IsOffloadEntry)
8880 std::string EntryFnIDName =
8882 ? std::string(EntryFnName)
8886 EntryFnName, EntryFnIDName);
8894 setOutlinedTargetRegionFunctionAttributes(OutlinedFn);
8895 auto OutlinedFnID = createOutlinedFunctionID(OutlinedFn, EntryFnIDName);
8896 auto EntryAddr = createTargetRegionEntryAddr(OutlinedFn, EntryFnName);
8898 EntryInfo, EntryAddr, OutlinedFnID,
8900 return OutlinedFnID;
8918 bool IsStandAlone = !BodyGenCB;
8925 MapInfo = &GenMapInfoCB(
Builder.saveIP());
8927 AllocaIP,
Builder.saveIP(), *MapInfo, Info, CustomMapperCB,
8928 true, DeviceAddrCB))
8935 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
8945 SrcLocInfo, DeviceID,
8952 assert(MapperFunc &&
"MapperFunc missing for standalone target data");
8956 if (Info.HasNoWait) {
8966 if (Info.HasNoWait) {
8970 emitBlock(OffloadContBlock, CurFn,
true);
8976 bool RequiresOuterTargetTask = Info.HasNoWait;
8977 if (!RequiresOuterTargetTask)
8978 cantFail(TaskBodyCB(
nullptr,
nullptr,
8982 {}, RTArgs, Info.HasNoWait));
8985 omp::OMPRTL___tgt_target_data_begin_mapper);
8989 for (
auto DeviceMap : Info.DevicePtrInfoMap) {
8993 Builder.CreateStore(LI, DeviceMap.second.second);
9030 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
9039 Value *OffloadingArgs[] = {SrcLocInfo, DeviceID,
9062 return emitIfClause(IfCond, BeginThenGen, BeginElseGen, AllocaIP);
9063 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9078 return emitIfClause(IfCond, EndThenGen, EndElseGen, AllocaIP);
9079 return EndThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9082 return emitIfClause(IfCond, BeginThenGen, EndElseGen, AllocaIP);
9083 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9094 bool IsGPUDistribute) {
9095 assert((IVSize == 32 || IVSize == 64) &&
9096 "IV size is not compatible with the omp runtime");
9098 if (IsGPUDistribute)
9100 ? (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_4
9101 : omp::OMPRTL___kmpc_distribute_static_init_4u)
9102 : (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_8
9103 : omp::OMPRTL___kmpc_distribute_static_init_8u);
9105 Name = IVSize == 32 ? (IVSigned ? omp::OMPRTL___kmpc_for_static_init_4
9106 : omp::OMPRTL___kmpc_for_static_init_4u)
9107 : (IVSigned ? omp::OMPRTL___kmpc_for_static_init_8
9108 : omp::OMPRTL___kmpc_for_static_init_8u);
9115 assert((IVSize == 32 || IVSize == 64) &&
9116 "IV size is not compatible with the omp runtime");
9118 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_4
9119 : omp::OMPRTL___kmpc_dispatch_init_4u)
9120 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_8
9121 : omp::OMPRTL___kmpc_dispatch_init_8u);
9128 assert((IVSize == 32 || IVSize == 64) &&
9129 "IV size is not compatible with the omp runtime");
9131 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_4
9132 : omp::OMPRTL___kmpc_dispatch_next_4u)
9133 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_8
9134 : omp::OMPRTL___kmpc_dispatch_next_8u);
9141 assert((IVSize == 32 || IVSize == 64) &&
9142 "IV size is not compatible with the omp runtime");
9144 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_4
9145 : omp::OMPRTL___kmpc_dispatch_fini_4u)
9146 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_8
9147 : omp::OMPRTL___kmpc_dispatch_fini_8u);
9158 DenseMap<
Value *, std::tuple<Value *, unsigned>> &ValueReplacementMap) {
9166 auto GetUpdatedDIVariable = [&](
DILocalVariable *OldVar,
unsigned arg) {
9170 if (NewVar && (arg == NewVar->
getArg()))
9180 auto UpdateDebugRecord = [&](
auto *DR) {
9183 for (
auto Loc : DR->location_ops()) {
9184 auto Iter = ValueReplacementMap.find(
Loc);
9185 if (Iter != ValueReplacementMap.end()) {
9186 DR->replaceVariableLocationOp(
Loc, std::get<0>(Iter->second));
9187 ArgNo = std::get<1>(Iter->second) + 1;
9191 DR->setVariable(GetUpdatedDIVariable(OldVar, ArgNo));
9196 if (DVR->getNumVariableLocationOps() != 1u) {
9197 DVR->setKillLocation();
9200 Value *
Loc = DVR->getVariableLocationOp(0u);
9207 RequiredBB = &DVR->getFunction()->getEntryBlock();
9209 if (RequiredBB && RequiredBB != CurBB) {
9221 "Unexpected debug intrinsic");
9223 UpdateDebugRecord(&DVR);
9224 MoveDebugRecordToCorrectBlock(&DVR);
9227 for (
auto *DVR : DVRsToDelete)
9228 DVR->getMarker()->MarkedInstr->dropOneDbgRecord(DVR);
9232 Module *M = Func->getParent();
9235 DB.createQualifiedType(dwarf::DW_TAG_pointer_type,
nullptr);
9236 unsigned ArgNo = Func->arg_size();
9238 NewSP,
"dyn_ptr", ArgNo, NewSP->
getFile(), 0, VoidPtrTy,
9239 false, DINode::DIFlags::FlagArtificial);
9241 Argument *LastArg = Func->getArg(Func->arg_size() - 1);
9242 DB.insertDeclare(LastArg, Var, DB.createExpression(),
Loc,
9264 for (
auto &Arg : Inputs)
9265 ParameterTypes.
push_back(Arg->getType()->isPointerTy()
9269 for (
auto &Arg : Inputs)
9270 ParameterTypes.
push_back(Arg->getType());
9278 auto BB = Builder.GetInsertBlock();
9279 auto M = BB->getModule();
9290 if (TargetCpuAttr.isStringAttribute())
9291 Func->addFnAttr(TargetCpuAttr);
9293 auto TargetFeaturesAttr = ParentFn->
getFnAttribute(
"target-features");
9294 if (TargetFeaturesAttr.isStringAttribute())
9295 Func->addFnAttr(TargetFeaturesAttr);
9300 OMPBuilder.
emitUsed(
"llvm.compiler.used", {ExecMode});
9310 Builder.SetCurrentDebugLocation(OutlinedFnLoc);
9314 Builder.SetInsertPoint(EntryBB);
9320 BasicBlock *UserCodeEntryBB = Builder.GetInsertBlock();
9330 splitBB(Builder,
true,
"outlined.body");
9337 Builder.SetInsertPoint(ExitBB);
9345 Builder.SetCurrentDebugLocation(OutlinedFnLoc);
9352 Builder.CreateRetVoid();
9356 auto AllocaIP = Builder.saveIP();
9361 const auto &ArgRange =
make_range(Func->arg_begin(), Func->arg_end() - 1);
9393 if (Instr->getFunction() == Func)
9394 Instr->replaceUsesOfWith(
Input, InputCopy);
9400 for (
auto InArg :
zip(Inputs, ArgRange)) {
9402 Argument &Arg = std::get<1>(InArg);
9403 Value *InputCopy =
nullptr;
9406 Arg,
Input, InputCopy, AllocaIP, Builder.saveIP(),
9410 Builder.restoreIP(*AfterIP);
9411 ValueReplacementMap[
Input] = std::make_tuple(InputCopy, Arg.
getArgNo());
9431 DeferredReplacement.push_back(std::make_pair(
Input, InputCopy));
9438 ReplaceValue(
Input, InputCopy, Func);
9442 for (
auto Deferred : DeferredReplacement)
9443 ReplaceValue(std::get<0>(Deferred), std::get<1>(Deferred), Func);
9446 ValueReplacementMap);
9454 Value *TaskWithPrivates,
9455 Type *TaskWithPrivatesTy) {
9457 Type *TaskTy = OMPIRBuilder.Task;
9460 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 0);
9461 Value *Shareds = TaskT;
9471 if (TaskWithPrivatesTy != TaskTy)
9472 Shareds = Builder.CreateStructGEP(TaskTy, TaskT, 0);
9489 const size_t NumOffloadingArrays,
const int SharedArgsOperandNo) {
9494 assert((!NumOffloadingArrays || PrivatesTy) &&
9495 "PrivatesTy cannot be nullptr when there are offloadingArrays"
9528 Type *TaskPtrTy = OMPBuilder.TaskPtr;
9529 [[maybe_unused]]
Type *TaskTy = OMPBuilder.Task;
9535 ".omp_target_task_proxy_func", M);
9536 Value *ThreadId = ProxyFn->getArg(0);
9537 Value *TaskWithPrivates = ProxyFn->getArg(1);
9538 ThreadId->
setName(
"thread.id");
9539 TaskWithPrivates->
setName(
"task");
9541 bool HasShareds = SharedArgsOperandNo > 0;
9542 bool HasOffloadingArrays = NumOffloadingArrays > 0;
9546 Builder.SetInsertPoint(EntryBB);
9553 if (HasOffloadingArrays) {
9554 assert(TaskTy != TaskWithPrivatesTy &&
9555 "If there are offloading arrays to pass to the target"
9556 "TaskTy cannot be the same as TaskWithPrivatesTy");
9559 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 1);
9560 for (
unsigned int i = 0; i < NumOffloadingArrays; ++i)
9562 Builder.CreateStructGEP(PrivatesTy, Privates, i));
9566 auto *ArgStructAlloca =
9568 assert(ArgStructAlloca &&
9569 "Unable to find the alloca instruction corresponding to arguments "
9570 "for extracted function");
9572 std::optional<TypeSize> ArgAllocSize =
9574 assert(ArgStructType && ArgAllocSize &&
9575 "Unable to determine size of arguments for extracted function");
9576 uint64_t StructSize = ArgAllocSize->getFixedValue();
9579 Builder.CreateAlloca(ArgStructType,
nullptr,
"structArg");
9581 Value *SharedsSize = Builder.getInt64(StructSize);
9584 OMPBuilder, Builder, TaskWithPrivates, TaskWithPrivatesTy);
9586 Builder.CreateMemCpy(
9587 NewArgStructAlloca, NewArgStructAlloca->
getAlign(), LoadShared,
9589 KernelLaunchArgs.
push_back(NewArgStructAlloca);
9592 Builder.CreateRetVoid();
9598 return GEP->getSourceElementType();
9600 return Alloca->getAllocatedType();
9623 if (OffloadingArraysToPrivatize.
empty())
9624 return OMPIRBuilder.Task;
9627 for (
Value *V : OffloadingArraysToPrivatize) {
9628 assert(V->getType()->isPointerTy() &&
9629 "Expected pointer to array to privatize. Got a non-pointer value "
9632 assert(ArrayTy &&
"ArrayType cannot be nullptr");
9638 "struct.task_with_privates");
9653 EntryFnName, Inputs, CBFunc,
9654 ArgAccessorFuncCB, OutlinedFnLoc);
9658 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
9795 TargetTaskAllocaBB->
begin());
9798 auto OI = std::make_unique<OutlineInfo>();
9799 OI->EntryBB = TargetTaskAllocaBB;
9800 OI->OuterAllocBB = AllocaIP.
getBlock();
9805 Builder, AllocaIP, ToBeDeleted, TargetTaskAllocaIP,
"global.tid",
false));
9808 Builder.restoreIP(TargetTaskBodyIP);
9809 if (
Error Err = TaskBodyCB(DeviceID, RTLoc, TargetTaskAllocaIP))
9827 bool NeedsTargetTask = HasNoWait && DeviceID;
9828 if (NeedsTargetTask) {
9834 OffloadingArraysToPrivatize.
push_back(V);
9835 OI->ExcludeArgsFromAggregate.push_back(V);
9839 OI->PostOutlineCB = [
this, ToBeDeleted, Dependencies, NeedsTargetTask,
9840 DeviceID, OffloadingArraysToPrivatize](
9843 "there must be a single user for the outlined function");
9857 const unsigned int NumStaleCIArgs = StaleCI->
arg_size();
9858 bool HasShareds = NumStaleCIArgs > OffloadingArraysToPrivatize.
size() + 1;
9860 NumStaleCIArgs == (OffloadingArraysToPrivatize.
size() + 2)) &&
9861 "Wrong number of arguments for StaleCI when shareds are present");
9862 int SharedArgOperandNo =
9863 HasShareds ? OffloadingArraysToPrivatize.
size() + 1 : 0;
9869 if (!OffloadingArraysToPrivatize.
empty())
9874 *
this,
Builder, StaleCI, PrivatesTy, TaskWithPrivatesTy,
9875 OffloadingArraysToPrivatize.
size(), SharedArgOperandNo);
9877 LLVM_DEBUG(
dbgs() <<
"Proxy task entry function created: " << *ProxyFn
9880 Builder.SetInsertPoint(StaleCI);
9897 OMPRTL___kmpc_omp_target_task_alloc);
9909 M.getDataLayout().getTypeStoreSize(TaskWithPrivatesTy));
9916 auto *ArgStructAlloca =
9918 assert(ArgStructAlloca &&
9919 "Unable to find the alloca instruction corresponding to arguments "
9920 "for extracted function");
9921 std::optional<TypeSize> ArgAllocSize =
9924 "Unable to determine size of arguments for extracted function");
9925 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
9944 TaskSize, SharedsSize,
9947 if (NeedsTargetTask) {
9948 assert(DeviceID &&
"Expected non-empty device ID.");
9958 *
this,
Builder, TaskData, TaskWithPrivatesTy);
9962 if (!OffloadingArraysToPrivatize.
empty()) {
9964 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskData, 1);
9965 for (
unsigned int i = 0; i < OffloadingArraysToPrivatize.
size(); ++i) {
9966 Value *PtrToPrivatize = OffloadingArraysToPrivatize[i];
9973 "ElementType should match ArrayType");
9976 Value *Dst =
Builder.CreateStructGEP(PrivatesTy, Privates, i);
9979 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(ElementType)));
9983 Value *DepArray =
nullptr;
9984 Value *NumDeps =
nullptr;
9987 NumDeps = Dependencies.
NumDeps;
9988 }
else if (!Dependencies.
Deps.empty()) {
9990 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
10001 if (!NeedsTargetTask) {
10010 ConstantInt::get(
Builder.getInt32Ty(), 0),
10023 }
else if (DepArray) {
10031 {Ident, ThreadID, TaskData, NumDeps, DepArray,
10032 ConstantInt::get(
Builder.getInt32Ty(), 0),
10040 Builder.ClearInsertionPoint();
10043 I->eraseFromParent();
10048 << *(
Builder.GetInsertBlock()) <<
"\n");
10050 << *(
Builder.GetInsertBlock()->getParent()->getParent())
10062 CustomMapperCB, IsNonContiguous, DeviceAddrCB))
10085 Builder.restoreIP(IP);
10091 return Builder.saveIP();
10094 bool HasDependencies = !Dependencies.
empty();
10095 bool RequiresOuterTargetTask = HasNoWait || HasDependencies;
10112 if (OutlinedFnID && DeviceID)
10114 EmitTargetCallFallbackCB, KArgs,
10115 DeviceID, RTLoc, TargetTaskAllocaIP);
10123 return EmitTargetCallFallbackCB(OMPBuilder.
Builder.
saveIP());
10130 auto &&EmitTargetCallElse =
10137 if (RequiresOuterTargetTask) {
10144 Dependencies, EmptyRTArgs, HasNoWait);
10146 return EmitTargetCallFallbackCB(Builder.saveIP());
10149 Builder.restoreIP(AfterIP);
10153 auto &&EmitTargetCallThen =
10157 Info.HasNoWait = HasNoWait;
10162 AllocaIP, Builder.saveIP(), Info, RTArgs, MapInfo, CustomMapperCB,
10168 for (
auto [DefaultVal, RuntimeVal] :
10170 NumTeamsC.
push_back(RuntimeVal ? RuntimeVal
10171 : Builder.getInt32(DefaultVal));
10175 auto InitMaxThreadsClause = [&Builder](
Value *
Clause) {
10177 Clause = Builder.CreateIntCast(
Clause, Builder.getInt32Ty(),
10181 auto CombineMaxThreadsClauses = [&Builder](
Value *
Clause,
Value *&Result) {
10184 Result ? Builder.CreateSelect(Builder.CreateICmpULT(Result,
Clause),
10192 Value *MaxThreadsClause =
10194 ? InitMaxThreadsClause(RuntimeAttrs.
MaxThreads.front())
10197 for (
auto [TeamsVal, TargetVal] :
zip_equal(
10199 Value *TeamsThreadLimitClause = InitMaxThreadsClause(TeamsVal);
10200 Value *NumThreads = InitMaxThreadsClause(TargetVal);
10202 CombineMaxThreadsClauses(TeamsThreadLimitClause, NumThreads);
10203 CombineMaxThreadsClauses(MaxThreadsClause, NumThreads);
10205 NumThreadsC.
push_back(NumThreads ? NumThreads : Builder.getInt32(0));
10208 unsigned NumTargetItems = Info.NumberOfPtrs;
10216 Builder.getInt64Ty(),
10218 : Builder.getInt64(0);
10222 DynCGroupMem = Builder.getInt32(0);
10225 NumTargetItems, RTArgs, TripCount, NumTeamsC, NumThreadsC, DynCGroupMem,
10226 HasNoWait,
false,
false,
10227 DynCGroupMemFallback);
10234 if (RequiresOuterTargetTask)
10236 RTLoc, AllocaIP, Dependencies,
10237 KArgs.
RTArgs, Info.HasNoWait);
10240 Builder, OutlinedFnID, EmitTargetCallFallbackCB, KArgs,
10241 RuntimeAttrs.
DeviceID, RTLoc, AllocaIP);
10244 Builder.restoreIP(AfterIP);
10251 if (!OutlinedFnID) {
10252 cantFail(EmitTargetCallElse(AllocaIP, Builder.saveIP(), DeallocBlocks));
10258 cantFail(EmitTargetCallThen(AllocaIP, Builder.saveIP(), DeallocBlocks));
10263 EmitTargetCallElse, AllocaIP));
10276 bool HasNowait,
Value *DynCGroupMem,
10283 Builder.restoreIP(CodeGenIP);
10291 *
this,
Builder, IsOffloadEntry, EntryInfo, DefaultAttrs, OutlinedFn,
10292 OutlinedFnID, Inputs, CBFunc, ArgAccessorFuncCB, OutlinedFnLoc))
10298 if (!
Config.isTargetDevice())
10300 RuntimeAttrs, IfCond, OutlinedFn, OutlinedFnID, Inputs,
10301 GenMapInfoCB, CustomMapperCB, Dependencies, HasNowait,
10302 DynCGroupMem, DynCGroupMemFallback);
10316 return OS.
str().str();
10321 return OpenMPIRBuilder::getNameWithSeparators(Parts,
Config.firstSeparator(),
10327 auto &Elem = *
InternalVars.try_emplace(Name,
nullptr).first;
10329 assert(Elem.second->getValueType() == Ty &&
10330 "OMP internal variable has different type than requested");
10343 :
M.getTargetTriple().isAMDGPU()
10345 :
DL.getDefaultGlobalsAddressSpace();
10346 auto Linkage = this->
M.getTargetTriple().isWasm()
10354 const llvm::Align PtrAlign =
DL.getPointerABIAlignment(AddressSpaceVal);
10355 GV->setAlignment(std::max(TypeAlign, PtrAlign));
10359 return Elem.second;
10362Value *OpenMPIRBuilder::getOMPCriticalRegionLock(
StringRef CriticalName) {
10363 std::string Prefix =
Twine(
"gomp_critical_user_", CriticalName).
str();
10364 std::string Name = getNameWithSeparators({Prefix,
"var"},
".",
".");
10375 return SizePtrToInt;
10380 std::string VarName) {
10388 return MaptypesArrayGlobal;
10393 unsigned NumOperands,
10402 ArrI8PtrTy,
nullptr,
".offload_baseptrs");
10406 ArrI64Ty,
nullptr,
".offload_sizes");
10417 int64_t DeviceID,
unsigned NumOperands) {
10423 Value *ArgsBaseGEP =
10425 {Builder.getInt32(0), Builder.getInt32(0)});
10428 {Builder.getInt32(0), Builder.getInt32(0)});
10429 Value *ArgSizesGEP =
10431 {Builder.getInt32(0), Builder.getInt32(0)});
10435 Builder.getInt32(NumOperands),
10436 ArgsBaseGEP, ArgsGEP, ArgSizesGEP,
10437 MaptypesArg, MapnamesArg, NullPtr});
10444 assert((!ForEndCall || Info.separateBeginEndCalls()) &&
10445 "expected region end call to runtime only when end call is separate");
10447 auto VoidPtrTy = UnqualPtrTy;
10448 auto VoidPtrPtrTy = UnqualPtrTy;
10450 auto Int64PtrTy = UnqualPtrTy;
10452 if (!Info.NumberOfPtrs) {
10464 Info.RTArgs.BasePointersArray,
10467 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray,
10471 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
10475 ForEndCall && Info.RTArgs.MapTypesArrayEnd ? Info.RTArgs.MapTypesArrayEnd
10476 : Info.RTArgs.MapTypesArray,
10482 if (!Info.EmitDebug)
10486 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.MapNamesArray,
10491 if (!Info.HasMapper)
10495 Builder.CreatePointerCast(Info.RTArgs.MappersArray, VoidPtrPtrTy);
10516 "struct.descriptor_dim");
10518 enum { OffsetFD = 0, CountFD, StrideFD };
10522 for (
unsigned I = 0, L = 0, E = NonContigInfo.
Dims.
size();
I < E; ++
I) {
10525 if (NonContigInfo.
Dims[
I] == 1)
10530 Builder.CreateAlloca(ArrayTy,
nullptr,
"dims");
10531 Builder.restoreIP(CodeGenIP);
10532 for (
unsigned II = 0, EE = NonContigInfo.
Dims[
I];
II < EE; ++
II) {
10533 unsigned RevIdx = EE -
II - 1;
10537 Value *OffsetLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, OffsetFD);
10539 NonContigInfo.
Offsets[L][RevIdx], OffsetLVal,
10540 M.getDataLayout().getPrefTypeAlign(OffsetLVal->
getType()));
10542 Value *CountLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, CountFD);
10544 NonContigInfo.
Counts[L][RevIdx], CountLVal,
10545 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10547 Value *StrideLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, StrideFD);
10549 NonContigInfo.
Strides[L][RevIdx], StrideLVal,
10550 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10553 Builder.restoreIP(CodeGenIP);
10554 Value *DAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
10555 DimsAddr,
Builder.getPtrTy());
10558 Info.RTArgs.PointersArray, 0,
I);
10560 DAddr,
P,
M.getDataLayout().getPrefTypeAlign(
Builder.getPtrTy()));
10565void OpenMPIRBuilder::emitUDMapperArrayInitOrDel(
10569 StringRef Prefix = IsInit ?
".init" :
".del";
10575 Builder.CreateICmpSGT(
Size, Builder.getInt64(1),
"omp.arrayinit.isarray");
10576 Value *DeleteBit = Builder.CreateAnd(
10579 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10580 OpenMPOffloadMappingFlags::OMP_MAP_DELETE)));
10585 Value *BaseIsBegin = Builder.CreateICmpNE(
Base, Begin);
10586 Cond = Builder.CreateOr(IsArray, BaseIsBegin);
10587 DeleteCond = Builder.CreateIsNull(
10592 DeleteCond =
Builder.CreateIsNotNull(
10608 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10609 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10610 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10611 MapTypeArg =
Builder.CreateOr(
10614 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10615 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT)));
10619 Value *OffloadingArgs[] = {MapperHandle,
Base, Begin,
10620 ArraySize, MapTypeArg, MapName};
10631 bool PreserveMemberOfFlags,
bool PropagatePresentToPointee) {
10647 MapperFn->
addFnAttr(Attribute::NoInline);
10648 MapperFn->
addFnAttr(Attribute::NoUnwind);
10659 Builder.SetInsertPoint(EntryBB);
10674 Value *PtrBegin = BeginIn;
10680 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
10681 MapType, MapName, ElementSize, HeadBB,
10692 Builder.CreateICmpEQ(PtrBegin, PtrEnd,
"omp.arraymap.isempty");
10693 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
10699 Builder.CreatePHI(PtrBegin->
getType(), 2,
"omp.arraymap.ptrcurrent");
10700 PtrPHI->addIncoming(PtrBegin, HeadBB);
10705 return Info.takeError();
10709 Value *OffloadingArgs[] = {MapperHandle};
10713 Value *ShiftedPreviousSize =
10717 for (
unsigned I = 0;
I < Info->BasePointers.size(); ++
I) {
10718 Value *CurBaseArg = Info->BasePointers[
I];
10719 Value *CurBeginArg = Info->Pointers[
I];
10720 Value *CurSizeArg = Info->Sizes[
I];
10721 Value *CurNameArg = Info->Names.size()
10726 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10729 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10731 constexpr uint64_t MemberOfMask =
10732 static_cast<uint64_t
>(OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
10733 constexpr uint64_t AttachBit =
10734 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10735 OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
10793 Value *MemberMapType;
10794 if (PreserveMemberOfFlags || (RawType & AttachBit) ||
10795 Info->HasAttachPtr[
I]) {
10796 if (RawType & MemberOfMask)
10797 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
10799 MemberMapType = OriMapType;
10801 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
10819 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10820 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10821 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10831 Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
10837 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10838 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10839 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10845 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10846 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
10847 Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
10853 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10854 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10860 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10861 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10862 Builder.CreateCondBr(IsFrom, FromBB, EndBB);
10868 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10869 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
10878 CurMapType->
addIncoming(MemberMapType, ToElseBB);
10915 uint64_t ModifierBits =
10916 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10917 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
10918 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
10919 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
10920 if (PropagatePresentToPointee && Info->HasAttachPtr[
I])
10922 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10923 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
10924 Value *ImportedModifierBits =
10927 CurMapType, ImportedModifierBits,
"omp.maptype.with.modifiers");
10932 Value *FinalMapType =
10933 (RawType & AttachBit) ? CurMapType : CurMapTypeWithModifiers;
10935 Value *OffloadingArgs[] = {MapperHandle, CurBaseArg, CurBeginArg,
10936 CurSizeArg, FinalMapType, CurNameArg};
10938 auto ChildMapperFn = CustomMapperCB(
I);
10939 if (!ChildMapperFn)
10940 return ChildMapperFn.takeError();
10941 if (*ChildMapperFn) {
10957 "omp.arraymap.next");
10958 PtrPHI->addIncoming(PtrNext, LastBB);
10959 Value *IsDone =
Builder.CreateICmpEQ(PtrNext, PtrEnd,
"omp.arraymap.isdone");
10961 Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
10966 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
10967 MapType, MapName, ElementSize, DoneBB,
10980 bool IsNonContiguous,
10984 Info.clearArrayInfo();
10987 if (Info.NumberOfPtrs == 0)
10996 Info.RTArgs.BasePointersArray =
Builder.CreateAlloca(
10997 PointerArrayType,
nullptr,
".offload_baseptrs");
10999 Info.RTArgs.PointersArray =
Builder.CreateAlloca(
11000 PointerArrayType,
nullptr,
".offload_ptrs");
11002 PointerArrayType,
nullptr,
".offload_mappers");
11003 Info.RTArgs.MappersArray = MappersArray;
11010 ConstantInt::get(Int64Ty, 0));
11012 for (
unsigned I = 0, E = CombinedInfo.
Sizes.
size();
I < E; ++
I) {
11013 bool IsNonContigEntry =
11015 (
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11017 OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG) != 0);
11020 if (IsNonContigEntry) {
11022 "Index must be in-bounds for NON_CONTIG Dims array");
11024 assert(DimCount > 0 &&
"NON_CONTIG DimCount must be > 0");
11025 ConstSizes[
I] = ConstantInt::get(Int64Ty, DimCount);
11030 ConstSizes[
I] = CI;
11034 RuntimeSizes.
set(
I);
11037 if (RuntimeSizes.
all()) {
11039 Info.RTArgs.SizesArray =
Builder.CreateAlloca(
11040 SizeArrayType,
nullptr,
".offload_sizes");
11046 auto *SizesArrayGbl =
11051 if (!RuntimeSizes.
any()) {
11052 Info.RTArgs.SizesArray = SizesArrayGbl;
11054 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
11055 Align OffloadSizeAlign =
M.getDataLayout().getABIIntegerTypeAlignment(64);
11058 SizeArrayType,
nullptr,
".offload_sizes");
11062 Buffer,
M.getDataLayout().getPrefTypeAlign(Buffer->
getType()),
11063 SizesArrayGbl, OffloadSizeAlign,
11068 Info.RTArgs.SizesArray = Buffer;
11076 for (
auto mapFlag : CombinedInfo.
Types)
11078 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11082 Info.RTArgs.MapTypesArray = MapTypesArrayGbl;
11088 Info.RTArgs.MapNamesArray = MapNamesArrayGbl;
11089 Info.EmitDebug =
true;
11091 Info.RTArgs.MapNamesArray =
11093 Info.EmitDebug =
false;
11098 if (Info.separateBeginEndCalls()) {
11099 bool EndMapTypesDiffer =
false;
11100 for (uint64_t &
Type : Mapping) {
11101 if (
Type &
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11102 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT)) {
11103 Type &= ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
11104 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
11105 EndMapTypesDiffer =
true;
11108 if (EndMapTypesDiffer) {
11110 Info.RTArgs.MapTypesArrayEnd = MapTypesArrayGbl;
11115 for (
unsigned I = 0;
I < Info.NumberOfPtrs; ++
I) {
11118 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.BasePointersArray,
11120 Builder.CreateAlignedStore(BPVal, BP,
11121 M.getDataLayout().getPrefTypeAlign(PtrTy));
11123 if (Info.requiresDevicePointerInfo()) {
11125 CodeGenIP =
Builder.saveIP();
11127 Info.DevicePtrInfoMap[BPVal] = {BP,
Builder.CreateAlloca(PtrTy)};
11130 DeviceAddrCB(
I, Info.DevicePtrInfoMap[BPVal].second);
11132 Info.DevicePtrInfoMap[BPVal] = {BP, BP};
11134 DeviceAddrCB(
I, BP);
11140 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray, 0,
11143 Builder.CreateAlignedStore(PVal,
P,
11144 M.getDataLayout().getPrefTypeAlign(PtrTy));
11146 if (RuntimeSizes.
test(
I)) {
11148 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
11154 S,
M.getDataLayout().getPrefTypeAlign(PtrTy));
11157 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
11160 auto CustomMFunc = CustomMapperCB(
I);
11162 return CustomMFunc.takeError();
11164 MFunc =
Builder.CreatePointerCast(*CustomMFunc, PtrTy);
11167 PointerArrayType, MappersArray,
11170 MFunc, MAddr,
M.getDataLayout().getPrefTypeAlign(MAddr->
getType()));
11174 Info.NumberOfPtrs == 0)
11191 Builder.ClearInsertionPoint();
11222 auto CondConstant = CI->getSExtValue();
11224 return ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
11226 return ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
11236 Builder.CreateCondBr(
Cond, ThenBlock, ElseBlock);
11239 if (
Error Err = ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks))
11245 if (
Error Err = ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks))
11254bool OpenMPIRBuilder::checkAndEmitFlushAfterAtomic(
11258 "Unexpected Atomic Ordering.");
11260 bool Flush =
false;
11322 assert(
X.Var->getType()->isPointerTy() &&
11323 "OMP Atomic expects a pointer to target memory");
11324 Type *XElemTy =
X.ElemTy;
11327 "OMP atomic read expected a scalar type");
11329 Value *XRead =
nullptr;
11333 Builder.CreateLoad(XElemTy,
X.Var,
X.IsVolatile,
"omp.atomic.read");
11342 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11345 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11347 XRead = AtomicLoadRes.first;
11354 Builder.CreateLoad(IntCastTy,
X.Var,
X.IsVolatile,
"omp.atomic.load");
11357 XRead =
Builder.CreateBitCast(XLoad, XElemTy,
"atomic.flt.cast");
11359 XRead =
Builder.CreateIntToPtr(XLoad, XElemTy,
"atomic.ptr.cast");
11362 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Read);
11363 Builder.CreateStore(XRead, V.Var, V.IsVolatile);
11374 assert(
X.Var->getType()->isPointerTy() &&
11375 "OMP Atomic expects a pointer to target memory");
11376 Type *XElemTy =
X.ElemTy;
11379 "OMP atomic write expected a scalar type");
11387 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11390 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11398 Builder.CreateBitCast(Expr, IntCastTy,
"atomic.src.int.cast");
11403 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Write);
11410 AtomicUpdateCallbackTy &UpdateOp,
bool IsXBinopExpr,
11411 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11417 Type *XTy =
X.Var->getType();
11419 "OMP Atomic expects a pointer to target memory");
11420 Type *XElemTy =
X.ElemTy;
11423 "OMP atomic update expected a scalar or struct type");
11426 "OpenMP atomic does not support LT or GT operations");
11430 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, RMWOp, UpdateOp,
X.IsVolatile,
11431 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11433 return AtomicResult.takeError();
11434 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Update);
11439Value *OpenMPIRBuilder::emitRMWOpAsInstruction(
Value *Src1,
Value *Src2,
11443 return Builder.CreateAdd(Src1, Src2);
11445 return Builder.CreateSub(Src1, Src2);
11447 return Builder.CreateAnd(Src1, Src2);
11449 return Builder.CreateNeg(Builder.CreateAnd(Src1, Src2));
11451 return Builder.CreateOr(Src1, Src2);
11453 return Builder.CreateXor(Src1, Src2);
11492Expected<std::pair<Value *, Value *>> OpenMPIRBuilder::emitAtomicUpdate(
11495 AtomicUpdateCallbackTy &UpdateOp,
bool VolatileX,
bool IsXBinopExpr,
11496 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11498 bool emitRMWOp =
false;
11506 emitRMWOp = XElemTy;
11509 emitRMWOp = (IsXBinopExpr && XElemTy);
11516 std::pair<Value *, Value *> Res;
11518 AtomicRMWInst *RMWInst =
11519 Builder.CreateAtomicRMW(RMWOp,
X, Expr, llvm::MaybeAlign(), AO);
11520 if (
T.isAMDGPU()) {
11521 if (IsIgnoreDenormalMode)
11522 RMWInst->
setMetadata(
"amdgpu.ignore.denormal.mode",
11524 if (!IsFineGrainedMemory)
11525 RMWInst->
setMetadata(
"amdgpu.no.fine.grained.memory",
11527 if (!IsRemoteMemory)
11531 Res.first = RMWInst;
11536 Res.second = Res.first;
11538 Res.second = emitRMWOpAsInstruction(Res.first, Expr, RMWOp);
11541 Builder.CreateLoad(XElemTy,
X,
X->getName() +
".atomic.load");
11547 OpenMPIRBuilder::AtomicInfo atomicInfo(
11549 OldVal->
getAlign(),
true , AllocaIP,
X);
11550 auto AtomicLoadRes = atomicInfo.EmitAtomicLoadLibcall(AO);
11553 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11560 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11561 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11562 Builder.SetInsertPoint(ContBB);
11564 PHI->addIncoming(AtomicLoadRes.first, CurBB);
11566 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11569 Value *Upd = *CBResult;
11570 Builder.CreateStore(Upd, NewAtomicAddr);
11573 auto Result = atomicInfo.EmitAtomicCompareExchangeLibcall(
11574 AtomicLoadRes.second, NewAtomicAddr, AO, Failure);
11575 LoadInst *PHILoad =
Builder.CreateLoad(XElemTy,
Result.first);
11576 PHI->addIncoming(PHILoad,
Builder.GetInsertBlock());
11579 Res.first = OldExprVal;
11582 if (UnreachableInst *ExitTI =
11585 Builder.SetInsertPoint(ExitBB);
11587 Builder.SetInsertPoint(ExitTI);
11590 IntegerType *IntCastTy =
11593 Builder.CreateLoad(IntCastTy,
X,
X->getName() +
".atomic.load");
11603 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11610 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11611 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11612 Builder.SetInsertPoint(ContBB);
11614 PHI->addIncoming(OldVal, CurBB);
11619 OldExprVal =
Builder.CreateBitCast(
PHI, XElemTy,
11620 X->getName() +
".atomic.fltCast");
11622 OldExprVal =
Builder.CreateIntToPtr(
PHI, XElemTy,
11623 X->getName() +
".atomic.ptrCast");
11627 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11630 Value *Upd = *CBResult;
11631 Builder.CreateStore(Upd, NewAtomicAddr);
11632 LoadInst *DesiredVal =
Builder.CreateLoad(IntCastTy, NewAtomicAddr);
11636 X,
PHI, DesiredVal, llvm::MaybeAlign(), AO, Failure);
11637 Result->setVolatile(VolatileX);
11638 Value *PreviousVal =
Builder.CreateExtractValue(Result, 0);
11639 Value *SuccessFailureVal =
Builder.CreateExtractValue(Result, 1);
11640 PHI->addIncoming(PreviousVal,
Builder.GetInsertBlock());
11641 Builder.CreateCondBr(SuccessFailureVal, ExitBB, ContBB);
11643 Res.first = OldExprVal;
11647 if (UnreachableInst *ExitTI =
11650 Builder.SetInsertPoint(ExitBB);
11652 Builder.SetInsertPoint(ExitTI);
11663 bool UpdateExpr,
bool IsPostfixUpdate,
bool IsXBinopExpr,
11664 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11669 Type *XTy =
X.Var->getType();
11671 "OMP Atomic expects a pointer to target memory");
11672 Type *XElemTy =
X.ElemTy;
11675 "OMP atomic capture expected a scalar or struct type");
11677 "OpenMP atomic does not support LT or GT operations");
11684 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, AtomicOp, UpdateOp,
X.IsVolatile,
11685 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11688 Value *CapturedVal =
11689 (IsPostfixUpdate ? AtomicResult->first : AtomicResult->second);
11690 Builder.CreateStore(CapturedVal, V.Var, V.IsVolatile);
11692 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Capture);
11700 bool IsFailOnly,
bool IsWeak) {
11704 IsPostfixUpdate, IsFailOnly, Failure, IsWeak);
11716 assert(
X.Var->getType()->isPointerTy() &&
11717 "OMP atomic expects a pointer to target memory");
11720 assert(V.Var->getType()->isPointerTy() &&
"v.var must be of pointer type");
11721 assert(V.ElemTy ==
X.ElemTy &&
"x and v must be of same type");
11724 bool IsInteger = E->getType()->isIntegerTy();
11726 if (
Op == OMPAtomicCompareOp::EQ) {
11729 Value *OldValue =
nullptr;
11730 Value *SuccessOrFail =
nullptr;
11768 X.Var->getName() +
".atomic.load");
11774 Value *EIsNaN =
Builder.CreateFCmpUNO(E, E,
"atomic.e.isnan");
11775 Value *XIsNaN =
Builder.CreateFCmpUNO(XFP, XFP,
"atomic.x.isnan");
11776 Value *EitherNaN =
Builder.CreateOr(EIsNaN, XIsNaN,
"atomic.either.nan");
11781 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11785 M.getContext(),
X.Var->getName() +
".atomic.nan",
F, ExitBB);
11787 M.getContext(),
X.Var->getName() +
".atomic.notnan",
F, ExitBB);
11789 M.getContext(),
X.Var->getName() +
".atomic.zero",
F, ExitBB);
11791 M.getContext(),
X.Var->getName() +
".atomic.normal",
F, ExitBB);
11795 Builder.SetInsertPoint(CurBB);
11796 Builder.CreateCondBr(EitherNaN, NaNBB, NotNaNBB);
11799 Builder.SetInsertPoint(NaNBB);
11803 Builder.SetInsertPoint(NotNaNBB);
11806 X.Var->getName() +
".atomic.xiszero");
11808 "atomic.e.iszero");
11809 Value *BothZero =
Builder.CreateAnd(XIsZero, EIsZero,
"atomic.both.zero");
11810 Builder.CreateCondBr(BothZero, ZeroBB, NormalBB);
11813 Builder.SetInsertPoint(ZeroBB);
11815 X.Var, XCurr, DBCast,
MaybeAlign(), AO, Failure);
11817 Value *OldZero =
Builder.CreateExtractValue(ResZero, 0);
11818 Value *OkZero =
Builder.CreateExtractValue(ResZero, 1);
11822 Builder.SetInsertPoint(NormalBB);
11824 X.Var, EBCast, DBCast,
MaybeAlign(), AO, Failure);
11826 Value *OldNormal =
Builder.CreateExtractValue(ResNormal, 0);
11827 Value *OkNormal =
Builder.CreateExtractValue(ResNormal, 1);
11833 Builder.CreatePHI(IntCastTy, 3,
X.Var->getName() +
".atomic.old");
11838 X.Var->getName() +
".atomic.ok");
11845 Builder.SetInsertPoint(ExitBB);
11850 OldValue =
Builder.CreateBitCast(OldIntPHI,
X.ElemTy,
11851 X.Var->getName() +
".atomic.old.fp");
11852 SuccessOrFail = SuccessPHI;
11860 Result =
Builder.CreateAtomicCmpXchg(
X.Var, EBCast, DBCast,
11866 Result->setWeak(IsWeak);
11869 OldValue =
Builder.CreateExtractValue(Result, 0);
11871 OldValue =
Builder.CreateBitCast(OldValue,
X.ElemTy);
11873 "OldValue and V must be of same type");
11874 if (IsPostfixUpdate) {
11875 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
11877 SuccessOrFail =
Builder.CreateExtractValue(Result, 1);
11881 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11883 CurBBTI,
X.Var->getName() +
".atomic.exit");
11889 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
11891 Builder.SetInsertPoint(ContBB);
11892 Builder.CreateStore(OldValue, V.Var);
11898 Builder.SetInsertPoint(ExitBB);
11900 Builder.SetInsertPoint(ExitTI);
11903 Value *CapturedValue =
11904 Builder.CreateSelect(SuccessOrFail, E, OldValue);
11905 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
11911 assert(R.Var->getType()->isPointerTy() &&
11912 "r.var must be of pointer type");
11913 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
11915 Value *SuccessFailureVal =
11916 Builder.CreateExtractValue(Result, 1);
11917 Value *ResultCast =
11918 R.IsSigned ?
Builder.CreateSExt(SuccessFailureVal, R.ElemTy)
11919 :
Builder.CreateZExt(SuccessFailureVal, R.ElemTy);
11920 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
11929 "OldValue and V must be of same type");
11930 if (IsPostfixUpdate) {
11931 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
11936 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11938 CurBBTI,
X.Var->getName() +
".atomic.exit");
11944 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
11946 Builder.SetInsertPoint(ContBB);
11947 Builder.CreateStore(OldValue, V.Var);
11953 Builder.SetInsertPoint(ExitBB);
11955 Builder.SetInsertPoint(ExitTI);
11958 Value *CapturedValue =
11959 Builder.CreateSelect(SuccessOrFail, E, OldValue);
11960 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
11966 assert(R.Var->getType()->isPointerTy() &&
11967 "r.var must be of pointer type");
11968 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
11970 Value *ResultCast = R.IsSigned
11971 ?
Builder.CreateSExt(SuccessOrFail, R.ElemTy)
11972 :
Builder.CreateZExt(SuccessOrFail, R.ElemTy);
11973 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
11977 assert((
Op == OMPAtomicCompareOp::MAX ||
Op == OMPAtomicCompareOp::MIN) &&
11978 "Op should be either max or min at this point");
11979 assert(!IsFailOnly &&
"IsFailOnly is only valid when the comparison is ==");
11990 if (IsXBinopExpr) {
12019 Value *CapturedValue =
nullptr;
12020 if (IsPostfixUpdate) {
12021 CapturedValue = OldValue;
12046 Value *NonAtomicCmp =
Builder.CreateCmp(Pred, OldValue, E);
12047 CapturedValue =
Builder.CreateSelect(NonAtomicCmp, E, OldValue);
12049 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
12053 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Compare);
12073 if (&OuterAllocaBB ==
Builder.GetInsertBlock()) {
12100 bool SubClausesPresent =
12101 (NumTeamsLower || NumTeamsUpper || ThreadLimit || IfExpr);
12103 if (!
Config.isTargetDevice() && SubClausesPresent) {
12104 assert((NumTeamsLower ==
nullptr || NumTeamsUpper !=
nullptr) &&
12105 "if lowerbound is non-null, then upperbound must also be non-null "
12106 "for bounds on num_teams");
12108 if (NumTeamsUpper ==
nullptr)
12109 NumTeamsUpper =
Builder.getInt32(0);
12111 if (NumTeamsLower ==
nullptr)
12112 NumTeamsLower = NumTeamsUpper;
12116 "argument to if clause must be an integer value");
12120 IfExpr =
Builder.CreateICmpNE(IfExpr,
12121 ConstantInt::get(IfExpr->
getType(), 0));
12122 NumTeamsUpper =
Builder.CreateSelect(
12123 IfExpr, NumTeamsUpper,
Builder.getInt32(1),
"numTeamsUpper");
12126 NumTeamsLower =
Builder.CreateSelect(
12127 IfExpr, NumTeamsLower,
Builder.getInt32(1),
"numTeamsLower");
12130 if (ThreadLimit ==
nullptr)
12131 ThreadLimit =
Builder.getInt32(0);
12135 Value *NumTeamsLowerInt32 =
12137 Value *NumTeamsUpperInt32 =
12139 Value *ThreadLimitInt32 =
12146 {Ident, ThreadNum, NumTeamsLowerInt32, NumTeamsUpperInt32,
12147 ThreadLimitInt32});
12152 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
12155 auto OI = std::make_unique<OutlineInfo>();
12156 OI->EntryBB = AllocaBB;
12157 OI->ExitBB = ExitBB;
12158 OI->OuterAllocBB = &OuterAllocaBB;
12164 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"gid",
true));
12166 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"tid",
true));
12168 auto HostPostOutlineCB = [
this, Ident,
12169 ToBeDeleted](
Function &OutlinedFn)
mutable {
12174 "there must be a single user for the outlined function");
12179 "Outlined function must have two or three arguments only");
12181 bool HasShared = OutlinedFn.
arg_size() == 3;
12189 assert(StaleCI &&
"Error while outlining - no CallInst user found for the "
12190 "outlined function.");
12191 Builder.SetInsertPoint(StaleCI);
12198 omp::RuntimeFunction::OMPRTL___kmpc_fork_teams),
12201 Builder.ClearInsertionPoint();
12203 I->eraseFromParent();
12206 if (!
Config.isTargetDevice())
12207 OI->PostOutlineCB = HostPostOutlineCB;
12211 Builder.SetInsertPoint(ExitBB);
12224 if (OuterAllocaBB ==
Builder.GetInsertBlock()) {
12239 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
12244 if (
Config.isTargetDevice()) {
12245 auto OI = std::make_unique<OutlineInfo>();
12246 OI->OuterAllocBB = OuterAllocIP.
getBlock();
12247 OI->EntryBB = AllocaBB;
12248 OI->ExitBB = ExitBB;
12249 OI->OuterDeallocBBs.reserve(OuterDeallocBlocks.
size());
12250 copy(OuterDeallocBlocks, OI->OuterDeallocBBs.
end());
12254 Builder.SetInsertPoint(ExitBB);
12261 std::string VarName) {
12270 return MapNamesArrayGlobal;
12275void OpenMPIRBuilder::initializeTypes(
Module &M) {
12279 unsigned ProgramAS = M.getDataLayout().getProgramAddressSpace();
12280#define OMP_TYPE(VarName, InitValue) VarName = InitValue;
12281#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \
12282 VarName##Ty = ArrayType::get(ElemTy, ArraySize); \
12283 VarName##PtrTy = PointerType::get(Ctx, DefaultTargetAS);
12284#define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) \
12285 VarName = FunctionType::get(ReturnType, {__VA_ARGS__}, IsVarArg); \
12286 VarName##Ptr = PointerType::get(Ctx, ProgramAS);
12287#define OMP_STRUCT_TYPE(VarName, StructName, Packed, ...) \
12288 T = StructType::getTypeByName(Ctx, StructName); \
12290 T = StructType::create(Ctx, {__VA_ARGS__}, StructName, Packed); \
12292 VarName##Ptr = PointerType::get(Ctx, DefaultTargetAS);
12293#include "llvm/Frontend/OpenMP/OMPKinds.def"
12304 while (!Worklist.
empty()) {
12308 if (
BlockSet.insert(SuccBB).second)
12313std::unique_ptr<CodeExtractor>
12315 bool ArgsInZeroAddressSpace,
12317 return std::make_unique<CodeExtractor>(
12327 Suffix.
str(), ArgsInZeroAddressSpace);
12330std::unique_ptr<CodeExtractor> DeviceSharedMemOutlineInfo::createCodeExtractor(
12332 return std::make_unique<DeviceSharedMemCodeExtractor>(
12333 OMPBuilder, Blocks,
nullptr,
12341 OuterDeallocBBs.empty()
12344 Suffix.
str(), ArgsInZeroAddressSpace);
12348 uint64_t
Size, int32_t Flags,
12354 Name.empty() ? Addr->
getName() : Name,
Size, Flags, 0);
12366 Fn->
addFnAttr(
"uniform-work-group-size");
12367 Fn->
addFnAttr(Attribute::MustProgress);
12385 auto &&GetMDInt = [
this](
unsigned V) {
12392 NamedMDNode *MD =
M.getOrInsertNamedMetadata(
"omp_offload.info");
12393 auto &&TargetRegionMetadataEmitter =
12394 [&
C, MD, &OrderedEntries, &GetMDInt, &GetMDString](
12409 GetMDInt(E.getKind()), GetMDInt(EntryInfo.DeviceID),
12410 GetMDInt(EntryInfo.FileID), GetMDString(EntryInfo.ParentName),
12411 GetMDInt(EntryInfo.Line), GetMDInt(EntryInfo.Count),
12412 GetMDInt(E.getOrder())};
12415 OrderedEntries[E.getOrder()] = std::make_pair(&E, EntryInfo);
12424 auto &&DeviceGlobalVarMetadataEmitter =
12425 [&
C, &OrderedEntries, &GetMDInt, &GetMDString, MD](
12435 Metadata *
Ops[] = {GetMDInt(E.getKind()), GetMDString(MangledName),
12436 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
12440 OrderedEntries[E.getOrder()] = std::make_pair(&E, varInfo);
12447 DeviceGlobalVarMetadataEmitter);
12449 for (
const auto &E : OrderedEntries) {
12450 assert(E.first &&
"All ordered entries must exist!");
12451 if (
const auto *CE =
12454 if (!CE->getID() || !CE->getAddress()) {
12458 if (!
M.getNamedValue(FnName))
12466 }
else if (
const auto *CE =
dyn_cast<
12475 if (
Config.isTargetDevice() &&
Config.hasRequiresUnifiedSharedMemory())
12477 if (!CE->getAddress()) {
12482 if (CE->getVarSize() == 0)
12486 assert(((
Config.isTargetDevice() && !CE->getAddress()) ||
12487 (!
Config.isTargetDevice() && CE->getAddress())) &&
12488 "Declaret target link address is set.");
12489 if (
Config.isTargetDevice())
12491 if (!CE->getAddress()) {
12498 if (!CE->getAddress()) {
12511 if ((
GV->hasLocalLinkage() ||
GV->hasHiddenVisibility()) &&
12515 OMPTargetGlobalVarEntryIndirectVTable))
12524 Flags, CE->getLinkage(), CE->getVarName());
12527 Flags, CE->getLinkage());
12538 if (
Config.hasRequiresFlags() && !
Config.isTargetDevice())
12544 Config.getRequiresFlags());
12554 OS <<
"_" <<
Count;
12559 unsigned NewCount = getTargetRegionEntryInfoCount(EntryInfo);
12562 EntryInfo.
Line, NewCount);
12570 auto FileIDInfo = CallBack();
12571 uint64_t FileID = 0;
12573 ID =
Status->getUniqueID();
12574 FileID =
Status->getUniqueID().getFile();
12578 FileID =
hash_value(std::get<0>(FileIDInfo));
12582 std::get<1>(FileIDInfo));
12587 for (uint64_t Remain =
12588 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12590 !(Remain & 1); Remain = Remain >> 1)
12608 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12610 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12617 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12623 Flags &=
~omp::OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
12624 Flags |= MemberOfFlag;
12630 bool IsDeclaration,
bool IsExternallyVisible,
12632 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12633 std::vector<Triple> TargetTriple,
Type *LlvmPtrTy,
12634 std::function<
Constant *()> GlobalInitializer,
12645 Config.hasRequiresUnifiedSharedMemory())) {
12650 if (!IsExternallyVisible)
12652 OS <<
"_decl_tgt_ref_ptr";
12655 Value *Ptr =
M.getNamedValue(PtrName);
12664 if (!
Config.isTargetDevice()) {
12665 if (GlobalInitializer)
12666 GV->setInitializer(GlobalInitializer());
12672 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12673 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12674 GlobalInitializer, VariableLinkage, LlvmPtrTy,
cast<Constant>(Ptr));
12686 bool IsDeclaration,
bool IsExternallyVisible,
12688 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12689 std::vector<Triple> TargetTriple,
12690 std::function<
Constant *()> GlobalInitializer,
12694 (TargetTriple.empty() && !
Config.isTargetDevice()))
12705 !
Config.hasRequiresUnifiedSharedMemory()) {
12707 VarName = MangledName;
12710 if (!IsDeclaration)
12712 M.getDataLayout().getTypeSizeInBits(LlvmVal->
getValueType()), 8);
12715 Linkage = (VariableLinkage) ? VariableLinkage() : LlvmVal->
getLinkage();
12719 if (
Config.isTargetDevice() &&
12728 if (!
M.getNamedValue(RefName)) {
12732 GvAddrRef->setConstant(
true);
12734 GvAddrRef->setInitializer(Addr);
12735 GeneratedRefs.push_back(GvAddrRef);
12744 if (
Config.isTargetDevice()) {
12745 VarName = (Addr) ? Addr->
getName() :
"";
12749 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12750 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12751 LlvmPtrTy, GlobalInitializer, VariableLinkage);
12752 VarName = (Addr) ? Addr->
getName() :
"";
12754 VarSize =
M.getDataLayout().getPointerSize();
12773 auto &&GetMDInt = [MN](
unsigned Idx) {
12778 auto &&GetMDString = [MN](
unsigned Idx) {
12780 return V->getString();
12783 switch (GetMDInt(0)) {
12787 case OffloadEntriesInfoManager::OffloadEntryInfo::
12788 OffloadingEntryInfoTargetRegion: {
12798 case OffloadEntriesInfoManager::OffloadEntryInfo::
12799 OffloadingEntryInfoDeviceGlobalVar:
12812 if (HostFilePath.
empty())
12816 if (std::error_code Err = Buf.getError()) {
12818 "OpenMPIRBuilder: " +
12826 if (std::error_code Err =
M.getError()) {
12828 (
"error parsing host file inside of OpenMPIRBuilder: " + Err.message())
12842 "expected a valid insertion block for creating an iterator loop");
12852 Builder.getCurrentDebugLocation(),
"omp.it.cont");
12864 T->eraseFromParent();
12873 if (!BodyBr || BodyBr->getSuccessor() != CLI->
getLatch()) {
12875 "iterator bodygen must terminate the canonical body with an "
12876 "unconditional branch to the loop latch",
12900 for (
const auto &
ParamAttr : ParamAttrs) {
12943 return std::string(Out.str());
12951 unsigned VecRegSize;
12953 ISADataTy ISAData[] = {
12972 for (
char Mask :
Masked) {
12973 for (
const ISADataTy &
Data : ISAData) {
12976 Out <<
"_ZGV" <<
Data.ISA << Mask;
12978 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
12992template <
typename T>
12995 StringRef MangledName,
bool OutputBecomesInput,
12999 Out << Prefix << ISA << LMask << VLEN;
13000 if (OutputBecomesInput)
13002 Out << ParSeq <<
'_' << MangledName;
13011 bool OutputBecomesInput,
13016 OutputBecomesInput, Fn);
13018 OutputBecomesInput, Fn);
13022 OutputBecomesInput, Fn);
13024 OutputBecomesInput, Fn);
13028 OutputBecomesInput, Fn);
13030 OutputBecomesInput, Fn);
13035 OutputBecomesInput, Fn);
13046 char ISA,
unsigned NarrowestDataSize,
bool OutputBecomesInput) {
13047 assert((ISA ==
'n' || ISA ==
's') &&
"Expected ISA either 's' or 'n'.");
13059 OutputBecomesInput, Fn);
13066 OutputBecomesInput, Fn);
13068 OutputBecomesInput, Fn);
13072 OutputBecomesInput, Fn);
13076 OutputBecomesInput, Fn);
13085 OutputBecomesInput, Fn);
13092 MangledName, OutputBecomesInput, Fn);
13094 MangledName, OutputBecomesInput, Fn);
13098 MangledName, OutputBecomesInput, Fn);
13102 MangledName, OutputBecomesInput, Fn);
13112 return OffloadEntriesTargetRegion.empty() &&
13113 OffloadEntriesDeviceGlobalVar.empty();
13116unsigned OffloadEntriesInfoManager::getTargetRegionEntryInfoCount(
13118 auto It = OffloadEntriesTargetRegionCount.find(
13119 getTargetRegionEntryCountKey(EntryInfo));
13120 if (It == OffloadEntriesTargetRegionCount.end())
13125void OffloadEntriesInfoManager::incrementTargetRegionEntryInfoCount(
13127 OffloadEntriesTargetRegionCount[getTargetRegionEntryCountKey(EntryInfo)] =
13128 EntryInfo.
Count + 1;
13134 OffloadEntriesTargetRegion[EntryInfo] =
13137 ++OffloadingEntriesNum;
13143 assert(EntryInfo.
Count == 0 &&
"expected default EntryInfo");
13146 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
13150 if (OMPBuilder->Config.isTargetDevice()) {
13155 auto &Entry = OffloadEntriesTargetRegion[EntryInfo];
13156 Entry.setAddress(Addr);
13158 Entry.setFlags(Flags);
13164 "Target region entry already registered!");
13166 OffloadEntriesTargetRegion[EntryInfo] = Entry;
13167 ++OffloadingEntriesNum;
13169 incrementTargetRegionEntryInfoCount(EntryInfo);
13176 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
13178 auto It = OffloadEntriesTargetRegion.find(EntryInfo);
13179 if (It == OffloadEntriesTargetRegion.end()) {
13183 if (!IgnoreAddressId && (It->second.getAddress() || It->second.getID()))
13191 for (
const auto &It : OffloadEntriesTargetRegion) {
13192 Action(It.first, It.second);
13198 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
13199 ++OffloadingEntriesNum;
13205 if (OMPBuilder->Config.isTargetDevice()) {
13209 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
13211 if (Entry.getVarSize() == 0) {
13212 Entry.setVarSize(VarSize);
13213 Entry.setLinkage(Linkage);
13217 Entry.setVarSize(VarSize);
13218 Entry.setLinkage(Linkage);
13219 Entry.setAddress(Addr);
13222 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
13223 assert(Entry.isValid() && Entry.getFlags() == Flags &&
13224 "Entry not initialized!");
13225 if (Entry.getVarSize() == 0) {
13226 Entry.setVarSize(VarSize);
13227 Entry.setLinkage(Linkage);
13234 OffloadEntriesDeviceGlobalVar.try_emplace(VarName, OffloadingEntriesNum,
13235 Addr, VarSize, Flags, Linkage,
13238 OffloadEntriesDeviceGlobalVar.try_emplace(
13239 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage,
"");
13240 ++OffloadingEntriesNum;
13247 for (
const auto &E : OffloadEntriesDeviceGlobalVar)
13248 Action(E.getKey(), E.getValue());
13255void CanonicalLoopInfo::collectControlBlocks(
13262 BBs.
append({getPreheader(), Header,
Cond, Latch, Exit, getAfter()});
13274void CanonicalLoopInfo::setTripCount(
Value *TripCount) {
13286void CanonicalLoopInfo::mapIndVar(
13296 for (
Use &U : OldIV->
uses()) {
13300 if (
User->getParent() == getCond())
13302 if (
User->getParent() == getLatch())
13308 Value *NewIV = Updater(OldIV);
13311 for (Use *U : ReplacableUses)
13332 "Preheader must terminate with unconditional branch");
13334 "Preheader must jump to header");
13338 "Header must terminate with unconditional branch");
13339 assert(Header->getSingleSuccessor() == Cond &&
13340 "Header must jump to exiting block");
13343 assert(Cond->getSinglePredecessor() == Header &&
13344 "Exiting block only reachable from header");
13347 "Exiting block must terminate with conditional branch");
13349 "Exiting block's first successor jump to the body");
13351 "Exiting block's second successor must exit the loop");
13355 "Body only reachable from exiting block");
13360 "Latch must terminate with unconditional branch");
13361 assert(Latch->getSingleSuccessor() == Header &&
"Latch must jump to header");
13364 assert(Latch->getSinglePredecessor() !=
nullptr);
13369 "Exit block must terminate with unconditional branch");
13370 assert(Exit->getSingleSuccessor() == After &&
13371 "Exit block must jump to after block");
13375 "After block only reachable from exit block");
13379 assert(IndVar &&
"Canonical induction variable not found?");
13381 "Induction variable must be an integer");
13383 "Induction variable must be a PHI in the loop header");
13389 auto *NextIndVar =
cast<PHINode>(IndVar)->getIncomingValue(1);
13397 assert(TripCount &&
"Loop trip count not found?");
13399 "Trip count and induction variable must have the same type");
13403 "Exit condition must be a signed less-than comparison");
13405 "Exit condition must compare the induction variable");
13407 "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.
user_iterator user_begin()
LLVM_ABI void moveBeforePreserving(InstListType::iterator MovePos)
Perform a moveBefore operation, while signalling that the caller intends to preserve the original ord...
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI void insertAfter(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately after the specified instruction.
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
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.
LLVM_ABI InsertPointOrErrorTy createTask(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< BasicBlock * > DeallocBlocks, BodyGenCallbackTy BodyGenCB, bool Tied=true, Value *Final=nullptr, Value *IfCondition=nullptr, const DependenciesInfo &Dependencies={}, const AffinityData &Affinities={}, bool Mergeable=false, Value *EventHandle=nullptr, Value *Priority=nullptr, bool FreeAgent=false)
Generator for #omp taskloop
std::forward_list< ScanInfo > ScanInfos
Collection of owned ScanInfo objects that eventually need to be free'd.
static LLVM_ABI void writeTeamsForKernel(const Triple &T, Function &Kernel, int32_t LB, int32_t UB)
LLVM_ABI Value * calculateCanonicalLoopTripCount(const LocationDescription &Loc, Value *Start, Value *Stop, Value *Step, bool IsSigned, bool InclusiveStop, const Twine &Name="loop")
Calculate the trip count of a canonical loop.
LLVM_ABI InsertPointOrErrorTy createBarrier(const LocationDescription &Loc, omp::Directive Kind, bool ForceSimpleCall=false, bool CheckCancelFlag=true)
Emitter methods for OpenMP directives.
LLVM_ABI void setCorrectMemberOfFlag(omp::OpenMPOffloadMappingFlags &Flags, omp::OpenMPOffloadMappingFlags MemberOfFlag)
Given an initial flag set, this function modifies it to contain the passed in MemberOfFlag generated ...
LLVM_ABI Error emitOffloadingArraysAndArgs(InsertPointTy AllocaIP, InsertPointTy CodeGenIP, TargetDataInfo &Info, TargetDataRTArgs &RTArgs, MapInfosTy &CombinedInfo, CustomMapperCallbackTy CustomMapperCB, bool IsNonContiguous=false, bool ForEndCall=false, function_ref< void(unsigned int, Value *)> DeviceAddrCB=nullptr)
Allocates memory for and populates the arrays required for offloading (offload_{baseptrs|ptrs|mappers...
LLVM_ABI Constant * getOrCreateDefaultSrcLocStr(uint32_t &SrcLocStrSize)
Return the (LLVM-IR) string describing the default source location.
LLVM_ABI InsertPointOrErrorTy createCritical(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, StringRef CriticalName, Value *HintInst)
Generator for 'omp critical'.
LLVM_ABI void createError(const LocationDescription &Loc, bool IsFatal, Value *Message)
Generate a call to the runtime to emit the diagnostic of an OpenMP error directive with at(execution)...
LLVM_ABI void createOffloadEntry(Constant *ID, Constant *Addr, uint64_t Size, int32_t Flags, GlobalValue::LinkageTypes, StringRef Name="")
Creates offloading entry for the provided entry ID ID, address Addr, size Size, and flags Flags.
static LLVM_ABI unsigned getOpenMPDefaultSimdAlign(const Triple &TargetTriple, const StringMap< bool > &Features)
Get the default alignment value for given target.
LLVM_ABI unsigned getFlagMemberOffset()
Get the offset of the OMP_MAP_MEMBER_OF field.
LLVM_ABI InsertPointOrErrorTy 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.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
LLVM_ABI bool hasNUses(unsigned N) const
Return true if this Value has exactly N uses.
LLVM_ABI User * getUniqueUndroppableUser()
Return true if there is exactly one unique user of this value that cannot be dropped (that user can h...
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
LLVM_ABI bool replaceUsesWithIf(Value *New, llvm::function_ref< bool(Use &U)> ShouldReplace)
Go through the uses list for this definition and make each use point to "V" if the callback ShouldRep...
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
A raw_ostream that writes to an SmallVector or SmallString.
The virtual file system interface.
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(const Twine &Name, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatile=false, bool IsText=true)
This is a convenience method that opens a file, gets its content and then closes the file.
virtual llvm::ErrorOr< Status > status(const Twine &Path)=0
Get the status of the entry at Path, if one exists.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ SPIR_KERNEL
Used for SPIR kernel functions.
@ PTX_Kernel
Call to a PTX kernel. Passes all arguments in parameter space.
@ BasicBlock
Various leaf nodes.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
Flag
These should be considered private to the implementation of the MCInstrDesc class.
constexpr StringLiteral MaxNTID("nvvm.maxntid")
constexpr StringLiteral MaxClusterRank("nvvm.maxclusterrank")
initializer< Ty > init(const Ty &Val)
@ User
could "use" a pointer
LLVM_ABI GlobalVariable * emitOffloadingEntry(Module &M, object::OffloadKind Kind, Constant *Addr, StringRef Name, uint64_t Size, uint32_t Flags, uint64_t Data, Constant *AuxAddr=nullptr)
OpenMPOffloadMappingFlags
Values for bit flags used to specify the mapping type for offloading.
@ OMP_MAP_PTR_AND_OBJ
The element being mapped is a pointer-pointee pair; both the pointer and the pointee should be mapped...
@ OMP_MAP_MEMBER_OF
The 16 MSBs of the flags indicate whether the entry is member of some struct/class.
IdentFlag
IDs for all omp runtime library ident_t flag encodings (see their defintion in openmp/runtime/src/kmp...
RuntimeFunction
IDs for all omp runtime library (RTL) functions.
constexpr const GV & getAMDGPUGridValues()
static constexpr GV SPIRVGridValues
For generic SPIR-V GPUs.
OMPDynGroupprivateFallbackType
The fallback types for the dyn_groupprivate clause.
static constexpr GV NVPTXGridValues
For Nvidia GPUs.
@ OMP_TGT_EXEC_MODE_SPMD_NO_LOOP
@ OMP_TGT_EXEC_MODE_GENERIC
Function * Kernel
Summary of a kernel (=entry point for target offloading).
WorksharingLoopType
A type of worksharing loop construct.
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),...