LLVM 24.0.0git
AMDGPUMachineFunctionInfo.cpp
Go to the documentation of this file.
1//===-- AMDGPUMachineFunctionInfo.cpp ---------------------------------------=//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "AMDGPUMemoryUtils.h"
11#include "AMDGPUSubtarget.h"
15#include "llvm/IR/Constants.h"
16#include "llvm/IR/Metadata.h"
18
19using namespace llvm;
20
21static const GlobalVariable *
23 const Module *M = F.getParent();
24 SmallString<64> KernelDynLDSName("llvm.amdgcn.");
25 KernelDynLDSName += F.getName();
26 KernelDynLDSName += ".dynlds";
27 return M->getNamedGlobal(KernelDynLDSName);
28}
29
30static bool hasLDSKernelArgument(const Function &F) {
31 for (const Argument &Arg : F.args()) {
32 Type *ArgTy = Arg.getType();
33 if (auto *PtrTy = dyn_cast<PointerType>(ArgTy)) {
34 if (PtrTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS)
35 return true;
36 }
37 }
38 return false;
39}
40
42 const AMDGPUSubtarget &ST)
43 : IsEntryFunction(AMDGPU::isEntryFunctionCC(F.getCallingConv())),
45 AMDGPU::isModuleEntryFunctionCC(F.getCallingConv())),
46 IsChainFunction(AMDGPU::isChainCC(F.getCallingConv())) {
47
48 // FIXME: Should initialize KernArgSize based on ExplicitKernelArgOffset,
49 // except reserved size is not correctly aligned.
50
51 Attribute MemBoundAttr = F.getFnAttribute("amdgpu-memory-bound");
52 MemoryBound = MemBoundAttr.getValueAsBool();
53
54 Attribute WaveLimitAttr = F.getFnAttribute("amdgpu-wave-limiter");
55 WaveLimiter = WaveLimitAttr.getValueAsBool();
56
57 // FIXME: How is this attribute supposed to interact with statically known
58 // global sizes?
59 StringRef S = F.getFnAttribute("amdgpu-gds-size").getValueAsString();
60 if (!S.empty())
62
63 // Assume the attribute allocates before any known GDS globals.
65
66 // Second value, if present, is the maximum value that can be assigned.
67 // Useful in PromoteAlloca or for LDS spills. Could be used for diagnostics
68 // during codegen.
69 std::pair<unsigned, unsigned> LDSSizeRange = AMDGPU::getIntegerPairAttribute(
70 F, "amdgpu-lds-size", {0, UINT32_MAX}, true);
71
72 // The two separate variables are only profitable when the LDS module lowering
73 // pass is disabled. If graphics does not use dynamic LDS, this is never
74 // profitable. Leaving cleanup for a later change.
75 LDSSize = LDSSizeRange.first;
77
78 CallingConv::ID CC = F.getCallingConv();
80 ExplicitKernArgSize = ST.getExplicitKernArgSize(F, MaxKernArgAlign);
81
83 if (DynLdsGlobal || hasLDSKernelArgument(F))
84 UsesDynamicLDS = true;
85}
86
88 const GlobalVariable &GV,
89 Align Trailing) {
90 auto Entry = LocalMemoryObjects.insert(std::pair(&GV, 0));
91 if (!Entry.second)
92 return Entry.first->second;
93
94 Align Alignment =
95 DL.getValueOrABITypeAlignment(GV.getAlign(), GV.getValueType());
96
97 unsigned Offset;
99 if (AMDGPU::isNamedBarrier(GV)) {
100 std::optional<unsigned> BarAddr = getLDSAbsoluteAddress(GV);
101 if (!BarAddr)
102 llvm_unreachable("named barrier should have an assigned address");
103 Entry.first->second = BarAddr.value();
104 unsigned BarCnt = GV.getGlobalSize(DL) / 16;
105 recordNumNamedBarriers(BarAddr.value(), BarCnt);
106 return BarAddr.value();
107 }
108
109 std::optional<uint32_t> MaybeAbs = getLDSAbsoluteAddress(GV);
110 if (MaybeAbs) {
111 // Absolute address LDS variables that exist prior to the LDS lowering
112 // pass raise a fatal error in that pass. These failure modes are only
113 // reachable if that lowering pass is disabled or broken. If/when adding
114 // support for absolute addresses on user specified variables, the
115 // alignment check moves to the lowering pass and the frame calculation
116 // needs to take the user variables into consideration.
117
118 uint32_t ObjectStart = *MaybeAbs;
119
120 if (ObjectStart != alignTo(ObjectStart, Alignment)) {
121 report_fatal_error("Absolute address LDS variable inconsistent with "
122 "variable alignment");
123 }
124
125 if (isModuleEntryFunction()) {
126 // If this is a module entry function, we can also sanity check against
127 // the static frame. Strictly it would be better to check against the
128 // attribute, i.e. that the variable is within the always-allocated
129 // section, and not within some other non-absolute-address object
130 // allocated here, but the extra error detection is minimal and we would
131 // have to pass the Function around or cache the attribute value.
132 uint32_t ObjectEnd = ObjectStart + GV.getGlobalSize(DL);
133 if (ObjectEnd > StaticLDSSize) {
135 "Absolute address LDS variable outside of static frame");
136 }
137 }
138
139 Entry.first->second = ObjectStart;
140 return ObjectStart;
141 }
142
143 /// TODO: We should sort these to minimize wasted space due to alignment
144 /// padding. Currently the padding is decided by the first encountered use
145 /// during lowering.
147
149
150 // Align LDS size to trailing, e.g. for aligning dynamic shared memory
151 LDSSize = alignTo(StaticLDSSize, Trailing);
152 } else {
154 "expected region address space");
155
158
159 // FIXME: Apply alignment of dynamic GDS
161 }
162
163 Entry.first->second = Offset;
164 return Offset;
165}
166
167std::optional<uint32_t>
169 // TODO: Would be more consistent with the abs symbols to use a range
170 MDNode *MD = F.getMetadata("llvm.amdgcn.lds.kernel.id");
171 if (MD && MD->getNumOperands() == 1) {
172 if (ConstantInt *KnownSize =
174 uint64_t ZExt = KnownSize->getZExtValue();
175 if (ZExt <= UINT32_MAX) {
176 return ZExt;
177 }
178 }
179 }
180 return {};
181}
182
183std::optional<uint32_t>
186 return {};
187
188 std::optional<ConstantRange> AbsSymRange = GV.getAbsoluteSymbolRange();
189 if (!AbsSymRange)
190 return {};
191
192 if (const APInt *V = AbsSymRange->getSingleElement()) {
193 std::optional<uint64_t> ZExt = V->tryZExtValue();
194 if (ZExt && (*ZExt <= UINT32_MAX)) {
195 return *ZExt;
196 }
197 }
198
199 return {};
200}
201
203 const GlobalVariable &GV) {
204 const Module *M = F.getParent();
205 const DataLayout &DL = M->getDataLayout();
206 assert(GV.getGlobalSize(DL) == 0);
207
208 Align Alignment =
209 DL.getValueOrABITypeAlignment(GV.getAlign(), GV.getValueType());
210 if (Alignment <= DynLDSAlign)
211 return;
212
213 LDSSize = alignTo(StaticLDSSize, Alignment);
214 DynLDSAlign = Alignment;
215
216 // If there is a dynamic LDS variable associated with this function F, every
217 // further dynamic LDS instance (allocated by calling setDynLDSAlign) must
218 // map to the same address. This holds because no LDS is allocated after the
219 // lowering pass if there are dynamic LDS variables present.
221 if (Dyn) {
222 unsigned Offset = LDSSize; // return this?
223 std::optional<uint32_t> Expect = getLDSAbsoluteAddress(*Dyn);
224 if (!Expect || (Offset != *Expect)) {
225 report_fatal_error("Inconsistent metadata on dynamic LDS variable");
226 }
227 }
228}
229
233
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool hasLDSKernelArgument(const Function &F)
static const GlobalVariable * getKernelDynLDSGlobalFromFunction(const Function &F)
Base class for AMDGPU specific classes of TargetSubtarget.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the declarations for the subclasses of Constant, which represent the different fla...
#define F(x, y, z)
Definition MD5.cpp:54
This file contains the declarations for metadata subclasses.
if(PassOpts->AAPipeline)
Align DynLDSAlign
Align for dynamic shared memory if any.
uint32_t StaticLDSSize
Number of bytes in the LDS allocated statically.
static std::optional< uint32_t > getLDSKernelIdMetadata(const Function &F)
void setDynLDSAlign(const Function &F, const GlobalVariable &GV)
unsigned allocateLDSGlobal(const DataLayout &DL, const GlobalVariable &GV)
AMDGPUMachineFunctionInfo(const Function &F, const AMDGPUSubtarget &ST)
void recordNumNamedBarriers(uint32_t GVAddr, unsigned BarCnt)
uint32_t LDSSize
Number of bytes in the LDS that are being used.
static std::optional< uint32_t > getLDSAbsoluteAddress(const GlobalValue &GV)
Class for arbitrary precision integers.
Definition APInt.h:78
This class represents an incoming formal argument to a Function.
Definition Argument.h:32
Functions, function parameters, and return types can have attributes to indicate how they should be t...
Definition Attributes.h:105
LLVM_ABI bool getValueAsBool() const
Return the attribute's value as a boolean.
This is the shared class of boolean and integer constants.
Definition Constants.h:87
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
unsigned getAddressSpace() const
LLVM_ABI std::optional< ConstantRange > getAbsoluteSymbolRange() const
If this is an absolute symbol reference, returns the range of the symbol, otherwise returns std::null...
Definition Globals.cpp:534
Type * getValueType() const
MaybeAlign getAlign() const
Returns the alignment of the given variable.
LLVM_ABI uint64_t getGlobalSize(const DataLayout &DL) const
Get the size of this global variable in bytes.
Definition Globals.cpp:640
Metadata node.
Definition Metadata.h:1069
const MDOperand & getOperand(unsigned I) const
Definition Metadata.h:1426
unsigned getNumOperands() const
Return number of MDNode operands.
Definition Metadata.h:1432
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
bool consumeInteger(unsigned Radix, T &Result)
Parse the current string as an integer of the specified radix.
Definition StringRef.h:519
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ REGION_ADDRESS
Address space for region memory. (GDS)
@ LOCAL_ADDRESS
Address space for local memory.
TargetExtType * isNamedBarrier(const GlobalVariable &GV)
std::pair< unsigned, unsigned > getIntegerPairAttribute(const Function &F, StringRef Name, std::pair< unsigned, unsigned > Default, bool OnlyFirstRequired)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ AMDGPU_KERNEL
Used for AMDGPU code object kernels.
@ SPIR_KERNEL
Used for SPIR kernel functions.
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
Definition Metadata.h:668
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39