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/MCContext.h"
19#include "llvm/MC/MCSymbol.h"
21
22using namespace llvm;
23
25 MCContext &OutContext) {
26 auto GOCS = [FuncName, &OutContext](StringRef Suffix) {
27 return OutContext.getOrCreateSymbol(FuncName + Twine(Suffix));
28 };
29 switch (RIK) {
30 case RIK_NumVGPR:
31 return GOCS(".num_vgpr");
32 case RIK_NumAGPR:
33 return GOCS(".num_agpr");
34 case RIK_NumSGPR:
35 return GOCS(".numbered_sgpr");
37 return GOCS(".private_seg_size");
38 case RIK_UsesVCC:
39 return GOCS(".uses_vcc");
41 return GOCS(".uses_flat_scratch");
43 return GOCS(".has_dyn_sized_stack");
45 return GOCS(".has_recursion");
47 return GOCS(".has_indirect_call");
48 }
49 llvm_unreachable("Unexpected ResourceInfoKind.");
50}
51
54 MCContext &Ctx) {
55 return MCSymbolRefExpr::create(getSymbol(FuncName, RIK, Ctx), Ctx);
56}
57
58void MCResourceInfo::assignMaxRegs(MCContext &OutContext) {
59 // Assign expression to get the max register use to the max_num_Xgpr symbol.
60 MCSymbol *MaxVGPRSym = getMaxVGPRSymbol(OutContext);
61 MCSymbol *MaxAGPRSym = getMaxAGPRSymbol(OutContext);
62 MCSymbol *MaxSGPRSym = getMaxSGPRSymbol(OutContext);
63
64 auto assignMaxRegSym = [&OutContext](MCSymbol *Sym, int32_t RegCount) {
65 const MCExpr *MaxExpr = MCConstantExpr::create(RegCount, OutContext);
66 Sym->setVariableValue(MaxExpr);
67 };
68
69 assignMaxRegSym(MaxVGPRSym, MaxVGPR);
70 assignMaxRegSym(MaxAGPRSym, MaxAGPR);
71 assignMaxRegSym(MaxSGPRSym, MaxSGPR);
72}
73
75
77 assert(!Finalized && "Cannot finalize ResourceInfo again.");
78 Finalized = true;
79 assignMaxRegs(OutContext);
80}
81
83 return OutContext.getOrCreateSymbol("amdgpu.max_num_vgpr");
84}
85
87 return OutContext.getOrCreateSymbol("amdgpu.max_num_agpr");
88}
89
91 return OutContext.getOrCreateSymbol("amdgpu.max_num_sgpr");
92}
93
94void MCResourceInfo::assignResourceInfoExpr(
95 int64_t LocalValue, ResourceInfoKind RIK, AMDGPUMCExpr::VariantKind Kind,
96 const MachineFunction &MF, const SmallVectorImpl<const Function *> &Callees,
97 MCContext &OutContext) {
98 const TargetMachine &TM = MF.getTarget();
99 MCSymbol *FnSym = TM.getSymbol(&MF.getFunction());
100 const MCConstantExpr *LocalConstExpr =
101 MCConstantExpr::create(LocalValue, OutContext);
102 const MCExpr *SymVal = LocalConstExpr;
103 MCSymbol *Sym = getSymbol(FnSym->getName(), RIK, OutContext);
104 if (!Callees.empty()) {
107 ArgExprs.push_back(LocalConstExpr);
108
109 for (const Function *Callee : Callees) {
110 if (!Seen.insert(Callee).second)
111 continue;
112
113 MCSymbol *CalleeFnSym = TM.getSymbol(&Callee->getFunction());
114 MCSymbol *CalleeValSym =
115 getSymbol(CalleeFnSym->getName(), RIK, OutContext);
116
117 // Avoid constructing recursive definitions by detecting whether `Sym` is
118 // found transitively within any of its `CalleeValSym`.
119 if (!CalleeValSym->isVariable() ||
120 !CalleeValSym->getVariableValue(/*isUsed=*/false)
122 ArgExprs.push_back(MCSymbolRefExpr::create(CalleeValSym, OutContext));
123 } else {
124 // In case of recursion: make sure to use conservative register counts
125 // (i.e., specifically for VGPR/SGPR/AGPR).
126 switch (RIK) {
127 default:
128 break;
129 case RIK_NumVGPR:
131 getMaxVGPRSymbol(OutContext), OutContext));
132 break;
133 case RIK_NumSGPR:
135 getMaxSGPRSymbol(OutContext), OutContext));
136 break;
137 case RIK_NumAGPR:
139 getMaxAGPRSymbol(OutContext), OutContext));
140 break;
141 }
142 }
143 }
144 if (ArgExprs.size() > 1)
145 SymVal = AMDGPUMCExpr::create(Kind, ArgExprs, OutContext);
146 }
147 Sym->setVariableValue(SymVal);
148}
149
151 const MachineFunction &MF,
153 MCContext &OutContext) {
154 // Worst case VGPR use for non-hardware-entrypoints.
155 MCSymbol *MaxVGPRSym = getMaxVGPRSymbol(OutContext);
156 MCSymbol *MaxAGPRSym = getMaxAGPRSymbol(OutContext);
157 MCSymbol *MaxSGPRSym = getMaxSGPRSymbol(OutContext);
158
163 }
164
165 const TargetMachine &TM = MF.getTarget();
166 MCSymbol *FnSym = TM.getSymbol(&MF.getFunction());
167
168 auto SetMaxReg = [&](MCSymbol *MaxSym, int32_t numRegs,
169 ResourceInfoKind RIK) {
170 if (!FRI.HasIndirectCall) {
171 assignResourceInfoExpr(numRegs, RIK, AMDGPUMCExpr::AGVK_Max, MF,
172 FRI.Callees, OutContext);
173 } else {
174 const MCExpr *SymRef = MCSymbolRefExpr::create(MaxSym, OutContext);
175 MCSymbol *LocalNumSym = getSymbol(FnSym->getName(), RIK, OutContext);
176 const MCExpr *MaxWithLocal = AMDGPUMCExpr::createMax(
177 {MCConstantExpr::create(numRegs, OutContext), SymRef}, OutContext);
178 LocalNumSym->setVariableValue(MaxWithLocal);
179 }
180 };
181
182 SetMaxReg(MaxVGPRSym, FRI.NumVGPR, RIK_NumVGPR);
183 SetMaxReg(MaxAGPRSym, FRI.NumAGPR, RIK_NumAGPR);
184 SetMaxReg(MaxSGPRSym, FRI.NumExplicitSGPR, RIK_NumSGPR);
185
186 {
187 // The expression for private segment size should be: FRI.PrivateSegmentSize
188 // + max(FRI.Callees, FRI.CalleeSegmentSize)
190 MCSymbol *Sym = getSymbol(FnSym->getName(), RIK_PrivateSegSize, OutContext);
191 if (FRI.CalleeSegmentSize)
192 ArgExprs.push_back(
194
196 Seen.insert(&MF.getFunction());
197 for (const Function *Callee : FRI.Callees) {
198 if (!Seen.insert(Callee).second)
199 continue;
200 if (!Callee->isDeclaration()) {
201 MCSymbol *CalleeFnSym = TM.getSymbol(&Callee->getFunction());
202 MCSymbol *CalleeValSym =
203 getSymbol(CalleeFnSym->getName(), RIK_PrivateSegSize, OutContext);
204
205 // Avoid constructing recursive definitions by detecting whether `Sym`
206 // is found transitively within any of its `CalleeValSym`.
207 if (!CalleeValSym->isVariable() ||
208 !CalleeValSym->getVariableValue(/*isUsed=*/false)
210 ArgExprs.push_back(MCSymbolRefExpr::create(CalleeValSym, OutContext));
211 }
212 }
213 }
214 const MCExpr *localConstExpr =
216 if (!ArgExprs.empty()) {
217 const AMDGPUMCExpr *transitiveExpr =
218 AMDGPUMCExpr::createMax(ArgExprs, OutContext);
219 localConstExpr =
220 MCBinaryExpr::createAdd(localConstExpr, transitiveExpr, OutContext);
221 }
222 Sym->setVariableValue(localConstExpr);
223 }
224
225 auto SetToLocal = [&](int64_t LocalValue, ResourceInfoKind RIK) {
226 MCSymbol *Sym = getSymbol(FnSym->getName(), RIK, OutContext);
227 Sym->setVariableValue(MCConstantExpr::create(LocalValue, OutContext));
228 };
229
230 if (!FRI.HasIndirectCall) {
231 assignResourceInfoExpr(FRI.UsesVCC, ResourceInfoKind::RIK_UsesVCC,
232 AMDGPUMCExpr::AGVK_Or, MF, FRI.Callees, OutContext);
233 assignResourceInfoExpr(FRI.UsesFlatScratch,
235 AMDGPUMCExpr::AGVK_Or, MF, FRI.Callees, OutContext);
236 assignResourceInfoExpr(FRI.HasDynamicallySizedStack,
238 AMDGPUMCExpr::AGVK_Or, MF, FRI.Callees, OutContext);
239 assignResourceInfoExpr(FRI.HasRecursion, ResourceInfoKind::RIK_HasRecursion,
240 AMDGPUMCExpr::AGVK_Or, MF, FRI.Callees, OutContext);
241 assignResourceInfoExpr(FRI.HasIndirectCall,
243 AMDGPUMCExpr::AGVK_Or, MF, FRI.Callees, OutContext);
244 } else {
245 SetToLocal(FRI.UsesVCC, ResourceInfoKind::RIK_UsesVCC);
247 SetToLocal(FRI.HasDynamicallySizedStack,
251 }
252}
253
255 MCContext &Ctx) {
256 const TargetMachine &TM = MF.getTarget();
257 MCSymbol *FnSym = TM.getSymbol(&MF.getFunction());
259 getSymRefExpr(FnSym->getName(), RIK_NumAGPR, Ctx),
260 getSymRefExpr(FnSym->getName(), RIK_NumVGPR, Ctx), Ctx);
261}
262
264 bool hasXnack,
265 MCContext &Ctx) {
266 const TargetMachine &TM = MF.getTarget();
267 MCSymbol *FnSym = TM.getSymbol(&MF.getFunction());
269 getSymRefExpr(FnSym->getName(), RIK_NumSGPR, Ctx),
271 getSymRefExpr(FnSym->getName(), RIK_UsesVCC, Ctx),
272 getSymRefExpr(FnSym->getName(), RIK_UsesFlatScratch, Ctx), hasXnack,
273 Ctx),
274 Ctx);
275}
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
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
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)
const MCExpr * getSymRefExpr(StringRef FuncName, ResourceInfoKind RIK, MCContext &Ctx)
void gatherResourceInfo(const MachineFunction &MF, const AMDGPUResourceUsageAnalysis::SIFunctionResourceInfo &FRI, MCContext &OutContext)
AMDGPUResourceUsageAnalysis gathers resource usage on a per-function granularity.
MCSymbol * getMaxSGPRSymbol(MCContext &OutContext)
MCSymbol * getMaxAGPRSymbol(MCContext &OutContext)
const MCExpr * createTotalNumVGPRs(const MachineFunction &MF, MCContext &Ctx)
void finalize(MCContext &OutContext)
void addMaxAGPRCandidate(int32_t candidate)
MCSymbol * getMaxVGPRSymbol(MCContext &OutContext)
const MCExpr * createTotalNumSGPRs(const MachineFunction &MF, bool hasXnack, MCContext &Ctx)
MCSymbol * getSymbol(StringRef FuncName, ResourceInfoKind RIK, MCContext &OutContext)
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