110#define DEBUG_TYPE "amdgpu-sw-lower-lds"
111#define COV5_HIDDEN_DYN_LDS_SIZE_ARG 15
120struct LDSAccessTypeInfo {
128struct KernelLDSParameters {
132 LDSAccessTypeInfo DirectAccess;
133 LDSAccessTypeInfo IndirectAccess;
135 LDSToReplacementIndicesMap;
143struct NonKernelLDSParameters {
150struct AsanInstrumentInfo {
156struct FunctionsAndLDSAccess {
164class AMDGPUSwLowerLDS {
166 AMDGPUSwLowerLDS(
Module &
Mod, DomTreeCallback Callback)
167 : M(
Mod), IRB(M), DTCallback(Callback) {}
169 void getUsesOfLDSByNonKernels();
170 void getNonKernelsWithLDSInstructions(
const CallGraph &CG);
175 void buildSwLDSGlobal(
Function *Func);
176 void buildSwDynLDSGlobal(
Function *Func);
177 void populateSwMetadataGlobal(
Function *Func);
178 void populateSwLDSAttributeAndMetadata(
Function *Func);
179 void populateLDSToReplacementIndicesMap(
Function *Func);
180 void getLDSMemoryInstructions(
Function *Func,
182 void replaceKernelLDSAccesses(
Function *Func);
183 Value *getTranslatedGlobalMemoryPtrOfLDS(
Value *LoadMallocPtr,
Value *LDSPtr);
186 void translateLDSMemoryOperationsToGlobalMemory(
191 void buildNonKernelLDSOffsetTable(NonKernelLDSParameters &NKLDSParams);
192 void buildNonKernelLDSBaseTable(NonKernelLDSParameters &NKLDSParams);
194 getAddressesOfVariablesInKernel(
Function *Func,
196 void lowerNonKernelLDSAccesses(
Function *Func,
198 NonKernelLDSParameters &NKLDSParams);
200 updateMallocSizeForDynamicLDS(
Function *Func,
Value **CurrMallocSize,
201 Value *HiddenDynLDSSize,
208 DomTreeCallback DTCallback;
209 FunctionsAndLDSAccess FuncLDSAccessInfo;
210 AsanInstrumentInfo AsanInfo;
213template <
typename T>
SetVector<T> sortByName(std::vector<T> &&
V) {
216 sort(
V, [](
const auto *L,
const auto *R) {
217 return L->getName() < R->getName();
226 std::vector<GlobalVariable *>(Variables.
begin(), Variables.
end()));
234 if (Kernels.size() > UINT32_MAX) {
238 sortByName(std::vector<Function *>(Kernels.begin(), Kernels.end()));
239 for (
size_t i = 0; i < Kernels.size(); i++) {
244 Func->setMetadata(
"llvm.amdgcn.lds.kernel.id",
247 return OrderedKernels;
251static bool isLDSMemoryInstruction(
const Instruction &Inst) {
261 unsigned SrcAS = ASC->getSrcAddressSpace();
262 unsigned DstAS = ASC->getDestAddressSpace();
277void AMDGPUSwLowerLDS::getNonKernelsWithLDSInstructions(
const CallGraph &CG) {
282 auto HasLDSInstructions = [&](
Function *
F) {
283 auto [It, Inserted] = HasLDSInstructionsCache.
try_emplace(
F,
false);
287 FuncLDSAccessInfo.NonKernelsWithLDSInstructions.
insert(
F);
296 F.hasAddressTaken(
nullptr,
false,
305 bool ReachesLDSInstructions =
false;
306 bool SeenUnknownCall =
false;
309 auto Visit = [&](
Function *Callee) {
310 if (Callee->isDeclaration() ||
isKernel(*Callee) ||
311 !Visited.
insert(Callee).second)
313 ReachesLDSInstructions |= HasLDSInstructions(Callee);
317 while (!WorkList.
empty()) {
320 if (!CallRecord.second)
322 if (
Function *Callee = CallRecord.second->getFunction()) {
328 SeenUnknownCall =
true;
329 for (
Function *PotentialCallee : AddressTakenFuncs)
330 Visit(PotentialCallee);
334 if (ReachesLDSInstructions)
335 FuncLDSAccessInfo.KernelsWithIndirectLDSAccess.
insert(&Kernel);
339void AMDGPUSwLowerLDS::getUsesOfLDSByNonKernels() {
340 for (
GlobalVariable *GV : FuncLDSAccessInfo.AllNonKernelLDSAccess) {
348 FuncLDSAccessInfo.NonKernelToLDSAccessMap[
F].
insert(GV);
362 ConstantInt::get(IntTy, Address + 1));
363 GV->
setMetadata(LLVMContext::MD_absolute_symbol, MetadataNode);
374 Func->addFnAttr(
"amdgpu-lds-size", Buffer);
383 Intrinsic::donothing, {});
385 Value *UseInstance[1] = {
386 Builder.CreateConstInBoundsGEP1_32(SGV->getValueType(), SGV, 0)};
388 Builder.CreateCall(Decl, {},
392void AMDGPUSwLowerLDS::buildSwLDSGlobal(
Function *Func) {
395 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
403 LDSParams.SwLDS->setSanitizerMetadata(MD);
406void AMDGPUSwLowerLDS::buildSwDynLDSGlobal(
Function *Func) {
408 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
409 if (LDSParams.DirectAccess.DynamicLDSGlobals.empty() &&
410 LDSParams.IndirectAccess.DynamicLDSGlobals.empty())
416 "llvm.amdgcn." + Func->getName() +
".dynlds",
nullptr,
418 markUsedByKernel(Func, LDSParams.SwDynLDS);
421 LDSParams.SwDynLDS->setSanitizerMetadata(MD);
424void AMDGPUSwLowerLDS::populateSwLDSAttributeAndMetadata(
Function *Func) {
425 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
426 bool IsDynLDSUsed = LDSParams.SwDynLDS;
428 recordLDSAbsoluteAddress(M, LDSParams.SwLDS, 0);
429 addLDSSizeAttribute(Func,
Offset, IsDynLDSUsed);
430 if (LDSParams.SwDynLDS)
431 recordLDSAbsoluteAddress(M, LDSParams.SwDynLDS,
Offset);
434void AMDGPUSwLowerLDS::populateSwMetadataGlobal(
Function *Func) {
437 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
438 auto &Ctx = M.getContext();
439 auto &
DL = M.getDataLayout();
440 std::vector<Type *> Items;
442 std::vector<Constant *> Initializers;
443 Align MaxAlignment(1);
446 MaxAlignment = std::max(MaxAlignment, GVAlign);
449 for (
GlobalVariable *GV : LDSParams.DirectAccess.StaticLDSGlobals)
450 UpdateMaxAlignment(GV);
452 for (
GlobalVariable *GV : LDSParams.DirectAccess.DynamicLDSGlobals)
453 UpdateMaxAlignment(GV);
455 for (
GlobalVariable *GV : LDSParams.IndirectAccess.StaticLDSGlobals)
456 UpdateMaxAlignment(GV);
458 for (
GlobalVariable *GV : LDSParams.IndirectAccess.DynamicLDSGlobals)
459 UpdateMaxAlignment(GV);
464 MDItemOS <<
"llvm.amdgcn.sw.lds." << Func->getName() <<
".md.item";
468 uint32_t &MallocSize = LDSParams.MallocSize;
470 int AsanScale = AsanInfo.Scale;
471 auto buildInitializerForSwLDSMD =
473 for (
auto &GV : LDSGlobals) {
476 UniqueLDSGlobals.
insert(GV);
479 const uint64_t SizeInBytes =
DL.getTypeAllocSize(Ty);
480 Items.push_back(LDSItemTy);
481 Constant *ItemStartOffset = ConstantInt::get(Int32Ty, MallocSize);
482 Constant *SizeInBytesConst = ConstantInt::get(Int32Ty, SizeInBytes);
487 MallocSize += SizeInBytes;
489 LDSParams.RedzoneOffsetAndSizeVector.emplace_back(MallocSize,
491 MallocSize += RightRedzoneSize;
494 alignTo(SizeInBytes + RightRedzoneSize, MaxAlignment);
496 ConstantInt::get(Int32Ty, AlignedSize);
498 MallocSize =
alignTo(MallocSize, MaxAlignment);
501 AlignedSizeInBytesConst});
502 Initializers.push_back(InitItem);
506 SwLDSVector.
insert(LDSParams.SwLDS);
507 buildInitializerForSwLDSMD(SwLDSVector);
508 buildInitializerForSwLDSMD(LDSParams.DirectAccess.StaticLDSGlobals);
509 buildInitializerForSwLDSMD(LDSParams.IndirectAccess.StaticLDSGlobals);
510 buildInitializerForSwLDSMD(LDSParams.DirectAccess.DynamicLDSGlobals);
511 buildInitializerForSwLDSMD(LDSParams.IndirectAccess.DynamicLDSGlobals);
514 Type *Ty = LDSParams.SwLDS->getValueType();
515 const uint64_t SizeInBytes =
DL.getTypeAllocSize(Ty);
517 LDSParams.LDSSize = AlignedSize;
520 MDTypeOS <<
"llvm.amdgcn.sw.lds." << Func->getName() <<
".md.type";
525 MDOS <<
"llvm.amdgcn.sw.lds." << Func->getName() <<
".md";
531 LDSParams.SwLDSMetadata->setInitializer(
data);
534 LDSParams.SwLDS->setAlignment(MaxAlignment);
535 if (LDSParams.SwDynLDS)
536 LDSParams.SwDynLDS->setAlignment(MaxAlignment);
539 LDSParams.SwLDSMetadata->setSanitizerMetadata(MD);
542void AMDGPUSwLowerLDS::populateLDSToReplacementIndicesMap(
Function *Func) {
545 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
549 for (
auto &GV : LDSGlobals) {
552 UniqueLDSGlobals.
insert(GV);
553 LDSParams.LDSToReplacementIndicesMap[GV] = {0,
Idx, 0};
559 SwLDSVector.
insert(LDSParams.SwLDS);
560 PopulateIndices(SwLDSVector,
Idx);
561 PopulateIndices(LDSParams.DirectAccess.StaticLDSGlobals,
Idx);
562 PopulateIndices(LDSParams.IndirectAccess.StaticLDSGlobals,
Idx);
563 PopulateIndices(LDSParams.DirectAccess.DynamicLDSGlobals,
Idx);
564 PopulateIndices(LDSParams.IndirectAccess.DynamicLDSGlobals,
Idx);
568 Value *Replacement) {
570 auto ReplaceUsesLambda = [Func](
const Use &U) ->
bool {
571 auto *
V = U.getUser();
582void AMDGPUSwLowerLDS::replaceKernelLDSAccesses(
Function *Func) {
583 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
591 auto &IndirectAccess = LDSParams.IndirectAccess;
592 auto &DirectAccess = LDSParams.DirectAccess;
596 for (
auto &GV : LDSGlobals) {
599 if ((IndirectAccess.StaticLDSGlobals.contains(GV) ||
600 IndirectAccess.DynamicLDSGlobals.contains(GV)) &&
601 (!DirectAccess.StaticLDSGlobals.contains(GV) &&
602 !DirectAccess.DynamicLDSGlobals.contains(GV)))
606 UniqueLDSGlobals.
insert(GV);
607 auto &Indices = LDSParams.LDSToReplacementIndicesMap[GV];
608 assert(Indices.size() == 3);
609 Constant *GEPIdx[] = {ConstantInt::get(Int32Ty, Indices[0]),
610 ConstantInt::get(Int32Ty, Indices[1]),
611 ConstantInt::get(Int32Ty, Indices[2])};
613 Func->getDataLayout(), SwLDSMetadataStructType, SwLDSMetadata, GEPIdx,
616 Value *BasePlusOffset =
620 replacesUsesOfGlobalInFunction(Func, GV, BasePlusOffset);
623 ReplaceLDSGlobalUses(DirectAccess.StaticLDSGlobals);
624 ReplaceLDSGlobalUses(IndirectAccess.StaticLDSGlobals);
625 ReplaceLDSGlobalUses(DirectAccess.DynamicLDSGlobals);
626 ReplaceLDSGlobalUses(IndirectAccess.DynamicLDSGlobals);
629void AMDGPUSwLowerLDS::updateMallocSizeForDynamicLDS(
632 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
637 assert(SwLDS && SwLDSMetadata);
642 Value *MaxAlignValueMinusOne = IRB.
getInt32(MaxAlignment - 1);
645 auto &Indices = LDSParams.LDSToReplacementIndicesMap[DynGV];
647 Constant *Index0 = ConstantInt::get(Int32Ty, 0);
648 Constant *Index1 = ConstantInt::get(Int32Ty, Indices[1]);
650 Constant *Index2Offset = ConstantInt::get(Int32Ty, 0);
652 MetadataStructType, SwLDSMetadata, {Index0, Index1, Index2Offset});
656 Constant *Index2Size = ConstantInt::get(Int32Ty, 1);
658 {Index0, Index1, Index2Size});
662 Constant *Index2AlignedSize = ConstantInt::get(Int32Ty, 2);
664 MetadataStructType, SwLDSMetadata, {Index0, Index1, Index2AlignedSize});
666 Value *AlignedDynLDSSize =
667 IRB.
CreateAdd(CurrDynLDSSize, MaxAlignValueMinusOne);
668 AlignedDynLDSSize = IRB.
CreateUDiv(AlignedDynLDSSize, MaxAlignValue);
669 AlignedDynLDSSize = IRB.
CreateMul(AlignedDynLDSSize, MaxAlignValue);
670 IRB.
CreateStore(AlignedDynLDSSize, GEPForAlignedSize);
673 *CurrMallocSize = IRB.
CreateAdd(*CurrMallocSize, AlignedDynLDSSize);
687void AMDGPUSwLowerLDS::getLDSMemoryInstructions(
690 if (isLDSMemoryInstruction(Inst))
691 LDSInstructions.
insert(&Inst);
694Value *AMDGPUSwLowerLDS::getTranslatedGlobalMemoryPtrOfLDS(
Value *LoadMallocPtr,
696 assert(LDSPtr &&
"Invalid LDS pointer operand");
713Value *AMDGPUSwLowerLDS::getTranslatedLDSPtrOfFlat(
Value *LoadMallocPtr,
730void AMDGPUSwLowerLDS::translateLDSMemoryOperationsToGlobalMemory(
733 LLVM_DEBUG(
dbgs() <<
"Translating LDS memory operations to global memory : "
738 Value *LIOperand = LI->getPointerOperand();
740 getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, LIOperand);
742 IRB.
CreateLoad(LI->getType(), Replacement, LI->getProperties());
743 AsanInfo.Instructions.
insert(NewLI);
744 LI->replaceAllUsesWith(NewLI);
745 LI->eraseFromParent();
747 Value *SIOperand =
SI->getPointerOperand();
749 getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, SIOperand);
751 SI->getProperties());
752 AsanInfo.Instructions.
insert(NewSI);
753 SI->replaceAllUsesWith(NewSI);
754 SI->eraseFromParent();
756 Value *RMWPtrOperand = RMW->getPointerOperand();
757 Value *RMWValOperand = RMW->getValOperand();
759 getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, RMWPtrOperand);
761 RMW->getOperation(), Replacement, RMWValOperand, RMW->getAlign(),
762 RMW->getOrdering(), RMW->getSyncScopeID());
764 AsanInfo.Instructions.
insert(NewRMW);
765 RMW->replaceAllUsesWith(NewRMW);
766 RMW->eraseFromParent();
768 Value *XCHGPtrOperand = XCHG->getPointerOperand();
770 getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, XCHGPtrOperand);
772 Replacement, XCHG->getCompareOperand(), XCHG->getNewValOperand(),
773 XCHG->getAlign(), XCHG->getSuccessOrdering(),
774 XCHG->getFailureOrdering(), XCHG->getSyncScopeID());
776 AsanInfo.Instructions.
insert(NewXCHG);
777 XCHG->replaceAllUsesWith(NewXCHG);
778 XCHG->eraseFromParent();
780 Value *NewDest =
MI->getRawDest();
782 NewDest = getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, NewDest);
785 if (
MI->isAtomic()) {
787 NewDest, MSI->getValue(), MSI->getLength(),
788 MSI->getDestAlign().valueOrOne(), MSI->getElementSizeInBytes());
790 NewMI = IRB.
CreateMemSet(NewDest, MSI->getValue(), MSI->getLength(),
795 Value *NewSrc = MTI->getRawSource();
797 NewSrc = getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, NewSrc);
798 if (
MI->isAtomic()) {
799 if (
MI->getIntrinsicID() ==
800 Intrinsic::memmove_element_unordered_atomic) {
802 NewDest, MTI->getDestAlign().valueOrOne(), NewSrc,
803 MTI->getSourceAlign().valueOrOne(), MTI->getLength(),
804 MTI->getElementSizeInBytes());
807 NewDest, MTI->getDestAlign().valueOrOne(), NewSrc,
808 MTI->getSourceAlign().valueOrOne(), MTI->getLength(),
809 MTI->getElementSizeInBytes());
813 MI->getIntrinsicID(), NewDest, MTI->getDestAlign(), NewSrc,
814 MTI->getSourceAlign(), MTI->getLength(),
819 AsanInfo.Instructions.
insert(NewMI);
820 MI->replaceAllUsesWith(NewMI);
821 MI->eraseFromParent();
823 Value *AIOperand = ASC->getPointerOperand();
824 Value *NewAI =
nullptr;
827 getTranslatedLDSPtrOfFlat(LoadMallocPtr, AIOperand, ASC->
getType());
830 getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, AIOperand);
837 ASC->eraseFromParent();
843void AMDGPUSwLowerLDS::poisonRedzones(
Function *Func,
Value *MallocPtr) {
844 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
848 "__asan_poison_region",
851 auto RedzonesVec = LDSParams.RedzoneOffsetAndSizeVector;
852 size_t VecSize = RedzonesVec.size();
853 for (
unsigned i = 0; i < VecSize; i++) {
854 auto &RedzonePair = RedzonesVec[i];
855 uint64_t RedzoneOffset = RedzonePair.first;
856 uint64_t RedzoneSize = RedzonePair.second;
858 IRB.
getInt8Ty(), MallocPtr, {IRB.getInt64(RedzoneOffset)});
861 {RedzoneAddress, IRB.
getInt64(RedzoneSize)});
865void AMDGPUSwLowerLDS::lowerKernelLDSAccesses(
Function *Func,
867 LLVM_DEBUG(
dbgs() <<
"Sw Lowering Kernel LDS for : " << Func->getName());
868 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
869 auto &Ctx = M.getContext();
870 auto *PrevEntryBlock = &Func->getEntryBlock();
872 getLDSMemoryInstructions(Func, LDSInstructions);
886 auto SplitIt = PrevEntryBlock->getFirstNonPHIOrAlloca();
887 WIdBlock->splice(WIdBlock->end(), PrevEntryBlock, PrevEntryBlock->begin(),
892 AI->moveBefore(*WIdBlock, WIdBlock->end());
907 IRB.
CreateCondBr(WIdzCond, MallocBlock, PrevEntryBlock);
917 assert(SwLDS && SwLDSMetadata);
925 for (
auto &GV : LDSGlobals) {
928 UniqueLDSGlobals.
insert(GV);
932 GetUniqueLDSGlobals(LDSParams.DirectAccess.StaticLDSGlobals);
933 GetUniqueLDSGlobals(LDSParams.IndirectAccess.StaticLDSGlobals);
936 unsigned LastStaticLDSIdx = UniqueLDSGlobals.
size();
937 UniqueLDSGlobals.
clear();
939 auto *GEPForEndStaticLDSOffset =
941 {ConstantInt::get(Int32Ty, 0),
942 ConstantInt::get(Int32Ty, LastStaticLDSIdx),
943 ConstantInt::get(Int32Ty, 0)});
945 auto *GEPForEndStaticLDSSize =
947 {ConstantInt::get(Int32Ty, 0),
948 ConstantInt::get(Int32Ty, LastStaticLDSIdx),
949 ConstantInt::get(Int32Ty, 2)});
951 Value *EndStaticLDSOffset = IRB.
CreateLoad(Int32Ty, GEPForEndStaticLDSOffset);
952 Value *EndStaticLDSSize = IRB.
CreateLoad(Int32Ty, GEPForEndStaticLDSSize);
953 Value *CurrMallocSize = IRB.
CreateAdd(EndStaticLDSOffset, EndStaticLDSSize);
955 if (LDSParams.SwDynLDS) {
958 "Dynamic LDS size query is only supported for CO V5 and later.");
964 {ConstantInt::get(Int64Ty, COV5_HIDDEN_DYN_LDS_SIZE_ARG)});
965 UniqueLDSGlobals.
clear();
966 GetUniqueLDSGlobals(LDSParams.DirectAccess.DynamicLDSGlobals);
967 GetUniqueLDSGlobals(LDSParams.IndirectAccess.DynamicLDSGlobals);
968 updateMallocSizeForDynamicLDS(Func, &CurrMallocSize, HiddenDynLDSSize,
972 CurrMallocSize = IRB.
CreateZExt(CurrMallocSize, Int64Ty);
977 Intrinsic::returnaddress, IRB.
getPtrTy(
DL.getProgramAddressSpace()),
983 Value *MallocCall = IRB.
CreateCall(MallocFunc, {CurrMallocSize, RAPtrToInt});
992 poisonRedzones(Func, MallocPtr);
1000 auto *XYZCondPhi = IRB.
CreatePHI(Int1Ty, 2,
"xyzCond");
1002 XYZCondPhi->addIncoming(IRB.
getInt1(1), MallocBlock);
1007 Value *LoadMallocPtr =
1011 replaceKernelLDSAccesses(Func);
1015 translateLDSMemoryOperationsToGlobalMemory(Func, LoadMallocPtr,
1024 RI->eraseFromParent();
1044 Intrinsic::returnaddress, IRB.
getPtrTy(
DL.getProgramAddressSpace()),
1048 IRB.
CreateCall(AsanFreeFunc, {MallocPtrToInt, RAPToInt});
1062Constant *AMDGPUSwLowerLDS::getAddressesOfVariablesInKernel(
1069 auto KernelIt = FuncLDSAccessInfo.KernelToLDSParametersMap.find(Func);
1070 if (KernelIt == FuncLDSAccessInfo.KernelToLDSParametersMap.end() ||
1071 !KernelIt->second.SwLDSMetadata)
1074 auto &LDSParams = KernelIt->second;
1076 auto *SwLDSMetadataStructType =
1080 for (
auto *GV : Variables) {
1081 auto It = LDSParams.LDSToReplacementIndicesMap.find(GV);
1082 if (It == LDSParams.LDSToReplacementIndicesMap.end()) {
1087 auto &Indices = It->second;
1088 Constant *GEPIdx[] = {ConstantInt::get(Int32Ty, Indices[0]),
1089 ConstantInt::get(Int32Ty, Indices[1]),
1090 ConstantInt::get(Int32Ty, Indices[2])};
1092 Func->getDataLayout(), SwLDSMetadataStructType, SwLDSMetadata, GEPIdx,
1094 Elements.push_back(
GEP);
1099void AMDGPUSwLowerLDS::buildNonKernelLDSBaseTable(
1100 NonKernelLDSParameters &NKLDSParams) {
1104 auto &Kernels = NKLDSParams.OrderedKernels;
1105 if (Kernels.empty())
1107 const size_t NumberKernels = Kernels.size();
1110 std::vector<Constant *> OverallConstantExprElts(NumberKernels);
1111 for (
size_t i = 0; i < NumberKernels; i++) {
1115 auto It = FuncLDSAccessInfo.KernelToLDSParametersMap.find(Kernels[i]);
1116 if (It != FuncLDSAccessInfo.KernelToLDSParametersMap.end() &&
1118 SwLDS = It->second.SwLDS;
1119 OverallConstantExprElts[i] = SwLDS;
1132void AMDGPUSwLowerLDS::buildNonKernelLDSOffsetTable(
1133 NonKernelLDSParameters &NKLDSParams) {
1141 auto &Variables = NKLDSParams.OrdereLDSGlobals;
1142 auto &Kernels = NKLDSParams.OrderedKernels;
1143 if (Variables.
empty() || Kernels.empty())
1145 const size_t NumberVariables = Variables.
size();
1146 const size_t NumberKernels = Kernels.size();
1153 std::vector<Constant *> overallConstantExprElts(NumberKernels);
1154 for (
size_t i = 0; i < NumberKernels; i++) {
1156 overallConstantExprElts[i] =
1157 getAddressesOfVariablesInKernel(Func, Variables);
1170void AMDGPUSwLowerLDS::lowerNonKernelLDSAccesses(
1172 NonKernelLDSParameters &NKLDSParams) {
1175 LLVM_DEBUG(
dbgs() <<
"Sw LDS lowering, lower non-kernel access for : "
1176 << Func->getName());
1177 auto InsertAt = Func->getEntryBlock().getFirstNonPHIOrAlloca();
1182 getLDSMemoryInstructions(Func, LDSInstructions);
1184 auto *KernelId = IRB.
CreateIntrinsic(Intrinsic::amdgcn_lds_kernel_id, {});
1187 auto &OrdereLDSGlobals = NKLDSParams.OrdereLDSGlobals;
1189 LDSBaseTable->
getValueType(), LDSBaseTable, {IRB.getInt32(0), KernelId});
1192 Value *LoadMallocPtr =
1196 const auto *GVIt =
llvm::find(OrdereLDSGlobals, GV);
1197 assert(GVIt != OrdereLDSGlobals.end());
1198 uint32_t GVOffset = std::distance(OrdereLDSGlobals.begin(), GVIt);
1202 {IRB.getInt32(0), KernelId, IRB.getInt32(GVOffset)});
1206 Value *BasePlusOffset =
1208 LLVM_DEBUG(
dbgs() <<
"Sw LDS Lowering, Replace non-kernel LDS for "
1210 replacesUsesOfGlobalInFunction(Func, GV, BasePlusOffset);
1212 translateLDSMemoryOperationsToGlobalMemory(Func, LoadMallocPtr,
1216static void reorderStaticDynamicIndirectLDSSet(KernelLDSParameters &LDSParams) {
1219 auto &DirectAccess = LDSParams.DirectAccess;
1220 auto &IndirectAccess = LDSParams.IndirectAccess;
1221 LDSParams.DirectAccess.StaticLDSGlobals = sortByName(
1222 std::vector<GlobalVariable *>(DirectAccess.StaticLDSGlobals.begin(),
1223 DirectAccess.StaticLDSGlobals.end()));
1224 LDSParams.DirectAccess.DynamicLDSGlobals = sortByName(
1225 std::vector<GlobalVariable *>(DirectAccess.DynamicLDSGlobals.begin(),
1226 DirectAccess.DynamicLDSGlobals.end()));
1227 LDSParams.IndirectAccess.StaticLDSGlobals = sortByName(
1228 std::vector<GlobalVariable *>(IndirectAccess.StaticLDSGlobals.begin(),
1229 IndirectAccess.StaticLDSGlobals.end()));
1230 LDSParams.IndirectAccess.DynamicLDSGlobals = sortByName(
1231 std::vector<GlobalVariable *>(IndirectAccess.DynamicLDSGlobals.begin(),
1232 IndirectAccess.DynamicLDSGlobals.end()));
1235void AMDGPUSwLowerLDS::initAsanInfo() {
1241 bool OrShadowOffset;
1243 false, &
Offset, &Scale, &OrShadowOffset);
1244 AsanInfo.Scale = Scale;
1245 AsanInfo.Offset =
Offset;
1249 for (
auto &
K : LDSAccesses) {
1253 if (
F->hasFnAttribute(Attribute::SanitizeAddress))
1259bool AMDGPUSwLowerLDS::run() {
1272 bool LowerAllLDS = hasFnWithSanitizeAddressAttr(LDSUsesInfo.
DirectAccess) ||
1280 bool DirectAccess) {
1281 for (
auto &
K : LDSAccesses) {
1283 if (!
F ||
K.second.empty())
1289 FuncLDSAccessInfo.KernelToLDSParametersMap.insert(
1290 {
F, KernelLDSParameters()});
1292 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[
F];
1294 FuncLDSAccessInfo.KernelsWithIndirectLDSAccess.
insert(
F);
1296 if (!DirectAccess) {
1298 LDSParams.IndirectAccess.DynamicLDSGlobals.insert(GV);
1300 LDSParams.IndirectAccess.StaticLDSGlobals.insert(GV);
1301 FuncLDSAccessInfo.AllNonKernelLDSAccess.insert(GV);
1304 LDSParams.DirectAccess.DynamicLDSGlobals.insert(GV);
1306 LDSParams.DirectAccess.StaticLDSGlobals.insert(GV);
1312 PopulateKernelStaticDynamicLDS(LDSUsesInfo.
DirectAccess,
true);
1313 PopulateKernelStaticDynamicLDS(LDSUsesInfo.
IndirectAccess,
false);
1318 for (
auto &
K : FuncLDSAccessInfo.KernelToLDSParametersMap) {
1320 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
1321 if (LDSParams.DirectAccess.StaticLDSGlobals.empty() &&
1322 LDSParams.DirectAccess.DynamicLDSGlobals.empty() &&
1323 LDSParams.IndirectAccess.StaticLDSGlobals.empty() &&
1324 LDSParams.IndirectAccess.DynamicLDSGlobals.empty())
1329 {
"amdgpu-no-workitem-id-x",
"amdgpu-no-workitem-id-y",
1330 "amdgpu-no-workitem-id-z",
"amdgpu-no-heap-ptr"});
1331 reorderStaticDynamicIndirectLDSSet(LDSParams);
1332 buildSwLDSGlobal(Func);
1333 buildSwDynLDSGlobal(Func);
1334 populateSwMetadataGlobal(Func);
1335 populateSwLDSAttributeAndMetadata(Func);
1336 populateLDSToReplacementIndicesMap(Func);
1337 DomTreeUpdater DTU(DTCallback(*Func), DomTreeUpdater::UpdateStrategy::Lazy);
1338 lowerKernelLDSAccesses(Func, DTU);
1343 getUsesOfLDSByNonKernels();
1346 getNonKernelsWithLDSInstructions(CG);
1350 for (
Function *Func : FuncLDSAccessInfo.KernelsWithIndirectLDSAccess)
1354 if (!FuncLDSAccessInfo.NonKernelToLDSAccessMap.
empty() ||
1355 !FuncLDSAccessInfo.NonKernelsWithLDSInstructions.
empty()) {
1356 NonKernelLDSParameters NKLDSParams;
1357 NKLDSParams.OrderedKernels = getOrderedIndirectLDSAccessingKernels(
1358 FuncLDSAccessInfo.KernelsWithIndirectLDSAccess);
1359 NKLDSParams.OrdereLDSGlobals = getOrderedNonKernelAllLDSGlobals(
1360 FuncLDSAccessInfo.AllNonKernelLDSAccess);
1361 buildNonKernelLDSBaseTable(NKLDSParams);
1362 buildNonKernelLDSOffsetTable(NKLDSParams);
1363 for (
auto &
K : FuncLDSAccessInfo.NonKernelToLDSAccessMap) {
1367 std::vector<GlobalVariable *>(LDSGlobals.
begin(), LDSGlobals.
end()));
1368 lowerNonKernelLDSAccesses(Func, OrderedLDSGlobals, NKLDSParams);
1370 for (
Function *Func : FuncLDSAccessInfo.NonKernelsWithLDSInstructions) {
1371 if (FuncLDSAccessInfo.NonKernelToLDSAccessMap.
contains(Func))
1374 lowerNonKernelLDSAccesses(Func, NoLDSGlobals, NKLDSParams);
1392 .getLibraryOptions()
1393 .get<AMDGPUOptions>()
1394 .asan_instrument_lds) {
1401 for (
auto &Operand : OperandsToInstrument) {
1402 Value *Addr = Operand.getPtr();
1404 Operand.Alignment.valueOrOne(), Operand.TypeStoreSize,
1405 Operand.IsWrite,
nullptr,
false,
false, AsanInfo.Scale,
1414class AMDGPUSwLowerLDSLegacy :
public ModulePass {
1418 bool runOnModule(
Module &M)
override;
1425char AMDGPUSwLowerLDSLegacy::ID = 0;
1429 "AMDGPU Software lowering of LDS",
false,
false)
1434bool AMDGPUSwLowerLDSLegacy::runOnModule(
Module &M) {
1437 if (!M.getModuleFlag(
"nosanitize_address"))
1440 getAnalysisIfAvailable<DominatorTreeWrapperPass>();
1442 return DTW ? &DTW->getDomTree() : nullptr;
1445 AMDGPUSwLowerLDS SwLowerLDSImpl(M, DTCallback);
1446 bool IsChanged = SwLowerLDSImpl.run();
1451 return new AMDGPUSwLowerLDSLegacy();
1458 if (!M.getModuleFlag(
"nosanitize_address"))
1464 AMDGPUSwLowerLDS SwLowerLDSImpl(M, DTCallback);
1465 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.
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.