70#define DEBUG_TYPE "openmp-ir-builder"
77 cl::desc(
"Use optimistic attributes describing "
78 "'as-if' properties of runtime calls."),
82 "openmp-ir-builder-unroll-threshold-factor",
cl::Hidden,
83 cl::desc(
"Factor for the unroll threshold to account for code "
84 "simplifications still taking place"),
88 "openmp-ir-builder-use-default-max-threads",
cl::Hidden,
99 if (!IP1.isSet() || !IP2.isSet())
101 return IP1.getBlock() == IP2.getBlock() && IP1.getPoint() == IP2.getPoint();
106 switch (SchedType & ~OMPScheduleType::MonotonicityMask) {
107 case OMPScheduleType::UnorderedStaticChunked:
108 case OMPScheduleType::UnorderedStatic:
109 case OMPScheduleType::UnorderedDynamicChunked:
110 case OMPScheduleType::UnorderedGuidedChunked:
111 case OMPScheduleType::UnorderedRuntime:
112 case OMPScheduleType::UnorderedAuto:
113 case OMPScheduleType::UnorderedTrapezoidal:
114 case OMPScheduleType::UnorderedGreedy:
115 case OMPScheduleType::UnorderedBalanced:
116 case OMPScheduleType::UnorderedGuidedIterativeChunked:
117 case OMPScheduleType::UnorderedGuidedAnalyticalChunked:
118 case OMPScheduleType::UnorderedSteal:
119 case OMPScheduleType::UnorderedStaticBalancedChunked:
120 case OMPScheduleType::UnorderedGuidedSimd:
121 case OMPScheduleType::UnorderedRuntimeSimd:
122 case OMPScheduleType::OrderedStaticChunked:
123 case OMPScheduleType::OrderedStatic:
124 case OMPScheduleType::OrderedDynamicChunked:
125 case OMPScheduleType::OrderedGuidedChunked:
126 case OMPScheduleType::OrderedRuntime:
127 case OMPScheduleType::OrderedAuto:
128 case OMPScheduleType::OrderdTrapezoidal:
129 case OMPScheduleType::NomergeUnorderedStaticChunked:
130 case OMPScheduleType::NomergeUnorderedStatic:
131 case OMPScheduleType::NomergeUnorderedDynamicChunked:
132 case OMPScheduleType::NomergeUnorderedGuidedChunked:
133 case OMPScheduleType::NomergeUnorderedRuntime:
134 case OMPScheduleType::NomergeUnorderedAuto:
135 case OMPScheduleType::NomergeUnorderedTrapezoidal:
136 case OMPScheduleType::NomergeUnorderedGreedy:
137 case OMPScheduleType::NomergeUnorderedBalanced:
138 case OMPScheduleType::NomergeUnorderedGuidedIterativeChunked:
139 case OMPScheduleType::NomergeUnorderedGuidedAnalyticalChunked:
140 case OMPScheduleType::NomergeUnorderedSteal:
141 case OMPScheduleType::NomergeOrderedStaticChunked:
142 case OMPScheduleType::NomergeOrderedStatic:
143 case OMPScheduleType::NomergeOrderedDynamicChunked:
144 case OMPScheduleType::NomergeOrderedGuidedChunked:
145 case OMPScheduleType::NomergeOrderedRuntime:
146 case OMPScheduleType::NomergeOrderedAuto:
147 case OMPScheduleType::NomergeOrderedTrapezoidal:
148 case OMPScheduleType::OrderedDistributeChunked:
149 case OMPScheduleType::OrderedDistribute:
157 SchedType & OMPScheduleType::MonotonicityMask;
158 if (MonotonicityFlags == OMPScheduleType::MonotonicityMask)
172 Builder.restoreIP(IP);
176 if (Builder.GetInsertPoint() != BB->
end())
186 unsigned Line = FSP->getScopeLine() ? FSP->getScopeLine() : FSP->getLine();
187 Builder.SetCurrentDebugLocation(
193 return T.isAMDGPU() ||
T.isNVPTX() ||
T.isSPIRV();
199 Kernel->getFnAttribute(
"target-features").getValueAsString();
200 if (Features.
count(
"+wavefrontsize64"))
215 bool HasSimdModifier,
bool HasDistScheduleChunks) {
217 switch (ClauseKind) {
218 case OMP_SCHEDULE_Default:
219 case OMP_SCHEDULE_Static:
220 return HasChunks ? OMPScheduleType::BaseStaticChunked
221 : OMPScheduleType::BaseStatic;
222 case OMP_SCHEDULE_Dynamic:
223 return OMPScheduleType::BaseDynamicChunked;
224 case OMP_SCHEDULE_Guided:
225 return HasSimdModifier ? OMPScheduleType::BaseGuidedSimd
226 : OMPScheduleType::BaseGuidedChunked;
227 case OMP_SCHEDULE_Auto:
229 case OMP_SCHEDULE_Runtime:
230 return HasSimdModifier ? OMPScheduleType::BaseRuntimeSimd
231 : OMPScheduleType::BaseRuntime;
232 case OMP_SCHEDULE_Distribute:
233 return HasDistScheduleChunks ? OMPScheduleType::BaseDistributeChunked
234 : OMPScheduleType::BaseDistribute;
242 bool HasOrderedClause) {
243 assert((BaseScheduleType & OMPScheduleType::ModifierMask) ==
244 OMPScheduleType::None &&
245 "Must not have ordering nor monotonicity flags already set");
248 ? OMPScheduleType::ModifierOrdered
249 : OMPScheduleType::ModifierUnordered;
253 if (OrderingScheduleType ==
254 (OMPScheduleType::BaseGuidedSimd | OMPScheduleType::ModifierOrdered))
255 return OMPScheduleType::OrderedGuidedChunked;
256 else if (OrderingScheduleType == (OMPScheduleType::BaseRuntimeSimd |
257 OMPScheduleType::ModifierOrdered))
258 return OMPScheduleType::OrderedRuntime;
260 return OrderingScheduleType;
266 bool HasSimdModifier,
bool HasMonotonic,
267 bool HasNonmonotonic,
bool HasOrderedClause) {
268 assert((ScheduleType & OMPScheduleType::MonotonicityMask) ==
269 OMPScheduleType::None &&
270 "Must not have monotonicity flags already set");
271 assert((!HasMonotonic || !HasNonmonotonic) &&
272 "Monotonic and Nonmonotonic are contradicting each other");
275 return ScheduleType | OMPScheduleType::ModifierMonotonic;
276 }
else if (HasNonmonotonic) {
277 return ScheduleType | OMPScheduleType::ModifierNonmonotonic;
287 if ((BaseScheduleType == OMPScheduleType::BaseStatic) ||
288 (BaseScheduleType == OMPScheduleType::BaseStaticChunked) ||
294 return ScheduleType | OMPScheduleType::ModifierNonmonotonic;
302 bool HasSimdModifier,
bool HasMonotonicModifier,
303 bool HasNonmonotonicModifier,
bool HasOrderedClause,
304 bool HasDistScheduleChunks) {
306 ClauseKind, HasChunks, HasSimdModifier, HasDistScheduleChunks);
310 OrderedSchedule, HasSimdModifier, HasMonotonicModifier,
311 HasNonmonotonicModifier, HasOrderedClause);
319static std::optional<omp::OMPTgtExecModeFlags>
324 if (
Call->getCalledFunction()->getName() ==
"__kmpc_target_init") {
325 TargetInitCall =
Call;
350 std::optional<omp::OMPTgtExecModeFlags> ExecMode =
362 if (
Instruction *Term = Source->getTerminatorOrNull()) {
371 NewBr->setDebugLoc(
DL);
376 assert(New->getFirstInsertionPt() == New->begin() &&
377 "Target BB must not have PHI nodes");
393 New->splice(New->begin(), Old, IP.
getPoint(), Old->
end());
397 NewBr->setDebugLoc(
DL);
409 Builder.SetInsertPoint(Old);
413 Builder.SetCurrentDebugLocation(
DebugLoc);
423 New->replaceSuccessorsPhiUsesWith(Old, New);
432 Builder.SetInsertPoint(Builder.GetInsertBlock()->getTerminator());
434 Builder.SetInsertPoint(Builder.GetInsertBlock());
437 Builder.SetCurrentDebugLocation(
DebugLoc);
446 Builder.SetInsertPoint(Builder.GetInsertBlock()->getTerminator());
448 Builder.SetInsertPoint(Builder.GetInsertBlock());
451 Builder.SetCurrentDebugLocation(
DebugLoc);
468 const Twine &Name =
"",
bool AsPtr =
true,
469 bool Is64Bit =
false) {
470 Builder.restoreIP(OuterAllocaIP);
474 Builder.CreateAlloca(IntTy,
nullptr, Name +
".addr");
478 FakeVal = FakeValAddr;
480 FakeVal = Builder.CreateLoad(IntTy, FakeValAddr, Name +
".val");
485 Builder.restoreIP(InnerAllocaIP);
488 UseFakeVal = Builder.CreateLoad(IntTy, FakeVal, Name +
".use");
491 FakeVal, Is64Bit ? Builder.getInt64(10) : Builder.getInt32(10)));
504enum OpenMPOffloadingRequiresDirFlags {
506 OMP_REQ_UNDEFINED = 0x000,
508 OMP_REQ_NONE = 0x001,
510 OMP_REQ_REVERSE_OFFLOAD = 0x002,
512 OMP_REQ_UNIFIED_ADDRESS = 0x004,
514 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008,
516 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010,
523 DominatorTree *DT =
nullptr,
bool AggregateArgs =
false,
524 BlockFrequencyInfo *BFI =
nullptr,
525 BranchProbabilityInfo *BPI =
nullptr,
526 AssumptionCache *AC =
nullptr,
bool AllowVarArgs =
false,
527 bool AllowAlloca =
false,
528 BasicBlock *AllocationBlock =
nullptr,
530 std::string Suffix =
"",
bool ArgsInZeroAddressSpace =
false)
531 : CodeExtractor(BBs, DT, AggregateArgs, BFI, BPI, AC, AllowVarArgs,
532 AllowAlloca, AllocationBlock, DeallocationBlocks, Suffix,
533 ArgsInZeroAddressSpace),
534 OMPBuilder(OMPBuilder) {}
536 virtual ~OMPCodeExtractor() =
default;
539 OpenMPIRBuilder &OMPBuilder;
542class DeviceSharedMemCodeExtractor :
public OMPCodeExtractor {
544 using OMPCodeExtractor::OMPCodeExtractor;
545 virtual ~DeviceSharedMemCodeExtractor() =
default;
549 allocateVar(IRBuilder<>::InsertPoint AllocaIP,
Type *VarType,
550 const Twine &Name = Twine(
""),
551 AddrSpaceCastInst **CastedAlloc =
nullptr)
override {
552 return OMPBuilder.createOMPAllocShared(AllocaIP, VarType, Name);
555 virtual Instruction *deallocateVar(IRBuilder<>::InsertPoint DeallocIP,
557 return OMPBuilder.createOMPFreeShared(DeallocIP, Var, VarType);
564 OpenMPIRBuilder &OMPBuilder;
566 DeviceSharedMemOutlineInfo(OpenMPIRBuilder &OMPBuilder)
567 : OMPBuilder(OMPBuilder) {}
568 virtual ~DeviceSharedMemOutlineInfo() =
default;
570 virtual std::unique_ptr<CodeExtractor>
572 bool ArgsInZeroAddressSpace,
573 Twine Suffix = Twine(
""))
override;
579 : RequiresFlags(OMP_REQ_UNDEFINED) {}
583 bool HasRequiresReverseOffload,
bool HasRequiresUnifiedAddress,
584 bool HasRequiresUnifiedSharedMemory,
bool HasRequiresDynamicAllocators)
587 RequiresFlags(OMP_REQ_UNDEFINED) {
588 if (HasRequiresReverseOffload)
589 RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
590 if (HasRequiresUnifiedAddress)
591 RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
592 if (HasRequiresUnifiedSharedMemory)
593 RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
594 if (HasRequiresDynamicAllocators)
595 RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
599 return RequiresFlags & OMP_REQ_REVERSE_OFFLOAD;
603 return RequiresFlags & OMP_REQ_UNIFIED_ADDRESS;
607 return RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY;
611 return RequiresFlags & OMP_REQ_DYNAMIC_ALLOCATORS;
616 :
static_cast<int64_t
>(OMP_REQ_NONE);
621 RequiresFlags |= OMP_REQ_REVERSE_OFFLOAD;
623 RequiresFlags &= ~OMP_REQ_REVERSE_OFFLOAD;
628 RequiresFlags |= OMP_REQ_UNIFIED_ADDRESS;
630 RequiresFlags &= ~OMP_REQ_UNIFIED_ADDRESS;
635 RequiresFlags |= OMP_REQ_UNIFIED_SHARED_MEMORY;
637 RequiresFlags &= ~OMP_REQ_UNIFIED_SHARED_MEMORY;
642 RequiresFlags |= OMP_REQ_DYNAMIC_ALLOCATORS;
644 RequiresFlags &= ~OMP_REQ_DYNAMIC_ALLOCATORS;
657 constexpr size_t MaxDim = 3;
662 Value *DynCGroupMemFallbackFlag =
664 DynCGroupMemFallbackFlag =
Builder.CreateShl(DynCGroupMemFallbackFlag, 2);
669 StrictBlocksFlag =
Builder.CreateShl(StrictBlocksFlag, 6);
670 StrictThreadsFlag =
Builder.CreateShl(StrictThreadsFlag, 7);
672 Value *Flags =
Builder.CreateOr(HasNoWaitFlag, DynCGroupMemFallbackFlag);
673 Flags =
Builder.CreateOr(Flags, StrictBlocksFlag);
674 Flags =
Builder.CreateOr(Flags, StrictThreadsFlag);
680 Value *NumThreads3D =
711 auto FnAttrs = Attrs.getFnAttrs();
712 auto RetAttrs = Attrs.getRetAttrs();
714 for (
size_t ArgNo = 0; ArgNo < Fn.
arg_size(); ++ArgNo)
719 bool Param =
true) ->
void {
720 bool HasSignExt = AS.hasAttribute(Attribute::SExt);
721 bool HasZeroExt = AS.hasAttribute(Attribute::ZExt);
722 if (HasSignExt || HasZeroExt) {
723 assert(AS.getNumAttributes() == 1 &&
724 "Currently not handling extension attr combined with others.");
726 if (
auto AK = TargetLibraryInfo::getExtAttrForI32Param(
T, HasSignExt))
729 TargetLibraryInfo::getExtAttrForI32Return(
T, HasSignExt))
736#define OMP_ATTRS_SET(VarName, AttrSet) AttributeSet VarName = AttrSet;
737#include "llvm/Frontend/OpenMP/OMPKinds.def"
741#define OMP_RTL_ATTRS(Enum, FnAttrSet, RetAttrSet, ArgAttrSets) \
743 FnAttrs = FnAttrs.addAttributes(Ctx, FnAttrSet); \
744 addAttrSet(RetAttrs, RetAttrSet, false); \
745 for (size_t ArgNo = 0; ArgNo < ArgAttrSets.size(); ++ArgNo) \
746 addAttrSet(ArgAttrs[ArgNo], ArgAttrSets[ArgNo]); \
747 Fn.setAttributes(AttributeList::get(Ctx, FnAttrs, RetAttrs, ArgAttrs)); \
749#include "llvm/Frontend/OpenMP/OMPKinds.def"
763#define OMP_RTL(Enum, Str, IsVarArg, ReturnType, ...) \
765 FnTy = FunctionType::get(ReturnType, ArrayRef<Type *>{__VA_ARGS__}, \
767 Fn = M.getFunction(Str); \
769#include "llvm/Frontend/OpenMP/OMPKinds.def"
775#define OMP_RTL(Enum, Str, ...) \
777 Fn = Function::Create(FnTy, GlobalValue::ExternalLinkage, Str, M); \
779#include "llvm/Frontend/OpenMP/OMPKinds.def"
783 if (FnID == OMPRTL___kmpc_fork_call || FnID == OMPRTL___kmpc_fork_teams) {
793 LLVMContext::MD_callback,
795 2, {-1, -1},
true)}));
808 assert(Fn &&
"Failed to create OpenMP runtime function");
819 Builder.SetInsertPoint(FiniBB);
831 FiniBB = OtherFiniBB;
833 Builder.SetInsertPoint(FiniBB->getFirstNonPHIIt());
841 auto EndIt = FiniBB->end();
842 if (FiniBB->size() >= 1)
843 if (
auto Prev = std::prev(EndIt); Prev->isTerminator())
848 FiniBB->replaceAllUsesWith(OtherFiniBB);
849 FiniBB->eraseFromParent();
850 FiniBB = OtherFiniBB;
857 assert(Fn &&
"Failed to create OpenMP runtime function pointer");
880 for (
auto Inst =
Block->getReverseIterator()->begin();
881 Inst !=
Block->getReverseIterator()->end();) {
910 Block.getParent()->getEntryBlock().getTerminator()->getIterator();
931 DeferredOutlines.
push_back(std::move(OI));
935 ParallelRegionBlockSet.
clear();
937 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
947 bool ArgsInZeroAddressSpace =
Config.isTargetDevice();
948 std::unique_ptr<CodeExtractor> Extractor =
949 OI->createCodeExtractor(Blocks, ArgsInZeroAddressSpace,
".omp_par");
953 <<
" Exit: " << OI->ExitBB->getName() <<
"\n");
954 assert(Extractor->isEligible() &&
955 "Expected OpenMP outlining to be possible!");
957 for (
auto *V : OI->ExcludeArgsFromAggregate)
958 Extractor->excludeArgFromAggregate(V);
961 Extractor->extractCodeRegion(CEAC, OI->Inputs, OI->Outputs);
965 if (TargetCpuAttr.isStringAttribute())
968 auto TargetFeaturesAttr = OuterFn->
getFnAttribute(
"target-features");
969 if (TargetFeaturesAttr.isStringAttribute())
970 OutlinedFn->
addFnAttr(TargetFeaturesAttr);
973 LLVM_DEBUG(
dbgs() <<
" Outlined function: " << *OutlinedFn <<
"\n");
975 "OpenMP outlined functions should not return a value!");
980 M.getFunctionList().insertAfter(OuterFn->
getIterator(), OutlinedFn);
987 assert(OI->EntryBB->getUniquePredecessor() == &ArtificialEntry);
994 "Expected instructions to add in the outlined region entry");
996 End = ArtificialEntry.
rend();
1001 if (
I.isTerminator()) {
1003 if (
Instruction *TI = OI->EntryBB->getTerminatorOrNull())
1004 TI->adoptDbgRecords(&ArtificialEntry,
I.getIterator(),
false);
1008 I.moveBeforePreserving(*OI->EntryBB,
1009 OI->EntryBB->getFirstInsertionPt());
1012 OI->EntryBB->moveBefore(&ArtificialEntry);
1019 if (OI->PostOutlineCB)
1020 OI->PostOutlineCB(*OutlinedFn);
1022 if (OI->FixUpNonEntryAllocas)
1054 errs() <<
"Error of kind: " << Kind
1055 <<
" when emitting offload entries and metadata during "
1056 "OMPIRBuilder finalization \n";
1064 if (
Config.isTargetDevice())
1065 applyDeclareTargetGlobalReplacements();
1067 if (
Config.EmitLLVMUsedMetaInfo.value_or(
false)) {
1068 std::vector<WeakTrackingVH> LLVMCompilerUsed = {
1069 M.getGlobalVariable(
"__openmp_nvptx_data_transfer_temporary_storage")};
1070 emitUsed(
"llvm.compiler.used", LLVMCompilerUsed);
1080 assert(Original && Replacement &&
1081 "Null values provided to registerDeclareTargetGlobalReplacement");
1085void OpenMPIRBuilder::applyDeclareTargetGlobalReplacements() {
1091 "A null value was inserted into DeclareTargetGlobalReplacements");
1095 if (!OldGV || !NewGV)
1129 for (
unsigned I = 0, E =
PHI->getNumIncomingValues();
I < E; ++
I) {
1130 if (
PHI->getIncomingValue(
I) != OldGV)
1135 Builder.SetCurrentDebugLocation(
PHI->getDebugLoc());
1137 PHI->setIncomingValue(
I, EdgeLoad);
1143 Builder.SetCurrentDebugLocation(Insn->getDebugLoc());
1159 "Non-default address space declare target global");
1161 unsigned DestAS = ASC->getType()->getPointerAddressSpace();
1162 if (DestAS == 0 && NewGVAS != OldGVAS) {
1163 ASC->replaceAllUsesWith(
Load);
1164 ASC->eraseFromParent();
1169 Insn->replaceUsesOfWith(OldGV,
Load);
1185 ConstantInt::get(I32Ty,
Value), Name);
1198 for (
unsigned I = 0, E =
List.size();
I != E; ++
I)
1202 if (UsedArray.
empty())
1209 GV->setSection(
"llvm.metadata");
1215 auto *Int8Ty =
Builder.getInt8Ty();
1218 ConstantInt::get(Int8Ty, Mode),
Twine(KernelName,
"_exec_mode"));
1226 unsigned Reserve2Flags) {
1228 LocFlags |= OMP_IDENT_FLAG_KMPC;
1235 ConstantInt::get(Int32,
uint32_t(LocFlags)),
1236 ConstantInt::get(Int32, Reserve2Flags),
1237 ConstantInt::get(Int32, SrcLocStrSize), SrcLocStr};
1239 size_t SrcLocStrArgIdx = 4;
1240 if (OpenMPIRBuilder::Ident->getElementType(SrcLocStrArgIdx)
1244 SrcLocStr, OpenMPIRBuilder::Ident->getElementType(SrcLocStrArgIdx));
1251 if (
GV.getValueType() == OpenMPIRBuilder::Ident &&
GV.hasInitializer())
1252 if (
GV.getInitializer() == Initializer)
1257 M, OpenMPIRBuilder::Ident,
1260 M.getDataLayout().getDefaultGlobalsAddressSpace());
1272 SrcLocStrSize = LocStr.
size();
1281 if (
GV.isConstant() &&
GV.hasInitializer() &&
1282 GV.getInitializer() == Initializer)
1285 SrcLocStr =
Builder.CreateGlobalString(
1286 LocStr,
"",
M.getDataLayout().getDefaultGlobalsAddressSpace(),
1294 unsigned Line,
unsigned Column,
1300 Buffer.
append(FunctionName);
1302 Buffer.
append(std::to_string(Line));
1304 Buffer.
append(std::to_string(Column));
1312 StringRef UnknownLoc =
";unknown;unknown;0;0;;";
1323 !DIL->getFilename().empty() ? DIL->getFilename() :
M.getName();
1328 DIL->getColumn(), SrcLocStrSize);
1334 Loc.IP.getBlock()->getParent());
1340 "omp_global_thread_num");
1348 "expected one result pointer type per in_reduction item");
1351 if (OrigPtrs.
empty())
1352 return Builder.saveIP();
1371 for (
unsigned Idx = 0; Idx < OrigPtrs.
size(); ++Idx) {
1374 Value *OrigPtr = OrigPtrs[Idx];
1376 OrigPtrTy && OrigPtrTy->getAddressSpace() != 0)
1377 OrigPtr = Builder.CreateAddrSpaceCast(OrigPtr, PtrTy);
1379 Value *
Priv = Builder.CreateCall(GetThData, {Gtid, NullDesc, OrigPtr},
1385 ResPtrTy && ResPtrTy->getAddressSpace() != 0)
1386 Priv = Builder.CreateAddrSpaceCast(
Priv, ResultPtrTys[Idx]);
1388 MapPrivateCB(Idx,
Priv);
1395 bool ForceSimpleCall,
bool CheckCancelFlag) {
1405 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_FOR;
1408 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SECTIONS;
1411 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL_SINGLE;
1414 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_EXPL;
1417 BarrierLocFlags = OMP_IDENT_FLAG_BARRIER_IMPL;
1430 bool UseCancelBarrier =
1435 ? OMPRTL___kmpc_cancel_barrier
1436 : OMPRTL___kmpc_barrier),
1439 if (UseCancelBarrier && CheckCancelFlag)
1449 omp::Directive CanceledDirective) {
1454 auto *UI =
Builder.CreateUnreachable();
1462 Builder.SetInsertPoint(ElseTI);
1463 auto ElseIP =
Builder.saveIP();
1471 Builder.SetInsertPoint(ThenTI);
1473 Value *CancelKind =
nullptr;
1474 switch (CanceledDirective) {
1475#define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) \
1476 case DirectiveEnum: \
1477 CancelKind = Builder.getInt32(Value); \
1479#include "llvm/Frontend/OpenMP/OMPKinds.def"
1496 Builder.SetInsertPoint(UI->getParent());
1497 UI->eraseFromParent();
1504 omp::Directive CanceledDirective) {
1509 auto *UI =
Builder.CreateUnreachable();
1512 Value *CancelKind =
nullptr;
1513 switch (CanceledDirective) {
1514#define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) \
1515 case DirectiveEnum: \
1516 CancelKind = Builder.getInt32(Value); \
1518#include "llvm/Frontend/OpenMP/OMPKinds.def"
1535 Builder.SetInsertPoint(UI->getParent());
1536 UI->eraseFromParent();
1549 auto *KernelArgsPtr =
1550 Builder.CreateAlloca(OpenMPIRBuilder::KernelArgs,
nullptr,
"kernel_args");
1555 Builder.CreateStructGEP(OpenMPIRBuilder::KernelArgs, KernelArgsPtr,
I);
1558 M.getDataLayout().getPrefTypeAlign(KernelArgs[
I]->getType()));
1562 NumThreads, HostPtr, KernelArgsPtr};
1589 assert(OutlinedFnID &&
"Invalid outlined function ID!");
1593 Value *Return =
nullptr;
1613 Builder, AllocaIP, Return, RTLoc, DeviceID, Args.NumTeams.front(),
1614 Args.NumThreads.front(), OutlinedFnID, ArgsVector));
1621 Builder.CreateCondBr(
Failed, OffloadFailedBlock, OffloadContBlock);
1623 auto CurFn =
Builder.GetInsertBlock()->getParent();
1630 emitBlock(OffloadContBlock, CurFn,
true);
1635 Value *CancelFlag, omp::Directive CanceledDirective) {
1637 "Unexpected cancellation!");
1657 Builder.CreateCondBr(Cmp, NonCancellationBlock, CancellationBlock,
1666 Builder.SetInsertPoint(CancellationBlock);
1667 Builder.CreateBr(*FiniBBOrErr);
1670 Builder.SetInsertPoint(NonCancellationBlock, NonCancellationBlock->
begin());
1682 size_t NumArgs = OutlinedFn.
arg_size();
1683 assert((NumArgs == 2 || NumArgs == 3) &&
1684 "expected a 2-3 argument parallel outlined function");
1685 bool UseArgStruct = NumArgs == 3;
1690 {Builder.getInt16Ty(), Builder.getInt32Ty()},
1694 OutlinedFn.
getName() +
".wrapper", OMPIRBuilder->
M);
1696 WrapperFn->addParamAttr(0, Attribute::NoUndef);
1697 WrapperFn->addParamAttr(0, Attribute::ZExt);
1698 WrapperFn->addParamAttr(1, Attribute::NoUndef);
1702 Builder.SetInsertPoint(EntryBB);
1705 Value *AddrAlloca = Builder.CreateAlloca(Builder.getInt32Ty(),
1707 AddrAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1708 AddrAlloca, Builder.getPtrTy(0),
1709 AddrAlloca->
getName() +
".ascast");
1711 Value *ZeroAlloca = Builder.CreateAlloca(Builder.getInt32Ty(),
1713 ZeroAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1714 ZeroAlloca, Builder.getPtrTy(0),
1715 ZeroAlloca->
getName() +
".ascast");
1717 Value *ArgsAlloca =
nullptr;
1719 ArgsAlloca = Builder.CreateAlloca(Builder.getPtrTy(),
1720 nullptr,
"global_args");
1721 ArgsAlloca = Builder.CreatePointerBitCastOrAddrSpaceCast(
1722 ArgsAlloca, Builder.getPtrTy(0),
1723 ArgsAlloca->
getName() +
".ascast");
1727 Builder.CreateStore(WrapperFn->getArg(1), AddrAlloca);
1728 Builder.CreateStore(Builder.getInt32(0), ZeroAlloca);
1732 llvm::omp::RuntimeFunction::OMPRTL___kmpc_get_shared_variables),
1740 Value *StructArg = Builder.CreateLoad(Builder.getPtrTy(), ArgsAlloca);
1741 StructArg = Builder.CreateInBoundsGEP(Builder.getPtrTy(), StructArg,
1742 {Builder.getInt64(0)});
1743 StructArg = Builder.CreateLoad(Builder.getPtrTy(), StructArg,
"structArg");
1744 Args.push_back(StructArg);
1748 Builder.CreateCall(&OutlinedFn, Args);
1749 Builder.CreateRetVoid();
1764 "Expected at least tid and bounded tid as arguments");
1765 unsigned NumCapturedVars = OutlinedFn.
arg_size() - 2;
1773 OutlinedFn.
addFnAttr(Attribute::NoUnwind);
1776 assert(CI &&
"Expected call instruction to outlined function");
1777 CI->
getParent()->setName(
"omp_parallel");
1779 Builder.SetInsertPoint(CI);
1780 Type *PtrTy = OMPIRBuilder->VoidPtr;
1783 OpenMPIRBuilder ::InsertPointTy CurrentIP = Builder.saveIP();
1787 Value *Args = ArgsAlloca;
1791 Args = Builder.CreatePointerCast(ArgsAlloca, PtrTy);
1792 Builder.restoreIP(CurrentIP);
1795 for (
unsigned Idx = 0; Idx < NumCapturedVars; Idx++) {
1797 Value *StoreAddress = Builder.CreateConstInBoundsGEP2_64(
1799 Builder.CreateStore(V, StoreAddress);
1803 IfCondition ? Builder.CreateSExtOrTrunc(IfCondition, OMPIRBuilder->Int32)
1804 : Builder.getInt32(1);
1805 Value *NumThreadsArg =
1806 NumThreads ? Builder.CreateZExtOrTrunc(NumThreads, OMPIRBuilder->Int32)
1807 : Builder.getInt32(-1);
1817 Value *Parallel60CallArgs[] = {
1822 Builder.getInt32(-1),
1826 Builder.getInt64(NumCapturedVars),
1827 Builder.getInt32(0)};
1835 << *Builder.GetInsertBlock()->getParent() <<
"\n");
1838 Builder.SetInsertPoint(PrivTID);
1840 Builder.CreateStore(Builder.CreateLoad(OMPIRBuilder->Int32, OutlinedAI),
1847 I->eraseFromParent();
1870 if (!
F->hasMetadata(LLVMContext::MD_callback)) {
1878 F->addMetadata(LLVMContext::MD_callback,
1887 OutlinedFn.
addFnAttr(Attribute::NoUnwind);
1890 "Expected at least tid and bounded tid as arguments");
1891 unsigned NumCapturedVars = OutlinedFn.
arg_size() - 2;
1894 CI->
getParent()->setName(
"omp_parallel");
1895 Builder.SetInsertPoint(CI);
1898 Value *ForkCallArgs[] = {Ident, Builder.getInt32(NumCapturedVars),
1902 RealArgs.
append(std::begin(ForkCallArgs), std::end(ForkCallArgs));
1904 Value *
Cond = Builder.CreateSExtOrTrunc(IfCondition, OMPIRBuilder->Int32);
1911 auto PtrTy = OMPIRBuilder->VoidPtr;
1912 if (IfCondition && NumCapturedVars == 0) {
1920 << *Builder.GetInsertBlock()->getParent() <<
"\n");
1923 Builder.SetInsertPoint(PrivTID);
1925 Builder.CreateStore(Builder.CreateLoad(OMPIRBuilder->Int32, OutlinedAI),
1932 I->eraseFromParent();
1940 Value *NumThreads, omp::ProcBindKind ProcBind,
bool IsCancellable) {
1949 const bool NeedThreadID = NumThreads ||
Config.isTargetDevice() ||
1950 (ProcBind != OMP_PROC_BIND_default);
1957 bool ArgsInZeroAddressSpace =
Config.isTargetDevice();
1961 if (NumThreads && !
Config.isTargetDevice()) {
1964 Builder.CreateIntCast(NumThreads, Int32,
false)};
1969 if (ProcBind != OMP_PROC_BIND_default) {
1973 ConstantInt::get(Int32,
unsigned(ProcBind),
true)};
1995 Builder.CreateAlloca(Int32,
nullptr,
"zero.addr");
1998 if (ArgsInZeroAddressSpace &&
M.getDataLayout().getAllocaAddrSpace() != 0) {
2001 TIDAddrAlloca, PointerType ::get(
M.getContext(), 0),
"tid.addr.ascast");
2005 PointerType ::get(
M.getContext(), 0),
2006 "zero.addr.ascast");
2030 if (IP.getBlock()->end() == IP.getPoint()) {
2036 assert(IP.getBlock()->getTerminator()->getNumSuccessors() == 1 &&
2037 IP.getBlock()->getTerminator()->getSuccessor(0) == PRegExitBB &&
2038 "Unexpected insertion point for finalization call!");
2050 Builder.CreateAlloca(Int32,
nullptr,
"tid.addr.local");
2056 Builder.CreateLoad(Int32, ZeroAddr,
"zero.addr.use");
2074 LLVM_DEBUG(
dbgs() <<
"Before body codegen: " << *OuterFn <<
"\n");
2077 assert(BodyGenCB &&
"Expected body generation callback!");
2079 if (
Error Err = BodyGenCB(InnerAllocaIP, CodeGenIP, PRegExitBB))
2082 LLVM_DEBUG(
dbgs() <<
"After body codegen: " << *OuterFn <<
"\n");
2086 bool UsesDeviceSharedMemory =
2088 std::unique_ptr<OutlineInfo> OI =
2089 UsesDeviceSharedMemory
2090 ? std::make_unique<DeviceSharedMemOutlineInfo>(*
this)
2091 : std::make_unique<OutlineInfo>();
2093 if (
Config.isTargetDevice()) {
2095 OI->PostOutlineCB = [=, ToBeDeletedVec =
2096 std::move(ToBeDeleted)](
Function &OutlinedFn) {
2098 IfCondition, NumThreads, PrivTID, PrivTIDAddr,
2099 ThreadID, ToBeDeletedVec);
2103 OI->PostOutlineCB = [=, ToBeDeletedVec =
2104 std::move(ToBeDeleted)](
Function &OutlinedFn) {
2106 PrivTID, PrivTIDAddr, ToBeDeletedVec);
2110 OI->FixUpNonEntryAllocas =
true;
2111 OI->OuterAllocBB = OuterAllocaBlock;
2112 OI->EntryBB = PRegEntryBB;
2113 OI->ExitBB = PRegExitBB;
2114 OI->OuterDeallocBBs.reserve(OuterDeallocBlocks.
size());
2115 copy(OuterDeallocBlocks, OI->OuterDeallocBBs.
end());
2119 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
2131 ".omp_par", ArgsInZeroAddressSpace);
2136 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
2138 Extractor.findInputsOutputs(Inputs, Outputs, SinkingCands,
2143 return GV->getValueType() == OpenMPIRBuilder::Ident;
2148 LLVM_DEBUG(
dbgs() <<
"Before privatization: " << *OuterFn <<
"\n");
2154 if (&V == TIDAddr || &V == ZeroAddr) {
2155 OI->ExcludeArgsFromAggregate.push_back(&V);
2160 for (
Use &U : V.uses())
2162 if (ParallelRegionBlockSet.
count(UserI->getParent()))
2172 if (!V.getType()->isPointerTy()) {
2176 Builder.restoreIP(OuterAllocIP);
2178 if (UsesDeviceSharedMemory) {
2181 V.getName() +
".reloaded");
2182 for (
BasicBlock *DeallocBlock : OuterDeallocBlocks)
2184 InsertPointTy(DeallocBlock, DeallocBlock->getFirstInsertionPt()),
2187 Ptr =
Builder.CreateAlloca(V.getType(),
nullptr,
2188 V.getName() +
".reloaded");
2193 Builder.SetInsertPoint(InsertBB,
2198 Builder.restoreIP(InnerAllocaIP);
2199 Inner =
Builder.CreateLoad(V.getType(), Ptr);
2202 Value *ReplacementValue =
nullptr;
2205 ReplacementValue = PrivTID;
2208 PrivCB(InnerAllocaIP,
Builder.saveIP(), V, *Inner, ReplacementValue);
2216 assert(ReplacementValue &&
2217 "Expected copy/create callback to set replacement value!");
2218 if (ReplacementValue == &V)
2223 UPtr->set(ReplacementValue);
2248 for (
Value *Output : Outputs)
2252 "OpenMP outlining should not produce live-out values!");
2254 LLVM_DEBUG(
dbgs() <<
"After privatization: " << *OuterFn <<
"\n");
2256 for (
auto *BB : Blocks)
2257 dbgs() <<
" PBR: " << BB->getName() <<
"\n";
2265 assert(FiniInfo.DK == OMPD_parallel &&
2266 "Unexpected finalization stack state!");
2277 Builder.CreateBr(*FiniBBOrErr);
2281 Term->eraseFromParent();
2287 InsertPointTy AfterIP(UI->getParent(), UI->getParent()->end());
2288 UI->eraseFromParent();
2320 Value *Severity = ConstantInt::get(Int32, IsFatal ? 2 : 1);
2322 Value *Args[] = {Ident, Severity, MessageArg};
2351 static_cast<unsigned int>(RTLDependInfoFields::BaseAddr));
2353 Builder.CreateStore(DepValPtr, Addr);
2356 DependInfo, Entry,
static_cast<unsigned int>(RTLDependInfoFields::Len));
2358 ConstantInt::get(SizeTy,
2363 DependInfo, Entry,
static_cast<unsigned int>(RTLDependInfoFields::Flags));
2365 static_cast<unsigned int>(Dep.
DepKind)),
2378 if (Dependencies.
empty())
2398 Type *DependInfo = OMPBuilder.DependInfo;
2400 Value *DepArray =
nullptr;
2402 Builder.SetInsertPoint(
2406 DepArray = Builder.CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
2408 Builder.restoreIP(OldIP);
2410 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies)) {
2412 Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
2436 Value *DepArray =
nullptr;
2437 Type *DepArrayTy =
nullptr;
2438 Value *NumDeps =
nullptr;
2441 NumDeps = Dependencies.
NumDeps;
2442 }
else if (!Dependencies.
Deps.empty()) {
2445 Builder.GetInsertBlock()->getParent()->getEntryBlock();
2449 DepArray =
Builder.CreateAlloca(DepArrayTy,
nullptr,
".dep.arr.addr");
2450 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
2453 for (
const auto &[DepIdx, Dep] :
enumerate(Dependencies.
Deps)) {
2455 Builder.CreateConstInBoundsGEP2_64(DepArrayTy, DepArray, 0, DepIdx);
2469 ConstantInt::get(
Builder.getInt32Ty(), 0),
2471 ConstantInt::get(
Builder.getInt32Ty(),
false)};
2474 omp::RuntimeFunction::OMPRTL___kmpc_omp_taskwait_deps_51),
2484 unsigned ProgramAddressSpace = M.getDataLayout().getProgramAddressSpace();
2496 auto *VoidPtrTy =
PointerType::get(Builder.getContext(), ProgramAddressSpace);
2499 Builder.getVoidTy(), {VoidPtrTy, VoidPtrTy, Builder.getInt32Ty()},
2503 "omp_taskloop_dup", M);
2506 Value *LastprivateFlagArg = DupFunction->
getArg(2);
2507 DestTaskArg->
setName(
"dest_task");
2508 SrcTaskArg->
setName(
"src_task");
2509 LastprivateFlagArg->
setName(
"lastprivate_flag");
2512 Builder.SetInsertPoint(
2515 auto GetTaskContextPtrFromArg = [&](
Value *Arg) ->
Value * {
2516 Type *TaskWithPrivatesTy =
2518 Value *TaskPrivates = Builder.CreateGEP(
2519 TaskWithPrivatesTy, Arg, {Builder.getInt32(0), Builder.getInt32(1)});
2520 Value *ContextPtr = Builder.CreateGEP(
2521 PrivatesTy, TaskPrivates,
2522 {Builder.getInt32(0), Builder.getInt32(PrivatesIndex)});
2526 Value *DestTaskContextPtr = GetTaskContextPtrFromArg(DestTaskArg);
2527 Value *SrcTaskContextPtr = GetTaskContextPtrFromArg(SrcTaskArg);
2529 DestTaskContextPtr->
setName(
"destPtr");
2530 SrcTaskContextPtr->
setName(
"srcPtr");
2535 Expected<IRBuilderBase::InsertPoint> AfterIPOrError =
2536 DupCB(AllocaIP, CodeGenIP, DestTaskContextPtr, SrcTaskContextPtr);
2537 if (!AfterIPOrError)
2539 Builder.restoreIP(*AfterIPOrError);
2549 llvm::function_ref<llvm::Expected<llvm::CanonicalLoopInfo *>()> LoopInfo,
2551 Value *GrainSize,
bool NoGroup,
int Sched,
Value *Final,
bool Mergeable,
2553 Value *TaskContextStructPtrVal) {
2558 uint32_t SrcLocStrSize;
2574 if (
Error Err = BodyGenCB(TaskloopAllocaIP, TaskloopBodyIP, TaskloopExitBB))
2577 llvm::Expected<llvm::CanonicalLoopInfo *> result = LoopInfo();
2582 llvm::CanonicalLoopInfo *CLI = result.
get();
2583 auto OI = std::make_unique<OutlineInfo>();
2584 OI->EntryBB = TaskloopAllocaBB;
2585 OI->OuterAllocBB = AllocaIP.getBlock();
2586 OI->ExitBB = TaskloopExitBB;
2587 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2588 copy(DeallocBlocks, OI->OuterDeallocBBs.end());
2591 SmallVector<Instruction *> ToBeDeleted;
2594 Builder, AllocaIP, ToBeDeleted, TaskloopAllocaIP,
"global.tid",
false));
2596 TaskloopAllocaIP,
"lb",
false,
true);
2598 TaskloopAllocaIP,
"ub",
false,
true);
2600 TaskloopAllocaIP,
"step",
false,
true);
2603 OI->Inputs.insert(FakeLB);
2604 OI->Inputs.insert(FakeUB);
2605 OI->Inputs.insert(FakeStep);
2606 if (TaskContextStructPtrVal)
2607 OI->Inputs.insert(TaskContextStructPtrVal);
2608 assert(((TaskContextStructPtrVal && DupCB) ||
2609 (!TaskContextStructPtrVal && !DupCB)) &&
2610 "Task context struct ptr and duplication callback must be both set "
2616 unsigned ProgramAddressSpace =
M.getDataLayout().getProgramAddressSpace();
2620 {FakeLB->getType(), FakeUB->getType(), FakeStep->getType(), PointerTy});
2621 Expected<Value *> TaskDupFnOrErr = createTaskDuplicationFunction(
2624 if (!TaskDupFnOrErr) {
2627 Value *TaskDupFn = *TaskDupFnOrErr;
2629 OI->PostOutlineCB = [
this, Ident, LBVal, UBVal, StepVal, Untied,
2630 TaskloopAllocaBB, CLI, TaskDupFn, ToBeDeleted, IfCond,
2631 GrainSize, NoGroup, Sched, FakeLB, FakeUB, FakeStep,
2632 FakeSharedsTy, Final, Mergeable, Priority,
2633 NumOfCollapseLoops](
Function &OutlinedFn)
mutable {
2635 assert(OutlinedFn.hasOneUse() &&
2636 "there must be a single user for the outlined function");
2643 Value *CastedLBVal =
2644 Builder.CreateIntCast(LBVal,
Builder.getInt64Ty(),
true,
"lb64");
2645 Value *CastedUBVal =
2646 Builder.CreateIntCast(UBVal,
Builder.getInt64Ty(),
true,
"ub64");
2647 Value *CastedStepVal =
2648 Builder.CreateIntCast(StepVal,
Builder.getInt64Ty(),
true,
"step64");
2650 Builder.SetInsertPoint(StaleCI);
2663 Builder.CreateCall(TaskgroupFn, {Ident, ThreadID});
2684 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
2686 AllocaInst *ArgStructAlloca =
2688 assert(ArgStructAlloca &&
2689 "Unable to find the alloca instruction corresponding to arguments "
2690 "for extracted function");
2691 std::optional<TypeSize> ArgAllocSize =
2694 "Unable to determine size of arguments for extracted function");
2695 Value *SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
2700 CallInst *TaskData =
Builder.CreateCall(
2701 TaskAllocFn, {Ident, ThreadID,
Flags,
2702 TaskSize, SharedsSize,
2707 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
2713 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(0)});
2716 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(1)});
2719 FakeSharedsTy, TaskShareds, {
Builder.getInt32(0),
Builder.getInt32(2)});
2725 IfCond ?
Builder.CreateIntCast(IfCond,
Builder.getInt32Ty(),
true)
2731 Value *GrainSizeVal =
2732 GrainSize ?
Builder.CreateIntCast(GrainSize,
Builder.getInt64Ty(),
true)
2734 Value *TaskDup = TaskDupFn;
2736 Value *
Args[] = {Ident, ThreadID, TaskData, IfCondVal, Lb, Ub,
2737 Loadstep, NoGroupVal, SchedVal, GrainSizeVal, TaskDup};
2742 Builder.CreateCall(TaskloopFn, Args);
2749 Builder.CreateCall(EndTaskgroupFn, {Ident, ThreadID});
2754 Builder.SetInsertPoint(TaskloopAllocaBB, TaskloopAllocaBB->begin());
2756 LoadInst *SharedsOutlined =
2757 Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
2758 OutlinedFn.getArg(1)->replaceUsesWithIf(
2760 [SharedsOutlined](Use &U) {
return U.getUser() != SharedsOutlined; });
2763 Type *IVTy =
IV->getType();
2769 Value *TaskLB =
nullptr;
2770 Value *TaskUB =
nullptr;
2771 Value *TaskStep =
nullptr;
2772 Value *LoadTaskLB =
nullptr;
2773 Value *LoadTaskUB =
nullptr;
2774 Value *LoadTaskStep =
nullptr;
2775 for (Instruction &
I : *TaskloopAllocaBB) {
2776 if (
I.getOpcode() == Instruction::GetElementPtr) {
2779 switch (CI->getZExtValue()) {
2791 }
else if (
I.getOpcode() == Instruction::Load) {
2793 if (
Load.getPointerOperand() == TaskLB) {
2794 assert(TaskLB !=
nullptr &&
"Expected value for TaskLB");
2796 }
else if (
Load.getPointerOperand() == TaskUB) {
2797 assert(TaskUB !=
nullptr &&
"Expected value for TaskUB");
2799 }
else if (
Load.getPointerOperand() == TaskStep) {
2800 assert(TaskStep !=
nullptr &&
"Expected value for TaskStep");
2806 Builder.SetInsertPoint(CLI->getPreheader()->getTerminator());
2808 assert(LoadTaskLB !=
nullptr &&
"Expected value for LoadTaskLB");
2809 assert(LoadTaskUB !=
nullptr &&
"Expected value for LoadTaskUB");
2810 assert(LoadTaskStep !=
nullptr &&
"Expected value for LoadTaskStep");
2812 Builder.CreateSub(LoadTaskUB, LoadTaskLB), LoadTaskStep);
2813 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One,
"trip_cnt");
2814 Value *CastedTripCount =
Builder.CreateIntCast(TripCount, IVTy,
true);
2815 Value *CastedTaskLB =
Builder.CreateIntCast(LoadTaskLB, IVTy,
true);
2817 CLI->setTripCount(CastedTripCount);
2819 Builder.SetInsertPoint(CLI->getBody(),
2820 CLI->getBody()->getFirstInsertionPt());
2822 if (NumOfCollapseLoops > 1) {
2828 Builder.CreateSub(CastedTaskLB, ConstantInt::get(IVTy, 1)));
2831 for (
auto IVUse = CLI->getIndVar()->uses().begin();
2832 IVUse != CLI->getIndVar()->uses().end(); IVUse++) {
2833 User *IVUser = IVUse->getUser();
2835 if (
Op->getOpcode() == Instruction::URem ||
2836 Op->getOpcode() == Instruction::UDiv) {
2841 for (User *User : UsersToReplace) {
2842 User->replaceUsesOfWith(CLI->getIndVar(), IVPlusTaskLB);
2859 assert(CLI->getIndVar()->getNumUses() == 3 &&
2860 "Canonical loop should have exactly three uses of the ind var");
2861 for (User *IVUser : CLI->getIndVar()->users()) {
2863 if (
Mul->getOpcode() == Instruction::Mul) {
2864 for (User *MulUser :
Mul->users()) {
2866 if (
Add->getOpcode() == Instruction::Add) {
2867 Add->setOperand(1, CastedTaskLB);
2876 FakeLB->replaceAllUsesWith(CastedLBVal);
2877 FakeUB->replaceAllUsesWith(CastedUBVal);
2878 FakeStep->replaceAllUsesWith(CastedStepVal);
2880 I->eraseFromParent();
2885 Builder.SetInsertPoint(TaskloopExitBB, TaskloopExitBB->
begin());
2891 M.getContext(),
M.getDataLayout().getPointerSizeInBits());
2901 bool Mergeable,
Value *EventHandle,
Value *Priority) {
2933 if (
Error Err = BodyGenCB(TaskAllocaIP, TaskBodyIP, TaskExitBB))
2936 auto OI = std::make_unique<OutlineInfo>();
2937 OI->EntryBB = TaskAllocaBB;
2938 OI->OuterAllocBB = AllocaIP.
getBlock();
2939 OI->ExitBB = TaskExitBB;
2940 OI->OuterDeallocBBs.reserve(DeallocBlocks.
size());
2941 copy(DeallocBlocks, OI->OuterDeallocBBs.
end());
2946 Builder, AllocaIP, ToBeDeleted, TaskAllocaIP,
"global.tid",
false));
2948 OI->PostOutlineCB = [
this, Ident, Tied, Final, IfCondition, Dependencies,
2949 Affinities, Mergeable, Priority, EventHandle,
2951 ToBeDeleted](
Function &OutlinedFn)
mutable {
2953 assert(OutlinedFn.hasOneUse() &&
2954 "there must be a single user for the outlined function");
2959 bool HasShareds = StaleCI->
arg_size() > 1;
2960 Builder.SetInsertPoint(StaleCI);
2985 bool UseMergedIf0Path = ConstIfCondition && ConstIfCondition->isZero();
2989 Flags =
Builder.CreateOr(FinalFlag, Flags);
2992 if (Mergeable || UseMergedIf0Path)
3004 divideCeil(
M.getDataLayout().getTypeSizeInBits(Task), 8));
3013 assert(ArgStructAlloca &&
3014 "Unable to find the alloca instruction corresponding to arguments "
3015 "for extracted function");
3016 std::optional<TypeSize> ArgAllocSize =
3019 "Unable to determine size of arguments for extracted function");
3020 SharedsSize =
Builder.getInt64(ArgAllocSize->getFixedValue());
3026 TaskAllocFn, {Ident, ThreadID, Flags,
3027 TaskSize, SharedsSize,
3030 if (Affinities.
Count && Affinities.
Info) {
3032 OMPRTL___kmpc_omp_reg_task_with_affinity);
3043 OMPRTL___kmpc_task_allow_completion_event);
3047 Builder.CreatePointerBitCastOrAddrSpaceCast(EventHandle,
3049 EventVal =
Builder.CreatePtrToInt(EventVal,
Builder.getInt64Ty());
3050 Builder.CreateStore(EventVal, EventHandleAddr);
3056 Value *TaskShareds =
Builder.CreateLoad(VoidPtr, TaskData);
3071 Constant *Zero = ConstantInt::get(Int32Ty, 0);
3075 Builder.CreateInBoundsGEP(TaskPtr, TaskData, {Zero, Zero});
3078 VoidPtr, VoidPtr,
Builder.getInt32Ty(), VoidPtr, VoidPtr);
3080 TaskStructType, TaskGEP, {Zero, ConstantInt::get(Int32Ty, 4)});
3083 Value *CmplrData =
Builder.CreateInBoundsGEP(CmplrStructType,
3084 PriorityData, {Zero, Zero});
3085 Builder.CreateStore(Priority, CmplrData);
3088 Value *DepArray =
nullptr;
3089 Value *NumDeps =
nullptr;
3092 NumDeps = Dependencies.
NumDeps;
3093 }
else if (!Dependencies.
Deps.empty()) {
3095 NumDeps =
Builder.getInt32(Dependencies.
Deps.size());
3115 if (IfCondition && !UseMergedIf0Path) {
3120 Builder.GetInsertPoint()->getParent()->getTerminator();
3121 Instruction *ThenTI = IfTerminator, *ElseTI =
nullptr;
3122 Builder.SetInsertPoint(IfTerminator);
3125 Builder.SetInsertPoint(ElseTI);
3132 {Ident, ThreadID, NumDeps, DepArray,
3133 ConstantInt::get(
Builder.getInt32Ty(), 0),
3148 Builder.SetInsertPoint(ThenTI);
3156 {Ident, ThreadID, TaskData, NumDeps, DepArray,
3157 ConstantInt::get(
Builder.getInt32Ty(), 0),
3168 Builder.SetInsertPoint(TaskAllocaBB, TaskAllocaBB->
begin());
3170 LoadInst *Shareds =
Builder.CreateLoad(VoidPtr, OutlinedFn.getArg(1));
3171 OutlinedFn.getArg(1)->replaceUsesWithIf(
3172 Shareds, [Shareds](
Use &U) {
return U.getUser() != Shareds; });
3178 Builder.ClearInsertionPoint();
3180 I->eraseFromParent();
3184 Builder.SetInsertPoint(TaskExitBB, TaskExitBB->
begin());
3206 if (
Error Err = BodyGenCB(AllocaIP,
Builder.saveIP(), DeallocBlocks))
3209 Builder.SetInsertPoint(TaskgroupExitBB);
3252 unsigned CaseNumber = 0;
3253 for (
auto SectionCB : SectionCBs) {
3255 M.getContext(),
"omp_section_loop.body.case", CurFn,
Continue);
3257 Builder.SetInsertPoint(CaseBB);
3272 Value *LB = ConstantInt::get(I32Ty, 0);
3273 Value *UB = ConstantInt::get(I32Ty, SectionCBs.
size());
3274 Value *ST = ConstantInt::get(I32Ty, 1);
3276 Loc, LoopBodyGenCB, LB, UB, ST,
true,
false, AllocaIP,
"section_loop");
3281 applyStaticWorkshareLoop(
Loc.DL, *
LoopInfo, AllocaIP,
3282 WorksharingLoopType::ForStaticLoop, !IsNowait);
3288 assert(LoopFini &&
"Bad structure of static workshare loop finalization");
3292 assert(FiniInfo.DK == OMPD_sections &&
3293 "Unexpected finalization stack state!");
3294 if (
Error Err = FiniInfo.mergeFiniBB(
Builder, LoopFini))
3308 if (IP.getBlock()->end() != IP.getPoint())
3319 auto *CaseBB =
Loc.IP.getBlock();
3320 auto *CondBB = CaseBB->getSinglePredecessor()->getSinglePredecessor();
3321 auto *ExitBB = CondBB->getTerminator()->getSuccessor(1);
3327 Directive OMPD = Directive::OMPD_sections;
3330 return EmitOMPInlinedRegion(OMPD,
nullptr,
nullptr, BodyGenCB, FiniCBWrapper,
3341Value *OpenMPIRBuilder::getGPUThreadID() {
3344 OMPRTL___kmpc_get_hardware_thread_id_in_block),
3348Value *OpenMPIRBuilder::getGPUWarpSize() {
3353Value *OpenMPIRBuilder::getNVPTXWarpID() {
3354 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3355 return Builder.CreateAShr(getGPUThreadID(), LaneIDBits,
"nvptx_warp_id");
3358Value *OpenMPIRBuilder::getNVPTXLaneID() {
3359 unsigned LaneIDBits =
Log2_32(
Config.getGridValue().GV_Warp_Size);
3360 assert(LaneIDBits < 32 &&
"Invalid LaneIDBits size in NVPTX device.");
3361 unsigned LaneIDMask = ~0
u >> (32u - LaneIDBits);
3362 return Builder.CreateAnd(getGPUThreadID(),
Builder.getInt32(LaneIDMask),
3369 uint64_t FromSize =
M.getDataLayout().getTypeStoreSize(FromType);
3370 uint64_t ToSize =
M.getDataLayout().getTypeStoreSize(ToType);
3371 assert(FromSize > 0 &&
"From size must be greater than zero");
3372 assert(ToSize > 0 &&
"To size must be greater than zero");
3373 if (FromType == ToType)
3375 if (FromSize == ToSize)
3376 return Builder.CreateBitCast(From, ToType);
3378 return Builder.CreateIntCast(From, ToType,
true);
3384 Value *ValCastItem =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3385 CastItem,
Builder.getPtrTy(0));
3386 Builder.CreateStore(From, ValCastItem);
3387 return Builder.CreateLoad(ToType, CastItem);
3394 uint64_t Size =
M.getDataLayout().getTypeStoreSize(ElementType);
3395 assert(
Size <= 8 &&
"Unsupported bitwidth in shuffle instruction");
3399 Value *ElemCast = castValueToType(AllocaIP, Element, CastTy);
3401 Builder.CreateIntCast(getGPUWarpSize(),
Builder.getInt16Ty(),
true);
3403 Size <= 4 ? RuntimeFunction::OMPRTL___kmpc_shuffle_int32
3404 : RuntimeFunction::OMPRTL___kmpc_shuffle_int64);
3405 Value *WarpSizeCast =
3407 Value *ShuffleCall =
3412 return castValueToType(AllocaIP, ShuffleCall, ElementType);
3419 uint64_t Size =
M.getDataLayout().getTypeStoreSize(ElemType);
3431 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3432 Value *ElemPtr = DstAddr;
3433 Value *Ptr = SrcAddr;
3434 for (
unsigned IntSize = 8; IntSize >= 1; IntSize /= 2) {
3438 Ptr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3441 Builder.CreateGEP(ElemType, SrcAddr, {ConstantInt::get(IndexTy, 1)});
3442 ElemPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3446 if ((
Size / IntSize) > 1) {
3447 Value *PtrEnd =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3448 SrcAddrGEP,
Builder.getPtrTy());
3465 Builder.CreatePointerBitCastOrAddrSpaceCast(Ptr,
Builder.getPtrTy()));
3467 Builder.CreateICmpSGT(PtrDiff,
Builder.getInt64(IntSize - 1)), ThenBB,
3470 Value *Res = createRuntimeShuffleFunction(
3473 IntType, Ptr,
M.getDataLayout().getPrefTypeAlign(ElemType)),
3475 Builder.CreateAlignedStore(Res, ElemPtr,
3476 M.getDataLayout().getPrefTypeAlign(ElemType));
3478 Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3479 Value *LocalElemPtr =
3480 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3488 Value *Res = createRuntimeShuffleFunction(
3489 AllocaIP,
Builder.CreateLoad(IntType, Ptr), IntType,
Offset);
3490 Builder.CreateStore(Res, ElemPtr);
3491 Ptr =
Builder.CreateGEP(IntType, Ptr, {ConstantInt::get(IndexTy, 1)});
3493 Builder.CreateGEP(IntType, ElemPtr, {ConstantInt::get(IndexTy, 1)});
3499Error OpenMPIRBuilder::emitReductionListCopy(
3504 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3505 Value *RemoteLaneOffset = CopyOptions.RemoteLaneOffset;
3509 for (
auto En :
enumerate(ReductionInfos)) {
3511 Value *SrcElementAddr =
nullptr;
3512 AllocaInst *DestAlloca =
nullptr;
3513 Value *DestElementAddr =
nullptr;
3514 Value *DestElementPtrAddr =
nullptr;
3516 bool ShuffleInElement =
false;
3519 bool UpdateDestListPtr =
false;
3523 ReductionArrayTy, SrcBase,
3524 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3525 SrcElementAddr =
Builder.CreateLoad(
Builder.getPtrTy(), SrcElementPtrAddr);
3529 DestElementPtrAddr =
Builder.CreateInBoundsGEP(
3530 ReductionArrayTy, DestBase,
3531 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
3532 bool IsByRefElem = (!IsByRef.
empty() && IsByRef[En.index()]);
3538 Type *DestAllocaType =
3539 IsByRefElem ? RI.ByRefAllocatedType : RI.ElementType;
3540 DestAlloca =
Builder.CreateAlloca(DestAllocaType,
nullptr,
3541 ".omp.reduction.element");
3543 M.getDataLayout().getPrefTypeAlign(DestAllocaType));
3544 DestElementAddr = DestAlloca;
3547 DestElementAddr->
getName() +
".ascast");
3549 ShuffleInElement =
true;
3550 UpdateDestListPtr =
true;
3562 if (ShuffleInElement) {
3563 Type *ShuffleType = RI.ElementType;
3564 Value *ShuffleSrcAddr = SrcElementAddr;
3565 Value *ShuffleDestAddr = DestElementAddr;
3566 AllocaInst *LocalStorage =
nullptr;
3569 assert(RI.ByRefElementType &&
"Expected by-ref element type to be set");
3570 assert(RI.ByRefAllocatedType &&
3571 "Expected by-ref allocated type to be set");
3576 ShuffleType = RI.ByRefElementType;
3578 if (RI.DataPtrPtrGen) {
3581 Builder.saveIP(), ShuffleSrcAddr, ShuffleSrcAddr);
3584 return GenResult.takeError();
3593 LocalStorage =
Builder.CreateAlloca(ShuffleType);
3595 ShuffleDestAddr = LocalStorage;
3600 ShuffleDestAddr = DestElementAddr;
3604 shuffleAndStore(AllocaIP, ShuffleSrcAddr, ShuffleDestAddr, ShuffleType,
3605 RemoteLaneOffset, ReductionArrayTy, IsByRefElem);
3607 if (IsByRefElem && RI.DataPtrPtrGen) {
3609 Value *DestDescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3610 DestAlloca,
Builder.getPtrTy(),
".ascast");
3613 DestDescriptorAddr, LocalStorage, SrcElementAddr,
3614 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
3617 return GenResult.takeError();
3620 switch (RI.EvaluationKind) {
3622 Value *Elem =
Builder.CreateLoad(RI.ElementType, SrcElementAddr);
3624 Builder.CreateStore(Elem, DestElementAddr);
3628 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3629 RI.ElementType, SrcElementAddr, 0, 0,
".realp");
3631 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
3633 RI.ElementType, SrcElementAddr, 0, 1,
".imagp");
3635 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
3637 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
3638 RI.ElementType, DestElementAddr, 0, 0,
".realp");
3639 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
3640 RI.ElementType, DestElementAddr, 0, 1,
".imagp");
3641 Builder.CreateStore(SrcReal, DestRealPtr);
3642 Builder.CreateStore(SrcImg, DestImgPtr);
3647 M.getDataLayout().getTypeStoreSize(RI.ElementType));
3649 DestElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3650 SrcElementAddr,
M.getDataLayout().getPrefTypeAlign(RI.ElementType),
3662 if (UpdateDestListPtr) {
3663 Value *CastDestAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3664 DestElementAddr,
Builder.getPtrTy(),
3665 DestElementAddr->
getName() +
".ascast");
3666 Builder.CreateStore(CastDestAddr, DestElementPtrAddr);
3673Expected<Function *> OpenMPIRBuilder::emitInterWarpCopyFunction(
3676 IRBuilder<>::InsertPointGuard IPG(
Builder);
3677 LLVMContext &Ctx =
M.getContext();
3679 Builder.getVoidTy(), {Builder.getPtrTy(), Builder.getInt32Ty()},
3683 "_omp_reduction_inter_warp_copy_func", &
M);
3689 Builder.SetInsertPoint(EntryBB);
3707 StringRef TransferMediumName =
3708 "__openmp_nvptx_data_transfer_temporary_storage";
3709 GlobalVariable *TransferMedium =
M.getGlobalVariable(TransferMediumName);
3710 unsigned WarpSize =
Config.getGridValue().GV_Warp_Size;
3712 if (!TransferMedium) {
3713 TransferMedium =
new GlobalVariable(
3721 Value *GPUThreadID = getGPUThreadID();
3723 Value *LaneID = getNVPTXLaneID();
3725 Value *WarpID = getNVPTXWarpID();
3729 Builder.GetInsertBlock()->getFirstInsertionPt());
3733 AllocaInst *ReduceListAlloca =
Builder.CreateAlloca(
3734 Arg0Type,
nullptr, ReduceListArg->
getName() +
".addr");
3735 AllocaInst *NumWarpsAlloca =
3736 Builder.CreateAlloca(Arg1Type,
nullptr, NumWarpsArg->
getName() +
".addr");
3737 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3738 ReduceListAlloca, Arg0Type, ReduceListAlloca->
getName() +
".ascast");
3739 Value *NumWarpsAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3740 NumWarpsAlloca,
Builder.getPtrTy(0),
3741 NumWarpsAlloca->
getName() +
".ascast");
3742 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
3743 Builder.CreateStore(NumWarpsArg, NumWarpsAddrCast);
3752 for (
auto En :
enumerate(ReductionInfos)) {
3758 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
3759 unsigned RealTySize =
M.getDataLayout().getTypeAllocSize(
3760 IsByRefElem ? RI.ByRefElementType : RI.ElementType);
3761 for (
unsigned TySize = 4; TySize > 0 && RealTySize > 0; TySize /= 2) {
3764 unsigned NumIters = RealTySize / TySize;
3767 Value *Cnt =
nullptr;
3768 Value *CntAddr =
nullptr;
3775 Builder.CreateAlloca(
Builder.getInt32Ty(),
nullptr,
".cnt.addr");
3777 CntAddr =
Builder.CreateAddrSpaceCast(CntAddr,
Builder.getPtrTy(),
3778 CntAddr->
getName() +
".ascast");
3790 Cnt, ConstantInt::get(
Builder.getInt32Ty(), NumIters));
3791 Builder.CreateCondBr(Cmp, BodyBB, ExitBB);
3798 omp::Directive::OMPD_unknown,
3802 return BarrierIP1.takeError();
3808 Value *IsWarpMaster =
Builder.CreateIsNull(LaneID,
"warp_master");
3809 Builder.CreateCondBr(IsWarpMaster, ThenBB, ElseBB);
3813 auto *RedListArrayTy =
3816 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
3818 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3819 {ConstantInt::get(IndexTy, 0),
3820 ConstantInt::get(IndexTy, En.index())});
3824 if (IsByRefElem && RI.DataPtrPtrGen) {
3826 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
3829 return GenRes.takeError();
3840 ArrayTy, TransferMedium, {
Builder.getInt64(0), WarpID});
3845 Builder.CreateStore(Elem, MediumPtr,
3857 omp::Directive::OMPD_unknown,
3861 return BarrierIP2.takeError();
3868 Value *NumWarpsVal =
3871 Value *IsActiveThread =
3872 Builder.CreateICmpULT(GPUThreadID, NumWarpsVal,
"is_active_thread");
3873 Builder.CreateCondBr(IsActiveThread, W0ThenBB, W0ElseBB);
3880 ArrayTy, TransferMedium, {
Builder.getInt64(0), GPUThreadID});
3882 Value *TargetElemPtrPtr =
3883 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
3884 {ConstantInt::get(IndexTy, 0),
3885 ConstantInt::get(IndexTy, En.index())});
3886 Value *TargetElemPtrVal =
3888 Value *TargetElemPtr = TargetElemPtrVal;
3890 if (IsByRefElem && RI.DataPtrPtrGen) {
3892 RI.DataPtrPtrGen(
Builder.saveIP(), TargetElemPtr, TargetElemPtr);
3895 return GenRes.takeError();
3897 TargetElemPtr =
Builder.CreateLoad(
Builder.getPtrTy(), TargetElemPtr);
3905 Value *SrcMediumValue =
3906 Builder.CreateLoad(CType, SrcMediumPtrVal,
true);
3907 Builder.CreateStore(SrcMediumValue, TargetElemPtr);
3917 Cnt, ConstantInt::get(
Builder.getInt32Ty(), 1));
3918 Builder.CreateStore(Cnt, CntAddr,
false);
3920 auto *CurFn =
Builder.GetInsertBlock()->getParent();
3924 RealTySize %= TySize;
3933Expected<Function *> OpenMPIRBuilder::emitShuffleAndReduceFunction(
3936 LLVMContext &Ctx =
M.getContext();
3937 IRBuilder<>::InsertPointGuard IPG(
Builder);
3938 FunctionType *FuncTy =
3940 {Builder.getPtrTy(), Builder.getInt16Ty(),
3941 Builder.getInt16Ty(), Builder.getInt16Ty()},
3945 "_omp_reduction_shuffle_and_reduce_func", &
M);
3956 Builder.SetInsertPoint(EntryBB);
3968 Type *ReduceListArgType = ReduceListArg->
getType();
3972 ReduceListArgType,
nullptr, ReduceListArg->
getName() +
".addr");
3973 Value *LaneIdAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
3974 LaneIDArg->
getName() +
".addr");
3976 LaneIDArgType,
nullptr, RemoteLaneOffsetArg->
getName() +
".addr");
3977 Value *AlgoVerAlloca =
Builder.CreateAlloca(LaneIDArgType,
nullptr,
3978 AlgoVerArg->
getName() +
".addr");
3985 RedListArrayTy,
nullptr,
".omp.reduction.remote_reduce_list");
3987 Value *ReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3988 ReduceListAlloca, ReduceListArgType,
3989 ReduceListAlloca->
getName() +
".ascast");
3990 Value *LaneIdAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3991 LaneIdAlloca, LaneIDArgPtrType, LaneIdAlloca->
getName() +
".ascast");
3992 Value *RemoteLaneOffsetAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3993 RemoteLaneOffsetAlloca, LaneIDArgPtrType,
3994 RemoteLaneOffsetAlloca->
getName() +
".ascast");
3995 Value *AlgoVerAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3996 AlgoVerAlloca, LaneIDArgPtrType, AlgoVerAlloca->
getName() +
".ascast");
3997 Value *RemoteListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
3998 RemoteReductionListAlloca,
Builder.getPtrTy(),
3999 RemoteReductionListAlloca->
getName() +
".ascast");
4001 Builder.CreateStore(ReduceListArg, ReduceListAddrCast);
4002 Builder.CreateStore(LaneIDArg, LaneIdAddrCast);
4003 Builder.CreateStore(RemoteLaneOffsetArg, RemoteLaneOffsetAddrCast);
4004 Builder.CreateStore(AlgoVerArg, AlgoVerAddrCast);
4006 Value *ReduceList =
Builder.CreateLoad(ReduceListArgType, ReduceListAddrCast);
4007 Value *LaneId =
Builder.CreateLoad(LaneIDArgType, LaneIdAddrCast);
4008 Value *RemoteLaneOffset =
4009 Builder.CreateLoad(LaneIDArgType, RemoteLaneOffsetAddrCast);
4010 Value *AlgoVer =
Builder.CreateLoad(LaneIDArgType, AlgoVerAddrCast);
4017 Error EmitRedLsCpRes = emitReductionListCopy(
4019 ReduceList, RemoteListAddrCast, IsByRef,
4020 {RemoteLaneOffset,
nullptr,
nullptr});
4023 return EmitRedLsCpRes;
4048 Value *LaneComp =
Builder.CreateICmpULT(LaneId, RemoteLaneOffset);
4053 Value *Algo2AndLaneIdComp =
Builder.CreateAnd(Algo2, LaneIdComp);
4054 Value *RemoteOffsetComp =
4056 Value *CondAlgo2 =
Builder.CreateAnd(Algo2AndLaneIdComp, RemoteOffsetComp);
4057 Value *CA0OrCA1 =
Builder.CreateOr(CondAlgo0, CondAlgo1);
4058 Value *CondReduce =
Builder.CreateOr(CA0OrCA1, CondAlgo2);
4064 Builder.CreateCondBr(CondReduce, ThenBB, ElseBB);
4066 Value *LocalReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4067 ReduceList,
Builder.getPtrTy());
4068 Value *RemoteReduceListPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4069 RemoteListAddrCast,
Builder.getPtrTy());
4071 ->addFnAttr(Attribute::NoUnwind);
4082 Value *LaneIdGtOffset =
Builder.CreateICmpUGE(LaneId, RemoteLaneOffset);
4083 Value *CondCopy =
Builder.CreateAnd(Algo1, LaneIdGtOffset);
4088 Builder.CreateCondBr(CondCopy, CpyThenBB, CpyElseBB);
4092 EmitRedLsCpRes = emitReductionListCopy(
4094 RemoteListAddrCast, ReduceList, IsByRef);
4097 return EmitRedLsCpRes;
4112OpenMPIRBuilder::generateReductionDescriptor(
4114 Type *DescriptorType,
4120 Value *DescriptorSize =
4121 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(DescriptorType));
4123 DescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4124 SrcDescriptorAddr,
M.getDataLayout().getPrefTypeAlign(DescriptorType),
4128 Value *DataPtrField;
4130 DataPtrPtrGen(
Builder.saveIP(), DescriptorAddr, DataPtrField);
4133 return GenResult.takeError();
4136 DataPtr,
Builder.getPtrTy(),
".ascast"),
4142Expected<Value *> OpenMPIRBuilder::createReductionDescriptorCopy(
4144 Value *SrcDescriptorAddr,
Type *DescriptorPtrTy,
const Twine &Name) {
4148 AllocaInst *DescriptorAlloca =
4149 Builder.CreateAlloca(RI.ByRefAllocatedType,
nullptr, Name);
4151 M.getDataLayout().getPrefTypeAlign(RI.ByRefAllocatedType));
4152 Value *DescriptorAddr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4153 DescriptorAlloca, DescriptorPtrTy,
4154 DescriptorAlloca->
getName() +
".ascast");
4159 generateReductionDescriptor(DescriptorAddr, DataPtr, SrcDescriptorAddr,
4160 RI.ByRefAllocatedType, RI.DataPtrPtrGen);
4162 return GenResult.takeError();
4164 return DescriptorAddr;
4167Expected<Function *> OpenMPIRBuilder::emitListToGlobalCopyFunction(
4170 IRBuilder<>::InsertPointGuard IPG(
Builder);
4171 LLVMContext &Ctx =
M.getContext();
4174 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4178 "_omp_reduction_list_to_global_copy_func", &
M);
4185 Builder.SetInsertPoint(EntryBlock);
4196 BufferArg->
getName() +
".addr");
4200 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4201 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4202 BufferArgAlloca,
Builder.getPtrTy(),
4203 BufferArgAlloca->
getName() +
".ascast");
4204 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4205 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4206 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4207 ReduceListArgAlloca,
Builder.getPtrTy(),
4208 ReduceListArgAlloca->
getName() +
".ascast");
4210 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4211 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4212 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4214 Value *LocalReduceList =
4216 Value *BufferArgVal =
4220 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4221 for (
auto En :
enumerate(ReductionInfos)) {
4223 auto *RedListArrayTy =
4227 RedListArrayTy, LocalReduceList,
4228 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4234 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferArgVal, Idxs);
4236 ReductionsBufferTy, BufferVD, 0, En.index());
4238 switch (RI.EvaluationKind) {
4240 Value *TargetElement;
4242 if (IsByRef.
empty() || !IsByRef[En.index()]) {
4243 TargetElement =
Builder.CreateLoad(RI.ElementType, ElemPtr);
4245 if (RI.DataPtrPtrGen) {
4247 RI.DataPtrPtrGen(
Builder.saveIP(), ElemPtr, ElemPtr);
4250 return GenResult.takeError();
4254 TargetElement =
Builder.CreateLoad(RI.ByRefElementType, ElemPtr);
4257 Builder.CreateStore(TargetElement, GlobVal);
4261 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4262 RI.ElementType, ElemPtr, 0, 0,
".realp");
4264 RI.ElementType->getStructElementType(0), SrcRealPtr,
".real");
4266 RI.ElementType, ElemPtr, 0, 1,
".imagp");
4268 RI.ElementType->getStructElementType(1), SrcImgPtr,
".imag");
4270 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4271 RI.ElementType, GlobVal, 0, 0,
".realp");
4272 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4273 RI.ElementType, GlobVal, 0, 1,
".imagp");
4274 Builder.CreateStore(SrcReal, DestRealPtr);
4275 Builder.CreateStore(SrcImg, DestImgPtr);
4280 Builder.getInt64(
M.getDataLayout().getTypeStoreSize(RI.ElementType));
4282 GlobVal,
M.getDataLayout().getPrefTypeAlign(RI.ElementType), ElemPtr,
4283 M.getDataLayout().getPrefTypeAlign(RI.ElementType), SizeVal,
false);
4293Expected<Function *> OpenMPIRBuilder::emitListToGlobalReduceFunction(
4296 IRBuilder<>::InsertPointGuard IPG(
Builder);
4297 LLVMContext &Ctx =
M.getContext();
4300 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4304 "_omp_reduction_list_to_global_reduce_func", &
M);
4311 Builder.SetInsertPoint(EntryBlock);
4322 BufferArg->
getName() +
".addr");
4326 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4327 auto *RedListArrayTy =
4332 Value *LocalReduceList =
4333 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4337 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4338 BufferArgAlloca,
Builder.getPtrTy(),
4339 BufferArgAlloca->
getName() +
".ascast");
4340 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4341 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4342 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4343 ReduceListArgAlloca,
Builder.getPtrTy(),
4344 ReduceListArgAlloca->
getName() +
".ascast");
4345 Value *LocalReduceListAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4346 LocalReduceList,
Builder.getPtrTy(),
4347 LocalReduceList->
getName() +
".ascast");
4349 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4350 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4351 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4356 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4357 for (
auto En :
enumerate(ReductionInfos)) {
4360 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4361 RedListArrayTy, LocalReduceListAddrCast,
4362 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4364 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4366 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4367 ReductionsBufferTy, BufferVD, 0, En.index());
4369 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4373 Value *SrcElementPtrPtr =
4374 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceList,
4375 {ConstantInt::get(IndexTy, 0),
4376 ConstantInt::get(IndexTy, En.index())});
4377 Value *SrcDescriptorAddr =
4381 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4382 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4386 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4388 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4396 ->addFnAttr(Attribute::NoUnwind);
4401Expected<Function *> OpenMPIRBuilder::emitGlobalToListCopyFunction(
4404 IRBuilder<>::InsertPointGuard IPG(
Builder);
4405 LLVMContext &Ctx =
M.getContext();
4408 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4412 "_omp_reduction_global_to_list_copy_func", &
M);
4419 Builder.SetInsertPoint(EntryBlock);
4430 BufferArg->
getName() +
".addr");
4434 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4435 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4436 BufferArgAlloca,
Builder.getPtrTy(),
4437 BufferArgAlloca->
getName() +
".ascast");
4438 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4439 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4440 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4441 ReduceListArgAlloca,
Builder.getPtrTy(),
4442 ReduceListArgAlloca->
getName() +
".ascast");
4443 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4444 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4445 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4447 Value *LocalReduceList =
4452 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4453 for (
auto En :
enumerate(ReductionInfos)) {
4454 const OpenMPIRBuilder::ReductionInfo &RI = En.value();
4455 auto *RedListArrayTy =
4459 RedListArrayTy, LocalReduceList,
4460 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4465 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4466 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4467 ReductionsBufferTy, BufferVD, 0, En.index());
4473 if (!IsByRef.
empty() && IsByRef[En.index()]) {
4480 return GenResult.takeError();
4486 Value *TargetElement =
Builder.CreateLoad(ElemType, GlobValPtr);
4487 Builder.CreateStore(TargetElement, ElemPtr);
4491 Value *SrcRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4500 Value *DestRealPtr =
Builder.CreateConstInBoundsGEP2_32(
4502 Value *DestImgPtr =
Builder.CreateConstInBoundsGEP2_32(
4504 Builder.CreateStore(SrcReal, DestRealPtr);
4505 Builder.CreateStore(SrcImg, DestImgPtr);
4512 ElemPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4513 GlobValPtr,
M.getDataLayout().getPrefTypeAlign(RI.
ElementType),
4524Expected<Function *> OpenMPIRBuilder::emitGlobalToListReduceFunction(
4527 IRBuilder<>::InsertPointGuard IPG(
Builder);
4528 LLVMContext &Ctx =
M.getContext();
4531 {Builder.getPtrTy(), Builder.getInt32Ty(), Builder.getPtrTy()},
4535 "_omp_reduction_global_to_list_reduce_func", &
M);
4542 Builder.SetInsertPoint(EntryBlock);
4553 BufferArg->
getName() +
".addr");
4557 Builder.getPtrTy(),
nullptr, ReduceListArg->
getName() +
".addr");
4563 Value *LocalReduceList =
4564 Builder.CreateAlloca(RedListArrayTy,
nullptr,
".omp.reduction.red_list");
4568 Value *BufferArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4569 BufferArgAlloca,
Builder.getPtrTy(),
4570 BufferArgAlloca->
getName() +
".ascast");
4571 Value *IdxArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4572 IdxArgAlloca,
Builder.getPtrTy(), IdxArgAlloca->
getName() +
".ascast");
4573 Value *ReduceListArgAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4574 ReduceListArgAlloca,
Builder.getPtrTy(),
4575 ReduceListArgAlloca->
getName() +
".ascast");
4576 Value *ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4577 LocalReduceList,
Builder.getPtrTy(),
4578 LocalReduceList->
getName() +
".ascast");
4580 Builder.CreateStore(BufferArg, BufferArgAddrCast);
4581 Builder.CreateStore(IdxArg, IdxArgAddrCast);
4582 Builder.CreateStore(ReduceListArg, ReduceListArgAddrCast);
4587 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4588 for (
auto En :
enumerate(ReductionInfos)) {
4591 Value *TargetElementPtrPtr =
Builder.CreateInBoundsGEP(
4592 RedListArrayTy, ReductionList,
4593 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4596 Builder.CreateInBoundsGEP(ReductionsBufferTy, BufferVal, Idxs);
4597 Value *GlobValPtr =
Builder.CreateConstInBoundsGEP2_32(
4598 ReductionsBufferTy, BufferVD, 0, En.index());
4600 if (!IsByRef.
empty() && IsByRef[En.index()] && RI.DataPtrPtrGen) {
4602 Value *ReduceListVal =
4604 Value *SrcElementPtrPtr =
4605 Builder.CreateInBoundsGEP(RedListArrayTy, ReduceListVal,
4606 {ConstantInt::get(IndexTy, 0),
4607 ConstantInt::get(IndexTy, En.index())});
4608 Value *SrcDescriptorAddr =
4612 Expected<Value *> ByRefAlloc = createReductionDescriptorCopy(
4613 AllocaIP, RI, GlobValPtr, SrcDescriptorAddr,
Builder.getPtrTy());
4617 Builder.CreateStore(*ByRefAlloc, TargetElementPtrPtr);
4619 Builder.CreateStore(GlobValPtr, TargetElementPtrPtr);
4627 ->addFnAttr(Attribute::NoUnwind);
4632std::string OpenMPIRBuilder::getReductionFuncName(StringRef Name)
const {
4633 std::string Suffix =
4635 return (Name + Suffix).str();
4638Expected<Function *> OpenMPIRBuilder::createReductionFunction(
4641 AttributeList FuncAttrs) {
4642 IRBuilder<>::InsertPointGuard IPG(
Builder);
4644 {Builder.getPtrTy(), Builder.getPtrTy()},
4646 std::string
Name = getReductionFuncName(ReducerName);
4655 Builder.SetInsertPoint(EntryBB);
4660 Value *LHSArrayPtr =
nullptr;
4661 Value *RHSArrayPtr =
nullptr;
4668 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
4670 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
4671 Value *LHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4672 LHSAlloca, Arg0Type, LHSAlloca->
getName() +
".ascast");
4673 Value *RHSAddrCast =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4674 RHSAlloca, Arg1Type, RHSAlloca->
getName() +
".ascast");
4675 Builder.CreateStore(Arg0, LHSAddrCast);
4676 Builder.CreateStore(Arg1, RHSAddrCast);
4677 LHSArrayPtr =
Builder.CreateLoad(Arg0Type, LHSAddrCast);
4678 RHSArrayPtr =
Builder.CreateLoad(Arg1Type, RHSAddrCast);
4682 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4684 for (
auto En :
enumerate(ReductionInfos)) {
4687 RedArrayTy, RHSArrayPtr,
4688 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4690 Value *RHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4691 RHSI8Ptr, RI.PrivateVariable->getType(),
4692 RHSI8Ptr->
getName() +
".ascast");
4695 RedArrayTy, LHSArrayPtr,
4696 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4698 Value *LHSPtr =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4699 LHSI8Ptr, RI.Variable->getType(), LHSI8Ptr->
getName() +
".ascast");
4708 if (!IsByRef.
empty() && !IsByRef[En.index()]) {
4709 LHS =
Builder.CreateLoad(RI.ElementType, LHSPtr);
4710 RHS =
Builder.CreateLoad(RI.ElementType, RHSPtr);
4717 return AfterIP.takeError();
4718 if (!
Builder.GetInsertBlock())
4719 return ReductionFunc;
4723 if (!IsByRef.
empty() && !IsByRef[En.index()])
4724 Builder.CreateStore(Reduced, LHSPtr);
4729 for (
auto En :
enumerate(ReductionInfos)) {
4730 unsigned Index = En.index();
4732 Value *LHSFixupPtr, *RHSFixupPtr;
4733 Builder.restoreIP(RI.ReductionGenClang(
4734 Builder.saveIP(), Index, &LHSFixupPtr, &RHSFixupPtr, ReductionFunc));
4739 LHSPtrs[Index], [ReductionFunc](
const Use &U) {
4744 RHSPtrs[Index], [ReductionFunc](
const Use &U) {
4758 return ReductionFunc;
4766 assert(RI.Variable &&
"expected non-null variable");
4767 assert(RI.PrivateVariable &&
"expected non-null private variable");
4768 assert((RI.ReductionGen || RI.ReductionGenClang) &&
4769 "expected non-null reduction generator callback");
4772 RI.Variable->getType() == RI.PrivateVariable->getType() &&
4773 "expected variables and their private equivalents to have the same "
4776 assert(RI.Variable->getType()->isPointerTy() &&
4777 "expected variables to be pointers");
4794 ArrayRef<bool> IsByRef,
bool IsNoWait,
bool IsTeamsReduction,
bool IsSPMD,
4796 Value *SrcLocInfo) {
4810 if (ReductionInfos.
size() == 0)
4820 Builder.SetInsertPoint(InsertBlock, InsertBlock->
end());
4824 AttributeList FuncAttrs;
4825 AttrBuilder AttrBldr(Ctx);
4827 AttrBldr.addAttribute(Attr);
4828 AttrBldr.removeAttribute(Attribute::OptimizeNone);
4829 FuncAttrs = FuncAttrs.addFnAttributes(Ctx, AttrBldr);
4833 Builder.GetInsertBlock()->getParent()->getName(), ReductionInfos, IsByRef,
4835 if (!ReductionResult)
4837 Function *ReductionFunc = *ReductionResult;
4841 if (GridValue.has_value())
4842 Config.setGridValue(GridValue.value());
4857 Builder.getPtrTy(
M.getDataLayout().getProgramAddressSpace());
4861 Value *ReductionListAlloca =
4862 Builder.CreateAlloca(RedArrayTy,
nullptr,
".omp.reduction.red_list");
4863 Value *ReductionList =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4864 ReductionListAlloca, PtrTy, ReductionListAlloca->
getName() +
".ascast");
4867 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
4868 for (
auto En :
enumerate(ReductionInfos)) {
4871 RedArrayTy, ReductionList,
4872 {ConstantInt::get(IndexTy, 0), ConstantInt::get(IndexTy, En.index())});
4875 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
4880 Builder.CreatePointerBitCastOrAddrSpaceCast(PrivateVar, PtrTy);
4881 Builder.CreateStore(CastElem, ElemPtr);
4885 ReductionInfos, ReductionFunc, FuncAttrs, IsByRef);
4891 emitInterWarpCopyFunction(
Loc, ReductionInfos, FuncAttrs, IsByRef);
4897 Value *RL =
Builder.CreatePointerBitCastOrAddrSpaceCast(ReductionList, PtrTy);
4906 unsigned MaxDataSize = 0;
4908 for (
auto En :
enumerate(ReductionInfos)) {
4912 Type *RedTypeArg = (!IsByRef.
empty() && IsByRef[En.index()])
4913 ? En.value().ByRefElementType
4914 : En.value().ElementType;
4915 auto Size =
M.getDataLayout().getTypeStoreSize(RedTypeArg);
4916 if (
Size > MaxDataSize)
4920 Value *ReductionDataSize =
4921 Builder.getInt64(MaxDataSize * ReductionInfos.
size());
4925 Function *CopyScratchToListFunc =
nullptr;
4927 Value *ScratchForCopyBack =
nullptr;
4930 Value *RLForCopyBack = RL;
4932 bool IsAtomicReduction =
4935 if (!IsTeamsReduction) {
4936 Value *SarFuncCast =
4937 Builder.CreatePointerBitCastOrAddrSpaceCast(*SarFunc, FuncPtrTy);
4939 Builder.CreatePointerBitCastOrAddrSpaceCast(WcFunc, FuncPtrTy);
4940 Value *Args[] = {SrcLocInfo, ReductionDataSize, RL, SarFuncCast,
4943 RuntimeFunction::OMPRTL___kmpc_nvptx_parallel_reduce_nowait_v2);
4945 }
else if (IsAtomicReduction) {
4949 RuntimeFunction::OMPRTL___kmpc_is_team_main_thread);
4954 Ctx, ReductionTypeArgs,
"struct._globalized_locals_ty");
4957 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
4962 ReductionInfos, ReductionsBufferTy, FuncAttrs, IsByRef);
4967 ReductionInfos, ReductionFunc, ReductionsBufferTy, FuncAttrs, IsByRef);
4990 Value *RuntimeRL = RL;
4997 ReductionsBufferTy,
nullptr,
".omp.reduction.scratch");
4998 Value *PerThreadScratch =
Builder.CreatePointerBitCastOrAddrSpaceCast(
4999 PerThreadScratchAlloca, PtrTy,
5000 PerThreadScratchAlloca->
getName() +
".ascast");
5003 Value *PerThreadRedListAlloca =
5004 Builder.CreateAlloca(RedArrayTy,
nullptr,
5005 ".omp.reduction.per_thread_red_list");
5006 RuntimeRL =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5007 PerThreadRedListAlloca, PtrTy,
5008 PerThreadRedListAlloca->
getName() +
".ascast");
5013 for (
auto En :
enumerate(ReductionInfos)) {
5015 bool IsByRefElem = !IsByRef.
empty() && IsByRef[En.index()];
5018 ReductionsBufferTy, PerThreadScratch, 0, En.index());
5019 Value *Slot =
Builder.CreateConstInBoundsGEP2_32(RedArrayTy, RuntimeRL,
5022 Value *RuntimeListEntry = FieldPtr;
5024 Value *SrcDescriptor =
5027 AllocaIP, RI, FieldPtr, SrcDescriptor, PtrTy);
5030 RuntimeListEntry = *Descriptor;
5032 Builder.CreateStore(RuntimeListEntry, Slot);
5038 Type *CopyArg0Ty = (*LtGCFunc)->getFunctionType()->getParamType(0);
5039 Type *CopyArg2Ty = (*LtGCFunc)->getFunctionType()->getParamType(2);
5040 ScratchForCopyBack =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5041 PerThreadScratch, CopyArg0Ty);
5043 Builder.CreatePointerBitCastOrAddrSpaceCast(RL, CopyArg2Ty);
5051 *LtGCFunc, {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
5052 CopyScratchToListFunc = *GtLCFunc;
5055 Value *Args3[] = {SrcLocInfo, RuntimeRL, *SarFunc, WcFunc,
5056 *LtGCFunc, *GtLCFunc, *GtLRFunc};
5059 RuntimeFunction::OMPRTL___kmpc_gpu_xteam_reduce_nowait);
5079 if (ScratchForCopyBack) {
5082 CopyScratchToListFunc,
5083 {ScratchForCopyBack,
Builder.getInt32(0), RLForCopyBack});
5087 for (
auto En :
enumerate(ReductionInfos)) {
5093 if (IsAtomicReduction) {
5109 Value *LHSPtr, *RHSPtr;
5111 &LHSPtr, &RHSPtr, CurFunc));
5117 RedValue =
Builder.CreatePointerBitCastOrAddrSpaceCast(
5119 if (RHSPtr->
getType() != RHS->getType())
5121 Builder.CreatePointerBitCastOrAddrSpaceCast(RHS, RHSPtr->
getType());
5132 if (IsByRef.
empty() || !IsByRef[En.index()]) {
5134 "red.value." +
Twine(En.index()));
5145 if (!IsByRef.
empty() && !IsByRef[En.index()])
5150 if (ContinuationBlock) {
5151 Builder.CreateBr(ContinuationBlock);
5152 Builder.SetInsertPoint(ContinuationBlock);
5154 Config.setEmitLLVMUsed();
5165 ".omp.reduction.func", &M);
5176 Builder.SetInsertPoint(ReductionFuncBlock);
5178 Value *LHSArrayPtr =
nullptr;
5179 Value *RHSArrayPtr =
nullptr;
5190 Builder.CreateAlloca(Arg0Type,
nullptr, Arg0->
getName() +
".addr");
5192 Builder.CreateAlloca(Arg1Type,
nullptr, Arg1->
getName() +
".addr");
5193 Value *LHSAddrCast =
5194 Builder.CreatePointerBitCastOrAddrSpaceCast(LHSAlloca, Arg0Type);
5195 Value *RHSAddrCast =
5196 Builder.CreatePointerBitCastOrAddrSpaceCast(RHSAlloca, Arg1Type);
5197 Builder.CreateStore(Arg0, LHSAddrCast);
5198 Builder.CreateStore(Arg1, RHSAddrCast);
5199 LHSArrayPtr = Builder.CreateLoad(Arg0Type, LHSAddrCast);
5200 RHSArrayPtr = Builder.CreateLoad(Arg1Type, RHSAddrCast);
5202 LHSArrayPtr = ReductionFunc->
getArg(0);
5203 RHSArrayPtr = ReductionFunc->
getArg(1);
5206 unsigned NumReductions = ReductionInfos.
size();
5209 for (
auto En :
enumerate(ReductionInfos)) {
5211 Value *LHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5212 RedArrayTy, LHSArrayPtr, 0, En.index());
5213 Value *LHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), LHSI8PtrPtr);
5214 Value *LHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5217 Value *RHSI8PtrPtr = Builder.CreateConstInBoundsGEP2_64(
5218 RedArrayTy, RHSArrayPtr, 0, En.index());
5219 Value *RHSI8Ptr = Builder.CreateLoad(Builder.getPtrTy(), RHSI8PtrPtr);
5220 Value *RHSPtr = Builder.CreatePointerBitCastOrAddrSpaceCast(
5229 Builder.restoreIP(*AfterIP);
5231 if (!Builder.GetInsertBlock())
5235 if (!IsByRef[En.index()])
5236 Builder.CreateStore(Reduced, LHSPtr);
5238 Builder.CreateRetVoid();
5245 bool IsNoWait,
bool IsTeamsReduction) {
5249 IsByRef, IsNoWait, IsTeamsReduction);
5256 if (ReductionInfos.
size() == 0)
5266 unsigned NumReductions = ReductionInfos.
size();
5269 Value *RedArray =
Builder.CreateAlloca(RedArrayTy,
nullptr,
"red.array");
5271 Builder.SetInsertPoint(InsertBlock, InsertBlock->
end());
5273 for (
auto En :
enumerate(ReductionInfos)) {
5274 unsigned Index = En.index();
5276 Value *RedArrayElemPtr =
Builder.CreateConstInBoundsGEP2_64(
5277 RedArrayTy, RedArray, 0, Index,
"red.array.elem." +
Twine(Index));
5284 M.getDataLayout(),
M.getDataLayout().getDefaultGlobalsAddressSpace());
5294 ? IdentFlag::OMP_IDENT_FLAG_ATOMIC_REDUCE
5299 unsigned RedArrayByteSize =
DL.getTypeStoreSize(RedArrayTy);
5300 Constant *RedArraySize = ConstantInt::get(IndexTy, RedArrayByteSize);
5302 Value *Lock = getOMPCriticalRegionLock(
".reduction");
5304 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_reduce_nowait
5305 : RuntimeFunction::OMPRTL___kmpc_reduce);
5308 {Ident, ThreadId, NumVariables, RedArraySize,
5309 RedArray, ReductionFunc, Lock},
5320 Builder.CreateSwitch(ReduceCall, ContinuationBlock, 2);
5321 Switch->addCase(
Builder.getInt32(1), NonAtomicRedBlock);
5322 Switch->addCase(
Builder.getInt32(2), AtomicRedBlock);
5327 Builder.SetInsertPoint(NonAtomicRedBlock);
5328 for (
auto En :
enumerate(ReductionInfos)) {
5334 if (!IsByRef[En.index()]) {
5336 "red.value." +
Twine(En.index()));
5338 Value *PrivateRedValue =
5340 "red.private.value." +
Twine(En.index()));
5348 if (!
Builder.GetInsertBlock())
5351 if (!IsByRef[En.index()])
5355 IsNoWait ? RuntimeFunction::OMPRTL___kmpc_end_reduce_nowait
5356 : RuntimeFunction::OMPRTL___kmpc_end_reduce);
5358 Builder.CreateBr(ContinuationBlock);
5363 Builder.SetInsertPoint(AtomicRedBlock);
5364 if (CanGenerateAtomic &&
llvm::none_of(IsByRef, [](
bool P) {
return P; })) {
5371 if (!
Builder.GetInsertBlock())
5374 Builder.CreateBr(ContinuationBlock);
5387 if (!
Builder.GetInsertBlock())
5390 Builder.SetInsertPoint(ContinuationBlock);
5401 Directive OMPD = Directive::OMPD_master;
5406 Value *Args[] = {Ident, ThreadId};
5414 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5425 Directive OMPD = Directive::OMPD_masked;
5431 Value *ArgsEnd[] = {Ident, ThreadId};
5439 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
5449 Call->setDoesNotThrow();
5464 bool IsInclusive,
ScanInfo *ScanRedInfo) {
5466 llvm::Error Err = emitScanBasedDirectiveDeclsIR(AllocaIP, ScanVars,
5467 ScanVarsType, ScanRedInfo);
5478 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5481 Type *DestTy = ScanVarsType[i];
5482 Value *Val =
Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5485 Builder.CreateStore(Src, Val);
5490 Builder.GetInsertBlock()->getParent());
5493 IV = ScanRedInfo->
IV;
5496 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5499 Type *DestTy = ScanVarsType[i];
5501 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5503 Builder.CreateStore(Src, ScanVars[i]);
5517 Builder.GetInsertBlock()->getParent());
5522Error OpenMPIRBuilder::emitScanBasedDirectiveDeclsIR(
5526 Builder.restoreIP(AllocaIP);
5528 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5530 Builder.CreateAlloca(Builder.getPtrTy(),
nullptr,
"vla");
5537 Builder.restoreIP(CodeGenIP);
5539 Builder.CreateAdd(ScanRedInfo->
Span, Builder.getInt32(1));
5540 for (
size_t i = 0; i < ScanVars.
size(); i++) {
5544 Value *Buff = Builder.CreateMalloc(
IntPtrTy, ScanVarsType[i], Allocsize,
5545 AllocSpan,
nullptr,
"arr");
5546 Builder.CreateStore(Buff, (*(ScanRedInfo->
ScanBuffPtrs))[ScanVars[i]]);
5564 Builder.SetInsertPoint(
Builder.GetInsertBlock()->getTerminator());
5573Error OpenMPIRBuilder::emitScanBasedDirectiveFinalsIR(
5579 Value *PrivateVar = RedInfo.PrivateVariable;
5580 Value *OrigVar = RedInfo.Variable;
5584 Type *SrcTy = RedInfo.ElementType;
5589 Builder.CreateStore(Src, OrigVar);
5612 Builder.SetInsertPoint(
Builder.GetInsertBlock()->getTerminator());
5637 Builder.GetInsertBlock()->getModule(),
5644 Builder.GetInsertBlock()->getModule(),
5650 llvm::ConstantInt::get(ScanRedInfo->
Span->
getType(), 1));
5651 Builder.SetInsertPoint(InputBB);
5654 Builder.SetInsertPoint(LoopBB);
5670 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5672 Builder.SetInsertPoint(InnerLoopBB);
5676 Value *ReductionVal = RedInfo.PrivateVariable;
5679 Type *DestTy = RedInfo.ElementType;
5682 Builder.CreateInBoundsGEP(DestTy, Buff,
IV,
"arrayOffset");
5685 Builder.CreateInBoundsGEP(DestTy, Buff, OffsetIval,
"arrayOffset");
5690 RedInfo.ReductionGen(
Builder.saveIP(), LHS, RHS, Result);
5693 Builder.CreateStore(Result, LHSPtr);
5696 IVal, llvm::ConstantInt::get(
Builder.getInt32Ty(), 1));
5698 CmpI =
Builder.CreateICmpUGE(NextIVal, Pow2K);
5699 Builder.CreateCondBr(CmpI, InnerLoopBB, InnerExitBB);
5702 Counter, llvm::ConstantInt::get(Counter->
getType(), 1));
5708 Builder.CreateCondBr(Cmp, LoopBB, ExitBB);
5729 Error Err = emitScanBasedDirectiveFinalsIR(ReductionInfos, ScanRedInfo);
5736Error OpenMPIRBuilder::emitScanBasedDirectiveIR(
5748 Error Err = InputLoopGen();
5759 Error Err = ScanLoopGen(Builder.saveIP());
5766void OpenMPIRBuilder::createScanBBs(ScanInfo *ScanRedInfo) {
5803 Builder.SetInsertPoint(Preheader);
5806 Builder.SetInsertPoint(Header);
5807 PHINode *IndVarPHI =
Builder.CreatePHI(IndVarTy, 2,
"omp_" + Name +
".iv");
5808 IndVarPHI->
addIncoming(ConstantInt::get(IndVarTy, 0), Preheader);
5813 Builder.CreateICmpULT(IndVarPHI, TripCount,
"omp_" + Name +
".cmp");
5814 Builder.CreateCondBr(Cmp, Body, Exit);
5819 Builder.SetInsertPoint(Latch);
5829 bool HasNSW =
Config.hasNoSignedWrap();
5832 unsigned BitWidth = CI->getType()->getIntegerBitWidth();
5834 if (CI->getValue().ugt(SignedMax))
5836 }
else if (IsCollapsed) {
5841 Builder.CreateAdd(IndVarPHI, ConstantInt::get(IndVarTy, 1),
5842 "omp_" + Name +
".next",
true, HasNSW);
5853 CL->Header = Header;
5872 NextBB, NextBB, Name);
5904 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
5913 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
5914 ScanRedInfo->
Span = TripCount;
5920 ScanRedInfo->
IV =
IV;
5921 createScanBBs(ScanRedInfo);
5924 assert(Terminator->getNumSuccessors() == 1);
5925 BasicBlock *ContinueBlock = Terminator->getSuccessor(0);
5928 Builder.GetInsertBlock()->getParent());
5931 Builder.GetInsertBlock()->getParent());
5932 Builder.CreateBr(ContinueBlock);
5938 const auto &&InputLoopGen = [&]() ->
Error {
5940 Builder.saveIP(), BodyGen, Start, Stop, Step, IsSigned, InclusiveStop,
5941 ComputeIP, Name,
true, ScanRedInfo);
5945 Builder.restoreIP((*LoopInfo)->getAfterIP());
5951 InclusiveStop, ComputeIP, Name,
true, ScanRedInfo);
5955 Builder.restoreIP((*LoopInfo)->getAfterIP());
5959 Error Err = emitScanBasedDirectiveIR(InputLoopGen, ScanLoopGen, ScanRedInfo);
5967 bool IsSigned,
bool InclusiveStop,
const Twine &Name) {
5977 assert(IndVarTy == Stop->
getType() &&
"Stop type mismatch");
5978 assert(IndVarTy == Step->
getType() &&
"Step type mismatch");
5982 ConstantInt *Zero = ConstantInt::get(IndVarTy, 0);
5998 Incr =
Builder.CreateSelect(IsNeg,
Builder.CreateNeg(Step), Step);
6001 Span =
Builder.CreateSub(UB, LB,
"",
false,
true);
6005 Span =
Builder.CreateSub(Stop, Start,
"",
true);
6010 Value *CountIfLooping;
6011 if (InclusiveStop) {
6012 CountIfLooping =
Builder.CreateAdd(
Builder.CreateUDiv(Span, Incr), One);
6018 CountIfLooping =
Builder.CreateSelect(OneCmp, One, CountIfTwo);
6021 return Builder.CreateSelect(ZeroCmp, Zero, CountIfLooping,
6022 "omp_" + Name +
".tripcount");
6027 Value *Start,
Value *Stop,
Value *Step,
bool IsSigned,
bool InclusiveStop,
6034 ComputeLoc, Start, Stop, Step, IsSigned, InclusiveStop, Name);
6039 Config.hasNoSignedWrap());
6040 Value *IndVar =
Builder.CreateAdd(Span, Start,
"",
false,
6041 Config.hasNoSignedWrap());
6043 ScanRedInfo->
IV = IndVar;
6044 return BodyGenCB(
Builder.saveIP(), IndVar);
6050 Builder.getCurrentDebugLocation());
6061 unsigned Bitwidth = Ty->getIntegerBitWidth();
6064 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_4u);
6067 M, omp::RuntimeFunction::OMPRTL___kmpc_dist_for_static_init_8u);
6077 unsigned Bitwidth = Ty->getIntegerBitWidth();
6080 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_4u);
6083 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_init_8u);
6091 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6093 "Require dedicated allocate IP");
6099 uint32_t SrcLocStrSize;
6103 case WorksharingLoopType::ForStaticLoop:
6104 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6106 case WorksharingLoopType::DistributeStaticLoop:
6107 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6109 case WorksharingLoopType::DistributeForStaticLoop:
6110 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
6117 Type *IVTy =
IV->getType();
6118 FunctionCallee StaticInit =
6119 LoopType == WorksharingLoopType::DistributeForStaticLoop
6122 FunctionCallee StaticFini =
6126 Builder.SetInsertPoint(AllocaIP.getBlock()->getFirstNonPHIOrDbgOrAlloca());
6129 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6130 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
6131 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
6132 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
6141 Constant *One = ConstantInt::get(IVTy, 1);
6142 Builder.CreateStore(Zero, PLowerBound);
6144 Builder.CreateStore(UpperBound, PUpperBound);
6145 Builder.CreateStore(One, PStride);
6151 (LoopType == WorksharingLoopType::DistributeStaticLoop)
6152 ? OMPScheduleType::OrderedDistribute
6155 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6159 auto BuildInitCall = [LoopType, SrcLoc, ThreadNum, PLastIter, PLowerBound,
6160 PUpperBound, IVTy, PStride, One,
Zero, StaticInit,
6163 PLowerBound, PUpperBound});
6164 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
6165 Value *PDistUpperBound =
6166 Builder.CreateAlloca(IVTy,
nullptr,
"p.distupperbound");
6167 Args.push_back(PDistUpperBound);
6172 BuildInitCall(SchedulingType,
Builder);
6173 if (HasDistSchedule &&
6174 LoopType != WorksharingLoopType::DistributeStaticLoop) {
6175 Constant *DistScheduleSchedType = ConstantInt::get(
6180 BuildInitCall(DistScheduleSchedType,
Builder);
6183 Value *InclusiveUpperBound =
Builder.CreateLoad(IVTy, PUpperBound);
6185 Value *TripCount =
Builder.CreateAdd(TripCountMinusOne, One);
6186 CLI->setTripCount(TripCount);
6192 CLI->mapIndVar([&](Instruction *OldIV) ->
Value * {
6197 Config.hasNoSignedWrap());
6209 omp::Directive::OMPD_for,
false,
6212 return BarrierIP.takeError();
6239 Reachable.insert(
Block);
6253OpenMPIRBuilder::applyStaticChunkedWorkshareLoop(
6257 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6258 assert((ChunkSize || DistScheduleChunkSize) &&
"Chunk size is required");
6263 Type *IVTy =
IV->getType();
6265 "Max supported tripcount bitwidth is 64 bits");
6267 :
Type::getInt64Ty(Ctx);
6270 Constant *One = ConstantInt::get(InternalIVTy, 1);
6275 SmallVector<Instruction *> UIs;
6276 for (BasicBlock &BB : *
F)
6277 if (!BB.hasTerminator())
6278 UIs.
push_back(
new UnreachableInst(
F->getContext(), &BB));
6283 LoopInfo &&LI = LIA.
run(*
F,
FAM);
6284 for (Instruction *
I : UIs)
6285 I->eraseFromParent();
6288 if (ChunkSize || DistScheduleChunkSize)
6293 FunctionCallee StaticInit =
6295 FunctionCallee StaticFini =
6301 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6302 Value *PLowerBound =
6303 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.lowerbound");
6304 Value *PUpperBound =
6305 Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.upperbound");
6306 Value *PStride =
Builder.CreateAlloca(InternalIVTy,
nullptr,
"p.stride");
6315 ChunkSize ? ChunkSize : Zero, InternalIVTy,
"chunksize");
6316 Value *CastedDistScheduleChunkSize =
Builder.CreateZExtOrTrunc(
6317 DistScheduleChunkSize ? DistScheduleChunkSize : Zero, InternalIVTy,
6318 "distschedulechunksize");
6319 Value *CastedTripCount =
6320 Builder.CreateZExt(OrigTripCount, InternalIVTy,
"tripcount");
6323 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6325 ConstantInt::get(I32Type,
static_cast<int>(DistScheduleSchedType));
6326 Builder.CreateStore(Zero, PLowerBound);
6327 Value *OrigUpperBound =
Builder.CreateSub(CastedTripCount, One);
6328 Value *IsTripCountZero =
Builder.CreateICmpEQ(CastedTripCount, Zero);
6330 Builder.CreateSelect(IsTripCountZero, Zero, OrigUpperBound);
6331 Builder.CreateStore(UpperBound, PUpperBound);
6332 Builder.CreateStore(One, PStride);
6336 uint32_t SrcLocStrSize;
6339 if (DistScheduleSchedType != OMPScheduleType::None) {
6340 Flag |= OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6345 auto BuildInitCall = [StaticInit, SrcLoc, ThreadNum, PLastIter, PLowerBound,
6346 PUpperBound, PStride, One,
6347 this](
Value *SchedulingType,
Value *ChunkSize,
6350 StaticInit, {SrcLoc, ThreadNum,
6351 SchedulingType, PLastIter,
6352 PLowerBound, PUpperBound,
6356 BuildInitCall(SchedulingType, CastedChunkSize,
Builder);
6357 if (DistScheduleSchedType != OMPScheduleType::None &&
6358 SchedType != OMPScheduleType::OrderedDistributeChunked &&
6359 SchedType != OMPScheduleType::OrderedDistribute) {
6363 BuildInitCall(DistSchedulingType, CastedDistScheduleChunkSize,
Builder);
6367 Value *FirstChunkStart =
6368 Builder.CreateLoad(InternalIVTy, PLowerBound,
"omp_firstchunk.lb");
6369 Value *FirstChunkStop =
6370 Builder.CreateLoad(InternalIVTy, PUpperBound,
"omp_firstchunk.ub");
6371 Value *FirstChunkEnd =
Builder.CreateAdd(FirstChunkStop, One);
6373 Builder.CreateSub(FirstChunkEnd, FirstChunkStart,
"omp_chunk.range");
6374 Value *NextChunkStride =
6375 Builder.CreateLoad(InternalIVTy, PStride,
"omp_dispatch.stride");
6379 Value *DispatchCounter;
6387 DispatchCounter = Counter;
6390 FirstChunkStart, CastedTripCount, NextChunkStride,
6413 Value *ChunkEnd =
Builder.CreateAdd(DispatchCounter, ChunkRange);
6414 Value *IsLastChunk =
6415 Builder.CreateICmpUGE(ChunkEnd, CastedTripCount,
"omp_chunk.is_last");
6416 Value *CountUntilOrigTripCount =
6417 Builder.CreateSub(CastedTripCount, DispatchCounter);
6419 IsLastChunk, CountUntilOrigTripCount, ChunkRange,
"omp_chunk.tripcount");
6420 Value *BackcastedChunkTC =
6421 Builder.CreateTrunc(ChunkTripCount, IVTy,
"omp_chunk.tripcount.trunc");
6422 CLI->setTripCount(BackcastedChunkTC);
6427 Value *BackcastedDispatchCounter =
6428 Builder.CreateTrunc(DispatchCounter, IVTy,
"omp_dispatch.iv.trunc");
6429 CLI->mapIndVar([&](Instruction *) ->
Value * {
6431 return Builder.CreateAdd(
IV, BackcastedDispatchCounter);
6444 return AfterIP.takeError();
6459static FunctionCallee
6462 unsigned Bitwidth = Ty->getIntegerBitWidth();
6465 case WorksharingLoopType::ForStaticLoop:
6468 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_4u);
6471 M, omp::RuntimeFunction::OMPRTL___kmpc_for_static_loop_8u);
6473 case WorksharingLoopType::DistributeStaticLoop:
6476 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_4u);
6479 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_static_loop_8u);
6481 case WorksharingLoopType::DistributeForStaticLoop:
6484 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_4u);
6487 M, omp::RuntimeFunction::OMPRTL___kmpc_distribute_for_static_loop_8u);
6490 if (Bitwidth != 32 && Bitwidth != 64) {
6502 Function &LoopBodyFn,
bool NoLoop) {
6513 if (LoopType == WorksharingLoopType::DistributeStaticLoop) {
6514 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6515 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6516 Builder.restoreIP({InsertBlock, std::prev(InsertBlock->
end())});
6521 M, omp::RuntimeFunction::OMPRTL_omp_get_num_threads);
6522 Builder.restoreIP({InsertBlock, std::prev(InsertBlock->
end())});
6526 Builder.CreateZExtOrTrunc(NumThreads, TripCountTy,
"num.threads.cast"));
6527 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6528 if (LoopType == WorksharingLoopType::DistributeForStaticLoop) {
6529 RealArgs.
push_back(ConstantInt::get(TripCountTy, 0));
6530 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), NoLoop));
6532 RealArgs.
push_back(ConstantInt::get(Builder.getInt8Ty(), 0));
6556 Builder.restoreIP({Preheader, Preheader->
end()});
6559 Builder.CreateBr(CLI->
getExit());
6567 CleanUpInfo.
collectBlocks(RegionBlockSet, BlocksToBeRemoved);
6575 "Expected unique undroppable user of outlined function");
6577 assert(OutlinedFnCallInstruction &&
"Expected outlined function call");
6579 "Expected outlined function call to be located in loop preheader");
6581 if (OutlinedFnCallInstruction->
arg_size() > 1)
6588 LoopBodyArg, TripCount, OutlinedFn, NoLoop);
6590 for (
auto &ToBeDeletedItem : ToBeDeleted)
6591 ToBeDeletedItem->eraseFromParent();
6598 uint32_t SrcLocStrSize;
6602 case WorksharingLoopType::ForStaticLoop:
6603 Flag = OMP_IDENT_FLAG_WORK_LOOP;
6605 case WorksharingLoopType::DistributeStaticLoop:
6606 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE;
6608 case WorksharingLoopType::DistributeForStaticLoop:
6609 Flag = OMP_IDENT_FLAG_WORK_DISTRIBUTE | OMP_IDENT_FLAG_WORK_LOOP;
6614 auto OI = std::make_unique<OutlineInfo>();
6619 SmallVector<Instruction *, 4> ToBeDeleted;
6621 OI->OuterAllocBB = AllocaIP.getBlock();
6644 SmallPtrSet<BasicBlock *, 32> ParallelRegionBlockSet;
6646 OI->collectBlocks(ParallelRegionBlockSet, Blocks);
6648 CodeExtractorAnalysisCache CEAC(*OuterFn);
6649 CodeExtractor Extractor(Blocks,
6663 SetVector<Value *> SinkingCands, HoistingCands;
6667 Extractor.findAllocas(CEAC, SinkingCands, HoistingCands, CommonExit);
6674 for (
auto Use :
Users) {
6676 if (ParallelRegionBlockSet.
count(Inst->getParent())) {
6677 Inst->replaceUsesOfWith(CLI->
getIndVar(), NewLoopCntLoad);
6683 OI->ExcludeArgsFromAggregate.push_back(NewLoopCntLoad);
6690 OI->PostOutlineCB = [=, ToBeDeletedVec =
6691 std::move(ToBeDeleted)](
Function &OutlinedFn) {
6701 bool NeedsBarrier, omp::ScheduleKind SchedKind,
Value *ChunkSize,
6702 bool HasSimdModifier,
bool HasMonotonicModifier,
6703 bool HasNonmonotonicModifier,
bool HasOrderedClause,
6705 Value *DistScheduleChunkSize) {
6706 if (
Config.isTargetDevice())
6707 return applyWorkshareLoopTarget(
DL, CLI, AllocaIP, LoopType, NoLoop);
6709 SchedKind, ChunkSize, HasSimdModifier, HasMonotonicModifier,
6710 HasNonmonotonicModifier, HasOrderedClause, DistScheduleChunkSize);
6712 bool IsOrdered = (EffectiveScheduleType & OMPScheduleType::ModifierOrdered) ==
6713 OMPScheduleType::ModifierOrdered;
6715 if (HasDistSchedule) {
6716 DistScheduleSchedType = DistScheduleChunkSize
6717 ? OMPScheduleType::OrderedDistributeChunked
6718 : OMPScheduleType::OrderedDistribute;
6720 switch (EffectiveScheduleType & ~OMPScheduleType::ModifierMask) {
6721 case OMPScheduleType::BaseStatic:
6722 case OMPScheduleType::BaseDistribute:
6723 assert((!ChunkSize || !DistScheduleChunkSize) &&
6724 "No chunk size with static-chunked schedule");
6725 if (IsOrdered && !HasDistSchedule)
6726 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6727 NeedsBarrier, ChunkSize);
6729 if (DistScheduleChunkSize)
6730 return applyStaticChunkedWorkshareLoop(
6731 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6732 DistScheduleChunkSize, DistScheduleSchedType);
6733 return applyStaticWorkshareLoop(
DL, CLI, AllocaIP, LoopType, NeedsBarrier,
6736 case OMPScheduleType::BaseStaticChunked:
6737 case OMPScheduleType::BaseDistributeChunked:
6738 if (IsOrdered && !HasDistSchedule)
6739 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6740 NeedsBarrier, ChunkSize);
6742 return applyStaticChunkedWorkshareLoop(
6743 DL, CLI, AllocaIP, NeedsBarrier, ChunkSize, EffectiveScheduleType,
6744 DistScheduleChunkSize, DistScheduleSchedType);
6746 case OMPScheduleType::BaseRuntime:
6747 case OMPScheduleType::BaseAuto:
6748 case OMPScheduleType::BaseGreedy:
6749 case OMPScheduleType::BaseBalanced:
6750 case OMPScheduleType::BaseSteal:
6751 case OMPScheduleType::BaseRuntimeSimd:
6753 "schedule type does not support user-defined chunk sizes");
6755 case OMPScheduleType::BaseGuidedSimd:
6756 case OMPScheduleType::BaseDynamicChunked:
6757 case OMPScheduleType::BaseGuidedChunked:
6758 case OMPScheduleType::BaseGuidedIterativeChunked:
6759 case OMPScheduleType::BaseGuidedAnalyticalChunked:
6760 case OMPScheduleType::BaseStaticBalancedChunked:
6761 return applyDynamicWorkshareLoop(
DL, CLI, AllocaIP, EffectiveScheduleType,
6762 NeedsBarrier, ChunkSize);
6775 unsigned Bitwidth = Ty->getIntegerBitWidth();
6778 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_4u);
6781 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_init_8u);
6789static FunctionCallee
6791 unsigned Bitwidth = Ty->getIntegerBitWidth();
6794 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_4u);
6797 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_next_8u);
6804static FunctionCallee
6806 unsigned Bitwidth = Ty->getIntegerBitWidth();
6809 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_4u);
6812 M, omp::RuntimeFunction::OMPRTL___kmpc_dispatch_fini_8u);
6817OpenMPIRBuilder::applyDynamicWorkshareLoop(
DebugLoc DL, CanonicalLoopInfo *CLI,
6820 bool NeedsBarrier,
Value *Chunk) {
6821 assert(CLI->
isValid() &&
"Requires a valid canonical loop");
6823 "Require dedicated allocate IP");
6825 "Require valid schedule type");
6827 bool Ordered = (SchedType & OMPScheduleType::ModifierOrdered) ==
6828 OMPScheduleType::ModifierOrdered;
6833 uint32_t SrcLocStrSize;
6840 Type *IVTy =
IV->getType();
6845 Builder.SetInsertPoint(AllocaIP.getBlock()->getFirstNonPHIOrDbgOrAlloca());
6847 Value *PLastIter =
Builder.CreateAlloca(I32Type,
nullptr,
"p.lastiter");
6848 Value *PLowerBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.lowerbound");
6849 Value *PUpperBound =
Builder.CreateAlloca(IVTy,
nullptr,
"p.upperbound");
6850 Value *PStride =
Builder.CreateAlloca(IVTy,
nullptr,
"p.stride");
6859 Constant *One = ConstantInt::get(IVTy, 1);
6860 Builder.CreateStore(One, PLowerBound);
6862 Builder.CreateStore(UpperBound, PUpperBound);
6863 Builder.CreateStore(One, PStride);
6881 ConstantInt::get(I32Type,
static_cast<int>(SchedType));
6893 Builder.SetInsertPoint(OuterCond, OuterCond->getFirstInsertionPt());
6896 {SrcLoc, ThreadNum, PLastIter, PLowerBound, PUpperBound, PStride});
6897 Constant *Zero32 = ConstantInt::get(I32Type, 0);
6900 Builder.CreateSub(
Builder.CreateLoad(IVTy, PLowerBound), One,
"lb");
6901 Builder.CreateCondBr(MoreWork, Header, Exit);
6907 PI->setIncomingBlock(0, OuterCond);
6913 Br->setSuccessor(OuterCond);
6919 UpperBound =
Builder.CreateLoad(IVTy, PUpperBound,
"ub");
6922 CI->setOperand(1, UpperBound);
6926 assert(BI->getSuccessor(1) == Exit);
6927 BI->setSuccessor(1, OuterCond);
6941 omp::Directive::OMPD_for,
false,
6944 return BarrierIP.takeError();
6996 assert(
Loops.size() >= 1 &&
"At least one loop required");
6997 size_t NumLoops =
Loops.size();
7001 return Loops.front();
7013 Loop->collectControlBlocks(OldControlBBs);
7017 if (ComputeIP.
isSet())
7024 Value *CollapsedTripCount =
nullptr;
7027 "All loops to collapse must be valid canonical loops");
7028 Value *OrigTripCount = L->getTripCount();
7029 if (!CollapsedTripCount) {
7030 CollapsedTripCount = OrigTripCount;
7035 CollapsedTripCount =
7036 Builder.CreateNUWMul(CollapsedTripCount, OrigTripCount);
7042 OrigPreheader->
getNextNode(), OrigAfter,
"collapsed",
7049 Builder.restoreIP(Result->getBodyIP());
7051 Value *Leftover = Result->getIndVar();
7053 NewIndVars.
resize(NumLoops);
7054 for (
int i = NumLoops - 1; i >= 1; --i) {
7055 Value *OrigTripCount =
Loops[i]->getTripCount();
7057 Value *NewIndVar =
Builder.CreateURem(Leftover, OrigTripCount);
7058 NewIndVars[i] = NewIndVar;
7060 Leftover =
Builder.CreateUDiv(Leftover, OrigTripCount);
7063 NewIndVars[0] = Leftover;
7072 BasicBlock *ContinueBlock = Result->getBody();
7074 auto ContinueWith = [&ContinueBlock, &ContinuePred,
DL](
BasicBlock *Dest,
7081 ContinueBlock =
nullptr;
7082 ContinuePred = NextSrc;
7089 for (
size_t i = 0; i < NumLoops - 1; ++i)
7090 ContinueWith(
Loops[i]->getBody(),
Loops[i + 1]->getHeader());
7096 for (
size_t i = NumLoops - 1; i > 0; --i)
7097 ContinueWith(
Loops[i]->getAfter(),
Loops[i - 1]->getLatch());
7100 ContinueWith(Result->getLatch(),
nullptr);
7107 for (
size_t i = 0; i < NumLoops; ++i)
7108 Loops[i]->getIndVar()->replaceAllUsesWith(NewIndVars[i]);
7122std::vector<CanonicalLoopInfo *>
7126 "Must pass as many tile sizes as there are loops");
7127 int NumLoops =
Loops.size();
7128 assert(NumLoops >= 1 &&
"At least one loop to tile required");
7140 Loop->collectControlBlocks(OldControlBBs);
7148 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7149 OrigTripCounts.
push_back(L->getTripCount());
7160 for (
int i = 0; i < NumLoops - 1; ++i) {
7173 for (
int i = 0; i < NumLoops; ++i) {
7175 Value *OrigTripCount = OrigTripCounts[i];
7188 Value *FloorTripOverflow =
7189 Builder.CreateICmpNE(FloorTripRem, ConstantInt::get(IVType, 0));
7191 FloorTripOverflow =
Builder.CreateZExt(FloorTripOverflow, IVType);
7192 Value *FloorTripCount =
7193 Builder.CreateAdd(FloorCompleteTripCount, FloorTripOverflow,
7194 "omp_floor" +
Twine(i) +
".tripcount",
true);
7197 FloorCompleteCount.
push_back(FloorCompleteTripCount);
7203 std::vector<CanonicalLoopInfo *> Result;
7204 Result.reserve(NumLoops * 2);
7217 auto EmbeddNewLoop =
7218 [
this,
DL,
F, InnerEnter, &Enter, &
Continue, &OutroInsertBefore](
7221 DL, TripCount,
F, InnerEnter, OutroInsertBefore, Name);
7226 Enter = EmbeddedLoop->
getBody();
7228 OutroInsertBefore = EmbeddedLoop->
getLatch();
7229 return EmbeddedLoop;
7233 const Twine &NameBase) {
7236 EmbeddNewLoop(
P.value(), NameBase +
Twine(
P.index()));
7237 Result.push_back(EmbeddedLoop);
7241 EmbeddNewLoops(FloorCount,
"floor");
7247 for (
int i = 0; i < NumLoops; ++i) {
7251 Value *FloorIsEpilogue =
7253 Value *TileTripCount =
7260 EmbeddNewLoops(TileCounts,
"tile");
7265 for (std::pair<BasicBlock *, BasicBlock *>
P : InbetweenCode) {
7274 BodyEnter =
nullptr;
7275 BodyEntered = ExitBB;
7287 Builder.restoreIP(Result.back()->getBodyIP());
7288 for (
int i = 0; i < NumLoops; ++i) {
7291 Value *OrigIndVar = OrigIndVars[i];
7342 assert(
Loop->isValid() &&
"Expecting a valid CanonicalLoopInfo");
7346 assert(Latch &&
"A valid CanonicalLoopInfo must have a unique latch");
7354 if (
I.mayReadOrWriteMemory()) {
7358 I.setMetadata(LLVMContext::MD_access_group,
AccessGroup);
7372 Loop->collectControlBlocks(oldControlBBs);
7377 assert(L->isValid() &&
"All input loops must be valid canonical loops");
7378 origTripCounts.
push_back(L->getTripCount());
7387 Builder.SetInsertPoint(TCBlock);
7388 Value *fusedTripCount =
nullptr;
7390 assert(L->isValid() &&
"All loops to fuse must be valid canonical loops");
7391 Value *origTripCount = L->getTripCount();
7392 if (!fusedTripCount) {
7393 fusedTripCount = origTripCount;
7396 Value *condTP =
Builder.CreateICmpSGT(fusedTripCount, origTripCount);
7397 fusedTripCount =
Builder.CreateSelect(condTP, fusedTripCount, origTripCount,
7411 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7412 Loops[i]->getPreheader()->moveBefore(TCBlock);
7413 Loops[i]->getAfter()->moveBefore(TCBlock);
7417 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7429 for (
size_t i = 0; i <
Loops.size(); ++i) {
7431 F->getContext(),
"omp.fused.inner.cond",
F,
Loops[i]->getBody());
7432 Builder.SetInsertPoint(condBlock);
7440 for (
size_t i = 0; i <
Loops.size() - 1; ++i) {
7441 Builder.SetInsertPoint(condBBs[i]);
7442 Builder.CreateCondBr(condValues[i],
Loops[i]->getBody(), condBBs[i + 1]);
7458 "omp.fused.pre_latch");
7491 const Twine &NamePrefix) {
7520 C, NamePrefix +
".if.then",
Cond->getParent(),
Cond->getNextNode());
7522 C, NamePrefix +
".if.else",
Cond->getParent(), CanonicalLoop->
getExit());
7525 Builder.SetInsertPoint(SplitBeforeIt);
7527 Builder.CreateCondBr(IfCond, ThenBlock, ElseBlock);
7530 spliceBB(IP, ThenBlock,
false, Builder.getCurrentDebugLocation());
7533 Builder.SetInsertPoint(ElseBlock);
7539 ExistingBlocks.
reserve(L->getNumBlocks() + 1);
7541 ExistingBlocks.
append(L->block_begin(), L->block_end());
7547 assert(LoopCond && LoopHeader &&
"Invalid loop structure");
7549 if (
Block == L->getLoopPreheader() ||
Block == L->getLoopLatch() ||
7556 if (
Block == ThenBlock)
7557 NewBB->
setName(NamePrefix +
".if.else");
7560 VMap[
Block] = NewBB;
7568 L->getLoopLatch()->splitBasicBlockBefore(
L->getLoopLatch()->begin(),
7569 NamePrefix +
".pre_latch");
7573 L->addBasicBlockToLoop(ThenBlock, LI);
7579 if (TargetTriple.
isX86()) {
7580 if (Features.
lookup(
"avx512f"))
7582 else if (Features.
lookup(
"avx"))
7586 if (TargetTriple.
isPPC())
7588 if (TargetTriple.
isWasm())
7595 Value *IfCond, OrderKind Order,
7605 if (!BB.hasTerminator())
7621 I->eraseFromParent();
7624 if (AlignedVars.
size()) {
7626 for (
auto &AlignedItem : AlignedVars) {
7627 Value *AlignedPtr = AlignedItem.first;
7631 Builder.CreateAlignmentAssumption(
F->getDataLayout(), AlignedPtr,
7639 createIfVersion(CanonicalLoop, IfCond, VMap, LIA, LI, L,
"simd");
7652 Reachable.insert(
Block);
7662 if ((Safelen ==
nullptr) || (Order == OrderKind::OMP_ORDER_concurrent))
7678 if (Simdlen || Safelen) {
7682 ConstantInt *VectorizeWidth = Simdlen ==
nullptr ? Safelen : Simdlen;
7708static std::unique_ptr<TargetMachine>
7712 StringRef CPU =
F->getFnAttribute(
"target-cpu").getValueAsString();
7713 StringRef Features =
F->getFnAttribute(
"target-features").getValueAsString();
7724 std::nullopt, OptLevel));
7742 if (!BB.hasTerminator())
7755 [&](
const Function &
F) {
return TM->getTargetTransformInfo(
F); });
7756 FAM.registerPass([&]() {
return TIRA; });
7770 I->eraseFromParent();
7773 assert(L &&
"Expecting CanonicalLoopInfo to be recognized as a loop");
7778 nullptr, ORE,
static_cast<int>(OptLevel),
7798 <<
" Threshold=" << UP.
Threshold <<
"\n"
7801 <<
" PartialOptSizeThreshold="
7821 Ptr =
Load->getPointerOperand();
7823 Ptr =
Store->getPointerOperand();
7830 if (Alloca->getParent() == &
F->getEntryBlock())
7850 int MaxTripCount = 0;
7851 bool MaxOrZero =
false;
7852 unsigned TripMultiple = 0;
7856 MaxTripCount, MaxOrZero, TripMultiple, UCE, UP, PP);
7857 LLVM_DEBUG(
dbgs() <<
"Suggesting unroll factor of " << Factor <<
"\n");
7868 assert(Factor >= 0 &&
"Unroll factor must not be negative");
7884 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst}));
7897 *UnrolledCLI =
Loop;
7902 "unrolling only makes sense with a factor of 2 or larger");
7904 Type *IndVarTy =
Loop->getIndVarType();
7911 std::vector<CanonicalLoopInfo *>
LoopNest =
7926 Ctx, {
MDString::get(Ctx,
"llvm.loop.unroll.count"), FactorConst})});
7929 (*UnrolledCLI)->assertOK();
7947 Value *Args[] = {Ident, ThreadId, BufSize, CpyBuf, CpyFn, DidItLD};
7966 if (!CPVars.
empty()) {
7971 Directive OMPD = Directive::OMPD_single;
7976 Value *Args[] = {Ident, ThreadId};
7985 if (
Error Err = FiniCB(IP))
8006 EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCBWrapper,
8013 for (
size_t I = 0, E = CPVars.
size();
I < E; ++
I)
8016 ConstantInt::get(Int64, 0), CPVars[
I],
8019 }
else if (!IsNowait) {
8022 omp::Directive::OMPD_unknown,
false,
8040 Directive::OMPD_scope,
nullptr,
nullptr,
8041 BodyGenCB, FiniCB,
false,
true,
8049 omp::Directive::OMPD_unknown,
8065 Directive OMPD = Directive::OMPD_critical;
8070 Value *LockVar = getOMPCriticalRegionLock(CriticalName);
8071 Value *Args[] = {Ident, ThreadId, LockVar};
8088 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
8096 const Twine &Name,
bool IsDependSource) {
8100 "OpenMP runtime requires depend vec with i64 type");
8113 for (
unsigned I = 0;
I < NumLoops; ++
I) {
8127 Value *Args[] = {Ident, ThreadId, DependBaseAddrGEP};
8145 Directive OMPD = Directive::OMPD_ordered_blockassoc;
8154 Value *Args[] = {Ident, ThreadId};
8164 return EmitOMPInlinedRegion(OMPD, EntryCall, ExitCall, BodyGenCB, FiniCB,
8171 bool HasFinalize,
bool IsCancellable) {
8178 BasicBlock *EntryBB = Builder.GetInsertBlock();
8187 emitCommonDirectiveEntry(OMPD, EntryCall, ExitBB, Conditional);
8199 "Unexpected control flow graph state!!");
8201 emitCommonDirectiveExit(OMPD, FinIP, ExitCall, HasFinalize);
8203 return AfterIP.takeError();
8208 "Unexpected Insertion point location!");
8211 auto InsertBB = merged ? ExitPredBB : ExitBB;
8214 Builder.SetInsertPoint(InsertBB);
8216 return Builder.saveIP();
8220 Directive OMPD,
Value *EntryCall, BasicBlock *ExitBB,
bool Conditional) {
8222 if (!Conditional || !EntryCall)
8228 auto *UI =
new UnreachableInst(
Builder.getContext(), ThenBB);
8238 Builder.CreateCondBr(CallBool, ThenBB, ExitBB);
8242 UI->eraseFromParent();
8250 omp::Directive OMPD,
InsertPointTy FinIP, Instruction *ExitCall,
8258 "Unexpected finalization stack state!");
8261 assert(Fi.DK == OMPD &&
"Unexpected Directive for Finalization call!");
8263 if (
Error Err = Fi.mergeFiniBB(
Builder, FinIP.getBlock()))
8264 return std::move(Err);
8268 Builder.SetInsertPoint(FinIP.getBlock()->getTerminator());
8278 return IRBuilder<>::InsertPoint(ExitCall->
getParent(),
8312 "copyin.not.master.end");
8319 Builder.SetInsertPoint(OMP_Entry);
8322 Value *cmp =
Builder.CreateICmpNE(MasterPtr, PrivatePtr);
8323 Builder.CreateCondBr(cmp, CopyBegin, CopyEnd);
8325 Builder.SetInsertPoint(CopyBegin);
8343 Value *Args[] = {ThreadId,
Size, Allocator};
8366 return Builder.CreateCall(Fn, Args, Name);
8380 Value *Args[] = {ThreadId, Addr, Allocator};
8387 const Twine &Name) {
8395 M.getContext(),
M.getDataLayout().getPrefTypeAlign(Int64)));
8401 const Twine &Name) {
8403 Loc,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)), Name);
8408 const Twine &Name) {
8414 return Builder.CreateCall(Fn, Args, Name);
8419 const Twine &Name) {
8421 Loc, Addr,
Builder.getInt64(
M.getDataLayout().getTypeAllocSize(VarType)),
8428 Value *DependenceAddress,
bool HaveNowaitClause) {
8438 else if (
Device->getType() != Int32)
8441 if (NumDependences ==
nullptr) {
8442 NumDependences = ConstantInt::get(Int32, 0);
8446 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8448 Ident, ThreadId, InteropVar, InteropTypeVal,
8449 Device, NumDependences, DependenceAddress, HaveNowaitClauseVal};
8458 Value *NumDependences,
Value *DependenceAddress,
bool HaveNowaitClause) {
8468 else if (
Device->getType() != Int32)
8470 if (NumDependences ==
nullptr) {
8471 NumDependences = ConstantInt::get(Int32, 0);
8475 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8477 Ident, ThreadId, InteropVar,
Device,
8478 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8487 Value *NumDependences,
8488 Value *DependenceAddress,
8489 bool HaveNowaitClause) {
8498 else if (
Device->getType() != Int32)
8500 if (NumDependences ==
nullptr) {
8501 NumDependences = ConstantInt::get(Int32, 0);
8505 Value *HaveNowaitClauseVal = ConstantInt::get(Int32, HaveNowaitClause);
8507 Ident, ThreadId, InteropVar,
Device,
8508 NumDependences, DependenceAddress, HaveNowaitClauseVal};
8538 assert(!Attrs.MaxThreads.empty() && !Attrs.MaxTeams.empty() &&
8539 "expected num_threads and num_teams to be specified");
8559 const std::string DebugPrefix =
"_debug__";
8560 if (KernelName.
ends_with(DebugPrefix)) {
8561 KernelName = KernelName.
drop_back(DebugPrefix.length());
8562 Kernel =
M.getFunction(KernelName);
8568 if (Attrs.MinTeams.front() > 1 || Attrs.MaxTeams.front() > 0)
8570 Attrs.MaxTeams.front());
8574 int32_t MaxThreadsVal = Attrs.MaxThreads.front();
8579 Attrs.MinThreads.front());
8581 MaxThreadsVal = Attrs.MinThreads.front();
8585 if (MaxThreadsVal > 0)
8598 omp::RuntimeFunction::OMPRTL___kmpc_target_init);
8601 Twine DynamicEnvironmentName = KernelName +
"_dynamic_environment";
8602 Constant *DynamicEnvironmentInitializer =
8606 DynamicEnvironmentInitializer, DynamicEnvironmentName,
8608 DL.getDefaultGlobalsAddressSpace());
8612 DynamicEnvironmentGV->
getType() == DynamicEnvironmentPtr
8613 ? DynamicEnvironmentGV
8615 DynamicEnvironmentPtr);
8618 ConfigurationEnvironment, {
8619 UseGenericStateMachineVal,
8620 MayUseNestedParallelismVal,
8629 KernelEnvironment, {
8630 ConfigurationEnvironmentInitializer,
8634 std::string KernelEnvironmentName =
8635 (KernelName +
"_kernel_environment").str();
8638 KernelEnvironmentInitializer, KernelEnvironmentName,
8640 DL.getDefaultGlobalsAddressSpace());
8644 KernelEnvironmentGV->
getType() == KernelEnvironmentPtr
8645 ? KernelEnvironmentGV
8647 KernelEnvironmentPtr);
8648 Value *KernelLaunchEnvironment =
8651 KernelLaunchEnvironment =
8652 KernelLaunchEnvironment->
getType() == KernelLaunchEnvParamTy
8653 ? KernelLaunchEnvironment
8654 :
Builder.CreateAddrSpaceCast(KernelLaunchEnvironment,
8655 KernelLaunchEnvParamTy);
8657 Fn, {KernelEnvironment, KernelLaunchEnvironment});
8669 auto *UI =
Builder.CreateUnreachable();
8675 Builder.SetInsertPoint(WorkerExitBB);
8679 Builder.SetInsertPoint(CheckBBTI);
8680 Builder.CreateCondBr(ExecUserCode, UI->getParent(), WorkerExitBB);
8682 CheckBBTI->eraseFromParent();
8683 UI->eraseFromParent();
8691 int32_t TeamsReductionDataSize) {
8696 omp::RuntimeFunction::OMPRTL___kmpc_target_deinit);
8700 if (!TeamsReductionDataSize)
8706 const std::string DebugPrefix =
"_debug__";
8708 KernelName = KernelName.
drop_back(DebugPrefix.length());
8709 auto *KernelEnvironmentGV =
8710 M.getNamedGlobal((KernelName +
"_kernel_environment").str());
8711 assert(KernelEnvironmentGV &&
"Expected kernel environment global\n");
8712 auto *KernelEnvironmentInitializer = KernelEnvironmentGV->getInitializer();
8714 KernelEnvironmentInitializer,
8715 ConstantInt::get(Int32, TeamsReductionDataSize), {0, 7});
8716 KernelEnvironmentGV->setInitializer(NewInitializer);
8721 if (
Kernel.hasFnAttribute(Name)) {
8722 int32_t OldLimit =
Kernel.getFnAttributeAsParsedInteger(Name);
8728std::pair<int32_t, int32_t>
8730 int32_t ThreadLimit =
8731 Kernel.getFnAttributeAsParsedInteger(
"omp_target_thread_limit");
8734 const auto &Attr =
Kernel.getFnAttribute(
"amdgpu-flat-work-group-size");
8735 if (!Attr.isValid() || !Attr.isStringAttribute())
8736 return {0, ThreadLimit};
8737 auto [LBStr, UBStr] = Attr.getValueAsString().split(
',');
8740 return {0, ThreadLimit};
8741 UB = ThreadLimit ? std::min(ThreadLimit, UB) : UB;
8749 return {0, ThreadLimit ? std::min(ThreadLimit, UB) : UB};
8751 return {0, ThreadLimit};
8757 Kernel.addFnAttr(
"omp_target_thread_limit", std::to_string(UB));
8760 Kernel.addFnAttr(
"amdgpu-flat-work-group-size",
8768std::pair<int32_t, int32_t>
8771 return {0,
Kernel.getFnAttributeAsParsedInteger(
"omp_target_num_teams")};
8775 int32_t LB, int32_t UB) {
8783 Kernel.addFnAttr(
"omp_target_num_teams", std::to_string(LB));
8786void OpenMPIRBuilder::setOutlinedTargetRegionFunctionAttributes(
8795 else if (
T.isNVPTX())
8797 else if (
T.isSPIRV())
8803 StringRef EntryFnIDName) {
8804 if (
Config.isTargetDevice()) {
8805 assert(OutlinedFn &&
"The outlined function must exist if embedded");
8809 return new GlobalVariable(
8814Constant *OpenMPIRBuilder::createTargetRegionEntryAddr(
Function *OutlinedFn,
8815 StringRef EntryFnName) {
8819 assert(!
M.getGlobalVariable(EntryFnName,
true) &&
8820 "Named kernel already exists?");
8821 return new GlobalVariable(
8834 if (
Config.isTargetDevice() || !
Config.openMPOffloadMandatory()) {
8838 OutlinedFn = *CBResult;
8840 OutlinedFn =
nullptr;
8846 if (!IsOffloadEntry)
8849 std::string EntryFnIDName =
8851 ? std::string(EntryFnName)
8855 EntryFnName, EntryFnIDName);
8863 setOutlinedTargetRegionFunctionAttributes(OutlinedFn);
8864 auto OutlinedFnID = createOutlinedFunctionID(OutlinedFn, EntryFnIDName);
8865 auto EntryAddr = createTargetRegionEntryAddr(OutlinedFn, EntryFnName);
8867 EntryInfo, EntryAddr, OutlinedFnID,
8869 return OutlinedFnID;
8887 bool IsStandAlone = !BodyGenCB;
8894 MapInfo = &GenMapInfoCB(
Builder.saveIP());
8896 AllocaIP,
Builder.saveIP(), *MapInfo, Info, CustomMapperCB,
8897 true, DeviceAddrCB))
8904 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
8914 SrcLocInfo, DeviceID,
8921 assert(MapperFunc &&
"MapperFunc missing for standalone target data");
8925 if (Info.HasNoWait) {
8935 if (Info.HasNoWait) {
8939 emitBlock(OffloadContBlock, CurFn,
true);
8945 bool RequiresOuterTargetTask = Info.HasNoWait;
8946 if (!RequiresOuterTargetTask)
8947 cantFail(TaskBodyCB(
nullptr,
nullptr,
8951 {}, RTArgs, Info.HasNoWait));
8954 omp::OMPRTL___tgt_target_data_begin_mapper);
8958 for (
auto DeviceMap : Info.DevicePtrInfoMap) {
8962 Builder.CreateStore(LI, DeviceMap.second.second);
8999 Value *PointerNum =
Builder.getInt32(Info.NumberOfPtrs);
9008 Value *OffloadingArgs[] = {SrcLocInfo, DeviceID,
9031 return emitIfClause(IfCond, BeginThenGen, BeginElseGen, AllocaIP);
9032 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9047 return emitIfClause(IfCond, EndThenGen, EndElseGen, AllocaIP);
9048 return EndThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9051 return emitIfClause(IfCond, BeginThenGen, EndElseGen, AllocaIP);
9052 return BeginThenGen(AllocaIP,
Builder.saveIP(), DeallocBlocks);
9063 bool IsGPUDistribute) {
9064 assert((IVSize == 32 || IVSize == 64) &&
9065 "IV size is not compatible with the omp runtime");
9067 if (IsGPUDistribute)
9069 ? (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_4
9070 : omp::OMPRTL___kmpc_distribute_static_init_4u)
9071 : (IVSigned ? omp::OMPRTL___kmpc_distribute_static_init_8
9072 : omp::OMPRTL___kmpc_distribute_static_init_8u);
9074 Name = IVSize == 32 ? (IVSigned ? omp::OMPRTL___kmpc_for_static_init_4
9075 : omp::OMPRTL___kmpc_for_static_init_4u)
9076 : (IVSigned ? omp::OMPRTL___kmpc_for_static_init_8
9077 : omp::OMPRTL___kmpc_for_static_init_8u);
9084 assert((IVSize == 32 || IVSize == 64) &&
9085 "IV size is not compatible with the omp runtime");
9087 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_4
9088 : omp::OMPRTL___kmpc_dispatch_init_4u)
9089 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_init_8
9090 : omp::OMPRTL___kmpc_dispatch_init_8u);
9097 assert((IVSize == 32 || IVSize == 64) &&
9098 "IV size is not compatible with the omp runtime");
9100 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_4
9101 : omp::OMPRTL___kmpc_dispatch_next_4u)
9102 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_next_8
9103 : omp::OMPRTL___kmpc_dispatch_next_8u);
9110 assert((IVSize == 32 || IVSize == 64) &&
9111 "IV size is not compatible with the omp runtime");
9113 ? (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_4
9114 : omp::OMPRTL___kmpc_dispatch_fini_4u)
9115 : (IVSigned ? omp::OMPRTL___kmpc_dispatch_fini_8
9116 : omp::OMPRTL___kmpc_dispatch_fini_8u);
9127 DenseMap<
Value *, std::tuple<Value *, unsigned>> &ValueReplacementMap) {
9135 auto GetUpdatedDIVariable = [&](
DILocalVariable *OldVar,
unsigned arg) {
9139 if (NewVar && (arg == NewVar->
getArg()))
9149 auto UpdateDebugRecord = [&](
auto *DR) {
9152 for (
auto Loc : DR->location_ops()) {
9153 auto Iter = ValueReplacementMap.find(
Loc);
9154 if (Iter != ValueReplacementMap.end()) {
9155 DR->replaceVariableLocationOp(
Loc, std::get<0>(Iter->second));
9156 ArgNo = std::get<1>(Iter->second) + 1;
9160 DR->setVariable(GetUpdatedDIVariable(OldVar, ArgNo));
9165 if (DVR->getNumVariableLocationOps() != 1u) {
9166 DVR->setKillLocation();
9169 Value *
Loc = DVR->getVariableLocationOp(0u);
9176 RequiredBB = &DVR->getFunction()->getEntryBlock();
9178 if (RequiredBB && RequiredBB != CurBB) {
9190 "Unexpected debug intrinsic");
9192 UpdateDebugRecord(&DVR);
9193 MoveDebugRecordToCorrectBlock(&DVR);
9196 for (
auto *DVR : DVRsToDelete)
9197 DVR->getMarker()->MarkedInstr->dropOneDbgRecord(DVR);
9201 Module *M = Func->getParent();
9204 DB.createQualifiedType(dwarf::DW_TAG_pointer_type,
nullptr);
9205 unsigned ArgNo = Func->arg_size();
9207 NewSP,
"dyn_ptr", ArgNo, NewSP->
getFile(), 0, VoidPtrTy,
9208 false, DINode::DIFlags::FlagArtificial);
9210 Argument *LastArg = Func->getArg(Func->arg_size() - 1);
9211 DB.insertDeclare(LastArg, Var, DB.createExpression(),
Loc,
9232 for (
auto &Arg : Inputs)
9233 ParameterTypes.
push_back(Arg->getType()->isPointerTy()
9237 for (
auto &Arg : Inputs)
9238 ParameterTypes.
push_back(Arg->getType());
9246 auto BB = Builder.GetInsertBlock();
9247 auto M = BB->getModule();
9258 if (TargetCpuAttr.isStringAttribute())
9259 Func->addFnAttr(TargetCpuAttr);
9261 auto TargetFeaturesAttr = ParentFn->
getFnAttribute(
"target-features");
9262 if (TargetFeaturesAttr.isStringAttribute())
9263 Func->addFnAttr(TargetFeaturesAttr);
9268 OMPBuilder.
emitUsed(
"llvm.compiler.used", {ExecMode});