110#define DEBUG_TYPE "amdgpu-sw-lower-lds"
111#define COV5_HIDDEN_DYN_LDS_SIZE_ARG 15
119 AsanInstrumentLDS(
"amdgpu-asan-instrument-lds",
120 cl::desc(
"Run asan instrumentation on LDS instructions "
121 "lowered to global memory"),
126struct LDSAccessTypeInfo {
134struct KernelLDSParameters {
138 LDSAccessTypeInfo DirectAccess;
139 LDSAccessTypeInfo IndirectAccess;
141 LDSToReplacementIndicesMap;
149struct NonKernelLDSParameters {
156struct AsanInstrumentInfo {
162struct FunctionsAndLDSAccess {
170class AMDGPUSwLowerLDS {
172 AMDGPUSwLowerLDS(
Module &
Mod, DomTreeCallback Callback)
173 : M(
Mod), IRB(M), DTCallback(Callback) {}
175 void getUsesOfLDSByNonKernels();
176 void getNonKernelsWithLDSInstructions(
const CallGraph &CG);
181 void buildSwLDSGlobal(
Function *Func);
182 void buildSwDynLDSGlobal(
Function *Func);
183 void populateSwMetadataGlobal(
Function *Func);
184 void populateSwLDSAttributeAndMetadata(
Function *Func);
185 void populateLDSToReplacementIndicesMap(
Function *Func);
186 void getLDSMemoryInstructions(
Function *Func,
188 void replaceKernelLDSAccesses(
Function *Func);
189 Value *getTranslatedGlobalMemoryPtrOfLDS(
Value *LoadMallocPtr,
Value *LDSPtr);
192 void translateLDSMemoryOperationsToGlobalMemory(
197 void buildNonKernelLDSOffsetTable(NonKernelLDSParameters &NKLDSParams);
198 void buildNonKernelLDSBaseTable(NonKernelLDSParameters &NKLDSParams);
200 getAddressesOfVariablesInKernel(
Function *Func,
202 void lowerNonKernelLDSAccesses(
Function *Func,
204 NonKernelLDSParameters &NKLDSParams);
206 updateMallocSizeForDynamicLDS(
Function *Func,
Value **CurrMallocSize,
207 Value *HiddenDynLDSSize,
214 DomTreeCallback DTCallback;
215 FunctionsAndLDSAccess FuncLDSAccessInfo;
216 AsanInstrumentInfo AsanInfo;
219template <
typename T>
SetVector<T> sortByName(std::vector<T> &&V) {
222 sort(V, [](
const auto *L,
const auto *R) {
223 return L->getName() < R->getName();
232 std::vector<GlobalVariable *>(Variables.
begin(), Variables.
end()));
240 if (Kernels.size() > UINT32_MAX) {
244 sortByName(std::vector<Function *>(Kernels.begin(), Kernels.end()));
245 for (
size_t i = 0; i < Kernels.size(); i++) {
250 Func->setMetadata(
"llvm.amdgcn.lds.kernel.id",
253 return OrderedKernels;
257static bool isLDSMemoryInstruction(
const Instruction &Inst) {
267 unsigned SrcAS = ASC->getSrcAddressSpace();
268 unsigned DstAS = ASC->getDestAddressSpace();
283void AMDGPUSwLowerLDS::getNonKernelsWithLDSInstructions(
const CallGraph &CG) {
288 auto HasLDSInstructions = [&](
Function *
F) {
289 auto [It, Inserted] = HasLDSInstructionsCache.
try_emplace(
F,
false);
293 FuncLDSAccessInfo.NonKernelsWithLDSInstructions.
insert(
F);
302 F.hasAddressTaken(
nullptr,
false,
311 bool ReachesLDSInstructions =
false;
312 bool SeenUnknownCall =
false;
315 auto Visit = [&](
Function *Callee) {
316 if (Callee->isDeclaration() ||
isKernel(*Callee) ||
317 !Visited.
insert(Callee).second)
319 ReachesLDSInstructions |= HasLDSInstructions(Callee);
323 while (!WorkList.
empty()) {
326 if (!CallRecord.second)
328 if (
Function *Callee = CallRecord.second->getFunction()) {
334 SeenUnknownCall =
true;
335 for (
Function *PotentialCallee : AddressTakenFuncs)
336 Visit(PotentialCallee);
340 if (ReachesLDSInstructions)
341 FuncLDSAccessInfo.KernelsWithIndirectLDSAccess.
insert(&Kernel);
345void AMDGPUSwLowerLDS::getUsesOfLDSByNonKernels() {
346 for (
GlobalVariable *GV : FuncLDSAccessInfo.AllNonKernelLDSAccess) {
354 FuncLDSAccessInfo.NonKernelToLDSAccessMap[
F].
insert(GV);
368 ConstantInt::get(IntTy, Address + 1));
369 GV->
setMetadata(LLVMContext::MD_absolute_symbol, MetadataNode);
380 Func->addFnAttr(
"amdgpu-lds-size", Buffer);
389 Intrinsic::donothing, {});
391 Value *UseInstance[1] = {
392 Builder.CreateConstInBoundsGEP1_32(SGV->getValueType(), SGV, 0)};
394 Builder.CreateCall(Decl, {},
398void AMDGPUSwLowerLDS::buildSwLDSGlobal(
Function *Func) {
401 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
409 LDSParams.SwLDS->setSanitizerMetadata(MD);
412void AMDGPUSwLowerLDS::buildSwDynLDSGlobal(
Function *Func) {
414 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
415 if (LDSParams.DirectAccess.DynamicLDSGlobals.empty() &&
416 LDSParams.IndirectAccess.DynamicLDSGlobals.empty())
422 "llvm.amdgcn." + Func->getName() +
".dynlds",
nullptr,
424 markUsedByKernel(Func, LDSParams.SwDynLDS);
427 LDSParams.SwDynLDS->setSanitizerMetadata(MD);
430void AMDGPUSwLowerLDS::populateSwLDSAttributeAndMetadata(
Function *Func) {
431 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
432 bool IsDynLDSUsed = LDSParams.SwDynLDS;
434 recordLDSAbsoluteAddress(M, LDSParams.SwLDS, 0);
435 addLDSSizeAttribute(Func,
Offset, IsDynLDSUsed);
436 if (LDSParams.SwDynLDS)
437 recordLDSAbsoluteAddress(M, LDSParams.SwDynLDS,
Offset);
440void AMDGPUSwLowerLDS::populateSwMetadataGlobal(
Function *Func) {
443 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
444 auto &Ctx = M.getContext();
445 auto &
DL = M.getDataLayout();
446 std::vector<Type *> Items;
448 std::vector<Constant *> Initializers;
449 Align MaxAlignment(1);
452 MaxAlignment = std::max(MaxAlignment, GVAlign);
455 for (
GlobalVariable *GV : LDSParams.DirectAccess.StaticLDSGlobals)
456 UpdateMaxAlignment(GV);
458 for (
GlobalVariable *GV : LDSParams.DirectAccess.DynamicLDSGlobals)
459 UpdateMaxAlignment(GV);
461 for (
GlobalVariable *GV : LDSParams.IndirectAccess.StaticLDSGlobals)
462 UpdateMaxAlignment(GV);
464 for (
GlobalVariable *GV : LDSParams.IndirectAccess.DynamicLDSGlobals)
465 UpdateMaxAlignment(GV);
470 MDItemOS <<
"llvm.amdgcn.sw.lds." << Func->getName() <<
".md.item";
474 uint32_t &MallocSize = LDSParams.MallocSize;
476 int AsanScale = AsanInfo.Scale;
477 auto buildInitializerForSwLDSMD =
479 for (
auto &GV : LDSGlobals) {
482 UniqueLDSGlobals.
insert(GV);
485 const uint64_t SizeInBytes =
DL.getTypeAllocSize(Ty);
486 Items.push_back(LDSItemTy);
487 Constant *ItemStartOffset = ConstantInt::get(Int32Ty, MallocSize);
488 Constant *SizeInBytesConst = ConstantInt::get(Int32Ty, SizeInBytes);
493 MallocSize += SizeInBytes;
495 LDSParams.RedzoneOffsetAndSizeVector.emplace_back(MallocSize,
497 MallocSize += RightRedzoneSize;
500 alignTo(SizeInBytes + RightRedzoneSize, MaxAlignment);
502 ConstantInt::get(Int32Ty, AlignedSize);
504 MallocSize =
alignTo(MallocSize, MaxAlignment);
507 AlignedSizeInBytesConst});
508 Initializers.push_back(InitItem);
512 SwLDSVector.
insert(LDSParams.SwLDS);
513 buildInitializerForSwLDSMD(SwLDSVector);
514 buildInitializerForSwLDSMD(LDSParams.DirectAccess.StaticLDSGlobals);
515 buildInitializerForSwLDSMD(LDSParams.IndirectAccess.StaticLDSGlobals);
516 buildInitializerForSwLDSMD(LDSParams.DirectAccess.DynamicLDSGlobals);
517 buildInitializerForSwLDSMD(LDSParams.IndirectAccess.DynamicLDSGlobals);
520 Type *Ty = LDSParams.SwLDS->getValueType();
521 const uint64_t SizeInBytes =
DL.getTypeAllocSize(Ty);
523 LDSParams.LDSSize = AlignedSize;
526 MDTypeOS <<
"llvm.amdgcn.sw.lds." << Func->getName() <<
".md.type";
531 MDOS <<
"llvm.amdgcn.sw.lds." << Func->getName() <<
".md";
537 LDSParams.SwLDSMetadata->setInitializer(
data);
540 LDSParams.SwLDS->setAlignment(MaxAlignment);
541 if (LDSParams.SwDynLDS)
542 LDSParams.SwDynLDS->setAlignment(MaxAlignment);
545 LDSParams.SwLDSMetadata->setSanitizerMetadata(MD);
548void AMDGPUSwLowerLDS::populateLDSToReplacementIndicesMap(
Function *Func) {
551 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
555 for (
auto &GV : LDSGlobals) {
558 UniqueLDSGlobals.
insert(GV);
559 LDSParams.LDSToReplacementIndicesMap[GV] = {0,
Idx, 0};
565 SwLDSVector.
insert(LDSParams.SwLDS);
566 PopulateIndices(SwLDSVector,
Idx);
567 PopulateIndices(LDSParams.DirectAccess.StaticLDSGlobals,
Idx);
568 PopulateIndices(LDSParams.IndirectAccess.StaticLDSGlobals,
Idx);
569 PopulateIndices(LDSParams.DirectAccess.DynamicLDSGlobals,
Idx);
570 PopulateIndices(LDSParams.IndirectAccess.DynamicLDSGlobals,
Idx);
574 Value *Replacement) {
576 auto ReplaceUsesLambda = [Func](
const Use &U) ->
bool {
577 auto *V = U.getUser();
588void AMDGPUSwLowerLDS::replaceKernelLDSAccesses(
Function *Func) {
589 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
597 auto &IndirectAccess = LDSParams.IndirectAccess;
598 auto &DirectAccess = LDSParams.DirectAccess;
602 for (
auto &GV : LDSGlobals) {
605 if ((IndirectAccess.StaticLDSGlobals.contains(GV) ||
606 IndirectAccess.DynamicLDSGlobals.contains(GV)) &&
607 (!DirectAccess.StaticLDSGlobals.contains(GV) &&
608 !DirectAccess.DynamicLDSGlobals.contains(GV)))
612 UniqueLDSGlobals.
insert(GV);
613 auto &Indices = LDSParams.LDSToReplacementIndicesMap[GV];
614 assert(Indices.size() == 3);
615 Constant *GEPIdx[] = {ConstantInt::get(Int32Ty, Indices[0]),
616 ConstantInt::get(Int32Ty, Indices[1]),
617 ConstantInt::get(Int32Ty, Indices[2])};
619 Func->getDataLayout(), SwLDSMetadataStructType, SwLDSMetadata, GEPIdx,
622 Value *BasePlusOffset =
626 replacesUsesOfGlobalInFunction(Func, GV, BasePlusOffset);
629 ReplaceLDSGlobalUses(DirectAccess.StaticLDSGlobals);
630 ReplaceLDSGlobalUses(IndirectAccess.StaticLDSGlobals);
631 ReplaceLDSGlobalUses(DirectAccess.DynamicLDSGlobals);
632 ReplaceLDSGlobalUses(IndirectAccess.DynamicLDSGlobals);
635void AMDGPUSwLowerLDS::updateMallocSizeForDynamicLDS(
638 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
643 assert(SwLDS && SwLDSMetadata);
648 Value *MaxAlignValueMinusOne = IRB.
getInt32(MaxAlignment - 1);
651 auto &Indices = LDSParams.LDSToReplacementIndicesMap[DynGV];
653 Constant *Index0 = ConstantInt::get(Int32Ty, 0);
654 Constant *Index1 = ConstantInt::get(Int32Ty, Indices[1]);
656 Constant *Index2Offset = ConstantInt::get(Int32Ty, 0);
658 MetadataStructType, SwLDSMetadata, {Index0, Index1, Index2Offset});
662 Constant *Index2Size = ConstantInt::get(Int32Ty, 1);
664 {Index0, Index1, Index2Size});
668 Constant *Index2AlignedSize = ConstantInt::get(Int32Ty, 2);
670 MetadataStructType, SwLDSMetadata, {Index0, Index1, Index2AlignedSize});
672 Value *AlignedDynLDSSize =
673 IRB.
CreateAdd(CurrDynLDSSize, MaxAlignValueMinusOne);
674 AlignedDynLDSSize = IRB.
CreateUDiv(AlignedDynLDSSize, MaxAlignValue);
675 AlignedDynLDSSize = IRB.
CreateMul(AlignedDynLDSSize, MaxAlignValue);
676 IRB.
CreateStore(AlignedDynLDSSize, GEPForAlignedSize);
679 *CurrMallocSize = IRB.
CreateAdd(*CurrMallocSize, AlignedDynLDSSize);
693void AMDGPUSwLowerLDS::getLDSMemoryInstructions(
696 if (isLDSMemoryInstruction(Inst))
697 LDSInstructions.
insert(&Inst);
700Value *AMDGPUSwLowerLDS::getTranslatedGlobalMemoryPtrOfLDS(
Value *LoadMallocPtr,
702 assert(LDSPtr &&
"Invalid LDS pointer operand");
719Value *AMDGPUSwLowerLDS::getTranslatedLDSPtrOfFlat(
Value *LoadMallocPtr,
736void AMDGPUSwLowerLDS::translateLDSMemoryOperationsToGlobalMemory(
739 LLVM_DEBUG(
dbgs() <<
"Translating LDS memory operations to global memory : "
744 Value *LIOperand = LI->getPointerOperand();
746 getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, LIOperand);
748 IRB.
CreateLoad(LI->getType(), Replacement, LI->getProperties());
749 AsanInfo.Instructions.
insert(NewLI);
750 LI->replaceAllUsesWith(NewLI);
751 LI->eraseFromParent();
753 Value *SIOperand =
SI->getPointerOperand();
755 getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, SIOperand);
757 SI->getProperties());
758 AsanInfo.Instructions.
insert(NewSI);
759 SI->replaceAllUsesWith(NewSI);
760 SI->eraseFromParent();
762 Value *RMWPtrOperand = RMW->getPointerOperand();
763 Value *RMWValOperand = RMW->getValOperand();
765 getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, RMWPtrOperand);
767 RMW->getOperation(), Replacement, RMWValOperand, RMW->getAlign(),
768 RMW->getOrdering(), RMW->getSyncScopeID());
770 AsanInfo.Instructions.
insert(NewRMW);
771 RMW->replaceAllUsesWith(NewRMW);
772 RMW->eraseFromParent();
774 Value *XCHGPtrOperand = XCHG->getPointerOperand();
776 getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, XCHGPtrOperand);
778 Replacement, XCHG->getCompareOperand(), XCHG->getNewValOperand(),
779 XCHG->getAlign(), XCHG->getSuccessOrdering(),
780 XCHG->getFailureOrdering(), XCHG->getSyncScopeID());
782 AsanInfo.Instructions.
insert(NewXCHG);
783 XCHG->replaceAllUsesWith(NewXCHG);
784 XCHG->eraseFromParent();
786 Value *NewDest =
MI->getRawDest();
788 NewDest = getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, NewDest);
791 if (
MI->isAtomic()) {
793 NewDest, MSI->getValue(), MSI->getLength(),
794 MSI->getDestAlign().valueOrOne(), MSI->getElementSizeInBytes());
796 NewMI = IRB.
CreateMemSet(NewDest, MSI->getValue(), MSI->getLength(),
801 Value *NewSrc = MTI->getRawSource();
803 NewSrc = getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, NewSrc);
804 if (
MI->isAtomic()) {
805 if (
MI->getIntrinsicID() ==
806 Intrinsic::memmove_element_unordered_atomic) {
808 NewDest, MTI->getDestAlign().valueOrOne(), NewSrc,
809 MTI->getSourceAlign().valueOrOne(), MTI->getLength(),
810 MTI->getElementSizeInBytes());
813 NewDest, MTI->getDestAlign().valueOrOne(), NewSrc,
814 MTI->getSourceAlign().valueOrOne(), MTI->getLength(),
815 MTI->getElementSizeInBytes());
819 MI->getIntrinsicID(), NewDest, MTI->getDestAlign(), NewSrc,
820 MTI->getSourceAlign(), MTI->getLength(),
825 AsanInfo.Instructions.
insert(NewMI);
826 MI->replaceAllUsesWith(NewMI);
827 MI->eraseFromParent();
829 Value *AIOperand = ASC->getPointerOperand();
830 Value *NewAI =
nullptr;
833 getTranslatedLDSPtrOfFlat(LoadMallocPtr, AIOperand, ASC->
getType());
836 getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, AIOperand);
843 ASC->eraseFromParent();
849void AMDGPUSwLowerLDS::poisonRedzones(
Function *Func,
Value *MallocPtr) {
850 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
854 "__asan_poison_region",
857 auto RedzonesVec = LDSParams.RedzoneOffsetAndSizeVector;
858 size_t VecSize = RedzonesVec.size();
859 for (
unsigned i = 0; i < VecSize; i++) {
860 auto &RedzonePair = RedzonesVec[i];
861 uint64_t RedzoneOffset = RedzonePair.first;
862 uint64_t RedzoneSize = RedzonePair.second;
864 IRB.
getInt8Ty(), MallocPtr, {IRB.getInt64(RedzoneOffset)});
867 {RedzoneAddress, IRB.
getInt64(RedzoneSize)});
871void AMDGPUSwLowerLDS::lowerKernelLDSAccesses(
Function *Func,
873 LLVM_DEBUG(
dbgs() <<
"Sw Lowering Kernel LDS for : " << Func->getName());
874 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
875 auto &Ctx = M.getContext();
876 auto *PrevEntryBlock = &Func->getEntryBlock();
878 getLDSMemoryInstructions(Func, LDSInstructions);
892 auto SplitIt = PrevEntryBlock->getFirstNonPHIOrAlloca();
893 WIdBlock->splice(WIdBlock->end(), PrevEntryBlock, PrevEntryBlock->begin(),
898 AI->moveBefore(*WIdBlock, WIdBlock->end());
913 IRB.
CreateCondBr(WIdzCond, MallocBlock, PrevEntryBlock);
923 assert(SwLDS && SwLDSMetadata);
931 for (
auto &GV : LDSGlobals) {
934 UniqueLDSGlobals.
insert(GV);
938 GetUniqueLDSGlobals(LDSParams.DirectAccess.StaticLDSGlobals);
939 GetUniqueLDSGlobals(LDSParams.IndirectAccess.StaticLDSGlobals);
942 unsigned LastStaticLDSIdx = UniqueLDSGlobals.
size();
943 UniqueLDSGlobals.
clear();
945 auto *GEPForEndStaticLDSOffset =
947 {ConstantInt::get(Int32Ty, 0),
948 ConstantInt::get(Int32Ty, LastStaticLDSIdx),
949 ConstantInt::get(Int32Ty, 0)});
951 auto *GEPForEndStaticLDSSize =
953 {ConstantInt::get(Int32Ty, 0),
954 ConstantInt::get(Int32Ty, LastStaticLDSIdx),
955 ConstantInt::get(Int32Ty, 2)});
957 Value *EndStaticLDSOffset = IRB.
CreateLoad(Int32Ty, GEPForEndStaticLDSOffset);
958 Value *EndStaticLDSSize = IRB.
CreateLoad(Int32Ty, GEPForEndStaticLDSSize);
959 Value *CurrMallocSize = IRB.
CreateAdd(EndStaticLDSOffset, EndStaticLDSSize);
961 if (LDSParams.SwDynLDS) {
964 "Dynamic LDS size query is only supported for CO V5 and later.");
970 {ConstantInt::get(Int64Ty, COV5_HIDDEN_DYN_LDS_SIZE_ARG)});
971 UniqueLDSGlobals.
clear();
972 GetUniqueLDSGlobals(LDSParams.DirectAccess.DynamicLDSGlobals);
973 GetUniqueLDSGlobals(LDSParams.IndirectAccess.DynamicLDSGlobals);
974 updateMallocSizeForDynamicLDS(Func, &CurrMallocSize, HiddenDynLDSSize,
978 CurrMallocSize = IRB.
CreateZExt(CurrMallocSize, Int64Ty);
983 Intrinsic::returnaddress, IRB.
getPtrTy(
DL.getProgramAddressSpace()),
989 Value *MallocCall = IRB.
CreateCall(MallocFunc, {CurrMallocSize, RAPtrToInt});
998 poisonRedzones(Func, MallocPtr);
1006 auto *XYZCondPhi = IRB.
CreatePHI(Int1Ty, 2,
"xyzCond");
1008 XYZCondPhi->addIncoming(IRB.
getInt1(1), MallocBlock);
1013 Value *LoadMallocPtr =
1017 replaceKernelLDSAccesses(Func);
1021 translateLDSMemoryOperationsToGlobalMemory(Func, LoadMallocPtr,
1030 RI->eraseFromParent();
1050 Intrinsic::returnaddress, IRB.
getPtrTy(
DL.getProgramAddressSpace()),
1054 IRB.
CreateCall(AsanFreeFunc, {MallocPtrToInt, RAPToInt});
1068Constant *AMDGPUSwLowerLDS::getAddressesOfVariablesInKernel(
1075 auto KernelIt = FuncLDSAccessInfo.KernelToLDSParametersMap.find(Func);
1076 if (KernelIt == FuncLDSAccessInfo.KernelToLDSParametersMap.end() ||
1077 !KernelIt->second.SwLDSMetadata)
1080 auto &LDSParams = KernelIt->second;
1082 auto *SwLDSMetadataStructType =
1086 for (
auto *GV : Variables) {
1087 auto It = LDSParams.LDSToReplacementIndicesMap.find(GV);
1088 if (It == LDSParams.LDSToReplacementIndicesMap.end()) {
1093 auto &Indices = It->second;
1094 Constant *GEPIdx[] = {ConstantInt::get(Int32Ty, Indices[0]),
1095 ConstantInt::get(Int32Ty, Indices[1]),
1096 ConstantInt::get(Int32Ty, Indices[2])};
1098 Func->getDataLayout(), SwLDSMetadataStructType, SwLDSMetadata, GEPIdx,
1100 Elements.push_back(
GEP);
1105void AMDGPUSwLowerLDS::buildNonKernelLDSBaseTable(
1106 NonKernelLDSParameters &NKLDSParams) {
1110 auto &Kernels = NKLDSParams.OrderedKernels;
1111 if (Kernels.empty())
1113 const size_t NumberKernels = Kernels.size();
1116 std::vector<Constant *> OverallConstantExprElts(NumberKernels);
1117 for (
size_t i = 0; i < NumberKernels; i++) {
1121 auto It = FuncLDSAccessInfo.KernelToLDSParametersMap.find(Kernels[i]);
1122 if (It != FuncLDSAccessInfo.KernelToLDSParametersMap.end() &&
1124 SwLDS = It->second.SwLDS;
1125 OverallConstantExprElts[i] = SwLDS;
1138void AMDGPUSwLowerLDS::buildNonKernelLDSOffsetTable(
1139 NonKernelLDSParameters &NKLDSParams) {
1147 auto &Variables = NKLDSParams.OrdereLDSGlobals;
1148 auto &Kernels = NKLDSParams.OrderedKernels;
1149 if (Variables.
empty() || Kernels.empty())
1151 const size_t NumberVariables = Variables.
size();
1152 const size_t NumberKernels = Kernels.size();
1159 std::vector<Constant *> overallConstantExprElts(NumberKernels);
1160 for (
size_t i = 0; i < NumberKernels; i++) {
1162 overallConstantExprElts[i] =
1163 getAddressesOfVariablesInKernel(Func, Variables);
1176void AMDGPUSwLowerLDS::lowerNonKernelLDSAccesses(
1178 NonKernelLDSParameters &NKLDSParams) {
1181 LLVM_DEBUG(
dbgs() <<
"Sw LDS lowering, lower non-kernel access for : "
1182 << Func->getName());
1183 auto InsertAt = Func->getEntryBlock().getFirstNonPHIOrAlloca();
1188 getLDSMemoryInstructions(Func, LDSInstructions);
1190 auto *KernelId = IRB.
CreateIntrinsic(Intrinsic::amdgcn_lds_kernel_id, {});
1193 auto &OrdereLDSGlobals = NKLDSParams.OrdereLDSGlobals;
1195 LDSBaseTable->
getValueType(), LDSBaseTable, {IRB.getInt32(0), KernelId});
1198 Value *LoadMallocPtr =
1202 const auto *GVIt =
llvm::find(OrdereLDSGlobals, GV);
1203 assert(GVIt != OrdereLDSGlobals.end());
1204 uint32_t GVOffset = std::distance(OrdereLDSGlobals.begin(), GVIt);
1208 {IRB.getInt32(0), KernelId, IRB.getInt32(GVOffset)});
1212 Value *BasePlusOffset =
1214 LLVM_DEBUG(
dbgs() <<
"Sw LDS Lowering, Replace non-kernel LDS for "
1216 replacesUsesOfGlobalInFunction(Func, GV, BasePlusOffset);
1218 translateLDSMemoryOperationsToGlobalMemory(Func, LoadMallocPtr,
1222static void reorderStaticDynamicIndirectLDSSet(KernelLDSParameters &LDSParams) {
1225 auto &DirectAccess = LDSParams.DirectAccess;
1226 auto &IndirectAccess = LDSParams.IndirectAccess;
1227 LDSParams.DirectAccess.StaticLDSGlobals = sortByName(
1228 std::vector<GlobalVariable *>(DirectAccess.StaticLDSGlobals.begin(),
1229 DirectAccess.StaticLDSGlobals.end()));
1230 LDSParams.DirectAccess.DynamicLDSGlobals = sortByName(
1231 std::vector<GlobalVariable *>(DirectAccess.DynamicLDSGlobals.begin(),
1232 DirectAccess.DynamicLDSGlobals.end()));
1233 LDSParams.IndirectAccess.StaticLDSGlobals = sortByName(
1234 std::vector<GlobalVariable *>(IndirectAccess.StaticLDSGlobals.begin(),
1235 IndirectAccess.StaticLDSGlobals.end()));
1236 LDSParams.IndirectAccess.DynamicLDSGlobals = sortByName(
1237 std::vector<GlobalVariable *>(IndirectAccess.DynamicLDSGlobals.begin(),
1238 IndirectAccess.DynamicLDSGlobals.end()));
1241void AMDGPUSwLowerLDS::initAsanInfo() {
1247 bool OrShadowOffset;
1249 false, &
Offset, &Scale, &OrShadowOffset);
1250 AsanInfo.Scale = Scale;
1251 AsanInfo.Offset =
Offset;
1255 for (
auto &
K : LDSAccesses) {
1259 if (
F->hasFnAttribute(Attribute::SanitizeAddress))
1265bool AMDGPUSwLowerLDS::run() {
1278 bool LowerAllLDS = hasFnWithSanitizeAddressAttr(LDSUsesInfo.
DirectAccess) ||
1286 bool DirectAccess) {
1287 for (
auto &
K : LDSAccesses) {
1289 if (!
F ||
K.second.empty())
1295 FuncLDSAccessInfo.KernelToLDSParametersMap.insert(
1296 {
F, KernelLDSParameters()});
1298 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[
F];
1300 FuncLDSAccessInfo.KernelsWithIndirectLDSAccess.
insert(
F);
1302 if (!DirectAccess) {
1304 LDSParams.IndirectAccess.DynamicLDSGlobals.insert(GV);
1306 LDSParams.IndirectAccess.StaticLDSGlobals.insert(GV);
1307 FuncLDSAccessInfo.AllNonKernelLDSAccess.insert(GV);
1310 LDSParams.DirectAccess.DynamicLDSGlobals.insert(GV);
1312 LDSParams.DirectAccess.StaticLDSGlobals.insert(GV);
1318 PopulateKernelStaticDynamicLDS(LDSUsesInfo.
DirectAccess,
true);
1319 PopulateKernelStaticDynamicLDS(LDSUsesInfo.
IndirectAccess,
false);
1324 for (
auto &
K : FuncLDSAccessInfo.KernelToLDSParametersMap) {
1326 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
1327 if (LDSParams.DirectAccess.StaticLDSGlobals.empty() &&
1328 LDSParams.DirectAccess.DynamicLDSGlobals.empty() &&
1329 LDSParams.IndirectAccess.StaticLDSGlobals.empty() &&
1330 LDSParams.IndirectAccess.DynamicLDSGlobals.empty())
1335 {
"amdgpu-no-workitem-id-x",
"amdgpu-no-workitem-id-y",
1336 "amdgpu-no-workitem-id-z",
"amdgpu-no-heap-ptr"});
1337 reorderStaticDynamicIndirectLDSSet(LDSParams);
1338 buildSwLDSGlobal(Func);
1339 buildSwDynLDSGlobal(Func);
1340 populateSwMetadataGlobal(Func);
1341 populateSwLDSAttributeAndMetadata(Func);
1342 populateLDSToReplacementIndicesMap(Func);
1343 DomTreeUpdater DTU(DTCallback(*Func), DomTreeUpdater::UpdateStrategy::Lazy);
1344 lowerKernelLDSAccesses(Func, DTU);
1349 getUsesOfLDSByNonKernels();
1352 getNonKernelsWithLDSInstructions(CG);
1356 for (
Function *Func : FuncLDSAccessInfo.KernelsWithIndirectLDSAccess)
1360 if (!FuncLDSAccessInfo.NonKernelToLDSAccessMap.
empty() ||
1361 !FuncLDSAccessInfo.NonKernelsWithLDSInstructions.
empty()) {
1362 NonKernelLDSParameters NKLDSParams;
1363 NKLDSParams.OrderedKernels = getOrderedIndirectLDSAccessingKernels(
1364 FuncLDSAccessInfo.KernelsWithIndirectLDSAccess);
1365 NKLDSParams.OrdereLDSGlobals = getOrderedNonKernelAllLDSGlobals(
1366 FuncLDSAccessInfo.AllNonKernelLDSAccess);
1367 buildNonKernelLDSBaseTable(NKLDSParams);
1368 buildNonKernelLDSOffsetTable(NKLDSParams);
1369 for (
auto &
K : FuncLDSAccessInfo.NonKernelToLDSAccessMap) {
1373 std::vector<GlobalVariable *>(LDSGlobals.
begin(), LDSGlobals.
end()));
1374 lowerNonKernelLDSAccesses(Func, OrderedLDSGlobals, NKLDSParams);
1376 for (
Function *Func : FuncLDSAccessInfo.NonKernelsWithLDSInstructions) {
1377 if (FuncLDSAccessInfo.NonKernelToLDSAccessMap.
contains(Func))
1380 lowerNonKernelLDSAccesses(Func, NoLDSGlobals, NKLDSParams);
1397 if (AsanInstrumentLDS) {
1404 for (
auto &Operand : OperandsToInstrument) {
1405 Value *Addr = Operand.getPtr();
1407 Operand.Alignment.valueOrOne(), Operand.TypeStoreSize,
1408 Operand.IsWrite,
nullptr,
false,
false, AsanInfo.Scale,
1417class AMDGPUSwLowerLDSLegacy :
public ModulePass {
1421 bool runOnModule(
Module &M)
override;
1428char AMDGPUSwLowerLDSLegacy::ID = 0;
1432 "AMDGPU Software lowering of LDS",
false,
false)
1437bool AMDGPUSwLowerLDSLegacy::runOnModule(
Module &M) {
1440 if (!M.getModuleFlag(
"nosanitize_address"))
1443 getAnalysisIfAvailable<DominatorTreeWrapperPass>();
1445 return DTW ? &DTW->getDomTree() : nullptr;
1448 AMDGPUSwLowerLDS SwLowerLDSImpl(M, DTCallback);
1449 bool IsChanged = SwLowerLDSImpl.run();
1454 return new AMDGPUSwLowerLDSLegacy();
1461 if (!M.getModuleFlag(
"nosanitize_address"))
1467 AMDGPUSwLowerLDS SwLowerLDSImpl(M, DTCallback);
1468 bool IsChanged = SwLowerLDSImpl.run();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
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.
std::pair< std::optional< WeakTrackingVH >, CallGraphNode * > CallRecord
A pair of the calling instruction (a call or invoke) and the call graph node being called.
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 ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static LLVM_ABI Constant * get(StructType *T, ArrayRef< Constant * > V)
This is an important base class in LLVM.
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.
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
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.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
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.
bool contains(const KeyT &Key) const
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.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
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.
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.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
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...
LLVM_ABI void getAddressSanitizerParams(const LLVMContext &Ctx, const Triple &TargetTriple, int LongSize, bool IsKasan, uint64_t *ShadowBase, int *MappingScale, bool *OrShadowOffset)
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.
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.