LLVM 23.0.0git
AMDGPUMachineFunction.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 "AMDGPU.h"
11#include "AMDGPUMemoryUtils.h"
12#include "AMDGPUSubtarget.h"
16#include "llvm/IR/Constants.h"
17#include "llvm/IR/Metadata.h"
19
20using namespace llvm;
21
22static const GlobalVariable *
24 const Module *M = F.getParent();
25 SmallString<64> KernelDynLDSName("llvm.amdgcn.");
26 KernelDynLDSName += F.getName();
27 KernelDynLDSName += ".dynlds";
28 return M->getNamedGlobal(KernelDynLDSName);
29}
30
31static bool hasLDSKernelArgument(const Function &F) {
32 for (const Argument &Arg : F.args()) {
33 Type *ArgTy = Arg.getType();
34 if (auto *PtrTy = dyn_cast<PointerType>(ArgTy)) {
35 if (PtrTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS)
36 return true;
37 }
38 }
39 return false;
40}
41
43 const AMDGPUSubtarget &ST)
44 : IsEntryFunction(AMDGPU::isEntryFunctionCC(F.getCallingConv())),
46 AMDGPU::isModuleEntryFunctionCC(F.getCallingConv())),
47 IsChainFunction(AMDGPU::isChainCC(F.getCallingConv())) {
48
49 // FIXME: Should initialize KernArgSize based on ExplicitKernelArgOffset,
50 // except reserved size is not correctly aligned.
51
52 Attribute MemBoundAttr = F.getFnAttribute("amdgpu-memory-bound");
53 MemoryBound = MemBoundAttr.getValueAsBool();
54
55 Attribute WaveLimitAttr = F.getFnAttribute("amdgpu-wave-limiter");
56 WaveLimiter = WaveLimitAttr.getValueAsBool();
57
58 // FIXME: How is this attribute supposed to interact with statically known
59 // global sizes?
60 StringRef S = F.getFnAttribute("amdgpu-gds-size").getValueAsString();
61 if (!S.empty())
63
64 // Assume the attribute allocates before any known GDS globals.
66
67 // Second value, if present, is the maximum value that can be assigned.
68 // Useful in PromoteAlloca or for LDS spills. Could be used for diagnostics
69 // during codegen.
70 std::pair<unsigned, unsigned> LDSSizeRange = AMDGPU::getIntegerPairAttribute(
71 F, "amdgpu-lds-size", {0, UINT32_MAX}, true);
72
73 // The two separate variables are only profitable when the LDS module lowering
74 // pass is disabled. If graphics does not use dynamic LDS, this is never
75 // profitable. Leaving cleanup for a later change.
76 LDSSize = LDSSizeRange.first;
78
79 CallingConv::ID CC = F.getCallingConv();
81 ExplicitKernArgSize = ST.getExplicitKernArgSize(F, MaxKernArgAlign);
82
83 // FIXME: Shouldn't be target specific
84 Attribute NSZAttr = F.getFnAttribute("no-signed-zeros-fp-math");
86 NSZAttr.isStringAttribute() && NSZAttr.getValueAsString() == "true";
87
89 if (DynLdsGlobal || hasLDSKernelArgument(F))
90 UsesDynamicLDS = true;
91}
92
94 const GlobalVariable &GV,
95 Align Trailing) {
96 auto Entry = LocalMemoryObjects.insert(std::pair(&GV, 0));
97 if (!Entry.second)
98 return Entry.first->second;
99
100 Align Alignment =
101 DL.getValueOrABITypeAlignment(GV.getAlign(), GV.getValueType());
102
103 unsigned Offset;
105 if (AMDGPU::isNamedBarrier(GV)) {
106 std::optional<unsigned> BarAddr = getLDSAbsoluteAddress(GV);
107 if (!BarAddr)
108 llvm_unreachable("named barrier should have an assigned address");
109 Entry.first->second = BarAddr.value();
110 unsigned BarCnt = GV.getGlobalSize(DL) / 16;
111 recordNumNamedBarriers(BarAddr.value(), BarCnt);
112 return BarAddr.value();
113 }
114
115 std::optional<uint32_t> MaybeAbs = getLDSAbsoluteAddress(GV);
116 if (MaybeAbs) {
117 // Absolute address LDS variables that exist prior to the LDS lowering
118 // pass raise a fatal error in that pass. These failure modes are only
119 // reachable if that lowering pass is disabled or broken. If/when adding
120 // support for absolute addresses on user specified variables, the
121 // alignment check moves to the lowering pass and the frame calculation
122 // needs to take the user variables into consideration.
123
124 uint32_t ObjectStart = *MaybeAbs;
125
126 if (ObjectStart != alignTo(ObjectStart, Alignment)) {
127 report_fatal_error("Absolute address LDS variable inconsistent with "
128 "variable alignment");
129 }
130
131 if (isModuleEntryFunction()) {
132 // If this is a module entry function, we can also sanity check against
133 // the static frame. Strictly it would be better to check against the
134 // attribute, i.e. that the variable is within the always-allocated
135 // section, and not within some other non-absolute-address object
136 // allocated here, but the extra error detection is minimal and we would
137 // have to pass the Function around or cache the attribute value.
138 uint32_t ObjectEnd = ObjectStart + GV.getGlobalSize(DL);
139 if (ObjectEnd > StaticLDSSize) {
141 "Absolute address LDS variable outside of static frame");
142 }
143 }
144
145 Entry.first->second = ObjectStart;
146 return ObjectStart;
147 }
148
149 /// TODO: We should sort these to minimize wasted space due to alignment
150 /// padding. Currently the padding is decided by the first encountered use
151 /// during lowering.
153
155
156 // Align LDS size to trailing, e.g. for aligning dynamic shared memory
157 LDSSize = alignTo(StaticLDSSize, Trailing);
158 } else {
160 "expected region address space");
161
164
165 // FIXME: Apply alignment of dynamic GDS
167 }
168
169 Entry.first->second = Offset;
170 return Offset;
171}
172
173std::optional<uint32_t>
175 // TODO: Would be more consistent with the abs symbols to use a range
176 MDNode *MD = F.getMetadata("llvm.amdgcn.lds.kernel.id");
177 if (MD && MD->getNumOperands() == 1) {
178 if (ConstantInt *KnownSize =
180 uint64_t ZExt = KnownSize->getZExtValue();
181 if (ZExt <= UINT32_MAX) {
182 return ZExt;
183 }
184 }
185 }
186 return {};
187}
188
189std::optional<uint32_t>
192 return {};
193
194 std::optional<ConstantRange> AbsSymRange = GV.getAbsoluteSymbolRange();
195 if (!AbsSymRange)
196 return {};
197
198 if (const APInt *V = AbsSymRange->getSingleElement()) {
199 std::optional<uint64_t> ZExt = V->tryZExtValue();
200 if (ZExt && (*ZExt <= UINT32_MAX)) {
201 return *ZExt;
202 }
203 }
204
205 return {};
206}
207
209 const GlobalVariable &GV) {
210 const Module *M = F.getParent();
211 const DataLayout &DL = M->getDataLayout();
212 assert(GV.getGlobalSize(DL) == 0);
213
214 Align Alignment =
215 DL.getValueOrABITypeAlignment(GV.getAlign(), GV.getValueType());
216 if (Alignment <= DynLDSAlign)
217 return;
218
219 LDSSize = alignTo(StaticLDSSize, Alignment);
220 DynLDSAlign = Alignment;
221
222 // If there is a dynamic LDS variable associated with this function F, every
223 // further dynamic LDS instance (allocated by calling setDynLDSAlign) must
224 // map to the same address. This holds because no LDS is allocated after the
225 // lowering pass if there are dynamic LDS variables present.
227 if (Dyn) {
228 unsigned Offset = LDSSize; // return this?
229 std::optional<uint32_t> Expect = getLDSAbsoluteAddress(*Dyn);
230 if (!Expect || (Offset != *Expect)) {
231 report_fatal_error("Inconsistent metadata on dynamic LDS variable");
232 }
233 }
234}
235
237 UsesDynamicLDS = DynLDS;
238}
239
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)
AMDGPUMachineFunction(const Function &F, const AMDGPUSubtarget &ST)
static std::optional< uint32_t > getLDSKernelIdMetadata(const Function &F)
Align DynLDSAlign
Align for dynamic shared memory if any.
uint32_t LDSSize
Number of bytes in the LDS that are being used.
void setDynLDSAlign(const Function &F, const GlobalVariable &GV)
static std::optional< uint32_t > getLDSAbsoluteAddress(const GlobalValue &GV)
void recordNumNamedBarriers(uint32_t GVAddr, unsigned BarCnt)
unsigned allocateLDSGlobal(const DataLayout &DL, const GlobalVariable &GV)
uint32_t StaticLDSSize
Number of bytes in the LDS allocated statically.
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:103
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:455
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:561
Metadata node.
Definition Metadata.h:1079
const MDOperand & getOperand(unsigned I) const
Definition Metadata.h:1443
unsigned getNumOperands() const
Return number of MDNode operands.
Definition Metadata.h:1449
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
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
bool consumeInteger(unsigned Radix, T &Result)
Parse the current string as an integer of the specified radix.
Definition StringRef.h:501
constexpr bool empty() const
empty - Check if the string is empty.
Definition StringRef.h:143
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
#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.
Definition Types.h:26
@ Offset
Definition DWP.cpp:532
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
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