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 IRB.
CreateLoad(LI->getType(), Replacement, LI->getProperties());
699 AsanInfo.Instructions.
insert(NewLI);
700 LI->replaceAllUsesWith(NewLI);
701 LI->eraseFromParent();
703 Value *SIOperand =
SI->getPointerOperand();
705 getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, SIOperand);
707 SI->getProperties());
708 AsanInfo.Instructions.
insert(NewSI);
709 SI->replaceAllUsesWith(NewSI);
710 SI->eraseFromParent();
712 Value *RMWPtrOperand = RMW->getPointerOperand();
713 Value *RMWValOperand = RMW->getValOperand();
715 getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, RMWPtrOperand);
717 RMW->getOperation(), Replacement, RMWValOperand, RMW->getAlign(),
718 RMW->getOrdering(), RMW->getSyncScopeID());
720 AsanInfo.Instructions.
insert(NewRMW);
721 RMW->replaceAllUsesWith(NewRMW);
722 RMW->eraseFromParent();
724 Value *XCHGPtrOperand = XCHG->getPointerOperand();
726 getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, XCHGPtrOperand);
728 Replacement, XCHG->getCompareOperand(), XCHG->getNewValOperand(),
729 XCHG->getAlign(), XCHG->getSuccessOrdering(),
730 XCHG->getFailureOrdering(), XCHG->getSyncScopeID());
732 AsanInfo.Instructions.
insert(NewXCHG);
733 XCHG->replaceAllUsesWith(NewXCHG);
734 XCHG->eraseFromParent();
736 Value *NewDest =
MI->getRawDest();
738 NewDest = getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, NewDest);
741 if (
MI->isAtomic()) {
743 NewDest, MSI->getValue(), MSI->getLength(),
744 MSI->getDestAlign().valueOrOne(), MSI->getElementSizeInBytes());
746 NewMI = IRB.
CreateMemSet(NewDest, MSI->getValue(), MSI->getLength(),
751 Value *NewSrc = MTI->getRawSource();
753 NewSrc = getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, NewSrc);
754 if (
MI->isAtomic()) {
755 if (
MI->getIntrinsicID() ==
756 Intrinsic::memmove_element_unordered_atomic) {
758 NewDest, MTI->getDestAlign().valueOrOne(), NewSrc,
759 MTI->getSourceAlign().valueOrOne(), MTI->getLength(),
760 MTI->getElementSizeInBytes());
763 NewDest, MTI->getDestAlign().valueOrOne(), NewSrc,
764 MTI->getSourceAlign().valueOrOne(), MTI->getLength(),
765 MTI->getElementSizeInBytes());
769 MI->getIntrinsicID(), NewDest, MTI->getDestAlign(), NewSrc,
770 MTI->getSourceAlign(), MTI->getLength(),
775 AsanInfo.Instructions.
insert(NewMI);
776 MI->replaceAllUsesWith(NewMI);
777 MI->eraseFromParent();
779 Value *AIOperand = ASC->getPointerOperand();
781 getTranslatedGlobalMemoryPtrOfLDS(LoadMallocPtr, AIOperand);
787 ASC->eraseFromParent();
793void AMDGPUSwLowerLDS::poisonRedzones(
Function *Func,
Value *MallocPtr) {
794 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
798 "__asan_poison_region",
801 auto RedzonesVec = LDSParams.RedzoneOffsetAndSizeVector;
802 size_t VecSize = RedzonesVec.size();
803 for (
unsigned i = 0; i < VecSize; i++) {
804 auto &RedzonePair = RedzonesVec[i];
805 uint64_t RedzoneOffset = RedzonePair.first;
806 uint64_t RedzoneSize = RedzonePair.second;
808 IRB.
getInt8Ty(), MallocPtr, {IRB.getInt64(RedzoneOffset)});
811 {RedzoneAddress, IRB.
getInt64(RedzoneSize)});
815void AMDGPUSwLowerLDS::lowerKernelLDSAccesses(
Function *Func,
817 LLVM_DEBUG(
dbgs() <<
"Sw Lowering Kernel LDS for : " << Func->getName());
818 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
819 auto &Ctx = M.getContext();
820 auto *PrevEntryBlock = &Func->getEntryBlock();
822 getLDSMemoryInstructions(Func, LDSInstructions);
836 auto SplitIt = PrevEntryBlock->getFirstNonPHIOrDbgOrAlloca();
837 WIdBlock->splice(WIdBlock->end(), PrevEntryBlock, PrevEntryBlock->begin(),
842 AI->moveBefore(*WIdBlock, WIdBlock->end());
857 IRB.
CreateCondBr(WIdzCond, MallocBlock, PrevEntryBlock);
867 assert(SwLDS && SwLDSMetadata);
871 Value *CurrMallocSize;
877 for (
auto &GV : LDSGlobals) {
880 UniqueLDSGlobals.
insert(GV);
884 GetUniqueLDSGlobals(LDSParams.DirectAccess.StaticLDSGlobals);
885 GetUniqueLDSGlobals(LDSParams.IndirectAccess.StaticLDSGlobals);
886 unsigned NumStaticLDS = 1 + UniqueLDSGlobals.
size();
887 UniqueLDSGlobals.
clear();
890 auto *GEPForEndStaticLDSOffset =
892 {ConstantInt::get(Int32Ty, 0),
893 ConstantInt::get(Int32Ty, NumStaticLDS - 1),
894 ConstantInt::get(Int32Ty, 0)});
896 auto *GEPForEndStaticLDSSize =
898 {ConstantInt::get(Int32Ty, 0),
899 ConstantInt::get(Int32Ty, NumStaticLDS - 1),
900 ConstantInt::get(Int32Ty, 2)});
902 Value *EndStaticLDSOffset =
903 IRB.
CreateLoad(Int32Ty, GEPForEndStaticLDSOffset);
904 Value *EndStaticLDSSize = IRB.
CreateLoad(Int32Ty, GEPForEndStaticLDSSize);
905 CurrMallocSize = IRB.
CreateAdd(EndStaticLDSOffset, EndStaticLDSSize);
907 CurrMallocSize = IRB.
getInt32(MallocSize);
909 if (LDSParams.SwDynLDS) {
912 "Dynamic LDS size query is only supported for CO V5 and later.");
918 {ConstantInt::get(Int64Ty, COV5_HIDDEN_DYN_LDS_SIZE_ARG)});
919 UniqueLDSGlobals.
clear();
920 GetUniqueLDSGlobals(LDSParams.DirectAccess.DynamicLDSGlobals);
921 GetUniqueLDSGlobals(LDSParams.IndirectAccess.DynamicLDSGlobals);
922 updateMallocSizeForDynamicLDS(Func, &CurrMallocSize, HiddenDynLDSSize,
926 CurrMallocSize = IRB.
CreateZExt(CurrMallocSize, Int64Ty);
931 Intrinsic::returnaddress, IRB.
getPtrTy(
DL.getProgramAddressSpace()),
937 Value *MallocCall = IRB.
CreateCall(MallocFunc, {CurrMallocSize, RAPtrToInt});
946 poisonRedzones(Func, MallocPtr);
954 auto *XYZCondPhi = IRB.
CreatePHI(Int1Ty, 2,
"xyzCond");
956 XYZCondPhi->addIncoming(IRB.
getInt1(1), MallocBlock);
961 Value *LoadMallocPtr =
965 replaceKernelLDSAccesses(Func);
969 translateLDSMemoryOperationsToGlobalMemory(Func, LoadMallocPtr,
978 RI->eraseFromParent();
998 Intrinsic::returnaddress, IRB.
getPtrTy(
DL.getProgramAddressSpace()),
1002 IRB.
CreateCall(AsanFreeFunc, {MallocPtrToInt, RAPToInt});
1016Constant *AMDGPUSwLowerLDS::getAddressesOfVariablesInKernel(
1019 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
1023 auto *SwLDSMetadataStructType =
1029 for (
auto *GV : Variables) {
1030 auto It = LDSParams.LDSToReplacementIndicesMap.find(GV);
1031 if (It == LDSParams.LDSToReplacementIndicesMap.end()) {
1036 auto &Indices = It->second;
1037 Constant *GEPIdx[] = {ConstantInt::get(Int32Ty, Indices[0]),
1038 ConstantInt::get(Int32Ty, Indices[1]),
1039 ConstantInt::get(Int32Ty, Indices[2])};
1041 SwLDSMetadata, GEPIdx,
true);
1042 Elements.push_back(
GEP);
1047void AMDGPUSwLowerLDS::buildNonKernelLDSBaseTable(
1048 NonKernelLDSParameters &NKLDSParams) {
1052 auto &Kernels = NKLDSParams.OrderedKernels;
1053 if (Kernels.empty())
1055 const size_t NumberKernels = Kernels.size();
1058 std::vector<Constant *> OverallConstantExprElts(NumberKernels);
1059 for (
size_t i = 0; i < NumberKernels; i++) {
1061 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
1062 OverallConstantExprElts[i] = LDSParams.SwLDS;
1075void AMDGPUSwLowerLDS::buildNonKernelLDSOffsetTable(
1076 NonKernelLDSParameters &NKLDSParams) {
1084 auto &Variables = NKLDSParams.OrdereLDSGlobals;
1085 auto &Kernels = NKLDSParams.OrderedKernels;
1086 if (Variables.
empty() || Kernels.empty())
1088 const size_t NumberVariables = Variables.
size();
1089 const size_t NumberKernels = Kernels.size();
1096 std::vector<Constant *> overallConstantExprElts(NumberKernels);
1097 for (
size_t i = 0; i < NumberKernels; i++) {
1099 overallConstantExprElts[i] =
1100 getAddressesOfVariablesInKernel(Func, Variables);
1113void AMDGPUSwLowerLDS::lowerNonKernelLDSAccesses(
1115 NonKernelLDSParameters &NKLDSParams) {
1118 LLVM_DEBUG(
dbgs() <<
"Sw LDS lowering, lower non-kernel access for : "
1119 << Func->getName());
1120 auto InsertAt = Func->getEntryBlock().getFirstNonPHIOrDbgOrAlloca();
1125 getLDSMemoryInstructions(Func, LDSInstructions);
1127 auto *KernelId = IRB.
CreateIntrinsic(Intrinsic::amdgcn_lds_kernel_id, {});
1130 auto &OrdereLDSGlobals = NKLDSParams.OrdereLDSGlobals;
1132 LDSBaseTable->
getValueType(), LDSBaseTable, {IRB.getInt32(0), KernelId});
1135 Value *LoadMallocPtr =
1139 const auto *GVIt =
llvm::find(OrdereLDSGlobals, GV);
1140 assert(GVIt != OrdereLDSGlobals.end());
1141 uint32_t GVOffset = std::distance(OrdereLDSGlobals.begin(), GVIt);
1145 {IRB.getInt32(0), KernelId, IRB.getInt32(GVOffset)});
1149 Value *BasePlusOffset =
1151 LLVM_DEBUG(
dbgs() <<
"Sw LDS Lowering, Replace non-kernel LDS for "
1153 replacesUsesOfGlobalInFunction(Func, GV, BasePlusOffset);
1155 translateLDSMemoryOperationsToGlobalMemory(Func, LoadMallocPtr,
1159static void reorderStaticDynamicIndirectLDSSet(KernelLDSParameters &LDSParams) {
1162 auto &DirectAccess = LDSParams.DirectAccess;
1163 auto &IndirectAccess = LDSParams.IndirectAccess;
1164 LDSParams.DirectAccess.StaticLDSGlobals = sortByName(
1165 std::vector<GlobalVariable *>(DirectAccess.StaticLDSGlobals.begin(),
1166 DirectAccess.StaticLDSGlobals.end()));
1167 LDSParams.DirectAccess.DynamicLDSGlobals = sortByName(
1168 std::vector<GlobalVariable *>(DirectAccess.DynamicLDSGlobals.begin(),
1169 DirectAccess.DynamicLDSGlobals.end()));
1170 LDSParams.IndirectAccess.StaticLDSGlobals = sortByName(
1171 std::vector<GlobalVariable *>(IndirectAccess.StaticLDSGlobals.begin(),
1172 IndirectAccess.StaticLDSGlobals.end()));
1173 LDSParams.IndirectAccess.DynamicLDSGlobals = sortByName(
1174 std::vector<GlobalVariable *>(IndirectAccess.DynamicLDSGlobals.begin(),
1175 IndirectAccess.DynamicLDSGlobals.end()));
1178void AMDGPUSwLowerLDS::initAsanInfo() {
1184 bool OrShadowOffset;
1186 &Scale, &OrShadowOffset);
1187 AsanInfo.Scale = Scale;
1188 AsanInfo.Offset =
Offset;
1192 for (
auto &K : LDSAccesses) {
1196 if (
F->hasFnAttribute(Attribute::SanitizeAddress))
1202bool AMDGPUSwLowerLDS::run() {
1215 bool LowerAllLDS = hasFnWithSanitizeAddressAttr(LDSUsesInfo.
DirectAccess) ||
1223 bool DirectAccess) {
1224 for (
auto &K : LDSAccesses) {
1226 if (!
F || K.second.empty())
1232 FuncLDSAccessInfo.KernelToLDSParametersMap.insert(
1233 {
F, KernelLDSParameters()});
1235 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[
F];
1237 FuncLDSAccessInfo.KernelsWithIndirectLDSAccess.
insert(
F);
1239 if (!DirectAccess) {
1241 LDSParams.IndirectAccess.DynamicLDSGlobals.insert(GV);
1243 LDSParams.IndirectAccess.StaticLDSGlobals.insert(GV);
1244 FuncLDSAccessInfo.AllNonKernelLDSAccess.insert(GV);
1247 LDSParams.DirectAccess.DynamicLDSGlobals.insert(GV);
1249 LDSParams.DirectAccess.StaticLDSGlobals.insert(GV);
1255 PopulateKernelStaticDynamicLDS(LDSUsesInfo.
DirectAccess,
true);
1256 PopulateKernelStaticDynamicLDS(LDSUsesInfo.
IndirectAccess,
false);
1261 for (
auto &K : FuncLDSAccessInfo.KernelToLDSParametersMap) {
1263 auto &LDSParams = FuncLDSAccessInfo.KernelToLDSParametersMap[Func];
1264 if (LDSParams.DirectAccess.StaticLDSGlobals.empty() &&
1265 LDSParams.DirectAccess.DynamicLDSGlobals.empty() &&
1266 LDSParams.IndirectAccess.StaticLDSGlobals.empty() &&
1267 LDSParams.IndirectAccess.DynamicLDSGlobals.empty()) {
1272 {
"amdgpu-no-workitem-id-x",
"amdgpu-no-workitem-id-y",
1273 "amdgpu-no-workitem-id-z",
"amdgpu-no-heap-ptr"});
1274 if (!LDSParams.IndirectAccess.StaticLDSGlobals.empty() ||
1275 !LDSParams.IndirectAccess.DynamicLDSGlobals.empty())
1277 reorderStaticDynamicIndirectLDSSet(LDSParams);
1278 buildSwLDSGlobal(Func);
1279 buildSwDynLDSGlobal(Func);
1280 populateSwMetadataGlobal(Func);
1281 populateSwLDSAttributeAndMetadata(Func);
1282 populateLDSToReplacementIndicesMap(Func);
1284 DomTreeUpdater::UpdateStrategy::Lazy);
1285 lowerKernelLDSAccesses(Func, DTU);
1291 getUsesOfLDSByNonKernels();
1294 getNonKernelsWithLDSArguments(CG);
1297 if (!FuncLDSAccessInfo.NonKernelToLDSAccessMap.empty() ||
1298 !FuncLDSAccessInfo.NonKernelsWithLDSArgument.
empty()) {
1299 NonKernelLDSParameters NKLDSParams;
1300 NKLDSParams.OrderedKernels = getOrderedIndirectLDSAccessingKernels(
1301 FuncLDSAccessInfo.KernelsWithIndirectLDSAccess);
1302 NKLDSParams.OrdereLDSGlobals = getOrderedNonKernelAllLDSGlobals(
1303 FuncLDSAccessInfo.AllNonKernelLDSAccess);
1304 buildNonKernelLDSBaseTable(NKLDSParams);
1305 buildNonKernelLDSOffsetTable(NKLDSParams);
1306 for (
auto &K : FuncLDSAccessInfo.NonKernelToLDSAccessMap) {
1310 std::vector<GlobalVariable *>(LDSGlobals.
begin(), LDSGlobals.
end()));
1311 lowerNonKernelLDSAccesses(Func, OrderedLDSGlobals, NKLDSParams);
1313 for (
Function *Func : FuncLDSAccessInfo.NonKernelsWithLDSArgument) {
1314 auto &K = FuncLDSAccessInfo.NonKernelToLDSAccessMap;
1315 if (K.contains(Func))
1318 lowerNonKernelLDSAccesses(Func, Vec, NKLDSParams);
1335 if (AsanInstrumentLDS) {
1342 for (
auto &Operand : OperandsToInstrument) {
1343 Value *Addr = Operand.getPtr();
1345 Operand.Alignment.valueOrOne(), Operand.TypeStoreSize,
1346 Operand.IsWrite,
nullptr,
false,
false, AsanInfo.Scale,
1355class AMDGPUSwLowerLDSLegacy :
public ModulePass {
1359 bool runOnModule(
Module &M)
override;
1366char AMDGPUSwLowerLDSLegacy::ID = 0;
1370 "AMDGPU Software lowering of LDS",
false,
false)
1375bool AMDGPUSwLowerLDSLegacy::runOnModule(
Module &M) {
1378 if (!M.getModuleFlag(
"nosanitize_address"))
1381 getAnalysisIfAvailable<DominatorTreeWrapperPass>();
1383 return DTW ? &DTW->getDomTree() : nullptr;
1386 AMDGPUSwLowerLDS SwLowerLDSImpl(M, DTCallback);
1387 bool IsChanged = SwLowerLDSImpl.run();
1392 return new AMDGPUSwLowerLDSLegacy();
1399 if (!M.getModuleFlag(
"nosanitize_address"))
1405 AMDGPUSwLowerLDS SwLowerLDSImpl(M, DTCallback);
1406 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.
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.
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.
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.
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.