[Clang/AMDGPU] Zero sized arrays not allowed in HIP device code. (#113470)
[llvm-project.git] / llvm / lib / Target / AMDGPU / AMDGPUMCResourceInfo.cpp
blob9511b6bb7de062b04cb07e6be077defce7db90eb
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 //===----------------------------------------------------------------------===//
15 #include "AMDGPUMCResourceInfo.h"
16 #include "Utils/AMDGPUBaseInfo.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/MC/MCContext.h"
19 #include "llvm/MC/MCSymbol.h"
20 #include "llvm/Target/TargetMachine.h"
22 using namespace llvm;
24 MCSymbol *MCResourceInfo::getSymbol(StringRef FuncName, ResourceInfoKind RIK,
25 MCContext &OutContext) {
26 auto GOCS = [FuncName, &OutContext](StringRef Suffix) {
27 return OutContext.getOrCreateSymbol(FuncName + Twine(Suffix));
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");
36 case RIK_PrivateSegSize:
37 return GOCS(".private_seg_size");
38 case RIK_UsesVCC:
39 return GOCS(".uses_vcc");
40 case RIK_UsesFlatScratch:
41 return GOCS(".uses_flat_scratch");
42 case RIK_HasDynSizedStack:
43 return GOCS(".has_dyn_sized_stack");
44 case RIK_HasRecursion:
45 return GOCS(".has_recursion");
46 case RIK_HasIndirectCall:
47 return GOCS(".has_indirect_call");
49 llvm_unreachable("Unexpected ResourceInfoKind.");
52 const MCExpr *MCResourceInfo::getSymRefExpr(StringRef FuncName,
53 ResourceInfoKind RIK,
54 MCContext &Ctx) {
55 return MCSymbolRefExpr::create(getSymbol(FuncName, RIK, Ctx), Ctx);
58 void 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);
64 auto assignMaxRegSym = [&OutContext](MCSymbol *Sym, int32_t RegCount) {
65 const MCExpr *MaxExpr = MCConstantExpr::create(RegCount, OutContext);
66 Sym->setVariableValue(MaxExpr);
69 assignMaxRegSym(MaxVGPRSym, MaxVGPR);
70 assignMaxRegSym(MaxAGPRSym, MaxAGPR);
71 assignMaxRegSym(MaxSGPRSym, MaxSGPR);
74 void MCResourceInfo::reset() { *this = MCResourceInfo(); }
76 void MCResourceInfo::finalize(MCContext &OutContext) {
77 assert(!Finalized && "Cannot finalize ResourceInfo again.");
78 Finalized = true;
79 assignMaxRegs(OutContext);
82 MCSymbol *MCResourceInfo::getMaxVGPRSymbol(MCContext &OutContext) {
83 return OutContext.getOrCreateSymbol("amdgpu.max_num_vgpr");
86 MCSymbol *MCResourceInfo::getMaxAGPRSymbol(MCContext &OutContext) {
87 return OutContext.getOrCreateSymbol("amdgpu.max_num_agpr");
90 MCSymbol *MCResourceInfo::getMaxSGPRSymbol(MCContext &OutContext) {
91 return OutContext.getOrCreateSymbol("amdgpu.max_num_sgpr");
94 void 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()) {
105 SmallVector<const MCExpr *, 8> ArgExprs;
106 SmallPtrSet<const Function *, 8> Seen;
107 ArgExprs.push_back(LocalConstExpr);
109 for (const Function *Callee : Callees) {
110 if (!Seen.insert(Callee).second)
111 continue;
113 MCSymbol *CalleeFnSym = TM.getSymbol(&Callee->getFunction());
114 MCSymbol *CalleeValSym =
115 getSymbol(CalleeFnSym->getName(), RIK, OutContext);
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)
121 ->isSymbolUsedInExpression(Sym)) {
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:
130 ArgExprs.push_back(MCSymbolRefExpr::create(
131 getMaxVGPRSymbol(OutContext), OutContext));
132 break;
133 case RIK_NumSGPR:
134 ArgExprs.push_back(MCSymbolRefExpr::create(
135 getMaxSGPRSymbol(OutContext), OutContext));
136 break;
137 case RIK_NumAGPR:
138 ArgExprs.push_back(MCSymbolRefExpr::create(
139 getMaxAGPRSymbol(OutContext), OutContext));
140 break;
144 if (ArgExprs.size() > 1)
145 SymVal = AMDGPUMCExpr::create(Kind, ArgExprs, OutContext);
147 Sym->setVariableValue(SymVal);
150 void MCResourceInfo::gatherResourceInfo(
151 const MachineFunction &MF,
152 const AMDGPUResourceUsageAnalysis::SIFunctionResourceInfo &FRI,
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);
159 if (!AMDGPU::isEntryFunctionCC(MF.getFunction().getCallingConv())) {
160 addMaxVGPRCandidate(FRI.NumVGPR);
161 addMaxAGPRCandidate(FRI.NumAGPR);
162 addMaxSGPRCandidate(FRI.NumExplicitSGPR);
165 const TargetMachine &TM = MF.getTarget();
166 MCSymbol *FnSym = TM.getSymbol(&MF.getFunction());
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);
182 SetMaxReg(MaxVGPRSym, FRI.NumVGPR, RIK_NumVGPR);
183 SetMaxReg(MaxAGPRSym, FRI.NumAGPR, RIK_NumAGPR);
184 SetMaxReg(MaxSGPRSym, FRI.NumExplicitSGPR, RIK_NumSGPR);
187 // The expression for private segment size should be: FRI.PrivateSegmentSize
188 // + max(FRI.Callees, FRI.CalleeSegmentSize)
189 SmallVector<const MCExpr *, 8> ArgExprs;
190 MCSymbol *Sym = getSymbol(FnSym->getName(), RIK_PrivateSegSize, OutContext);
191 if (FRI.CalleeSegmentSize)
192 ArgExprs.push_back(
193 MCConstantExpr::create(FRI.CalleeSegmentSize, OutContext));
195 SmallPtrSet<const Function *, 8> Seen;
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);
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)
209 ->isSymbolUsedInExpression(Sym)) {
210 ArgExprs.push_back(MCSymbolRefExpr::create(CalleeValSym, OutContext));
214 const MCExpr *localConstExpr =
215 MCConstantExpr::create(FRI.PrivateSegmentSize, OutContext);
216 if (!ArgExprs.empty()) {
217 const AMDGPUMCExpr *transitiveExpr =
218 AMDGPUMCExpr::createMax(ArgExprs, OutContext);
219 localConstExpr =
220 MCBinaryExpr::createAdd(localConstExpr, transitiveExpr, OutContext);
222 Sym->setVariableValue(localConstExpr);
225 auto SetToLocal = [&](int64_t LocalValue, ResourceInfoKind RIK) {
226 MCSymbol *Sym = getSymbol(FnSym->getName(), RIK, OutContext);
227 Sym->setVariableValue(MCConstantExpr::create(LocalValue, OutContext));
230 if (!FRI.HasIndirectCall) {
231 assignResourceInfoExpr(FRI.UsesVCC, ResourceInfoKind::RIK_UsesVCC,
232 AMDGPUMCExpr::AGVK_Or, MF, FRI.Callees, OutContext);
233 assignResourceInfoExpr(FRI.UsesFlatScratch,
234 ResourceInfoKind::RIK_UsesFlatScratch,
235 AMDGPUMCExpr::AGVK_Or, MF, FRI.Callees, OutContext);
236 assignResourceInfoExpr(FRI.HasDynamicallySizedStack,
237 ResourceInfoKind::RIK_HasDynSizedStack,
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,
242 ResourceInfoKind::RIK_HasIndirectCall,
243 AMDGPUMCExpr::AGVK_Or, MF, FRI.Callees, OutContext);
244 } else {
245 SetToLocal(FRI.UsesVCC, ResourceInfoKind::RIK_UsesVCC);
246 SetToLocal(FRI.UsesFlatScratch, ResourceInfoKind::RIK_UsesFlatScratch);
247 SetToLocal(FRI.HasDynamicallySizedStack,
248 ResourceInfoKind::RIK_HasDynSizedStack);
249 SetToLocal(FRI.HasRecursion, ResourceInfoKind::RIK_HasRecursion);
250 SetToLocal(FRI.HasIndirectCall, ResourceInfoKind::RIK_HasIndirectCall);
254 const MCExpr *MCResourceInfo::createTotalNumVGPRs(const MachineFunction &MF,
255 MCContext &Ctx) {
256 const TargetMachine &TM = MF.getTarget();
257 MCSymbol *FnSym = TM.getSymbol(&MF.getFunction());
258 return AMDGPUMCExpr::createTotalNumVGPR(
259 getSymRefExpr(FnSym->getName(), RIK_NumAGPR, Ctx),
260 getSymRefExpr(FnSym->getName(), RIK_NumVGPR, Ctx), Ctx);
263 const MCExpr *MCResourceInfo::createTotalNumSGPRs(const MachineFunction &MF,
264 bool hasXnack,
265 MCContext &Ctx) {
266 const TargetMachine &TM = MF.getTarget();
267 MCSymbol *FnSym = TM.getSymbol(&MF.getFunction());
268 return MCBinaryExpr::createAdd(
269 getSymRefExpr(FnSym->getName(), RIK_NumSGPR, Ctx),
270 AMDGPUMCExpr::createExtraSGPRs(
271 getSymRefExpr(FnSym->getName(), RIK_UsesVCC, Ctx),
272 getSymRefExpr(FnSym->getName(), RIK_UsesFlatScratch, Ctx), hasXnack,
273 Ctx),
274 Ctx);