195#include "llvm/IR/IntrinsicsAMDGPU.h"
212#define DEBUG_TYPE "amdgpu-lower-module-lds"
219 "amdgpu-super-align-lds-globals",
220 cl::desc(
"Increase alignment of LDS if it is not on align boundary"),
223enum class LoweringKind { module, table, kernel, hybrid };
225 "amdgpu-lower-module-lds-strategy",
229 clEnumValN(LoweringKind::table,
"table",
"Lower via table lookup"),
230 clEnumValN(LoweringKind::module,
"module",
"Lower via module struct"),
232 LoweringKind::kernel,
"kernel",
233 "Lower variables reachable from one kernel, otherwise abort"),
235 "Lower via mixture of above strategies")));
248template <
typename T> std::vector<T> sortByName(std::vector<T> &&V) {
249 llvm::sort(V.begin(), V.end(), [](
const auto *L,
const auto *R) {
250 return L->getName() < R->getName();
252 return {std::move(V)};
255class AMDGPULowerModuleLDS {
259 removeLocalVarsFromUsedLists(
Module &M,
265 LocalVarsSet.
insert(cast<Constant>(LocalVar->stripPointerCasts()));
271 LocalVar->removeDeadConstantUsers();
296 IRBuilder<> Builder(Entry, Entry->getFirstNonPHIIt());
301 Value *UseInstance[1] = {
308 static bool eliminateConstantExprUsesOfLDSFromAllInstructions(
Module &M) {
323 for (
auto &GV : M.globals())
338 FunctionVariableMap &kernels,
343 for (
auto &GV : M.globals()) {
348 for (
User *V : GV.users()) {
349 if (
auto *
I = dyn_cast<Instruction>(V)) {
351 if (isKernelLDS(
F)) {
352 kernels[
F].insert(&GV);
361 struct LDSUsesInfoTy {
362 FunctionVariableMap direct_access;
363 FunctionVariableMap indirect_access;
366 static LDSUsesInfoTy getTransitiveUsesOfLDS(
CallGraph const &CG,
Module &M) {
368 FunctionVariableMap direct_map_kernel;
369 FunctionVariableMap direct_map_function;
370 getUsesOfLDSByFunction(CG, M, direct_map_kernel, direct_map_function);
375 if (!isKernelLDS(&
F))
376 if (
F.hasAddressTaken(
nullptr,
381 set_union(VariablesReachableThroughFunctionPointer,
382 direct_map_function[&
F]);
386 auto functionMakesUnknownCall = [&](
const Function *
F) ->
bool {
389 if (!R.second->getFunction()) {
397 FunctionVariableMap transitive_map_function = direct_map_function;
402 if (!
F.isDeclaration() && functionMakesUnknownCall(&
F)) {
403 if (!isKernelLDS(&
F)) {
405 VariablesReachableThroughFunctionPointer);
412 for (
Function &Func : M.functions()) {
413 if (Func.isDeclaration() || isKernelLDS(&Func))
419 while (!wip.empty()) {
424 set_union(transitive_map_function[&Func], direct_map_function[
F]);
427 Function *ith = R.second->getFunction();
440 FunctionVariableMap indirect_map_kernel;
442 for (
Function &Func : M.functions()) {
443 if (Func.isDeclaration() || !isKernelLDS(&Func))
447 Function *ith = R.second->getFunction();
449 set_union(indirect_map_kernel[&Func], transitive_map_function[ith]);
452 VariablesReachableThroughFunctionPointer);
461 std::optional<bool> HasAbsoluteGVs;
462 for (
auto &Map : {direct_map_kernel, indirect_map_kernel}) {
463 for (
auto &[Fn, GVs] : Map) {
464 for (
auto *GV : GVs) {
465 bool IsAbsolute = GV->isAbsoluteSymbolRef();
466 if (HasAbsoluteGVs.has_value()) {
467 if (*HasAbsoluteGVs != IsAbsolute) {
469 "Module cannot mix absolute and non-absolute LDS GVs");
472 HasAbsoluteGVs = IsAbsolute;
479 if (HasAbsoluteGVs && *HasAbsoluteGVs)
480 return {FunctionVariableMap(), FunctionVariableMap()};
482 return {std::move(direct_map_kernel), std::move(indirect_map_kernel)};
485 struct LDSVariableReplacement {
495 static Constant *getAddressesOfVariablesInKernel(
505 ArrayType *KernelOffsetsType = ArrayType::get(I32, Variables.
size());
508 for (
size_t i = 0; i < Variables.
size(); i++) {
510 auto ConstantGepIt = LDSVarsToConstantGEP.
find(GV);
511 if (ConstantGepIt != LDSVarsToConstantGEP.
end()) {
513 Elements.push_back(elt);
525 if (Variables.
empty()) {
530 const size_t NumberVariables = Variables.
size();
531 const size_t NumberKernels = kernels.size();
537 ArrayType::get(KernelOffsetsType, NumberKernels);
540 std::vector<Constant *> overallConstantExprElts(NumberKernels);
541 for (
size_t i = 0; i < NumberKernels; i++) {
542 auto Replacement = KernelToReplacement.
find(kernels[i]);
543 overallConstantExprElts[i] =
544 (Replacement == KernelToReplacement.
end())
546 : getAddressesOfVariablesInKernel(
547 Ctx, Variables, Replacement->second.LDSVarsToConstantGEP);
562 Value *OptionalIndex) {
566 auto *
I = cast<Instruction>(U.getUser());
568 Value *tableKernelIndex = getTableLookupKernelIndex(M,
I->getFunction());
570 if (
auto *Phi = dyn_cast<PHINode>(
I)) {
578 ConstantInt::get(I32, 0),
585 LookupTable->getValueType(), LookupTable, GEPIdx, GV->
getName());
595 void replaceUsesInInstructionsWithTableLookup(
604 auto *GV = ModuleScopeVariables[
Index];
607 auto *
I = dyn_cast<Instruction>(U.getUser());
611 replaceUseWithTableLookup(M, Builder, LookupTable, GV, U,
612 ConstantInt::get(I32,
Index));
618 Module &M, LDSUsesInfoTy &LDSUsesInfo,
623 if (VariableSet.
empty())
626 for (
Function &Func : M.functions()) {
627 if (Func.isDeclaration() || !isKernelLDS(&Func))
631 KernelSet.insert(&Func);
641 chooseBestVariableForModuleStrategy(
const DataLayout &
DL,
642 VariableFunctionMap &LDSVars) {
647 size_t UserCount = 0;
650 CandidateTy() =
default;
653 : GV(GV), UserCount(UserCount),
Size(AllocSize) {}
657 if (UserCount <
Other.UserCount) {
660 if (UserCount >
Other.UserCount) {
678 CandidateTy MostUsed;
680 for (
auto &K : LDSVars) {
682 if (K.second.size() <= 1) {
687 CandidateTy Candidate(
690 if (MostUsed < Candidate)
691 MostUsed = Candidate;
715 auto [It, Inserted] = tableKernelIndexCache.
try_emplace(
F);
720 auto InsertAt =
F->getEntryBlock().getFirstNonPHIOrDbgOrAlloca();
729 static std::vector<Function *> assignLDSKernelIDToEachKernel(
737 std::vector<Function *> OrderedKernels;
738 if (!KernelsThatAllocateTableLDS.
empty() ||
739 !KernelsThatIndirectlyAllocateDynamicLDS.
empty()) {
741 for (
Function &Func : M->functions()) {
742 if (Func.isDeclaration())
744 if (!isKernelLDS(&Func))
747 if (KernelsThatAllocateTableLDS.
contains(&Func) ||
748 KernelsThatIndirectlyAllocateDynamicLDS.
contains(&Func)) {
750 OrderedKernels.push_back(&Func);
755 OrderedKernels = sortByName(std::move(OrderedKernels));
761 if (OrderedKernels.size() > UINT32_MAX) {
766 for (
size_t i = 0; i < OrderedKernels.size(); i++) {
770 OrderedKernels[i]->setMetadata(
"llvm.amdgcn.lds.kernel.id",
774 return OrderedKernels;
777 static void partitionVariablesIntoIndirectStrategies(
778 Module &M, LDSUsesInfoTy
const &LDSUsesInfo,
779 VariableFunctionMap &LDSToKernelsThatNeedToAccessItIndirectly,
786 LoweringKindLoc != LoweringKind::hybrid
788 : chooseBestVariableForModuleStrategy(
789 M.getDataLayout(), LDSToKernelsThatNeedToAccessItIndirectly);
794 ? LDSToKernelsThatNeedToAccessItIndirectly[HybridModuleRoot]
797 for (
auto &K : LDSToKernelsThatNeedToAccessItIndirectly) {
803 assert(K.second.size() != 0);
806 DynamicVariables.
insert(GV);
810 switch (LoweringKindLoc) {
811 case LoweringKind::module:
812 ModuleScopeVariables.insert(GV);
815 case LoweringKind::table:
816 TableLookupVariables.
insert(GV);
819 case LoweringKind::kernel:
820 if (K.second.size() == 1) {
821 KernelAccessVariables.
insert(GV);
824 "cannot lower LDS '" + GV->
getName() +
825 "' to kernel access as it is reachable from multiple kernels");
829 case LoweringKind::hybrid: {
830 if (GV == HybridModuleRoot) {
831 assert(K.second.size() != 1);
832 ModuleScopeVariables.insert(GV);
833 }
else if (K.second.size() == 1) {
834 KernelAccessVariables.
insert(GV);
835 }
else if (
set_is_subset(K.second, HybridModuleRootKernels)) {
836 ModuleScopeVariables.insert(GV);
838 TableLookupVariables.
insert(GV);
847 assert(ModuleScopeVariables.
size() + TableLookupVariables.
size() +
848 KernelAccessVariables.
size() + DynamicVariables.
size() ==
849 LDSToKernelsThatNeedToAccessItIndirectly.size());
862 if (ModuleScopeVariables.
empty()) {
868 LDSVariableReplacement ModuleScopeReplacement =
869 createLDSVariableReplacement(M,
"llvm.amdgcn.module.lds",
870 ModuleScopeVariables);
874 cast<Constant>(ModuleScopeReplacement.SGV),
875 PointerType::getUnqual(Ctx)))});
878 recordLDSAbsoluteAddress(&M, ModuleScopeReplacement.SGV, 0);
881 removeLocalVarsFromUsedLists(M, ModuleScopeVariables);
884 replaceLDSVariablesWithStruct(
885 M, ModuleScopeVariables, ModuleScopeReplacement, [&](
Use &U) {
891 return !isKernelLDS(
F);
898 for (
Function &Func : M.functions()) {
899 if (Func.isDeclaration() || !isKernelLDS(&Func))
902 if (KernelsThatAllocateModuleLDS.
contains(&Func)) {
903 replaceLDSVariablesWithStruct(
904 M, ModuleScopeVariables, ModuleScopeReplacement, [&](
Use &U) {
913 markUsedByKernel(&Func, ModuleScopeReplacement.SGV);
917 return ModuleScopeReplacement.SGV;
921 lowerKernelScopeStructVariables(
922 Module &M, LDSUsesInfoTy &LDSUsesInfo,
930 for (
Function &Func : M.functions()) {
931 if (Func.isDeclaration() || !isKernelLDS(&Func))
937 for (
auto &v : LDSUsesInfo.direct_access[&Func]) {
939 KernelUsedVariables.
insert(v);
945 for (
auto &v : LDSUsesInfo.indirect_access[&Func]) {
947 KernelUsedVariables.
insert(v);
953 if (KernelsThatAllocateModuleLDS.
contains(&Func)) {
955 KernelUsedVariables.
erase(v);
959 if (KernelUsedVariables.
empty()) {
971 if (!Func.hasName()) {
975 std::string VarName =
976 (
Twine(
"llvm.amdgcn.kernel.") + Func.getName() +
".lds").str();
979 createLDSVariableReplacement(M, VarName, KernelUsedVariables);
984 auto Accesses = LDSUsesInfo.indirect_access.find(&Func);
985 if ((Accesses != LDSUsesInfo.indirect_access.end()) &&
986 !Accesses->second.empty())
987 markUsedByKernel(&Func, Replacement.SGV);
990 removeLocalVarsFromUsedLists(M, KernelUsedVariables);
991 KernelToReplacement[&Func] = Replacement;
994 replaceLDSVariablesWithStruct(
995 M, KernelUsedVariables, Replacement, [&Func](
Use &U) {
997 return I &&
I->getFunction() == &Func;
1000 return KernelToReplacement;
1004 buildRepresentativeDynamicLDSInstance(
Module &M, LDSUsesInfoTy &LDSUsesInfo,
1016 assert(isKernelLDS(func));
1020 Align MaxDynamicAlignment(1);
1022 auto UpdateMaxAlignment = [&MaxDynamicAlignment, &
DL](
GlobalVariable *GV) {
1024 MaxDynamicAlignment =
1030 UpdateMaxAlignment(GV);
1034 UpdateMaxAlignment(GV);
1043 N->setAlignment(MaxDynamicAlignment);
1057 bool SeenUnknownCall =
false;
1059 while (!WorkList.empty()) {
1062 for (
auto &CallRecord : *CG[
F]) {
1063 if (!CallRecord.second)
1066 Function *Callee = CallRecord.second->getFunction();
1068 if (!SeenUnknownCall) {
1069 SeenUnknownCall =
true;
1078 if (!isKernelLDS(PotentialCallee))
1079 PotentialCallee->
removeFnAttr(
"amdgpu-no-lds-kernel-id");
1083 Callee->removeFnAttr(
"amdgpu-no-lds-kernel-id");
1084 if (Visited.
insert(Callee).second)
1085 WorkList.push_back(Callee);
1092 Module &M, LDSUsesInfoTy &LDSUsesInfo,
1095 std::vector<Function *>
const &OrderedKernels) {
1097 if (!KernelsThatIndirectlyAllocateDynamicLDS.
empty()) {
1102 std::vector<Constant *> newDynamicLDS;
1105 for (
auto &func : OrderedKernels) {
1107 if (KernelsThatIndirectlyAllocateDynamicLDS.
contains(func)) {
1108 assert(isKernelLDS(func));
1114 buildRepresentativeDynamicLDSInstance(M, LDSUsesInfo, func);
1116 KernelToCreatedDynamicLDS[func] =
N;
1118 markUsedByKernel(func,
N);
1122 emptyCharArray,
N, ConstantInt::get(I32, 0),
true);
1128 assert(OrderedKernels.size() == newDynamicLDS.size());
1130 ArrayType *t = ArrayType::get(I32, newDynamicLDS.size());
1134 "llvm.amdgcn.dynlds.offset.table",
nullptr,
1139 auto *
I = dyn_cast<Instruction>(U.getUser());
1142 if (isKernelLDS(
I->getFunction()))
1145 replaceUseWithTableLookup(M, Builder, table, GV, U,
nullptr);
1149 return KernelToCreatedDynamicLDS;
1152 bool runOnModule(
Module &M) {
1154 bool Changed = superAlignLDSGlobals(M);
1156 Changed |= eliminateConstantExprUsesOfLDSFromAllInstructions(M);
1162 LDSUsesInfoTy LDSUsesInfo = getTransitiveUsesOfLDS(CG, M);
1165 VariableFunctionMap LDSToKernelsThatNeedToAccessItIndirectly;
1166 for (
auto &K : LDSUsesInfo.indirect_access) {
1170 LDSToKernelsThatNeedToAccessItIndirectly[GV].insert(
F);
1179 partitionVariablesIntoIndirectStrategies(
1180 M, LDSUsesInfo, LDSToKernelsThatNeedToAccessItIndirectly,
1181 ModuleScopeVariables, TableLookupVariables, KernelAccessVariables,
1188 kernelsThatIndirectlyAccessAnyOfPassedVariables(M, LDSUsesInfo,
1189 ModuleScopeVariables);
1191 kernelsThatIndirectlyAccessAnyOfPassedVariables(M, LDSUsesInfo,
1192 TableLookupVariables);
1195 kernelsThatIndirectlyAccessAnyOfPassedVariables(M, LDSUsesInfo,
1198 GlobalVariable *MaybeModuleScopeStruct = lowerModuleScopeStructVariables(
1199 M, ModuleScopeVariables, KernelsThatAllocateModuleLDS);
1202 lowerKernelScopeStructVariables(M, LDSUsesInfo, ModuleScopeVariables,
1203 KernelsThatAllocateModuleLDS,
1204 MaybeModuleScopeStruct);
1207 for (
auto &GV : KernelAccessVariables) {
1208 auto &funcs = LDSToKernelsThatNeedToAccessItIndirectly[GV];
1209 assert(funcs.size() == 1);
1210 LDSVariableReplacement Replacement =
1211 KernelToReplacement[*(funcs.begin())];
1216 replaceLDSVariablesWithStruct(M, Vec, Replacement, [](
Use &U) {
1217 return isa<Instruction>(U.getUser());
1222 std::vector<Function *> OrderedKernels =
1223 assignLDSKernelIDToEachKernel(&M, KernelsThatAllocateTableLDS,
1224 KernelsThatIndirectlyAllocateDynamicLDS);
1226 if (!KernelsThatAllocateTableLDS.
empty()) {
1232 auto TableLookupVariablesOrdered =
1233 sortByName(std::vector<GlobalVariable *>(TableLookupVariables.
begin(),
1234 TableLookupVariables.
end()));
1237 M, TableLookupVariablesOrdered, OrderedKernels, KernelToReplacement);
1238 replaceUsesInInstructionsWithTableLookup(M, TableLookupVariablesOrdered,
1245 for (
Function *
F : KernelsThatAllocateTableLDS)
1246 removeNoLdsKernelIdFromReachable(CG,
F);
1250 lowerDynamicLDSVariables(M, LDSUsesInfo,
1251 KernelsThatIndirectlyAllocateDynamicLDS,
1252 DynamicVariables, OrderedKernels);
1259 for (
Function &Func : M.functions()) {
1260 if (Func.isDeclaration() || !isKernelLDS(&Func))
1274 const bool AllocateModuleScopeStruct =
1275 MaybeModuleScopeStruct &&
1276 KernelsThatAllocateModuleLDS.
contains(&Func);
1278 auto Replacement = KernelToReplacement.
find(&Func);
1279 const bool AllocateKernelScopeStruct =
1280 Replacement != KernelToReplacement.
end();
1282 const bool AllocateDynamicVariable =
1283 KernelToCreatedDynamicLDS.
contains(&Func);
1287 if (AllocateModuleScopeStruct) {
1293 if (AllocateKernelScopeStruct) {
1296 recordLDSAbsoluteAddress(&M, KernelStruct,
Offset);
1304 if (AllocateDynamicVariable) {
1305 GlobalVariable *DynamicVariable = KernelToCreatedDynamicLDS[&Func];
1307 recordLDSAbsoluteAddress(&M, DynamicVariable,
Offset);
1322 if (AllocateDynamicVariable)
1325 Func.addFnAttr(
"amdgpu-lds-size", Buffer);
1344 static bool superAlignLDSGlobals(
Module &M) {
1346 bool Changed =
false;
1347 if (!SuperAlignLDSGlobals) {
1351 for (
auto &GV : M.globals()) {
1366 Alignment = std::max(Alignment,
Align(16));
1367 }
else if (GVSize > 4) {
1369 Alignment = std::max(Alignment,
Align(8));
1370 }
else if (GVSize > 2) {
1372 Alignment = std::max(Alignment,
Align(4));
1373 }
else if (GVSize > 1) {
1375 Alignment = std::max(Alignment,
Align(2));
1386 static LDSVariableReplacement createLDSVariableReplacement(
1387 Module &M, std::string VarName,
1404 auto Sorted = sortByName(std::vector<GlobalVariable *>(
1405 LDSVarsToTransform.
begin(), LDSVarsToTransform.
end()));
1417 std::vector<GlobalVariable *> LocalVars;
1420 IsPaddingField.
reserve(LDSVarsToTransform.
size());
1423 for (
size_t I = 0;
I < LayoutFields.
size();
I++) {
1425 const_cast<void *
>(LayoutFields[
I].Id));
1426 Align DataAlign = LayoutFields[
I].Alignment;
1429 if (
uint64_t Rem = CurrentOffset % DataAlignV) {
1430 uint64_t Padding = DataAlignV - Rem;
1442 CurrentOffset += Padding;
1445 LocalVars.push_back(FGV);
1447 CurrentOffset += LayoutFields[
I].
Size;
1451 std::vector<Type *> LocalVarTypes;
1452 LocalVarTypes.reserve(LocalVars.size());
1454 LocalVars.cbegin(), LocalVars.cend(), std::back_inserter(LocalVarTypes),
1469 for (
size_t I = 0;
I < LocalVars.size();
I++) {
1471 Constant *GEPIdx[] = {ConstantInt::get(I32, 0), ConstantInt::get(I32,
I)};
1473 if (IsPaddingField[
I]) {
1480 assert(Map.size() == LDSVarsToTransform.
size());
1481 return {SGV, std::move(Map)};
1484 template <
typename PredicateTy>
1485 static void replaceLDSVariablesWithStruct(
1487 const LDSVariableReplacement &Replacement, PredicateTy Predicate) {
1494 auto LDSVarsToTransform = sortByName(std::vector<GlobalVariable *>(
1495 LDSVarsToTransformArg.
begin(), LDSVarsToTransformArg.
end()));
1501 const size_t NumberVars = LDSVarsToTransform.
size();
1502 if (NumberVars > 1) {
1504 AliasScopes.
reserve(NumberVars);
1506 for (
size_t I = 0;
I < NumberVars;
I++) {
1510 NoAliasList.
append(&AliasScopes[1], AliasScopes.
end());
1515 for (
size_t I = 0;
I < NumberVars;
I++) {
1517 Constant *
GEP = Replacement.LDSVarsToConstantGEP.at(GV);
1521 APInt APOff(
DL.getIndexTypeSizeInBits(
GEP->getType()), 0);
1522 GEP->stripAndAccumulateInBoundsConstantOffsets(
DL, APOff);
1529 NoAliasList[
I - 1] = AliasScopes[
I - 1];
1535 refineUsesAlignmentAndAA(
GEP,
A,
DL, AliasScope, NoAlias);
1542 if (!
MaxDepth || (
A == 1 && !AliasScope))
1545 for (
User *U :
Ptr->users()) {
1546 if (
auto *
I = dyn_cast<Instruction>(U)) {
1547 if (AliasScope &&
I->mayReadOrWriteMemory()) {
1548 MDNode *AS =
I->getMetadata(LLVMContext::MD_alias_scope);
1551 I->setMetadata(LLVMContext::MD_alias_scope, AS);
1553 MDNode *NA =
I->getMetadata(LLVMContext::MD_noalias);
1555 I->setMetadata(LLVMContext::MD_noalias, NA);
1559 if (
auto *LI = dyn_cast<LoadInst>(U)) {
1560 LI->setAlignment(std::max(
A, LI->getAlign()));
1563 if (
auto *SI = dyn_cast<StoreInst>(U)) {
1564 if (SI->getPointerOperand() ==
Ptr)
1565 SI->setAlignment(std::max(
A, SI->getAlign()));
1568 if (
auto *AI = dyn_cast<AtomicRMWInst>(U)) {
1571 if (AI->getPointerOperand() ==
Ptr)
1572 AI->setAlignment(std::max(
A, AI->getAlign()));
1575 if (
auto *AI = dyn_cast<AtomicCmpXchgInst>(U)) {
1576 if (AI->getPointerOperand() ==
Ptr)
1577 AI->setAlignment(std::max(
A, AI->getAlign()));
1580 if (
auto *
GEP = dyn_cast<GetElementPtrInst>(U)) {
1581 unsigned BitWidth =
DL.getIndexTypeSizeInBits(
GEP->getType());
1583 if (
GEP->getPointerOperand() ==
Ptr) {
1585 if (
GEP->accumulateConstantOffset(
DL, Off))
1587 refineUsesAlignmentAndAA(
GEP, GA,
DL, AliasScope, NoAlias,
1592 if (
auto *
I = dyn_cast<Instruction>(U)) {
1593 if (
I->getOpcode() == Instruction::BitCast ||
1594 I->getOpcode() == Instruction::AddrSpaceCast)
1595 refineUsesAlignmentAndAA(
I,
A,
DL, AliasScope, NoAlias,
MaxDepth - 1);
1601class AMDGPULowerModuleLDSLegacy :
public ModulePass {
1618 auto &TPC = getAnalysis<TargetPassConfig>();
1622 return AMDGPULowerModuleLDS(*TM).runOnModule(M);
1627char AMDGPULowerModuleLDSLegacy::ID = 0;
1632 "Lower uses of LDS variables from non-kernel functions",
1641 return new AMDGPULowerModuleLDSLegacy(
TM);
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Lower uses of LDS variables from non kernel functions
The AMDGPU TargetMachine interface definition for hw codegen targets.
This file implements the BitVector class.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
This file provides interfaces used to build and manipulate a call graph, which is a very useful tool ...
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Given that RA is a live propagate it s liveness to any other values it uses(according to Uses). void DeadArgumentEliminationPass
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
std::optional< std::vector< StOtherPiece > > Other
static const unsigned MaxDepth
This file provides an interface for laying out a sequence of fields as a struct in a way that attempt...
const char LLVMTargetMachineRef TM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines generic set operations that may be used on set's of different types,...
Target-Independent Code Generator Pass Configuration Options pass.
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
A container for analyses that lazily runs them and caches their results.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
LLVM Basic Block Representation.
const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
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.
CallGraphNode * getExternalCallingNode() const
Returns the CallGraphNode which is used to represent undetermined calls into the callgraph.
static Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static Constant * getPointerBitCastOrAddrSpaceCast(Constant *C, Type *Ty)
Create a BitCast or AddrSpaceCast for a pointer type depending on the address space.
static Constant * getPtrToInt(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static Constant * getGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant * > IdxList, bool InBounds=false, std::optional< ConstantRange > InRange=std::nullopt, Type *OnlyIfReducedTy=nullptr)
Getelementptr form.
This is an important base class in LLVM.
void removeDeadConstantUsers() const
If there are any dead constant users dangling off of this constant, remove them.
A parsed version of the target data layout string in and methods for querying it.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&... Args)
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Implements a dense probed hash-table based set.
const Function & getFunction() const
void removeFnAttr(Attribute::AttrKind Kind)
Remove function attributes from this function.
void setMetadata(unsigned KindID, MDNode *Node)
Set a particular kind of metadata attachment.
void setAlignment(Align Align)
Sets the alignment attribute of the GlobalObject.
PointerType * getType() const
Global values are always pointers.
@ InternalLinkage
Rename collisions when linking (static functions).
@ ExternalLinkage
Externally visible function.
Type * getValueType() const
bool hasInitializer() const
Definitions have initializers, declarations don't.
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateConstInBoundsGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
Value * CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="")
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args=std::nullopt, const Twine &Name="", MDNode *FPMathTag=nullptr)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
This is an important class for using LLVM in a threaded context.
MDNode * createAnonymousAliasScope(MDNode *Domain, StringRef Name=StringRef())
Return metadata appropriate for an alias scope root node.
MDNode * createAnonymousAliasScopeDomain(StringRef Name=StringRef())
Return metadata appropriate for an alias scope domain node.
static MDNode * getMostGenericAliasScope(MDNode *A, MDNode *B)
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static MDNode * intersect(MDNode *A, MDNode *B)
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
virtual bool runOnModule(Module &M)=0
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
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.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
static 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 none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
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.
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Class to represent struct types.
static StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Target-Independent Code Generator Pass Configuration Options.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
static IntegerType * getInt8Ty(LLVMContext &C)
static IntegerType * getInt32Ty(LLVMContext &C)
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
void 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...
iterator_range< use_iterator > uses()
StringRef getName() const
Return a constant reference to the value's name.
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
bool erase(const ValueT &V)
A raw_ostream that writes to an std::string.
@ LOCAL_ADDRESS
Address space for local memory.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
LLVM_READNONE bool isKernel(CallingConv::ID CC)
bool isDynamicLDS(const GlobalVariable &GV)
Align getAlign(DataLayout const &DL, const GlobalVariable *GV)
bool isLDSVariableToLower(const GlobalVariable &GV)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=std::nullopt)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
bool operator<(int64_t V1, const APSInt &V2)
bool convertUsersOfConstantsToInstructions(ArrayRef< Constant * > Consts)
Replace constant expressions users of the given constants with instructions.
bool set_is_subset(const S1Ty &S1, const S2Ty &S2)
set_is_subset(A, B) - Return true iff A in B
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...
void initializeAMDGPULowerModuleLDSLegacyPass(PassRegistry &)
void sort(IteratorTy Start, IteratorTy End)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
char & AMDGPULowerModuleLDSLegacyPassID
bool set_union(S1Ty &S1, const S2Ty &S2)
set_union(A, B) - Compute A := A u B, return whether A changed.
void removeFromUsedLists(Module &M, function_ref< bool(Constant *)> ShouldRemove)
Removes global values from the llvm.used and llvm.compiler.used arrays.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
ModulePass * createAMDGPULowerModuleLDSLegacyPass(const AMDGPUTargetMachine *TM=nullptr)
void appendToCompilerUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.compiler.used list.
std::pair< uint64_t, Align > performOptimizedStructLayout(MutableArrayRef< OptimizedStructLayoutField > Fields)
Compute a layout for a struct containing the given fields, making a best-effort attempt to minimize t...
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
constexpr unsigned BitWidth
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
const AMDGPUTargetMachine & TM
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.