104#include "llvm/IR/IntrinsicsAMDGPU.h"
114#define DEBUG_TYPE "amdgpu-sw-lower-lds"
115#define COV5_HIDDEN_DYN_LDS_SIZE_ARG 15
123 AsanInstrumentLDS(
"amdgpu-asan-instrument-lds",
124 cl::desc(
"Run asan instrumentation on LDS instructions "
125 "lowered to global memory"),
130struct LDSAccessTypeInfo {
138struct KernelLDSParameters {
142 LDSAccessTypeInfo DirectAccess;
143 LDSAccessTypeInfo IndirectAccess;
145 LDSToReplacementIndicesMap;
153struct NonKernelLDSParameters {
160struct AsanInstrumentInfo {
166struct FunctionsAndLDSAccess {
174class AMDGPUSwLowerLDS {
176 AMDGPUSwLowerLDS(
Module &
Mod, DomTreeCallback Callback)
177 : M(
Mod), IRB(M.getContext()), DTCallback(Callback) {}
179 void getUsesOfLDSByNonKernels();
180 void getNonKernelsWithLDSArguments(
const CallGraph &CG);
185 void buildSwLDSGlobal(
Function *Func);
186 void buildSwDynLDSGlobal(
Function *Func);
187 void populateSwMetadataGlobal(
Function *Func);
188 void populateSwLDSAttributeAndMetadata(
Function *Func);
189 void populateLDSToReplacementIndicesMap(
Function *Func);
190 void getLDSMemoryInstructions(
Function *Func,
192 void replaceKernelLDSAccesses(
Function *Func);
193 Value *getTranslatedGlobalMemoryPtrOfLDS(
Value *LoadMallocPtr,
Value *LDSPtr);
194 void translateLDSMemoryOperationsToGlobalMemory(
199 void buildNonKernelLDSOffsetTable(NonKernelLDSParameters &NKLDSParams);
200 void buildNonKernelLDSBaseTable(NonKernelLDSParameters &NKLDSParams);
202 getAddressesOfVariablesInKernel(
Function *Func,
204 void lowerNonKernelLDSAccesses(
Function *Func,
206 NonKernelLDSParameters &NKLDSParams);
208 updateMallocSizeForDynamicLDS(
Function *Func,
Value **CurrMallocSize,
209 Value *HiddenDynLDSSize,
216 DomTreeCallback DTCallback;
217 FunctionsAndLDSAccess FuncLDSAccessInfo;
218 AsanInstrumentInfo AsanInfo;
221template <
typename T>
SetVector<T> sortByName(std::vector<T> &&V) {
224 sort(V, [](
const auto *L,
const auto *R) {
225 return L->getName() < R->getName();
234 std::vector<GlobalVariable *>(Variables.
begin(), Variables.
end()));
242 if (Kernels.size() > UINT32_MAX) {
246 sortByName(std::vector<Function *>(Kernels.begin(), Kernels.end()));
247 for (
size_t i = 0; i < Kernels.size(); i++) {
252 Func->setMetadata(
"llvm.amdgcn.lds.kernel.id",
255 return OrderedKernels;
258void AMDGPUSwLowerLDS::getNonKernelsWithLDSArguments(
const CallGraph &CG) {
262 for (
auto &K : FuncLDSAccessInfo.KernelToLDSParametersMap) {
267 for (
auto &
I : *CGN) {
276 Type *ArgTy = (*AI).getType();
281 FuncLDSAccessInfo.NonKernelsWithLDSArgument.
insert(CalledFunc);
284 FuncLDSAccessInfo.KernelsWithIndirectLDSAccess.
insert(Func);
290void AMDGPUSwLowerLDS::getUsesOfLDSByNonKernels() {
291 for (
GlobalVariable *GV : FuncLDSAccessInfo.AllNonKernelLDSAccess) {
299 FuncLDSAccessInfo.NonKernelToLDSAccessMap[
F].insert(GV);
313 ConstantInt::get(IntTy, Address + 1));
314 GV->
setMetadata(LLVMContext::MD_absolute_symbol, MetadataNode);
325 Func->addFnAttr(
"amdgpu-lds-size", Buffer);
331 IRBuilder<> Builder(Entry, Entry->getFirstNonPHIIt());
334 Intrinsic::donothing, {});
336 Value *UseInstance[1] = {
337 Builder.CreateConstInBoundsGEP1_32(SGV->
getValueType(), SGV, 0)};
339 Builder.CreateCall(Decl, {},
343void AMDGPUSwLowerLDS::buildSwLDSGlobal(
Function *Func) {
346 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
354 LDSParams.SwLDS->setSanitizerMetadata(MD);
357void AMDGPUSwLowerLDS::buildSwDynLDSGlobal(
Function *Func) {
359 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
360 if (LDSParams.DirectAccess.DynamicLDSGlobals.empty() &&
361 LDSParams.IndirectAccess.DynamicLDSGlobals.empty())
367 "llvm.amdgcn." + Func->getName() +
".dynlds",
nullptr,
369 markUsedByKernel(Func, LDSParams.SwDynLDS);
372 LDSParams.SwDynLDS->setSanitizerMetadata(MD);
375void AMDGPUSwLowerLDS::populateSwLDSAttributeAndMetadata(
Function *Func) {
376 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
377 bool IsDynLDSUsed = LDSParams.SwDynLDS;
379 recordLDSAbsoluteAddress(M, LDSParams.SwLDS, 0);
380 addLDSSizeAttribute(Func,
Offset, IsDynLDSUsed);
381 if (LDSParams.SwDynLDS)
382 recordLDSAbsoluteAddress(M, LDSParams.SwDynLDS,
Offset);
385void AMDGPUSwLowerLDS::populateSwMetadataGlobal(
Function *Func) {
388 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
389 auto &Ctx = M.getContext();
390 auto &
DL = M.getDataLayout();
391 std::vector<Type *> Items;
393 std::vector<Constant *> Initializers;
394 Align MaxAlignment(1);
397 MaxAlignment = std::max(MaxAlignment, GVAlign);
400 for (
GlobalVariable *GV : LDSParams.DirectAccess.StaticLDSGlobals)
401 UpdateMaxAlignment(GV);
403 for (
GlobalVariable *GV : LDSParams.DirectAccess.DynamicLDSGlobals)
404 UpdateMaxAlignment(GV);
406 for (
GlobalVariable *GV : LDSParams.IndirectAccess.StaticLDSGlobals)
407 UpdateMaxAlignment(GV);
409 for (
GlobalVariable *GV : LDSParams.IndirectAccess.DynamicLDSGlobals)
410 UpdateMaxAlignment(GV);
415 MDItemOS <<
"llvm.amdgcn.sw.lds." << Func->getName() <<
".md.item";
419 uint32_t &MallocSize = LDSParams.MallocSize;
421 int AsanScale = AsanInfo.Scale;
422 auto buildInitializerForSwLDSMD =
424 for (
auto &GV : LDSGlobals) {
427 UniqueLDSGlobals.
insert(GV);
430 const uint64_t SizeInBytes =
DL.getTypeAllocSize(Ty);
431 Items.push_back(LDSItemTy);
432 Constant *ItemStartOffset = ConstantInt::get(Int32Ty, MallocSize);
433 Constant *SizeInBytesConst = ConstantInt::get(Int32Ty, SizeInBytes);
438 MallocSize += SizeInBytes;
440 LDSParams.RedzoneOffsetAndSizeVector.emplace_back(MallocSize,
442 MallocSize += RightRedzoneSize;
445 alignTo(SizeInBytes + RightRedzoneSize, MaxAlignment);
447 ConstantInt::get(Int32Ty, AlignedSize);
449 MallocSize =
alignTo(MallocSize, MaxAlignment);
452 AlignedSizeInBytesConst});
453 Initializers.push_back(InitItem);
457 SwLDSVector.
insert(LDSParams.SwLDS);
458 buildInitializerForSwLDSMD(SwLDSVector);
459 buildInitializerForSwLDSMD(LDSParams.DirectAccess.StaticLDSGlobals);
460 buildInitializerForSwLDSMD(LDSParams.IndirectAccess.StaticLDSGlobals);
461 buildInitializerForSwLDSMD(LDSParams.DirectAccess.DynamicLDSGlobals);
462 buildInitializerForSwLDSMD(LDSParams.IndirectAccess.DynamicLDSGlobals);
465 Type *Ty = LDSParams.SwLDS->getValueType();
466 const uint64_t SizeInBytes =
DL.getTypeAllocSize(Ty);
468 LDSParams.LDSSize = AlignedSize;
471 MDTypeOS <<
"llvm.amdgcn.sw.lds." << Func->getName() <<
".md.type";
476 MDOS <<
"llvm.amdgcn.sw.lds." << Func->getName() <<
".md";
482 LDSParams.SwLDSMetadata->setInitializer(
data);
485 LDSParams.SwLDS->setAlignment(MaxAlignment);
486 if (LDSParams.SwDynLDS)
487 LDSParams.SwDynLDS->setAlignment(MaxAlignment);
490 LDSParams.SwLDSMetadata->setSanitizerMetadata(MD);
493void AMDGPUSwLowerLDS::populateLDSToReplacementIndicesMap(
Function *Func) {
496 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
500 for (
auto &GV : LDSGlobals) {
503 UniqueLDSGlobals.
insert(GV);
504 LDSParams.LDSToReplacementIndicesMap[GV] = {0, Idx, 0};
510 SwLDSVector.
insert(LDSParams.SwLDS);
511 PopulateIndices(SwLDSVector, Idx);
512 PopulateIndices(LDSParams.DirectAccess.StaticLDSGlobals, Idx);
513 PopulateIndices(LDSParams.IndirectAccess.StaticLDSGlobals, Idx);
514 PopulateIndices(LDSParams.DirectAccess.DynamicLDSGlobals, Idx);
515 PopulateIndices(LDSParams.IndirectAccess.DynamicLDSGlobals, Idx);
519 Value *Replacement) {
521 auto ReplaceUsesLambda = [Func](
const Use &U) ->
bool {
522 auto *V = U.getUser();
524 auto *Func1 = Inst->getFunction();
533void AMDGPUSwLowerLDS::replaceKernelLDSAccesses(
Function *Func) {
534 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
542 auto &IndirectAccess = LDSParams.IndirectAccess;
543 auto &DirectAccess = LDSParams.DirectAccess;
547 for (
auto &GV : LDSGlobals) {
550 if ((IndirectAccess.StaticLDSGlobals.contains(GV) ||
551 IndirectAccess.DynamicLDSGlobals.contains(GV)) &&
552 (!DirectAccess.StaticLDSGlobals.contains(GV) &&
553 !DirectAccess.DynamicLDSGlobals.contains(GV)))
557 UniqueLDSGlobals.
insert(GV);
558 auto &Indices = LDSParams.LDSToReplacementIndicesMap[GV];
559 assert(Indices.size() == 3);
560 Constant *GEPIdx[] = {ConstantInt::get(Int32Ty, Indices[0]),
561 ConstantInt::get(Int32Ty, Indices[1]),
562 ConstantInt::get(Int32Ty, Indices[2])};
564 SwLDSMetadataStructType, SwLDSMetadata, GEPIdx,
true);
566 Value *BasePlusOffset =
570 replacesUsesOfGlobalInFunction(Func, GV, BasePlusOffset);
573 ReplaceLDSGlobalUses(DirectAccess.StaticLDSGlobals);
574 ReplaceLDSGlobalUses(IndirectAccess.StaticLDSGlobals);
575 ReplaceLDSGlobalUses(DirectAccess.DynamicLDSGlobals);
576 ReplaceLDSGlobalUses(IndirectAccess.DynamicLDSGlobals);
579void AMDGPUSwLowerLDS::updateMallocSizeForDynamicLDS(
582 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
587 assert(SwLDS && SwLDSMetadata);
592 Value *MaxAlignValueMinusOne = IRB.
getInt32(MaxAlignment - 1);
595 auto &Indices = LDSParams.LDSToReplacementIndicesMap[DynGV];
597 Constant *Index0 = ConstantInt::get(Int32Ty, 0);
598 Constant *Index1 = ConstantInt::get(Int32Ty, Indices[1]);
600 Constant *Index2Offset = ConstantInt::get(Int32Ty, 0);
602 MetadataStructType, SwLDSMetadata, {Index0, Index1, Index2Offset});
606 Constant *Index2Size = ConstantInt::get(Int32Ty, 1);
608 {Index0, Index1, Index2Size});
612 Constant *Index2AlignedSize = ConstantInt::get(Int32Ty, 2);
614 MetadataStructType, SwLDSMetadata, {Index0, Index1, Index2AlignedSize});
616 Value *AlignedDynLDSSize =
617 IRB.
CreateAdd(CurrDynLDSSize, MaxAlignValueMinusOne);
618 AlignedDynLDSSize = IRB.
CreateUDiv(AlignedDynLDSSize, MaxAlignValue);
619 AlignedDynLDSSize = IRB.
CreateMul(AlignedDynLDSSize, MaxAlignValue);
620 IRB.
CreateStore(AlignedDynLDSSize, GEPForAlignedSize);
623 *CurrMallocSize = IRB.
CreateAdd(*CurrMallocSize, AlignedDynLDSSize);
637void AMDGPUSwLowerLDS::getLDSMemoryInstructions(
643 LDSInstructions.
insert(&Inst);
646 LDSInstructions.
insert(&Inst);
649 LDSInstructions.
insert(&Inst);
652 LDSInstructions.
insert(&Inst);
656 LDSInstructions.
insert(&Inst);
659 LDSInstructions.
insert(&Inst);
662 LDSInstructions.
insert(&Inst);
670Value *AMDGPUSwLowerLDS::getTranslatedGlobalMemoryPtrOfLDS(
Value *LoadMallocPtr,
672 assert(LDSPtr &&
"Invalid LDS pointer operand");
686void AMDGPUSwLowerLDS::translateLDSMemoryOperationsToGlobalMemory(
689 LLVM_DEBUG(
dbgs() <<
"Translating LDS memory operations to global memory : "
694 Value *LIOperand = LI->getPointerOperand();
696 getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, LIOperand);
698 LI->getAlign(), LI->isVolatile());
699 NewLI->
setAtomic(LI->getOrdering(), LI->getSyncScopeID());
700 AsanInfo.Instructions.
insert(NewLI);
701 LI->replaceAllUsesWith(NewLI);
702 LI->eraseFromParent();
704 Value *SIOperand =
SI->getPointerOperand();
706 getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, SIOperand);
708 SI->getValueOperand(), Replacement,
SI->getAlign(),
SI->isVolatile());
710 AsanInfo.Instructions.
insert(NewSI);
711 SI->replaceAllUsesWith(NewSI);
712 SI->eraseFromParent();
714 Value *RMWPtrOperand = RMW->getPointerOperand();
715 Value *RMWValOperand = RMW->getValOperand();
717 getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, RMWPtrOperand);
719 RMW->getOperation(), Replacement, RMWValOperand, RMW->getAlign(),
720 RMW->getOrdering(), RMW->getSyncScopeID());
722 AsanInfo.Instructions.
insert(NewRMW);
723 RMW->replaceAllUsesWith(NewRMW);
724 RMW->eraseFromParent();
726 Value *XCHGPtrOperand = XCHG->getPointerOperand();
728 getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, XCHGPtrOperand);
730 Replacement, XCHG->getCompareOperand(), XCHG->getNewValOperand(),
731 XCHG->getAlign(), XCHG->getSuccessOrdering(),
732 XCHG->getFailureOrdering(), XCHG->getSyncScopeID());
734 AsanInfo.Instructions.
insert(NewXCHG);
735 XCHG->replaceAllUsesWith(NewXCHG);
736 XCHG->eraseFromParent();
738 Value *NewDest =
MI->getRawDest();
740 NewDest = getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, NewDest);
743 if (
MI->isAtomic()) {
745 NewDest, MSI->getValue(), MSI->getLength(),
746 MSI->getDestAlign().valueOrOne(), MSI->getElementSizeInBytes());
748 NewMI = IRB.
CreateMemSet(NewDest, MSI->getValue(), MSI->getLength(),
753 Value *NewSrc = MTI->getRawSource();
755 NewSrc = getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, NewSrc);
756 if (
MI->isAtomic()) {
757 if (
MI->getIntrinsicID() ==
758 Intrinsic::memmove_element_unordered_atomic) {
760 NewDest, MTI->getDestAlign().valueOrOne(), NewSrc,
761 MTI->getSourceAlign().valueOrOne(), MTI->getLength(),
762 MTI->getElementSizeInBytes());
765 NewDest, MTI->getDestAlign().valueOrOne(), NewSrc,
766 MTI->getSourceAlign().valueOrOne(), MTI->getLength(),
767 MTI->getElementSizeInBytes());
771 MI->getIntrinsicID(), NewDest, MTI->getDestAlign(), NewSrc,
772 MTI->getSourceAlign(), MTI->getLength(),
777 AsanInfo.Instructions.
insert(NewMI);
778 MI->replaceAllUsesWith(NewMI);
779 MI->eraseFromParent();
781 Value *AIOperand = ASC->getPointerOperand();
783 getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, AIOperand);
789 ASC->eraseFromParent();
795void AMDGPUSwLowerLDS::poisonRedzones(
Function *Func,
Value *MallocPtr) {
796 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
800 "__asan_poison_region",
803 auto RedzonesVec = LDSParams.RedzoneOffsetAndSizeVector;
804 size_t VecSize = RedzonesVec.size();
805 for (
unsigned i = 0; i < VecSize; i++) {
806 auto &RedzonePair = RedzonesVec[i];
807 uint64_t RedzoneOffset = RedzonePair.first;
808 uint64_t RedzoneSize = RedzonePair.second;
810 IRB.
getInt8Ty(), MallocPtr, {IRB.getInt64(RedzoneOffset)});
813 {RedzoneAddress, IRB.
getInt64(RedzoneSize)});
817void AMDGPUSwLowerLDS::lowerKernelLDSAccesses(
Function *Func,
819 LLVM_DEBUG(
dbgs() <<
"Sw Lowering Kernel LDS for : " << Func->getName());
820 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
821 auto &Ctx = M.getContext();
822 auto *PrevEntryBlock = &Func->getEntryBlock();
824 getLDSMemoryInstructions(Func, LDSInstructions);
838 auto SplitIt = PrevEntryBlock->getFirstNonPHIOrDbgOrAlloca();
839 WIdBlock->splice(WIdBlock->end(), PrevEntryBlock, PrevEntryBlock->begin(),
844 AI->moveBefore(*WIdBlock, WIdBlock->end());
859 IRB.
CreateCondBr(WIdzCond, MallocBlock, PrevEntryBlock);
869 assert(SwLDS && SwLDSMetadata);
873 Value *CurrMallocSize;
879 for (
auto &GV : LDSGlobals) {
882 UniqueLDSGlobals.
insert(GV);
886 GetUniqueLDSGlobals(LDSParams.DirectAccess.StaticLDSGlobals);
887 GetUniqueLDSGlobals(LDSParams.IndirectAccess.StaticLDSGlobals);
888 unsigned NumStaticLDS = 1 + UniqueLDSGlobals.
size();
889 UniqueLDSGlobals.
clear();
892 auto *GEPForEndStaticLDSOffset =
894 {ConstantInt::get(Int32Ty, 0),
895 ConstantInt::get(Int32Ty, NumStaticLDS - 1),
896 ConstantInt::get(Int32Ty, 0)});
898 auto *GEPForEndStaticLDSSize =
900 {ConstantInt::get(Int32Ty, 0),
901 ConstantInt::get(Int32Ty, NumStaticLDS - 1),
902 ConstantInt::get(Int32Ty, 2)});
904 Value *EndStaticLDSOffset =
905 IRB.
CreateLoad(Int32Ty, GEPForEndStaticLDSOffset);
906 Value *EndStaticLDSSize = IRB.
CreateLoad(Int32Ty, GEPForEndStaticLDSSize);
907 CurrMallocSize = IRB.
CreateAdd(EndStaticLDSOffset, EndStaticLDSSize);
909 CurrMallocSize = IRB.
getInt32(MallocSize);
911 if (LDSParams.SwDynLDS) {
914 "Dynamic LDS size query is only supported for CO V5 and later.");
920 {ConstantInt::get(Int64Ty, COV5_HIDDEN_DYN_LDS_SIZE_ARG)});
921 UniqueLDSGlobals.
clear();
922 GetUniqueLDSGlobals(LDSParams.DirectAccess.DynamicLDSGlobals);
923 GetUniqueLDSGlobals(LDSParams.IndirectAccess.DynamicLDSGlobals);
924 updateMallocSizeForDynamicLDS(Func, &CurrMallocSize, HiddenDynLDSSize,
928 CurrMallocSize = IRB.
CreateZExt(CurrMallocSize, Int64Ty);
933 Intrinsic::returnaddress, IRB.
getPtrTy(
DL.getProgramAddressSpace()),
939 Value *MallocCall = IRB.
CreateCall(MallocFunc, {CurrMallocSize, RAPtrToInt});
948 poisonRedzones(Func, MallocPtr);
956 auto *XYZCondPhi = IRB.
CreatePHI(Int1Ty, 2,
"xyzCond");
958 XYZCondPhi->addIncoming(IRB.
getInt1(1), MallocBlock);
963 Value *LoadMallocPtr =
967 replaceKernelLDSAccesses(Func);
971 translateLDSMemoryOperationsToGlobalMemory(Func, LoadMallocPtr,
980 RI->eraseFromParent();
1000 Intrinsic::returnaddress, IRB.
getPtrTy(
DL.getProgramAddressSpace()),
1004 IRB.
CreateCall(AsanFreeFunc, {MallocPtrToInt, RAPToInt});
1018Constant *AMDGPUSwLowerLDS::getAddressesOfVariablesInKernel(
1021 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
1025 auto *SwLDSMetadataStructType =
1031 for (
auto *GV : Variables) {
1032 auto It = LDSParams.LDSToReplacementIndicesMap.find(GV);
1033 if (It == LDSParams.LDSToReplacementIndicesMap.end()) {
1038 auto &Indices = It->second;
1039 Constant *GEPIdx[] = {ConstantInt::get(Int32Ty, Indices[0]),
1040 ConstantInt::get(Int32Ty, Indices[1]),
1041 ConstantInt::get(Int32Ty, Indices[2])};
1043 SwLDSMetadata, GEPIdx,
true);
1044 Elements.push_back(
GEP);
1049void AMDGPUSwLowerLDS::buildNonKernelLDSBaseTable(
1050 NonKernelLDSParameters &NKLDSParams) {
1054 auto &Kernels = NKLDSParams.OrderedKernels;
1055 if (Kernels.empty())
1057 const size_t NumberKernels = Kernels.size();
1060 std::vector<Constant *> OverallConstantExprElts(NumberKernels);
1061 for (
size_t i = 0; i < NumberKernels; i++) {
1063 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
1064 OverallConstantExprElts[i] = LDSParams.SwLDS;
1077void AMDGPUSwLowerLDS::buildNonKernelLDSOffsetTable(
1078 NonKernelLDSParameters &NKLDSParams) {
1086 auto &Variables = NKLDSParams.OrdereLDSGlobals;
1087 auto &Kernels = NKLDSParams.OrderedKernels;
1088 if (Variables.
empty() || Kernels.empty())
1090 const size_t NumberVariables = Variables.
size();
1091 const size_t NumberKernels = Kernels.size();
1098 std::vector<Constant *> overallConstantExprElts(NumberKernels);
1099 for (
size_t i = 0; i < NumberKernels; i++) {
1101 overallConstantExprElts[i] =
1102 getAddressesOfVariablesInKernel(Func, Variables);
1115void AMDGPUSwLowerLDS::lowerNonKernelLDSAccesses(
1117 NonKernelLDSParameters &NKLDSParams) {
1120 LLVM_DEBUG(
dbgs() <<
"Sw LDS lowering, lower non-kernel access for : "
1121 << Func->getName());
1122 auto InsertAt = Func->getEntryBlock().getFirstNonPHIOrDbgOrAlloca();
1127 getLDSMemoryInstructions(Func, LDSInstructions);
1129 auto *KernelId = IRB.
CreateIntrinsic(Intrinsic::amdgcn_lds_kernel_id, {});
1132 auto &OrdereLDSGlobals = NKLDSParams.OrdereLDSGlobals;
1134 LDSBaseTable->
getValueType(), LDSBaseTable, {IRB.getInt32(0), KernelId});
1137 Value *LoadMallocPtr =
1141 const auto *GVIt =
llvm::find(OrdereLDSGlobals, GV);
1142 assert(GVIt != OrdereLDSGlobals.end());
1143 uint32_t GVOffset = std::distance(OrdereLDSGlobals.begin(), GVIt);
1147 {IRB.getInt32(0), KernelId, IRB.getInt32(GVOffset)});
1151 Value *BasePlusOffset =
1153 LLVM_DEBUG(
dbgs() <<
"Sw LDS Lowering, Replace non-kernel LDS for "
1155 replacesUsesOfGlobalInFunction(Func, GV, BasePlusOffset);
1157 translateLDSMemoryOperationsToGlobalMemory(Func, LoadMallocPtr,
1161static void reorderStaticDynamicIndirectLDSSet(KernelLDSParameters &LDSParams) {
1164 auto &DirectAccess = LDSParams.DirectAccess;
1165 auto &IndirectAccess = LDSParams.IndirectAccess;
1166 LDSParams.DirectAccess.StaticLDSGlobals = sortByName(
1167 std::vector<GlobalVariable *>(DirectAccess.StaticLDSGlobals.begin(),
1168 DirectAccess.StaticLDSGlobals.end()));
1169 LDSParams.DirectAccess.DynamicLDSGlobals = sortByName(
1170 std::vector<GlobalVariable *>(DirectAccess.DynamicLDSGlobals.begin(),
1171 DirectAccess.DynamicLDSGlobals.end()));
1172 LDSParams.IndirectAccess.StaticLDSGlobals = sortByName(
1173 std::vector<GlobalVariable *>(IndirectAccess.StaticLDSGlobals.begin(),
1174 IndirectAccess.StaticLDSGlobals.end()));
1175 LDSParams.IndirectAccess.DynamicLDSGlobals = sortByName(
1176 std::vector<GlobalVariable *>(IndirectAccess.DynamicLDSGlobals.begin(),
1177 IndirectAccess.DynamicLDSGlobals.end()));
1180void AMDGPUSwLowerLDS::initAsanInfo() {
1186 bool OrShadowOffset;
1188 &Scale, &OrShadowOffset);
1189 AsanInfo.Scale = Scale;
1190 AsanInfo.Offset =
Offset;
1194 for (
auto &K : LDSAccesses) {
1198 if (
F->hasFnAttribute(Attribute::SanitizeAddress))
1204bool AMDGPUSwLowerLDS::run() {
1217 bool LowerAllLDS = hasFnWithSanitizeAddressAttr(LDSUsesInfo.
DirectAccess) ||
1225 bool DirectAccess) {
1226 for (
auto &K : LDSAccesses) {
1228 if (!
F || K.second.empty())
1234 FuncLDSAccessInfo.KernelToLDSParametersMap.insert(
1235 {
F, KernelLDSParameters()});
1237 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[
F];
1239 FuncLDSAccessInfo.KernelsWithIndirectLDSAccess.
insert(
F);
1241 if (!DirectAccess) {
1243 LDSParams.IndirectAccess.DynamicLDSGlobals.insert(GV);
1245 LDSParams.IndirectAccess.StaticLDSGlobals.insert(GV);
1246 FuncLDSAccessInfo.AllNonKernelLDSAccess.insert(GV);
1249 LDSParams.DirectAccess.DynamicLDSGlobals.insert(GV);
1251 LDSParams.DirectAccess.StaticLDSGlobals.insert(GV);
1257 PopulateKernelStaticDynamicLDS(LDSUsesInfo.
DirectAccess,
true);
1258 PopulateKernelStaticDynamicLDS(LDSUsesInfo.
IndirectAccess,
false);
1263 for (
auto &K : FuncLDSAccessInfo.KernelToLDSParametersMap) {
1265 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
1266 if (LDSParams.DirectAccess.StaticLDSGlobals.empty() &&
1267 LDSParams.DirectAccess.DynamicLDSGlobals.empty() &&
1268 LDSParams.IndirectAccess.StaticLDSGlobals.empty() &&
1269 LDSParams.IndirectAccess.DynamicLDSGlobals.empty()) {
1274 {
"amdgpu-no-workitem-id-x",
"amdgpu-no-workitem-id-y",
1275 "amdgpu-no-workitem-id-z",
"amdgpu-no-heap-ptr"});
1276 if (!LDSParams.IndirectAccess.StaticLDSGlobals.empty() ||
1277 !LDSParams.IndirectAccess.DynamicLDSGlobals.empty())
1279 reorderStaticDynamicIndirectLDSSet(LDSParams);
1280 buildSwLDSGlobal(Func);
1281 buildSwDynLDSGlobal(Func);
1282 populateSwMetadataGlobal(Func);
1283 populateSwLDSAttributeAndMetadata(Func);
1284 populateLDSToReplacementIndicesMap(Func);
1286 DomTreeUpdater::UpdateStrategy::Lazy);
1287 lowerKernelLDSAccesses(Func, DTU);
1293 getUsesOfLDSByNonKernels();
1296 getNonKernelsWithLDSArguments(CG);
1299 if (!FuncLDSAccessInfo.NonKernelToLDSAccessMap.empty() ||
1300 !FuncLDSAccessInfo.NonKernelsWithLDSArgument.
empty()) {
1301 NonKernelLDSParameters NKLDSParams;
1302 NKLDSParams.OrderedKernels = getOrderedIndirectLDSAccessingKernels(
1303 FuncLDSAccessInfo.KernelsWithIndirectLDSAccess);
1304 NKLDSParams.OrdereLDSGlobals = getOrderedNonKernelAllLDSGlobals(
1305 FuncLDSAccessInfo.AllNonKernelLDSAccess);
1306 buildNonKernelLDSBaseTable(NKLDSParams);
1307 buildNonKernelLDSOffsetTable(NKLDSParams);
1308 for (
auto &K : FuncLDSAccessInfo.NonKernelToLDSAccessMap) {
1312 std::vector<GlobalVariable *>(LDSGlobals.
begin(), LDSGlobals.
end()));
1313 lowerNonKernelLDSAccesses(Func, OrderedLDSGlobals, NKLDSParams);
1315 for (
Function *Func : FuncLDSAccessInfo.NonKernelsWithLDSArgument) {
1316 auto &K = FuncLDSAccessInfo.NonKernelToLDSAccessMap;
1317 if (K.contains(Func))
1320 lowerNonKernelLDSAccesses(Func, Vec, NKLDSParams);
1337 if (AsanInstrumentLDS) {
1344 for (
auto &Operand : OperandsToInstrument) {
1345 Value *Addr = Operand.getPtr();
1347 Operand.Alignment.valueOrOne(), Operand.TypeStoreSize,
1348 Operand.IsWrite,
nullptr,
false,
false, AsanInfo.Scale,
1357class AMDGPUSwLowerLDSLegacy :
public ModulePass {
1361 bool runOnModule(
Module &M)
override;
1368char AMDGPUSwLowerLDSLegacy::ID = 0;
1372 "AMDGPU Software lowering of LDS",
false,
false)
1377bool AMDGPUSwLowerLDSLegacy::runOnModule(
Module &M) {
1380 if (!M.getModuleFlag(
"nosanitize_address"))
1383 getAnalysisIfAvailable<DominatorTreeWrapperPass>();
1385 return DTW ? &DTW->getDomTree() : nullptr;
1388 AMDGPUSwLowerLDS SwLowerLDSImpl(M, DTCallback);
1389 bool IsChanged = SwLowerLDSImpl.run();
1394 return new AMDGPUSwLowerLDSLegacy();
1401 if (!M.getModuleFlag(
"nosanitize_address"))
1407 AMDGPUSwLowerLDS SwLowerLDSImpl(M, DTCallback);
1408 bool IsChanged = SwLowerLDSImpl.run();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
The AMDGPU TargetMachine interface definition for hw codegen targets.
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...
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
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)
This file implements a set that has insertion order iteration characteristics.
Target-Independent Code Generator Pass Configuration Options pass.
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 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 * 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.
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.
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
uint64_t getAlignment() const
FIXME: Remove this function once transition to Align is over.
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.
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.
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, const char *Name)
CondBrInst * CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a conditional 'br Cond, TrueDest, FalseDest' instruction.
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="")
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)
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
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.
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)
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 * CreateAddrSpaceCast(Value *V, Type *DestTy, const Twine &Name="")
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.
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this load instruction.
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)
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.
void setAtomic(AtomicOrdering Ordering, SyncScope::ID SSID=SyncScope::System)
Sets the ordering constraint and the synchronization scope ID of this store instruction.
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)
DenseMap< 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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
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.