108#define DEBUG_TYPE "amdgpu-sw-lower-lds"
109#define COV5_HIDDEN_DYN_LDS_SIZE_ARG 15
117 AsanInstrumentLDS(
"amdgpu-asan-instrument-lds",
118 cl::desc(
"Run asan instrumentation on LDS instructions "
119 "lowered to global memory"),
124struct LDSAccessTypeInfo {
132struct KernelLDSParameters {
136 LDSAccessTypeInfo DirectAccess;
137 LDSAccessTypeInfo IndirectAccess;
139 LDSToReplacementIndicesMap;
147struct NonKernelLDSParameters {
154struct AsanInstrumentInfo {
160struct FunctionsAndLDSAccess {
168class AMDGPUSwLowerLDS {
170 AMDGPUSwLowerLDS(
Module &
Mod, DomTreeCallback Callback)
171 : M(
Mod), IRB(M), DTCallback(Callback) {}
173 void getUsesOfLDSByNonKernels();
174 void getNonKernelsWithLDSArguments(
const CallGraph &CG);
179 void buildSwLDSGlobal(
Function *Func);
180 void buildSwDynLDSGlobal(
Function *Func);
181 void populateSwMetadataGlobal(
Function *Func);
182 void populateSwLDSAttributeAndMetadata(
Function *Func);
183 void populateLDSToReplacementIndicesMap(
Function *Func);
184 void getLDSMemoryInstructions(
Function *Func,
186 void replaceKernelLDSAccesses(
Function *Func);
187 Value *getTranslatedGlobalMemoryPtrOfLDS(
Value *LoadMallocPtr,
Value *LDSPtr);
190 void translateLDSMemoryOperationsToGlobalMemory(
195 void buildNonKernelLDSOffsetTable(NonKernelLDSParameters &NKLDSParams);
196 void buildNonKernelLDSBaseTable(NonKernelLDSParameters &NKLDSParams);
198 getAddressesOfVariablesInKernel(
Function *Func,
200 void lowerNonKernelLDSAccesses(
Function *Func,
202 NonKernelLDSParameters &NKLDSParams);
204 updateMallocSizeForDynamicLDS(
Function *Func,
Value **CurrMallocSize,
205 Value *HiddenDynLDSSize,
212 DomTreeCallback DTCallback;
213 FunctionsAndLDSAccess FuncLDSAccessInfo;
214 AsanInstrumentInfo AsanInfo;
217template <
typename T>
SetVector<T> sortByName(std::vector<T> &&V) {
220 sort(V, [](
const auto *L,
const auto *R) {
221 return L->getName() < R->getName();
230 std::vector<GlobalVariable *>(Variables.
begin(), Variables.
end()));
238 if (Kernels.size() > UINT32_MAX) {
242 sortByName(std::vector<Function *>(Kernels.begin(), Kernels.end()));
243 for (
size_t i = 0; i < Kernels.size(); i++) {
248 Func->setMetadata(
"llvm.amdgcn.lds.kernel.id",
251 return OrderedKernels;
254void AMDGPUSwLowerLDS::getNonKernelsWithLDSArguments(
const CallGraph &CG) {
258 for (
auto &
K : FuncLDSAccessInfo.KernelToLDSParametersMap) {
263 for (
auto &
I : *CGN) {
272 Type *ArgTy = (*AI).getType();
277 FuncLDSAccessInfo.NonKernelsWithLDSArgument.
insert(CalledFunc);
280 FuncLDSAccessInfo.KernelsWithIndirectLDSAccess.
insert(Func);
286void AMDGPUSwLowerLDS::getUsesOfLDSByNonKernels() {
287 for (
GlobalVariable *GV : FuncLDSAccessInfo.AllNonKernelLDSAccess) {
295 FuncLDSAccessInfo.NonKernelToLDSAccessMap[
F].
insert(GV);
309 ConstantInt::get(IntTy, Address + 1));
310 GV->
setMetadata(LLVMContext::MD_absolute_symbol, MetadataNode);
321 Func->addFnAttr(
"amdgpu-lds-size", Buffer);
330 Intrinsic::donothing, {});
332 Value *UseInstance[1] = {
333 Builder.CreateConstInBoundsGEP1_32(SGV->getValueType(), SGV, 0)};
335 Builder.CreateCall(Decl, {},
339void AMDGPUSwLowerLDS::buildSwLDSGlobal(
Function *Func) {
342 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
350 LDSParams.SwLDS->setSanitizerMetadata(MD);
353void AMDGPUSwLowerLDS::buildSwDynLDSGlobal(
Function *Func) {
355 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
356 if (LDSParams.DirectAccess.DynamicLDSGlobals.empty() &&
357 LDSParams.IndirectAccess.DynamicLDSGlobals.empty())
363 "llvm.amdgcn." + Func->getName() +
".dynlds",
nullptr,
365 markUsedByKernel(Func, LDSParams.SwDynLDS);
368 LDSParams.SwDynLDS->setSanitizerMetadata(MD);
371void AMDGPUSwLowerLDS::populateSwLDSAttributeAndMetadata(
Function *Func) {
372 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
373 bool IsDynLDSUsed = LDSParams.SwDynLDS;
375 recordLDSAbsoluteAddress(M, LDSParams.SwLDS, 0);
376 addLDSSizeAttribute(Func,
Offset, IsDynLDSUsed);
377 if (LDSParams.SwDynLDS)
378 recordLDSAbsoluteAddress(M, LDSParams.SwDynLDS,
Offset);
381void AMDGPUSwLowerLDS::populateSwMetadataGlobal(
Function *Func) {
384 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
385 auto &Ctx = M.getContext();
386 auto &
DL = M.getDataLayout();
387 std::vector<Type *> Items;
389 std::vector<Constant *> Initializers;
390 Align MaxAlignment(1);
393 MaxAlignment = std::max(MaxAlignment, GVAlign);
396 for (
GlobalVariable *GV : LDSParams.DirectAccess.StaticLDSGlobals)
397 UpdateMaxAlignment(GV);
399 for (
GlobalVariable *GV : LDSParams.DirectAccess.DynamicLDSGlobals)
400 UpdateMaxAlignment(GV);
402 for (
GlobalVariable *GV : LDSParams.IndirectAccess.StaticLDSGlobals)
403 UpdateMaxAlignment(GV);
405 for (
GlobalVariable *GV : LDSParams.IndirectAccess.DynamicLDSGlobals)
406 UpdateMaxAlignment(GV);
411 MDItemOS <<
"llvm.amdgcn.sw.lds." << Func->getName() <<
".md.item";
415 uint32_t &MallocSize = LDSParams.MallocSize;
417 int AsanScale = AsanInfo.Scale;
418 auto buildInitializerForSwLDSMD =
420 for (
auto &GV : LDSGlobals) {
423 UniqueLDSGlobals.
insert(GV);
426 const uint64_t SizeInBytes =
DL.getTypeAllocSize(Ty);
427 Items.push_back(LDSItemTy);
428 Constant *ItemStartOffset = ConstantInt::get(Int32Ty, MallocSize);
429 Constant *SizeInBytesConst = ConstantInt::get(Int32Ty, SizeInBytes);
434 MallocSize += SizeInBytes;
436 LDSParams.RedzoneOffsetAndSizeVector.emplace_back(MallocSize,
438 MallocSize += RightRedzoneSize;
441 alignTo(SizeInBytes + RightRedzoneSize, MaxAlignment);
443 ConstantInt::get(Int32Ty, AlignedSize);
445 MallocSize =
alignTo(MallocSize, MaxAlignment);
448 AlignedSizeInBytesConst});
449 Initializers.push_back(InitItem);
453 SwLDSVector.
insert(LDSParams.SwLDS);
454 buildInitializerForSwLDSMD(SwLDSVector);
455 buildInitializerForSwLDSMD(LDSParams.DirectAccess.StaticLDSGlobals);
456 buildInitializerForSwLDSMD(LDSParams.IndirectAccess.StaticLDSGlobals);
457 buildInitializerForSwLDSMD(LDSParams.DirectAccess.DynamicLDSGlobals);
458 buildInitializerForSwLDSMD(LDSParams.IndirectAccess.DynamicLDSGlobals);
461 Type *Ty = LDSParams.SwLDS->getValueType();
462 const uint64_t SizeInBytes =
DL.getTypeAllocSize(Ty);
464 LDSParams.LDSSize = AlignedSize;
467 MDTypeOS <<
"llvm.amdgcn.sw.lds." << Func->getName() <<
".md.type";
472 MDOS <<
"llvm.amdgcn.sw.lds." << Func->getName() <<
".md";
478 LDSParams.SwLDSMetadata->setInitializer(
data);
481 LDSParams.SwLDS->setAlignment(MaxAlignment);
482 if (LDSParams.SwDynLDS)
483 LDSParams.SwDynLDS->setAlignment(MaxAlignment);
486 LDSParams.SwLDSMetadata->setSanitizerMetadata(MD);
489void AMDGPUSwLowerLDS::populateLDSToReplacementIndicesMap(
Function *Func) {
492 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
496 for (
auto &GV : LDSGlobals) {
499 UniqueLDSGlobals.
insert(GV);
500 LDSParams.LDSToReplacementIndicesMap[GV] = {0,
Idx, 0};
506 SwLDSVector.
insert(LDSParams.SwLDS);
507 PopulateIndices(SwLDSVector,
Idx);
508 PopulateIndices(LDSParams.DirectAccess.StaticLDSGlobals,
Idx);
509 PopulateIndices(LDSParams.IndirectAccess.StaticLDSGlobals,
Idx);
510 PopulateIndices(LDSParams.DirectAccess.DynamicLDSGlobals,
Idx);
511 PopulateIndices(LDSParams.IndirectAccess.DynamicLDSGlobals,
Idx);
515 Value *Replacement) {
517 auto ReplaceUsesLambda = [Func](
const Use &U) ->
bool {
518 auto *V = U.getUser();
520 auto *Func1 = Inst->getFunction();
529void AMDGPUSwLowerLDS::replaceKernelLDSAccesses(
Function *Func) {
530 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
538 auto &IndirectAccess = LDSParams.IndirectAccess;
539 auto &DirectAccess = LDSParams.DirectAccess;
543 for (
auto &GV : LDSGlobals) {
546 if ((IndirectAccess.StaticLDSGlobals.contains(GV) ||
547 IndirectAccess.DynamicLDSGlobals.contains(GV)) &&
548 (!DirectAccess.StaticLDSGlobals.contains(GV) &&
549 !DirectAccess.DynamicLDSGlobals.contains(GV)))
553 UniqueLDSGlobals.
insert(GV);
554 auto &Indices = LDSParams.LDSToReplacementIndicesMap[GV];
555 assert(Indices.size() == 3);
556 Constant *GEPIdx[] = {ConstantInt::get(Int32Ty, Indices[0]),
557 ConstantInt::get(Int32Ty, Indices[1]),
558 ConstantInt::get(Int32Ty, Indices[2])};
560 Func->getDataLayout(), SwLDSMetadataStructType, SwLDSMetadata, GEPIdx,
563 Value *BasePlusOffset =
567 replacesUsesOfGlobalInFunction(Func, GV, BasePlusOffset);
570 ReplaceLDSGlobalUses(DirectAccess.StaticLDSGlobals);
571 ReplaceLDSGlobalUses(IndirectAccess.StaticLDSGlobals);
572 ReplaceLDSGlobalUses(DirectAccess.DynamicLDSGlobals);
573 ReplaceLDSGlobalUses(IndirectAccess.DynamicLDSGlobals);
576void AMDGPUSwLowerLDS::updateMallocSizeForDynamicLDS(
579 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
584 assert(SwLDS && SwLDSMetadata);
589 Value *MaxAlignValueMinusOne = IRB.
getInt32(MaxAlignment - 1);
592 auto &Indices = LDSParams.LDSToReplacementIndicesMap[DynGV];
594 Constant *Index0 = ConstantInt::get(Int32Ty, 0);
595 Constant *Index1 = ConstantInt::get(Int32Ty, Indices[1]);
597 Constant *Index2Offset = ConstantInt::get(Int32Ty, 0);
599 MetadataStructType, SwLDSMetadata, {Index0, Index1, Index2Offset});
603 Constant *Index2Size = ConstantInt::get(Int32Ty, 1);
605 {Index0, Index1, Index2Size});
609 Constant *Index2AlignedSize = ConstantInt::get(Int32Ty, 2);
611 MetadataStructType, SwLDSMetadata, {Index0, Index1, Index2AlignedSize});
613 Value *AlignedDynLDSSize =
614 IRB.
CreateAdd(CurrDynLDSSize, MaxAlignValueMinusOne);
615 AlignedDynLDSSize = IRB.
CreateUDiv(AlignedDynLDSSize, MaxAlignValue);
616 AlignedDynLDSSize = IRB.
CreateMul(AlignedDynLDSSize, MaxAlignValue);
617 IRB.
CreateStore(AlignedDynLDSSize, GEPForAlignedSize);
620 *CurrMallocSize = IRB.
CreateAdd(*CurrMallocSize, AlignedDynLDSSize);
634void AMDGPUSwLowerLDS::getLDSMemoryInstructions(
640 LDSInstructions.
insert(&Inst);
643 LDSInstructions.
insert(&Inst);
646 LDSInstructions.
insert(&Inst);
649 LDSInstructions.
insert(&Inst);
651 unsigned SrcAS = ASC->getSrcAddressSpace();
652 unsigned DstAS = ASC->getDestAddressSpace();
657 LDSInstructions.
insert(&Inst);
660 LDSInstructions.
insert(&Inst);
663 LDSInstructions.
insert(&Inst);
671Value *AMDGPUSwLowerLDS::getTranslatedGlobalMemoryPtrOfLDS(
Value *LoadMallocPtr,
673 assert(LDSPtr &&
"Invalid LDS pointer operand");
690Value *AMDGPUSwLowerLDS::getTranslatedLDSPtrOfFlat(
Value *LoadMallocPtr,
707void AMDGPUSwLowerLDS::translateLDSMemoryOperationsToGlobalMemory(
710 LLVM_DEBUG(
dbgs() <<
"Translating LDS memory operations to global memory : "
715 Value *LIOperand = LI->getPointerOperand();
717 getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, LIOperand);
719 IRB.
CreateLoad(LI->getType(), Replacement, LI->getProperties());
720 AsanInfo.Instructions.
insert(NewLI);
721 LI->replaceAllUsesWith(NewLI);
722 LI->eraseFromParent();
724 Value *SIOperand =
SI->getPointerOperand();
726 getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, SIOperand);
728 SI->getProperties());
729 AsanInfo.Instructions.
insert(NewSI);
730 SI->replaceAllUsesWith(NewSI);
731 SI->eraseFromParent();
733 Value *RMWPtrOperand = RMW->getPointerOperand();
734 Value *RMWValOperand = RMW->getValOperand();
736 getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, RMWPtrOperand);
738 RMW->getOperation(), Replacement, RMWValOperand, RMW->getAlign(),
739 RMW->getOrdering(), RMW->getSyncScopeID());
741 AsanInfo.Instructions.
insert(NewRMW);
742 RMW->replaceAllUsesWith(NewRMW);
743 RMW->eraseFromParent();
745 Value *XCHGPtrOperand = XCHG->getPointerOperand();
747 getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, XCHGPtrOperand);
749 Replacement, XCHG->getCompareOperand(), XCHG->getNewValOperand(),
750 XCHG->getAlign(), XCHG->getSuccessOrdering(),
751 XCHG->getFailureOrdering(), XCHG->getSyncScopeID());
753 AsanInfo.Instructions.
insert(NewXCHG);
754 XCHG->replaceAllUsesWith(NewXCHG);
755 XCHG->eraseFromParent();
757 Value *NewDest =
MI->getRawDest();
759 NewDest = getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, NewDest);
762 if (
MI->isAtomic()) {
764 NewDest, MSI->getValue(), MSI->getLength(),
765 MSI->getDestAlign().valueOrOne(), MSI->getElementSizeInBytes());
767 NewMI = IRB.
CreateMemSet(NewDest, MSI->getValue(), MSI->getLength(),
772 Value *NewSrc = MTI->getRawSource();
774 NewSrc = getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, NewSrc);
775 if (
MI->isAtomic()) {
776 if (
MI->getIntrinsicID() ==
777 Intrinsic::memmove_element_unordered_atomic) {
779 NewDest, MTI->getDestAlign().valueOrOne(), NewSrc,
780 MTI->getSourceAlign().valueOrOne(), MTI->getLength(),
781 MTI->getElementSizeInBytes());
784 NewDest, MTI->getDestAlign().valueOrOne(), NewSrc,
785 MTI->getSourceAlign().valueOrOne(), MTI->getLength(),
786 MTI->getElementSizeInBytes());
790 MI->getIntrinsicID(), NewDest, MTI->getDestAlign(), NewSrc,
791 MTI->getSourceAlign(), MTI->getLength(),
796 AsanInfo.Instructions.
insert(NewMI);
797 MI->replaceAllUsesWith(NewMI);
798 MI->eraseFromParent();
800 Value *AIOperand = ASC->getPointerOperand();
801 Value *NewAI =
nullptr;
804 getTranslatedLDSPtrOfFlat(LoadMallocPtr, AIOperand, ASC->
getType());
807 getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, AIOperand);
814 ASC->eraseFromParent();
820void AMDGPUSwLowerLDS::poisonRedzones(
Function *Func,
Value *MallocPtr) {
821 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
825 "__asan_poison_region",
828 auto RedzonesVec = LDSParams.RedzoneOffsetAndSizeVector;
829 size_t VecSize = RedzonesVec.size();
830 for (
unsigned i = 0; i < VecSize; i++) {
831 auto &RedzonePair = RedzonesVec[i];
832 uint64_t RedzoneOffset = RedzonePair.first;
833 uint64_t RedzoneSize = RedzonePair.second;
835 IRB.
getInt8Ty(), MallocPtr, {IRB.getInt64(RedzoneOffset)});
838 {RedzoneAddress, IRB.
getInt64(RedzoneSize)});
842void AMDGPUSwLowerLDS::lowerKernelLDSAccesses(
Function *Func,
844 LLVM_DEBUG(
dbgs() <<
"Sw Lowering Kernel LDS for : " << Func->getName());
845 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
846 auto &Ctx = M.getContext();
847 auto *PrevEntryBlock = &Func->getEntryBlock();
849 getLDSMemoryInstructions(Func, LDSInstructions);
863 auto SplitIt = PrevEntryBlock->getFirstNonPHIOrDbgOrAlloca();
864 WIdBlock->splice(WIdBlock->end(), PrevEntryBlock, PrevEntryBlock->begin(),
869 AI->moveBefore(*WIdBlock, WIdBlock->end());
884 IRB.
CreateCondBr(WIdzCond, MallocBlock, PrevEntryBlock);
894 assert(SwLDS && SwLDSMetadata);
902 for (
auto &GV : LDSGlobals) {
905 UniqueLDSGlobals.
insert(GV);
909 GetUniqueLDSGlobals(LDSParams.DirectAccess.StaticLDSGlobals);
910 GetUniqueLDSGlobals(LDSParams.IndirectAccess.StaticLDSGlobals);
913 unsigned LastStaticLDSIdx = UniqueLDSGlobals.
size();
914 UniqueLDSGlobals.
clear();
916 auto *GEPForEndStaticLDSOffset =
918 {ConstantInt::get(Int32Ty, 0),
919 ConstantInt::get(Int32Ty, LastStaticLDSIdx),
920 ConstantInt::get(Int32Ty, 0)});
922 auto *GEPForEndStaticLDSSize =
924 {ConstantInt::get(Int32Ty, 0),
925 ConstantInt::get(Int32Ty, LastStaticLDSIdx),
926 ConstantInt::get(Int32Ty, 2)});
928 Value *EndStaticLDSOffset = IRB.
CreateLoad(Int32Ty, GEPForEndStaticLDSOffset);
929 Value *EndStaticLDSSize = IRB.
CreateLoad(Int32Ty, GEPForEndStaticLDSSize);
930 Value *CurrMallocSize = IRB.
CreateAdd(EndStaticLDSOffset, EndStaticLDSSize);
932 if (LDSParams.SwDynLDS) {
935 "Dynamic LDS size query is only supported for CO V5 and later.");
941 {ConstantInt::get(Int64Ty, COV5_HIDDEN_DYN_LDS_SIZE_ARG)});
942 UniqueLDSGlobals.
clear();
943 GetUniqueLDSGlobals(LDSParams.DirectAccess.DynamicLDSGlobals);
944 GetUniqueLDSGlobals(LDSParams.IndirectAccess.DynamicLDSGlobals);
945 updateMallocSizeForDynamicLDS(Func, &CurrMallocSize, HiddenDynLDSSize,
949 CurrMallocSize = IRB.
CreateZExt(CurrMallocSize, Int64Ty);
954 Intrinsic::returnaddress, IRB.
getPtrTy(
DL.getProgramAddressSpace()),
960 Value *MallocCall = IRB.
CreateCall(MallocFunc, {CurrMallocSize, RAPtrToInt});
969 poisonRedzones(Func, MallocPtr);
977 auto *XYZCondPhi = IRB.
CreatePHI(Int1Ty, 2,
"xyzCond");
979 XYZCondPhi->addIncoming(IRB.
getInt1(1), MallocBlock);
984 Value *LoadMallocPtr =
988 replaceKernelLDSAccesses(Func);
992 translateLDSMemoryOperationsToGlobalMemory(Func, LoadMallocPtr,
1001 RI->eraseFromParent();
1021 Intrinsic::returnaddress, IRB.
getPtrTy(
DL.getProgramAddressSpace()),
1025 IRB.
CreateCall(AsanFreeFunc, {MallocPtrToInt, RAPToInt});
1039Constant *AMDGPUSwLowerLDS::getAddressesOfVariablesInKernel(
1042 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
1046 auto *SwLDSMetadataStructType =
1052 for (
auto *GV : Variables) {
1053 auto It = LDSParams.LDSToReplacementIndicesMap.find(GV);
1054 if (It == LDSParams.LDSToReplacementIndicesMap.end()) {
1059 auto &Indices = It->second;
1060 Constant *GEPIdx[] = {ConstantInt::get(Int32Ty, Indices[0]),
1061 ConstantInt::get(Int32Ty, Indices[1]),
1062 ConstantInt::get(Int32Ty, Indices[2])};
1064 Func->getDataLayout(), SwLDSMetadataStructType, SwLDSMetadata, GEPIdx,
1066 Elements.push_back(
GEP);
1071void AMDGPUSwLowerLDS::buildNonKernelLDSBaseTable(
1072 NonKernelLDSParameters &NKLDSParams) {
1076 auto &Kernels = NKLDSParams.OrderedKernels;
1077 if (Kernels.empty())
1079 const size_t NumberKernels = Kernels.size();
1082 std::vector<Constant *> OverallConstantExprElts(NumberKernels);
1083 for (
size_t i = 0; i < NumberKernels; i++) {
1085 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
1086 OverallConstantExprElts[i] = LDSParams.SwLDS;
1099void AMDGPUSwLowerLDS::buildNonKernelLDSOffsetTable(
1100 NonKernelLDSParameters &NKLDSParams) {
1108 auto &Variables = NKLDSParams.OrdereLDSGlobals;
1109 auto &Kernels = NKLDSParams.OrderedKernels;
1110 if (Variables.
empty() || Kernels.empty())
1112 const size_t NumberVariables = Variables.
size();
1113 const size_t NumberKernels = Kernels.size();
1120 std::vector<Constant *> overallConstantExprElts(NumberKernels);
1121 for (
size_t i = 0; i < NumberKernels; i++) {
1123 overallConstantExprElts[i] =
1124 getAddressesOfVariablesInKernel(Func, Variables);
1137void AMDGPUSwLowerLDS::lowerNonKernelLDSAccesses(
1139 NonKernelLDSParameters &NKLDSParams) {
1142 LLVM_DEBUG(
dbgs() <<
"Sw LDS lowering, lower non-kernel access for : "
1143 << Func->getName());
1144 auto InsertAt = Func->getEntryBlock().getFirstNonPHIOrDbgOrAlloca();
1149 getLDSMemoryInstructions(Func, LDSInstructions);
1151 auto *KernelId = IRB.
CreateIntrinsic(Intrinsic::amdgcn_lds_kernel_id, {});
1154 auto &OrdereLDSGlobals = NKLDSParams.OrdereLDSGlobals;
1156 LDSBaseTable->
getValueType(), LDSBaseTable, {IRB.getInt32(0), KernelId});
1159 Value *LoadMallocPtr =
1163 const auto *GVIt =
llvm::find(OrdereLDSGlobals, GV);
1164 assert(GVIt != OrdereLDSGlobals.end());
1165 uint32_t GVOffset = std::distance(OrdereLDSGlobals.begin(), GVIt);
1169 {IRB.getInt32(0), KernelId, IRB.getInt32(GVOffset)});
1173 Value *BasePlusOffset =
1175 LLVM_DEBUG(
dbgs() <<
"Sw LDS Lowering, Replace non-kernel LDS for "
1177 replacesUsesOfGlobalInFunction(Func, GV, BasePlusOffset);
1179 translateLDSMemoryOperationsToGlobalMemory(Func, LoadMallocPtr,
1183static void reorderStaticDynamicIndirectLDSSet(KernelLDSParameters &LDSParams) {
1186 auto &DirectAccess = LDSParams.DirectAccess;
1187 auto &IndirectAccess = LDSParams.IndirectAccess;
1188 LDSParams.DirectAccess.StaticLDSGlobals = sortByName(
1189 std::vector<GlobalVariable *>(DirectAccess.StaticLDSGlobals.begin(),
1190 DirectAccess.StaticLDSGlobals.end()));
1191 LDSParams.DirectAccess.DynamicLDSGlobals = sortByName(
1192 std::vector<GlobalVariable *>(DirectAccess.DynamicLDSGlobals.begin(),
1193 DirectAccess.DynamicLDSGlobals.end()));
1194 LDSParams.IndirectAccess.StaticLDSGlobals = sortByName(
1195 std::vector<GlobalVariable *>(IndirectAccess.StaticLDSGlobals.begin(),
1196 IndirectAccess.StaticLDSGlobals.end()));
1197 LDSParams.IndirectAccess.DynamicLDSGlobals = sortByName(
1198 std::vector<GlobalVariable *>(IndirectAccess.DynamicLDSGlobals.begin(),
1199 IndirectAccess.DynamicLDSGlobals.end()));
1202void AMDGPUSwLowerLDS::initAsanInfo() {
1208 bool OrShadowOffset;
1210 &Scale, &OrShadowOffset);
1211 AsanInfo.Scale = Scale;
1212 AsanInfo.Offset =
Offset;
1216 for (
auto &
K : LDSAccesses) {
1220 if (
F->hasFnAttribute(Attribute::SanitizeAddress))
1226bool AMDGPUSwLowerLDS::run() {
1239 bool LowerAllLDS = hasFnWithSanitizeAddressAttr(LDSUsesInfo.
DirectAccess) ||
1247 bool DirectAccess) {
1248 for (
auto &
K : LDSAccesses) {
1250 if (!
F ||
K.second.empty())
1256 FuncLDSAccessInfo.KernelToLDSParametersMap.insert(
1257 {
F, KernelLDSParameters()});
1259 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[
F];
1261 FuncLDSAccessInfo.KernelsWithIndirectLDSAccess.
insert(
F);
1263 if (!DirectAccess) {
1265 LDSParams.IndirectAccess.DynamicLDSGlobals.insert(GV);
1267 LDSParams.IndirectAccess.StaticLDSGlobals.insert(GV);
1268 FuncLDSAccessInfo.AllNonKernelLDSAccess.insert(GV);
1271 LDSParams.DirectAccess.DynamicLDSGlobals.insert(GV);
1273 LDSParams.DirectAccess.StaticLDSGlobals.insert(GV);
1279 PopulateKernelStaticDynamicLDS(LDSUsesInfo.
DirectAccess,
true);
1280 PopulateKernelStaticDynamicLDS(LDSUsesInfo.
IndirectAccess,
false);
1285 for (
auto &
K : FuncLDSAccessInfo.KernelToLDSParametersMap) {
1287 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
1288 if (LDSParams.DirectAccess.StaticLDSGlobals.empty() &&
1289 LDSParams.DirectAccess.DynamicLDSGlobals.empty() &&
1290 LDSParams.IndirectAccess.StaticLDSGlobals.empty() &&
1291 LDSParams.IndirectAccess.DynamicLDSGlobals.empty())
1296 {
"amdgpu-no-workitem-id-x",
"amdgpu-no-workitem-id-y",
1297 "amdgpu-no-workitem-id-z",
"amdgpu-no-heap-ptr"});
1298 if (!LDSParams.IndirectAccess.StaticLDSGlobals.empty() ||
1299 !LDSParams.IndirectAccess.DynamicLDSGlobals.empty())
1301 reorderStaticDynamicIndirectLDSSet(LDSParams);
1302 buildSwLDSGlobal(Func);
1303 buildSwDynLDSGlobal(Func);
1304 populateSwMetadataGlobal(Func);
1305 populateSwLDSAttributeAndMetadata(Func);
1306 populateLDSToReplacementIndicesMap(Func);
1307 DomTreeUpdater DTU(DTCallback(*Func), DomTreeUpdater::UpdateStrategy::Lazy);
1308 lowerKernelLDSAccesses(Func, DTU);
1313 getUsesOfLDSByNonKernels();
1316 getNonKernelsWithLDSArguments(CG);
1319 if (!FuncLDSAccessInfo.NonKernelToLDSAccessMap.
empty() ||
1320 !FuncLDSAccessInfo.NonKernelsWithLDSArgument.
empty()) {
1321 NonKernelLDSParameters NKLDSParams;
1322 NKLDSParams.OrderedKernels = getOrderedIndirectLDSAccessingKernels(
1323 FuncLDSAccessInfo.KernelsWithIndirectLDSAccess);
1324 NKLDSParams.OrdereLDSGlobals = getOrderedNonKernelAllLDSGlobals(
1325 FuncLDSAccessInfo.AllNonKernelLDSAccess);
1326 buildNonKernelLDSBaseTable(NKLDSParams);
1327 buildNonKernelLDSOffsetTable(NKLDSParams);
1328 for (
auto &
K : FuncLDSAccessInfo.NonKernelToLDSAccessMap) {
1332 std::vector<GlobalVariable *>(LDSGlobals.
begin(), LDSGlobals.
end()));
1333 lowerNonKernelLDSAccesses(Func, OrderedLDSGlobals, NKLDSParams);
1335 for (
Function *Func : FuncLDSAccessInfo.NonKernelsWithLDSArgument) {
1336 auto &
K = FuncLDSAccessInfo.NonKernelToLDSAccessMap;
1337 if (
K.contains(Func))
1340 lowerNonKernelLDSAccesses(Func, Vec, NKLDSParams);
1357 if (AsanInstrumentLDS) {
1364 for (
auto &Operand : OperandsToInstrument) {
1365 Value *Addr = Operand.getPtr();
1367 Operand.Alignment.valueOrOne(), Operand.TypeStoreSize,
1368 Operand.IsWrite,
nullptr,
false,
false, AsanInfo.Scale,
1377class AMDGPUSwLowerLDSLegacy :
public ModulePass {
1381 bool runOnModule(
Module &M)
override;
1388char AMDGPUSwLowerLDSLegacy::ID = 0;
1392 "AMDGPU Software lowering of LDS",
false,
false)
1397bool AMDGPUSwLowerLDSLegacy::runOnModule(
Module &M) {
1400 if (!M.getModuleFlag(
"nosanitize_address"))
1403 getAnalysisIfAvailable<DominatorTreeWrapperPass>();
1405 return DTW ? &DTW->getDomTree() : nullptr;
1408 AMDGPUSwLowerLDS SwLowerLDSImpl(M, DTCallback);
1409 bool IsChanged = SwLowerLDSImpl.run();
1414 return new AMDGPUSwLowerLDSLegacy();
1421 if (!M.getModuleFlag(
"nosanitize_address"))
1427 AMDGPUSwLowerLDS SwLowerLDSImpl(M, DTCallback);
1428 bool IsChanged = SwLowerLDSImpl.run();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file provides interfaces used to build and manipulate a call graph, which is a very useful tool ...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
if(auto Err=PB.parsePassPipeline(MPM, Passes)) return wrap(std MPM run * Mod
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
static DebugLoc getOrCreateDebugLoc(const Instruction *InsertBefore, DISubprogram *SP)
This class represents a conversion between pointers from one address space to another.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
This class represents any memset intrinsic.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
An instruction that atomically checks whether a specified value is in a memory location,...
void setVolatile(bool V)
Specify whether this is a volatile cmpxchg.
an instruction that atomically reads a memory location, combines it with another value,...
void setVolatile(bool V)
Specify whether this is a volatile RMW or not.
LLVM Basic Block Representation.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
A node in the call graph for a module.
Function * getFunction() const
Returns the function that this call graph node represents.
The basic data container for the call graph of a Module of IR.
This class represents a function call, abstracting a target machine's calling convention.
static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static LLVM_SUPPRESS_DEPRECATED_DECLARATIONS_PUSH Constant * getGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant * > IdxList, GEPNoWrapFlags NW=GEPNoWrapFlags::none(), std::optional< ConstantRange > InRange=std::nullopt, Type *OnlyIfReducedTy=nullptr)
Getelementptr form.
static LLVM_ABI Constant * getAddrSpaceCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static LLVM_ABI Constant * get(StructType *T, ArrayRef< Constant * > V)
This is an important base class in LLVM.
LLVM_ABI void removeDeadConstantUsers() const
If there are any dead constant users dangling off of this constant, remove them.
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
Subprogram description. Uses SubclassData1.
A parsed version of the target data layout string in and methods for querying it.
Implements a dense probed hash-table based set.
Analysis pass which computes a DominatorTree.
static constexpr UpdateKind Insert
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static GEPNoWrapFlags inBounds()
void applyUpdates(ArrayRef< UpdateT > Updates)
Submit updates to all available trees.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set a particular kind of metadata attachment.
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
LLVM_ABI void setSanitizerMetadata(SanitizerMetadata Meta)
@ InternalLinkage
Rename collisions when linking (static functions).
@ ExternalLinkage
Externally visible function.
Type * getValueType() const
MaybeAlign getAlign() const
Returns the alignment of the given variable.
LLVM_ABI void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
ConstantInt * getInt1(bool V)
Get a constant value representing either true or false.
Value * CreateAddrSpaceCast(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNull=false)
AtomicCmpXchgInst * CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New, MaybeAlign Align, AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering, SyncScope::ID SSID=SyncScope::System)
IntegerType * getInt1Ty()
Fetch the type representing a single bit.
CondBrInst * CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a conditional 'br Cond, TrueDest, FalseDest' instruction.
Value * CreatePtrToAddr(Value *V, const Twine &Name="")
LLVM_ABI Value * CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name="")
Return a vector value that contains.
LLVM_ABI Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
void SetCurrentDebugLocation(const DebugLoc &L)
Set location information used by debugging information.
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
IntegerType * getInt64Ty()
Fetch the type representing a 64-bit integer.
Value * CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="")
LLVM_ABI CallInst * CreateElementUnorderedAtomicMemMove(Value *Dst, Align DstAlign, Value *Src, Align SrcAlign, Value *Size, uint32_t ElementSize, const AAMDNodes &AAInfo=AAMDNodes())
Create and insert an element unordered-atomic memmove between the specified pointers.
Value * CreateUDiv(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
ConstantInt * getInt64(uint64_t C)
Get a constant 64-bit value.
UncondBrInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
CallInst * CreateElementUnorderedAtomicMemSet(Value *Ptr, Value *Val, uint64_t Size, Align Alignment, uint32_t ElementSize, const AAMDNodes &AAInfo=AAMDNodes())
Create and insert an element unordered-atomic memset of the region of memory starting at the given po...
CallInst * CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, MaybeAlign Align, bool isVolatile=false, const AAMDNodes &AAInfo=AAMDNodes())
Create and insert a memset to the specified pointer and the specified value.
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
ReturnInst * CreateRetVoid()
Create a 'ret void' instruction.
LLVM_ABI Value * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={}, function_ref< void(CallInst *)> SetFn=[](CallInst *) {})
Variant to create a possibly constant-folded intrinsic.
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
Value * CreateIsNull(Value *Arg, const Twine &Name="")
Return a boolean value testing if Arg == 0.
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Type * getVoidTy()
Fetch the type representing void.
LLVM_ABI CallInst * CreateElementUnorderedAtomicMemCpy(Value *Dst, Align DstAlign, Value *Src, Align SrcAlign, Value *Size, uint32_t ElementSize, const AAMDNodes &AAInfo=AAMDNodes())
Create and insert an element unordered-atomic memcpy between the specified pointers.
LLVM_ABI CallInst * CreateMemTransferInst(Intrinsic::ID IntrID, Value *Dst, MaybeAlign DstAlign, Value *Src, MaybeAlign SrcAlign, Value *Size, bool isVolatile=false, const AAMDNodes &AAInfo=AAMDNodes())
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
AtomicRMWInst * CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, Value *Val, MaybeAlign Align, AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System, bool Elementwise=false)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
LLVM_ABI MDNode * createRange(const APInt &Lo, const APInt &Hi)
Return metadata describing the range [Lo, Hi).
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
This class implements a map that also provides access to all stored values in a deterministic order.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
A Module instance is used to store all the information related to an LLVM module.
A container for an operand bundle being viewed as a set of values rather than a set of uses.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Return a value (possibly void), from a function.
A vector that has set insertion semantics.
size_type size() const
Determine the number of elements in the SetVector.
iterator end()
Get an iterator to the end of the SetVector.
void clear()
Completely clear the SetVector.
bool empty() const
Determine if the SetVector is empty or not.
iterator begin()
Get an iterator to the beginning of the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
Class to represent struct types.
static LLVM_ABI StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Target-Independent Code Generator Pass Configuration Options.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isPointerTy() const
True if this is an instance of PointerType.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
LLVM_ABI void printAsOperand(raw_ostream &O, bool PrintType=true, const Module *M=nullptr) const
Print the name of this Value out to the specified raw_ostream.
LLVM_ABI bool replaceUsesWithIf(Value *New, llvm::function_ref< bool(Use &U)> ShouldReplace)
Go through the uses list for this definition and make each use point to "V" if the callback ShouldRep...
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
An efficient, type-erasing, non-owning reference to a callable.
A raw_ostream that writes to an std::string.
A raw_ostream that writes to an SmallVector or SmallString.
StringRef str() const
Return a StringRef for the vector contents.
@ LOCAL_ADDRESS
Address space for local memory.
@ FLAT_ADDRESS
Address space for flat memory.
@ GLOBAL_ADDRESS
Address space for global memory (RAT0, VTX0).
GVUsesInfoTy getTransitiveUsesOfLDSForLowering(const CallGraph &CG, Module &M)
Collects all uses of LDS Global Variables in M using getUsesOfGVByFunction, with isLDSVariableToLower...
void getInterestingMemoryOperands(Module &M, Instruction *I, SmallVectorImpl< InterestingMemoryOperand > &Interesting)
Get all the memory operands from the instruction that needs to be instrumented.
bool isDynamicLDS(const GlobalVariable &GV)
unsigned getAMDHSACodeObjectVersion(const Module &M)
void removeFnAttrFromReachable(CallGraph &CG, Function *KernelRoot, ArrayRef< StringRef > FnAttrs)
Strip FnAttr attribute from any functions where we may have introduced its use.
bool eliminateGVConstantExprUsesFromAllInstructions(Module &M, function_ref< bool(const GlobalVariable &)> Filter)
Iterates over all GlobalVariables in M, and whenever Filter returns true, replace all constant users ...
LLVM_READNONE constexpr bool isKernel(CallingConv::ID CC)
MapVector< Function *, DenseSet< GlobalVariable * > > FunctionVariableMap
bool isLDSVariableToLower(const GlobalVariable &GV)
Align getAlign(const DataLayout &DL, const GlobalVariable *GV)
void instrumentAddress(Module &M, IRBuilder<> &IRB, Instruction *OrigIns, Instruction *InsertBefore, Value *Addr, Align Alignment, TypeSize TypeStoreSize, bool IsWrite, Value *SizeArgument, bool UseCalls, bool Recover, int AsanScale, int AsanOffset)
Instrument the memory operand Addr.
uint64_t getRedzoneSizeForGlobal(int AsanScale, uint64_t SizeInBytes)
Given SizeInBytes of the Value to be instrunmented, Returns the redzone size corresponding to it.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
ModulePass * createAMDGPUSwLowerLDSLegacyPass()
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
constexpr from_range_t from_range
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
char & AMDGPUSwLowerLDSLegacyPassID
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
LLVM_ABI void getAddressSanitizerParams(const Triple &TargetTriple, int LongSize, bool IsKasan, uint64_t *ShadowBase, int *MappingScale, bool *OrShadowOffset)
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
FunctionVariableMap DirectAccess
FunctionVariableMap IndirectAccess
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.