LLVM 20.0.0git
AMDGPUMCResourceInfo.cpp
Go to the documentation of this file.
1//===- AMDGPUMCResourceInfo.cpp --- MC Resource Info ----------------------===//
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//
9/// \file
10/// \brief MC infrastructure to propagate the function level resource usage
11/// info.
12///
13//===----------------------------------------------------------------------===//
14
17#include "llvm/ADT/StringRef.h"
18#include "llvm/MC/MCAsmInfo.h"
19#include "llvm/MC/MCContext.h"
20#include "llvm/MC/MCSymbol.h"
22
23using namespace llvm;
24
26 MCContext &OutContext, bool IsLocal) {
27 auto GOCS = [FuncName, &OutContext, IsLocal](StringRef Suffix) {
28 StringRef Prefix =
29 IsLocal ? OutContext.getAsmInfo()->getPrivateGlobalPrefix() : "";
30 return OutContext.getOrCreateSymbol(Twine(Prefix) + FuncName +
31 Twine(Suffix));
32 };
33 switch (RIK) {
34 case RIK_NumVGPR:
35 return GOCS(".num_vgpr");
36 case RIK_NumAGPR:
37 return GOCS(".num_agpr");
38 case RIK_NumSGPR:
39 return GOCS(".numbered_sgpr");
41 return GOCS(".private_seg_size");
42 case RIK_UsesVCC:
43 return GOCS(".uses_vcc");
45 return GOCS(".uses_flat_scratch");
47 return GOCS(".has_dyn_sized_stack");
49 return GOCS(".has_recursion");
51 return GOCS(".has_indirect_call");
52 }
53 llvm_unreachable("Unexpected ResourceInfoKind.");
54}
55
58 MCContext &Ctx, bool IsLocal) {
59 return MCSymbolRefExpr::create(getSymbol(FuncName, RIK, Ctx, IsLocal), Ctx);
60}
61
62void MCResourceInfo::assignMaxRegs(MCContext &OutContext) {
63 // Assign expression to get the max register use to the max_num_Xgpr symbol.
64 MCSymbol *MaxVGPRSym = getMaxVGPRSymbol(OutContext);
65 MCSymbol *MaxAGPRSym = getMaxAGPRSymbol(OutContext);
66 MCSymbol *MaxSGPRSym = getMaxSGPRSymbol(OutContext);
67
68 auto assignMaxRegSym = [&OutContext](MCSymbol *Sym, int32_t RegCount) {
69 const MCExpr *MaxExpr = MCConstantExpr::create(RegCount, OutContext);
70 Sym->setVariableValue(MaxExpr);
71 };
72
73 assignMaxRegSym(MaxVGPRSym, MaxVGPR);
74 assignMaxRegSym(MaxAGPRSym, MaxAGPR);
75 assignMaxRegSym(MaxSGPRSym, MaxSGPR);
76}
77
79
81 assert(!Finalized && "Cannot finalize ResourceInfo again.");
82 Finalized = true;
83 assignMaxRegs(OutContext);
84}
85
87 return OutContext.getOrCreateSymbol("amdgpu.max_num_vgpr");
88}
89
91 return OutContext.getOrCreateSymbol("amdgpu.max_num_agpr");
92}
93
95 return OutContext.getOrCreateSymbol("amdgpu.max_num_sgpr");
96}
97
98void MCResourceInfo::assignResourceInfoExpr(
99 int64_t LocalValue, ResourceInfoKind RIK, AMDGPUMCExpr::VariantKind Kind,
100 const MachineFunction &MF, const SmallVectorImpl<const Function *> &Callees,
101 MCContext &OutContext) {
102 const TargetMachine &TM = MF.getTarget();
103 bool IsLocal = MF.getFunction().hasLocalLinkage();
104 MCSymbol *FnSym = TM.getSymbol(&MF.getFunction());
105 const MCConstantExpr *LocalConstExpr =
106 MCConstantExpr::create(LocalValue, OutContext);
107 const MCExpr *SymVal = LocalConstExpr;
108 MCSymbol *Sym = getSymbol(FnSym->getName(), RIK, OutContext, IsLocal);
109 if (!Callees.empty()) {
112 ArgExprs.push_back(LocalConstExpr);
113
114 for (const Function *Callee : Callees) {
115 if (!Seen.insert(Callee).second)
116 continue;
117
118 bool IsCalleeLocal = Callee->hasLocalLinkage();
119 MCSymbol *CalleeFnSym = TM.getSymbol(&Callee->getFunction());
120 MCSymbol *CalleeValSym =
121 getSymbol(CalleeFnSym->getName(), RIK, OutContext, IsCalleeLocal);
122
123 // Avoid constructing recursive definitions by detecting whether `Sym` is
124 // found transitively within any of its `CalleeValSym`.
125 if (!CalleeValSym->isVariable() ||
126 !CalleeValSym->getVariableValue(/*isUsed=*/false)
128 ArgExprs.push_back(MCSymbolRefExpr::create(CalleeValSym, OutContext));
129 } else {
130 // In case of recursion: make sure to use conservative register counts
131 // (i.e., specifically for VGPR/SGPR/AGPR).
132 switch (RIK) {
133 default:
134 break;
135 case RIK_NumVGPR:
137 getMaxVGPRSymbol(OutContext), OutContext));
138 break;
139 case RIK_NumSGPR:
141 getMaxSGPRSymbol(OutContext), OutContext));
142 break;
143 case RIK_NumAGPR:
145 getMaxAGPRSymbol(OutContext), OutContext));
146 break;
147 }
148 }
149 }
150 if (ArgExprs.size() > 1)
151 SymVal = AMDGPUMCExpr::create(Kind, ArgExprs, OutContext);
152 }
153 Sym->setVariableValue(SymVal);
154}
155
157 const MachineFunction &MF,
159 MCContext &OutContext) {
160 // Worst case VGPR use for non-hardware-entrypoints.
161 MCSymbol *MaxVGPRSym = getMaxVGPRSymbol(OutContext);
162 MCSymbol *MaxAGPRSym = getMaxAGPRSymbol(OutContext);
163 MCSymbol *MaxSGPRSym = getMaxSGPRSymbol(OutContext);
164 bool IsLocal = MF.getFunction().hasLocalLinkage();
165
170 }
171
172 const TargetMachine &TM = MF.getTarget();
173 MCSymbol *FnSym = TM.getSymbol(&MF.getFunction());
174
175 auto SetMaxReg = [&](MCSymbol *MaxSym, int32_t numRegs,
176 ResourceInfoKind RIK) {
177 if (!FRI.HasIndirectCall) {
178 assignResourceInfoExpr(numRegs, RIK, AMDGPUMCExpr::AGVK_Max, MF,
179 FRI.Callees, OutContext);
180 } else {
181 const MCExpr *SymRef = MCSymbolRefExpr::create(MaxSym, OutContext);
182 MCSymbol *LocalNumSym =
183 getSymbol(FnSym->getName(), RIK, OutContext, IsLocal);
184 const MCExpr *MaxWithLocal = AMDGPUMCExpr::createMax(
185 {MCConstantExpr::create(numRegs, OutContext), SymRef}, OutContext);
186 LocalNumSym->setVariableValue(MaxWithLocal);
187 }
188 };
189
190 SetMaxReg(MaxVGPRSym, FRI.NumVGPR, RIK_NumVGPR);
191 SetMaxReg(MaxAGPRSym, FRI.NumAGPR, RIK_NumAGPR);
192 SetMaxReg(MaxSGPRSym, FRI.NumExplicitSGPR, RIK_NumSGPR);
193
194 {
195 // The expression for private segment size should be: FRI.PrivateSegmentSize
196 // + max(FRI.Callees, FRI.CalleeSegmentSize)
198 MCSymbol *Sym =
199 getSymbol(FnSym->getName(), RIK_PrivateSegSize, OutContext, IsLocal);
200 if (FRI.CalleeSegmentSize)
201 ArgExprs.push_back(
203
205 Seen.insert(&MF.getFunction());
206 for (const Function *Callee : FRI.Callees) {
207 if (!Seen.insert(Callee).second)
208 continue;
209 if (!Callee->isDeclaration()) {
210 bool IsCalleeLocal = Callee->hasLocalLinkage();
211 MCSymbol *CalleeFnSym = TM.getSymbol(&Callee->getFunction());
212 MCSymbol *CalleeValSym =
213 getSymbol(CalleeFnSym->getName(), RIK_PrivateSegSize, OutContext,
214 IsCalleeLocal);
215
216 // Avoid constructing recursive definitions by detecting whether `Sym`
217 // is found transitively within any of its `CalleeValSym`.
218 if (!CalleeValSym->isVariable() ||
219 !CalleeValSym->getVariableValue(/*isUsed=*/false)
221 ArgExprs.push_back(MCSymbolRefExpr::create(CalleeValSym, OutContext));
222 }
223 }
224 }
225 const MCExpr *localConstExpr =
227 if (!ArgExprs.empty()) {
228 const AMDGPUMCExpr *transitiveExpr =
229 AMDGPUMCExpr::createMax(ArgExprs, OutContext);
230 localConstExpr =
231 MCBinaryExpr::createAdd(localConstExpr, transitiveExpr, OutContext);
232 }
233 Sym->setVariableValue(localConstExpr);
234 }
235
236 auto SetToLocal = [&](int64_t LocalValue, ResourceInfoKind RIK) {
237 MCSymbol *Sym = getSymbol(FnSym->getName(), RIK, OutContext, IsLocal);
238 Sym->setVariableValue(MCConstantExpr::create(LocalValue, OutContext));
239 };
240
241 if (!FRI.HasIndirectCall) {
242 assignResourceInfoExpr(FRI.UsesVCC, ResourceInfoKind::RIK_UsesVCC,
243 AMDGPUMCExpr::AGVK_Or, MF, FRI.Callees, OutContext);
244 assignResourceInfoExpr(FRI.UsesFlatScratch,
246 AMDGPUMCExpr::AGVK_Or, MF, FRI.Callees, OutContext);
247 assignResourceInfoExpr(FRI.HasDynamicallySizedStack,
249 AMDGPUMCExpr::AGVK_Or, MF, FRI.Callees, OutContext);
250 assignResourceInfoExpr(FRI.HasRecursion, ResourceInfoKind::RIK_HasRecursion,
251 AMDGPUMCExpr::AGVK_Or, MF, FRI.Callees, OutContext);
252 assignResourceInfoExpr(FRI.HasIndirectCall,
254 AMDGPUMCExpr::AGVK_Or, MF, FRI.Callees, OutContext);
255 } else {
256 SetToLocal(FRI.UsesVCC, ResourceInfoKind::RIK_UsesVCC);
258 SetToLocal(FRI.HasDynamicallySizedStack,
262 }
263}
264
266 MCContext &Ctx) {
267 const TargetMachine &TM = MF.getTarget();
268 MCSymbol *FnSym = TM.getSymbol(&MF.getFunction());
269 bool IsLocal = MF.getFunction().hasLocalLinkage();
271 getSymRefExpr(FnSym->getName(), RIK_NumAGPR, Ctx, IsLocal),
272 getSymRefExpr(FnSym->getName(), RIK_NumVGPR, Ctx, IsLocal), Ctx);
273}
274
276 bool hasXnack,
277 MCContext &Ctx) {
278 const TargetMachine &TM = MF.getTarget();
279 MCSymbol *FnSym = TM.getSymbol(&MF.getFunction());
280 bool IsLocal = MF.getFunction().hasLocalLinkage();
282 getSymRefExpr(FnSym->getName(), RIK_NumSGPR, Ctx, IsLocal),
284 getSymRefExpr(FnSym->getName(), RIK_UsesVCC, Ctx, IsLocal),
285 getSymRefExpr(FnSym->getName(), RIK_UsesFlatScratch, Ctx, IsLocal),
286 hasXnack, Ctx),
287 Ctx);
288}
MC infrastructure to propagate the function level resource usage info.
Symbol * Sym
Definition: ELF_riscv.cpp:479
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
AMDGPU target specific MCExpr operations.
Definition: AMDGPUMCExpr.h:30
static const AMDGPUMCExpr * createMax(ArrayRef< const MCExpr * > Args, MCContext &Ctx)
Definition: AMDGPUMCExpr.h:69
static const AMDGPUMCExpr * createTotalNumVGPR(const MCExpr *NumAGPR, const MCExpr *NumVGPR, MCContext &Ctx)
static const AMDGPUMCExpr * create(VariantKind Kind, ArrayRef< const MCExpr * > Args, MCContext &Ctx)
static const AMDGPUMCExpr * createExtraSGPRs(const MCExpr *VCCUsed, const MCExpr *FlatScrUsed, bool XNACKUsed, MCContext &Ctx)
Allow delayed MCExpr resolve of ExtraSGPRs (in case VCCUsed or FlatScrUsed are unresolvable but neede...
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition: Function.h:277
bool hasLocalLinkage() const
Definition: GlobalValue.h:529
StringRef getPrivateGlobalPrefix() const
Definition: MCAsmInfo.h:549
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:537
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:222
Context object for machine code objects.
Definition: MCContext.h:83
const MCAsmInfo * getAsmInfo() const
Definition: MCContext.h:412
MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Definition: MCContext.cpp:212
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:34
bool isSymbolUsedInExpression(const MCSymbol *Sym) const
Returns whether the given symbol is used anywhere in the expression or subexpressions.
Definition: MCExpr.cpp:180
MCResourceInfo()=default
void addMaxSGPRCandidate(int32_t candidate)
void gatherResourceInfo(const MachineFunction &MF, const AMDGPUResourceUsageAnalysis::SIFunctionResourceInfo &FRI, MCContext &OutContext)
AMDGPUResourceUsageAnalysis gathers resource usage on a per-function granularity.
MCSymbol * getMaxSGPRSymbol(MCContext &OutContext)
const MCExpr * getSymRefExpr(StringRef FuncName, ResourceInfoKind RIK, MCContext &Ctx, bool IsLocal)
MCSymbol * getMaxAGPRSymbol(MCContext &OutContext)
const MCExpr * createTotalNumVGPRs(const MachineFunction &MF, MCContext &Ctx)
void finalize(MCContext &OutContext)
MCSymbol * getSymbol(StringRef FuncName, ResourceInfoKind RIK, MCContext &OutContext, bool IsLocal)
void addMaxAGPRCandidate(int32_t candidate)
MCSymbol * getMaxVGPRSymbol(MCContext &OutContext)
const MCExpr * createTotalNumSGPRs(const MachineFunction &MF, bool hasXnack, MCContext &Ctx)
void addMaxVGPRCandidate(int32_t candidate)
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:398
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
const MCExpr * getVariableValue(bool SetUsed=true) const
getVariableValue - Get the value for variable symbols.
Definition: MCSymbol.h:305
StringRef getName() const
getName - Get the symbol name.
Definition: MCSymbol.h:205
bool isVariable() const
isVariable - Check if this is a variable symbol.
Definition: MCSymbol.h:300
void setVariableValue(const MCExpr *Value)
Definition: MCSymbol.cpp:47
Function & getFunction()
Return the LLVM function that this machine code represents.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Definition: SmallPtrSet.h:384
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:519
bool empty() const
Definition: SmallVector.h:81
size_t size() const
Definition: SmallVector.h:78
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:77
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool isEntryFunctionCC(CallingConv::ID CC)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18