69#define DEBUG_TYPE "openmp-ir-builder"
76 cl::desc(
"Use optimistic attributes describing "
77 "'as-if' properties of runtime calls."),
81 "openmp-ir-builder-unroll-threshold-factor",
cl::Hidden,
82 cl::desc(
"Factor for the unroll threshold to account for code "
83 "simplifications still taking place"),
87 "openmp-ir-builder-use-default-max-threads",
cl::Hidden,
98 if (!IP1.isSet() || !IP2.isSet())
100 return IP1.getBlock() == IP2.getBlock() && IP1.getPoint() == IP2.getPoint();
105 switch (SchedType & ~OMPScheduleType::MonotonicityMask) {
106 case OMPScheduleType::UnorderedStaticChunked:
107 case OMPScheduleType::UnorderedStatic:
108 case OMPScheduleType::UnorderedDynamicChunked:
109 case OMPScheduleType::UnorderedGuidedChunked:
110 case OMPScheduleType::UnorderedRuntime:
111 case OMPScheduleType::UnorderedAuto:
112 case OMPScheduleType::UnorderedTrapezoidal:
113 case OMPScheduleType::UnorderedGreedy:
114 case OMPScheduleType::UnorderedBalanced:
115 case OMPScheduleType::UnorderedGuidedIterativeChunked:
116 case OMPScheduleType::UnorderedGuidedAnalyticalChunked:
117 case OMPScheduleType::UnorderedSteal:
118 case OMPScheduleType::UnorderedStaticBalancedChunked:
119 case OMPScheduleType::UnorderedGuidedSimd:
120 case OMPScheduleType::UnorderedRuntimeSimd:
121 case OMPScheduleType::OrderedStaticChunked:
122 case OMPScheduleType::OrderedStatic:
123 case OMPScheduleType::OrderedDynamicChunked:
124 case OMPScheduleType::OrderedGuidedChunked:
125 case OMPScheduleType::OrderedRuntime:
126 case OMPScheduleType::OrderedAuto:
127 case OMPScheduleType::OrderdTrapezoidal:
128 case OMPScheduleType::NomergeUnorderedStaticChunked:
129 case OMPScheduleType::NomergeUnorderedStatic:
130 case OMPScheduleType::NomergeUnorderedDynamicChunked:
131 case OMPScheduleType::NomergeUnorderedGuidedChunked:
132 case OMPScheduleType::NomergeUnorderedRuntime:
133 case OMPScheduleType::NomergeUnorderedAuto:
134 case OMPScheduleType::NomergeUnorderedTrapezoidal:
135 case OMPScheduleType::NomergeUnorderedGreedy:
136 case OMPScheduleType::NomergeUnorderedBalanced:
137 case OMPScheduleType::NomergeUnorderedGuidedIterativeChunked:
138 case OMPScheduleType::NomergeUnorderedGuidedAnalyticalChunked:
139 case OMPScheduleType::NomergeUnorderedSteal:
140 case OMPScheduleType::NomergeOrderedStaticChunked:
141 case OMPScheduleType::NomergeOrderedStatic:
142 case OMPScheduleType::NomergeOrderedDynamicChunked:
143 case OMPScheduleType::NomergeOrderedGuidedChunked:
144 case OMPScheduleType::NomergeOrderedRuntime:
145 case OMPScheduleType::NomergeOrderedAuto:
146 case OMPScheduleType::NomergeOrderedTrapezoidal:
147 case OMPScheduleType::OrderedDistributeChunked:
148 case OMPScheduleType::OrderedDistribute:
156 SchedType & OMPScheduleType::MonotonicityMask;
157 if (MonotonicityFlags == OMPScheduleType::MonotonicityMask)
171 Builder.restoreIP(IP);
175 if (Builder.GetInsertPoint() != BB->
end())
185 unsigned Line = FSP->getScopeLine() ? FSP->getScopeLine() : FSP->getLine();
186 Builder.SetCurrentDebugLocation(
192 return T.isAMDGPU() ||
T.isNVPTX() ||
T.isSPIRV();
198 Kernel->getFnAttribute(
"target-features").getValueAsString();
199 if (Features.
count(
"+wavefrontsize64"))
214 bool HasSimdModifier,
bool HasDistScheduleChunks) {
216 switch (ClauseKind) {
217 case OMP_SCHEDULE_Default:
218 case OMP_SCHEDULE_Static:
219 return HasChunks ? OMPScheduleType::BaseStaticChunked
220 : OMPScheduleType::BaseStatic;
221 case OMP_SCHEDULE_Dynamic:
222 return OMPScheduleType::BaseDynamicChunked;
223 case OMP_SCHEDULE_Guided:
224 return HasSimdModifier ? OMPScheduleType::BaseGuidedSimd
225 : OMPScheduleType::BaseGuidedChunked;
226 case OMP_SCHEDULE_Auto:
228 case OMP_SCHEDULE_Runtime:
229 return HasSimdModifier ? OMPScheduleType::BaseRuntimeSimd
230 : OMPScheduleType::BaseRuntime;
231 case OMP_SCHEDULE_Distribute:
232 return HasDistScheduleChunks ? OMPScheduleType::BaseDistributeChunked
233 : OMPScheduleType::BaseDistribute;
241 bool HasOrderedClause) {
242 assert((BaseScheduleType & OMPScheduleType::ModifierMask) ==
243 OMPScheduleType::None &&
244 "Must not have ordering nor monotonicity flags already set");
247 ? OMPScheduleType::ModifierOrdered
248 : OMPScheduleType::ModifierUnordered;
252 if (OrderingScheduleType ==
253 (OMPScheduleType::BaseGuidedSimd | OMPScheduleType::ModifierOrdered))
254 return OMPScheduleType::OrderedGuidedChunked;
255 else if (OrderingScheduleType == (OMPScheduleType::BaseRuntimeSimd |
256 OMPScheduleType::ModifierOrdered))
257 return OMPScheduleType::OrderedRuntime;
259 return OrderingScheduleType;
265 bool HasSimdModifier,
bool HasMonotonic,
266 bool HasNonmonotonic,
bool HasOrderedClause) {
267 assert((ScheduleType & OMPScheduleType::MonotonicityMask) ==
268 OMPScheduleType::None &&
269 "Must not have monotonicity flags already set");
270 assert((!HasMonotonic || !HasNonmonotonic) &&
271 "Monotonic and Nonmonotonic are contradicting each other");
274 return ScheduleType | OMPScheduleType::ModifierMonotonic;
275 }
else if (HasNonmonotonic) {
276 return ScheduleType | OMPScheduleType::ModifierNonmonotonic;
286 if ((BaseScheduleType == OMPScheduleType::BaseStatic) ||
287 (BaseScheduleType == OMPScheduleType::BaseStaticChunked) ||
293 return ScheduleType | OMPScheduleType::ModifierNonmonotonic;
301 bool HasSimdModifier,
bool HasMonotonicModifier,
302 bool HasNonmonotonicModifier,
bool HasOrderedClause,
303 bool HasDistScheduleChunks) {
305 ClauseKind, HasChunks, HasSimdModifier, HasDistScheduleChunks);
309 OrderedSchedule, HasSimdModifier, HasMonotonicModifier,
310 HasNonmonotonicModifier, HasOrderedClause);
318static std::optional<omp::OMPTgtExecModeFlags>
323 if (
Call->getCalledFunction()->getName() ==
"__kmpc_target_init") {
324 TargetInitCall =
Call;
349 std::optional<omp::OMPTgtExecModeFlags> ExecMode =
361 if (
Instruction *Term = Source->getTerminatorOrNull()) {
370 NewBr->setDebugLoc(
DL);
375 assert(New->getFirstInsertionPt() == New->begin() &&
376 "Target BB must not have PHI nodes");
392 New->splice(New->begin(), Old, IP.
getPoint(), Old->
end());
396 NewBr->setDebugLoc(
DL);
408 Builder.SetInsertPoint(Old);
412 Builder.SetCurrentDebugLocation(
DebugLoc);
422 New->replaceSuccessorsPhiUsesWith(Old, New);
431 Builder.SetInsertPoint(Builder.GetInsertBlock()->getTerminator());
433 Builder.SetInsertPoint(Builder.GetInsertBlock());
436 Builder.SetCurrentDebugLocation(
DebugLoc);
445 Builder.SetInsertPoint(Builder.GetInsertBlock()->getTerminator());
447 Builder.SetInsertPoint(Builder.GetInsertBlock());
450 Builder.SetCurrentDebugLocation(
DebugLoc);
467 const Twine &Name =
"",
bool AsPtr =
true,
468 bool Is64Bit =
false) {
469 Builder.restoreIP(OuterAllocaIP);
473 Builder.CreateAlloca(IntTy,
nullptr, Name +
".addr");
477 FakeVal = FakeValAddr;
479 FakeVal = Builder.CreateLoad(IntTy, FakeValAddr, Name +
".val");
484 Builder.restoreIP(InnerAllocaIP);
487 UseFakeVal = Builder.CreateLoad(IntTy, FakeVal, Name +
".use");
490 FakeVal, Is64Bit ? Builder.getInt64(10) : Builder.getInt32(10)));
503enum OpenMPOffloadingRequiresDirFlags {
505 OMP_REQ_UNDEFINED = 0x000,
507 OMP_REQ_NONE = 0x001,
509 OMP_REQ_REVERSE_OFFLOAD = 0x002,
511 OMP_REQ_UNIFIED_ADDRESS = 0x004,
513 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008,
515 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010,
522 DominatorTree *DT =
nullptr,
bool AggregateArgs =
false,
523 BlockFrequencyInfo *BFI =
nullptr,
524 BranchProbabilityInfo *BPI =
nullptr,
525 AssumptionCache *AC =
nullptr,
bool AllowVarArgs =
false,
526 bool AllowAlloca =
false,
527 BasicBlock *AllocationBlock =
nullptr,
529 std::string Suffix =
"",
bool ArgsInZeroAddressSpace =
false)
530 : CodeExtractor(BBs, DT, AggregateArgs, BFI, BPI, AC, AllowVarArgs,
531 AllowAlloca, AllocationBlock, DeallocationBlocks, Suffix,
532 ArgsInZeroAddressSpace),
533 OMPBuilder(OMPBuilder) {}
535 virtual ~OMPCodeExtractor() =
default;
538 OpenMPIRBuilder &OMPBuilder;
541class DeviceSharedMemCodeExtractor :
public OMPCodeExtractor {
543 using OMPCodeExtractor::OMPCodeExtractor;
544 virtual ~DeviceSharedMemCodeExtractor() =
default;
548 allocateVar(IRBuilder<>::InsertPoint AllocaIP,
Type *VarType,
549 const Twine &Name = Twine(
""),
550 AddrSpaceCastInst **CastedAlloc =
nullptr)
override {
551 return OMPBuilder.createOMPAllocShared(AllocaIP, VarType, Name);
554 virtual Instruction *deallocateVar(IRBuilder<>::InsertPoint DeallocIP,
556 return OMPBuilder.createOMPFreeShared(DeallocIP, Var, VarType);
563 OpenMPIRBuilder &OMPBuilder;
565 DeviceSharedMemOutlineInfo(OpenMPIRBuilder &OMPBuilder)
566 : OMPBuilder(OMPBuilder) {}
567 virtual ~DeviceSharedMemOutlineInfo() =
default;
569 virtual std::unique_ptr<CodeExtractor>
571 bool ArgsInZeroAddressSpace,
572 Twine Suffix = Twine(
""))
override;
578 : RequiresFlags(OMP_REQ_UNDEFINED) {}
582 bool HasRequiresReverseOffload,
bool HasRequiresUnifiedAddress,
583 bool HasRequiresUnifiedSharedMemory,
bool HasRequiresDynamicAllocators)
586 RequiresFlags(OMP_REQ_UNDEFINED) {
587 if (HasRequiresReverseOffload)
588 RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
589 if (HasRequiresUnifiedAddress)
590 RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
591 if (HasRequiresUnifiedSharedMemory)
592 RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
593 if (HasRequiresDynamicAllocators)
594 RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
598 return RequiresFlags & OMP_REQ_REVERSE_OFFLOAD;
602 return RequiresFlags & OMP_REQ_UNIFIED_ADDRESS;
606 return RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY;
610 return RequiresFlags & OMP_REQ_DYNAMIC_ALLOCATORS;
615 :
static_cast<int64_t
>(OMP_REQ_NONE);
620 RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
622 RequiresFlags &= ~OMP_REQ_REVERSE_OFFLOAD;
627 RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
629 RequiresFlags &= ~OMP_REQ_UNIFIED_ADDRESS;
634 RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
636 RequiresFlags &= ~OMP_REQ_UNIFIED_SHARED_MEMORY;
641 RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
643 RequiresFlags &= ~OMP_REQ_DYNAMIC_ALLOCATORS;
656 constexpr size_t MaxDim = 3;
661 Value *DynCGroupMemFallbackFlag =
663 DynCGroupMemFallbackFlag =
Builder.CreateShl(DynCGroupMemFallbackFlag, 2);
668 StrictBlocksFlag =
Builder.CreateShl(StrictBlocksFlag, 6);
669 StrictThreadsFlag =
Builder.CreateShl(StrictThreadsFlag, 7);
671 Value *Flags =
Builder.CreateOr(HasNoWaitFlag, DynCGroupMemFallbackFlag);
672 Flags =
Builder.CreateOr(Flags, StrictBlocksFlag);
673 Flags =
Builder.CreateOr(Flags, StrictThreadsFlag);
679 Value *NumThreads3D =
710 auto FnAttrs = Attrs.getFnAttrs();
711 auto RetAttrs = Attrs.getRetAttrs();
713 for (
size_t ArgNo = 0; ArgNo < Fn.
arg_size(); ++ArgNo)
718 bool Param =
true) ->
void {
719 bool HasSignExt = AS.hasAttribute(Attribute::SExt);
720 bool HasZeroExt = AS.hasAttribute(Attribute::ZExt);
721 if (HasSignExt || HasZeroExt) {
722 assert(AS.getNumAttributes() == 1 &&
723 "Currently not handling extension attr combined with others.");
725 if (
auto AK = TargetLibraryInfo::getExtAttrForI32Param(
T, HasSignExt))
728 TargetLibraryInfo::getExtAttrForI32Return(
T, HasSignExt))
735#define OMP_ATTRS_SET(VarName, AttrSet) AttributeSet VarName = AttrSet;
736#include "llvm/Frontend/OpenMP/OMPKinds.def"
740#define OMP_RTL_ATTRS(Enum, FnAttrSet, RetAttrSet, ArgAttrSets) \
742 FnAttrs = FnAttrs.addAttributes(Ctx, FnAttrSet); \
743 addAttrSet(RetAttrs, RetAttrSet, false); \
744 for (size_t ArgNo = 0; ArgNo < ArgAttrSets.size(); ++ArgNo) \
745 addAttrSet(ArgAttrs[ArgNo], ArgAttrSets[ArgNo]); \
746 Fn.setAttributes(AttributeList::get(Ctx, FnAttrs, RetAttrs, ArgAttrs)); \
748#include "llvm/Frontend/OpenMP/OMPKinds.def"
762#define OMP_RTL(Enum, Str, IsVarArg, ReturnType, ...) \
764 FnTy = FunctionType::get(ReturnType, ArrayRef<Type *>{__VA_ARGS__}, \
766 Fn = M.getFunction(Str); \
768#include "llvm/Frontend/OpenMP/OMPKinds.def"
774#define OMP_RTL(Enum, Str, ...) \
776 Fn = Function::Create(FnTy, GlobalValue::ExternalLinkage, Str, M); \
778#include "llvm/Frontend/OpenMP/OMPKinds.def"
782 if (FnID == OMPRTL___kmpc_fork_call || FnID == OMPRTL___kmpc_fork_teams) {
792 LLVMContext::MD_callback,
794 2, {-1, -1},
true)}));
807 assert(Fn &&
"Failed to create OpenMP runtime function");
818 Builder.SetInsertPoint(FiniBB);
830 FiniBB = OtherFiniBB;
832 Builder.SetInsertPoint(FiniBB->getFirstNonPHIIt());
840 auto EndIt = FiniBB->end();
841 if (FiniBB->size() >= 1)
842 if (
auto Prev = std::prev(EndIt); Prev->isTerminator())
847 FiniBB->replaceAllUsesWith(OtherFiniBB);
848 FiniBB->eraseFromParent();
849 FiniBB = OtherFiniBB;
856 assert(Fn &&
"Failed to create OpenMP runtime function pointer");
879 for (
auto Inst =
Block->getReverseIterator()->begin();
880 Inst !=
Block->getReverseIterator()->end();) {
909 Block.getParent()->getEntryBlock().getTerminator()->getIterator();
930 DeferredOutlines.
push_back(std::move(OI));
934 ParallelRegionBlockSet.
clear();
936 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
946 bool ArgsInZeroAddressSpace =
Config.isTargetDevice();
947 std::unique_ptr<CodeExtractor> Extractor =
948 OI->createCodeExtractor(Blocks, ArgsInZeroAddressSpace,
".omp_par");
952 <<
" Exit: " << OI->ExitBB->getName() <<
"\n");
953 assert(Extractor->isEligible() &&
954 "Expected OpenMP outlining to be possible!");
956 for (
auto *V : OI->ExcludeArgsFromAggregate)
957 Extractor->excludeArgFromAggregate(V);
960 Extractor->extractCodeRegion(CEAC, OI->Inputs, OI->Outputs);
964 if (TargetCpuAttr.isStringAttribute())
967 auto TargetFeaturesAttr = OuterFn->
getFnAttribute(
"target-features");
968 if (TargetFeaturesAttr.isStringAttribute())
969 OutlinedFn->
addFnAttr(TargetFeaturesAttr);
972 LLVM_DEBUG(
dbgs() <<
" Outlined function: " << *OutlinedFn <<
"\n");
974 "OpenMP outlined functions should not return a value!");
979 M.getFunctionList().insertAfter(OuterFn->
getIterator(), OutlinedFn);
986 assert(OI->EntryBB->getUniquePredecessor() == &ArtificialEntry);
993 "Expected instructions to add in the outlined region entry");
995 End = ArtificialEntry.
rend();
1000 if (
I.isTerminator()) {
1002 if (
Instruction *TI = OI->EntryBB->getTerminatorOrNull())
1003 TI->adoptDbgRecords(&ArtificialEntry,
I.getIterator(),
false);
1007 I.moveBeforePreserving(*OI->EntryBB,
1008 OI->EntryBB->getFirstInsertionPt());
1011 OI->EntryBB->moveBefore(&ArtificialEntry);
1018 if (OI->PostOutlineCB)
1019 OI->PostOutlineCB(*OutlinedFn);
1021 if (OI->FixUpNonEntryAllocas)
1053 errs() <<
"Error of kind: " << Kind
1054 <<
" when emitting offload entries and metadata during "
1055 "OMPIRBuilder finalization \n";
1063 if (
Config.isTargetDevice())
1064 applyDeclareTargetGlobalReplacements();
1066 if (
Config.EmitLLVMUsedMetaInfo.value_or(
false)) {
1067 std::vector<WeakTrackingVH> LLVMCompilerUsed = {
1068 M.getGlobalVariable(
"__openmp_nvptx_data_transfer_temporary_storage")};
1069 emitUsed(
"llvm.compiler.used", LLVMCompilerUsed);
1079 assert(Original && Replacement &&
1080 "Null values provided to registerDeclareTargetGlobalReplacement");
1084void OpenMPIRBuilder::applyDeclareTargetGlobalReplacements() {
1090 "A null value was inserted into DeclareTargetGlobalReplacements");
1094 if (!OldGV || !NewGV)
1128 for (
unsigned I = 0, E =
PHI->getNumIncomingValues();
I < E; ++
I) {
1129 if (
PHI->getIncomingValue(
I) != OldGV)
1134 Builder.SetCurrentDebugLocation(
PHI->getDebugLoc());
1136 PHI->setIncomingValue(
I, EdgeLoad);
1142 Builder.SetCurrentDebugLocation(Insn->getDebugLoc());
1158 "Non-default address space declare target global");
1160 unsigned DestAS = ASC->getType()->getPointerAddressSpace();
1161 if (DestAS == 0 && NewGVAS != OldGVAS) {
1162 ASC->replaceAllUsesWith(
Load);
1163 ASC->eraseFromParent();
1168 Insn->replaceUsesOfWith(OldGV,
Load);
1184 ConstantInt::get(I32Ty,
Value), Name);
1197 for (
unsigned I = 0, E =
List.size();
I != E; ++
I)
1201 if (UsedArray.
empty())
1208 GV->setSection(
"llvm.metadata");
1214 auto *Int8Ty =
Builder.getInt8Ty();
1217 ConstantInt::get(Int8Ty, Mode),
Twine(KernelName,
"_exec_mode"));
1225 unsigned Reserve2Flags) {
1227 LocFlags |= OMP_IDENT_FLAG_KMPC;
1234 ConstantInt::get(Int32,
uint32_t(LocFlags)),
1235 ConstantInt::get(Int32, Reserve2Flags),
1236 ConstantInt::get(Int32, SrcLocStrSize), SrcLocStr};
1238 size_t SrcLocStrArgIdx = 4;
1239 if (OpenMPIRBuilder::Ident->getElementType(SrcLocStrArgIdx)
1243 SrcLocStr, OpenMPIRBuilder::Ident->getElementType(SrcLocStrArgIdx));
1250 if (
GV.getValueType() == OpenMPIRBuilder::Ident &&
GV.hasInitializer())
1251 if (
GV.getInitializer() == Initializer)
1256 M, OpenMPIRBuilder::Ident,
1259 M.getDataLayout().getDefaultGlobalsAddressSpace());
1271 SrcLocStrSize = LocStr.
size();
1280 if (
GV.isConstant() &&
GV.hasInitializer() &&
1281 GV.getInitializer() == Initializer)
1284 SrcLocStr =
Builder.CreateGlobalString(
1285 LocStr,
"",
M.getDataLayout().getDefaultGlobalsAddressSpace(),
1293 unsigned Line,
unsigned Column,
1299 Buffer.
append(FunctionName);
1301 Buffer.
append(std::to_string(Line));
1303 Buffer.
append(std::to_string(Column));
1311 StringRef UnknownLoc =
";unknown;unknown;0;0;;";
1322 !DIL->getFilename().empty() ? DIL->getFilename() :
M.getName();
1327 DIL->getColumn(), SrcLocStrSize);
1333 Loc.IP.getBlock()->getParent());
1339 "omp_global_thread_num");
1347 "expected one result pointer type per in_reduction item");
1350 if (OrigPtrs.
empty())
1351 return Builder.saveIP();
1370 for (
unsigned Idx = 0; Idx < OrigPtrs.
size(); ++Idx) {
1373 Value *OrigPtr = OrigPtrs[Idx];
1375 OrigPtrTy && OrigPtrTy->getAddressSpace() != 0)
1376 OrigPtr = Builder.CreateAddrSpaceCast(OrigPtr, PtrTy);
1378 Value *
Priv = Builder.CreateCall(GetThData, {Gtid, NullDesc, OrigPtr},
1384 ResPtrTy && ResPtrTy->getAddressSpace() != 0)
1385 Priv = Builder.CreateAddrSpaceCast(
Priv, ResultPtrTys[Idx]);
1387 MapPrivateCB(Idx,
Priv);
1394 bool ForceSimpleCall,
bool CheckCancelFlag) {
1404 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_FOR;
1407 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SECTIONS;
1410 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SINGLE;
1413 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_EXPL;
1416 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL;
1429 bool UseCancelBarrier =
1434 ? OMPRTL___kmpc_cancel_barrier
1435 : OMPRTL___kmpc_barrier),
1438 if (UseCancelBarrier && CheckCancelFlag)
1448 omp::Directive CanceledDirective) {
1453 auto *UI =
Builder.CreateUnreachable();
1461 Builder.SetInsertPoint(ElseTI);
1462 auto ElseIP =
Builder.saveIP();
1470 Builder.SetInsertPoint(ThenTI);
1472 Value *CancelKind =
nullptr;
1473 switch (CanceledDirective) {
1474#define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) \
1475 case DirectiveEnum: \
1476 CancelKind = Builder.getInt32(Value); \
1478#include "llvm/Frontend/OpenMP/OMPKinds.def"
1495 Builder.SetInsertPoint(UI->getParent());
1496 UI->eraseFromParent();
1503 omp::Directive CanceledDirective) {
1508 auto *UI =
Builder.CreateUnreachable();
1511 Value *CancelKind =
nullptr;
1512 switch (CanceledDirective) {
1513#define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) \
1514 case DirectiveEnum: \
1515 CancelKind = Builder.getInt32(Value); \
1517#include "llvm/Frontend/OpenMP/OMPKinds.def"
1534 Builder.SetInsertPoint(UI->getParent());
1535 UI->eraseFromParent();
1548 auto *KernelArgsPtr =
1549 Builder.CreateAlloca(OpenMPIRBuilder::KernelArgs,
nullptr,
"kernel_args");
1554 Builder.CreateStructGEP(OpenMPIRBuilder::KernelArgs, KernelArgsPtr,
I);
1557 M.getDataLayout().getPrefTypeAlign(KernelArgs[
I]->getType()));
1561 NumThreads, HostPtr, KernelArgsPtr};
1588 assert(OutlinedFnID &&
"Invalid outlined function ID!");
1592 Value *Return =
nullptr;
1612 Builder, AllocaIP, Return, RTLoc, DeviceID, Args.NumTeams.front(),
1613 Args.NumThreads.front(), OutlinedFnID, ArgsVector));
1620 Builder.CreateCondBr(
Failed, OffloadFailedBlock, OffloadContBlock);
1622 auto CurFn =
Builder.GetInsertBlock()->getParent();
1629 emitBlock(OffloadContBlock, CurFn,
true);
1634 Value *CancelFlag, omp::Directive CanceledDirective) {
1636 "Unexpected cancellation!");
1656 Builder.CreateCondBr(Cmp, NonCancellationBlock, CancellationBlock,
1665 Builder.SetInsertPoint(CancellationBlock);
1666 Builder.CreateBr(*FiniBBOrErr);
1669 Builder.SetInsertPoint(NonCancellationBlock, NonCancellationBlock->
begin());
1681 size_t NumArgs = OutlinedFn.
arg_size();
1682 assert((NumArgs == 2 || NumArgs == 3) &&
1683 "expected a 2-3 argument parallel outlined function");
1684 bool UseArgStruct = NumArgs == 3;
1689 {Builder.getInt16Ty(), Builder.getInt32Ty()},
1693 OutlinedFn.
getName() +
".wrapper", OMPIRBuilder->
M);
1695 WrapperFn->addParamAttr(0, Attribute::NoUndef);
1696 WrapperFn->addParamAttr(0, Attribute::ZExt);
1697 WrapperFn->addParamAttr(1, Attribute::NoUndef);
1701 Builder.SetInsertPoint(EntryBB);
1704 Value *AddrAlloca = Builder.CreateAlloca(Builder.getInt32Ty(),
1706 AddrAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1707 AddrAlloca, Builder.getPtrTy(0),
1708 AddrAlloca->
getName() +
".ascast");
1710 Value *ZeroAlloca = Builder.CreateAlloca(Builder.getInt32Ty(),
1712 ZeroAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1713 ZeroAlloca, Builder.getPtrTy(0),
1714 ZeroAlloca->
getName() +
".ascast");
1716 Value *ArgsAlloca =
nullptr;
1718 ArgsAlloca = Builder.CreateAlloca(Builder.getPtrTy(),
1719 nullptr,
"global_args");
1720 ArgsAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1721 ArgsAlloca, Builder.getPtrTy(0),
1722 ArgsAlloca->
getName() +
".ascast");
1726 Builder.CreateStore(WrapperFn->getArg(1), AddrAlloca);
1727 Builder.CreateStore(Builder.getInt32(0), ZeroAlloca);
1731 llvm::omp::RuntimeFunction::OMPRTL___kmpc_get_shared_variables),
1739 Value *StructArg = Builder.CreateLoad(Builder.getPtrTy(), ArgsAlloca);
1740 StructArg = Builder.CreateInBoundsGEP(Builder.getPtrTy(), StructArg,
1741 {Builder.getInt64(0)});
1742 StructArg = Builder.CreateLoad(Builder.getPtrTy(), StructArg,
"structArg");
1743 Args.push_back(StructArg);
1747 Builder.CreateCall(&OutlinedFn, Args);
1748 Builder.CreateRetVoid();
1763 "Expected at least tid and bounded tid as arguments");
1764 unsigned NumCapturedVars = OutlinedFn.
arg_size() - 2;
1772 OutlinedFn.
addFnAttr(Attribute::NoUnwind);
1775 assert(CI &&
"Expected call instruction to outlined function");
1776 CI->
getParent()->setName(
"omp_parallel");
1778 Builder.SetInsertPoint(CI);
1779 Type *PtrTy = OMPIRBuilder->VoidPtr;
1782 OpenMPIRBuilder ::InsertPointTy CurrentIP = Builder.saveIP();
1786 Value *Args = ArgsAlloca;
1790 Args = Builder.CreatePointerCast(ArgsAlloca, PtrTy);
1791 Builder.restoreIP(CurrentIP);
1794 for (
unsigned Idx = 0; Idx < NumCapturedVars; Idx++) {
1796 Value *StoreAddress = Builder.CreateConstInBoundsGEP2_64(
1798 Builder.CreateStore(V, StoreAddress);
1802 IfCondition ? Builder.CreateSExtOrTrunc(IfCondition, OMPIRBuilder->Int32)
1803 : Builder.getInt32(1);
1804 Value *NumThreadsArg =
1805 NumThreads ? Builder.CreateZExtOrTrunc(NumThreads, OMPIRBuilder->Int32)
1806 : Builder.getInt32(-1);
1816 Value *Parallel60CallArgs[] = {
1821 Builder.getInt32(-1),
1825 Builder.getInt64(NumCapturedVars),
1826 Builder.getInt32(0)};
1834 << *Builder.GetInsertBlock()->getParent() <<
"\n");
1837 Builder.SetInsertPoint(PrivTID);
1839 Builder.CreateStore(Builder.CreateLoad(OMPIRBuilder->Int32, OutlinedAI),
1846 I->eraseFromParent();
1869 if (!
F->hasMetadata(LLVMContext::MD_callback)) {
1877 F->addMetadata(LLVMContext::MD_callback,
1886 OutlinedFn.
addFnAttr(Attribute::NoUnwind);
1889 "Expected at least tid and bounded tid as arguments");
1890 unsigned NumCapturedVars = OutlinedFn.
arg_size() - 2;
1893 CI->
getParent()->setName(
"omp_parallel");
1894 Builder.SetInsertPoint(CI);
1897 Value *ForkCallArgs[] = {Ident, Builder.getInt32(NumCapturedVars),
1901 RealArgs.
append(std::begin(ForkCallArgs), std::end(ForkCallArgs));
1903 Value *
Cond = Builder.CreateSExtOrTrunc(IfCondition, OMPIRBuilder->Int32);
1910 auto PtrTy = OMPIRBuilder->VoidPtr;
1911 if (IfCondition && NumCapturedVars == 0) {
1919 << *Builder.GetInsertBlock()->getParent() <<
"\n");
1922 Builder.SetInsertPoint(PrivTID);
1924 Builder.CreateStore(Builder.CreateLoad(OMPIRBuilder->Int32, OutlinedAI),
1931 I->eraseFromParent();
1939 Value *NumThreads, omp::ProcBindKind ProcBind,
bool IsCancellable) {
1948 const bool NeedThreadID = NumThreads ||
Config.isTargetDevice() ||
1949 (ProcBind != OMP_PROC_BIND_default);
1956 bool ArgsInZeroAddressSpace =
Config.isTargetDevice();
1960 if (NumThreads && !
Config.isTargetDevice()) {
1963 Builder.CreateIntCast(NumThreads, Int32,
false)};
1968 if (ProcBind != OMP_PROC_BIND_default) {
1972 ConstantInt::get(Int32,
unsigned(ProcBind),
true)};
1994 Builder.CreateAlloca(Int32,
nullptr,
"zero.addr");
1997 if (ArgsInZeroAddressSpace &&
M.getDataLayout().getAllocaAddrSpace() != 0) {
2000 TIDAddrAlloca, PointerType ::get(
M.getContext(), 0),
"tid.addr.ascast");
2004 PointerType ::get(
M.getContext(), 0),
2005 "zero.addr.ascast");
2029 if (IP.getBlock()->end() == IP.getPoint()) {
2035 assert(IP.getBlock()->getTerminator()->getNumSuccessors() == 1 &&
2036 IP.getBlock()->getTerminator()->getSuccessor(0) == PRegExitBB &&
2037 "Unexpected insertion point for finalization call!");
2049 Builder.CreateAlloca(Int32,
nullptr,
"tid.addr.local");
2055 Builder.CreateLoad(Int32, ZeroAddr,
"zero.addr.use");
2073 LLVM_DEBUG(
dbgs() <<
"Before body codegen: " << *OuterFn <<
"\n");
2076 assert(BodyGenCB &&
"Expected body generation callback!");
2078 if (
Error Err = BodyGenCB(InnerAllocaIP, CodeGenIP, PRegExitBB))
2081 LLVM_DEBUG(
dbgs() <<
"After body codegen: " << *OuterFn <<
"\n");
2085 bool UsesDeviceSharedMemory =
2087 std::unique_ptr<OutlineInfo> OI =
2088 UsesDeviceSharedMemory
2089 ? std::make_unique<DeviceSharedMemOutlineInfo>(*
this)
2090 : std::make_unique<OutlineInfo>();
2092 if (
Config.isTargetDevice()) {
2094 OI->PostOutlineCB = [=, ToBeDeletedVec =
2095 std::move(ToBeDeleted)](
Function &OutlinedFn) {
2097 IfCondition, NumThreads, PrivTID, PrivTIDAddr,
2098 ThreadID, ToBeDeletedVec);
2102 OI->PostOutlineCB = [=, ToBeDeletedVec =
2103 std::move(ToBeDeleted)](
Function &OutlinedFn) {
2105 PrivTID, PrivTIDAddr, ToBeDeletedVec);
2109 OI->FixUpNonEntryAllocas =
true;
2110 OI->OuterAllocBB = OuterAllocaBlock;
2111 OI->EntryBB = PRegEntryBB;
2112 OI->ExitBB = PRegExitBB;
2113 OI->OuterDeallocBBs.reserve(OuterDeallocBlocks.
size());
2114 copy(OuterDeallocBlocks, OI->OuterDeallocBBs.
end());
2118 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
2130 ".omp_par", ArgsInZeroAddressSpace);
2135 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
2137 Extractor.findInputsOutputs(Inputs, Outputs, SinkingCands,
2142 return GV->getValueType() == OpenMPIRBuilder::Ident;
2147 LLVM_DEBUG(
dbgs() <<
"Before privatization: " << *OuterFn <<
"\n");
2153 if (&V == TIDAddr || &V == ZeroAddr) {
2154 OI->ExcludeArgsFromAggregate.push_back(&V);
2159 for (
Use &U : V.uses())
2161 if (ParallelRegionBlockSet.
count(UserI->getParent()))
2171 if (!V.getType()->isPointerTy()) {
2175 Builder.restoreIP(OuterAllocIP);
2177 if (UsesDeviceSharedMemory) {
2180 V.getName() +
".reloaded");
2181 for (
BasicBlock *DeallocBlock : OuterDeallocBlocks)
2183 InsertPointTy(DeallocBlock, DeallocBlock->getFirstInsertionPt()),
2186 Ptr =
Builder.CreateAlloca(V.getType(),
nullptr,
2187 V.getName() +
".reloaded");
2192 Builder.SetInsertPoint(InsertBB,
2197 Builder.restoreIP(InnerAllocaIP);
2198 Inner =
Builder.CreateLoad(V.getType(), Ptr);
2201 Value *ReplacementValue =
nullptr;
2204 ReplacementValue = PrivTID;
2207 PrivCB(InnerAllocaIP,
Builder.saveIP(), V, *Inner, ReplacementValue);
2215 assert(ReplacementValue &&
2216 "Expected copy/create callback to set replacement value!");
2217 if (ReplacementValue == &V)
2222 UPtr->set(ReplacementValue);
2247 for (
Value *Output : Outputs)
2251 "OpenMP outlining should not produce live-out values!");
2253 LLVM_DEBUG(
dbgs() <<
"After privatization: " << *OuterFn <<
"\n");
2255 for (
auto *BB : Blocks)
2256 dbgs() <<
" PBR: " << BB->getName() <<
"\n";
2264 assert(FiniInfo.DK == OMPD_parallel &&
2265 "Unexpected finalization stack state!");
2276 Builder.CreateBr(*FiniBBOrErr);
2280 Term->eraseFromParent();
2286 InsertPointTy AfterIP(UI->getParent(), UI->getParent()->end());
2287 UI->eraseFromParent();
2319 Value *Severity = ConstantInt::get(Int32, IsFatal ? 2 : 1);
2321 Value *Args[] = {Ident, Severity, MessageArg};
2350 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr));
2352 Builder.CreateStore(DepValPtr, Addr);
2355 DependInfo, Entry,
static_cast<unsigned int>(RTLDependInfoFields::Len));
2357 ConstantInt::get(SizeTy,
2362 DependInfo, Entry,
static_cast<unsigned int>(RTLDependInfoFields::Flags));
2364 static_cast<unsigned int>(Dep.
DepKind)),
2377 if (Dependencies.
empty())
2397 Type *DependInfo = OMPBuilder.DependInfo;
2399 Value *DepArray =
nullptr;
2401 Builder.SetInsertPoint(
2405 DepArray = Builder.CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
2407 Builder.restoreIP(OldIP);
2409 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies)) {
2411 Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
2435 Value *DepArray =
nullptr;
2436 Type *DepArrayTy =
nullptr;
2437 Value *NumDeps =
nullptr;
2440 NumDeps = Dependencies.
NumDeps;
2441 }
else if (!Dependencies.
Deps.empty()) {
2444 Builder.GetInsertBlock()->getParent()->getEntryBlock();
2448 DepArray =
Builder.CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
2449 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
2452 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies.
Deps)) {
2454 Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
2468 ConstantInt::get(
Builder.getInt32Ty(), 0),
2470 ConstantInt::get(
Builder.getInt32Ty(),
false)};
2473 omp::RuntimeFunction::OMPRTL___kmpc_omp_taskwait_deps_51),
2483 unsigned ProgramAddressSpace = M.getDataLayout().getProgramAddressSpace();
2495 auto *VoidPtrTy =
PointerType::get(Builder.getContext(), ProgramAddressSpace);
2498 Builder.getVoidTy(), {VoidPtrTy, VoidPtrTy, Builder.getInt32Ty()},
2502 "omp_taskloop_dup", M);
2505 Value *LastprivateFlagArg = DupFunction->
getArg(2);
2506 DestTaskArg->
setName(
"dest_task");
2507 SrcTaskArg->
setName(
"src_task");
2508 LastprivateFlagArg->
setName(
"lastprivate_flag");
2511 Builder.SetInsertPoint(
2514 auto GetTaskContextPtrFromArg = [&](
Value *Arg) ->
Value * {
2515 Type *TaskWithPrivatesTy =
2517 Value *TaskPrivates = Builder.CreateGEP(
2518 TaskWithPrivatesTy, Arg, {Builder.getInt32(0), Builder.getInt32(1)});
2519 Value *ContextPtr = Builder.CreateGEP(
2520 PrivatesTy, TaskPrivates,
2521 {Builder.getInt32(0), Builder.getInt32(PrivatesIndex)});
2525 Value *DestTaskContextPtr = GetTaskContextPtrFromArg(DestTaskArg);
2526 Value *SrcTaskContextPtr = GetTaskContextPtrFromArg(SrcTaskArg);
2528 DestTaskContextPtr->
setName(
"destPtr");
2529 SrcTaskContextPtr->
setName(
"srcPtr");
2534 Expected<IRBuilderBase::InsertPoint> AfterIPOrError =
2535 DupCB(AllocaIP, CodeGenIP, DestTaskContextPtr, SrcTaskContextPtr);
2536 if (!AfterIPOrError)
2538 Builder.restoreIP(*AfterIPOrError);
2548 llvm::function_ref<llvm::Expected<llvm::CanonicalLoopInfo *>()> LoopInfo,
2550 Value *GrainSize,
bool NoGroup,
int Sched,
Value *Final,
bool Mergeable,
2552 Value *TaskContextStructPtrVal) {
2557 uint32_t SrcLocStrSize;
2573 if (
Error Err = BodyGenCB(TaskloopAllocaIP, TaskloopBodyIP, TaskloopExitBB))
2576 llvm::Expected<llvm::CanonicalLoopInfo *> result = LoopInfo();
2581 llvm::CanonicalLoopInfo *CLI = result.
get();
2582 auto OI = std::make_unique<OutlineInfo>();
2583 OI->EntryBB = TaskloopAllocaBB;
2584 OI->OuterAllocBB = AllocaIP.getBlock();
2585 OI->ExitBB = TaskloopExitBB;
2586 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2587 copy(DeallocBlocks, OI->OuterDeallocBBs.end());
2590 SmallVector<Instruction *> ToBeDeleted;
2593 Builder, AllocaIP, ToBeDeleted, TaskloopAllocaIP,
"global.tid",
false));
2595 TaskloopAllocaIP,
"lb",
false,
true);
2597 TaskloopAllocaIP,
"ub",
false,
true);
2599 TaskloopAllocaIP,
"step",
false,
true);
2602 OI->Inputs.insert(FakeLB);
2603 OI->Inputs.insert(FakeUB);
2604 OI->Inputs.insert(FakeStep);
2605 if (TaskContextStructPtrVal)
2606 OI->Inputs.insert(TaskContextStructPtrVal);
2607 assert(((TaskContextStructPtrVal && DupCB) ||
2608 (!TaskContextStructPtrVal && !DupCB)) &&
2609 "Task context struct ptr and duplication callback must be both set "
2615 unsigned ProgramAddressSpace =
M.getDataLayout().getProgramAddressSpace();
2619 {FakeLB->getType(), FakeUB->getType(), FakeStep->getType(), PointerTy});
2620 Expected<Value *> TaskDupFnOrErr = createTaskDuplicationFunction(
2623 if (!TaskDupFnOrErr) {
2626 Value *TaskDupFn = *TaskDupFnOrErr;
2628 OI->PostOutlineCB = [
this, Ident, LBVal, UBVal, StepVal, Untied,
2629 TaskloopAllocaBB, CLI, TaskDupFn, ToBeDeleted, IfCond,
2630 GrainSize, NoGroup, Sched, FakeLB, FakeUB, FakeStep,
2631 FakeSharedsTy, Final, Mergeable, Priority,
2632 NumOfCollapseLoops](
Function &OutlinedFn)
mutable {
2634 assert(OutlinedFn.hasOneUse() &&
2635 "there must be a single user for the outlined function");
2642 Value *CastedLBVal =
2643 Builder.CreateIntCast(LBVal,
Builder.getInt64Ty(),
true,
"lb64");
2644 Value *CastedUBVal =
2645 Builder.CreateIntCast(UBVal,
Builder.getInt64Ty(),
true,
"ub64");
2646 Value *CastedStepVal =
2647 Builder.CreateIntCast(StepVal,
Builder.getInt64Ty(),
true,
"step64");
2649 Builder.SetInsertPoint(StaleCI);
2662 Builder.CreateCall(TaskgroupFn, {Ident, ThreadID});
2683 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
2685 AllocaInst *ArgStructAlloca =
2687 assert(ArgStructAlloca &&
2688 "Unable to find the alloca instruction corresponding to arguments "
2689 "for extracted function");
2690 std::optional<TypeSize> ArgAllocSize =
2693 "Unable to determine size of arguments for extracted function");
2694 Value *SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
2699 CallInst *TaskData =
Builder.CreateCall(
2700 TaskAllocFn, {Ident, ThreadID,
Flags,
2701 TaskSize, SharedsSize,
2706 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
2712 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(0)});
2715 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(1)});
2718 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(2)});
2724 IfCond ?
Builder.CreateIntCast(IfCond,
Builder.getInt32Ty(),
true)
2730 Value *GrainSizeVal =
2731 GrainSize ?
Builder.CreateIntCast(GrainSize,
Builder.getInt64Ty(),
true)
2733 Value *TaskDup = TaskDupFn;
2735 Value *
Args[] = {Ident, ThreadID, TaskData, IfCondVal, Lb, Ub,
2736 Loadstep, NoGroupVal, SchedVal, GrainSizeVal, TaskDup};
2741 Builder.CreateCall(TaskloopFn, Args);
2748 Builder.CreateCall(EndTaskgroupFn, {Ident, ThreadID});
2753 Builder.SetInsertPoint(TaskloopAllocaBB, TaskloopAllocaBB->begin());
2755 LoadInst *SharedsOutlined =
2756 Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
2757 OutlinedFn.getArg(1)->replaceUsesWithIf(
2759 [SharedsOutlined](Use &U) {
return U.getUser() != SharedsOutlined; });
2762 Type *IVTy =
IV->getType();
2768 Value *TaskLB =
nullptr;
2769 Value *TaskUB =
nullptr;
2770 Value *TaskStep =
nullptr;
2771 Value *LoadTaskLB =
nullptr;
2772 Value *LoadTaskUB =
nullptr;
2773 Value *LoadTaskStep =
nullptr;
2774 for (Instruction &
I : *TaskloopAllocaBB) {
2775 if (
I.getOpcode() == Instruction::GetElementPtr) {
2778 switch (CI->getZExtValue()) {
2790 }
else if (
I.getOpcode() == Instruction::Load) {
2792 if (
Load.getPointerOperand() == TaskLB) {
2793 assert(TaskLB !=
nullptr &&
"Expected value for TaskLB");
2795 }
else if (
Load.getPointerOperand() == TaskUB) {
2796 assert(TaskUB !=
nullptr &&
"Expected value for TaskUB");
2798 }
else if (
Load.getPointerOperand() == TaskStep) {
2799 assert(TaskStep !=
nullptr &&
"Expected value for TaskStep");
2805 Builder.SetInsertPoint(CLI->getPreheader()->getTerminator());
2807 assert(LoadTaskLB !=
nullptr &&
"Expected value for LoadTaskLB");
2808 assert(LoadTaskUB !=
nullptr &&
"Expected value for LoadTaskUB");
2809 assert(LoadTaskStep !=
nullptr &&
"Expected value for LoadTaskStep");
2811 Builder.CreateSub(LoadTaskUB, LoadTaskLB), LoadTaskStep);
2812 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One,
"trip_cnt");
2813 Value *CastedTripCount =
Builder.CreateIntCast(TripCount, IVTy,
true);
2814 Value *CastedTaskLB =
Builder.CreateIntCast(LoadTaskLB, IVTy,
true);
2816 CLI->setTripCount(CastedTripCount);
2818 Builder.SetInsertPoint(CLI->getBody(),
2819 CLI->getBody()->getFirstInsertionPt());
2821 if (NumOfCollapseLoops > 1) {
2827 Builder.CreateSub(CastedTaskLB, ConstantInt::get(IVTy, 1)));
2830 for (
auto IVUse = CLI->getIndVar()->uses().begin();
2831 IVUse != CLI->getIndVar()->uses().end(); IVUse++) {
2832 User *IVUser = IVUse->getUser();
2834 if (
Op->getOpcode() == Instruction::URem ||
2835 Op->getOpcode() == Instruction::UDiv) {
2840 for (User *User : UsersToReplace) {
2841 User->replaceUsesOfWith(CLI->getIndVar(), IVPlusTaskLB);
2858 assert(CLI->getIndVar()->getNumUses() == 3 &&
2859 "Canonical loop should have exactly three uses of the ind var");
2860 for (User *IVUser : CLI->getIndVar()->users()) {
2862 if (
Mul->getOpcode() == Instruction::Mul) {
2863 for (User *MulUser :
Mul->users()) {
2865 if (
Add->getOpcode() == Instruction::Add) {
2866 Add->setOperand(1, CastedTaskLB);
2875 FakeLB->replaceAllUsesWith(CastedLBVal);
2876 FakeUB->replaceAllUsesWith(CastedUBVal);
2877 FakeStep->replaceAllUsesWith(CastedStepVal);
2879 I->eraseFromParent();
2884 Builder.SetInsertPoint(TaskloopExitBB, TaskloopExitBB->
begin());
2890 M.getContext(),
M.getDataLayout().getPointerSizeInBits());
2900 bool Mergeable,
Value *EventHandle,
Value *Priority) {
2932 if (
Error Err = BodyGenCB(TaskAllocaIP, TaskBodyIP, TaskExitBB))
2935 auto OI = std::make_unique<OutlineInfo>();
2936 OI->EntryBB = TaskAllocaBB;
2937 OI->OuterAllocBB = AllocaIP.
getBlock();
2938 OI->ExitBB = TaskExitBB;
2939 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2940 copy(DeallocBlocks, OI->OuterDeallocBBs.
end());
2945 Builder, AllocaIP, ToBeDeleted, TaskAllocaIP,
"global.tid",
false));
2947 OI->PostOutlineCB = [
this, Ident, Tied, Final, IfCondition, Dependencies,
2948 Affinities, Mergeable, Priority, EventHandle,
2950 ToBeDeleted](
Function &OutlinedFn)
mutable {
2952 assert(OutlinedFn.hasOneUse() &&
2953 "there must be a single user for the outlined function");
2958 bool HasShareds = StaleCI->
arg_size() > 1;
2959 Builder.SetInsertPoint(StaleCI);
2984 bool UseMergedIf0Path = ConstIfCondition && ConstIfCondition->isZero();
2988 Flags =
Builder.CreateOr(FinalFlag, Flags);
2991 if (Mergeable || UseMergedIf0Path)
3003 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
3012 assert(ArgStructAlloca &&
3013 "Unable to find the alloca instruction corresponding to arguments "
3014 "for extracted function");
3015 std::optional<TypeSize> ArgAllocSize =
3018 "Unable to determine size of arguments for extracted function");
3019 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
3025 TaskAllocFn, {Ident, ThreadID, Flags,
3026 TaskSize, SharedsSize,
3029 if (Affinities.
Count && Affinities.
Info) {
3031 OMPRTL___kmpc_omp_reg_task_with_affinity);
3042 OMPRTL___kmpc_task_allow_completion_event);
3046 Builder.CreatePointerBitCastOrAddrSpaceCast(EventHandle,
3048 EventVal =
Builder.CreatePtrToInt(EventVal,
Builder.getInt64Ty());
3049 Builder.CreateStore(EventVal, EventHandleAddr);
3055 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
3070 Constant *Zero = ConstantInt::get(Int32Ty, 0);
3074 Builder.CreateInBoundsGEP(TaskPtr, TaskData, {Zero, Zero});
3077 VoidPtr, VoidPtr,
Builder.getInt32Ty(), VoidPtr, VoidPtr);
3079 TaskStructType, TaskGEP, {Zero, ConstantInt::get(Int32Ty, 4)});
3082 Value *CmplrData =
Builder.CreateInBoundsGEP(CmplrStructType,
3083 PriorityData, {Zero, Zero});
3084 Builder.CreateStore(Priority, CmplrData);
3087 Value *DepArray =
nullptr;
3088 Value *NumDeps =
nullptr;
3091 NumDeps = Dependencies.
NumDeps;
3092 }
else if (!Dependencies.
Deps.empty()) {
3094 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
3114 if (IfCondition && !UseMergedIf0Path) {
3119 Builder.GetInsertPoint()->getParent()->getTerminator();
3120 Instruction *ThenTI = IfTerminator, *ElseTI =
nullptr;
3121 Builder.SetInsertPoint(IfTerminator);
3124 Builder.SetInsertPoint(ElseTI);
3131 {Ident, ThreadID, NumDeps, DepArray,
3132 ConstantInt::get(
Builder.getInt32Ty(), 0),
3147 Builder.SetInsertPoint(ThenTI);
3155 {Ident, ThreadID, TaskData, NumDeps, DepArray,
3156 ConstantInt::get(
Builder.getInt32Ty(), 0),
3167 Builder.SetInsertPoint(TaskAllocaBB, TaskAllocaBB->
begin());
3169 LoadInst *Shareds =
Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
3170 OutlinedFn.getArg(1)->replaceUsesWithIf(
3171 Shareds, [Shareds](
Use &U) {
return U.getUser() != Shareds; });
3177 Builder.ClearInsertionPoint();
3179 I->eraseFromParent();
3183 Builder.SetInsertPoint(TaskExitBB, TaskExitBB->
begin());
3205 if (
Error Err = BodyGenCB(AllocaIP,
Builder.saveIP(), DeallocBlocks))
3208 Builder.SetInsertPoint(TaskgroupExitBB);
3251 unsigned CaseNumber = 0;
3252 for (
auto SectionCB : SectionCBs) {
3254 M.getContext(),
"omp_section_loop.body.case", CurFn,
Continue);
3256 Builder.SetInsertPoint(CaseBB);
3271 Value *LB = ConstantInt::get(I32Ty, 0);
3272 Value *UB = ConstantInt::get(I32Ty, SectionCBs.
size());
3273 Value *ST = ConstantInt::get(I32Ty, 1);
3275 Loc, LoopBodyGenCB, LB, UB, ST,
true,
false, AllocaIP,
"section_loop");
3280 applyStaticWorkshareLoop(
Loc.DL, *
LoopInfo, AllocaIP,
3281 WorksharingLoopType::ForStaticLoop, !IsNowait);
3287 assert(LoopFini &&
"Bad structure of static workshare loop finalization");
3291 assert(FiniInfo.DK == OMPD_sections &&
3292 "Unexpected finalization stack state!");
3293 if (
Error Err = FiniInfo.mergeFiniBB(
Builder, LoopFini))
3307 if (IP.getBlock()->end() != IP.getPoint())
3318 auto *CaseBB =
Loc.IP.getBlock();
3319 auto *CondBB = CaseBB->getSinglePredecessor()->getSinglePredecessor();
3320 auto *ExitBB = CondBB->getTerminator()->getSuccessor(1);
3326 Directive OMPD = Directive::OMPD_sections;
3329 return EmitOMPInlinedRegion(OMPD,
nullptr,
nullptr, BodyGenCB, FiniCBWrapper,
3340Value *OpenMPIRBuilder::getGPUThreadID() {
3343 OMPRTL___kmpc_get_hardware_thread_id_in_block),
3347Value *OpenMPIRBuilder::getGPUWarpSize() {
3352Value *OpenMPIRBuilder::getNVPTXWarpID() {
3353 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3354 return Builder.CreateAShr(getGPUThreadID(), LaneIDBits,
"nvptx_warp_id");
3357Value *OpenMPIRBuilder::getNVPTXLaneID() {
3358 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3359 assert(LaneIDBits < 32 &&
"Invalid LaneIDBits size in NVPTX device.");
3360 unsigned LaneIDMask = ~0
u >> (32u - LaneIDBits);
3361 return Builder.CreateAnd(getGPUThreadID(),
Builder.getInt32(LaneIDMask),
3368 uint64_t FromSize =
M.getDataLayout().getTypeStoreSize(FromType);
3369 uint64_t ToSize =
M.getDataLayout().getTypeStoreSize(ToType);
3370 assert(FromSize > 0 &&
"From size must be greater than zero");
3371 assert(ToSize > 0 &&
"To size must be greater than zero");
3372 if (FromType == ToType)
3374 if (FromSize == ToSize)
3375 return Builder.CreateBitCast(From, ToType);
3377 return Builder.CreateIntCast(From, ToType,
true);
3383 Value *ValCastItem =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3384 CastItem,
Builder.getPtrTy(0));
3385 Builder.CreateStore(From, ValCastItem);
3386 return Builder.CreateLoad(ToType, CastItem);
3393 uint64_t Size =
M.getDataLayout().getTypeStoreSize(ElementType);
3394 assert(
Size <= 8 &&
"Unsupported bitwidth in shuffle instruction");
3398 Value *ElemCast = castValueToType(AllocaIP, Element, CastTy);
3400 Builder.CreateIntCast(getGPUWarpSize(),
Builder.getInt16Ty(),
true);
3402 Size <= 4 ? RuntimeFunction::OMPRTL___kmpc_shuffle_int32
3403 : RuntimeFunction::OMPRTL___kmpc_shuffle_int64);
3404 Value *WarpSizeCast =
3406 Value *ShuffleCall =
3411 return castValueToType(AllocaIP, ShuffleCall, ElementType);
3418 uint64_t Size =
M.getDataLayout().getTypeStoreSize(ElemType);
3430 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3431 Value *ElemPtr = DstAddr;
3432 Value *Ptr = SrcAddr;
3433 for (
unsigned IntSize = 8; IntSize >= 1; IntSize /= 2) {
3437 Ptr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3440 Builder.CreateGEP(ElemType, SrcAddr, {ConstantInt::get(IndexTy, 1)});
3441 ElemPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3445 if ((
Size / IntSize) > 1) {
3446 Value *PtrEnd =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3447 SrcAddrGEP,
Builder.getPtrTy());
3464 Builder.CreatePointerBitCastOrAddrSpaceCast(Ptr,
Builder.getPtrTy()));
3466 Builder.CreateICmpSGT(PtrDiff,
Builder.getInt64(IntSize - 1)), ThenBB,
3469 Value *Res = createRuntimeShuffleFunction(
3472 IntType, Ptr,
M.getDataLayout().getPrefTypeAlign(ElemType)),
3474 Builder.CreateAlignedStore(Res, ElemPtr,
3475 M.getDataLayout().getPrefTypeAlign(ElemType));
3477 Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3478 Value *LocalElemPtr =
3479 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3487 Value *Res = createRuntimeShuffleFunction(
3488 AllocaIP,
Builder.CreateLoad(IntType, Ptr), IntType,
Offset);
3489 Builder.CreateStore(Res, ElemPtr);
3490 Ptr =
Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3492 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3498Error OpenMPIRBuilder::emitReductionListCopy(
3503 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3504 Value *RemoteLaneOffset = CopyOptions.RemoteLaneOffset;
3508 for (
auto En :
enumerate(ReductionInfos)) {
3510 Value *SrcElementAddr =
nullptr;
3511 AllocaInst *DestAlloca =
nullptr;
3512 Value *DestElementAddr =
nullptr;
3513 Value *DestElementPtrAddr =
nullptr;
3515 bool ShuffleInElement =
false;
3518 bool UpdateDestListPtr =
false;
3522 ReductionArrayTy, SrcBase,
3523 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3524 SrcElementAddr =
Builder.CreateLoad(
Builder.getPtrTy(), SrcElementPtrAddr);
3528 DestElementPtrAddr =
Builder.CreateInBoundsGEP(
3529 ReductionArrayTy, DestBase,
3530 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3531 bool IsByRefElem = (!IsByRef.
empty() && IsByRef[En.index()]);
3537 Type *DestAllocaType =
3538 IsByRefElem ? RI.ByRefAllocatedType : RI.ElementType;
3539 DestAlloca =
Builder.CreateAlloca(DestAllocaType,
nullptr,
3540 ".omp.reduction.element");
3542 M.getDataLayout().getPrefTypeAlign(DestAllocaType));
3543 DestElementAddr = DestAlloca;
3546 DestElementAddr->
getName() +
".ascast");
3548 ShuffleInElement =
true;
3549 UpdateDestListPtr =
true;
3561 if (ShuffleInElement) {
3562 Type *ShuffleType = RI.ElementType;
3563 Value *ShuffleSrcAddr = SrcElementAddr;
3564 Value *ShuffleDestAddr = DestElementAddr;
3565 AllocaInst *LocalStorage =
nullptr;
3568 assert(RI.ByRefElementType &&
"Expected by-ref element type to be set");
3569 assert(RI.ByRefAllocatedType &&
3570 "Expected by-ref allocated type to be set");
3575 ShuffleType = RI.ByRefElementType;
3577 if (RI.DataPtrPtrGen) {
3580 Builder.saveIP(), ShuffleSrcAddr, ShuffleSrcAddr);
3583 return GenResult.takeError();
3592 LocalStorage =
Builder.CreateAlloca(ShuffleType);
3594 ShuffleDestAddr = LocalStorage;
3599 ShuffleDestAddr = DestElementAddr;
3603 shuffleAndStore(AllocaIP, ShuffleSrcAddr, ShuffleDestAddr, ShuffleType,
3604 RemoteLaneOffset, ReductionArrayTy, IsByRefElem);
3606 if (IsByRefElem && RI.DataPtrPtrGen) {
3608 Value *DestDescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3609 DestAlloca,
Builder.getPtrTy(),
".ascast");
3612 DestDescriptorAddr, LocalStorage, SrcElementAddr,
3613 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
3616 return GenResult.takeError();
3619 switch (RI.EvaluationKind) {
3621 Value *Elem =
Builder.CreateLoad(RI.ElementType, SrcElementAddr);
3623 Builder.CreateStore(Elem, DestElementAddr);
3627 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3628 RI.ElementType, SrcElementAddr, 0, 0,
".realp");
3630 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
3632 RI.ElementType, SrcElementAddr, 0, 1,
".imagp");
3634 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
3636 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3637 RI.ElementType, DestElementAddr, 0, 0,
".realp");
3638 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
3639 RI.ElementType, DestElementAddr, 0, 1,
".imagp");
3640 Builder.CreateStore(SrcReal, DestRealPtr);
3641 Builder.CreateStore(SrcImg, DestImgPtr);
3646 M.getDataLayout().getTypeStoreSize(RI.ElementType));
3648 DestElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3649 SrcElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3661 if (UpdateDestListPtr) {
3662 Value *CastDestAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3663 DestElementAddr,
Builder.getPtrTy(),
3664 DestElementAddr->
getName() +
".ascast");
3665 Builder.CreateStore(CastDestAddr, DestElementPtrAddr);
3672Expected<Function *> OpenMPIRBuilder::emitInterWarpCopyFunction(
3675 IRBuilder<>::InsertPointGuard IPG(
Builder);
3676 LLVMContext &Ctx =
M.getContext();
3678 Builder.getVoidTy(), {Builder.getPtrTy(), Builder.getInt32Ty()},
3682 "_omp_reduction_inter_warp_copy_func", &
M);
3688 Builder.SetInsertPoint(EntryBB);
3706 StringRef TransferMediumName =
3707 "__openmp_nvptx_data_transfer_temporary_storage";
3708 GlobalVariable *TransferMedium =
M.getGlobalVariable(TransferMediumName);
3709 unsigned WarpSize =
Config.getGridValue().GV_Warp_Size;
3711 if (!TransferMedium) {
3712 TransferMedium =
new GlobalVariable(
3720 Value *GPUThreadID = getGPUThreadID();
3722 Value *LaneID = getNVPTXLaneID();
3724 Value *WarpID = getNVPTXWarpID();
3728 Builder.GetInsertBlock()->getFirstInsertionPt());
3732 AllocaInst *ReduceListAlloca =
Builder.CreateAlloca(
3733 Arg0Type,
nullptr, ReduceListArg->
getName() +
".addr");
3734 AllocaInst *NumWarpsAlloca =
3735 Builder.CreateAlloca(Arg1Type,
nullptr, NumWarpsArg->
getName() +
".addr");
3736 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3737 ReduceListAlloca, Arg0Type, ReduceListAlloca->
getName() +
".ascast");
3738 Value *NumWarpsAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3739 NumWarpsAlloca,
Builder.getPtrTy(0),
3740 NumWarpsAlloca->
getName() +
".ascast");
3741 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
3742 Builder.CreateStore(NumWarpsArg, NumWarpsAddrCast);
3751 for (
auto En :
enumerate(ReductionInfos)) {
3757 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
3758 unsigned RealTySize =
M.getDataLayout().getTypeAllocSize(
3759 IsByRefElem ? RI.ByRefElementType : RI.ElementType);
3760 for (
unsigned TySize = 4; TySize > 0 && RealTySize > 0; TySize /= 2) {
3763 unsigned NumIters = RealTySize / TySize;
3766 Value *Cnt =
nullptr;
3767 Value *CntAddr =
nullptr;
3774 Builder.CreateAlloca(
Builder.getInt32Ty(),
nullptr,
".cnt.addr");
3776 CntAddr =
Builder.CreateAddrSpaceCast(CntAddr,
Builder.getPtrTy(),
3777 CntAddr->
getName() +
".ascast");
3789 Cnt, ConstantInt::get(
Builder.getInt32Ty(), NumIters));
3790 Builder.CreateCondBr(Cmp, BodyBB, ExitBB);
3797 omp::Directive::OMPD_unknown,
3801 return BarrierIP1.takeError();
3807 Value *IsWarpMaster =
Builder.CreateIsNull(LaneID,
"warp_master");
3808 Builder.CreateCondBr(IsWarpMaster, ThenBB, ElseBB);
3812 auto *RedListArrayTy =
3815 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3817 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3818 {ConstantInt::get(IndexTy, 0),
3819 ConstantInt::get(IndexTy, En.index())});
3823 if (IsByRefElem && RI.DataPtrPtrGen) {
3825 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
3828 return GenRes.takeError();
3839 ArrayTy, TransferMedium, {
Builder.getInt64(0), WarpID});
3844 Builder.CreateStore(Elem, MediumPtr,
3856 omp::Directive::OMPD_unknown,
3860 return BarrierIP2.takeError();
3867 Value *NumWarpsVal =
3870 Value *IsActiveThread =
3871 Builder.CreateICmpULT(GPUThreadID, NumWarpsVal,
"is_active_thread");
3872 Builder.CreateCondBr(IsActiveThread, W0ThenBB, W0ElseBB);
3879 ArrayTy, TransferMedium, {
Builder.getInt64(0), GPUThreadID});
3881 Value *TargetElemPtrPtr =
3882 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3883 {ConstantInt::get(IndexTy, 0),
3884 ConstantInt::get(IndexTy, En.index())});
3885 Value *TargetElemPtrVal =
3887 Value *TargetElemPtr = TargetElemPtrVal;
3889 if (IsByRefElem && RI.DataPtrPtrGen) {
3891 RI.DataPtrPtrGen(
Builder.saveIP(), TargetElemPtr, TargetElemPtr);
3894 return GenRes.takeError();
3896 TargetElemPtr =
Builder.CreateLoad(
Builder.getPtrTy(), TargetElemPtr);
3904 Value *SrcMediumValue =
3905 Builder.CreateLoad(CType, SrcMediumPtrVal,
true);
3906 Builder.CreateStore(SrcMediumValue, TargetElemPtr);
3916 Cnt, ConstantInt::get(
Builder.getInt32Ty(), 1));
3917 Builder.CreateStore(Cnt, CntAddr,
false);
3919 auto *CurFn =
Builder.GetInsertBlock()->getParent();
3923 RealTySize %= TySize;
3932Expected<Function *> OpenMPIRBuilder::emitShuffleAndReduceFunction(
3935 LLVMContext &Ctx =
M.getContext();
3936 IRBuilder<>::InsertPointGuard IPG(
Builder);
3937 FunctionType *FuncTy =
3939 {Builder.getPtrTy(), Builder.getInt16Ty(),
3940 Builder.getInt16Ty(), Builder.getInt16Ty()},
3944 "_omp_reduction_shuffle_and_reduce_func", &
M);
3955 Builder.SetInsertPoint(EntryBB);
3967 Type *ReduceListArgType = ReduceListArg->
getType();
3971 ReduceListArgType,
nullptr, ReduceListArg->
getName() +
".addr");
3972 Value *LaneIdAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
3973 LaneIDArg->
getName() +
".addr");
3975 LaneIDArgType,
nullptr, RemoteLaneOffsetArg->
getName() +
".addr");
3976 Value *AlgoVerAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
3977 AlgoVerArg->
getName() +
".addr");
3984 RedListArrayTy,
nullptr,
".omp.reduction.remote_reduce_list");
3986 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3987 ReduceListAlloca, ReduceListArgType,
3988 ReduceListAlloca->
getName() +
".ascast");
3989 Value *LaneIdAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3990 LaneIdAlloca, LaneIDArgPtrType, LaneIdAlloca->
getName() +
".ascast");
3991 Value *RemoteLaneOffsetAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3992 RemoteLaneOffsetAlloca, LaneIDArgPtrType,
3993 RemoteLaneOffsetAlloca->
getName() +
".ascast");
3994 Value *AlgoVerAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3995 AlgoVerAlloca, LaneIDArgPtrType, AlgoVerAlloca->
getName() +
".ascast");
3996 Value *RemoteListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3997 RemoteReductionListAlloca,
Builder.getPtrTy(),
3998 RemoteReductionListAlloca->
getName() +
".ascast");
4000 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
4001 Builder.CreateStore(LaneIDArg, LaneIdAddrCast);
4002 Builder.CreateStore(RemoteLaneOffsetArg, RemoteLaneOffsetAddrCast);
4003 Builder.CreateStore(AlgoVerArg, AlgoVerAddrCast);
4005 Value *ReduceList =
Builder.CreateLoad(ReduceListArgType, ReduceListAddrCast);
4006 Value *LaneId =
Builder.CreateLoad(LaneIDArgType, LaneIdAddrCast);
4007 Value *RemoteLaneOffset =
4008 Builder.CreateLoad(LaneIDArgType, RemoteLaneOffsetAddrCast);
4009 Value *AlgoVer =
Builder.CreateLoad(LaneIDArgType, AlgoVerAddrCast);
4016 Error EmitRedLsCpRes = emitReductionListCopy(
4018 ReduceList, RemoteListAddrCast, IsByRef,
4019 {RemoteLaneOffset,
nullptr,
nullptr});
4022 return EmitRedLsCpRes;
4047 Value *LaneComp =
Builder.CreateICmpULT(LaneId, RemoteLaneOffset);
4052 Value *Algo2AndLaneIdComp =
Builder.CreateAnd(Algo2, LaneIdComp);
4053 Value *RemoteOffsetComp =
4055 Value *CondAlgo2 =
Builder.CreateAnd(Algo2AndLaneIdComp, RemoteOffsetComp);
4056 Value *CA0OrCA1 =
Builder.CreateOr(CondAlgo0, CondAlgo1);
4057 Value *CondReduce =
Builder.CreateOr(CA0OrCA1, CondAlgo2);
4063 Builder.CreateCondBr(CondReduce, ThenBB, ElseBB);
4065 Value *LocalReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4066 ReduceList,
Builder.getPtrTy());
4067 Value *RemoteReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4068 RemoteListAddrCast,
Builder.getPtrTy());
4070 ->addFnAttr(Attribute::NoUnwind);
4081 Value *LaneIdGtOffset =
Builder.CreateICmpUGE(LaneId, RemoteLaneOffset);
4082 Value *CondCopy =
Builder.CreateAnd(Algo1, LaneIdGtOffset);
4087 Builder.CreateCondBr(CondCopy, CpyThenBB, CpyElseBB);
4091 EmitRedLsCpRes = emitReductionListCopy(
4093 RemoteListAddrCast, ReduceList, IsByRef);
4096 return EmitRedLsCpRes;
4111OpenMPIRBuilder::generateReductionDescriptor(
4113 Type *DescriptorType,
4119 Value *DescriptorSize =
4120 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(DescriptorType));
4122 DescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4123 SrcDescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4127 Value *DataPtrField;
4129 DataPtrPtrGen(
Builder.saveIP(), DescriptorAddr, DataPtrField);
4132 return GenResult.takeError();
4135 DataPtr,
Builder.getPtrTy(),
".ascast"),
4141Expected<Value *> OpenMPIRBuilder::createReductionDescriptorCopy(
4143 Value *SrcDescriptorAddr,
Type *DescriptorPtrTy,
const Twine &Name) {
4147 AllocaInst *DescriptorAlloca =
4148 Builder.CreateAlloca(RI.ByRefAllocatedType,
nullptr, Name);
4150 M.getDataLayout().getPrefTypeAlign(RI.ByRefAllocatedType));
4151 Value *DescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4152 DescriptorAlloca, DescriptorPtrTy,
4153 DescriptorAlloca->
getName() +
".ascast");
4158 generateReductionDescriptor(DescriptorAddr, DataPtr, SrcDescriptorAddr,
4159 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
4161 return GenResult.takeError();
4163 return DescriptorAddr;
4166Expected<Function *> OpenMPIRBuilder::emitListToGlobalCopyFunction(
4169 IRBuilder<>::InsertPointGuard IPG(
Builder);
4170 LLVMContext &Ctx =
M.getContext();
4173 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4177 "_omp_reduction_list_to_global_copy_func", &
M);
4184 Builder.SetInsertPoint(EntryBlock);
4195 BufferArg->
getName() +
".addr");
4199 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4200 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4201 BufferArgAlloca,
Builder.getPtrTy(),
4202 BufferArgAlloca->
getName() +
".ascast");
4203 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4204 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4205 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4206 ReduceListArgAlloca,
Builder.getPtrTy(),
4207 ReduceListArgAlloca->
getName() +
".ascast");
4209 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4210 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4211 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4213 Value *LocalReduceList =
4215 Value *BufferArgVal =
4219 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4220 for (
auto En :
enumerate(ReductionInfos)) {
4222 auto *RedListArrayTy =
4226 RedListArrayTy, LocalReduceList,
4227 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4233 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferArgVal, Idxs);
4235 ReductionsBufferTy, BufferVD, 0, En.index());
4237 switch (RI.EvaluationKind) {
4239 Value *TargetElement;
4241 if (IsByRef.
empty() || !IsByRef[En.index()]) {
4242 TargetElement =
Builder.CreateLoad(RI.ElementType, ElemPtr);
4244 if (RI.DataPtrPtrGen) {
4246 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
4249 return GenResult.takeError();
4253 TargetElement =
Builder.CreateLoad(RI.ByRefElementType, ElemPtr);
4256 Builder.CreateStore(TargetElement, GlobVal);
4260 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4261 RI.ElementType, ElemPtr, 0, 0,
".realp");
4263 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
4265 RI.ElementType, ElemPtr, 0, 1,
".imagp");
4267 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
4269 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4270 RI.ElementType, GlobVal, 0, 0,
".realp");
4271 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4272 RI.ElementType, GlobVal, 0, 1,
".imagp");
4273 Builder.CreateStore(SrcReal, DestRealPtr);
4274 Builder.CreateStore(SrcImg, DestImgPtr);
4279 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(RI.ElementType));
4281 GlobVal,
M.getDataLayout().getPrefTypeAlign(RI.ElementType), ElemPtr,
4282 M.getDataLayout().getPrefTypeAlign(RI.ElementType), SizeVal,
false);
4292Expected<Function *> OpenMPIRBuilder::emitListToGlobalReduceFunction(
4295 IRBuilder<>::InsertPointGuard IPG(
Builder);
4296 LLVMContext &Ctx =
M.getContext();
4299 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4303 "_omp_reduction_list_to_global_reduce_func", &
M);
4310 Builder.SetInsertPoint(EntryBlock);
4321 BufferArg->
getName() +
".addr");
4325 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4326 auto *RedListArrayTy =
4331 Value *LocalReduceList =
4332 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4336 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4337 BufferArgAlloca,
Builder.getPtrTy(),
4338 BufferArgAlloca->
getName() +
".ascast");
4339 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4340 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4341 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4342 ReduceListArgAlloca,
Builder.getPtrTy(),
4343 ReduceListArgAlloca->
getName() +
".ascast");
4344 Value *LocalReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4345 LocalReduceList,
Builder.getPtrTy(),
4346 LocalReduceList->
getName() +
".ascast");
4348 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4349 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4350 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4355 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4356 for (
auto En :
enumerate(ReductionInfos)) {
4359 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4360 RedListArrayTy, LocalReduceListAddrCast,
4361 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4363 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4365 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4366 ReductionsBufferTy, BufferVD, 0, En.index());
4368 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4372 Value *SrcElementPtrPtr =
4373 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
4374 {ConstantInt::get(IndexTy, 0),
4375 ConstantInt::get(IndexTy, En.index())});
4376 Value *SrcDescriptorAddr =
4380 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4381 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4385 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4387 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4395 ->addFnAttr(Attribute::NoUnwind);
4400Expected<Function *> OpenMPIRBuilder::emitGlobalToListCopyFunction(
4403 IRBuilder<>::InsertPointGuard IPG(
Builder);
4404 LLVMContext &Ctx =
M.getContext();
4407 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4411 "_omp_reduction_global_to_list_copy_func", &
M);
4418 Builder.SetInsertPoint(EntryBlock);
4429 BufferArg->
getName() +
".addr");
4433 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4434 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4435 BufferArgAlloca,
Builder.getPtrTy(),
4436 BufferArgAlloca->
getName() +
".ascast");
4437 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4438 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4439 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4440 ReduceListArgAlloca,
Builder.getPtrTy(),
4441 ReduceListArgAlloca->
getName() +
".ascast");
4442 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4443 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4444 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4446 Value *LocalReduceList =
4451 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4452 for (
auto En :
enumerate(ReductionInfos)) {
4453 const OpenMPIRBuilder::ReductionInfo &RI = En.value();
4454 auto *RedListArrayTy =
4458 RedListArrayTy, LocalReduceList,
4459 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4464 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4465 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4466 ReductionsBufferTy, BufferVD, 0, En.index());
4472 if (!IsByRef.
empty() && IsByRef[En.index()]) {
4479 return GenResult.takeError();
4485 Value *TargetElement =
Builder.CreateLoad(ElemType, GlobValPtr);
4486 Builder.CreateStore(TargetElement, ElemPtr);
4490 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4499 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4501 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4503 Builder.CreateStore(SrcReal, DestRealPtr);
4504 Builder.CreateStore(SrcImg, DestImgPtr);
4511 ElemPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4512 GlobValPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4523Expected<Function *> OpenMPIRBuilder::emitGlobalToListReduceFunction(
4526 IRBuilder<>::InsertPointGuard IPG(
Builder);
4527 LLVMContext &Ctx =
M.getContext();
4530 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4534 "_omp_reduction_global_to_list_reduce_func", &
M);
4541 Builder.SetInsertPoint(EntryBlock);
4552 BufferArg->
getName() +
".addr");
4556 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4562 Value *LocalReduceList =
4563 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4567 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4568 BufferArgAlloca,
Builder.getPtrTy(),
4569 BufferArgAlloca->
getName() +
".ascast");
4570 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4571 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4572 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4573 ReduceListArgAlloca,
Builder.getPtrTy(),
4574 ReduceListArgAlloca->
getName() +
".ascast");
4575 Value *ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4576 LocalReduceList,
Builder.getPtrTy(),
4577 LocalReduceList->
getName() +
".ascast");
4579 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4580 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4581 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4586 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4587 for (
auto En :
enumerate(ReductionInfos)) {
4590 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4591 RedListArrayTy, ReductionList,
4592 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4595 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4596 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4597 ReductionsBufferTy, BufferVD, 0, En.index());
4599 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4601 Value *ReduceListVal =
4603 Value *SrcElementPtrPtr =
4604 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceListVal,
4605 {ConstantInt::get(IndexTy, 0),
4606 ConstantInt::get(IndexTy, En.index())});
4607 Value *SrcDescriptorAddr =
4611 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4612 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4616 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4618 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4626 ->addFnAttr(Attribute::NoUnwind);
4631std::string OpenMPIRBuilder::getReductionFuncName(StringRef Name)
const {
4632 std::string Suffix =
4634 return (Name + Suffix).str();
4637Expected<Function *> OpenMPIRBuilder::createReductionFunction(
4640 AttributeList FuncAttrs) {
4641 IRBuilder<>::InsertPointGuard IPG(
Builder);
4643 {Builder.getPtrTy(), Builder.getPtrTy()},
4645 std::string
Name = getReductionFuncName(ReducerName);
4654 Builder.SetInsertPoint(EntryBB);
4659 Value *LHSArrayPtr =
nullptr;
4660 Value *RHSArrayPtr =
nullptr;
4667 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
4669 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
4670 Value *LHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4671 LHSAlloca, Arg0Type, LHSAlloca->
getName() +
".ascast");
4672 Value *RHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4673 RHSAlloca, Arg1Type, RHSAlloca->
getName() +
".ascast");
4674 Builder.CreateStore(Arg0, LHSAddrCast);
4675 Builder.CreateStore(Arg1, RHSAddrCast);
4676 LHSArrayPtr =
Builder.CreateLoad(Arg0Type, LHSAddrCast);
4677 RHSArrayPtr =
Builder.CreateLoad(Arg1Type, RHSAddrCast);
4681 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4683 for (
auto En :
enumerate(ReductionInfos)) {
4686 RedArrayTy, RHSArrayPtr,
4687 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4689 Value *RHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4690 RHSI8Ptr, RI.PrivateVariable->getType(),
4691 RHSI8Ptr->
getName() +
".ascast");
4694 RedArrayTy, LHSArrayPtr,
4695 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4697 Value *LHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4698 LHSI8Ptr, RI.Variable->getType(), LHSI8Ptr->
getName() +
".ascast");
4707 if (!IsByRef.
empty() && !IsByRef[En.index()]) {
4708 LHS =
Builder.CreateLoad(RI.ElementType, LHSPtr);
4709 RHS =
Builder.CreateLoad(RI.ElementType, RHSPtr);
4716 return AfterIP.takeError();
4717 if (!
Builder.GetInsertBlock())
4718 return ReductionFunc;
4722 if (!IsByRef.
empty() && !IsByRef[En.index()])
4723 Builder.CreateStore(Reduced, LHSPtr);
4728 for (
auto En :
enumerate(ReductionInfos)) {
4729 unsigned Index = En.index();
4731 Value *LHSFixupPtr, *RHSFixupPtr;
4732 Builder.restoreIP(RI.ReductionGenClang(
4733 Builder.saveIP(), Index, &LHSFixupPtr, &RHSFixupPtr, ReductionFunc));
4738 LHSPtrs[Index], [ReductionFunc](
const Use &U) {
4743 RHSPtrs[Index], [ReductionFunc](
const Use &U) {
4757 return ReductionFunc;
4765 assert(RI.Variable &&
"expected non-null variable");
4766 assert(RI.PrivateVariable &&
"expected non-null private variable");
4767 assert((RI.ReductionGen || RI.ReductionGenClang) &&
4768 "expected non-null reduction generator callback");
4771 RI.Variable->getType() == RI.PrivateVariable->getType() &&
4772 "expected variables and their private equivalents to have the same "
4775 assert(RI.Variable->getType()->isPointerTy() &&
4776 "expected variables to be pointers");
4793 ArrayRef<bool> IsByRef,
bool IsNoWait,
bool IsTeamsReduction,
bool IsSPMD,
4795 Value *SrcLocInfo) {
4809 if (ReductionInfos.
size() == 0)
4819 Builder.SetInsertPoint(InsertBlock, InsertBlock->
end());
4823 AttributeList FuncAttrs;
4824 AttrBuilder AttrBldr(Ctx);
4826 AttrBldr.addAttribute(Attr);
4827 AttrBldr.removeAttribute(Attribute::OptimizeNone);
4828 FuncAttrs = FuncAttrs.addFnAttributes(Ctx, AttrBldr);
4832 Builder.GetInsertBlock()->getParent()->getName(), ReductionInfos, IsByRef,
4834 if (!ReductionResult)
4836 Function *ReductionFunc = *ReductionResult;
4840 if (GridValue.has_value())
4841 Config.setGridValue(GridValue.value());
4856 Builder.getPtrTy(
M.getDataLayout().getProgramAddressSpace());
4860 Value *ReductionListAlloca =
4861 Builder.CreateAlloca(RedArrayTy,
nullptr,
".omp.reduction.red_list");
4862 Value *ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4863 ReductionListAlloca, PtrTy, ReductionListAlloca->
getName() +
".ascast");
4866 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4867 for (
auto En :
enumerate(ReductionInfos)) {
4870 RedArrayTy, ReductionList,
4871 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4874 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
4879 Builder.CreatePointerBitCastOrAddrSpaceCast(PrivateVar, PtrTy);
4880 Builder.CreateStore(CastElem, ElemPtr);
4884 ReductionInfos, ReductionFunc, FuncAttrs, IsByRef);
4890 emitInterWarpCopyFunction(
Loc, ReductionInfos, FuncAttrs, IsByRef);
4896 Value *RL =
Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList, PtrTy);
4905 unsigned MaxDataSize = 0;
4907 for (
auto En :
enumerate(ReductionInfos)) {
4911 Type *RedTypeArg = (!IsByRef.
empty() && IsByRef[En.index()])
4912 ? En.value().ByRefElementType
4913 : En.value().ElementType;
4914 auto Size =
M.getDataLayout().getTypeStoreSize(RedTypeArg);
4915 if (
Size > MaxDataSize)
4919 Value *ReductionDataSize =
4920 Builder.getInt64(MaxDataSize * ReductionInfos.
size());
4924 Function *CopyScratchToListFunc =
nullptr;
4926 Value *ScratchForCopyBack =
nullptr;
4929 Value *RLForCopyBack = RL;
4931 bool IsAtomicReduction =
4934 if (!IsTeamsReduction) {
4935 Value *SarFuncCast =
4936 Builder.CreatePointerBitCastOrAddrSpaceCast(*SarFunc, FuncPtrTy);
4938 Builder.CreatePointerBitCastOrAddrSpaceCast(WcFunc, FuncPtrTy);
4939 Value *Args[] = {SrcLocInfo, ReductionDataSize, RL, SarFuncCast,
4942 RuntimeFunction::OMPRTL___kmpc_nvptx_parallel_reduce_nowait_v2);
4944 }
else if (IsAtomicReduction) {
4948 RuntimeFunction::OMPRTL___kmpc_is_team_main_thread);
4953 Ctx, ReductionTypeArgs,
"struct._globalized_locals_ty");
4956 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
4961 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
4966 ReductionInfos, ReductionFunc, ReductionsBufferTy, FuncAttrs, IsByRef);
4989 Value *RuntimeRL = RL;
4996 ReductionsBufferTy,
nullptr,
".omp.reduction.scratch");
4997 Value *PerThreadScratch =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4998 PerThreadScratchAlloca, PtrTy,
4999 PerThreadScratchAlloca->
getName() +
".ascast");
5002 Value *PerThreadRedListAlloca =
5003 Builder.CreateAlloca(RedArrayTy,
nullptr,
5004 ".omp.reduction.per_thread_red_list");
5005 RuntimeRL =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5006 PerThreadRedListAlloca, PtrTy,
5007 PerThreadRedListAlloca->
getName() +
".ascast");
5012 for (
auto En :
enumerate(ReductionInfos)) {
5014 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
5017 ReductionsBufferTy, PerThreadScratch, 0, En.index());
5018 Value *Slot =
Builder.CreateConstInBoundsGEP2_32(RedArrayTy, RuntimeRL,
5021 Value *RuntimeListEntry = FieldPtr;
5023 Value *SrcDescriptor =
5026 AllocaIP, RI, FieldPtr, SrcDescriptor, PtrTy);
5029 RuntimeListEntry = *Descriptor;
5031 Builder.CreateStore(RuntimeListEntry, Slot);
5037 Type *CopyArg0Ty = (*LtGCFunc)->getFunctionType()->getParamType(0);
5038 Type *CopyArg2Ty = (*LtGCFunc)->getFunctionType()->getParamType(2);
5039 ScratchForCopyBack =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5040 PerThreadScratch, CopyArg0Ty);
5042 Builder.CreatePointerBitCastOrAddrSpaceCast(RL, CopyArg2Ty);
5050 *LtGCFunc, {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
5051 CopyScratchToListFunc = *GtLCFunc;
5054 Value *Args3[] = {SrcLocInfo, RuntimeRL, *SarFunc, WcFunc,
5055 *LtGCFunc, *GtLCFunc, *GtLRFunc};
5058 RuntimeFunction::OMPRTL___kmpc_gpu_xteam_reduce_nowait);
5078 if (ScratchForCopyBack) {
5081 CopyScratchToListFunc,
5082 {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
5086 for (
auto En :
enumerate(ReductionInfos)) {
5092 if (IsAtomicReduction) {
5108 Value *LHSPtr, *RHSPtr;
5110 &LHSPtr, &RHSPtr, CurFunc));
5116 RedValue =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5118 if (RHSPtr->
getType() != RHS->getType())
5120 Builder.CreatePointerBitCastOrAddrSpaceCast(RHS, RHSPtr->
getType());
5131 if (IsByRef.
empty() || !IsByRef[En.index()]) {
5133 "red.value." +
Twine(En.index()));
5144 if (!IsByRef.
empty() && !IsByRef[En.index()])
5149 if (ContinuationBlock) {
5150 Builder.CreateBr(ContinuationBlock);
5151 Builder.SetInsertPoint(ContinuationBlock);
5153 Config.setEmitLLVMUsed();
5164 ".omp.reduction.func", &M);
5175 Builder.SetInsertPoint(ReductionFuncBlock);
5177 Value *LHSArrayPtr =
nullptr;
5178 Value *RHSArrayPtr =
nullptr;
5189 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
5191 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
5192 Value *LHSAddrCast =
5193 Builder.CreatePointerBitCastOrAddrSpaceCast(LHSAlloca, Arg0Type);
5194 Value *RHSAddrCast =
5195 Builder.CreatePointerBitCastOrAddrSpaceCast(RHSAlloca, Arg1Type);
5196 Builder.CreateStore(Arg0, LHSAddrCast);
5197 Builder.CreateStore(Arg1, RHSAddrCast);
5198 LHSArrayPtr = Builder.CreateLoad(Arg0Type, LHSAddrCast);
5199 RHSArrayPtr = Builder.CreateLoad(Arg1Type, RHSAddrCast);
5201 LHSArrayPtr = ReductionFunc->
getArg(0);
5202 RHSArrayPtr = ReductionFunc->
getArg(1);
5205 unsigned NumReductions = ReductionInfos.
size();
5208 for (
auto En :
enumerate(ReductionInfos)) {
5210 Value *LHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5211 RedArrayTy, LHSArrayPtr, 0, En.index());
5212 Value *LHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), LHSI8PtrPtr);
5213 Value *LHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5216 Value *RHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5217 RedArrayTy, RHSArrayPtr, 0, En.index());
5218 Value *RHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), RHSI8PtrPtr);
5219 Value *RHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5228 Builder.restoreIP(*AfterIP);
5230 if (!Builder.GetInsertBlock())
5234 if (!IsByRef[En.index()])
5235 Builder.CreateStore(Reduced, LHSPtr);
5237 Builder.CreateRetVoid();
5244 bool IsNoWait,
bool IsTeamsReduction) {
5248 IsByRef, IsNoWait, IsTeamsReduction);
5255 if (ReductionInfos.
size() == 0)
5265 unsigned NumReductions = ReductionInfos.
size();
5268 Value *RedArray =
Builder.CreateAlloca(RedArrayTy,
nullptr,
"red.array");
5270 Builder.SetInsertPoint(InsertBlock, InsertBlock->
end());
5275 for (
auto En :
enumerate(ReductionInfos)) {
5276 unsigned Index = En.index();
5278 Value *RedArrayElemPtr =
Builder.CreateConstInBoundsGEP2_64(
5279 RedArrayTy, RedArray, 0, Index,
"red.array.elem." +
Twine(Index));
5286 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
5296 ? IdentFlag::OMP_IDENT_FLAG_ATOMIC_REDUCE
5301 unsigned RedArrayByteSize =
DL.getTypeStoreSize(RedArrayTy);
5302 Constant *RedArraySize = ConstantInt::get(IndexTy, RedArrayByteSize);
5304 Value *Lock = getOMPCriticalRegionLock(
".reduction");
5306 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_reduce_nowait
5307 : RuntimeFunction::OMPRTL___kmpc_reduce);
5310 {Ident, ThreadId, NumVariables, RedArraySize,
5311 RedArray, ReductionFunc, Lock},
5322 Builder.CreateSwitch(ReduceCall, ContinuationBlock, 2);
5323 Switch->addCase(
Builder.getInt32(1), NonAtomicRedBlock);
5324 Switch->addCase(
Builder.getInt32(2), AtomicRedBlock);
5329 Builder.SetInsertPoint(NonAtomicRedBlock);
5330 for (
auto En :
enumerate(ReductionInfos)) {
5336 if (!IsByRef[En.index()]) {
5338 "red.value." +
Twine(En.index()));
5340 Value *PrivateRedValue =
5342 "red.private.value." +
Twine(En.index()));
5350 if (!
Builder.GetInsertBlock())
5353 if (!IsByRef[En.index()])
5357 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_end_reduce_nowait
5358 : RuntimeFunction::OMPRTL___kmpc_end_reduce);
5360 Builder.CreateBr(ContinuationBlock);
5365 Builder.SetInsertPoint(AtomicRedBlock);
5366 if (CanGenerateAtomic &&
llvm::none_of(IsByRef, [](
bool P) {
return P; })) {
5373 if (!
Builder.GetInsertBlock())
5376 Builder.CreateBr(ContinuationBlock);
5389 if (!
Builder.GetInsertBlock())
5392 Builder.SetInsertPoint(ContinuationBlock);
5403 Directive OMPD = Directive::OMPD_master;
5408 Value *Args[] = {Ident, ThreadId};
5416 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5428 Directive OMPD = Directive::OMPD_masked;
5434 Value *ArgsEnd[] = {Ident, ThreadId};
5442 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5452 Call->setDoesNotThrow();
5467 bool IsInclusive,
ScanInfo *ScanRedInfo) {
5469 llvm::Error Err = emitScanBasedDirectiveDeclsIR(AllocaIP, ScanVars,
5470 ScanVarsType, ScanRedInfo);
5481 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5484 Type *DestTy = ScanVarsType[i];
5485 Value *Val =
Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5488 Builder.CreateStore(Src, Val);
5493 Builder.GetInsertBlock()->getParent());
5496 IV = ScanRedInfo->
IV;
5499 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5502 Type *DestTy = ScanVarsType[i];
5504 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5506 Builder.CreateStore(Src, ScanVars[i]);
5520 Builder.GetInsertBlock()->getParent());
5525Error OpenMPIRBuilder::emitScanBasedDirectiveDeclsIR(
5529 Builder.restoreIP(AllocaIP);
5531 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5533 Builder.CreateAlloca(Builder.getPtrTy(),
nullptr,
"vla");
5540 Builder.restoreIP(CodeGenIP);
5542 Builder.CreateAdd(ScanRedInfo->
Span, Builder.getInt32(1));
5543 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5547 Value *Buff = Builder.CreateMalloc(
IntPtrTy, ScanVarsType[i], Allocsize,
5548 AllocSpan,
nullptr,
"arr");
5549 Builder.CreateStore(Buff, (*(ScanRedInfo->
ScanBuffPtrs))[ScanVars[i]]);
5576Error OpenMPIRBuilder::emitScanBasedDirectiveFinalsIR(
5582 Value *PrivateVar = RedInfo.PrivateVariable;
5583 Value *OrigVar = RedInfo.Variable;
5587 Type *SrcTy = RedInfo.ElementType;
5592 Builder.CreateStore(Src, OrigVar);
5640 Builder.GetInsertBlock()->getModule(),
5647 Builder.GetInsertBlock()->getModule(),
5653 llvm::ConstantInt::get(ScanRedInfo->
Span->
getType(), 1));
5654 Builder.SetInsertPoint(InputBB);
5657 Builder.SetInsertPoint(LoopBB);
5673 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5675 Builder.SetInsertPoint(InnerLoopBB);
5679 Value *ReductionVal = RedInfo.PrivateVariable;
5682 Type *DestTy = RedInfo.ElementType;
5685 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5688 Builder.CreateInBoundsGEP(DestTy, Buff, OffsetIval,
"arrayOffset");
5693 RedInfo.ReductionGen(
Builder.saveIP(), LHS, RHS, Result);
5696 Builder.CreateStore(Result, LHSPtr);
5699 IVal, llvm::ConstantInt::get(
Builder.getInt32Ty(), 1));
5701 CmpI =
Builder.CreateICmpUGE(NextIVal, Pow2K);
5702 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5705 Counter, llvm::ConstantInt::get(Counter->
getType(), 1));
5711 Builder.CreateCondBr(Cmp, LoopBB, ExitBB);
5732 Error Err = emitScanBasedDirectiveFinalsIR(ReductionInfos, ScanRedInfo);
5739Error OpenMPIRBuilder::emitScanBasedDirectiveIR(
5751 Error Err = InputLoopGen();
5762 Error Err = ScanLoopGen(Builder);
5769void OpenMPIRBuilder::createScanBBs(ScanInfo *ScanRedInfo) {
5806 Builder.SetInsertPoint(Preheader);
5809 Builder.SetInsertPoint(Header);
5810 PHINode *IndVarPHI =
Builder.CreatePHI(IndVarTy, 2,
"omp_" + Name +
".iv");
5811 IndVarPHI->
addIncoming(ConstantInt::get(IndVarTy, 0), Preheader);
5816 Builder.CreateICmpULT(IndVarPHI, TripCount,
"omp_" + Name +
".cmp");
5817 Builder.CreateCondBr(Cmp, Body, Exit);
5822 Builder.SetInsertPoint(Latch);
5832 bool HasNSW =
Config.hasNoSignedWrap();
5835 unsigned BitWidth = CI->getType()->getIntegerBitWidth();
5837 if (CI->getValue().ugt(SignedMax))
5839 }
else if (IsCollapsed) {
5844 Builder.CreateAdd(IndVarPHI, ConstantInt::get(IndVarTy, 1),
5845 "omp_" + Name +
".next",
true, HasNSW);
5856 CL->Header = Header;
5875 NextBB, NextBB, Name);
5907 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
5916 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
5917 ScanRedInfo->
Span = TripCount;
5923 ScanRedInfo->
IV =
IV;
5924 createScanBBs(ScanRedInfo);
5927 assert(Terminator->getNumSuccessors() == 1);
5928 BasicBlock *ContinueBlock = Terminator->getSuccessor(0);
5931 Builder.GetInsertBlock()->getParent());
5934 Builder.GetInsertBlock()->getParent());
5935 Builder.CreateBr(ContinueBlock);
5941 const auto &&InputLoopGen = [&]() ->
Error {
5944 InclusiveStop, ComputeIP, Name,
true, ScanRedInfo);
5948 Builder.restoreIP((*LoopInfo)->getAfterIP());
5954 InclusiveStop, ComputeIP, Name,
true, ScanRedInfo);
5958 Builder.restoreIP((*LoopInfo)->getAfterIP());
5962 Error Err = emitScanBasedDirectiveIR(InputLoopGen, ScanLoopGen, ScanRedInfo);
5970 bool IsSigned,
bool InclusiveStop,
const Twine &Name) {
5980 assert(IndVarTy == Stop->
getType() &&
"Stop type mismatch");
5981 assert(IndVarTy == Step->
getType() &&
"Step type mismatch");
5985 ConstantInt *Zero = ConstantInt::get(IndVarTy, 0);
6001 Incr =
Builder.CreateSelect(IsNeg,
Builder.CreateNeg(Step), Step);
6004 Span =
Builder.CreateSub(UB, LB,
"",
false,
true);
6008 Span =
Builder.CreateSub(Stop, Start,
"",
true);
6013 Value *CountIfLooping;
6014 if (InclusiveStop) {
6015 CountIfLooping =
Builder.CreateAdd(
Builder.CreateUDiv(Span, Incr), One);
6021 CountIfLooping =
Builder.CreateSelect(OneCmp, One, CountIfTwo);
6024 return Builder.CreateSelect(ZeroCmp, Zero, CountIfLooping,
6025 "omp_" + Name +
".tripcount");
6030 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
6037 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
6042 Config.hasNoSignedWrap());
6043 Value *IndVar =
Builder.CreateAdd(Span, Start,
"",
false,
6044 Config.hasNoSignedWrap());
6046 ScanRedInfo->
IV = IndVar;
6047 return BodyGenCB(
Builder.saveIP(), IndVar);
6053 Builder.getCurrentDebugLocation());
6064 unsigned Bitwidth = Ty->getIntegerBitWidth();
6067 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_4u);
6070 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_8u);
6080 unsigned Bitwidth = Ty->getIntegerBitWidth();
6083 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_4u);
6086 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_8u);
6094 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6096 "Require dedicated allocate IP");
6102 uint32_t SrcLocStrSize;
6106 case WorksharingLoopType::ForStaticLoop:
6107 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6109 case WorksharingLoopType::DistributeStaticLoop:
6110 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6112 case WorksharingLoopType::DistributeForStaticLoop:
6113 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
6120 Type *IVTy =
IV->getType();
6121 FunctionCallee StaticInit =
6122 LoopType == WorksharingLoopType::DistributeForStaticLoop
6125 FunctionCallee StaticFini =
6129 Builder.SetInsertPoint(AllocaIP.getBlock()->getFirstNonPHIOrDbgOrAlloca());
6132 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6133 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
6134 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
6135 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
6144 Constant *One = ConstantInt::get(IVTy, 1);
6145 Builder.CreateStore(Zero, PLowerBound);
6147 Builder.CreateStore(UpperBound, PUpperBound);
6148 Builder.CreateStore(One, PStride);
6154 (LoopType == WorksharingLoopType::DistributeStaticLoop)
6155 ? OMPScheduleType::OrderedDistribute
6158 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6162 auto BuildInitCall = [LoopType, SrcLoc, ThreadNum, PLastIter, PLowerBound,
6163 PUpperBound, IVTy, PStride, One,
Zero, StaticInit,
6166 PLowerBound, PUpperBound});
6167 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
6168 Value *PDistUpperBound =
6169 Builder.CreateAlloca(IVTy,
nullptr,
"p.distupperbound");
6170 Args.push_back(PDistUpperBound);
6175 BuildInitCall(SchedulingType,
Builder);
6176 if (HasDistSchedule &&
6177 LoopType != WorksharingLoopType::DistributeStaticLoop) {
6178 Constant *DistScheduleSchedType = ConstantInt::get(
6183 BuildInitCall(DistScheduleSchedType,
Builder);
6186 Value *InclusiveUpperBound =
Builder.CreateLoad(IVTy, PUpperBound);
6188 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One);
6189 CLI->setTripCount(TripCount);
6195 CLI->mapIndVar([&](Instruction *OldIV) ->
Value * {
6200 Config.hasNoSignedWrap());
6212 omp::Directive::OMPD_for,
false,
6215 return BarrierIP.takeError();
6242 Reachable.insert(
Block);
6256OpenMPIRBuilder::applyStaticChunkedWorkshareLoop(
6260 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6261 assert((ChunkSize || DistScheduleChunkSize) &&
"Chunk size is required");
6266 Type *IVTy =
IV->getType();
6268 "Max supported tripcount bitwidth is 64 bits");
6270 :
Type::getInt64Ty(Ctx);
6273 Constant *One = ConstantInt::get(InternalIVTy, 1);
6278 SmallVector<Instruction *> UIs;
6279 for (BasicBlock &BB : *
F)
6280 if (!BB.hasTerminator())
6281 UIs.
push_back(
new UnreachableInst(
F->getContext(), &BB));
6286 LoopInfo &&LI = LIA.
run(*
F,
FAM);
6287 for (Instruction *
I : UIs)
6288 I->eraseFromParent();
6291 if (ChunkSize || DistScheduleChunkSize)
6296 FunctionCallee StaticInit =
6298 FunctionCallee StaticFini =
6304 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6305 Value *PLowerBound =
6306 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.lowerbound");
6307 Value *PUpperBound =
6308 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.upperbound");
6309 Value *PStride =
Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.stride");
6318 ChunkSize ? ChunkSize : Zero, InternalIVTy,
"chunksize");
6319 Value *CastedDistScheduleChunkSize =
Builder.CreateZExtOrTrunc(
6320 DistScheduleChunkSize ? DistScheduleChunkSize : Zero, InternalIVTy,
6321 "distschedulechunksize");
6322 Value *CastedTripCount =
6323 Builder.CreateZExt(OrigTripCount, InternalIVTy,
"tripcount");
6326 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6328 ConstantInt::get(I32Type,
static_cast<int>(DistScheduleSchedType));
6329 Builder.CreateStore(Zero, PLowerBound);
6330 Value *OrigUpperBound =
Builder.CreateSub(CastedTripCount, One);
6331 Value *IsTripCountZero =
Builder.CreateICmpEQ(CastedTripCount, Zero);
6333 Builder.CreateSelect(IsTripCountZero, Zero, OrigUpperBound);
6334 Builder.CreateStore(UpperBound, PUpperBound);
6335 Builder.CreateStore(One, PStride);
6339 uint32_t SrcLocStrSize;
6342 if (DistScheduleSchedType != OMPScheduleType::None) {
6343 Flag |= OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6348 auto BuildInitCall = [StaticInit, SrcLoc, ThreadNum, PLastIter, PLowerBound,
6349 PUpperBound, PStride, One,
6350 this](
Value *SchedulingType,
Value *ChunkSize,
6353 StaticInit, {SrcLoc, ThreadNum,
6354 SchedulingType, PLastIter,
6355 PLowerBound, PUpperBound,
6359 BuildInitCall(SchedulingType, CastedChunkSize,
Builder);
6360 if (DistScheduleSchedType != OMPScheduleType::None &&
6361 SchedType != OMPScheduleType::OrderedDistributeChunked &&
6362 SchedType != OMPScheduleType::OrderedDistribute) {
6366 BuildInitCall(DistSchedulingType, CastedDistScheduleChunkSize,
Builder);
6370 Value *FirstChunkStart =
6371 Builder.CreateLoad(InternalIVTy, PLowerBound,
"omp_firstchunk.lb");
6372 Value *FirstChunkStop =
6373 Builder.CreateLoad(InternalIVTy, PUpperBound,
"omp_firstchunk.ub");
6374 Value *FirstChunkEnd =
Builder.CreateAdd(FirstChunkStop, One);
6376 Builder.CreateSub(FirstChunkEnd, FirstChunkStart,
"omp_chunk.range");
6377 Value *NextChunkStride =
6378 Builder.CreateLoad(InternalIVTy, PStride,
"omp_dispatch.stride");
6382 Value *DispatchCounter;
6390 DispatchCounter = Counter;
6393 FirstChunkStart, CastedTripCount, NextChunkStride,
6416 Value *ChunkEnd =
Builder.CreateAdd(DispatchCounter, ChunkRange);
6417 Value *IsLastChunk =
6418 Builder.CreateICmpUGE(ChunkEnd, CastedTripCount,
"omp_chunk.is_last");
6419 Value *CountUntilOrigTripCount =
6420 Builder.CreateSub(CastedTripCount, DispatchCounter);
6422 IsLastChunk, CountUntilOrigTripCount, ChunkRange,
"omp_chunk.tripcount");
6423 Value *BackcastedChunkTC =
6424 Builder.CreateTrunc(ChunkTripCount, IVTy,
"omp_chunk.tripcount.trunc");
6425 CLI->setTripCount(BackcastedChunkTC);
6430 Value *BackcastedDispatchCounter =
6431 Builder.CreateTrunc(DispatchCounter, IVTy,
"omp_dispatch.iv.trunc");
6432 CLI->mapIndVar([&](Instruction *) ->
Value * {
6434 return Builder.CreateAdd(
IV, BackcastedDispatchCounter);
6447 return AfterIP.takeError();
6462static FunctionCallee
6465 unsigned Bitwidth = Ty->getIntegerBitWidth();
6468 case WorksharingLoopType::ForStaticLoop:
6471 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_4u);
6474 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_8u);
6476 case WorksharingLoopType::DistributeStaticLoop:
6479 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_4u);
6482 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_8u);
6484 case WorksharingLoopType::DistributeForStaticLoop:
6487 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_4u);
6490 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_8u);
6493 if (Bitwidth != 32 && Bitwidth != 64) {
6505 Function &LoopBodyFn,
bool NoLoop) {
6516 if (LoopType == WorksharingLoopType::DistributeStaticLoop) {
6517 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6518 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6519 Builder.restoreIP({InsertBlock, std::prev(InsertBlock->
end())});
6524 M, omp::RuntimeFunction::OMPRTL_omp_get_num_threads);
6525 Builder.restoreIP({InsertBlock, std::prev(InsertBlock->
end())});
6529 Builder.CreateZExtOrTrunc(NumThreads, TripCountTy,
"num.threads.cast"));
6530 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6531 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
6532 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6533 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), NoLoop));
6535 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6559 Builder.restoreIP({Preheader, Preheader->
end()});
6562 Builder.CreateBr(CLI->
getExit());
6570 CleanUpInfo.
collectBlocks(RegionBlockSet, BlocksToBeRemoved);
6578 "Expected unique undroppable user of outlined function");
6580 assert(OutlinedFnCallInstruction &&
"Expected outlined function call");
6582 "Expected outlined function call to be located in loop preheader");
6584 if (OutlinedFnCallInstruction->
arg_size() > 1)
6591 LoopBodyArg, TripCount, OutlinedFn, NoLoop);
6593 for (
auto &ToBeDeletedItem : ToBeDeleted)
6594 ToBeDeletedItem->eraseFromParent();
6601 uint32_t SrcLocStrSize;
6605 case WorksharingLoopType::ForStaticLoop:
6606 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6608 case WorksharingLoopType::DistributeStaticLoop:
6609 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6611 case WorksharingLoopType::DistributeForStaticLoop:
6612 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
6617 auto OI = std::make_unique<OutlineInfo>();
6622 SmallVector<Instruction *, 4> ToBeDeleted;
6624 OI->OuterAllocBB = AllocaIP.getBlock();
6647 SmallPtrSet<BasicBlock *, 32> ParallelRegionBlockSet;
6649 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
6651 CodeExtractorAnalysisCache CEAC(*OuterFn);
6652 CodeExtractor Extractor(Blocks,
6666 SetVector<Value *> SinkingCands, HoistingCands;
6670 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
6677 for (
auto Use :
Users) {
6679 if (ParallelRegionBlockSet.
count(Inst->getParent())) {
6680 Inst->replaceUsesOfWith(CLI->
getIndVar(), NewLoopCntLoad);
6686 OI->ExcludeArgsFromAggregate.push_back(NewLoopCntLoad);
6693 OI->PostOutlineCB = [=, ToBeDeletedVec =
6694 std::move(ToBeDeleted)](
Function &OutlinedFn) {
6704 bool NeedsBarrier, omp::ScheduleKind SchedKind,
Value *ChunkSize,
6705 bool HasSimdModifier,
bool HasMonotonicModifier,
6706 bool HasNonmonotonicModifier,
bool HasOrderedClause,
6708 Value *DistScheduleChunkSize) {
6709 if (
Config.isTargetDevice())
6710 return applyWorkshareLoopTarget(
DL, CLI, AllocaIP, LoopType, NoLoop);
6712 SchedKind, ChunkSize, HasSimdModifier, HasMonotonicModifier,
6713 HasNonmonotonicModifier, HasOrderedClause, DistScheduleChunkSize);
6715 bool IsOrdered = (EffectiveScheduleType & OMPScheduleType::ModifierOrdered) ==
6716 OMPScheduleType::ModifierOrdered;
6718 if (HasDistSchedule) {
6719 DistScheduleSchedType = DistScheduleChunkSize
6720 ? OMPScheduleType::OrderedDistributeChunked
6721 : OMPScheduleType::OrderedDistribute;
6723 switch (EffectiveScheduleType & ~OMPScheduleType::ModifierMask) {
6724 case OMPScheduleType::BaseStatic:
6725 case OMPScheduleType::BaseDistribute:
6726 assert((!ChunkSize || !DistScheduleChunkSize) &&
6727 "No chunk size with static-chunked schedule");
6728 if (IsOrdered && !HasDistSchedule)
6729 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6730 NeedsBarrier, ChunkSize);
6732 if (DistScheduleChunkSize)
6733 return applyStaticChunkedWorkshareLoop(
6734 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6735 DistScheduleChunkSize, DistScheduleSchedType);
6736 return applyStaticWorkshareLoop(
DL, CLI, AllocaIP, LoopType, NeedsBarrier,
6739 case OMPScheduleType::BaseStaticChunked:
6740 case OMPScheduleType::BaseDistributeChunked:
6741 if (IsOrdered && !HasDistSchedule)
6742 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6743 NeedsBarrier, ChunkSize);
6745 return applyStaticChunkedWorkshareLoop(
6746 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6747 DistScheduleChunkSize, DistScheduleSchedType);
6749 case OMPScheduleType::BaseRuntime:
6750 case OMPScheduleType::BaseAuto:
6751 case OMPScheduleType::BaseGreedy:
6752 case OMPScheduleType::BaseBalanced:
6753 case OMPScheduleType::BaseSteal:
6754 case OMPScheduleType::BaseRuntimeSimd:
6756 "schedule type does not support user-defined chunk sizes");
6758 case OMPScheduleType::BaseGuidedSimd:
6759 case OMPScheduleType::BaseDynamicChunked:
6760 case OMPScheduleType::BaseGuidedChunked:
6761 case OMPScheduleType::BaseGuidedIterativeChunked:
6762 case OMPScheduleType::BaseGuidedAnalyticalChunked:
6763 case OMPScheduleType::BaseStaticBalancedChunked:
6764 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6765 NeedsBarrier, ChunkSize);
6778 unsigned Bitwidth = Ty->getIntegerBitWidth();
6781 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_4u);
6784 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_8u);
6792static FunctionCallee
6794 unsigned Bitwidth = Ty->getIntegerBitWidth();
6797 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_4u);
6800 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_8u);
6807static FunctionCallee
6809 unsigned Bitwidth = Ty->getIntegerBitWidth();
6812 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_4u);
6815 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_8u);
6820OpenMPIRBuilder::applyDynamicWorkshareLoop(
DebugLoc DL, CanonicalLoopInfo *CLI,
6823 bool NeedsBarrier,
Value *Chunk) {
6824 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6826 "Require dedicated allocate IP");
6828 "Require valid schedule type");
6830 bool Ordered = (SchedType & OMPScheduleType::ModifierOrdered) ==
6831 OMPScheduleType::ModifierOrdered;
6836 uint32_t SrcLocStrSize;
6843 Type *IVTy =
IV->getType();
6848 Builder.SetInsertPoint(AllocaIP.getBlock()->getFirstNonPHIOrDbgOrAlloca());
6850 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6851 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
6852 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
6853 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
6862 Constant *One = ConstantInt::get(IVTy, 1);
6863 Builder.CreateStore(One, PLowerBound);
6865 Builder.CreateStore(UpperBound, PUpperBound);
6866 Builder.CreateStore(One, PStride);
6884 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6896 Builder.SetInsertPoint(OuterCond, OuterCond->getFirstInsertionPt());
6899 {SrcLoc, ThreadNum, PLastIter, PLowerBound, PUpperBound, PStride});
6900 Constant *Zero32 = ConstantInt::get(I32Type, 0);
6903 Builder.CreateSub(
Builder.CreateLoad(IVTy, PLowerBound), One,
"lb");
6904 Builder.CreateCondBr(MoreWork, Header, Exit);
6910 PI->setIncomingBlock(0, OuterCond);
6916 Br->setSuccessor(OuterCond);
6922 UpperBound =
Builder.CreateLoad(IVTy, PUpperBound,
"ub");
6925 CI->setOperand(1, UpperBound);
6929 assert(BI->getSuccessor(1) == Exit);
6930 BI->setSuccessor(1, OuterCond);
6944 omp::Directive::OMPD_for,
false,
6947 return BarrierIP.takeError();
6999 assert(
Loops.size() >= 1 &&
"At least one loop required");
7000 size_t NumLoops =
Loops.size();
7004 return Loops.front();
7016 Loop->collectControlBlocks(OldControlBBs);
7020 if (ComputeIP.
isSet())
7027 Value *CollapsedTripCount =
nullptr;
7030 "All loops to collapse must be valid canonical loops");
7031 Value *OrigTripCount = L->getTripCount();
7032 if (!CollapsedTripCount) {
7033 CollapsedTripCount = OrigTripCount;
7038 CollapsedTripCount =
7039 Builder.CreateNUWMul(CollapsedTripCount, OrigTripCount);
7045 OrigPreheader->
getNextNode(), OrigAfter,
"collapsed",
7052 Builder.restoreIP(Result->getBodyIP());
7054 Value *Leftover = Result->getIndVar();
7056 NewIndVars.
resize(NumLoops);
7057 for (
int i = NumLoops - 1; i >= 1; --i) {
7058 Value *OrigTripCount =
Loops[i]->getTripCount();
7060 Value *NewIndVar =
Builder.CreateURem(Leftover, OrigTripCount);
7061 NewIndVars[i] = NewIndVar;
7063 Leftover =
Builder.CreateUDiv(Leftover, OrigTripCount);
7066 NewIndVars[0] = Leftover;
7075 BasicBlock *ContinueBlock = Result->getBody();
7077 auto ContinueWith = [&ContinueBlock, &ContinuePred,
DL](
BasicBlock *Dest,
7084 ContinueBlock =
nullptr;
7085 ContinuePred = NextSrc;
7092 for (
size_t i = 0; i < NumLoops - 1; ++i)
7093 ContinueWith(
Loops[i]->getBody(),
Loops[i + 1]->getHeader());
7099 for (
size_t i = NumLoops - 1; i > 0; --i)
7100 ContinueWith(
Loops[i]->getAfter(),
Loops[i - 1]->getLatch());
7103 ContinueWith(Result->getLatch(),
nullptr);
7110 for (
size_t i = 0; i < NumLoops; ++i)
7111 Loops[i]->getIndVar()->replaceAllUsesWith(NewIndVars[i]);
7125std::vector<CanonicalLoopInfo *>
7129 "Must pass as many tile sizes as there are loops");
7130 int NumLoops =
Loops.size();
7131 assert(NumLoops >= 1 &&
"At least one loop to tile required");
7143 Loop->collectControlBlocks(OldControlBBs);
7151 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7152 OrigTripCounts.
push_back(L->getTripCount());
7163 for (
int i = 0; i < NumLoops - 1; ++i) {
7176 for (
int i = 0; i < NumLoops; ++i) {
7178 Value *OrigTripCount = OrigTripCounts[i];
7191 Value *FloorTripOverflow =
7192 Builder.CreateICmpNE(FloorTripRem, ConstantInt::get(IVType, 0));
7194 FloorTripOverflow =
Builder.CreateZExt(FloorTripOverflow, IVType);
7195 Value *FloorTripCount =
7196 Builder.CreateAdd(FloorCompleteTripCount, FloorTripOverflow,
7197 "omp_floor" +
Twine(i) +
".tripcount",
true);
7200 FloorCompleteCount.
push_back(FloorCompleteTripCount);
7206 std::vector<CanonicalLoopInfo *> Result;
7207 Result.reserve(NumLoops * 2);
7220 auto EmbeddNewLoop =
7221 [
this,
DL,
F, InnerEnter, &Enter, &
Continue, &OutroInsertBefore](
7224 DL, TripCount,
F, InnerEnter, OutroInsertBefore, Name);
7229 Enter = EmbeddedLoop->
getBody();
7231 OutroInsertBefore = EmbeddedLoop->
getLatch();
7232 return EmbeddedLoop;
7236 const Twine &NameBase) {
7239 EmbeddNewLoop(
P.value(), NameBase +
Twine(
P.index()));
7240 Result.push_back(EmbeddedLoop);
7244 EmbeddNewLoops(FloorCount,
"floor");
7250 for (
int i = 0; i < NumLoops; ++i) {
7254 Value *FloorIsEpilogue =
7256 Value *TileTripCount =
7263 EmbeddNewLoops(TileCounts,
"tile");
7268 for (std::pair<BasicBlock *, BasicBlock *>
P : InbetweenCode) {
7277 BodyEnter =
nullptr;
7278 BodyEntered = ExitBB;
7290 Builder.restoreIP(Result.back()->getBodyIP());
7291 for (
int i = 0; i < NumLoops; ++i) {
7294 Value *OrigIndVar = OrigIndVars[i];
7345 assert(
Loop->isValid() &&
"Expecting a valid CanonicalLoopInfo");
7349 assert(Latch &&
"A valid CanonicalLoopInfo must have a unique latch");
7357 if (
I.mayReadOrWriteMemory()) {
7361 I.setMetadata(LLVMContext::MD_access_group,
AccessGroup);
7375 Loop->collectControlBlocks(oldControlBBs);
7380 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7381 origTripCounts.
push_back(L->getTripCount());
7390 Builder.SetInsertPoint(TCBlock);
7391 Value *fusedTripCount =
nullptr;
7393 assert(L->isValid() &&
"All loops to fuse must be valid canonical loops");
7394 Value *origTripCount = L->getTripCount();
7395 if (!fusedTripCount) {
7396 fusedTripCount = origTripCount;
7399 Value *condTP =
Builder.CreateICmpSGT(fusedTripCount, origTripCount);
7400 fusedTripCount =
Builder.CreateSelect(condTP, fusedTripCount, origTripCount,
7414 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7415 Loops[i]->getPreheader()->moveBefore(TCBlock);
7416 Loops[i]->getAfter()->moveBefore(TCBlock);
7420 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7432 for (
size_t i = 0; i <
Loops.size(); ++i) {
7434 F->getContext(),
"omp.fused.inner.cond",
F,
Loops[i]->getBody());
7435 Builder.SetInsertPoint(condBlock);
7443 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7444 Builder.SetInsertPoint(condBBs[i]);
7445 Builder.CreateCondBr(condValues[i],
Loops[i]->getBody(), condBBs[i + 1]);
7461 "omp.fused.pre_latch");
7494 const Twine &NamePrefix) {
7523 C, NamePrefix +
".if.then",
Cond->getParent(),
Cond->getNextNode());
7525 C, NamePrefix +
".if.else",
Cond->getParent(), CanonicalLoop->
getExit());
7528 Builder.SetInsertPoint(SplitBeforeIt);
7530 Builder.CreateCondBr(IfCond, ThenBlock, ElseBlock);
7533 spliceBB(IP, ThenBlock,
false, Builder.getCurrentDebugLocation());
7536 Builder.SetInsertPoint(ElseBlock);
7542 ExistingBlocks.
reserve(L->getNumBlocks() + 1);
7544 ExistingBlocks.
append(L->block_begin(), L->block_end());
7550 assert(LoopCond && LoopHeader &&
"Invalid loop structure");
7552 if (
Block == L->getLoopPreheader() ||
Block == L->getLoopLatch() ||
7559 if (
Block == ThenBlock)
7560 NewBB->
setName(NamePrefix +
".if.else");
7563 VMap[
Block] = NewBB;
7571 L->getLoopLatch()->splitBasicBlockBefore(
L->getLoopLatch()->begin(),
7572 NamePrefix +
".pre_latch");
7576 L->addBasicBlockToLoop(ThenBlock, LI);
7582 if (TargetTriple.
isX86()) {
7583 if (Features.
lookup(
"avx512f"))
7585 else if (Features.
lookup(
"avx"))
7589 if (TargetTriple.
isPPC())
7591 if (TargetTriple.
isWasm())
7600 Value *IfCond, OrderKind Order,
7610 if (!BB.hasTerminator())
7626 I->eraseFromParent();
7629 if (AlignedVars.
size()) {
7631 for (
auto &AlignedItem : AlignedVars) {
7632 Value *AlignedPtr = AlignedItem.first;
7636 Builder.CreateAlignmentAssumption(
F->getDataLayout(), AlignedPtr,
7644 createIfVersion(CanonicalLoop, IfCond, VMap, LIA, LI, L,
"simd");
7657 Reachable.insert(
Block);
7667 if ((Safelen ==
nullptr) || (Order == OrderKind::OMP_ORDER_concurrent))
7683 if (Simdlen || Safelen) {
7687 ConstantInt *VectorizeWidth = Simdlen ==
nullptr ? Safelen : Simdlen;
7713static std::unique_ptr<TargetMachine>
7717 StringRef CPU =
F->getFnAttribute(
"target-cpu").getValueAsString();
7718 StringRef Features =
F->getFnAttribute(
"target-features").getValueAsString();
7729 std::nullopt, OptLevel));
7747 if (!BB.hasTerminator())
7760 [&](
const Function &
F) {
return TM->getTargetTransformInfo(
F); });
7761 FAM.registerPass([&]() {
return TIRA; });
7775 I->eraseFromParent();
7778 assert(L &&
"Expecting CanonicalLoopInfo to be recognized as a loop");
7783 nullptr, ORE,
static_cast<int>(OptLevel),
7803 <<
" Threshold=" << UP.
Threshold <<
"\n"
7806 <<
" PartialOptSizeThreshold="
7826 Ptr =
Load->getPointerOperand();
7828 Ptr =
Store->getPointerOperand();
7835 if (Alloca->getParent() == &
F->getEntryBlock())
7855 int MaxTripCount = 0;
7856 bool MaxOrZero =
false;
7857 unsigned TripMultiple = 0;
7861 MaxTripCount, MaxOrZero, TripMultiple, UCE, UP, PP);
7862 LLVM_DEBUG(
dbgs() <<
"Suggesting unroll factor of " << Factor <<
"\n");
7873 assert(Factor >= 0 &&
"Unroll factor must not be negative");
7889 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst}));
7902 *UnrolledCLI =
Loop;
7907 "unrolling only makes sense with a factor of 2 or larger");
7909 Type *IndVarTy =
Loop->getIndVarType();
7916 std::vector<CanonicalLoopInfo *>
LoopNest =
7931 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst})});
7934 (*UnrolledCLI)->assertOK();
7952 Value *Args[] = {Ident, ThreadId, BufSize, CpyBuf, CpyFn, DidItLD};
7971 if (!CPVars.
empty()) {
7976 Directive OMPD = Directive::OMPD_single;
7981 Value *Args[] = {Ident, ThreadId};
7990 if (
Error Err = FiniCB(IP))
8011 EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCBWrapper,
8018 for (
size_t I = 0, E = CPVars.
size();
I < E; ++
I)
8021 ConstantInt::get(Int64, 0), CPVars[
I],
8024 }
else if (!IsNowait) {
8027 omp::Directive::OMPD_unknown,
false,
8045 Directive::OMPD_scope,
nullptr,
nullptr,
8046 BodyGenCB, FiniCB,
false,
true,
8054 omp::Directive::OMPD_unknown,
8070 Directive OMPD = Directive::OMPD_critical;
8075 Value *LockVar = getOMPCriticalRegionLock(CriticalName);
8076 Value *Args[] = {Ident, ThreadId, LockVar};
8093 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
8101 const Twine &Name,
bool IsDependSource) {
8105 "OpenMP runtime requires depend vec with i64 type");
8118 for (
unsigned I = 0;
I < NumLoops; ++
I) {
8132 Value *Args[] = {Ident, ThreadId, DependBaseAddrGEP};
8150 Directive OMPD = Directive::OMPD_ordered_blockassoc;
8159 Value *Args[] = {Ident, ThreadId};
8169 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
8176 bool HasFinalize,
bool IsCancellable) {
8183 BasicBlock *EntryBB = Builder.GetInsertBlock();
8192 emitCommonDirectiveEntry(OMPD, EntryCall, ExitBB, Conditional);
8204 "Unexpected control flow graph state!!");
8206 emitCommonDirectiveExit(OMPD, FinIP, ExitCall, HasFinalize);
8208 return AfterIP.takeError();
8213 "Unexpected Insertion point location!");
8216 auto InsertBB = merged ? ExitPredBB : ExitBB;
8219 Builder.SetInsertPoint(InsertBB);
8221 return Builder.saveIP();
8225 Directive OMPD,
Value *EntryCall, BasicBlock *ExitBB,
bool Conditional) {
8227 if (!Conditional || !EntryCall)
8233 auto *UI =
new UnreachableInst(
Builder.getContext(), ThenBB);
8243 Builder.CreateCondBr(CallBool, ThenBB, ExitBB);
8247 UI->eraseFromParent();
8255 omp::Directive OMPD,
InsertPointTy FinIP, Instruction *ExitCall,
8263 "Unexpected finalization stack state!");
8266 assert(Fi.DK == OMPD &&
"Unexpected Directive for Finalization call!");
8268 if (
Error Err = Fi.mergeFiniBB(
Builder, FinIP.getBlock()))
8269 return std::move(Err);
8273 Builder.SetInsertPoint(FinIP.getBlock()->getTerminator());
8283 return IRBuilder<>::InsertPoint(ExitCall->
getParent(),
8317 "copyin.not.master.end");
8324 Builder.SetInsertPoint(OMP_Entry);
8327 Value *cmp =
Builder.CreateICmpNE(MasterPtr, PrivatePtr);
8328 Builder.CreateCondBr(cmp, CopyBegin, CopyEnd);
8330 Builder.SetInsertPoint(CopyBegin);
8348 Value *Args[] = {ThreadId,
Size, Allocator};
8371 return Builder.CreateCall(Fn, Args, Name);
8385 Value *Args[] = {ThreadId, Addr, Allocator};
8392 const Twine &Name) {
8400 M.getContext(),
M.getDataLayout().getPrefTypeAlign(Int64)));
8406 const Twine &Name) {
8408 Loc,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)), Name);
8413 const Twine &Name) {
8419 return Builder.CreateCall(Fn, Args, Name);
8424 const Twine &Name) {
8426 Loc, Addr,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)),
8433 Value *DependenceAddress,
bool HaveNowaitClause) {
8443 else if (
Device->getType() != Int32)
8446 if (NumDependences ==
nullptr) {
8447 NumDependences = ConstantInt::get(Int32, 0);
8451 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8453 Ident, ThreadId, InteropVar, InteropTypeVal,
8454 Device, NumDependences, DependenceAddress, HaveNowaitClauseVal};
8463 Value *NumDependences,
Value *DependenceAddress,
bool HaveNowaitClause) {
8473 else if (
Device->getType() != Int32)
8475 if (NumDependences ==
nullptr) {
8476 NumDependences = ConstantInt::get(Int32, 0);
8480 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8482 Ident, ThreadId, InteropVar,
Device,
8483 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8492 Value *NumDependences,
8493 Value *DependenceAddress,
8494 bool HaveNowaitClause) {
8503 else if (
Device->getType() != Int32)
8505 if (NumDependences ==
nullptr) {
8506 NumDependences = ConstantInt::get(Int32, 0);
8510 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8512 Ident, ThreadId, InteropVar,
Device,
8513 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8543 assert(!Attrs.MaxThreads.empty() && !Attrs.MaxTeams.empty() &&
8544 "expected num_threads and num_teams to be specified");
8564 const std::string DebugPrefix =
"_debug__";
8565 if (KernelName.
ends_with(DebugPrefix)) {
8566 KernelName = KernelName.
drop_back(DebugPrefix.length());
8567 Kernel =
M.getFunction(KernelName);
8573 if (Attrs.MinTeams.front() > 1 || Attrs.MaxTeams.front() > 0)
8575 Attrs.MaxTeams.front());
8579 int32_t MaxThreadsVal = Attrs.MaxThreads.front();
8584 Attrs.MinThreads.front());
8586 MaxThreadsVal = Attrs.MinThreads.front();
8590 if (MaxThreadsVal > 0)
8603 omp::RuntimeFunction::OMPRTL___kmpc_target_init);
8606 Twine DynamicEnvironmentName = KernelName +
"_dynamic_environment";
8607 Constant *DynamicEnvironmentInitializer =
8611 DynamicEnvironmentInitializer, DynamicEnvironmentName,
8613 DL.getDefaultGlobalsAddressSpace());
8617 DynamicEnvironmentGV->
getType() == DynamicEnvironmentPtr
8618 ? DynamicEnvironmentGV
8620 DynamicEnvironmentPtr);
8623 ConfigurationEnvironment, {
8624 UseGenericStateMachineVal,
8625 MayUseNestedParallelismVal,
8634 KernelEnvironment, {
8635 ConfigurationEnvironmentInitializer,
8639 std::string KernelEnvironmentName =
8640 (KernelName +
"_kernel_environment").str();
8643 KernelEnvironmentInitializer, KernelEnvironmentName,
8645 DL.getDefaultGlobalsAddressSpace());
8649 KernelEnvironmentGV->
getType() == KernelEnvironmentPtr
8650 ? KernelEnvironmentGV
8652 KernelEnvironmentPtr);
8653 Value *KernelLaunchEnvironment =
8656 KernelLaunchEnvironment =
8657 KernelLaunchEnvironment->
getType() == KernelLaunchEnvParamTy
8658 ? KernelLaunchEnvironment
8659 :
Builder.CreateAddrSpaceCast(KernelLaunchEnvironment,
8660 KernelLaunchEnvParamTy);
8662 Fn, {KernelEnvironment, KernelLaunchEnvironment});
8674 auto *UI =
Builder.CreateUnreachable();
8680 Builder.SetInsertPoint(WorkerExitBB);
8684 Builder.SetInsertPoint(CheckBBTI);
8685 Builder.CreateCondBr(ExecUserCode, UI->getParent(), WorkerExitBB);
8687 CheckBBTI->eraseFromParent();
8688 UI->eraseFromParent();
8696 int32_t TeamsReductionDataSize) {
8701 omp::RuntimeFunction::OMPRTL___kmpc_target_deinit);
8705 if (!TeamsReductionDataSize)
8711 const std::string DebugPrefix =
"_debug__";
8713 KernelName = KernelName.
drop_back(DebugPrefix.length());
8714 auto *KernelEnvironmentGV =
8715 M.getNamedGlobal((KernelName +
"_kernel_environment").str());
8716 assert(KernelEnvironmentGV &&
"Expected kernel environment global\n");
8717 auto *KernelEnvironmentInitializer = KernelEnvironmentGV->getInitializer();
8719 KernelEnvironmentInitializer,
8720 ConstantInt::get(Int32, TeamsReductionDataSize), {0, 7});
8721 KernelEnvironmentGV->setInitializer(NewInitializer);
8726 if (
Kernel.hasFnAttribute(Name)) {
8727 int32_t OldLimit =
Kernel.getFnAttributeAsParsedInteger(Name);
8733std::pair<int32_t, int32_t>
8735 int32_t ThreadLimit =
8736 Kernel.getFnAttributeAsParsedInteger(
"omp_target_thread_limit");
8739 const auto &Attr =
Kernel.getFnAttribute(
"amdgpu-flat-work-group-size");
8740 if (!Attr.isValid() || !Attr.isStringAttribute())
8741 return {0, ThreadLimit};
8742 auto [LBStr, UBStr] = Attr.getValueAsString().split(
',');
8745 return {0, ThreadLimit};
8746 UB = ThreadLimit ? std::min(ThreadLimit, UB) : UB;
8754 return {0, ThreadLimit ? std::min(ThreadLimit, UB) : UB};
8756 return {0, ThreadLimit};
8762 Kernel.addFnAttr(
"omp_target_thread_limit", std::to_string(UB));
8765 Kernel.addFnAttr(
"amdgpu-flat-work-group-size",
8773std::pair<int32_t, int32_t>
8776 return {0,
Kernel.getFnAttributeAsParsedInteger(
"omp_target_num_teams")};
8780 int32_t LB, int32_t UB) {
8788 Kernel.addFnAttr(
"omp_target_num_teams", std::to_string(LB));
8791void OpenMPIRBuilder::setOutlinedTargetRegionFunctionAttributes(
8800 else if (
T.isNVPTX())
8802 else if (
T.isSPIRV())
8808 StringRef EntryFnIDName) {
8809 if (
Config.isTargetDevice()) {
8810 assert(OutlinedFn &&
"The outlined function must exist if embedded");
8814 return new GlobalVariable(
8819Constant *OpenMPIRBuilder::createTargetRegionEntryAddr(
Function *OutlinedFn,
8820 StringRef EntryFnName) {
8824 assert(!
M.getGlobalVariable(EntryFnName,
true) &&
8825 "Named kernel already exists?");
8826 return new GlobalVariable(
8839 if (
Config.isTargetDevice() || !
Config.openMPOffloadMandatory()) {
8843 OutlinedFn = *CBResult;
8845 OutlinedFn =
nullptr;
8851 if (!IsOffloadEntry)
8854 std::string EntryFnIDName =
8856 ? std::string(EntryFnName)
8860 EntryFnName, EntryFnIDName);
8868 setOutlinedTargetRegionFunctionAttributes(OutlinedFn);
8869 auto OutlinedFnID = createOutlinedFunctionID(OutlinedFn, EntryFnIDName);
8870 auto EntryAddr = createTargetRegionEntryAddr(OutlinedFn, EntryFnName);
8872 EntryInfo, EntryAddr, OutlinedFnID,
8874 return OutlinedFnID;
8892 bool IsStandAlone = !BodyGenCB;
8899 MapInfo = &GenMapInfoCB(
Builder.saveIP());
8901 AllocaIP,
Builder.saveIP(), *MapInfo, Info, CustomMapperCB,
8902 true, DeviceAddrCB))
8909 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
8919 SrcLocInfo, DeviceID,
8926 assert(MapperFunc &&
"MapperFunc missing for standalone target data");
8930 if (Info.HasNoWait) {
8940 if (Info.HasNoWait) {
8944 emitBlock(OffloadContBlock, CurFn,
true);
8950 bool RequiresOuterTargetTask = Info.HasNoWait;
8951 if (!RequiresOuterTargetTask)
8952 cantFail(TaskBodyCB(
nullptr,
nullptr,
8956 {}, RTArgs, Info.HasNoWait));
8959 omp::OMPRTL___tgt_target_data_begin_mapper);
8963 for (
auto DeviceMap : Info.DevicePtrInfoMap) {
8967 Builder.CreateStore(LI, DeviceMap.second.second);
9004 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
9013 Value *OffloadingArgs[] = {SrcLocInfo, DeviceID,
9036 return emitIfClause(IfCond, BeginThenGen, BeginElseGen, AllocaIP);
9037 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9052 return emitIfClause(IfCond, EndThenGen, EndElseGen, AllocaIP);
9053 return EndThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9056 return emitIfClause(IfCond, BeginThenGen, EndElseGen, AllocaIP);
9057 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9068 bool IsGPUDistribute) {
9069 assert((IVSize == 32 || IVSize == 64) &&
9070 "IV size is not compatible with the omp runtime");
9072 if (IsGPUDistribute)
9074 ? (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_4
9075 : omp::OMPRTL___kmpc_distribute_static_init_4u)
9076 : (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_8
9077 : omp::OMPRTL___kmpc_distribute_static_init_8u);
9079 Name = IVSize == 32 ? (IVSigned ? omp::OMPRTL___kmpc_for_static_init_4
9080 : omp::OMPRTL___kmpc_for_static_init_4u)
9081 : (IVSigned ? omp::OMPRTL___kmpc_for_static_init_8
9082 : omp::OMPRTL___kmpc_for_static_init_8u);
9089 assert((IVSize == 32 || IVSize == 64) &&
9090 "IV size is not compatible with the omp runtime");
9092 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_4
9093 : omp::OMPRTL___kmpc_dispatch_init_4u)
9094 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_8
9095 : omp::OMPRTL___kmpc_dispatch_init_8u);
9102 assert((IVSize == 32 || IVSize == 64) &&
9103 "IV size is not compatible with the omp runtime");
9105 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_4
9106 : omp::OMPRTL___kmpc_dispatch_next_4u)
9107 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_8
9108 : omp::OMPRTL___kmpc_dispatch_next_8u);
9115 assert((IVSize == 32 || IVSize == 64) &&
9116 "IV size is not compatible with the omp runtime");
9118 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_4
9119 : omp::OMPRTL___kmpc_dispatch_fini_4u)
9120 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_8
9121 : omp::OMPRTL___kmpc_dispatch_fini_8u);
9132 DenseMap<
Value *, std::tuple<Value *, unsigned>> &ValueReplacementMap) {
9140 auto GetUpdatedDIVariable = [&](
DILocalVariable *OldVar,
unsigned arg) {
9144 if (NewVar && (arg == NewVar->
getArg()))
9154 auto UpdateDebugRecord = [&](
auto *DR) {
9157 for (
auto Loc : DR->location_ops()) {
9158 auto Iter = ValueReplacementMap.find(
Loc);
9159 if (Iter != ValueReplacementMap.end()) {
9160 DR->replaceVariableLocationOp(
Loc, std::get<0>(Iter->second));
9161 ArgNo = std::get<1>(Iter->second) + 1;
9165 DR->setVariable(GetUpdatedDIVariable(OldVar, ArgNo));
9170 if (DVR->getNumVariableLocationOps() != 1u) {
9171 DVR->setKillLocation();
9174 Value *
Loc = DVR->getVariableLocationOp(0u);
9181 RequiredBB = &DVR->getFunction()->getEntryBlock();
9183 if (RequiredBB && RequiredBB != CurBB) {
9195 "Unexpected debug intrinsic");
9197 UpdateDebugRecord(&DVR);
9198 MoveDebugRecordToCorrectBlock(&DVR);
9201 for (
auto *DVR : DVRsToDelete)
9202 DVR->getMarker()->MarkedInstr->dropOneDbgRecord(DVR);
9206 Module *M = Func->getParent();
9209 DB.createQualifiedType(dwarf::DW_TAG_pointer_type,
nullptr);
9210 unsigned ArgNo = Func->arg_size();
9212 NewSP,
"dyn_ptr", ArgNo, NewSP->
getFile(), 0, VoidPtrTy,
9213 false, DINode::DIFlags::FlagArtificial);
9215 Argument *LastArg = Func->getArg(Func->arg_size() - 1);
9216 DB.insertDeclare(LastArg, Var, DB.createExpression(),
Loc,
9238 for (
auto &Arg : Inputs)
9239 ParameterTypes.
push_back(Arg->getType()->isPointerTy()
9243 for (
auto &Arg : Inputs)
9244 ParameterTypes.
push_back(Arg->getType());
9252 auto BB = Builder.GetInsertBlock();
9253 auto M = BB->getModule();
9264 if (TargetCpuAttr.isStringAttribute())
9265 Func->addFnAttr(TargetCpuAttr);
9267 auto TargetFeaturesAttr = ParentFn->
getFnAttribute(
"target-features");
9268 if (TargetFeaturesAttr.isStringAttribute())
9269 Func->addFnAttr(TargetFeaturesAttr);
9274 OMPBuilder.
emitUsed(
"llvm.compiler.used", {ExecMode});
9284 Builder.SetCurrentDebugLocation(OutlinedFnLoc);
9288 Builder.SetInsertPoint(EntryBB);
9294 BasicBlock *UserCodeEntryBB = Builder.GetInsertBlock();
9304 splitBB(Builder,
true,
"outlined.body");
9311 Builder.SetInsertPoint(ExitBB);
9319 Builder.SetCurrentDebugLocation(OutlinedFnLoc);
9326 Builder.CreateRetVoid();
9330 auto AllocaIP = Builder.saveIP();
9335 const auto &ArgRange =
make_range(Func->arg_begin(), Func->arg_end() - 1);
9367 if (Instr->getFunction() == Func)
9368 Instr->replaceUsesOfWith(
Input, InputCopy);
9374 for (
auto InArg :
zip(Inputs, ArgRange)) {
9376 Argument &Arg = std::get<1>(InArg);
9377 Value *InputCopy =
nullptr;
9380 Arg,
Input, InputCopy, AllocaIP, Builder.saveIP(),
9384 Builder.restoreIP(*AfterIP);
9385 ValueReplacementMap[
Input] = std::make_tuple(InputCopy, Arg.
getArgNo());
9405 DeferredReplacement.push_back(std::make_pair(
Input, InputCopy));
9412 ReplaceValue(
Input, InputCopy, Func);
9416 for (
auto Deferred : DeferredReplacement)
9417 ReplaceValue(std::get<0>(Deferred), std::get<1>(Deferred), Func);
9420 ValueReplacementMap);
9428 Value *TaskWithPrivates,
9429 Type *TaskWithPrivatesTy) {
9431 Type *TaskTy = OMPIRBuilder.Task;
9434 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 0);
9435 Value *Shareds = TaskT;
9445 if (TaskWithPrivatesTy != TaskTy)
9446 Shareds = Builder.CreateStructGEP(TaskTy, TaskT, 0);
9463 const size_t NumOffloadingArrays,
const int SharedArgsOperandNo) {
9468 assert((!NumOffloadingArrays || PrivatesTy) &&
9469 "PrivatesTy cannot be nullptr when there are offloadingArrays"
9502 Type *TaskPtrTy = OMPBuilder.TaskPtr;
9503 [[maybe_unused]]
Type *TaskTy = OMPBuilder.Task;
9509 ".omp_target_task_proxy_func", M);
9510 Value *ThreadId = ProxyFn->getArg(0);
9511 Value *TaskWithPrivates = ProxyFn->getArg(1);
9512 ThreadId->
setName(
"thread.id");
9513 TaskWithPrivates->
setName(
"task");
9515 bool HasShareds = SharedArgsOperandNo > 0;
9516 bool HasOffloadingArrays = NumOffloadingArrays > 0;
9520 Builder.SetInsertPoint(EntryBB);
9527 if (HasOffloadingArrays) {
9528 assert(TaskTy != TaskWithPrivatesTy &&
9529 "If there are offloading arrays to pass to the target"
9530 "TaskTy cannot be the same as TaskWithPrivatesTy");
9533 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskWithPrivates, 1);
9534 for (
unsigned int i = 0; i < NumOffloadingArrays; ++i)
9536 Builder.CreateStructGEP(PrivatesTy, Privates, i));
9540 auto *ArgStructAlloca =
9542 assert(ArgStructAlloca &&
9543 "Unable to find the alloca instruction corresponding to arguments "
9544 "for extracted function");
9546 std::optional<TypeSize> ArgAllocSize =
9548 assert(ArgStructType && ArgAllocSize &&
9549 "Unable to determine size of arguments for extracted function");
9550 uint64_t StructSize = ArgAllocSize->getFixedValue();
9553 Builder.CreateAlloca(ArgStructType,
nullptr,
"structArg");
9555 Value *SharedsSize = Builder.getInt64(StructSize);
9558 OMPBuilder, Builder, TaskWithPrivates, TaskWithPrivatesTy);
9560 Builder.CreateMemCpy(
9561 NewArgStructAlloca, NewArgStructAlloca->
getAlign(), LoadShared,
9563 KernelLaunchArgs.
push_back(NewArgStructAlloca);
9566 Builder.CreateRetVoid();
9572 return GEP->getSourceElementType();
9574 return Alloca->getAllocatedType();
9597 if (OffloadingArraysToPrivatize.
empty())
9598 return OMPIRBuilder.Task;
9601 for (
Value *V : OffloadingArraysToPrivatize) {
9602 assert(V->getType()->isPointerTy() &&
9603 "Expected pointer to array to privatize. Got a non-pointer value "
9606 assert(ArrayTy &&
"ArrayType cannot be nullptr");
9612 "struct.task_with_privates");
9627 EntryFnName, Inputs, CBFunc,
9628 ArgAccessorFuncCB, OutlinedFnLoc);
9632 EntryInfo, GenerateOutlinedFunction, IsOffloadEntry, OutlinedFn,
9769 TargetTaskAllocaBB->
begin());
9772 auto OI = std::make_unique<OutlineInfo>();
9773 OI->EntryBB = TargetTaskAllocaBB;
9774 OI->OuterAllocBB = AllocaIP.
getBlock();
9779 Builder, AllocaIP, ToBeDeleted, TargetTaskAllocaIP,
"global.tid",
false));
9782 Builder.restoreIP(TargetTaskBodyIP);
9783 if (
Error Err = TaskBodyCB(DeviceID, RTLoc, TargetTaskAllocaIP))
9801 bool NeedsTargetTask = HasNoWait && DeviceID;
9802 if (NeedsTargetTask) {
9808 OffloadingArraysToPrivatize.
push_back(V);
9809 OI->ExcludeArgsFromAggregate.push_back(V);
9813 OI->PostOutlineCB = [
this, ToBeDeleted, Dependencies, NeedsTargetTask,
9814 DeviceID, OffloadingArraysToPrivatize](
9817 "there must be a single user for the outlined function");
9831 const unsigned int NumStaleCIArgs = StaleCI->
arg_size();
9832 bool HasShareds = NumStaleCIArgs > OffloadingArraysToPrivatize.
size() + 1;
9834 NumStaleCIArgs == (OffloadingArraysToPrivatize.
size() + 2)) &&
9835 "Wrong number of arguments for StaleCI when shareds are present");
9836 int SharedArgOperandNo =
9837 HasShareds ? OffloadingArraysToPrivatize.
size() + 1 : 0;
9843 if (!OffloadingArraysToPrivatize.
empty())
9848 *
this,
Builder, StaleCI, PrivatesTy, TaskWithPrivatesTy,
9849 OffloadingArraysToPrivatize.
size(), SharedArgOperandNo);
9851 LLVM_DEBUG(
dbgs() <<
"Proxy task entry function created: " << *ProxyFn
9854 Builder.SetInsertPoint(StaleCI);
9871 OMPRTL___kmpc_omp_target_task_alloc);
9883 M.getDataLayout().getTypeStoreSize(TaskWithPrivatesTy));
9890 auto *ArgStructAlloca =
9892 assert(ArgStructAlloca &&
9893 "Unable to find the alloca instruction corresponding to arguments "
9894 "for extracted function");
9895 std::optional<TypeSize> ArgAllocSize =
9898 "Unable to determine size of arguments for extracted function");
9899 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
9918 TaskSize, SharedsSize,
9921 if (NeedsTargetTask) {
9922 assert(DeviceID &&
"Expected non-empty device ID.");
9932 *
this,
Builder, TaskData, TaskWithPrivatesTy);
9936 if (!OffloadingArraysToPrivatize.
empty()) {
9938 Builder.CreateStructGEP(TaskWithPrivatesTy, TaskData, 1);
9939 for (
unsigned int i = 0; i < OffloadingArraysToPrivatize.
size(); ++i) {
9940 Value *PtrToPrivatize = OffloadingArraysToPrivatize[i];
9947 "ElementType should match ArrayType");
9950 Value *Dst =
Builder.CreateStructGEP(PrivatesTy, Privates, i);
9953 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(ElementType)));
9957 Value *DepArray =
nullptr;
9958 Value *NumDeps =
nullptr;
9961 NumDeps = Dependencies.
NumDeps;
9962 }
else if (!Dependencies.
Deps.empty()) {
9964 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
9975 if (!NeedsTargetTask) {
9984 ConstantInt::get(
Builder.getInt32Ty(), 0),
9997 }
else if (DepArray) {
10005 {Ident, ThreadID, TaskData, NumDeps, DepArray,
10006 ConstantInt::get(
Builder.getInt32Ty(), 0),
10014 Builder.ClearInsertionPoint();
10017 I->eraseFromParent();
10022 << *(
Builder.GetInsertBlock()) <<
"\n");
10024 << *(
Builder.GetInsertBlock()->getParent()->getParent())
10036 CustomMapperCB, IsNonContiguous, DeviceAddrCB))
10059 Builder.restoreIP(IP);
10065 return Builder.saveIP();
10068 bool HasDependencies = !Dependencies.
empty();
10069 bool RequiresOuterTargetTask = HasNoWait || HasDependencies;
10086 if (OutlinedFnID && DeviceID)
10088 EmitTargetCallFallbackCB, KArgs,
10089 DeviceID, RTLoc, TargetTaskAllocaIP);
10097 return EmitTargetCallFallbackCB(OMPBuilder.
Builder.
saveIP());
10104 auto &&EmitTargetCallElse =
10111 if (RequiresOuterTargetTask) {
10118 Dependencies, EmptyRTArgs, HasNoWait);
10120 return EmitTargetCallFallbackCB(Builder.saveIP());
10123 Builder.restoreIP(AfterIP);
10127 auto &&EmitTargetCallThen =
10131 Info.HasNoWait = HasNoWait;
10136 AllocaIP, Builder.saveIP(), Info, RTArgs, MapInfo, CustomMapperCB,
10142 for (
auto [DefaultVal, RuntimeVal] :
10144 NumTeamsC.
push_back(RuntimeVal ? RuntimeVal
10145 : Builder.getInt32(DefaultVal));
10149 auto InitMaxThreadsClause = [&Builder](
Value *
Clause) {
10151 Clause = Builder.CreateIntCast(
Clause, Builder.getInt32Ty(),
10155 auto CombineMaxThreadsClauses = [&Builder](
Value *
Clause,
Value *&Result) {
10158 Result ? Builder.CreateSelect(Builder.CreateICmpULT(Result,
Clause),
10166 Value *MaxThreadsClause =
10168 ? InitMaxThreadsClause(RuntimeAttrs.
MaxThreads.front())
10171 for (
auto [TeamsVal, TargetVal] :
zip_equal(
10173 Value *TeamsThreadLimitClause = InitMaxThreadsClause(TeamsVal);
10174 Value *NumThreads = InitMaxThreadsClause(TargetVal);
10176 CombineMaxThreadsClauses(TeamsThreadLimitClause, NumThreads);
10177 CombineMaxThreadsClauses(MaxThreadsClause, NumThreads);
10179 NumThreadsC.
push_back(NumThreads ? NumThreads : Builder.getInt32(0));
10182 unsigned NumTargetItems = Info.NumberOfPtrs;
10190 Builder.getInt64Ty(),
10192 : Builder.getInt64(0);
10196 DynCGroupMem = Builder.getInt32(0);
10199 NumTargetItems, RTArgs, TripCount, NumTeamsC, NumThreadsC, DynCGroupMem,
10200 HasNoWait,
false,
false,
10201 DynCGroupMemFallback);
10208 if (RequiresOuterTargetTask)
10210 RTLoc, AllocaIP, Dependencies,
10211 KArgs.
RTArgs, Info.HasNoWait);
10214 Builder, OutlinedFnID, EmitTargetCallFallbackCB, KArgs,
10215 RuntimeAttrs.
DeviceID, RTLoc, AllocaIP);
10218 Builder.restoreIP(AfterIP);
10225 if (!OutlinedFnID) {
10226 cantFail(EmitTargetCallElse(AllocaIP, Builder.saveIP(), DeallocBlocks));
10232 cantFail(EmitTargetCallThen(AllocaIP, Builder.saveIP(), DeallocBlocks));
10237 EmitTargetCallElse, AllocaIP));
10250 bool HasNowait,
Value *DynCGroupMem,
10257 Builder.restoreIP(CodeGenIP);
10265 *
this,
Builder, IsOffloadEntry, EntryInfo, DefaultAttrs, OutlinedFn,
10266 OutlinedFnID, Inputs, CBFunc, ArgAccessorFuncCB, OutlinedFnLoc))
10272 if (!
Config.isTargetDevice())
10274 RuntimeAttrs, IfCond, OutlinedFn, OutlinedFnID, Inputs,
10275 GenMapInfoCB, CustomMapperCB, Dependencies, HasNowait,
10276 DynCGroupMem, DynCGroupMemFallback);
10290 return OS.
str().str();
10295 return OpenMPIRBuilder::getNameWithSeparators(Parts,
Config.firstSeparator(),
10301 auto &Elem = *
InternalVars.try_emplace(Name,
nullptr).first;
10303 assert(Elem.second->getValueType() == Ty &&
10304 "OMP internal variable has different type than requested");
10317 :
M.getTargetTriple().isAMDGPU()
10319 :
DL.getDefaultGlobalsAddressSpace();
10320 auto Linkage = this->
M.getTargetTriple().isWasm()
10328 const llvm::Align PtrAlign =
DL.getPointerABIAlignment(AddressSpaceVal);
10329 GV->setAlignment(std::max(TypeAlign, PtrAlign));
10333 return Elem.second;
10336Value *OpenMPIRBuilder::getOMPCriticalRegionLock(
StringRef CriticalName) {
10337 std::string Prefix =
Twine(
"gomp_critical_user_", CriticalName).
str();
10338 std::string Name = getNameWithSeparators({Prefix,
"var"},
".",
".");
10349 return SizePtrToInt;
10354 std::string VarName) {
10362 return MaptypesArrayGlobal;
10367 unsigned NumOperands,
10376 ArrI8PtrTy,
nullptr,
".offload_baseptrs");
10380 ArrI64Ty,
nullptr,
".offload_sizes");
10391 int64_t DeviceID,
unsigned NumOperands) {
10397 Value *ArgsBaseGEP =
10399 {Builder.getInt32(0), Builder.getInt32(0)});
10402 {Builder.getInt32(0), Builder.getInt32(0)});
10403 Value *ArgSizesGEP =
10405 {Builder.getInt32(0), Builder.getInt32(0)});
10409 Builder.getInt32(NumOperands),
10410 ArgsBaseGEP, ArgsGEP, ArgSizesGEP,
10411 MaptypesArg, MapnamesArg, NullPtr});
10418 assert((!ForEndCall || Info.separateBeginEndCalls()) &&
10419 "expected region end call to runtime only when end call is separate");
10421 auto VoidPtrTy = UnqualPtrTy;
10422 auto VoidPtrPtrTy = UnqualPtrTy;
10424 auto Int64PtrTy = UnqualPtrTy;
10426 if (!Info.NumberOfPtrs) {
10438 Info.RTArgs.BasePointersArray,
10441 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray,
10445 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
10449 ForEndCall && Info.RTArgs.MapTypesArrayEnd ? Info.RTArgs.MapTypesArrayEnd
10450 : Info.RTArgs.MapTypesArray,
10456 if (!Info.EmitDebug)
10460 ArrayType::get(VoidPtrTy, Info.NumberOfPtrs), Info.RTArgs.MapNamesArray,
10465 if (!Info.HasMapper)
10469 Builder.CreatePointerCast(Info.RTArgs.MappersArray, VoidPtrPtrTy);
10490 "struct.descriptor_dim");
10492 enum { OffsetFD = 0, CountFD, StrideFD };
10496 for (
unsigned I = 0, L = 0, E = NonContigInfo.
Dims.
size();
I < E; ++
I) {
10499 if (NonContigInfo.
Dims[
I] == 1)
10504 Builder.CreateAlloca(ArrayTy,
nullptr,
"dims");
10505 Builder.restoreIP(CodeGenIP);
10506 for (
unsigned II = 0, EE = NonContigInfo.
Dims[
I];
II < EE; ++
II) {
10507 unsigned RevIdx = EE -
II - 1;
10511 Value *OffsetLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, OffsetFD);
10513 NonContigInfo.
Offsets[L][RevIdx], OffsetLVal,
10514 M.getDataLayout().getPrefTypeAlign(OffsetLVal->
getType()));
10516 Value *CountLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, CountFD);
10518 NonContigInfo.
Counts[L][RevIdx], CountLVal,
10519 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10521 Value *StrideLVal =
Builder.CreateStructGEP(DimTy, DimsLVal, StrideFD);
10523 NonContigInfo.
Strides[L][RevIdx], StrideLVal,
10524 M.getDataLayout().getPrefTypeAlign(CountLVal->
getType()));
10527 Builder.restoreIP(CodeGenIP);
10528 Value *DAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
10529 DimsAddr,
Builder.getPtrTy());
10532 Info.RTArgs.PointersArray, 0,
I);
10534 DAddr,
P,
M.getDataLayout().getPrefTypeAlign(
Builder.getPtrTy()));
10539void OpenMPIRBuilder::emitUDMapperArrayInitOrDel(
10543 StringRef Prefix = IsInit ?
".init" :
".del";
10549 Builder.CreateICmpSGT(
Size, Builder.getInt64(1),
"omp.arrayinit.isarray");
10550 Value *DeleteBit = Builder.CreateAnd(
10553 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10554 OpenMPOffloadMappingFlags::OMP_MAP_DELETE)));
10559 Value *BaseIsBegin = Builder.CreateICmpNE(
Base, Begin);
10560 Cond = Builder.CreateOr(IsArray, BaseIsBegin);
10561 DeleteCond = Builder.CreateIsNull(
10566 DeleteCond =
Builder.CreateIsNotNull(
10582 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10583 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10584 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10585 MapTypeArg =
Builder.CreateOr(
10588 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10589 OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT)));
10593 Value *OffloadingArgs[] = {MapperHandle,
Base, Begin,
10594 ArraySize, MapTypeArg, MapName};
10605 bool PreserveMemberOfFlags,
bool PropagatePresentToPointee) {
10621 MapperFn->
addFnAttr(Attribute::NoInline);
10622 MapperFn->
addFnAttr(Attribute::NoUnwind);
10633 Builder.SetInsertPoint(EntryBB);
10646 TypeSize ElementSize =
M.getDataLayout().getTypeStoreSize(ElemTy);
10648 Value *PtrBegin = BeginIn;
10654 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
10655 MapType, MapName, ElementSize, HeadBB,
10666 Builder.CreateICmpEQ(PtrBegin, PtrEnd,
"omp.arraymap.isempty");
10667 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
10673 Builder.CreatePHI(PtrBegin->
getType(), 2,
"omp.arraymap.ptrcurrent");
10674 PtrPHI->addIncoming(PtrBegin, HeadBB);
10679 return Info.takeError();
10683 Value *OffloadingArgs[] = {MapperHandle};
10687 Value *ShiftedPreviousSize =
10691 for (
unsigned I = 0;
I < Info->BasePointers.size(); ++
I) {
10692 Value *CurBaseArg = Info->BasePointers[
I];
10693 Value *CurBeginArg = Info->Pointers[
I];
10694 Value *CurSizeArg = Info->Sizes[
I];
10695 Value *CurNameArg = Info->Names.size()
10700 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10703 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10705 constexpr uint64_t MemberOfMask =
10706 static_cast<uint64_t
>(OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF);
10707 constexpr uint64_t AttachBit =
10708 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10709 OpenMPOffloadMappingFlags::OMP_MAP_ATTACH);
10767 Value *MemberMapType;
10768 if (PreserveMemberOfFlags || (RawType & AttachBit) ||
10769 Info->HasAttachPtr[
I]) {
10770 if (RawType & MemberOfMask)
10771 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
10773 MemberMapType = OriMapType;
10775 MemberMapType =
Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
10793 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10794 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10795 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10805 Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
10811 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10812 OpenMPOffloadMappingFlags::OMP_MAP_TO |
10813 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10819 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10820 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
10821 Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
10827 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10828 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10834 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10835 OpenMPOffloadMappingFlags::OMP_MAP_FROM)));
10836 Builder.CreateCondBr(IsFrom, FromBB, EndBB);
10842 ~
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10843 OpenMPOffloadMappingFlags::OMP_MAP_TO)));
10852 CurMapType->
addIncoming(MemberMapType, ToElseBB);
10889 uint64_t ModifierBits =
10890 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10891 OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS |
10892 OpenMPOffloadMappingFlags::OMP_MAP_DELETE |
10893 OpenMPOffloadMappingFlags::OMP_MAP_CLOSE);
10894 if (PropagatePresentToPointee && Info->HasAttachPtr[
I])
10896 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10897 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
10898 Value *ImportedModifierBits =
10901 CurMapType, ImportedModifierBits,
"omp.maptype.with.modifiers");
10906 Value *FinalMapType =
10907 (RawType & AttachBit) ? CurMapType : CurMapTypeWithModifiers;
10909 Value *OffloadingArgs[] = {MapperHandle, CurBaseArg, CurBeginArg,
10910 CurSizeArg, FinalMapType, CurNameArg};
10912 auto ChildMapperFn = CustomMapperCB(
I);
10913 if (!ChildMapperFn)
10914 return ChildMapperFn.takeError();
10915 if (*ChildMapperFn) {
10930 Value *PtrNext =
Builder.CreateConstGEP1_32(ElemTy, PtrPHI, 1,
10931 "omp.arraymap.next");
10932 PtrPHI->addIncoming(PtrNext, LastBB);
10933 Value *IsDone =
Builder.CreateICmpEQ(PtrNext, PtrEnd,
"omp.arraymap.isdone");
10935 Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
10940 emitUDMapperArrayInitOrDel(MapperFn, MapperHandle, BaseIn, BeginIn,
Size,
10941 MapType, MapName, ElementSize, DoneBB,
10954 bool IsNonContiguous,
10958 Info.clearArrayInfo();
10961 if (Info.NumberOfPtrs == 0)
10970 Info.RTArgs.BasePointersArray =
Builder.CreateAlloca(
10971 PointerArrayType,
nullptr,
".offload_baseptrs");
10973 Info.RTArgs.PointersArray =
Builder.CreateAlloca(
10974 PointerArrayType,
nullptr,
".offload_ptrs");
10976 PointerArrayType,
nullptr,
".offload_mappers");
10977 Info.RTArgs.MappersArray = MappersArray;
10984 ConstantInt::get(Int64Ty, 0));
10986 for (
unsigned I = 0, E = CombinedInfo.
Sizes.
size();
I < E; ++
I) {
10987 bool IsNonContigEntry =
10989 (
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
10991 OpenMPOffloadMappingFlags::OMP_MAP_NON_CONTIG) != 0);
10994 if (IsNonContigEntry) {
10996 "Index must be in-bounds for NON_CONTIG Dims array");
10998 assert(DimCount > 0 &&
"NON_CONTIG DimCount must be > 0");
10999 ConstSizes[
I] = ConstantInt::get(Int64Ty, DimCount);
11004 ConstSizes[
I] = CI;
11008 RuntimeSizes.
set(
I);
11011 if (RuntimeSizes.
all()) {
11013 Info.RTArgs.SizesArray =
Builder.CreateAlloca(
11014 SizeArrayType,
nullptr,
".offload_sizes");
11020 auto *SizesArrayGbl =
11025 if (!RuntimeSizes.
any()) {
11026 Info.RTArgs.SizesArray = SizesArrayGbl;
11028 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
11029 Align OffloadSizeAlign =
M.getDataLayout().getABIIntegerTypeAlignment(64);
11032 SizeArrayType,
nullptr,
".offload_sizes");
11036 Buffer,
M.getDataLayout().getPrefTypeAlign(Buffer->
getType()),
11037 SizesArrayGbl, OffloadSizeAlign,
11042 Info.RTArgs.SizesArray = Buffer;
11050 for (
auto mapFlag : CombinedInfo.
Types)
11052 static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11056 Info.RTArgs.MapTypesArray = MapTypesArrayGbl;
11062 Info.RTArgs.MapNamesArray = MapNamesArrayGbl;
11063 Info.EmitDebug =
true;
11065 Info.RTArgs.MapNamesArray =
11067 Info.EmitDebug =
false;
11072 if (Info.separateBeginEndCalls()) {
11073 bool EndMapTypesDiffer =
false;
11074 for (uint64_t &
Type : Mapping) {
11075 if (
Type &
static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>
>(
11076 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT)) {
11077 Type &= ~static_cast<std::underlying_type_t<OpenMPOffloadMappingFlags>>(
11078 OpenMPOffloadMappingFlags::OMP_MAP_PRESENT);
11079 EndMapTypesDiffer =
true;
11082 if (EndMapTypesDiffer) {
11084 Info.RTArgs.MapTypesArrayEnd = MapTypesArrayGbl;
11089 for (
unsigned I = 0;
I < Info.NumberOfPtrs; ++
I) {
11092 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.BasePointersArray,
11094 Builder.CreateAlignedStore(BPVal, BP,
11095 M.getDataLayout().getPrefTypeAlign(PtrTy));
11097 if (Info.requiresDevicePointerInfo()) {
11099 CodeGenIP =
Builder.saveIP();
11101 Info.DevicePtrInfoMap[BPVal] = {BP,
Builder.CreateAlloca(PtrTy)};
11104 DeviceAddrCB(
I, Info.DevicePtrInfoMap[BPVal].second);
11106 Info.DevicePtrInfoMap[BPVal] = {BP, BP};
11108 DeviceAddrCB(
I, BP);
11114 ArrayType::get(PtrTy, Info.NumberOfPtrs), Info.RTArgs.PointersArray, 0,
11117 Builder.CreateAlignedStore(PVal,
P,
11118 M.getDataLayout().getPrefTypeAlign(PtrTy));
11120 if (RuntimeSizes.
test(
I)) {
11122 ArrayType::get(Int64Ty, Info.NumberOfPtrs), Info.RTArgs.SizesArray,
11128 S,
M.getDataLayout().getPrefTypeAlign(PtrTy));
11131 unsigned IndexSize =
M.getDataLayout().getIndexSizeInBits(0);
11134 auto CustomMFunc = CustomMapperCB(
I);
11136 return CustomMFunc.takeError();
11138 MFunc =
Builder.CreatePointerCast(*CustomMFunc, PtrTy);
11141 PointerArrayType, MappersArray,
11144 MFunc, MAddr,
M.getDataLayout().getPrefTypeAlign(MAddr->
getType()));
11148 Info.NumberOfPtrs == 0)
11165 Builder.ClearInsertionPoint();
11196 auto CondConstant = CI->getSExtValue();
11198 return ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
11200 return ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
11210 Builder.CreateCondBr(
Cond, ThenBlock, ElseBlock);
11213 if (
Error Err = ThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks))
11219 if (
Error Err = ElseGen(AllocaIP,
Builder.saveIP(), DeallocBlocks))
11228bool OpenMPIRBuilder::checkAndEmitFlushAfterAtomic(
11232 "Unexpected Atomic Ordering.");
11234 bool Flush =
false;
11296 assert(
X.Var->getType()->isPointerTy() &&
11297 "OMP Atomic expects a pointer to target memory");
11298 Type *XElemTy =
X.ElemTy;
11301 "OMP atomic read expected a scalar type");
11303 Value *XRead =
nullptr;
11307 Builder.CreateLoad(XElemTy,
X.Var,
X.IsVolatile,
"omp.atomic.read");
11316 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11319 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11321 XRead = AtomicLoadRes.first;
11328 Builder.CreateLoad(IntCastTy,
X.Var,
X.IsVolatile,
"omp.atomic.load");
11331 XRead =
Builder.CreateBitCast(XLoad, XElemTy,
"atomic.flt.cast");
11333 XRead =
Builder.CreateIntToPtr(XLoad, XElemTy,
"atomic.ptr.cast");
11336 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Read);
11337 Builder.CreateStore(XRead, V.Var, V.IsVolatile);
11348 assert(
X.Var->getType()->isPointerTy() &&
11349 "OMP Atomic expects a pointer to target memory");
11350 Type *XElemTy =
X.ElemTy;
11353 "OMP atomic write expected a scalar type");
11361 unsigned LoadSize =
DL.getTypeStoreSize(XElemTy);
11364 OldVal->
getAlign(),
true , AllocaIP,
X.Var);
11372 Builder.CreateBitCast(Expr, IntCastTy,
"atomic.src.int.cast");
11377 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Write);
11384 AtomicUpdateCallbackTy &UpdateOp,
bool IsXBinopExpr,
11385 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11391 Type *XTy =
X.Var->getType();
11393 "OMP Atomic expects a pointer to target memory");
11394 Type *XElemTy =
X.ElemTy;
11397 "OMP atomic update expected a scalar or struct type");
11400 "OpenMP atomic does not support LT or GT operations");
11404 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, RMWOp, UpdateOp,
X.IsVolatile,
11405 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11407 return AtomicResult.takeError();
11408 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Update);
11413Value *OpenMPIRBuilder::emitRMWOpAsInstruction(
Value *Src1,
Value *Src2,
11417 return Builder.CreateAdd(Src1, Src2);
11419 return Builder.CreateSub(Src1, Src2);
11421 return Builder.CreateAnd(Src1, Src2);
11423 return Builder.CreateNeg(Builder.CreateAnd(Src1, Src2));
11425 return Builder.CreateOr(Src1, Src2);
11427 return Builder.CreateXor(Src1, Src2);
11466Expected<std::pair<Value *, Value *>> OpenMPIRBuilder::emitAtomicUpdate(
11469 AtomicUpdateCallbackTy &UpdateOp,
bool VolatileX,
bool IsXBinopExpr,
11470 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11472 bool emitRMWOp =
false;
11480 emitRMWOp = XElemTy;
11483 emitRMWOp = (IsXBinopExpr && XElemTy);
11490 std::pair<Value *, Value *> Res;
11492 AtomicRMWInst *RMWInst =
11493 Builder.CreateAtomicRMW(RMWOp,
X, Expr, llvm::MaybeAlign(), AO);
11494 if (
T.isAMDGPU()) {
11495 if (IsIgnoreDenormalMode)
11496 RMWInst->
setMetadata(
"amdgpu.ignore.denormal.mode",
11498 if (!IsFineGrainedMemory)
11499 RMWInst->
setMetadata(
"amdgpu.no.fine.grained.memory",
11501 if (!IsRemoteMemory)
11505 Res.first = RMWInst;
11510 Res.second = Res.first;
11512 Res.second = emitRMWOpAsInstruction(Res.first, Expr, RMWOp);
11515 Builder.CreateLoad(XElemTy,
X,
X->getName() +
".atomic.load");
11521 OpenMPIRBuilder::AtomicInfo atomicInfo(
11523 OldVal->
getAlign(),
true , AllocaIP,
X);
11524 auto AtomicLoadRes = atomicInfo.EmitAtomicLoadLibcall(AO);
11527 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11534 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11535 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11536 Builder.SetInsertPoint(ContBB);
11538 PHI->addIncoming(AtomicLoadRes.first, CurBB);
11540 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11543 Value *Upd = *CBResult;
11544 Builder.CreateStore(Upd, NewAtomicAddr);
11547 auto Result = atomicInfo.EmitAtomicCompareExchangeLibcall(
11548 AtomicLoadRes.second, NewAtomicAddr, AO, Failure);
11549 LoadInst *PHILoad =
Builder.CreateLoad(XElemTy,
Result.first);
11550 PHI->addIncoming(PHILoad,
Builder.GetInsertBlock());
11553 Res.first = OldExprVal;
11556 if (UnreachableInst *ExitTI =
11559 Builder.SetInsertPoint(ExitBB);
11561 Builder.SetInsertPoint(ExitTI);
11564 IntegerType *IntCastTy =
11567 Builder.CreateLoad(IntCastTy,
X,
X->getName() +
".atomic.load");
11577 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11584 AllocaInst *NewAtomicAddr =
Builder.CreateAlloca(XElemTy);
11585 NewAtomicAddr->
setName(
X->getName() +
"x.new.val");
11586 Builder.SetInsertPoint(ContBB);
11588 PHI->addIncoming(OldVal, CurBB);
11593 OldExprVal =
Builder.CreateBitCast(
PHI, XElemTy,
11594 X->getName() +
".atomic.fltCast");
11596 OldExprVal =
Builder.CreateIntToPtr(
PHI, XElemTy,
11597 X->getName() +
".atomic.ptrCast");
11601 Expected<Value *> CBResult = UpdateOp(OldExprVal,
Builder);
11604 Value *Upd = *CBResult;
11605 Builder.CreateStore(Upd, NewAtomicAddr);
11606 LoadInst *DesiredVal =
Builder.CreateLoad(IntCastTy, NewAtomicAddr);
11610 X,
PHI, DesiredVal, llvm::MaybeAlign(), AO, Failure);
11611 Result->setVolatile(VolatileX);
11612 Value *PreviousVal =
Builder.CreateExtractValue(Result, 0);
11613 Value *SuccessFailureVal =
Builder.CreateExtractValue(Result, 1);
11614 PHI->addIncoming(PreviousVal,
Builder.GetInsertBlock());
11615 Builder.CreateCondBr(SuccessFailureVal, ExitBB, ContBB);
11617 Res.first = OldExprVal;
11621 if (UnreachableInst *ExitTI =
11624 Builder.SetInsertPoint(ExitBB);
11626 Builder.SetInsertPoint(ExitTI);
11637 bool UpdateExpr,
bool IsPostfixUpdate,
bool IsXBinopExpr,
11638 bool IsIgnoreDenormalMode,
bool IsFineGrainedMemory,
bool IsRemoteMemory) {
11643 Type *XTy =
X.Var->getType();
11645 "OMP Atomic expects a pointer to target memory");
11646 Type *XElemTy =
X.ElemTy;
11649 "OMP atomic capture expected a scalar or struct type");
11651 "OpenMP atomic does not support LT or GT operations");
11658 AllocaIP,
X.Var,
X.ElemTy, Expr, AO, AtomicOp, UpdateOp,
X.IsVolatile,
11659 IsXBinopExpr, IsIgnoreDenormalMode, IsFineGrainedMemory, IsRemoteMemory);
11662 Value *CapturedVal =
11663 (IsPostfixUpdate ? AtomicResult->first : AtomicResult->second);
11664 Builder.CreateStore(CapturedVal, V.Var, V.IsVolatile);
11666 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Capture);
11674 bool IsFailOnly,
bool IsWeak) {
11678 IsPostfixUpdate, IsFailOnly, Failure, IsWeak);
11690 assert(
X.Var->getType()->isPointerTy() &&
11691 "OMP atomic expects a pointer to target memory");
11694 assert(V.Var->getType()->isPointerTy() &&
"v.var must be of pointer type");
11695 assert(V.ElemTy ==
X.ElemTy &&
"x and v must be of same type");
11698 bool IsInteger = E->getType()->isIntegerTy();
11700 if (
Op == OMPAtomicCompareOp::EQ) {
11703 Value *OldValue =
nullptr;
11704 Value *SuccessOrFail =
nullptr;
11742 X.Var->getName() +
".atomic.load");
11748 Value *EIsNaN =
Builder.CreateFCmpUNO(E, E,
"atomic.e.isnan");
11749 Value *XIsNaN =
Builder.CreateFCmpUNO(XFP, XFP,
"atomic.x.isnan");
11750 Value *EitherNaN =
Builder.CreateOr(EIsNaN, XIsNaN,
"atomic.either.nan");
11755 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11759 M.getContext(),
X.Var->getName() +
".atomic.nan",
F, ExitBB);
11761 M.getContext(),
X.Var->getName() +
".atomic.notnan",
F, ExitBB);
11763 M.getContext(),
X.Var->getName() +
".atomic.zero",
F, ExitBB);
11765 M.getContext(),
X.Var->getName() +
".atomic.normal",
F, ExitBB);
11769 Builder.SetInsertPoint(CurBB);
11770 Builder.CreateCondBr(EitherNaN, NaNBB, NotNaNBB);
11773 Builder.SetInsertPoint(NaNBB);
11777 Builder.SetInsertPoint(NotNaNBB);
11780 X.Var->getName() +
".atomic.xiszero");
11782 "atomic.e.iszero");
11783 Value *BothZero =
Builder.CreateAnd(XIsZero, EIsZero,
"atomic.both.zero");
11784 Builder.CreateCondBr(BothZero, ZeroBB, NormalBB);
11787 Builder.SetInsertPoint(ZeroBB);
11789 X.Var, XCurr, DBCast,
MaybeAlign(), AO, Failure);
11791 Value *OldZero =
Builder.CreateExtractValue(ResZero, 0);
11792 Value *OkZero =
Builder.CreateExtractValue(ResZero, 1);
11796 Builder.SetInsertPoint(NormalBB);
11798 X.Var, EBCast, DBCast,
MaybeAlign(), AO, Failure);
11800 Value *OldNormal =
Builder.CreateExtractValue(ResNormal, 0);
11801 Value *OkNormal =
Builder.CreateExtractValue(ResNormal, 1);
11807 Builder.CreatePHI(IntCastTy, 3,
X.Var->getName() +
".atomic.old");
11812 X.Var->getName() +
".atomic.ok");
11819 Builder.SetInsertPoint(ExitBB);
11824 OldValue =
Builder.CreateBitCast(OldIntPHI,
X.ElemTy,
11825 X.Var->getName() +
".atomic.old.fp");
11826 SuccessOrFail = SuccessPHI;
11834 Result =
Builder.CreateAtomicCmpXchg(
X.Var, EBCast, DBCast,
11840 Result->setWeak(IsWeak);
11843 OldValue =
Builder.CreateExtractValue(Result, 0);
11845 OldValue =
Builder.CreateBitCast(OldValue,
X.ElemTy);
11847 "OldValue and V must be of same type");
11848 if (IsPostfixUpdate) {
11849 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
11851 SuccessOrFail =
Builder.CreateExtractValue(Result, 1);
11855 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11857 CurBBTI,
X.Var->getName() +
".atomic.exit");
11863 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
11865 Builder.SetInsertPoint(ContBB);
11866 Builder.CreateStore(OldValue, V.Var);
11872 Builder.SetInsertPoint(ExitBB);
11874 Builder.SetInsertPoint(ExitTI);
11877 Value *CapturedValue =
11878 Builder.CreateSelect(SuccessOrFail, E, OldValue);
11879 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
11885 assert(R.Var->getType()->isPointerTy() &&
11886 "r.var must be of pointer type");
11887 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
11889 Value *SuccessFailureVal =
11890 Builder.CreateExtractValue(Result, 1);
11891 Value *ResultCast =
11892 R.IsSigned ?
Builder.CreateSExt(SuccessFailureVal, R.ElemTy)
11893 :
Builder.CreateZExt(SuccessFailureVal, R.ElemTy);
11894 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
11903 "OldValue and V must be of same type");
11904 if (IsPostfixUpdate) {
11905 Builder.CreateStore(OldValue, V.Var, V.IsVolatile);
11910 CurBBTI = CurBBTI ? CurBBTI :
Builder.CreateUnreachable();
11912 CurBBTI,
X.Var->getName() +
".atomic.exit");
11918 Builder.CreateCondBr(SuccessOrFail, ExitBB, ContBB);
11920 Builder.SetInsertPoint(ContBB);
11921 Builder.CreateStore(OldValue, V.Var);
11927 Builder.SetInsertPoint(ExitBB);
11929 Builder.SetInsertPoint(ExitTI);
11932 Value *CapturedValue =
11933 Builder.CreateSelect(SuccessOrFail, E, OldValue);
11934 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
11940 assert(R.Var->getType()->isPointerTy() &&
11941 "r.var must be of pointer type");
11942 assert(R.ElemTy->isIntegerTy() &&
"r must be of integral type");
11944 Value *ResultCast = R.IsSigned
11945 ?
Builder.CreateSExt(SuccessOrFail, R.ElemTy)
11946 :
Builder.CreateZExt(SuccessOrFail, R.ElemTy);
11947 Builder.CreateStore(ResultCast, R.Var, R.IsVolatile);
11951 assert((
Op == OMPAtomicCompareOp::MAX ||
Op == OMPAtomicCompareOp::MIN) &&
11952 "Op should be either max or min at this point");
11953 assert(!IsFailOnly &&
"IsFailOnly is only valid when the comparison is ==");
11964 if (IsXBinopExpr) {
11993 Value *CapturedValue =
nullptr;
11994 if (IsPostfixUpdate) {
11995 CapturedValue = OldValue;
12020 Value *NonAtomicCmp =
Builder.CreateCmp(Pred, OldValue, E);
12021 CapturedValue =
Builder.CreateSelect(NonAtomicCmp, E, OldValue);
12023 Builder.CreateStore(CapturedValue, V.Var, V.IsVolatile);
12027 checkAndEmitFlushAfterAtomic(
Loc, AO, AtomicKind::Compare);
12047 if (&OuterAllocaBB ==
Builder.GetInsertBlock()) {
12074 bool SubClausesPresent =
12075 (NumTeamsLower || NumTeamsUpper || ThreadLimit || IfExpr);
12077 if (!
Config.isTargetDevice() && SubClausesPresent) {
12078 assert((NumTeamsLower ==
nullptr || NumTeamsUpper !=
nullptr) &&
12079 "if lowerbound is non-null, then upperbound must also be non-null "
12080 "for bounds on num_teams");
12082 if (NumTeamsUpper ==
nullptr)
12083 NumTeamsUpper =
Builder.getInt32(0);
12085 if (NumTeamsLower ==
nullptr)
12086 NumTeamsLower = NumTeamsUpper;
12090 "argument to if clause must be an integer value");
12094 IfExpr =
Builder.CreateICmpNE(IfExpr,
12095 ConstantInt::get(IfExpr->
getType(), 0));
12096 NumTeamsUpper =
Builder.CreateSelect(
12097 IfExpr, NumTeamsUpper,
Builder.getInt32(1),
"numTeamsUpper");
12100 NumTeamsLower =
Builder.CreateSelect(
12101 IfExpr, NumTeamsLower,
Builder.getInt32(1),
"numTeamsLower");
12104 if (ThreadLimit ==
nullptr)
12105 ThreadLimit =
Builder.getInt32(0);
12109 Value *NumTeamsLowerInt32 =
12111 Value *NumTeamsUpperInt32 =
12113 Value *ThreadLimitInt32 =
12120 {Ident, ThreadNum, NumTeamsLowerInt32, NumTeamsUpperInt32,
12121 ThreadLimitInt32});
12126 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
12129 auto OI = std::make_unique<OutlineInfo>();
12130 OI->EntryBB = AllocaBB;
12131 OI->ExitBB = ExitBB;
12132 OI->OuterAllocBB = &OuterAllocaBB;
12138 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"gid",
true));
12140 Builder, OuterAllocaIP, ToBeDeleted, AllocaIP,
"tid",
true));
12142 auto HostPostOutlineCB = [
this, Ident,
12143 ToBeDeleted](
Function &OutlinedFn)
mutable {
12148 "there must be a single user for the outlined function");
12153 "Outlined function must have two or three arguments only");
12155 bool HasShared = OutlinedFn.
arg_size() == 3;
12163 assert(StaleCI &&
"Error while outlining - no CallInst user found for the "
12164 "outlined function.");
12165 Builder.SetInsertPoint(StaleCI);
12172 omp::RuntimeFunction::OMPRTL___kmpc_fork_teams),
12175 Builder.ClearInsertionPoint();
12177 I->eraseFromParent();
12180 if (!
Config.isTargetDevice())
12181 OI->PostOutlineCB = HostPostOutlineCB;
12185 Builder.SetInsertPoint(ExitBB);
12198 if (OuterAllocaBB ==
Builder.GetInsertBlock()) {
12213 if (
Error Err = BodyGenCB(AllocaIP, CodeGenIP, ExitBB))
12218 if (
Config.isTargetDevice()) {
12219 auto OI = std::make_unique<OutlineInfo>();
12220 OI->OuterAllocBB = OuterAllocIP.
getBlock();
12221 OI->EntryBB = AllocaBB;
12222 OI->ExitBB = ExitBB;
12223 OI->OuterDeallocBBs.reserve(OuterDeallocBlocks.
size());
12224 copy(OuterDeallocBlocks, OI->OuterDeallocBBs.
end());
12228 Builder.SetInsertPoint(ExitBB);
12235 std::string VarName) {
12244 return MapNamesArrayGlobal;
12249void OpenMPIRBuilder::initializeTypes(
Module &M) {
12253 unsigned ProgramAS = M.getDataLayout().getProgramAddressSpace();
12254#define OMP_TYPE(VarName, InitValue) VarName = InitValue;
12255#define OMP_ARRAY_TYPE(VarName, ElemTy, ArraySize) \
12256 VarName##Ty = ArrayType::get(ElemTy, ArraySize); \
12257 VarName##PtrTy = PointerType::get(Ctx, DefaultTargetAS);
12258#define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) \
12259 VarName = FunctionType::get(ReturnType, {__VA_ARGS__}, IsVarArg); \
12260 VarName##Ptr = PointerType::get(Ctx, ProgramAS);
12261#define OMP_STRUCT_TYPE(VarName, StructName, Packed, ...) \
12262 T = StructType::getTypeByName(Ctx, StructName); \
12264 T = StructType::create(Ctx, {__VA_ARGS__}, StructName, Packed); \
12266 VarName##Ptr = PointerType::get(Ctx, DefaultTargetAS);
12267#include "llvm/Frontend/OpenMP/OMPKinds.def"
12278 while (!Worklist.
empty()) {
12282 if (
BlockSet.insert(SuccBB).second)
12287std::unique_ptr<CodeExtractor>
12289 bool ArgsInZeroAddressSpace,
12291 return std::make_unique<CodeExtractor>(
12301 Suffix.
str(), ArgsInZeroAddressSpace);
12304std::unique_ptr<CodeExtractor> DeviceSharedMemOutlineInfo::createCodeExtractor(
12306 return std::make_unique<DeviceSharedMemCodeExtractor>(
12307 OMPBuilder, Blocks,
nullptr,
12315 OuterDeallocBBs.empty()
12318 Suffix.
str(), ArgsInZeroAddressSpace);
12322 uint64_t
Size, int32_t Flags,
12328 Name.empty() ? Addr->
getName() : Name,
Size, Flags, 0);
12340 Fn->
addFnAttr(
"uniform-work-group-size");
12341 Fn->
addFnAttr(Attribute::MustProgress);
12359 auto &&GetMDInt = [
this](
unsigned V) {
12366 NamedMDNode *MD =
M.getOrInsertNamedMetadata(
"omp_offload.info");
12367 auto &&TargetRegionMetadataEmitter =
12368 [&
C, MD, &OrderedEntries, &GetMDInt, &GetMDString](
12383 GetMDInt(E.getKind()), GetMDInt(EntryInfo.DeviceID),
12384 GetMDInt(EntryInfo.FileID), GetMDString(EntryInfo.ParentName),
12385 GetMDInt(EntryInfo.Line), GetMDInt(EntryInfo.Count),
12386 GetMDInt(E.getOrder())};
12389 OrderedEntries[E.getOrder()] = std::make_pair(&E, EntryInfo);
12398 auto &&DeviceGlobalVarMetadataEmitter =
12399 [&
C, &OrderedEntries, &GetMDInt, &GetMDString, MD](
12409 Metadata *
Ops[] = {GetMDInt(E.getKind()), GetMDString(MangledName),
12410 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
12414 OrderedEntries[E.getOrder()] = std::make_pair(&E, varInfo);
12421 DeviceGlobalVarMetadataEmitter);
12423 for (
const auto &E : OrderedEntries) {
12424 assert(E.first &&
"All ordered entries must exist!");
12425 if (
const auto *CE =
12428 if (!CE->getID() || !CE->getAddress()) {
12432 if (!
M.getNamedValue(FnName))
12440 }
else if (
const auto *CE =
dyn_cast<
12449 if (
Config.isTargetDevice() &&
Config.hasRequiresUnifiedSharedMemory())
12451 if (!CE->getAddress()) {
12456 if (CE->getVarSize() == 0)
12460 assert(((
Config.isTargetDevice() && !CE->getAddress()) ||
12461 (!
Config.isTargetDevice() && CE->getAddress())) &&
12462 "Declaret target link address is set.");
12463 if (
Config.isTargetDevice())
12465 if (!CE->getAddress()) {
12472 if (!CE->getAddress()) {
12485 if ((
GV->hasLocalLinkage() ||
GV->hasHiddenVisibility()) &&
12489 OMPTargetGlobalVarEntryIndirectVTable))
12498 Flags, CE->getLinkage(), CE->getVarName());
12501 Flags, CE->getLinkage());
12512 if (
Config.hasRequiresFlags() && !
Config.isTargetDevice())
12518 Config.getRequiresFlags());
12528 OS <<
"_" <<
Count;
12533 unsigned NewCount = getTargetRegionEntryInfoCount(EntryInfo);
12536 EntryInfo.
Line, NewCount);
12544 auto FileIDInfo = CallBack();
12545 uint64_t FileID = 0;
12547 ID =
Status->getUniqueID();
12548 FileID =
Status->getUniqueID().getFile();
12552 FileID =
hash_value(std::get<0>(FileIDInfo));
12556 std::get<1>(FileIDInfo));
12561 for (uint64_t Remain =
12562 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12564 !(Remain & 1); Remain = Remain >> 1)
12582 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12584 static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12591 if (
static_cast<std::underlying_type_t<omp::OpenMPOffloadMappingFlags>
>(
12597 Flags &=
~omp::OpenMPOffloadMappingFlags::OMP_MAP_MEMBER_OF;
12598 Flags |= MemberOfFlag;
12604 bool IsDeclaration,
bool IsExternallyVisible,
12606 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12607 std::vector<Triple> TargetTriple,
Type *LlvmPtrTy,
12608 std::function<
Constant *()> GlobalInitializer,
12619 Config.hasRequiresUnifiedSharedMemory())) {
12624 if (!IsExternallyVisible)
12626 OS <<
"_decl_tgt_ref_ptr";
12629 Value *Ptr =
M.getNamedValue(PtrName);
12638 if (!
Config.isTargetDevice()) {
12639 if (GlobalInitializer)
12640 GV->setInitializer(GlobalInitializer());
12646 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12647 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12648 GlobalInitializer, VariableLinkage, LlvmPtrTy,
cast<Constant>(Ptr));
12660 bool IsDeclaration,
bool IsExternallyVisible,
12662 std::vector<GlobalVariable *> &GeneratedRefs,
bool OpenMPSIMD,
12663 std::vector<Triple> TargetTriple,
12664 std::function<
Constant *()> GlobalInitializer,
12668 (TargetTriple.empty() && !
Config.isTargetDevice()))
12679 !
Config.hasRequiresUnifiedSharedMemory()) {
12681 VarName = MangledName;
12684 if (!IsDeclaration)
12686 M.getDataLayout().getTypeSizeInBits(LlvmVal->
getValueType()), 8);
12689 Linkage = (VariableLinkage) ? VariableLinkage() : LlvmVal->
getLinkage();
12693 if (
Config.isTargetDevice() &&
12702 if (!
M.getNamedValue(RefName)) {
12706 GvAddrRef->setConstant(
true);
12708 GvAddrRef->setInitializer(Addr);
12709 GeneratedRefs.push_back(GvAddrRef);
12718 if (
Config.isTargetDevice()) {
12719 VarName = (Addr) ? Addr->
getName() :
"";
12723 CaptureClause, DeviceClause, IsDeclaration, IsExternallyVisible,
12724 EntryInfo, MangledName, GeneratedRefs, OpenMPSIMD, TargetTriple,
12725 LlvmPtrTy, GlobalInitializer, VariableLinkage);
12726 VarName = (Addr) ? Addr->
getName() :
"";
12728 VarSize =
M.getDataLayout().getPointerSize();
12747 auto &&GetMDInt = [MN](
unsigned Idx) {
12752 auto &&GetMDString = [MN](
unsigned Idx) {
12754 return V->getString();
12757 switch (GetMDInt(0)) {
12761 case OffloadEntriesInfoManager::OffloadEntryInfo::
12762 OffloadingEntryInfoTargetRegion: {
12772 case OffloadEntriesInfoManager::OffloadEntryInfo::
12773 OffloadingEntryInfoDeviceGlobalVar:
12786 if (HostFilePath.
empty())
12790 if (std::error_code Err = Buf.getError()) {
12792 "OpenMPIRBuilder: " +
12800 if (std::error_code Err =
M.getError()) {
12802 (
"error parsing host file inside of OpenMPIRBuilder: " + Err.message())
12816 "expected a valid insertion block for creating an iterator loop");
12826 Builder.getCurrentDebugLocation(),
"omp.it.cont");
12838 T->eraseFromParent();
12847 if (!BodyBr || BodyBr->getSuccessor() != CLI->
getLatch()) {
12849 "iterator bodygen must terminate the canonical body with an "
12850 "unconditional branch to the loop latch",
12874 for (
const auto &
ParamAttr : ParamAttrs) {
12917 return std::string(Out.
str());
12925 unsigned VecRegSize;
12927 ISADataTy ISAData[] = {
12946 for (
char Mask :
Masked) {
12947 for (
const ISADataTy &
Data : ISAData) {
12950 Out <<
"_ZGV" <<
Data.ISA << Mask;
12952 assert(NumElts &&
"Non-zero simdlen/cdtsize expected");
12966template <
typename T>
12969 StringRef MangledName,
bool OutputBecomesInput,
12973 Out << Prefix << ISA << LMask << VLEN;
12974 if (OutputBecomesInput)
12976 Out << ParSeq <<
'_' << MangledName;
12985 bool OutputBecomesInput,
12990 OutputBecomesInput, Fn);
12992 OutputBecomesInput, Fn);
12996 OutputBecomesInput, Fn);
12998 OutputBecomesInput, Fn);
13002 OutputBecomesInput, Fn);
13004 OutputBecomesInput, Fn);
13009 OutputBecomesInput, Fn);
13020 char ISA,
unsigned NarrowestDataSize,
bool OutputBecomesInput) {
13021 assert((ISA ==
'n' || ISA ==
's') &&
"Expected ISA either 's' or 'n'.");
13033 OutputBecomesInput, Fn);
13040 OutputBecomesInput, Fn);
13042 OutputBecomesInput, Fn);
13046 OutputBecomesInput, Fn);
13050 OutputBecomesInput, Fn);
13059 OutputBecomesInput, Fn);
13066 MangledName, OutputBecomesInput, Fn);
13068 MangledName, OutputBecomesInput, Fn);
13072 MangledName, OutputBecomesInput, Fn);
13076 MangledName, OutputBecomesInput, Fn);
13086 return OffloadEntriesTargetRegion.empty() &&
13087 OffloadEntriesDeviceGlobalVar.empty();
13090unsigned OffloadEntriesInfoManager::getTargetRegionEntryInfoCount(
13092 auto It = OffloadEntriesTargetRegionCount.find(
13093 getTargetRegionEntryCountKey(EntryInfo));
13094 if (It == OffloadEntriesTargetRegionCount.end())
13099void OffloadEntriesInfoManager::incrementTargetRegionEntryInfoCount(
13101 OffloadEntriesTargetRegionCount[getTargetRegionEntryCountKey(EntryInfo)] =
13102 EntryInfo.
Count + 1;
13108 OffloadEntriesTargetRegion[EntryInfo] =
13111 ++OffloadingEntriesNum;
13117 assert(EntryInfo.
Count == 0 &&
"expected default EntryInfo");
13120 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
13124 if (OMPBuilder->Config.isTargetDevice()) {
13129 auto &Entry = OffloadEntriesTargetRegion[EntryInfo];
13130 Entry.setAddress(Addr);
13132 Entry.setFlags(Flags);
13138 "Target region entry already registered!");
13140 OffloadEntriesTargetRegion[EntryInfo] = Entry;
13141 ++OffloadingEntriesNum;
13143 incrementTargetRegionEntryInfoCount(EntryInfo);
13150 EntryInfo.
Count = getTargetRegionEntryInfoCount(EntryInfo);
13152 auto It = OffloadEntriesTargetRegion.find(EntryInfo);
13153 if (It == OffloadEntriesTargetRegion.end()) {
13157 if (!IgnoreAddressId && (It->second.getAddress() || It->second.getID()))
13165 for (
const auto &It : OffloadEntriesTargetRegion) {
13166 Action(It.first, It.second);
13172 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
13173 ++OffloadingEntriesNum;
13179 if (OMPBuilder->Config.isTargetDevice()) {
13183 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
13185 if (Entry.getVarSize() == 0) {
13186 Entry.setVarSize(VarSize);
13187 Entry.setLinkage(Linkage);
13191 Entry.setVarSize(VarSize);
13192 Entry.setLinkage(Linkage);
13193 Entry.setAddress(Addr);
13196 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
13197 assert(Entry.isValid() && Entry.getFlags() == Flags &&
13198 "Entry not initialized!");
13199 if (Entry.getVarSize() == 0) {
13200 Entry.setVarSize(VarSize);
13201 Entry.setLinkage(Linkage);
13208 OffloadEntriesDeviceGlobalVar.try_emplace(VarName, OffloadingEntriesNum,
13209 Addr, VarSize, Flags, Linkage,
13212 OffloadEntriesDeviceGlobalVar.try_emplace(
13213 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage,
"");
13214 ++OffloadingEntriesNum;
13221 for (
const auto &E : OffloadEntriesDeviceGlobalVar)
13222 Action(E.getKey(), E.getValue());
13229void CanonicalLoopInfo::collectControlBlocks(
13236 BBs.
append({getPreheader(), Header,
Cond, Latch, Exit, getAfter()});
13248void CanonicalLoopInfo::setTripCount(
Value *TripCount) {
13260void CanonicalLoopInfo::mapIndVar(
13270 for (
Use &U : OldIV->
uses()) {
13274 if (
User->getParent() == getCond())
13276 if (
User->getParent() == getLatch())
13282 Value *NewIV = Updater(OldIV);
13285 for (Use *U : ReplacableUses)
13306 "Preheader must terminate with unconditional branch");
13308 "Preheader must jump to header");
13312 "Header must terminate with unconditional branch");
13313 assert(Header->getSingleSuccessor() == Cond &&
13314 "Header must jump to exiting block");
13317 assert(Cond->getSinglePredecessor() == Header &&
13318 "Exiting block only reachable from header");
13321 "Exiting block must terminate with conditional branch");
13323 "Exiting block's first successor jump to the body");
13325 "Exiting block's second successor must exit the loop");
13329 "Body only reachable from exiting block");
13334 "Latch must terminate with unconditional branch");
13335 assert(Latch->getSingleSuccessor() == Header &&
"Latch must jump to header");
13338 assert(Latch->getSinglePredecessor() !=
nullptr);
13343 "Exit block must terminate with unconditional branch");
13344 assert(Exit->getSingleSuccessor() == After &&
13345 "Exit block must jump to after block");
13349 "After block only reachable from exit block");
13353 assert(IndVar &&
"Canonical induction variable not found?");
13355 "Induction variable must be an integer");
13357 "Induction variable must be a PHI in the loop header");
13363 auto *NextIndVar =
cast<PHINode>(IndVar)->getIncomingValue(1);
13371 assert(TripCount &&
"Loop trip count not found?");
13373 "Trip count and induction variable must have the same type");
13377 "Exit condition must be a signed less-than comparison");
13379 "Exit condition must compare the induction variable");
13381 "Exit condition must compare with the trip count");
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
Expand Atomic instructions
This file contains the simple types necessary to represent the attributes associated with functions a...
static const Function * getParent(const Value *V)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
This header defines various interfaces for pass management in LLVM.
iv Induction Variable Users
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
static cl::opt< unsigned > TileSize("fuse-matrix-tile-size", cl::init(4), cl::Hidden, cl::desc("Tile size for matrix instruction fusion using square-shaped tiles."))
uint64_t IntrinsicInst * II
#define OMP_KERNEL_ARG_VERSION
Provides definitions for Target specific Grid Values.
static Value * removeASCastIfPresent(Value *V)
static void createTargetLoopWorkshareCall(OpenMPIRBuilder *OMPBuilder, WorksharingLoopType LoopType, BasicBlock *InsertBlock, Value *Ident, Value *LoopBodyArg, Value *TripCount, Function &LoopBodyFn, bool NoLoop)
Value * createFakeIntVal(IRBuilderBase &Builder, OpenMPIRBuilder::InsertPointTy OuterAllocaIP, llvm::SmallVectorImpl< Instruction * > &ToBeDeleted, OpenMPIRBuilder::InsertPointTy InnerAllocaIP, const Twine &Name="", bool AsPtr=true, bool Is64Bit=false)
static Function * createTargetParallelWrapper(OpenMPIRBuilder *OMPIRBuilder, Function &OutlinedFn)
Create wrapper function used to gather the outlined function's argument structure from a shared buffe...
static void redirectTo(BasicBlock *Source, BasicBlock *Target, DebugLoc DL)
Make Source branch to Target.
static FunctionCallee getKmpcDistForStaticInitForType(Type *Ty, Module &M, OpenMPIRBuilder &OMPBuilder)
static void applyParallelAccessesMetadata(CanonicalLoopInfo *CLI, LLVMContext &Ctx, Loop *Loop, LoopInfo &LoopInfo, SmallVector< Metadata * > &LoopMDList)
static Expected< Function * > createOutlinedFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, const OpenMPIRBuilder::TargetKernelDefaultAttrs &DefaultAttrs, StringRef FuncName, SmallVectorImpl< Value * > &Inputs, OpenMPIRBuilder::TargetBodyGenCallbackTy &CBFunc, OpenMPIRBuilder::TargetGenArgAccessorsCallbackTy &ArgAccessorFuncCB, DebugLoc OutlinedFnLoc)
static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, char ISA, StringRef ParSeq, StringRef MangledName, bool OutputBecomesInput, llvm::Function *Fn)
static FunctionCallee getKmpcForDynamicFiniForType(Type *Ty, Module &M, OpenMPIRBuilder &OMPBuilder)
Returns an LLVM function to call for finalizing the dynamic loop using depending on type.
static void FixupDebugInfoForOutlinedFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, Function *Func, DenseMap< Value *, std::tuple< Value *, unsigned > > &ValueReplacementMap)
static OMPScheduleType getOpenMPOrderingScheduleType(OMPScheduleType BaseScheduleType, bool HasOrderedClause)
Adds ordering modifier flags to schedule type.
static OMPScheduleType getOpenMPMonotonicityScheduleType(OMPScheduleType ScheduleType, bool HasSimdModifier, bool HasMonotonic, bool HasNonmonotonic, bool HasOrderedClause)
Adds monotonicity modifier flags to schedule type.
static std::string mangleVectorParameters(ArrayRef< llvm::OpenMPIRBuilder::DeclareSimdAttrTy > ParamAttrs)
Mangle the parameter part of the vector function name according to their OpenMP classification.
static bool isGenericKernel(Function &Fn)
static void workshareLoopTargetCallback(OpenMPIRBuilder *OMPIRBuilder, CanonicalLoopInfo *CLI, Value *Ident, Function &OutlinedFn, const SmallVector< Instruction *, 4 > &ToBeDeleted, WorksharingLoopType LoopType, bool NoLoop)
static bool isValidWorkshareLoopScheduleType(OMPScheduleType SchedType)
static bool isAtomicableReductionSet(ArrayRef< OpenMPIRBuilder::ReductionInfo > ReductionInfos)
static llvm::CallInst * emitNoUnwindRuntimeCall(IRBuilder<> &Builder, llvm::FunctionCallee Callee, ArrayRef< llvm::Value * > Args, const llvm::Twine &Name)
static Error populateReductionFunction(Function *ReductionFunc, ArrayRef< OpenMPIRBuilder::ReductionInfo > ReductionInfos, IRBuilder<> &Builder, ArrayRef< bool > IsByRef, bool IsGPU)
static Function * getFreshReductionFunc(Module &M)
static void raiseUserConstantDataAllocasToEntryBlock(IRBuilderBase &Builder, Function *Function)
static FunctionCallee getKmpcForDynamicNextForType(Type *Ty, Module &M, OpenMPIRBuilder &OMPBuilder)
Returns an LLVM function to call for updating the next loop using OpenMP dynamic scheduling depending...
static bool isConflictIP(IRBuilder<>::InsertPoint IP1, IRBuilder<>::InsertPoint IP2)
Return whether IP1 and IP2 are ambiguous, i.e.
static void checkReductionInfos(ArrayRef< OpenMPIRBuilder::ReductionInfo > ReductionInfos, bool IsGPU)
static Type * getOffloadingArrayType(Value *V)
static OMPScheduleType getOpenMPBaseScheduleType(llvm::omp::ScheduleKind ClauseKind, bool HasChunks, bool HasSimdModifier, bool HasDistScheduleChunks)
Determine which scheduling algorithm to use, determined from schedule clause arguments.
static OMPScheduleType computeOpenMPScheduleType(ScheduleKind ClauseKind, bool HasChunks, bool HasSimdModifier, bool HasMonotonicModifier, bool HasNonmonotonicModifier, bool HasOrderedClause, bool HasDistScheduleChunks)
Determine the schedule type using schedule and ordering clause arguments.
static FunctionCallee getKmpcForDynamicInitForType(Type *Ty, Module &M, OpenMPIRBuilder &OMPBuilder)
Returns an LLVM function to call for initializing loop bounds using OpenMP dynamic scheduling dependi...
static std::optional< omp::OMPTgtExecModeFlags > getTargetKernelExecMode(Function &Kernel)
Given a function, if it represents the entry point of a target kernel, this returns the execution mod...
static StructType * createTaskWithPrivatesTy(OpenMPIRBuilder &OMPIRBuilder, ArrayRef< Value * > OffloadingArraysToPrivatize)
static cl::opt< double > UnrollThresholdFactor("openmp-ir-builder-unroll-threshold-factor", cl::Hidden, cl::desc("Factor for the unroll threshold to account for code " "simplifications still taking place"), cl::init(1.5))
static cl::opt< bool > UseDefaultMaxThreads("openmp-ir-builder-use-default-max-threads", cl::Hidden, cl::desc("Use a default max threads if none is provided."), cl::init(true))
static int32_t computeHeuristicUnrollFactor(CanonicalLoopInfo *CLI)
Heuristically determine the best-performant unroll factor for CLI.
static Error emitTargetOutlinedFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, bool IsOffloadEntry, TargetRegionEntryInfo &EntryInfo, const OpenMPIRBuilder::TargetKernelDefaultAttrs &DefaultAttrs, Function *&OutlinedFn, Constant *&OutlinedFnID, SmallVectorImpl< Value * > &Inputs, OpenMPIRBuilder::TargetBodyGenCallbackTy &CBFunc, OpenMPIRBuilder::TargetGenArgAccessorsCallbackTy &ArgAccessorFuncCB, DebugLoc OutlinedFnLoc)
static void emitTargetCall(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, OpenMPIRBuilder::InsertPointTy AllocaIP, ArrayRef< BasicBlock * > DeallocBlocks, OpenMPIRBuilder::TargetDataInfo &Info, const OpenMPIRBuilder::TargetKernelDefaultAttrs &DefaultAttrs, const OpenMPIRBuilder::TargetKernelRuntimeAttrs &RuntimeAttrs, Value *IfCond, Function *OutlinedFn, Constant *OutlinedFnID, SmallVectorImpl< Value * > &Args, OpenMPIRBuilder::GenMapInfoCallbackTy GenMapInfoCB, OpenMPIRBuilder::CustomMapperCallbackTy CustomMapperCB, const OpenMPIRBuilder::DependenciesInfo &Dependencies, bool HasNoWait, Value *DynCGroupMem, OMPDynGroupprivateFallbackType DynCGroupMemFallback)
static Value * emitTaskDependencies(OpenMPIRBuilder &OMPBuilder, const SmallVectorImpl< OpenMPIRBuilder::DependData > &Dependencies)
static void updateNVPTXAttr(Function &Kernel, StringRef Name, int32_t Value, bool Min)
static OpenMPIRBuilder::InsertPointTy getInsertPointAfterInstr(Instruction *I)
static void redirectAllPredecessorsTo(BasicBlock *OldTarget, BasicBlock *NewTarget, DebugLoc DL)
Redirect all edges that branch to OldTarget to NewTarget.
static void hoistNonEntryAllocasToEntryBlock(llvm::BasicBlock &Block)
static std::unique_ptr< TargetMachine > createTargetMachine(Function *F, CodeGenOptLevel OptLevel)
Create the TargetMachine object to query the backend for optimization preferences.
static FunctionCallee getKmpcForStaticInitForType(Type *Ty, Module &M, OpenMPIRBuilder &OMPBuilder)
static void addAccessGroupMetadata(BasicBlock *Block, MDNode *AccessGroup, LoopInfo &LI)
Attach llvm.access.group metadata to the memref instructions of Block.
static void addBasicBlockMetadata(BasicBlock *BB, ArrayRef< Metadata * > Properties)
Attach metadata Properties to the basic block described by BB.
static void restoreIPandDebugLoc(llvm::IRBuilderBase &Builder, llvm::IRBuilderBase::InsertPoint IP)
This is a wrapper over IRBuilderBase::restoreIP that also restores a current debug location when the ...
static LoadInst * loadSharedDataFromTaskDescriptor(OpenMPIRBuilder &OMPIRBuilder, IRBuilderBase &Builder, Value *TaskWithPrivates, Type *TaskWithPrivatesTy)
Given a task descriptor, TaskWithPrivates, return the pointer to the block of pointers containing sha...
static cl::opt< bool > OptimisticAttributes("openmp-ir-builder-optimistic-attributes", cl::Hidden, cl::desc("Use optimistic attributes describing " "'as-if' properties of runtime calls."), cl::init(false))
static bool hasGridValue(const Triple &T)
static FunctionCallee getKmpcForStaticLoopForType(Type *Ty, OpenMPIRBuilder *OMPBuilder, WorksharingLoopType LoopType)
static const omp::GV & getGridValue(const Triple &T, Function *Kernel)
static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, StringRef Prefix, char ISA, StringRef ParSeq, StringRef MangledName, bool OutputBecomesInput, llvm::Function *Fn)
static Function * emitTargetTaskProxyFunction(OpenMPIRBuilder &OMPBuilder, IRBuilderBase &Builder, CallInst *StaleCI, StructType *PrivatesTy, StructType *TaskWithPrivatesTy, const size_t NumOffloadingArrays, const int SharedArgsOperandNo)
Create an entry point for a target task with the following.
static void addLoopMetadata(CanonicalLoopInfo *Loop, ArrayRef< Metadata * > Properties)
Attach loop metadata Properties to the loop described by Loop.
static AtomicOrdering TransformReleaseAcquireRelease(AtomicOrdering AO)
static void removeUnusedBlocksFromParent(ArrayRef< BasicBlock * > BBs)
static void targetParallelCallback(OpenMPIRBuilder *OMPIRBuilder, Function &OutlinedFn, Function *OuterFn, BasicBlock *OuterAllocaBB, Value *Ident, Value *IfCondition, Value *NumThreads, Instruction *PrivTID, AllocaInst *PrivTIDAddr, Value *ThreadID, const SmallVector< Instruction *, 4 > &ToBeDeleted)
static void hostParallelCallback(OpenMPIRBuilder *OMPIRBuilder, Function &OutlinedFn, Function *OuterFn, Value *Ident, Value *IfCondition, Instruction *PrivTID, AllocaInst *PrivTIDAddr, const SmallVector< Instruction *, 4 > &ToBeDeleted)
FunctionAnalysisManager FAM
This file defines the Pass Instrumentation classes that provide instrumentation points into the pass ...
const SmallVectorImpl< MachineOperand > & Cond
Remove Loads Into Fake Uses
static bool isValid(const char C)
Returns true if C is a valid mangled character: <0-9a-zA-Z_>.
SmallPtrSet< BasicBlock *, 0 > BlockSet
This file implements the SmallBitVector class.
This file defines the SmallSet class.
static SymbolRef::Type getType(const Symbol *Sym)
Defines the virtual file system interface vfs::FileSystem.
static cl::opt< unsigned > MaxThreads("xcore-max-threads", cl::Optional, cl::desc("Maximum number of threads (for emulation thread-local storage)"), cl::Hidden, cl::value_desc("number"), cl::init(8))
static const uint32_t IV[8]
Class for arbitrary precision integers.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
An arbitrary precision integer that knows its signedness.
static APSInt getUnsigned(uint64_t X)
This class represents a conversion between pointers from one address space to another.
an instruction to allocate memory on the stack
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
PointerType * getType() const
Overload to return most specific pointer type.
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
unsigned getAddressSpace() const
Return the address space for the allocation.
LLVM_ABI std::optional< TypeSize > getAllocationSize(const DataLayout &DL) const
Get allocation size in bytes.
LLVM_ABI bool isArrayAllocation() const
Return true if there is an allocation size parameter to the allocation instruction that is not 1.
void setAlignment(Align Align)
const Value * getArraySize() const
Get the number of elements allocated.
bool registerPass(PassBuilderT &&PassBuilder)
Register an analysis pass with the manager.
This class represents an incoming formal argument to a Function.
unsigned getArgNo() const
Return the index of this formal argument in its containing function.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
Class to represent array types.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
A function analysis which provides an AssumptionCache.
LLVM_ABI AssumptionCache run(Function &F, FunctionAnalysisManager &)
A cache of @llvm.assume calls within a function.
An instruction that atomically checks whether a specified value is in a memory location,...
void setWeak(bool IsWeak)
static AtomicOrdering getStrongestFailureOrdering(AtomicOrdering SuccessOrdering)
Returns the strongest permitted ordering on failure, given the desired ordering on success.
LLVM_ABI std::pair< LoadInst *, AllocaInst * > EmitAtomicLoadLibcall(AtomicOrdering AO)
LLVM_ABI void EmitAtomicStoreLibcall(AtomicOrdering AO, Value *Source)
an instruction that atomically reads a memory location, combines it with another value,...
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ FMinimum
*p = minimum(old, v) minimum matches the behavior of llvm.minimum.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ FMaximum
*p = maximum(old, v) maximum matches the behavior of llvm.maximum.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ FMin
*p = minnum(old, v) minnum matches the behavior of llvm.minnum.
@ UMax
*p = old >unsigned v ? old : v
@ FMaximumNum
*p = maximumnum(old, v) maximumnum matches the behavior of llvm.maximumnum.
@ FMax
*p = maxnum(old, v) maxnum matches the behavior of llvm.maxnum.
@ UDecWrap
Decrement one until a minimum value or zero.
@ FMinimumNum
*p = minimumnum(old, v) minimumnum matches the behavior of llvm.minimumnum.
This class holds the attributes for a particular argument, parameter, function, or return value.
LLVM_ABI AttributeSet addAttributes(LLVMContext &C, AttributeSet AS) const
Add attributes to the attribute set.
LLVM_ABI AttributeSet addAttribute(LLVMContext &C, Attribute::AttrKind Kind) const
Add an argument attribute.
static LLVM_ABI Attribute getWithAlignment(LLVMContext &Context, Align Alignment)
Return a uniquified Attribute object that has the specific alignment set.
LLVM Basic Block Representation.
LLVM_ABI void replaceSuccessorsPhiUsesWith(BasicBlock *Old, BasicBlock *New)
Update all phi nodes in this basic block's successors to refer to basic block New instead of basic bl...
iterator begin()
Instruction iterator methods.
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
LLVM_ABI BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
const Function * getParent() const
Return the enclosing method, or null if none.
reverse_iterator rbegin()
bool hasTerminator() const LLVM_READONLY
Returns whether the block has a terminator.
const Instruction & back() const
LLVM_ABI BasicBlock * splitBasicBlockBefore(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction and insert the new basic blo...
LLVM_ABI InstListType::const_iterator getFirstNonPHIIt() const
Returns an iterator to the first instruction in this block that is not a PHINode instruction.
LLVM_ABI void insertDbgRecordBefore(DbgRecord *DR, InstListType::iterator Here)
Insert a DbgRecord into a block at the position given by Here.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
LLVM_ABI InstListType::const_iterator getFirstNonPHIOrDbg(bool SkipPseudoOp=true) const
Returns a pointer to the first instruction in this block that is not a PHINode or a debug intrinsic,...
LLVM_ABI const BasicBlock * getUniqueSuccessor() const
Return the successor of this block if it has a unique successor.
LLVM_ABI const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
const Instruction & front() const
InstListType::reverse_iterator reverse_iterator
LLVM_ABI const BasicBlock * getUniquePredecessor() const
Return the predecessor of this block if it has a unique predecessor block.
const Instruction * getTerminatorOrNull() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
LLVM_ABI const BasicBlock * getSingleSuccessor() const
Return the successor of this block if it has a single successor.
LLVM_ABI SymbolTableList< BasicBlock >::iterator eraseFromParent()
Unlink 'this' from the containing function and delete it.
InstListType::iterator iterator
Instruction iterators...
LLVM_ABI LLVMContext & getContext() const
Get the context in which this basic block lives.
void moveBefore(BasicBlock *MovePos)
Unlink this basic block from its current function and insert it into the function that MovePos lives ...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
void splice(BasicBlock::iterator ToIt, BasicBlock *FromBB)
Transfer all instructions from FromBB to this basic block at ToIt.
LLVM_ABI void removePredecessor(BasicBlock *Pred, bool KeepOneInputPHIs=false)
Update PHI nodes in this BasicBlock before removal of predecessor Pred.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
User::op_iterator arg_begin()
Return the iterator pointing to the beginning of the argument list.
Value * getArgOperand(unsigned i) const
User::op_iterator arg_end()
Return the iterator pointing to the end of the argument list.
unsigned arg_size() const
This class represents a function call, abstracting a target machine's calling convention.
Class to represented the control flow structure of an OpenMP canonical loop.
Value * getTripCount() const
Returns the llvm::Value containing the number of loop iterations.
BasicBlock * getHeader() const
The header is the entry for each iteration.
LLVM_ABI void assertOK() const
Consistency self-check.
Type * getIndVarType() const
Return the type of the induction variable (and the trip count).
BasicBlock * getBody() const
The body block is the single entry for a loop iteration and not controlled by CanonicalLoopInfo.
bool isValid() const
Returns whether this object currently represents the IR of a loop.
void setLastIter(Value *IterVar)
Sets the last iteration variable for this loop.
OpenMPIRBuilder::InsertPointTy getAfterIP() const
Return the insertion point for user code after the loop.
OpenMPIRBuilder::InsertPointTy getBodyIP() const
Return the insertion point for user code in the body.
BasicBlock * getAfter() const
The after block is intended for clean-up code such as lifetime end markers.
Function * getFunction() const
LLVM_ABI void invalidate()
Invalidate this loop.
BasicBlock * getLatch() const
Reaching the latch indicates the end of the loop body code.
OpenMPIRBuilder::InsertPointTy getPreheaderIP() const
Return the insertion point for user code before the loop.
BasicBlock * getCond() const
The condition block computes whether there is another loop iteration.
BasicBlock * getExit() const
Reaching the exit indicates no more iterations are being executed.
LLVM_ABI BasicBlock * getPreheader() const
The preheader ensures that there is only a single edge entering the loop.
Instruction * getIndVar() const
Returns the instruction representing the current logical induction variable.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ ICMP_ULT
unsigned less than
@ ICMP_ULE
unsigned less or equal
static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)
get() constructor - Return a constant with array type with an element count and element type matching...
static LLVM_ABI Constant * getString(LLVMContext &Context, StringRef Initializer, bool AddNull=true, bool ByteString=false)
This method constructs a CDS and initializes it with a text string.
static LLVM_ABI Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
static LLVM_ABI Constant * getTruncOrBitCast(Constant *C, Type *Ty)
static LLVM_ABI Constant * getPointerBitCastOrAddrSpaceCast(Constant *C, Type *Ty)
Create a BitCast or AddrSpaceCast for a pointer type depending on the address space.
static LLVM_ABI Constant * getSizeOf(Type *Ty)
getSizeOf constant expr - computes the (alloc) size of a type (in address-units, not bits) in a targe...
static LLVM_ABI Constant * getAddrSpaceCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static LLVM_ABI ConstantFP * getZero(Type *Ty, bool Negative=false)
This is the shared class of boolean and integer constants.
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static LLVM_ABI Constant * get(StructType *T, ArrayRef< Constant * > V)
This is an important base class in LLVM.
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
DILocalScope * getScope() const
Get the local scope for this variable.
DINodeArray getAnnotations() const
Subprogram description. Uses SubclassData1.
uint32_t getAlignInBits() const
StringRef getName() const
A parsed version of the target data layout string in and methods for querying it.
TypeSize getTypeStoreSize(Type *Ty) const
Returns the maximum number of bytes that may be overwritten by storing the specified type.
Record of a variable value-assignment, aka a non instruction representation of the dbg....
Analysis pass which computes a DominatorTree.
LLVM_ABI DominatorTree run(Function &F, FunctionAnalysisManager &)
Run the analysis pass over a function and produce a dominator tree.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Represents either an error or a value T.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
reference get()
Returns a reference to the stored T value.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
Class to represent function types.
Type * getParamType(unsigned i) const
Parameter type accessors.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
const BasicBlock & getEntryBlock() const
FunctionType * getFunctionType() const
Returns the FunctionType for me.
void removeFromParent()
removeFromParent - This method unlinks 'this' from the containing module, but does not delete it.
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
DISubprogram * getSubprogram() const
Get the attached subprogram.
AttributeList getAttributes() const
Return the attribute list for this Function.
const Function & getFunction() const
void setAttributes(AttributeList Attrs)
Set the attribute list for this Function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
adds the attribute to the list of attributes for the given arg.
Function::iterator insert(Function::iterator Position, BasicBlock *BB)
Insert BB in the basic block list at Position.
Type * getReturnType() const
Returns the type of the ret val.
void setCallingConv(CallingConv::ID CC)
Argument * getArg(unsigned i) const
bool hasMetadata() const
Return true if this GlobalObject has any metadata attached to it.
LLVM_ABI void addMetadata(unsigned KindID, MDNode &MD)
Add a metadata attachment.
LinkageTypes getLinkage() const
void setLinkage(LinkageTypes LT)
Module * getParent()
Get the module that this global value is contained inside of...
void setDSOLocal(bool Local)
PointerType * getType() const
Global values are always pointers.
@ HiddenVisibility
The GV is hidden.
@ ProtectedVisibility
The GV is protected.
void setVisibility(VisibilityTypes V)
LinkageTypes
An enumeration for the kinds of linkage for global values.
@ PrivateLinkage
Like Internal, but omit from symbol table.
@ CommonLinkage
Tentative definitions.
@ InternalLinkage
Rename collisions when linking (static functions).
@ WeakODRLinkage
Same, but only replaced by something equivalent.
@ WeakAnyLinkage
Keep one copy of named function when linking (weak)
@ AppendingLinkage
Special purpose, only applies to global arrays.
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
InsertPoint - A saved insertion point.
BasicBlock * getBlock() const
bool isSet() const
Returns true if this insert point is set.
BasicBlock::iterator getPoint() const
Common base class shared among various IRBuilders.
InsertPoint saveIP() const
Returns the current insert point.
void restoreIP(InsertPoint IP)
Sets the current insert point to a previously-saved location.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI const DebugLoc & getStableDebugLoc() const
Fetch the debug location for this node, unless this is a debug intrinsic, in which case fetch the deb...
LLVM_ABI void removeFromParent()
This method unlinks 'this' from the containing basic block, but does not delete it.
LLVM_ABI unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI void moveBefore(InstListType::iterator InsertPos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
LLVM_ABI BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY
Return the specified successor. This instruction must be a terminator.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
LLVM_ABI void moveBeforePreserving(InstListType::iterator MovePos)
Perform a moveBefore operation, while signalling that the caller intends to preserve the original ord...
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI void insertAfter(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately after the specified instruction.
Class to represent integer types.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this load instruction.
Align getAlign() const
Return the alignment of the access that is being performed.
Analysis pass that exposes the LoopInfo for a function.
LLVM_ABI LoopInfo run(Function &F, FunctionAnalysisManager &AM)
ArrayRef< BlockT * > getBlocks() const
Get a list of the basic blocks which make up this loop.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
This class represents a loop nest and can be used to query its properties.
Represents a single loop in the control flow graph.
LLVM_ABI MDNode * createCallbackEncoding(unsigned CalleeArgNo, ArrayRef< int > Arguments, bool VarArgsArePassed)
Return metadata describing a callback (see llvm::AbstractCallSite).
LLVM_ABI void replaceOperandWith(unsigned I, Metadata *New)
Replace a specific operand.
static MDTuple * getDistinct(LLVMContext &Context, ArrayRef< Metadata * > MDs)
ArrayRef< MDOperand > operands() const
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
This class implements a map that also provides access to all stored values in a deterministic order.
A Module instance is used to store all the information related to an LLVM module.
LLVMContext & getContext() const
Get the global data context.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
iterator_range< op_iterator > operands()
LLVM_ABI void addOperand(MDNode *M)
Device global variable entries info.
Target region entries info.
Base class of the entries info.
Class that manages information about offload code regions and data.
function_ref< void(StringRef, const OffloadEntryInfoDeviceGlobalVar &)> OffloadDeviceGlobalVarEntryInfoActTy
Applies action Action on all registered entries.
OMPTargetDeviceClauseKind
Kind of device clause for declare target variables and functions NOTE: Currently not used as a part o...
@ OMPTargetDeviceClauseAny
The target is marked for all devices.
LLVM_ABI void registerDeviceGlobalVarEntryInfo(StringRef VarName, Constant *Addr, int64_t VarSize, OMPTargetGlobalVarEntryKind Flags, GlobalValue::LinkageTypes Linkage)
Register device global variable entry.
LLVM_ABI void initializeDeviceGlobalVarEntryInfo(StringRef Name, OMPTargetGlobalVarEntryKind Flags, unsigned Order)
Initialize device global variable entry.
LLVM_ABI void actOnDeviceGlobalVarEntriesInfo(const OffloadDeviceGlobalVarEntryInfoActTy &Action)
OMPTargetRegionEntryKind
Kind of the target registry entry.
@ OMPTargetRegionEntryTargetRegion
Mark the entry as target region.
LLVM_ABI void getTargetRegionEntryFnName(SmallVectorImpl< char > &Name, const TargetRegionEntryInfo &EntryInfo)
LLVM_ABI bool hasTargetRegionEntryInfo(TargetRegionEntryInfo EntryInfo, bool IgnoreAddressId=false) const
Return true if a target region entry with the provided information exists.
LLVM_ABI void registerTargetRegionEntryInfo(TargetRegionEntryInfo EntryInfo, Constant *Addr, Constant *ID, OMPTargetRegionEntryKind Flags)
Register target region entry.
LLVM_ABI void actOnTargetRegionEntriesInfo(const OffloadTargetRegionEntryInfoActTy &Action)
LLVM_ABI void initializeTargetRegionEntryInfo(const TargetRegionEntryInfo &EntryInfo, unsigned Order)
Initialize target region entry.
OMPTargetGlobalVarEntryKind
Kind of the global variable entry..
@ OMPTargetGlobalVarEntryEnter
Mark the entry as a declare target enter.
@ OMPTargetGlobalRegisterRequires
Mark the entry as a register requires global.
@ OMPTargetGlobalVarEntryIndirect
Mark the entry as a declare target indirect global.
@ OMPTargetGlobalVarEntryLink
Mark the entry as a to declare target link.
@ OMPTargetGlobalVarEntryTo
Mark the entry as a to declare target.
@ OMPTargetGlobalVarEntryIndirectVTable
Mark the entry as a declare target indirect vtable.
function_ref< void(const TargetRegionEntryInfo &EntryInfo, const OffloadEntryInfoTargetRegion &)> OffloadTargetRegionEntryInfoActTy
brief Applies action Action on all registered entries.
bool hasDeviceGlobalVarEntryInfo(StringRef VarName) const
Checks if the variable with the given name has been registered already.
LLVM_ABI bool empty() const
Return true if a there are no entries defined.
std::optional< bool > IsTargetDevice
Flag to define whether to generate code for the role of the OpenMP host (if set to false) or device (...
std::optional< bool > IsGPU
Flag for specifying if the compilation is done for an accelerator.
LLVM_ABI int64_t getRequiresFlags() const
Returns requires directive clauses as flags compatible with those expected by libomptarget.
std::optional< bool > OpenMPOffloadMandatory
Flag for specifying if offloading is mandatory.
LLVM_ABI void setHasRequiresReverseOffload(bool Value)
LLVM_ABI OpenMPIRBuilderConfig()
LLVM_ABI bool hasRequiresUnifiedSharedMemory() const
LLVM_ABI void setHasRequiresUnifiedSharedMemory(bool Value)
unsigned getDefaultTargetAS() const
LLVM_ABI bool hasRequiresDynamicAllocators() const
LLVM_ABI void setHasRequiresUnifiedAddress(bool Value)
bool isTargetDevice() const
LLVM_ABI void setHasRequiresDynamicAllocators(bool Value)
LLVM_ABI bool hasRequiresReverseOffload() const
bool hasRequiresFlags() const
LLVM_ABI bool hasRequiresUnifiedAddress() const
Struct that keeps the information that should be kept throughout a 'target data' region.
An interface to create LLVM-IR for OpenMP directives.
LLVM_ABI InsertPointOrErrorTy createOrderedThreadsSimd(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, bool IsThreads)
Generator for 'omp ordered [threads | simd]'.
LLVM_ABI void emitAArch64DeclareSimdFunction(llvm::Function *Fn, unsigned VLENVal, llvm::ArrayRef< DeclareSimdAttrTy > ParamAttrs, DeclareSimdBranch Branch, char ISA, unsigned NarrowestDataSize, bool OutputBecomesInput)
Emit AArch64 vector-function ABI attributes for a declare simd function.
LLVM_ABI Constant * getOrCreateIdent(Constant *SrcLocStr, uint32_t SrcLocStrSize, omp::IdentFlag Flags=omp::IdentFlag(0), unsigned Reserve2Flags=0)
Return an ident_t* encoding the source location SrcLocStr and Flags.
LLVM_ABI void registerDeclareTargetGlobalReplacement(GlobalValue *Original, GlobalValue *Replacement)
Register a module-scope replacement of a declare target global variable.
LLVM_ABI FunctionCallee getOrCreateRuntimeFunction(Module &M, omp::RuntimeFunction FnID)
Return the function declaration for the runtime function with FnID.
LLVM_ABI InsertPointOrErrorTy createCancel(const LocationDescription &Loc, Value *IfCondition, omp::Directive CanceledDirective)
Generator for 'omp cancel'.
std::function< Expected< Function * >(StringRef FunctionName)> FunctionGenCallback
Functions used to generate a function with the given name.
LLVM_ABI CallInst * createOMPAllocShared(const LocationDescription &Loc, Value *Size, const Twine &Name=Twine(""))
Create a runtime call for kmpc_alloc_shared.
ReductionGenCBKind
Enum class for the RedctionGen CallBack type to be used.
LLVM_ABI CanonicalLoopInfo * collapseLoops(DebugLoc DL, ArrayRef< CanonicalLoopInfo * > Loops, InsertPointTy ComputeIP)
Collapse a loop nest into a single loop.
LLVM_ABI void createTaskyield(const LocationDescription &Loc)
Generator for 'omp taskyield'.
std::function< Error(InsertPointTy CodeGenIP)> FinalizeCallbackTy
Callback type for variable finalization (think destructors).
LLVM_ABI void emitBranch(BasicBlock *Target)
LLVM_ABI Error emitCancelationCheckImpl(Value *CancelFlag, omp::Directive CanceledDirective)
Generate control flow and cleanup for cancellation.
static LLVM_ABI void writeThreadBoundsForKernel(const Triple &T, Function &Kernel, int32_t LB, int32_t UB)
LLVM_ABI void emitTaskwaitImpl(const LocationDescription &Loc)
Generate a taskwait runtime call.
LLVM_ABI Constant * registerTargetRegionFunction(TargetRegionEntryInfo &EntryInfo, Function *OutlinedFunction, StringRef EntryFnName, StringRef EntryFnIDName)
Registers the given function and sets up the attribtues of the function Returns the FunctionID.
LLVM_ABI GlobalVariable * emitKernelExecutionMode(StringRef KernelName, omp::OMPTgtExecModeFlags Mode)
Emit the kernel execution mode.
LLVM_ABI void initialize()
Initialize the internal state, this will put structures types and potentially other helpers into the ...
LLVM_ABI InsertPointTy createAtomicCompare(const LocationDescription &Loc, AtomicOpValue &X, AtomicOpValue &V, AtomicOpValue &R, Value *E, Value *D, AtomicOrdering AO, omp::OMPAtomicCompareOp Op, bool IsXBinopExpr, bool IsPostfixUpdate, bool IsFailOnly, bool IsWeak=false)
LLVM_ABI InsertPointTy createAtomicWrite(const LocationDescription &Loc, AtomicOpValue &X, Value *Expr, AtomicOrdering AO, InsertPointTy AllocaIP)
Emit atomic write for : X = Expr — Only Scalar data types.
LLVM_ABI void loadOffloadInfoMetadata(Module &M)
Loads all the offload entries information from the host IR metadata.
function_ref< MapInfosTy &(InsertPointTy CodeGenIP)> GenMapInfoCallbackTy
Callback type for creating the map infos for the kernel parameters.
LLVM_ABI Error emitOffloadingArrays(InsertPointTy AllocaIP, InsertPointTy CodeGenIP, MapInfosTy &CombinedInfo, TargetDataInfo &Info, CustomMapperCallbackTy CustomMapperCB, bool IsNonContiguous=false, function_ref< void(unsigned int, Value *)> DeviceAddrCB=nullptr)
Emit the arrays used to pass the captures and map information to the offloading runtime library.
LLVM_ABI void unrollLoopFull(DebugLoc DL, CanonicalLoopInfo *Loop)
Fully unroll a loop.
function_ref< Error(InsertPointTy CodeGenIP, Value *IndVar)> LoopBodyGenCallbackTy
Callback type for loop body code generation.
LLVM_ABI InsertPointOrErrorTy emitScanReduction(const LocationDescription &Loc, ArrayRef< llvm::OpenMPIRBuilder::ReductionInfo > ReductionInfos, ScanInfo *ScanRedInfo)
This function performs the scan reduction of the values updated in the input phase.
LLVM_ABI void emitFlush(const LocationDescription &Loc)
Generate a flush runtime call.
LLVM_ABI InsertPointOrErrorTy createScope(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, bool IsNowait)
Generator for 'omp scope'.
static LLVM_ABI std::pair< int32_t, int32_t > readThreadBoundsForKernel(const Triple &T, Function &Kernel)
}
OpenMPIRBuilderConfig Config
The OpenMPIRBuilder Configuration.
LLVM_ABI CallInst * createOMPInteropDestroy(const LocationDescription &Loc, Value *InteropVar, Value *Device, Value *NumDependences, Value *DependenceAddress, bool HaveNowaitClause)
Create a runtime call for __tgt_interop_destroy.
LLVM_ABI void emitUsed(StringRef Name, ArrayRef< llvm::WeakTrackingVH > List)
Emit the llvm.used metadata.
LLVM_ABI InsertPointOrErrorTy createSingle(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, bool IsNowait, ArrayRef< llvm::Value * > CPVars={}, ArrayRef< llvm::Function * > CPFuncs={})
Generator for 'omp single'.
LLVM_ABI InsertPointOrErrorTy createTeams(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, Value *NumTeamsLower=nullptr, Value *NumTeamsUpper=nullptr, Value *ThreadLimit=nullptr, Value *IfExpr=nullptr)
Generator for #omp teams
std::forward_list< CanonicalLoopInfo > LoopInfos
Collection of owned canonical loop objects that eventually need to be free'd.
LLVM_ABI llvm::StructType * getKmpTaskAffinityInfoTy()
Return the LLVM struct type matching runtime kmp_task_affinity_info_t.
LLVM_ABI std::string createPlatformSpecificName(ArrayRef< StringRef > Parts) const
Get the create a name using the platform specific separators.
LLVM_ABI FunctionCallee createDispatchNextFunction(unsigned IVSize, bool IVSigned)
Returns __kmpc_dispatch_next_* runtime function for the specified size IVSize and sign IVSigned.
static LLVM_ABI void getKernelArgsVector(TargetKernelArgs &KernelArgs, IRBuilderBase &Builder, SmallVector< Value * > &ArgsVector)
Create the kernel args vector used by emitTargetKernel.
LLVM_ABI void unrollLoopHeuristic(DebugLoc DL, CanonicalLoopInfo *Loop)
Fully or partially unroll a loop.
LLVM_ABI omp::OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position)
Get OMP_MAP_MEMBER_OF flag with extra bits reserved based on the position given.
LLVM_ABI void addAttributes(omp::RuntimeFunction FnID, Function &Fn)
Add attributes known for FnID to Fn.
Module & M
The underlying LLVM-IR module.
StringMap< Constant * > SrcLocStrMap
Map to remember source location strings.
LLVM_ABI void createMapperAllocas(const LocationDescription &Loc, InsertPointTy AllocaIP, unsigned NumOperands, struct MapperAllocas &MapperAllocas)
Create the allocas instruction used in call to mapper functions.
SmallVector< DeclareTargetGlobalReplacement, 8 > DeclareTargetGlobalReplacements
Collection of declare target globals to rewrite uses of during device module finalizaiton.
LLVM_ABI Constant * getOrCreateSrcLocStr(StringRef LocStr, uint32_t &SrcLocStrSize)
Return the (LLVM-IR) string describing the source location LocStr.
LLVM_ABI Error emitTargetRegionFunction(TargetRegionEntryInfo &EntryInfo, FunctionGenCallback &GenerateFunctionCallback, bool IsOffloadEntry, Function *&OutlinedFn, Constant *&OutlinedFnID)
Create a unique name for the entry function using the source location information of the current targ...
LLVM_ABI InsertPointOrErrorTy createIteratorLoop(LocationDescription Loc, llvm::Value *TripCount, IteratorBodyGenTy BodyGen, llvm::StringRef Name="iterator")
Create a canonical iterator loop at the current insertion point.
LLVM_ABI Expected< SmallVector< llvm::CanonicalLoopInfo * > > createCanonicalScanLoops(const LocationDescription &Loc, LoopBodyGenCallbackTy BodyGenCB, Value *Start, Value *Stop, Value *Step, bool IsSigned, bool InclusiveStop, InsertPointTy ComputeIP, const Twine &Name, ScanInfo *ScanRedInfo)
Generator for the control flow structure of an OpenMP canonical loops if the parent directive has an ...
LLVM_ABI FunctionCallee createDispatchFiniFunction(unsigned IVSize, bool IVSigned)
Returns __kmpc_dispatch_fini_* runtime function for the specified size IVSize and sign IVSigned.
function_ref< InsertPointOrErrorTy( InsertPointTy AllocaIP, InsertPointTy CodeGenIP, ArrayRef< BasicBlock * > DeallocBlocks)> TargetBodyGenCallbackTy
LLVM_ABI void unrollLoopPartial(DebugLoc DL, CanonicalLoopInfo *Loop, int32_t Factor, CanonicalLoopInfo **UnrolledCLI)
Partially unroll a loop.
function_ref< Error(Value *DeviceID, Value *RTLoc, IRBuilderBase::InsertPoint TargetTaskAllocaIP)> TargetTaskBodyCallbackTy
Callback type for generating the bodies of device directives that require outer target tasks (e....
Expected< MapInfosTy & > MapInfosOrErrorTy
bool HandleFPNegZero
Emit atomic compare for constructs: — Only scalar data types cond-expr-stmt: x = x ordop expr ?
LLVM_ABI void emitTaskyieldImpl(const LocationDescription &Loc)
Generate a taskyield runtime call.
LLVM_ABI void emitMapperCall(const LocationDescription &Loc, Function *MapperFunc, Value *SrcLocInfo, Value *MaptypesArg, Value *MapnamesArg, struct MapperAllocas &MapperAllocas, int64_t DeviceID, unsigned NumOperands)
Create the call for the target mapper function.
LLVM_ABI InsertPointOrErrorTy createDistribute(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< BasicBlock * > DeallocBlocks, BodyGenCallbackTy BodyGenCB)
Generator for #omp distribute
LLVM_ABI InsertPointOrErrorTy createTask(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< BasicBlock * > DeallocBlocks, BodyGenCallbackTy BodyGenCB, bool Tied=true, Value *Final=nullptr, Value *IfCondition=nullptr, const DependenciesInfo &Dependencies={}, const AffinityData &Affinities={}, bool Mergeable=false, Value *EventHandle=nullptr, Value *Priority=nullptr)
Generator for #omp taskloop
function_ref< Expected< Function * >(unsigned int)> CustomMapperCallbackTy
LLVM_ABI InsertPointTy createOrderedDepend(const LocationDescription &Loc, InsertPointTy AllocaIP, unsigned NumLoops, ArrayRef< llvm::Value * > StoreValues, const Twine &Name, bool IsDependSource)
Generator for 'omp ordered depend (source | sink)'.
LLVM_ABI InsertPointTy createCopyinClauseBlocks(InsertPointTy IP, Value *MasterAddr, Value *PrivateAddr, llvm::IntegerType *IntPtrTy, bool BranchtoEnd=true)
Generate conditional branch and relevant BasicBlocks through which private threads copy the 'copyin' ...
function_ref< InsertPointOrErrorTy( InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Value &Original, Value &Inner, Value *&ReplVal)> PrivatizeCallbackTy
Callback type for variable privatization (think copy & default constructor).
LLVM_ABI bool isFinalized()
Check whether the finalize function has already run.
SmallVector< FinalizationInfo, 8 > FinalizationStack
The finalization stack made up of finalize callbacks currently in-flight, wrapped into FinalizationIn...
LLVM_ABI std::vector< CanonicalLoopInfo * > tileLoops(DebugLoc DL, ArrayRef< CanonicalLoopInfo * > Loops, ArrayRef< Value * > TileSizes)
Tile a loop nest.
LLVM_ABI CallInst * createOMPInteropInit(const LocationDescription &Loc, Value *InteropVar, omp::OMPInteropType InteropType, Value *Device, Value *NumDependences, Value *DependenceAddress, bool HaveNowaitClause)
Create a runtime call for __tgt_interop_init.
LLVM_ABI Error emitIfClause(Value *Cond, BodyGenCallbackTy ThenGen, BodyGenCallbackTy ElseGen, InsertPointTy AllocaIP={}, ArrayRef< BasicBlock * > DeallocBlocks={})
Emits code for OpenMP 'if' clause using specified BodyGenCallbackTy Here is the logic: if (Cond) { Th...
LLVM_ABI void finalize(Function *Fn=nullptr)
Finalize the underlying module, e.g., by outlining regions.
LLVM_ABI Function * getOrCreateRuntimeFunctionPtr(omp::RuntimeFunction FnID)
void addOutlineInfo(std::unique_ptr< OutlineInfo > &&OI)
Add a new region that will be outlined later.
LLVM_ABI InsertPointTy createTargetInit(const LocationDescription &Loc, const llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs &Attrs)
The omp target interface.
LLVM_ABI InsertPointOrErrorTy createReductions(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< ReductionInfo > ReductionInfos, ArrayRef< bool > IsByRef, bool IsNoWait=false, bool IsTeamsReduction=false)
Generator for 'omp reduction'.
const Triple T
The target triple of the underlying module.
DenseMap< std::pair< Constant *, uint64_t >, Constant * > IdentMap
Map to remember existing ident_t*.
LLVM_ABI CallInst * createOMPFree(const LocationDescription &Loc, Value *Addr, Value *Allocator, std::string Name="")
Create a runtime call for kmpc_free.
LLVM_ABI InsertPointOrErrorTy createReductionsGPU(const LocationDescription &Loc, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, ArrayRef< ReductionInfo > ReductionInfos, ArrayRef< bool > IsByRef, bool IsNoWait=false, bool IsTeamsReduction=false, bool IsSPMD=false, ReductionGenCBKind ReductionGenCBKind=ReductionGenCBKind::MLIR, std::optional< omp::GV > GridValue={}, Value *SrcLocInfo=nullptr)
Design of OpenMP reductions on the GPU.
LLVM_ABI FunctionCallee createForStaticInitFunction(unsigned IVSize, bool IVSigned, bool IsGPUDistribute)
Returns __kmpc_for_static_init_* runtime function for the specified size IVSize and sign IVSigned.
LLVM_ABI CallInst * createOMPAlloc(const LocationDescription &Loc, Value *Size, Value *Allocator, std::string Name="")
Create a runtime call for kmpc_alloc.
LLVM_ABI void emitNonContiguousDescriptor(InsertPointTy AllocaIP, InsertPointTy CodeGenIP, MapInfosTy &CombinedInfo, TargetDataInfo &Info)
Emit an array of struct descriptors to be assigned to the offload args.
LLVM_ABI InsertPointOrErrorTy createSection(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB)
Generator for 'omp section'.
LLVM_ABI InsertPointOrErrorTy createTaskgroup(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< BasicBlock * > DeallocBlocks, BodyGenCallbackTy BodyGenCB)
Generator for the taskgroup construct.
LLVM_ABI InsertPointOrErrorTy createParallel(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< BasicBlock * > DeallocBlocks, BodyGenCallbackTy BodyGenCB, PrivatizeCallbackTy PrivCB, FinalizeCallbackTy FiniCB, Value *IfCondition, Value *NumThreads, omp::ProcBindKind ProcBind, bool IsCancellable)
Generator for 'omp parallel'.
function_ref< InsertPointOrErrorTy(InsertPointTy)> EmitFallbackCallbackTy
Callback function type for functions emitting the host fallback code that is executed when the kernel...
static LLVM_ABI TargetRegionEntryInfo getTargetEntryUniqueInfo(FileIdentifierInfoCallbackTy CallBack, vfs::FileSystem &VFS, StringRef ParentName="")
Creates a unique info for a target entry when provided a filename and line number from.
LLVM_ABI void emitTaskDependency(IRBuilderBase &Builder, Value *Entry, const DependData &Dep)
Store one kmp_depend_info entry at the given Entry pointer.
LLVM_ABI void emitBlock(BasicBlock *BB, Function *CurFn, bool IsFinished=false)
LLVM_ABI Value * getOrCreateThreadID(Value *Ident)
Return the current thread ID.
LLVM_ABI InsertPointOrErrorTy createMaster(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB)
Generator for 'omp master'.
LLVM_ABI InsertPointOrErrorTy createTarget(const LocationDescription &Loc, bool IsOffloadEntry, OpenMPIRBuilder::InsertPointTy AllocaIP, OpenMPIRBuilder::InsertPointTy CodeGenIP, ArrayRef< BasicBlock * > DeallocBlocks, TargetDataInfo &Info, TargetRegionEntryInfo &EntryInfo, const TargetKernelDefaultAttrs &DefaultAttrs, const TargetKernelRuntimeAttrs &RuntimeAttrs, Value *IfCond, SmallVectorImpl< Value * > &Inputs, GenMapInfoCallbackTy GenMapInfoCB, TargetBodyGenCallbackTy BodyGenCB, TargetGenArgAccessorsCallbackTy ArgAccessorFuncCB, CustomMapperCallbackTy CustomMapperCB, const DependenciesInfo &Dependencies={}, bool HasNowait=false, Value *DynCGroupMem=nullptr, omp::OMPDynGroupprivateFallbackType DynCGroupMemFallback=omp::OMPDynGroupprivateFallbackType::Abort, DebugLoc OutlinedFnLoc={})
Generator for 'omp target'.
LLVM_ABI InsertPointOrErrorTy createTargetData(const LocationDescription &Loc, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, ArrayRef< BasicBlock * > DeallocBlocks, Value *DeviceID, Value *IfCond, TargetDataInfo &Info, GenMapInfoCallbackTy GenMapInfoCB, CustomMapperCallbackTy CustomMapperCB, omp::RuntimeFunction *MapperFunc=nullptr, function_ref< InsertPointOrErrorTy(InsertPointTy CodeGenIP, BodyGenTy BodyGenType)> BodyGenCB=nullptr, function_ref< void(unsigned int, Value *)> DeviceAddrCB=nullptr, Value *SrcLocInfo=nullptr)
Generator for 'omp target data'.
LLVM_ABI CallInst * createRuntimeFunctionCall(FunctionCallee Callee, ArrayRef< Value * > Args, StringRef Name="")
LLVM_ABI InsertPointOrErrorTy emitKernelLaunch(const LocationDescription &Loc, Value *OutlinedFnID, EmitFallbackCallbackTy EmitTargetCallFallbackCB, TargetKernelArgs &Args, Value *DeviceID, Value *RTLoc, InsertPointTy AllocaIP)
Generate a target region entry call and host fallback call.
StringMap< GlobalVariable *, BumpPtrAllocator > InternalVars
An ordered map of auto-generated variables to their unique names.
LLVM_ABI InsertPointOrErrorTy createCancellationPoint(const LocationDescription &Loc, omp::Directive CanceledDirective)
Generator for 'omp cancellation point'.
LLVM_ABI CallInst * createOMPAlignedAlloc(const LocationDescription &Loc, Value *Align, Value *Size, Value *Allocator, std::string Name="")
Create a runtime call for kmpc_align_alloc.
LLVM_ABI FunctionCallee createDispatchInitFunction(unsigned IVSize, bool IVSigned)
Returns __kmpc_dispatch_init_* runtime function for the specified size IVSize and sign IVSigned.
LLVM_ABI InsertPointOrErrorTy createScan(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< llvm::Value * > ScanVars, ArrayRef< llvm::Type * > ScanVarsType, bool IsInclusive, ScanInfo *ScanRedInfo)
This directive split and directs the control flow to input phase blocks or scan phase blocks based on...
LLVM_ABI CallInst * createOMPFreeShared(const LocationDescription &Loc, Value *Addr, Value *Size, const Twine &Name=Twine(""))
Create a runtime call for kmpc_free_shared.
LLVM_ABI CallInst * createOMPInteropUse(const LocationDescription &Loc, Value *InteropVar, Value *Device, Value *NumDependences, Value *DependenceAddress, bool HaveNowaitClause)
Create a runtime call for __tgt_interop_use.
IRBuilder<>::InsertPoint InsertPointTy
Type used throughout for insertion points.
LLVM_ABI GlobalVariable * getOrCreateInternalVariable(Type *Ty, const StringRef &Name, std::optional< unsigned > AddressSpace={})
Gets (if variable with the given name already exist) or creates internal global variable with the spe...
LLVM_ABI GlobalVariable * createOffloadMapnames(SmallVectorImpl< llvm::Constant * > &Names, std::string VarName)
Create the global variable holding the offload names information.
std::forward_list< ScanInfo > ScanInfos
Collection of owned ScanInfo objects that eventually need to be free'd.
static LLVM_ABI void writeTeamsForKernel(const Triple &T, Function &Kernel, int32_t LB, int32_t UB)
LLVM_ABI Value * calculateCanonicalLoopTripCount(const LocationDescription &Loc, Value *Start, Value *Stop, Value *Step, bool IsSigned, bool InclusiveStop, const Twine &Name="loop")
Calculate the trip count of a canonical loop.
LLVM_ABI InsertPointOrErrorTy createBarrier(const LocationDescription &Loc, omp::Directive Kind, bool ForceSimpleCall=false, bool CheckCancelFlag=true)
Emitter methods for OpenMP directives.
LLVM_ABI void setCorrectMemberOfFlag(omp::OpenMPOffloadMappingFlags &Flags, omp::OpenMPOffloadMappingFlags MemberOfFlag)
Given an initial flag set, this function modifies it to contain the passed in MemberOfFlag generated ...
LLVM_ABI Error emitOffloadingArraysAndArgs(InsertPointTy AllocaIP, InsertPointTy CodeGenIP, TargetDataInfo &Info, TargetDataRTArgs &RTArgs, MapInfosTy &CombinedInfo, CustomMapperCallbackTy CustomMapperCB, bool IsNonContiguous=false, bool ForEndCall=false, function_ref< void(unsigned int, Value *)> DeviceAddrCB=nullptr)
Allocates memory for and populates the arrays required for offloading (offload_{baseptrs|ptrs|mappers...
LLVM_ABI Constant * getOrCreateDefaultSrcLocStr(uint32_t &SrcLocStrSize)
Return the (LLVM-IR) string describing the default source location.
LLVM_ABI InsertPointOrErrorTy createCritical(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, StringRef CriticalName, Value *HintInst)
Generator for 'omp critical'.
LLVM_ABI void createError(const LocationDescription &Loc, bool IsFatal, Value *Message)
Generate a call to the runtime to emit the diagnostic of an OpenMP error directive with at(execution)...
LLVM_ABI void createOffloadEntry(Constant *ID, Constant *Addr, uint64_t Size, int32_t Flags, GlobalValue::LinkageTypes, StringRef Name="")
Creates offloading entry for the provided entry ID ID, address Addr, size Size, and flags Flags.
static LLVM_ABI unsigned getOpenMPDefaultSimdAlign(const Triple &TargetTriple, const StringMap< bool > &Features)
Get the default alignment value for given target.
LLVM_ABI unsigned getFlagMemberOffset()
Get the offset of the OMP_MAP_MEMBER_OF field.
LLVM_ABI InsertPointOrErrorTy applyWorkshareLoop(DebugLoc DL, CanonicalLoopInfo *CLI, InsertPointTy AllocaIP, bool NeedsBarrier, llvm::omp::ScheduleKind SchedKind=llvm::omp::OMP_SCHEDULE_Default, Value *ChunkSize=nullptr, bool HasSimdModifier=false, bool HasMonotonicModifier=false, bool HasNonmonotonicModifier=false, bool HasOrderedClause=false, omp::WorksharingLoopType LoopType=omp::WorksharingLoopType::ForStaticLoop, bool NoLoop=false, bool HasDistSchedule=false, Value *DistScheduleChunkSize=nullptr)
Modifies the canonical loop to be a workshare loop.
LLVM_ABI InsertPointOrErrorTy createAtomicCapture(const LocationDescription &Loc, InsertPointTy AllocaIP, AtomicOpValue &X, AtomicOpValue &V, Value *Expr, AtomicOrdering AO, AtomicRMWInst::BinOp RMWOp, AtomicUpdateCallbackTy &UpdateOp, bool UpdateExpr, bool IsPostfixUpdate, bool IsXBinopExpr, bool IsIgnoreDenormalMode=false, bool IsFineGrainedMemory=false, bool IsRemoteMemory=false)
Emit atomic update for constructs: — Only Scalar data types V = X; X = X BinOp Expr ,...
LLVM_ABI CanonicalLoopInfo * createLoopSkeleton(DebugLoc DL, Value *TripCount, Function *F, BasicBlock *PreInsertBefore, BasicBlock *PostInsertBefore, const Twine &Name={}, bool IsCollapsed=false)
Create the control flow structure of a canonical OpenMP loop.
LLVM_ABI void createOffloadEntriesAndInfoMetadata(EmitMetadataErrorReportFunctionTy &ErrorReportFunction)
LLVM_ABI void applySimd(CanonicalLoopInfo *Loop, MapVector< Value *, Value * > AlignedVars, Value *IfCond, omp::OrderKind Order, ConstantInt *Simdlen, ConstantInt *Safelen)
Add metadata to simd-ize a loop.
SmallVector< std::unique_ptr< OutlineInfo >, 16 > OutlineInfos
Collection of regions that need to be outlined during finalization.
LLVM_ABI InsertPointOrErrorTy createAtomicUpdate(const LocationDescription &Loc, InsertPointTy AllocaIP, AtomicOpValue &X, Value *Expr, AtomicOrdering AO, AtomicRMWInst::BinOp RMWOp, AtomicUpdateCallbackTy &UpdateOp, bool IsXBinopExpr, bool IsIgnoreDenormalMode=false, bool IsFineGrainedMemory=false, bool IsRemoteMemory=false)
Emit atomic update for constructs: X = X BinOp Expr ,or X = Expr BinOp X For complex Operations: X = ...
std::function< std::tuple< std::string, uint64_t >()> FileIdentifierInfoCallbackTy
bool isLastFinalizationInfoCancellable(omp::Directive DK)
Return true if the last entry in the finalization stack is of kind DK and cancellable.
LLVM_ABI InsertPointTy emitTargetKernel(const LocationDescription &Loc, InsertPointTy AllocaIP, Value *&Return, Value *Ident, Value *DeviceID, Value *NumTeams, Value *NumThreads, Value *HostPtr, ArrayRef< Value * > KernelArgs)
Generate a target region entry call.
LLVM_ABI GlobalVariable * createOffloadMaptypes(SmallVectorImpl< uint64_t > &Mappings, std::string VarName)
Create the global variable holding the offload mappings information.
LLVM_ABI ~OpenMPIRBuilder()
LLVM_ABI Expected< Function * > emitUserDefinedMapper(function_ref< MapInfosOrErrorTy(InsertPointTy CodeGenIP, llvm::Value *PtrPHI, llvm::Value *BeginArg)> PrivAndGenMapInfoCB, llvm::Type *ElemTy, StringRef FuncName, CustomMapperCallbackTy CustomMapperCB, bool PreserveMemberOfFlags=false, bool PropagatePresentToPointee=false)
Emit the user-defined mapper function.
LLVM_ABI CallInst * createCachedThreadPrivate(const LocationDescription &Loc, llvm::Value *Pointer, llvm::ConstantInt *Size, const llvm::Twine &Name=Twine(""))
Create a runtime call for kmpc_threadprivate_cached.
IRBuilder Builder
The LLVM-IR Builder used to create IR.
LLVM_ABI GlobalValue * createGlobalFlag(unsigned Value, StringRef Name)
Create a hidden global flag Name in the module with initial value Value.
LLVM_ABI void emitOffloadingArraysArgument(IRBuilderBase &Builder, OpenMPIRBuilder::TargetDataRTArgs &RTArgs, OpenMPIRBuilder::TargetDataInfo &Info, bool ForEndCall=false)
Emit the arguments to be passed to the runtime library based on the arrays of base pointers,...
LLVM_ABI InsertPointOrErrorTy createMasked(const LocationDescription &Loc, BodyGenCallbackTy BodyGenCB, FinalizeCallbackTy FiniCB, Value *Filter)
Generator for 'omp masked'.
LLVM_ABI Expected< CanonicalLoopInfo * > createCanonicalLoop(const LocationDescription &Loc, LoopBodyGenCallbackTy BodyGenCB, Value *TripCount, const Twine &Name="loop")
Generator for the control flow structure of an OpenMP canonical loop.
function_ref< Expected< InsertPointTy >( InsertPointTy AllocaIP, InsertPointTy CodeGenIP, Value *DestPtr, Value *SrcPtr)> TaskDupCallbackTy
Callback type for task duplication function code generation.
LLVM_ABI Value * getSizeInBytes(Value *BasePtr)
Computes the size of type in bytes.
llvm::function_ref< llvm::Error( InsertPointTy BodyIP, llvm::Value *LinearIV)> IteratorBodyGenTy
LLVM_ABI FunctionCallee createDispatchDeinitFunction()
Returns __kmpc_dispatch_deinit runtime function.
LLVM_ABI void registerTargetGlobalVariable(OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind CaptureClause, OffloadEntriesInfoManager::OMPTargetDeviceClauseKind DeviceClause, bool IsDeclaration, bool IsExternallyVisible, TargetRegionEntryInfo EntryInfo, StringRef MangledName, std::vector< GlobalVariable * > &GeneratedRefs, bool OpenMPSIMD, std::vector< Triple > TargetTriple, std::function< Constant *()> GlobalInitializer, std::function< GlobalValue::LinkageTypes()> VariableLinkage, Type *LlvmPtrTy, Constant *Addr)
Registers a target variable for device or host.
LLVM_ABI void createTargetDeinit(const LocationDescription &Loc, int32_t TeamsReductionDataSize=0)
Create a runtime call for kmpc_target_deinit.
BodyGenTy
Type of BodyGen to use for region codegen.
LLVM_ABI CanonicalLoopInfo * fuseLoops(DebugLoc DL, ArrayRef< CanonicalLoopInfo * > Loops)
Fuse a sequence of loops.
LLVM_ABI void emitX86DeclareSimdFunction(llvm::Function *Fn, unsigned NumElements, const llvm::APSInt &VLENVal, llvm::ArrayRef< DeclareSimdAttrTy > ParamAttrs, DeclareSimdBranch Branch)
Emit x86 vector-function ABI attributes for a declare simd function.
SmallVector< llvm::Function *, 16 > ConstantAllocaRaiseCandidates
A collection of candidate target functions that's constant allocas will attempt to be raised on a cal...
OffloadEntriesInfoManager OffloadInfoManager
Info manager to keep track of target regions.
static LLVM_ABI std::pair< int32_t, int32_t > readTeamBoundsForKernel(const Triple &T, Function &Kernel)
Read/write a bounds on teams for Kernel.
const std::string ompOffloadInfoName
OMP Offload Info Metadata name string.
Expected< InsertPointTy > InsertPointOrErrorTy
Type used to represent an insertion point or an error value.
LLVM_ABI InsertPointTy createCopyPrivate(const LocationDescription &Loc, llvm::Value *BufSize, llvm::Value *CpyBuf, llvm::Value *CpyFn, llvm::Value *DidIt)
Generator for __kmpc_copyprivate.
LLVM_ABI InsertPointOrErrorTy createSections(const LocationDescription &Loc, InsertPointTy AllocaIP, ArrayRef< StorableBodyGenCallbackTy > SectionCBs, PrivatizeCallbackTy PrivCB, FinalizeCallbackTy FiniCB, bool IsCancellable, bool IsNowait)
Generator for 'omp sections'.
std::function< void(EmitMetadataErrorKind, TargetRegionEntryInfo)> EmitMetadataErrorReportFunctionTy
Callback function type.
function_ref< InsertPointOrErrorTy( Argument &Arg, Value *Input, Value *&RetVal, InsertPointTy AllocaIP, InsertPointTy CodeGenIP, ArrayRef< InsertPointTy > DeallocIPs)> TargetGenArgAccessorsCallbackTy
LLVM_ABI Expected< ScanInfo * > scanInfoInitialize()
Creates a ScanInfo object, allocates and returns the pointer.
LLVM_ABI InsertPointOrErrorTy emitTargetTask(TargetTaskBodyCallbackTy TaskBodyCB, Value *DeviceID, Value *RTLoc, OpenMPIRBuilder::InsertPointTy AllocaIP, const DependenciesInfo &Dependencies, const TargetDataRTArgs &RTArgs, bool HasNoWait)
Generate a target-task for the target construct.
LLVM_ABI InsertPointTy createAtomicRead(const LocationDescription &Loc, AtomicOpValue &X, AtomicOpValue &V, AtomicOrdering AO, InsertPointTy AllocaIP)
Emit atomic Read for : V = X — Only Scalar data types.
function_ref< Error(InsertPointTy AllocaIP, InsertPointTy CodeGenIP, ArrayRef< BasicBlock * > DeallocBlocks)> BodyGenCallbackTy
Callback type for body (=inner region) code generation.
bool updateToLocation(const LocationDescription &Loc)
Update the internal location to Loc.
LLVM_ABI void createFlush(const LocationDescription &Loc)
Generator for 'omp flush'.
LLVM_ABI void createTaskwait(const LocationDescription &Loc, DependenciesInfo Dependencies={})
Generator for 'omp taskwait'.
LLVM_ABI Constant * getAddrOfDeclareTargetVar(OffloadEntriesInfoManager::OMPTargetGlobalVarEntryKind CaptureClause, OffloadEntriesInfoManager::OMPTargetDeviceClauseKind DeviceClause, bool IsDeclaration, bool IsExternallyVisible, TargetRegionEntryInfo EntryInfo, StringRef MangledName, std::vector< GlobalVariable * > &GeneratedRefs, bool OpenMPSIMD, std::vector< Triple > TargetTriple, Type *LlvmPtrTy, std::function< Constant *()> GlobalInitializer, std::function< GlobalValue::LinkageTypes()> VariableLinkage)
Retrieve (or create if non-existent) the address of a declare target variable, used in conjunction wi...
origPtr *with the address space normalization required by the runtime entry point *The NULL descriptor makes the runtime walk the enclosing taskgroups to *find the matching task_reduction registration for the item The lookups *are emitted at p Loc
EmitMetadataErrorKind
The kind of errors that can occur when emitting the offload entries and metadata.
@ EMIT_MD_DECLARE_TARGET_ERROR
@ EMIT_MD_GLOBAL_VAR_INDIRECT_ERROR
@ EMIT_MD_GLOBAL_VAR_LINK_ERROR
@ EMIT_MD_TARGET_REGION_ERROR
unsigned getOpcode() const
Return the opcode for this Instruction or ConstantExpr.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
Pseudo-analysis pass that exposes the PassInstrumentation to pass managers.
Class to represent pointers.
static PointerType * getUnqual(LLVMContext &C)
This constructs an opaque pointer to an object in the default address space (address space zero).
static LLVM_ABI PointerType * get(LLVMContext &C, unsigned AddressSpace)
This constructs an opaque pointer to an object in a numbered address space.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
Analysis pass that exposes the ScalarEvolution for a function.
LLVM_ABI ScalarEvolution run(Function &F, FunctionAnalysisManager &AM)
The main scalar evolution driver.
ScanInfo holds the information to assist in lowering of Scan reduction.
llvm::SmallDenseMap< llvm::Value *, llvm::Value * > * ScanBuffPtrs
Maps the private reduction variable to the pointer of the temporary buffer.
llvm::BasicBlock * OMPScanLoopExit
Exit block of loop body.
llvm::Value * IV
Keeps track of value of iteration variable for input/scan loop to be used for Scan directive lowering...
llvm::BasicBlock * OMPAfterScanBlock
Dominates the body of the loop before scan directive.
llvm::BasicBlock * OMPScanInit
Block before loop body where scan initializations are done.
llvm::BasicBlock * OMPBeforeScanBlock
Dominates the body of the loop before scan directive.
llvm::BasicBlock * OMPScanFinish
Block after loop body where scan finalizations are done.
llvm::Value * Span
Stores the span of canonical loop being lowered to be used for temporary buffer allocation or Finaliz...
bool OMPFirstScanLoop
If true, it indicates Input phase is lowered; else it indicates ScanPhase is lowered.
llvm::BasicBlock * OMPScanDispatch
Controls the flow to before or after scan blocks.
A vector that has set insertion semantics.
bool remove_if(UnaryPredicate P)
Remove items from the set vector based on a predicate function.
bool empty() const
Determine if the SetVector is empty or not.
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
bool test(unsigned Idx) const
Returns true if bit Idx is set.
bool all() const
Returns true if all bits are set.
bool any() const
Returns true if any bit is set.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void append(StringRef RHS)
Append from a StringRef.
StringRef str() const
Explicit conversion to StringRef.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
void setAlignment(Align Align)
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this store instruction.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
ValueTy lookup(StringRef Key) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
Represent a constant reference to a string, i.e.
std::string str() const
Get the contents as an std::string.
constexpr bool empty() const
Check if the string is empty.
constexpr size_t size() const
Get the string size.
size_t count(char C) const
Return the number of occurrences of C in the string.
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
Class to represent struct types.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
static LLVM_ABI StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Type * getElementType(unsigned N) const
LLVM_ABI void addCase(ConstantInt *OnVal, BasicBlock *Dest)
Add an entry to the switch instruction.
Analysis pass providing the TargetTransformInfo.
LLVM_ABI Result run(const Function &F, FunctionAnalysisManager &)
TargetTransformInfo Result
Analysis pass providing the TargetLibraryInfo.
Target - Wrapper for Target specific information.
TargetMachine * createTargetMachine(const Triple &TT, StringRef CPU, StringRef Features, const TargetOptions &Options, std::optional< Reloc::Model > RM, std::optional< CodeModel::Model > CM=std::nullopt, CodeGenOptLevel OL=CodeGenOptLevel::Default, bool JIT=false) const
createTargetMachine - Create a target specific machine implementation for the specified Triple.
Triple - Helper class for working with autoconf configuration names.
bool isPPC() const
Tests whether the target is PowerPC (32- or 64-bit LE or BE).
bool isX86() const
Tests whether the target is x86 (32- or 64-bit).
bool isWasm() const
Tests whether the target is wasm (32- and 64-bit).
bool isSystemZ() const
Tests whether the target is SystemZ.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
LLVM_ABI unsigned getIntegerBitWidth() const
LLVM_ABI Type * getStructElementType(unsigned N) const
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isPointerTy() const
True if this is an instance of PointerType.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
bool isStructTy() const
True if this is an instance of StructType.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
bool isVoidTy() const
Return true if this is 'void'.
Unconditional Branch instruction.
static UncondBrInst * Create(BasicBlock *Target, InsertPosition InsertBefore=nullptr)
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
This function has undefined behavior.
Produce an estimate of the unrolled cost of the specified loop.
LLVM_ABI bool canUnroll(OptimizationRemarkEmitter *ORE=nullptr, const Loop *L=nullptr) const
Whether it is legal to unroll this loop.
uint64_t getRolledLoopSize() const
A Use represents the edge between a Value definition and its users.
void setOperand(unsigned i, Value *Val)
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
user_iterator user_begin()
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
LLVM_ABI bool hasNUses(unsigned N) const
Return true if this Value has exactly N uses.
LLVM_ABI User * getUniqueUndroppableUser()
Return true if there is exactly one unique user of this value that cannot be dropped (that user can h...
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
LLVM_ABI bool replaceUsesWithIf(Value *New, llvm::function_ref< bool(Use &U)> ShouldReplace)
Go through the uses list for this definition and make each use point to "V" if the callback ShouldRep...
iterator_range< use_iterator > uses()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
A raw_ostream that writes to an SmallVector or SmallString.
StringRef str() const
Return a StringRef for the vector contents.
The virtual file system interface.
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(const Twine &Name, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatile=false, bool IsText=true)
This is a convenience method that opens a file, gets its content and then closes the file.
virtual llvm::ErrorOr< Status > status(const Twine &Path)=0
Get the status of the entry at Path, if one exists.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ SPIR_KERNEL
Used for SPIR kernel functions.
@ PTX_Kernel
Call to a PTX kernel. Passes all arguments in parameter space.
@ BasicBlock
Various leaf nodes.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
Flag
These should be considered private to the implementation of the MCInstrDesc class.
constexpr StringLiteral MaxNTID("nvvm.maxntid")
constexpr StringLiteral MaxClusterRank("nvvm.maxclusterrank")
initializer< Ty > init(const Ty &Val)
@ User
could "use" a pointer
LLVM_ABI GlobalVariable * emitOffloadingEntry(Module &M, object::OffloadKind Kind, Constant *Addr, StringRef Name, uint64_t Size, uint32_t Flags, uint64_t Data, Constant *AuxAddr=nullptr)
OpenMPOffloadMappingFlags
Values for bit flags used to specify the mapping type for offloading.
@ OMP_MAP_PTR_AND_OBJ
The element being mapped is a pointer-pointee pair; both the pointer and the pointee should be mapped...
@ OMP_MAP_MEMBER_OF
The 16 MSBs of the flags indicate whether the entry is member of some struct/class.
IdentFlag
IDs for all omp runtime library ident_t flag encodings (see their defintion in openmp/runtime/src/kmp...
RuntimeFunction
IDs for all omp runtime library (RTL) functions.
constexpr const GV & getAMDGPUGridValues()
static constexpr GV SPIRVGridValues
For generic SPIR-V GPUs.
OMPDynGroupprivateFallbackType
The fallback types for the dyn_groupprivate clause.
static constexpr GV NVPTXGridValues
For Nvidia GPUs.
@ OMP_TGT_EXEC_MODE_SPMD_NO_LOOP
@ OMP_TGT_EXEC_MODE_GENERIC
Function * Kernel
Summary of a kernel (=entry point for target offloading).
WorksharingLoopType
A type of worksharing loop construct.
EnumSet< Property, Property_enumSize > Properties
OMPAtomicCompareOp
Atomic compare operations. Currently OpenMP only supports ==, >, and <.
NodeAddr< PhiNode * > Phi
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
LLVM_ABI BasicBlock * splitBBWithSuffix(IRBuilderBase &Builder, bool CreateBranch, llvm::Twine Suffix=".split")
Like splitBB, but reuses the current block's name for the new name.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
LLVM_ABI unsigned computeUnrollCount(Loop *L, const TargetTransformInfo &TTI, DominatorTree &DT, LoopInfo *LI, AssumptionCache *AC, ScalarEvolution &SE, const SmallPtrSetImpl< const Value * > &EphValues, OptimizationRemarkEmitter *ORE, unsigned TripCount, unsigned MaxTripCount, bool MaxOrZero, unsigned TripMultiple, const UnrollCostEstimator &UCE, TargetTransformInfo::UnrollingPreferences &UP, TargetTransformInfo::PeelingPreferences &PP)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
hash_code hash_value(const FixedPointSemantics &Val)
LLVM_ABI Expected< std::unique_ptr< Module > > parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context, ParserCallbacks Callbacks={})
Read the specified bitcode file, returning the module.
detail::zippy< detail::zip_first, T, U, Args... > zip_equal(T &&t, U &&u, Args &&...args)
zip iterator that assumes that all iteratees have the same length.
@ LLVM_MARK_AS_BITMASK_ENUM
LLVM_ABI BasicBlock * CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap, const Twine &NameSuffix="", Function *F=nullptr, ClonedCodeInfo *CodeInfo=nullptr, bool MapAtoms=true)
Return a copy of the specified basic block, but without embedding the block into a particular functio...
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
unsigned getPointerAddressSpace(const Type *T)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto successors(const MachineBasicBlock *BB)
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
testing::Matcher< const detail::ErrorHolder & > Failed()
constexpr from_range_t from_range
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE()
LLVM_ABI BasicBlock * splitBB(IRBuilderBase::InsertPoint IP, bool CreateBranch, DebugLoc DL, llvm::Twine Name={})
Split a BasicBlock at an InsertPoint, even if the block is degenerate (missing the terminator).
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
LLVM_ABI TargetTransformInfo::UnrollingPreferences gatherUnrollingPreferences(Loop *L, ScalarEvolution &SE, const TargetTransformInfo &TTI, BlockFrequencyInfo *BFI, ProfileSummaryInfo *PSI, llvm::OptimizationRemarkEmitter &ORE, int OptLevel, std::optional< unsigned > UserThreshold, std::optional< bool > UserAllowPartial, std::optional< bool > UserRuntime, std::optional< bool > UserUpperBound, std::optional< unsigned > UserFullUnrollMaxCount)
Gather the various unrolling parameters based on the defaults, compiler flags, TTI overrides and user...
std::string utostr(uint64_t X, bool isNeg=false)
ErrorOr< T > expectedToErrorOrAndEmitErrors(LLVMContext &Ctx, Expected< T > Val)
bool isa_and_nonnull(const Y &Val)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto dyn_cast_or_null(const Y &Val)
LLVM_ABI bool convertUsersOfConstantsToInstructions(ArrayRef< Constant * > Consts, Function *RestrictToFunc=nullptr, bool RemoveDeadConstants=true, bool IncludeSelf=false)
Replace constant expressions users of the given constants with instructions.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
auto reverse(ContainerTy &&C)
LLVM_ABI TargetTransformInfo::PeelingPreferences gatherPeelingPreferences(Loop *L, ScalarEvolution &SE, const TargetTransformInfo &TTI, std::optional< bool > UserAllowPeeling, std::optional< bool > UserAllowProfileBasedPeeling, bool UnrollingSpecficValues=false)
LLVM_ABI void SplitBlockAndInsertIfThenElse(Value *Cond, BasicBlock::iterator SplitBefore, Instruction **ThenTerm, Instruction **ElseTerm, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr)
SplitBlockAndInsertIfThenElse is similar to SplitBlockAndInsertIfThen, but also creates the ElseBlock...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
CodeGenOptLevel
Code generation optimization level.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
AtomicOrdering
Atomic ordering for LLVM's memory model.
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
LLVM_ABI bool MergeBlockIntoPredecessor(BasicBlock *BB, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, MemoryDependenceResults *MemDep=nullptr, bool PredecessorWithTwoSuccessors=false, DominatorTree *DT=nullptr)
Attempts to merge a block into its predecessor, if possible.
@ Mul
Product of integers.
LLVM_ABI BasicBlock * SplitBlock(BasicBlock *Old, BasicBlock::iterator SplitPt, DominatorTree *DT, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, const Twine &BBName="")
Split the specified block at the specified instruction.
DWARFExpression::Operation Op
LLVM_ABI void remapInstructionsInBlocks(ArrayRef< BasicBlock * > Blocks, ValueToValueMapTy &VMap)
Remaps instructions in Blocks using the mapping in VMap.
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt copy(R &&Range, OutputIt Out)
constexpr unsigned BitWidth
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
LLVM_ABI void spliceBB(IRBuilderBase::InsertPoint IP, BasicBlock *New, bool CreateBranch, DebugLoc DL)
Move the instruction after an InsertPoint to the beginning of another BasicBlock.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
auto predecessors(const MachineBasicBlock *BB)
auto filter_to_vector(ContainerTy &&C, PredicateFn &&Pred)
Filter a range to a SmallVector with the element types deduced.
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
LLVM_ABI Constant * ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val, ArrayRef< unsigned > Idxs)
Attempt to constant fold an insertvalue instruction with the specified operands and indices.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI void DeleteDeadBlocks(ArrayRef< BasicBlock * > BBs, DomTreeUpdater *DTU=nullptr, bool KeepOneInputPHIs=false)
Delete the specified blocks from BB.
bool to_integer(StringRef S, N &Num, unsigned Base=0)
Convert the string S to an integer of the specified type using the radix Base. If Base is 0,...
static auto filterDbgVars(iterator_range< simple_ilist< DbgRecord >::iterator > R)
Filter the DbgRecord range to DbgVariableRecord types only and downcast.
This struct is a compact representation of a valid (non-zero power of two) alignment.
static LLVM_ABI void collectEphemeralValues(const Loop *L, AssumptionCache *AC, SmallPtrSetImpl< const Value * > &EphValues)
Collect a loop's ephemeral values (those used only by an assume or similar intrinsics in the loop).
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
A struct to pack the relevant information for an OpenMP affinity clause.
a struct to pack relevant information while generating atomic Ops
A struct to pack the relevant information for an OpenMP depend clause.
omp::RTLDependenceKindTy DepKind
A struct to pack static and dynamic dependency information for a task.
SmallVector< DependData > Deps
LLVM_ABI Error mergeFiniBB(IRBuilderBase &Builder, BasicBlock *ExistingFiniBB)
For cases where there is an unavoidable existing finalization block (e.g.
LLVM_ABI Expected< BasicBlock * > getFiniBB(IRBuilderBase &Builder)
The basic block to which control should be transferred to implement the FiniCB.
Description of a LLVM-IR insertion point (IP) and a debug/source location (filename,...
MapNonContiguousArrayTy Offsets
MapNonContiguousArrayTy Counts
MapNonContiguousArrayTy Strides
This structure contains combined information generated for mappable clauses, including base pointers,...
MapDeviceInfoArrayTy DevicePointers
MapValuesArrayTy BasePointers
MapValuesArrayTy Pointers
StructNonContiguousInfo NonContigInfo
Helper that contains information about regions we need to outline during finalization.
void collectBlocks(SmallPtrSetImpl< BasicBlock * > &BlockSet, SmallVectorImpl< BasicBlock * > &BlockVector)
Collect all blocks in between EntryBB and ExitBB in both the given vector and set.
BasicBlock * OuterAllocBB
virtual std::unique_ptr< CodeExtractor > createCodeExtractor(ArrayRef< BasicBlock * > Blocks, bool ArgsInZeroAddressSpace, Twine Suffix=Twine(""))
Create a CodeExtractor instance based on the information stored in this structure,...
Information about an OpenMP reduction.
EvalKind EvaluationKind
Reduction evaluation kind - scalar, complex or aggregate.
ReductionGenAtomicCBTy AtomicReductionGen
Callback for generating the atomic reduction body, may be null.
ReductionGenCBTy ReductionGen
Callback for generating the reduction body.
Value * Variable
Reduction variable of pointer type.
Value * PrivateVariable
Thread-private partial reduction variable.
ReductionGenClangCBTy ReductionGenClang
Clang callback for generating the reduction body.
Type * ElementType
Reduction element type, must match pointee type of variable.
ReductionGenDataPtrPtrCBTy DataPtrPtrGen
Container for the arguments used to pass data to the runtime library.
Value * SizesArray
The array of sizes passed to the runtime library.
Value * PointersArray
The array of section pointers passed to the runtime library.
Value * MappersArray
The array of user-defined mappers passed to the runtime library.
Value * MapTypesArrayEnd
The array of map types passed to the runtime library for the end of the region, or nullptr if there a...
Value * BasePointersArray
The array of base pointer passed to the runtime library.
Value * MapTypesArray
The array of map types passed to the runtime library for the beginning of the region or for the entir...
Value * MapNamesArray
The array of original declaration names of mapped pointers sent to the runtime library for debugging.
Data structure that contains the needed information to construct the kernel args vector.
bool StrictBlocks
True if the kernel strictly requires the number of blocks and threads above to run.
ArrayRef< Value * > NumThreads
The number of threads.
TargetDataRTArgs RTArgs
Arguments passed to the runtime library.
Value * NumIterations
The number of iterations.
Value * DynCGroupMem
The size of the dynamic shared memory.
unsigned NumTargetItems
Number of arguments passed to the runtime library.
bool HasNoWait
True if the kernel has 'no wait' clause.
ArrayRef< Value * > NumTeams
The number of teams.
omp::OMPDynGroupprivateFallbackType DynCGroupMemFallback
The fallback mechanism for the shared memory.
Container to pass the default attributes with which a kernel must be launched, used to set kernel att...
omp::OMPTgtExecModeFlags ExecFlags
SmallVector< int32_t, 3 > MaxTeams
Container to pass LLVM IR runtime values or constants related to the number of teams and threads with...
Value * DeviceID
Device ID value used in the kernel launch.
SmallVector< Value *, 3 > MaxTeams
Value * LoopTripCount
Total number of iterations of the SPMD or Generic-SPMD kernel or null if it is a generic kernel.
SmallVector< Value *, 3 > TargetThreadLimit
SmallVector< Value *, 3 > TeamsThreadLimit
SmallVector< Value * > MaxThreads
'parallel' construct 'num_threads' clause value, if present and it is an SPMD kernel.
Data structure to contain the information needed to uniquely identify a target entry.
static LLVM_ABI void getTargetRegionEntryFnName(SmallVectorImpl< char > &Name, StringRef ParentName, unsigned DeviceID, unsigned FileID, unsigned Line, unsigned Count)
static constexpr const char * KernelNamePrefix
The prefix used for kernel names.
static LLVM_ABI const Target * lookupTarget(const Triple &TheTriple, std::string &Error)
lookupTarget - Lookup a target based on a target triple.
Defines various target-specific GPU grid values that must be consistent between host RTL (plugin),...