135#include "llvm/IR/IntrinsicsAMDGPU.h"
151#define DEBUG_TYPE "amdgpu-lower-module-lds"
158 "amdgpu-super-align-lds-globals",
159 cl::desc(
"Increase alignment of LDS if it is not on align boundary"),
162enum class LoweringKind { module, table, kernel, hybrid };
164 "amdgpu-lower-module-lds-strategy",
168 clEnumValN(LoweringKind::table,
"table",
"Lower via table lookup"),
169 clEnumValN(LoweringKind::module,
"module",
"Lower via module struct"),
171 LoweringKind::kernel,
"kernel",
172 "Lower variables reachable from one kernel, otherwise abort"),
174 "Lower via mixture of above strategies")));
184 return AMDGPU::isKernel(
F->getCallingConv());
187class AMDGPULowerModuleLDS :
public ModulePass {
190 removeLocalVarsFromUsedLists(
Module &M,
196 LocalVarsSet.
insert(cast<Constant>(LocalVar->stripPointerCasts()));
202 LocalVar->removeDeadConstantUsers();
230 Builder.SetInsertPoint(Func->getEntryBlock().getFirstNonPHI());
240 Builder.CreateCall(FTy, Decl, {},
245 static bool eliminateConstantExprUsesOfLDSFromAllInstructions(
Module &M) {
260 for (
auto &GV : M.globals())
261 if (AMDGPU::isLDSVariableToLower(GV))
279 FunctionVariableMap &kernels,
284 for (
auto &GV : M.globals()) {
285 if (!AMDGPU::isLDSVariableToLower(GV)) {
290 for (
User *V : GV.users()) {
291 if (
auto *
I = dyn_cast<Instruction>(V)) {
293 if (isKernelLDS(
F)) {
294 kernels[
F].insert(&GV);
303 struct LDSUsesInfoTy {
304 FunctionVariableMap direct_access;
305 FunctionVariableMap indirect_access;
308 static LDSUsesInfoTy getTransitiveUsesOfLDS(
CallGraph const &CG,
Module &M) {
310 FunctionVariableMap direct_map_kernel;
311 FunctionVariableMap direct_map_function;
312 getUsesOfLDSByFunction(CG, M, direct_map_kernel, direct_map_function);
317 if (!isKernelLDS(&
F))
318 if (
F.hasAddressTaken(
nullptr,
323 set_union(VariablesReachableThroughFunctionPointer,
324 direct_map_function[&
F]);
328 auto functionMakesUnknownCall = [&](
const Function *
F) ->
bool {
331 if (!R.second->getFunction()) {
339 FunctionVariableMap transitive_map_function = direct_map_function;
344 if (!
F.isDeclaration() && functionMakesUnknownCall(&
F)) {
345 if (!isKernelLDS(&
F)) {
347 VariablesReachableThroughFunctionPointer);
354 for (
Function &Func : M.functions()) {
355 if (Func.isDeclaration() || isKernelLDS(&Func))
361 while (!wip.empty()) {
366 set_union(transitive_map_function[&Func], direct_map_function[
F]);
369 Function *ith = R.second->getFunction();
382 FunctionVariableMap indirect_map_kernel;
384 for (
Function &Func : M.functions()) {
385 if (Func.isDeclaration() || !isKernelLDS(&Func))
389 Function *ith = R.second->getFunction();
391 set_union(indirect_map_kernel[&Func], transitive_map_function[ith]);
394 VariablesReachableThroughFunctionPointer);
399 return {std::move(direct_map_kernel), std::move(indirect_map_kernel)};
402 struct LDSVariableReplacement {
412 static Constant *getAddressesOfVariablesInKernel(
425 for (
size_t i = 0; i < Variables.
size(); i++) {
427 if (LDSVarsToConstantGEP.
count(GV) != 0) {
429 Elements.push_back(elt);
441 if (Variables.
empty()) {
446 const size_t NumberVariables = Variables.
size();
447 const size_t NumberKernels = kernels.size();
455 std::vector<Constant *> overallConstantExprElts(NumberKernels);
456 for (
size_t i = 0; i < NumberKernels; i++) {
457 LDSVariableReplacement Replacement = KernelToReplacement[kernels[i]];
458 overallConstantExprElts[i] = getAddressesOfVariablesInKernel(
459 Ctx, Variables, Replacement.LDSVarsToConstantGEP);
471 void replaceUsesInInstructionsWithTableLookup(
480 auto *GV = ModuleScopeVariables[
Index];
483 auto *
I = dyn_cast<Instruction>(U.getUser());
487 Value *tableKernelIndex =
488 getTableLookupKernelIndex(M,
I->getFunction());
492 if (
auto *Phi = dyn_cast<PHINode>(
I)) {
506 LookupTable->getValueType(), LookupTable, GEPIdx, GV->
getName());
519 Module &M, LDSUsesInfoTy &LDSUsesInfo,
524 if (VariableSet.
empty())
527 for (
Function &Func : M.functions()) {
528 if (Func.isDeclaration() || !isKernelLDS(&Func))
532 KernelSet.insert(&Func);
542 chooseBestVariableForModuleStrategy(
const DataLayout &
DL,
543 VariableFunctionMap &LDSVars) {
548 size_t UserCount = 0;
551 CandidateTy() =
default;
554 : GV(GV), UserCount(UserCount),
Size(AllocSize) {}
558 if (UserCount <
Other.UserCount) {
561 if (UserCount >
Other.UserCount) {
579 CandidateTy MostUsed;
581 for (
auto &K : LDSVars) {
583 if (K.second.size() <= 1) {
588 CandidateTy Candidate(
591 if (MostUsed < Candidate)
592 MostUsed = Candidate;
616 if (tableKernelIndexCache.
count(
F) == 0) {
624 F->getEntryBlock().getFirstNonPHIOrDbgOrAlloca();
628 tableKernelIndexCache[
F] =
Builder.CreateCall(FTy, Decl, {});
631 return tableKernelIndexCache[
F];
634 static std::vector<Function *> assignLDSKernelIDToEachKernel(
641 std::vector<Function *> OrderedKernels;
643 for (
Function &Func : M->functions()) {
644 if (Func.isDeclaration())
646 if (!isKernelLDS(&Func))
649 if (KernelsThatAllocateTableLDS.
contains(&Func)) {
651 OrderedKernels.push_back(&Func);
656 llvm::sort(OrderedKernels.begin(), OrderedKernels.end(),
658 return lhs->getName() < rhs->getName();
665 if (OrderedKernels.size() > UINT32_MAX) {
670 for (
size_t i = 0; i < OrderedKernels.size(); i++) {
674 OrderedKernels[i]->setMetadata(
"llvm.amdgcn.lds.kernel.id",
678 return OrderedKernels;
681 static void partitionVariablesIntoIndirectStrategies(
682 Module &M, LDSUsesInfoTy
const &LDSUsesInfo,
683 VariableFunctionMap &LDSToKernelsThatNeedToAccessItIndirectly,
689 LoweringKindLoc != LoweringKind::hybrid
691 : chooseBestVariableForModuleStrategy(
692 M.getDataLayout(), LDSToKernelsThatNeedToAccessItIndirectly);
697 ? LDSToKernelsThatNeedToAccessItIndirectly[HybridModuleRoot]
700 for (
auto &K : LDSToKernelsThatNeedToAccessItIndirectly) {
705 assert(AMDGPU::isLDSVariableToLower(*GV));
706 assert(K.second.size() != 0);
708 switch (LoweringKindLoc) {
709 case LoweringKind::module:
710 ModuleScopeVariables.insert(GV);
713 case LoweringKind::table:
714 TableLookupVariables.
insert(GV);
717 case LoweringKind::kernel:
718 if (K.second.size() == 1) {
719 KernelAccessVariables.
insert(GV);
722 "cannot lower LDS '" + GV->
getName() +
723 "' to kernel access as it is reachable from multiple kernels");
727 case LoweringKind::hybrid: {
728 if (GV == HybridModuleRoot) {
729 assert(K.second.size() != 1);
730 ModuleScopeVariables.insert(GV);
731 }
else if (K.second.size() == 1) {
732 KernelAccessVariables.
insert(GV);
733 }
else if (
set_is_subset(K.second, HybridModuleRootKernels)) {
734 ModuleScopeVariables.insert(GV);
736 TableLookupVariables.
insert(GV);
745 assert(ModuleScopeVariables.
size() + TableLookupVariables.
size() +
746 KernelAccessVariables.
size() ==
747 LDSToKernelsThatNeedToAccessItIndirectly.size());
760 if (ModuleScopeVariables.
empty()) {
766 LDSVariableReplacement ModuleScopeReplacement =
767 createLDSVariableReplacement(M,
"llvm.amdgcn.module.lds",
768 ModuleScopeVariables);
772 cast<Constant>(ModuleScopeReplacement.SGV),
776 recordLDSAbsoluteAddress(&M, ModuleScopeReplacement.SGV, 0);
779 removeLocalVarsFromUsedLists(M, ModuleScopeVariables);
782 replaceLDSVariablesWithStruct(
783 M, ModuleScopeVariables, ModuleScopeReplacement, [&](
Use &U) {
789 return !isKernelLDS(
F);
798 for (
Function &Func : M.functions()) {
799 if (Func.isDeclaration() || !isKernelLDS(&Func))
802 if (KernelsThatAllocateModuleLDS.
contains(&Func)) {
803 replaceLDSVariablesWithStruct(
804 M, ModuleScopeVariables, ModuleScopeReplacement, [&](
Use &U) {
813 markUsedByKernel(
Builder, &Func, ModuleScopeReplacement.SGV);
816 Func.addFnAttr(
"amdgpu-elide-module-lds");
820 return ModuleScopeReplacement.SGV;
824 lowerKernelScopeStructVariables(
825 Module &M, LDSUsesInfoTy &LDSUsesInfo,
833 for (
Function &Func : M.functions()) {
834 if (Func.isDeclaration() || !isKernelLDS(&Func))
840 for (
auto &v : LDSUsesInfo.direct_access[&Func]) {
841 KernelUsedVariables.
insert(v);
846 for (
auto &v : LDSUsesInfo.indirect_access[&Func]) {
847 KernelUsedVariables.
insert(v);
852 if (KernelsThatAllocateModuleLDS.
contains(&Func)) {
854 KernelUsedVariables.
erase(v);
858 if (KernelUsedVariables.
empty()) {
869 if (!Func.hasName()) {
873 std::string VarName =
874 (
Twine(
"llvm.amdgcn.kernel.") + Func.getName() +
".lds").str();
877 createLDSVariableReplacement(M, VarName, KernelUsedVariables);
890 if (!MaybeModuleScopeStruct ||
891 Func.hasFnAttribute(
"amdgpu-elide-module-lds")) {
894 recordLDSAbsoluteAddress(&M, Replacement.SGV, 0);
901 recordLDSAbsoluteAddress(&M, Replacement.SGV,
902 alignTo(ModuleSize, KernelAlign));
907 removeLocalVarsFromUsedLists(M, KernelUsedVariables);
908 KernelToReplacement[&Func] = Replacement;
911 replaceLDSVariablesWithStruct(
912 M, KernelUsedVariables, Replacement, [&Func](
Use &U) {
914 return I &&
I->getFunction() == &Func;
917 return KernelToReplacement;
922 bool Changed = superAlignLDSGlobals(M);
924 Changed |= eliminateConstantExprUsesOfLDSFromAllInstructions(M);
930 LDSUsesInfoTy LDSUsesInfo = getTransitiveUsesOfLDS(CG, M);
933 VariableFunctionMap LDSToKernelsThatNeedToAccessItIndirectly;
934 for (
auto &K : LDSUsesInfo.indirect_access) {
938 LDSToKernelsThatNeedToAccessItIndirectly[GV].insert(
F);
945 partitionVariablesIntoIndirectStrategies(
946 M, LDSUsesInfo, LDSToKernelsThatNeedToAccessItIndirectly,
947 ModuleScopeVariables, TableLookupVariables, KernelAccessVariables);
953 kernelsThatIndirectlyAccessAnyOfPassedVariables(M, LDSUsesInfo,
954 ModuleScopeVariables);
956 kernelsThatIndirectlyAccessAnyOfPassedVariables(M, LDSUsesInfo,
957 TableLookupVariables);
959 GlobalVariable *MaybeModuleScopeStruct = lowerModuleScopeStructVariables(
960 M, ModuleScopeVariables, KernelsThatAllocateModuleLDS);
963 lowerKernelScopeStructVariables(M, LDSUsesInfo, ModuleScopeVariables,
964 KernelsThatAllocateModuleLDS,
965 MaybeModuleScopeStruct);
968 for (
auto &GV : KernelAccessVariables) {
969 auto &funcs = LDSToKernelsThatNeedToAccessItIndirectly[GV];
970 assert(funcs.size() == 1);
971 LDSVariableReplacement Replacement =
972 KernelToReplacement[*(funcs.begin())];
979 replaceLDSVariablesWithStruct(M, Vec, Replacement, [](
Use &U) {
980 return isa<Instruction>(U.getUser());
984 if (!KernelsThatAllocateTableLDS.
empty()) {
989 std::vector<Function *> OrderedKernels =
990 assignLDSKernelIDToEachKernel(&M, KernelsThatAllocateTableLDS);
992 for (
size_t i = 0; i < OrderedKernels.size(); i++) {
993 markUsedByKernel(
Builder, OrderedKernels[i],
994 KernelToReplacement[OrderedKernels[i]].SGV);
999 std::vector<GlobalVariable *> TableLookupVariablesOrdered(
1000 TableLookupVariables.
begin(), TableLookupVariables.
end());
1001 llvm::sort(TableLookupVariablesOrdered.begin(),
1002 TableLookupVariablesOrdered.end(),
1004 return lhs->getName() < rhs->getName();
1008 M, TableLookupVariablesOrdered, OrderedKernels, KernelToReplacement);
1009 replaceUsesInInstructionsWithTableLookup(M, TableLookupVariablesOrdered,
1014 if (AMDGPU::isLDSVariableToLower(GV)) {
1027 static bool superAlignLDSGlobals(
Module &M) {
1029 bool Changed =
false;
1030 if (!SuperAlignLDSGlobals) {
1034 for (
auto &GV : M.globals()) {
1049 Alignment = std::max(Alignment,
Align(16));
1050 }
else if (GVSize > 4) {
1052 Alignment = std::max(Alignment,
Align(8));
1053 }
else if (GVSize > 2) {
1055 Alignment = std::max(Alignment,
Align(4));
1056 }
else if (GVSize > 1) {
1058 Alignment = std::max(Alignment,
Align(2));
1061 if (Alignment != AMDGPU::getAlign(
DL, &GV)) {
1069 static LDSVariableReplacement createLDSVariableReplacement(
1070 Module &M, std::string VarName,
1087 std::vector<GlobalVariable *> Sorted(LDSVarsToTransform.
begin(),
1088 LDSVarsToTransform.
end());
1091 return lhs->getName() < rhs->getName();
1096 AMDGPU::getAlign(
DL, GV));
1103 std::vector<GlobalVariable *> LocalVars;
1106 IsPaddingField.
reserve(LDSVarsToTransform.
size());
1109 for (
size_t I = 0;
I < LayoutFields.
size();
I++) {
1111 const_cast<void *
>(LayoutFields[
I].Id));
1112 Align DataAlign = LayoutFields[
I].Alignment;
1115 if (
uint64_t Rem = CurrentOffset % DataAlignV) {
1116 uint64_t Padding = DataAlignV - Rem;
1128 CurrentOffset += Padding;
1131 LocalVars.push_back(FGV);
1133 CurrentOffset += LayoutFields[
I].
Size;
1137 std::vector<Type *> LocalVarTypes;
1138 LocalVarTypes.reserve(LocalVars.size());
1140 LocalVars.cbegin(), LocalVars.cend(), std::back_inserter(LocalVarTypes),
1155 for (
size_t I = 0;
I < LocalVars.size();
I++) {
1159 if (IsPaddingField[
I]) {
1166 assert(Map.size() == LDSVarsToTransform.
size());
1167 return {SGV, std::move(Map)};
1170 template <
typename PredicateTy>
1171 static void replaceLDSVariablesWithStruct(
1173 LDSVariableReplacement Replacement, PredicateTy Predicate) {
1180 std::vector<GlobalVariable *> LDSVarsToTransform(
1181 LDSVarsToTransformArg.
begin(), LDSVarsToTransformArg.
end());
1182 llvm::sort(LDSVarsToTransform.begin(), LDSVarsToTransform.end(),
1184 return lhs->getName() < rhs->getName();
1191 const size_t NumberVars = LDSVarsToTransform.
size();
1192 if (NumberVars > 1) {
1194 AliasScopes.
reserve(NumberVars);
1196 for (
size_t I = 0;
I < NumberVars;
I++) {
1200 NoAliasList.
append(&AliasScopes[1], AliasScopes.
end());
1205 for (
size_t I = 0;
I < NumberVars;
I++) {
1207 Constant *
GEP = Replacement.LDSVarsToConstantGEP[GV];
1211 APInt APOff(
DL.getIndexTypeSizeInBits(
GEP->getType()), 0);
1212 GEP->stripAndAccumulateInBoundsConstantOffsets(
DL, APOff);
1219 NoAliasList[
I - 1] = AliasScopes[
I - 1];
1225 refineUsesAlignmentAndAA(
GEP,
A,
DL, AliasScope, NoAlias);
1232 if (!
MaxDepth || (
A == 1 && !AliasScope))
1235 for (
User *U :
Ptr->users()) {
1236 if (
auto *
I = dyn_cast<Instruction>(U)) {
1237 if (AliasScope &&
I->mayReadOrWriteMemory()) {
1238 MDNode *AS =
I->getMetadata(LLVMContext::MD_alias_scope);
1241 I->setMetadata(LLVMContext::MD_alias_scope, AS);
1243 MDNode *NA =
I->getMetadata(LLVMContext::MD_noalias);
1245 I->setMetadata(LLVMContext::MD_noalias, NA);
1249 if (
auto *LI = dyn_cast<LoadInst>(U)) {
1250 LI->setAlignment(std::max(
A, LI->getAlign()));
1253 if (
auto *
SI = dyn_cast<StoreInst>(U)) {
1254 if (
SI->getPointerOperand() ==
Ptr)
1255 SI->setAlignment(std::max(
A,
SI->getAlign()));
1258 if (
auto *AI = dyn_cast<AtomicRMWInst>(U)) {
1261 if (AI->getPointerOperand() ==
Ptr)
1262 AI->setAlignment(std::max(
A, AI->getAlign()));
1265 if (
auto *AI = dyn_cast<AtomicCmpXchgInst>(U)) {
1266 if (AI->getPointerOperand() ==
Ptr)
1267 AI->setAlignment(std::max(
A, AI->getAlign()));
1270 if (
auto *
GEP = dyn_cast<GetElementPtrInst>(U)) {
1271 unsigned BitWidth =
DL.getIndexTypeSizeInBits(
GEP->getType());
1273 if (
GEP->getPointerOperand() ==
Ptr) {
1275 if (
GEP->accumulateConstantOffset(
DL, Off))
1277 refineUsesAlignmentAndAA(
GEP, GA,
DL, AliasScope, NoAlias,
1282 if (
auto *
I = dyn_cast<Instruction>(U)) {
1283 if (
I->getOpcode() == Instruction::BitCast ||
1284 I->getOpcode() == Instruction::AddrSpaceCast)
1285 refineUsesAlignmentAndAA(
I,
A,
DL, AliasScope, NoAlias,
MaxDepth - 1);
1292char AMDGPULowerModuleLDS::ID = 0;
1297 "Lower uses of LDS variables from non-kernel functions",
false,
1301 return new AMDGPULowerModuleLDS();
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu propagate attributes Late propagate attributes from kernels to functions
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...
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...
#define INITIALIZE_PASS(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,...
This file implements a set that has insertion order iteration characteristics.
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.
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.
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
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...
InstListType::iterator iterator
Instruction iterators...
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.
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< unsigned > InRangeIndex=std::nullopt, Type *OnlyIfReducedTy=nullptr)
Getelementptr form.
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
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.
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Implements a dense probed hash-table based set.
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
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).
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.
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...
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.
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.
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 Type * getVoidTy(LLVMContext &C)
static IntegerType * getInt8Ty(LLVMContext &C)
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
static IntegerType * getInt32Ty(LLVMContext &C)
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified 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.
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...
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)
@ LOCAL_ADDRESS
Address space for local memory.
@ CONSTANT_ADDRESS
Address space for constant memory (VTX2).
Align getAlign(DataLayout const &DL, 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.
char & AMDGPULowerModuleLDSID
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...
ModulePass * createAMDGPULowerModuleLDSPass()
void sort(IteratorTy Start, IteratorTy End)
void initializeAMDGPULowerModuleLDSPass(PassRegistry &)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
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.
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)
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.