xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===-- AMDGPUAsmPrinter.cpp - AMDGPU assembly printer --------------------===//
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 ///
11 /// The AMDGPUAsmPrinter is used to print both assembly string and also binary
12 /// code.  When passed an MCAsmStreamer it prints assembly and when passed
13 /// an MCObjectStreamer it outputs binary code.
14 //
15 //===----------------------------------------------------------------------===//
16 //
17 
18 #include "AMDGPUAsmPrinter.h"
19 #include "AMDGPU.h"
20 #include "AMDGPUHSAMetadataStreamer.h"
21 #include "AMDGPUResourceUsageAnalysis.h"
22 #include "GCNSubtarget.h"
23 #include "MCTargetDesc/AMDGPUInstPrinter.h"
24 #include "MCTargetDesc/AMDGPUMCExpr.h"
25 #include "MCTargetDesc/AMDGPUMCKernelDescriptor.h"
26 #include "MCTargetDesc/AMDGPUTargetStreamer.h"
27 #include "R600AsmPrinter.h"
28 #include "SIMachineFunctionInfo.h"
29 #include "TargetInfo/AMDGPUTargetInfo.h"
30 #include "Utils/AMDGPUBaseInfo.h"
31 #include "Utils/AMDKernelCodeTUtils.h"
32 #include "Utils/SIDefinesUtils.h"
33 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
34 #include "llvm/BinaryFormat/ELF.h"
35 #include "llvm/CodeGen/MachineFrameInfo.h"
36 #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
37 #include "llvm/IR/DiagnosticInfo.h"
38 #include "llvm/MC/MCAssembler.h"
39 #include "llvm/MC/MCContext.h"
40 #include "llvm/MC/MCSectionELF.h"
41 #include "llvm/MC/MCStreamer.h"
42 #include "llvm/MC/TargetRegistry.h"
43 #include "llvm/Support/AMDHSAKernelDescriptor.h"
44 #include "llvm/Target/TargetLoweringObjectFile.h"
45 #include "llvm/Target/TargetMachine.h"
46 #include "llvm/TargetParser/TargetParser.h"
47 
48 using namespace llvm;
49 using namespace llvm::AMDGPU;
50 
51 // This should get the default rounding mode from the kernel. We just set the
52 // default here, but this could change if the OpenCL rounding mode pragmas are
53 // used.
54 //
55 // The denormal mode here should match what is reported by the OpenCL runtime
56 // for the CL_FP_DENORM bit from CL_DEVICE_{HALF|SINGLE|DOUBLE}_FP_CONFIG, but
57 // can also be override to flush with the -cl-denorms-are-zero compiler flag.
58 //
59 // AMD OpenCL only sets flush none and reports CL_FP_DENORM for double
60 // precision, and leaves single precision to flush all and does not report
61 // CL_FP_DENORM for CL_DEVICE_SINGLE_FP_CONFIG. Mesa's OpenCL currently reports
62 // CL_FP_DENORM for both.
63 //
64 // FIXME: It seems some instructions do not support single precision denormals
65 // regardless of the mode (exp_*_f32, rcp_*_f32, rsq_*_f32, rsq_*f32, sqrt_f32,
66 // and sin_f32, cos_f32 on most parts).
67 
68 // We want to use these instructions, and using fp32 denormals also causes
69 // instructions to run at the double precision rate for the device so it's
70 // probably best to just report no single precision denormals.
getFPMode(SIModeRegisterDefaults Mode)71 static uint32_t getFPMode(SIModeRegisterDefaults Mode) {
72   return FP_ROUND_MODE_SP(FP_ROUND_ROUND_TO_NEAREST) |
73          FP_ROUND_MODE_DP(FP_ROUND_ROUND_TO_NEAREST) |
74          FP_DENORM_MODE_SP(Mode.fpDenormModeSPValue()) |
75          FP_DENORM_MODE_DP(Mode.fpDenormModeDPValue());
76 }
77 
78 static AsmPrinter *
createAMDGPUAsmPrinterPass(TargetMachine & tm,std::unique_ptr<MCStreamer> && Streamer)79 createAMDGPUAsmPrinterPass(TargetMachine &tm,
80                            std::unique_ptr<MCStreamer> &&Streamer) {
81   return new AMDGPUAsmPrinter(tm, std::move(Streamer));
82 }
83 
LLVMInitializeAMDGPUAsmPrinter()84 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAMDGPUAsmPrinter() {
85   TargetRegistry::RegisterAsmPrinter(getTheR600Target(),
86                                      llvm::createR600AsmPrinterPass);
87   TargetRegistry::RegisterAsmPrinter(getTheGCNTarget(),
88                                      createAMDGPUAsmPrinterPass);
89 }
90 
AMDGPUAsmPrinter(TargetMachine & TM,std::unique_ptr<MCStreamer> Streamer)91 AMDGPUAsmPrinter::AMDGPUAsmPrinter(TargetMachine &TM,
92                                    std::unique_ptr<MCStreamer> Streamer)
93     : AsmPrinter(TM, std::move(Streamer)) {
94   assert(OutStreamer && "AsmPrinter constructed without streamer");
95 }
96 
getPassName() const97 StringRef AMDGPUAsmPrinter::getPassName() const {
98   return "AMDGPU Assembly Printer";
99 }
100 
getGlobalSTI() const101 const MCSubtargetInfo *AMDGPUAsmPrinter::getGlobalSTI() const {
102   return TM.getMCSubtargetInfo();
103 }
104 
getTargetStreamer() const105 AMDGPUTargetStreamer* AMDGPUAsmPrinter::getTargetStreamer() const {
106   if (!OutStreamer)
107     return nullptr;
108   return static_cast<AMDGPUTargetStreamer*>(OutStreamer->getTargetStreamer());
109 }
110 
emitStartOfAsmFile(Module & M)111 void AMDGPUAsmPrinter::emitStartOfAsmFile(Module &M) {
112   IsTargetStreamerInitialized = false;
113 }
114 
initTargetStreamer(Module & M)115 void AMDGPUAsmPrinter::initTargetStreamer(Module &M) {
116   IsTargetStreamerInitialized = true;
117 
118   // TODO: Which one is called first, emitStartOfAsmFile or
119   // emitFunctionBodyStart?
120   if (getTargetStreamer() && !getTargetStreamer()->getTargetID())
121     initializeTargetID(M);
122 
123   if (TM.getTargetTriple().getOS() != Triple::AMDHSA &&
124       TM.getTargetTriple().getOS() != Triple::AMDPAL)
125     return;
126 
127   getTargetStreamer()->EmitDirectiveAMDGCNTarget();
128 
129   if (TM.getTargetTriple().getOS() == Triple::AMDHSA) {
130     getTargetStreamer()->EmitDirectiveAMDHSACodeObjectVersion(
131         CodeObjectVersion);
132     HSAMetadataStream->begin(M, *getTargetStreamer()->getTargetID());
133   }
134 
135   if (TM.getTargetTriple().getOS() == Triple::AMDPAL)
136     getTargetStreamer()->getPALMetadata()->readFromIR(M);
137 }
138 
emitEndOfAsmFile(Module & M)139 void AMDGPUAsmPrinter::emitEndOfAsmFile(Module &M) {
140   // Init target streamer if it has not yet happened
141   if (!IsTargetStreamerInitialized)
142     initTargetStreamer(M);
143 
144   if (TM.getTargetTriple().getOS() != Triple::AMDHSA)
145     getTargetStreamer()->EmitISAVersion();
146 
147   // Emit HSA Metadata (NT_AMD_AMDGPU_HSA_METADATA).
148   // Emit HSA Metadata (NT_AMD_HSA_METADATA).
149   if (TM.getTargetTriple().getOS() == Triple::AMDHSA) {
150     HSAMetadataStream->end();
151     bool Success = HSAMetadataStream->emitTo(*getTargetStreamer());
152     (void)Success;
153     assert(Success && "Malformed HSA Metadata");
154   }
155 }
156 
emitFunctionBodyStart()157 void AMDGPUAsmPrinter::emitFunctionBodyStart() {
158   const SIMachineFunctionInfo &MFI = *MF->getInfo<SIMachineFunctionInfo>();
159   const GCNSubtarget &STM = MF->getSubtarget<GCNSubtarget>();
160   const Function &F = MF->getFunction();
161 
162   // TODO: We're checking this late, would be nice to check it earlier.
163   if (STM.requiresCodeObjectV6() && CodeObjectVersion < AMDGPU::AMDHSA_COV6) {
164     report_fatal_error(
165         STM.getCPU() + " is only available on code object version 6 or better",
166         /*gen_crash_diag*/ false);
167   }
168 
169   // TODO: Which one is called first, emitStartOfAsmFile or
170   // emitFunctionBodyStart?
171   if (!getTargetStreamer()->getTargetID())
172     initializeTargetID(*F.getParent());
173 
174   const auto &FunctionTargetID = STM.getTargetID();
175   // Make sure function's xnack settings are compatible with module's
176   // xnack settings.
177   if (FunctionTargetID.isXnackSupported() &&
178       FunctionTargetID.getXnackSetting() != IsaInfo::TargetIDSetting::Any &&
179       FunctionTargetID.getXnackSetting() != getTargetStreamer()->getTargetID()->getXnackSetting()) {
180     OutContext.reportError({}, "xnack setting of '" + Twine(MF->getName()) +
181                            "' function does not match module xnack setting");
182     return;
183   }
184   // Make sure function's sramecc settings are compatible with module's
185   // sramecc settings.
186   if (FunctionTargetID.isSramEccSupported() &&
187       FunctionTargetID.getSramEccSetting() != IsaInfo::TargetIDSetting::Any &&
188       FunctionTargetID.getSramEccSetting() != getTargetStreamer()->getTargetID()->getSramEccSetting()) {
189     OutContext.reportError({}, "sramecc setting of '" + Twine(MF->getName()) +
190                            "' function does not match module sramecc setting");
191     return;
192   }
193 
194   if (!MFI.isEntryFunction())
195     return;
196 
197   if (STM.isMesaKernel(F) &&
198       (F.getCallingConv() == CallingConv::AMDGPU_KERNEL ||
199        F.getCallingConv() == CallingConv::SPIR_KERNEL)) {
200     AMDGPUMCKernelCodeT KernelCode;
201     getAmdKernelCode(KernelCode, CurrentProgramInfo, *MF);
202     KernelCode.validate(&STM, MF->getContext());
203     getTargetStreamer()->EmitAMDKernelCodeT(KernelCode);
204   }
205 
206   if (STM.isAmdHsaOS())
207     HSAMetadataStream->emitKernel(*MF, CurrentProgramInfo);
208 
209   if (MFI.getNumKernargPreloadedSGPRs() > 0) {
210     assert(AMDGPU::hasKernargPreload(STM));
211     getTargetStreamer()->EmitKernargPreloadHeader(*getGlobalSTI(),
212                                                   STM.isAmdHsaOS());
213   }
214 }
215 
emitFunctionBodyEnd()216 void AMDGPUAsmPrinter::emitFunctionBodyEnd() {
217   const SIMachineFunctionInfo &MFI = *MF->getInfo<SIMachineFunctionInfo>();
218   if (!MFI.isEntryFunction())
219     return;
220 
221   if (TM.getTargetTriple().getOS() != Triple::AMDHSA)
222     return;
223 
224   auto &Streamer = getTargetStreamer()->getStreamer();
225   auto &Context = Streamer.getContext();
226   auto &ObjectFileInfo = *Context.getObjectFileInfo();
227   auto &ReadOnlySection = *ObjectFileInfo.getReadOnlySection();
228 
229   Streamer.pushSection();
230   Streamer.switchSection(&ReadOnlySection);
231 
232   // CP microcode requires the kernel descriptor to be allocated on 64 byte
233   // alignment.
234   Streamer.emitValueToAlignment(Align(64), 0, 1, 0);
235   ReadOnlySection.ensureMinAlignment(Align(64));
236 
237   const GCNSubtarget &STM = MF->getSubtarget<GCNSubtarget>();
238 
239   SmallString<128> KernelName;
240   getNameWithPrefix(KernelName, &MF->getFunction());
241   getTargetStreamer()->EmitAmdhsaKernelDescriptor(
242       STM, KernelName, getAmdhsaKernelDescriptor(*MF, CurrentProgramInfo),
243       CurrentProgramInfo.NumVGPRsForWavesPerEU,
244       MCBinaryExpr::createSub(
245           CurrentProgramInfo.NumSGPRsForWavesPerEU,
246           AMDGPUMCExpr::createExtraSGPRs(
247               CurrentProgramInfo.VCCUsed, CurrentProgramInfo.FlatUsed,
248               getTargetStreamer()->getTargetID()->isXnackOnOrAny(), Context),
249           Context),
250       CurrentProgramInfo.VCCUsed, CurrentProgramInfo.FlatUsed);
251 
252   Streamer.popSection();
253 }
254 
emitImplicitDef(const MachineInstr * MI) const255 void AMDGPUAsmPrinter::emitImplicitDef(const MachineInstr *MI) const {
256   Register RegNo = MI->getOperand(0).getReg();
257 
258   SmallString<128> Str;
259   raw_svector_ostream OS(Str);
260   OS << "implicit-def: "
261      << printReg(RegNo, MF->getSubtarget().getRegisterInfo());
262 
263   if (MI->getAsmPrinterFlags() & AMDGPU::SGPR_SPILL)
264     OS << " : SGPR spill to VGPR lane";
265 
266   OutStreamer->AddComment(OS.str());
267   OutStreamer->addBlankLine();
268 }
269 
emitFunctionEntryLabel()270 void AMDGPUAsmPrinter::emitFunctionEntryLabel() {
271   if (TM.getTargetTriple().getOS() == Triple::AMDHSA) {
272     AsmPrinter::emitFunctionEntryLabel();
273     return;
274   }
275 
276   const SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>();
277   const GCNSubtarget &STM = MF->getSubtarget<GCNSubtarget>();
278   if (MFI->isEntryFunction() && STM.isAmdHsaOrMesa(MF->getFunction())) {
279     SmallString<128> SymbolName;
280     getNameWithPrefix(SymbolName, &MF->getFunction()),
281     getTargetStreamer()->EmitAMDGPUSymbolType(
282         SymbolName, ELF::STT_AMDGPU_HSA_KERNEL);
283   }
284   if (DumpCodeInstEmitter) {
285     // Disassemble function name label to text.
286     DisasmLines.push_back(MF->getName().str() + ":");
287     DisasmLineMaxLen = std::max(DisasmLineMaxLen, DisasmLines.back().size());
288     HexLines.emplace_back("");
289   }
290 
291   AsmPrinter::emitFunctionEntryLabel();
292 }
293 
emitBasicBlockStart(const MachineBasicBlock & MBB)294 void AMDGPUAsmPrinter::emitBasicBlockStart(const MachineBasicBlock &MBB) {
295   if (DumpCodeInstEmitter && !isBlockOnlyReachableByFallthrough(&MBB)) {
296     // Write a line for the basic block label if it is not only fallthrough.
297     DisasmLines.push_back(
298         (Twine("BB") + Twine(getFunctionNumber())
299          + "_" + Twine(MBB.getNumber()) + ":").str());
300     DisasmLineMaxLen = std::max(DisasmLineMaxLen, DisasmLines.back().size());
301     HexLines.emplace_back("");
302   }
303   AsmPrinter::emitBasicBlockStart(MBB);
304 }
305 
emitGlobalVariable(const GlobalVariable * GV)306 void AMDGPUAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
307   if (GV->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS) {
308     if (GV->hasInitializer() && !isa<UndefValue>(GV->getInitializer())) {
309       OutContext.reportError({},
310                              Twine(GV->getName()) +
311                                  ": unsupported initializer for address space");
312       return;
313     }
314 
315     // LDS variables aren't emitted in HSA or PAL yet.
316     const Triple::OSType OS = TM.getTargetTriple().getOS();
317     if (OS == Triple::AMDHSA || OS == Triple::AMDPAL)
318       return;
319 
320     MCSymbol *GVSym = getSymbol(GV);
321 
322     GVSym->redefineIfPossible();
323     if (GVSym->isDefined() || GVSym->isVariable())
324       report_fatal_error("symbol '" + Twine(GVSym->getName()) +
325                          "' is already defined");
326 
327     const DataLayout &DL = GV->getDataLayout();
328     uint64_t Size = DL.getTypeAllocSize(GV->getValueType());
329     Align Alignment = GV->getAlign().value_or(Align(4));
330 
331     emitVisibility(GVSym, GV->getVisibility(), !GV->isDeclaration());
332     emitLinkage(GV, GVSym);
333     auto TS = getTargetStreamer();
334     TS->emitAMDGPULDS(GVSym, Size, Alignment);
335     return;
336   }
337 
338   AsmPrinter::emitGlobalVariable(GV);
339 }
340 
doInitialization(Module & M)341 bool AMDGPUAsmPrinter::doInitialization(Module &M) {
342   CodeObjectVersion = AMDGPU::getAMDHSACodeObjectVersion(M);
343 
344   if (TM.getTargetTriple().getOS() == Triple::AMDHSA) {
345     switch (CodeObjectVersion) {
346     case AMDGPU::AMDHSA_COV4:
347       HSAMetadataStream = std::make_unique<HSAMD::MetadataStreamerMsgPackV4>();
348       break;
349     case AMDGPU::AMDHSA_COV5:
350       HSAMetadataStream = std::make_unique<HSAMD::MetadataStreamerMsgPackV5>();
351       break;
352     case AMDGPU::AMDHSA_COV6:
353       HSAMetadataStream = std::make_unique<HSAMD::MetadataStreamerMsgPackV6>();
354       break;
355     default:
356       report_fatal_error("Unexpected code object version");
357     }
358   }
359   return AsmPrinter::doInitialization(M);
360 }
361 
doFinalization(Module & M)362 bool AMDGPUAsmPrinter::doFinalization(Module &M) {
363   // Pad with s_code_end to help tools and guard against instruction prefetch
364   // causing stale data in caches. Arguably this should be done by the linker,
365   // which is why this isn't done for Mesa.
366   const MCSubtargetInfo &STI = *getGlobalSTI();
367   if ((AMDGPU::isGFX10Plus(STI) || AMDGPU::isGFX90A(STI)) &&
368       (STI.getTargetTriple().getOS() == Triple::AMDHSA ||
369        STI.getTargetTriple().getOS() == Triple::AMDPAL)) {
370     OutStreamer->switchSection(getObjFileLowering().getTextSection());
371     getTargetStreamer()->EmitCodeEnd(STI);
372   }
373 
374   return AsmPrinter::doFinalization(M);
375 }
376 
377 // Print comments that apply to both callable functions and entry points.
emitCommonFunctionComments(uint32_t NumVGPR,std::optional<uint32_t> NumAGPR,uint32_t TotalNumVGPR,uint32_t NumSGPR,uint64_t ScratchSize,uint64_t CodeSize,const AMDGPUMachineFunction * MFI)378 void AMDGPUAsmPrinter::emitCommonFunctionComments(
379     uint32_t NumVGPR, std::optional<uint32_t> NumAGPR, uint32_t TotalNumVGPR,
380     uint32_t NumSGPR, uint64_t ScratchSize, uint64_t CodeSize,
381     const AMDGPUMachineFunction *MFI) {
382   OutStreamer->emitRawComment(" codeLenInByte = " + Twine(CodeSize), false);
383   OutStreamer->emitRawComment(" NumSgprs: " + Twine(NumSGPR), false);
384   OutStreamer->emitRawComment(" NumVgprs: " + Twine(NumVGPR), false);
385   if (NumAGPR) {
386     OutStreamer->emitRawComment(" NumAgprs: " + Twine(*NumAGPR), false);
387     OutStreamer->emitRawComment(" TotalNumVgprs: " + Twine(TotalNumVGPR),
388                                 false);
389   }
390   OutStreamer->emitRawComment(" ScratchSize: " + Twine(ScratchSize), false);
391   OutStreamer->emitRawComment(" MemoryBound: " + Twine(MFI->isMemoryBound()),
392                               false);
393 }
394 
getMCExprStr(const MCExpr * Value)395 SmallString<128> AMDGPUAsmPrinter::getMCExprStr(const MCExpr *Value) {
396   SmallString<128> Str;
397   raw_svector_ostream OSS(Str);
398   int64_t IVal;
399   if (Value->evaluateAsAbsolute(IVal)) {
400     OSS << static_cast<uint64_t>(IVal);
401   } else {
402     Value->print(OSS, MAI);
403   }
404   return Str;
405 }
406 
emitCommonFunctionComments(const MCExpr * NumVGPR,const MCExpr * NumAGPR,const MCExpr * TotalNumVGPR,const MCExpr * NumSGPR,const MCExpr * ScratchSize,uint64_t CodeSize,const AMDGPUMachineFunction * MFI)407 void AMDGPUAsmPrinter::emitCommonFunctionComments(
408     const MCExpr *NumVGPR, const MCExpr *NumAGPR, const MCExpr *TotalNumVGPR,
409     const MCExpr *NumSGPR, const MCExpr *ScratchSize, uint64_t CodeSize,
410     const AMDGPUMachineFunction *MFI) {
411   OutStreamer->emitRawComment(" codeLenInByte = " + Twine(CodeSize), false);
412   OutStreamer->emitRawComment(" NumSgprs: " + getMCExprStr(NumSGPR), false);
413   OutStreamer->emitRawComment(" NumVgprs: " + getMCExprStr(NumVGPR), false);
414   if (NumAGPR && TotalNumVGPR) {
415     OutStreamer->emitRawComment(" NumAgprs: " + getMCExprStr(NumAGPR), false);
416     OutStreamer->emitRawComment(" TotalNumVgprs: " + getMCExprStr(TotalNumVGPR),
417                                 false);
418   }
419   OutStreamer->emitRawComment(" ScratchSize: " + getMCExprStr(ScratchSize),
420                               false);
421   OutStreamer->emitRawComment(" MemoryBound: " + Twine(MFI->isMemoryBound()),
422                               false);
423 }
424 
getAmdhsaKernelCodeProperties(const MachineFunction & MF) const425 const MCExpr *AMDGPUAsmPrinter::getAmdhsaKernelCodeProperties(
426     const MachineFunction &MF) const {
427   const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
428   MCContext &Ctx = MF.getContext();
429   uint16_t KernelCodeProperties = 0;
430   const GCNUserSGPRUsageInfo &UserSGPRInfo = MFI.getUserSGPRInfo();
431 
432   if (UserSGPRInfo.hasPrivateSegmentBuffer()) {
433     KernelCodeProperties |=
434         amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER;
435   }
436   if (UserSGPRInfo.hasDispatchPtr()) {
437     KernelCodeProperties |=
438         amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR;
439   }
440   if (UserSGPRInfo.hasQueuePtr() && CodeObjectVersion < AMDGPU::AMDHSA_COV5) {
441     KernelCodeProperties |=
442         amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR;
443   }
444   if (UserSGPRInfo.hasKernargSegmentPtr()) {
445     KernelCodeProperties |=
446         amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR;
447   }
448   if (UserSGPRInfo.hasDispatchID()) {
449     KernelCodeProperties |=
450         amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID;
451   }
452   if (UserSGPRInfo.hasFlatScratchInit()) {
453     KernelCodeProperties |=
454         amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT;
455   }
456   if (UserSGPRInfo.hasPrivateSegmentSize()) {
457     KernelCodeProperties |=
458         amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE;
459   }
460   if (MF.getSubtarget<GCNSubtarget>().isWave32()) {
461     KernelCodeProperties |=
462         amdhsa::KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32;
463   }
464 
465   // CurrentProgramInfo.DynamicCallStack is a MCExpr and could be
466   // un-evaluatable at this point so it cannot be conditionally checked here.
467   // Instead, we'll directly shift the possibly unknown MCExpr into its place
468   // and bitwise-or it into KernelCodeProperties.
469   const MCExpr *KernelCodePropExpr =
470       MCConstantExpr::create(KernelCodeProperties, Ctx);
471   const MCExpr *OrValue = MCConstantExpr::create(
472       amdhsa::KERNEL_CODE_PROPERTY_USES_DYNAMIC_STACK_SHIFT, Ctx);
473   OrValue = MCBinaryExpr::createShl(CurrentProgramInfo.DynamicCallStack,
474                                     OrValue, Ctx);
475   KernelCodePropExpr = MCBinaryExpr::createOr(KernelCodePropExpr, OrValue, Ctx);
476 
477   return KernelCodePropExpr;
478 }
479 
480 MCKernelDescriptor
getAmdhsaKernelDescriptor(const MachineFunction & MF,const SIProgramInfo & PI) const481 AMDGPUAsmPrinter::getAmdhsaKernelDescriptor(const MachineFunction &MF,
482                                             const SIProgramInfo &PI) const {
483   const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
484   const Function &F = MF.getFunction();
485   const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
486   MCContext &Ctx = MF.getContext();
487 
488   MCKernelDescriptor KernelDescriptor;
489 
490   KernelDescriptor.group_segment_fixed_size =
491       MCConstantExpr::create(PI.LDSSize, Ctx);
492   KernelDescriptor.private_segment_fixed_size = PI.ScratchSize;
493 
494   Align MaxKernArgAlign;
495   KernelDescriptor.kernarg_size = MCConstantExpr::create(
496       STM.getKernArgSegmentSize(F, MaxKernArgAlign), Ctx);
497 
498   KernelDescriptor.compute_pgm_rsrc1 = PI.getComputePGMRSrc1(STM, Ctx);
499   KernelDescriptor.compute_pgm_rsrc2 = PI.getComputePGMRSrc2(Ctx);
500   KernelDescriptor.kernel_code_properties = getAmdhsaKernelCodeProperties(MF);
501 
502   int64_t PGRM_Rsrc3 = 1;
503   bool EvaluatableRsrc3 =
504       CurrentProgramInfo.ComputePGMRSrc3GFX90A->evaluateAsAbsolute(PGRM_Rsrc3);
505   (void)PGRM_Rsrc3;
506   (void)EvaluatableRsrc3;
507   assert(STM.hasGFX90AInsts() || !EvaluatableRsrc3 ||
508          static_cast<uint64_t>(PGRM_Rsrc3) == 0);
509   KernelDescriptor.compute_pgm_rsrc3 = CurrentProgramInfo.ComputePGMRSrc3GFX90A;
510 
511   KernelDescriptor.kernarg_preload = MCConstantExpr::create(
512       AMDGPU::hasKernargPreload(STM) ? Info->getNumKernargPreloadedSGPRs() : 0,
513       Ctx);
514 
515   return KernelDescriptor;
516 }
517 
runOnMachineFunction(MachineFunction & MF)518 bool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
519   // Init target streamer lazily on the first function so that previous passes
520   // can set metadata.
521   if (!IsTargetStreamerInitialized)
522     initTargetStreamer(*MF.getFunction().getParent());
523 
524   ResourceUsage = &getAnalysis<AMDGPUResourceUsageAnalysis>();
525   CurrentProgramInfo.reset(MF);
526 
527   const AMDGPUMachineFunction *MFI = MF.getInfo<AMDGPUMachineFunction>();
528   MCContext &Ctx = MF.getContext();
529 
530   // The starting address of all shader programs must be 256 bytes aligned.
531   // Regular functions just need the basic required instruction alignment.
532   MF.setAlignment(MFI->isEntryFunction() ? Align(256) : Align(4));
533 
534   SetupMachineFunction(MF);
535 
536   const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
537   MCContext &Context = getObjFileLowering().getContext();
538   // FIXME: This should be an explicit check for Mesa.
539   if (!STM.isAmdHsaOS() && !STM.isAmdPalOS()) {
540     MCSectionELF *ConfigSection =
541         Context.getELFSection(".AMDGPU.config", ELF::SHT_PROGBITS, 0);
542     OutStreamer->switchSection(ConfigSection);
543   }
544 
545   if (MFI->isModuleEntryFunction()) {
546     getSIProgramInfo(CurrentProgramInfo, MF);
547   }
548 
549   if (STM.isAmdPalOS()) {
550     if (MFI->isEntryFunction())
551       EmitPALMetadata(MF, CurrentProgramInfo);
552     else if (MFI->isModuleEntryFunction())
553       emitPALFunctionMetadata(MF);
554   } else if (!STM.isAmdHsaOS()) {
555     EmitProgramInfoSI(MF, CurrentProgramInfo);
556   }
557 
558   DumpCodeInstEmitter = nullptr;
559   if (STM.dumpCode()) {
560     // For -dumpcode, get the assembler out of the streamer. This only works
561     // with -filetype=obj.
562     MCAssembler *Assembler = OutStreamer->getAssemblerPtr();
563     if (Assembler)
564       DumpCodeInstEmitter = Assembler->getEmitterPtr();
565   }
566 
567   DisasmLines.clear();
568   HexLines.clear();
569   DisasmLineMaxLen = 0;
570 
571   emitFunctionBody();
572 
573   emitResourceUsageRemarks(MF, CurrentProgramInfo, MFI->isModuleEntryFunction(),
574                            STM.hasMAIInsts());
575 
576   if (isVerbose()) {
577     MCSectionELF *CommentSection =
578         Context.getELFSection(".AMDGPU.csdata", ELF::SHT_PROGBITS, 0);
579     OutStreamer->switchSection(CommentSection);
580 
581     if (!MFI->isEntryFunction()) {
582       OutStreamer->emitRawComment(" Function info:", false);
583       const AMDGPUResourceUsageAnalysis::SIFunctionResourceInfo &Info =
584           ResourceUsage->getResourceInfo(&MF.getFunction());
585       emitCommonFunctionComments(
586           Info.NumVGPR,
587           STM.hasMAIInsts() ? Info.NumAGPR : std::optional<uint32_t>(),
588           Info.getTotalNumVGPRs(STM),
589           Info.getTotalNumSGPRs(MF.getSubtarget<GCNSubtarget>()),
590           Info.PrivateSegmentSize, getFunctionCodeSize(MF), MFI);
591       return false;
592     }
593 
594     OutStreamer->emitRawComment(" Kernel info:", false);
595     emitCommonFunctionComments(
596         CurrentProgramInfo.NumArchVGPR,
597         STM.hasMAIInsts() ? CurrentProgramInfo.NumAccVGPR : nullptr,
598         CurrentProgramInfo.NumVGPR, CurrentProgramInfo.NumSGPR,
599         CurrentProgramInfo.ScratchSize, getFunctionCodeSize(MF), MFI);
600 
601     OutStreamer->emitRawComment(
602       " FloatMode: " + Twine(CurrentProgramInfo.FloatMode), false);
603     OutStreamer->emitRawComment(
604       " IeeeMode: " + Twine(CurrentProgramInfo.IEEEMode), false);
605     OutStreamer->emitRawComment(
606       " LDSByteSize: " + Twine(CurrentProgramInfo.LDSSize) +
607       " bytes/workgroup (compile time only)", false);
608 
609     OutStreamer->emitRawComment(
610         " SGPRBlocks: " + getMCExprStr(CurrentProgramInfo.SGPRBlocks), false);
611 
612     OutStreamer->emitRawComment(
613         " VGPRBlocks: " + getMCExprStr(CurrentProgramInfo.VGPRBlocks), false);
614 
615     OutStreamer->emitRawComment(
616         " NumSGPRsForWavesPerEU: " +
617             getMCExprStr(CurrentProgramInfo.NumSGPRsForWavesPerEU),
618         false);
619     OutStreamer->emitRawComment(
620         " NumVGPRsForWavesPerEU: " +
621             getMCExprStr(CurrentProgramInfo.NumVGPRsForWavesPerEU),
622         false);
623 
624     if (STM.hasGFX90AInsts()) {
625       const MCExpr *AdjustedAccum = MCBinaryExpr::createAdd(
626           CurrentProgramInfo.AccumOffset, MCConstantExpr::create(1, Ctx), Ctx);
627       AdjustedAccum = MCBinaryExpr::createMul(
628           AdjustedAccum, MCConstantExpr::create(4, Ctx), Ctx);
629       OutStreamer->emitRawComment(
630           " AccumOffset: " + getMCExprStr(AdjustedAccum), false);
631     }
632 
633     OutStreamer->emitRawComment(
634         " Occupancy: " + getMCExprStr(CurrentProgramInfo.Occupancy), false);
635 
636     OutStreamer->emitRawComment(
637       " WaveLimiterHint : " + Twine(MFI->needsWaveLimiter()), false);
638 
639     OutStreamer->emitRawComment(
640         " COMPUTE_PGM_RSRC2:SCRATCH_EN: " +
641             getMCExprStr(CurrentProgramInfo.ScratchEnable),
642         false);
643     OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:USER_SGPR: " +
644                                     Twine(CurrentProgramInfo.UserSGPR),
645                                 false);
646     OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TRAP_HANDLER: " +
647                                     Twine(CurrentProgramInfo.TrapHandlerEnable),
648                                 false);
649     OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TGID_X_EN: " +
650                                     Twine(CurrentProgramInfo.TGIdXEnable),
651                                 false);
652     OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TGID_Y_EN: " +
653                                     Twine(CurrentProgramInfo.TGIdYEnable),
654                                 false);
655     OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TGID_Z_EN: " +
656                                     Twine(CurrentProgramInfo.TGIdZEnable),
657                                 false);
658     OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TIDIG_COMP_CNT: " +
659                                     Twine(CurrentProgramInfo.TIdIGCompCount),
660                                 false);
661 
662     [[maybe_unused]] int64_t PGMRSrc3;
663     assert(STM.hasGFX90AInsts() ||
664            (CurrentProgramInfo.ComputePGMRSrc3GFX90A->evaluateAsAbsolute(
665                 PGMRSrc3) &&
666             static_cast<uint64_t>(PGMRSrc3) == 0));
667     if (STM.hasGFX90AInsts()) {
668       OutStreamer->emitRawComment(
669           " COMPUTE_PGM_RSRC3_GFX90A:ACCUM_OFFSET: " +
670               getMCExprStr(MCKernelDescriptor::bits_get(
671                   CurrentProgramInfo.ComputePGMRSrc3GFX90A,
672                   amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET_SHIFT,
673                   amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET, Ctx)),
674           false);
675       OutStreamer->emitRawComment(
676           " COMPUTE_PGM_RSRC3_GFX90A:TG_SPLIT: " +
677               getMCExprStr(MCKernelDescriptor::bits_get(
678                   CurrentProgramInfo.ComputePGMRSrc3GFX90A,
679                   amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT_SHIFT,
680                   amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT, Ctx)),
681           false);
682     }
683   }
684 
685   if (DumpCodeInstEmitter) {
686 
687     OutStreamer->switchSection(
688         Context.getELFSection(".AMDGPU.disasm", ELF::SHT_PROGBITS, 0));
689 
690     for (size_t i = 0; i < DisasmLines.size(); ++i) {
691       std::string Comment = "\n";
692       if (!HexLines[i].empty()) {
693         Comment = std::string(DisasmLineMaxLen - DisasmLines[i].size(), ' ');
694         Comment += " ; " + HexLines[i] + "\n";
695       }
696 
697       OutStreamer->emitBytes(StringRef(DisasmLines[i]));
698       OutStreamer->emitBytes(StringRef(Comment));
699     }
700   }
701 
702   return false;
703 }
704 
705 // TODO: Fold this into emitFunctionBodyStart.
initializeTargetID(const Module & M)706 void AMDGPUAsmPrinter::initializeTargetID(const Module &M) {
707   // In the beginning all features are either 'Any' or 'NotSupported',
708   // depending on global target features. This will cover empty modules.
709   getTargetStreamer()->initializeTargetID(*getGlobalSTI(),
710                                           getGlobalSTI()->getFeatureString());
711 
712   // If module is empty, we are done.
713   if (M.empty())
714     return;
715 
716   // If module is not empty, need to find first 'Off' or 'On' feature
717   // setting per feature from functions in module.
718   for (auto &F : M) {
719     auto &TSTargetID = getTargetStreamer()->getTargetID();
720     if ((!TSTargetID->isXnackSupported() || TSTargetID->isXnackOnOrOff()) &&
721         (!TSTargetID->isSramEccSupported() || TSTargetID->isSramEccOnOrOff()))
722       break;
723 
724     const GCNSubtarget &STM = TM.getSubtarget<GCNSubtarget>(F);
725     const IsaInfo::AMDGPUTargetID &STMTargetID = STM.getTargetID();
726     if (TSTargetID->isXnackSupported())
727       if (TSTargetID->getXnackSetting() == IsaInfo::TargetIDSetting::Any)
728         TSTargetID->setXnackSetting(STMTargetID.getXnackSetting());
729     if (TSTargetID->isSramEccSupported())
730       if (TSTargetID->getSramEccSetting() == IsaInfo::TargetIDSetting::Any)
731         TSTargetID->setSramEccSetting(STMTargetID.getSramEccSetting());
732   }
733 }
734 
getFunctionCodeSize(const MachineFunction & MF) const735 uint64_t AMDGPUAsmPrinter::getFunctionCodeSize(const MachineFunction &MF) const {
736   const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
737   const SIInstrInfo *TII = STM.getInstrInfo();
738 
739   uint64_t CodeSize = 0;
740 
741   for (const MachineBasicBlock &MBB : MF) {
742     for (const MachineInstr &MI : MBB) {
743       // TODO: CodeSize should account for multiple functions.
744 
745       // TODO: Should we count size of debug info?
746       if (MI.isDebugInstr())
747         continue;
748 
749       CodeSize += TII->getInstSizeInBytes(MI);
750     }
751   }
752 
753   return CodeSize;
754 }
755 
getSIProgramInfo(SIProgramInfo & ProgInfo,const MachineFunction & MF)756 void AMDGPUAsmPrinter::getSIProgramInfo(SIProgramInfo &ProgInfo,
757                                         const MachineFunction &MF) {
758   const AMDGPUResourceUsageAnalysis::SIFunctionResourceInfo &Info =
759       ResourceUsage->getResourceInfo(&MF.getFunction());
760   const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
761   MCContext &Ctx = MF.getContext();
762 
763   auto CreateExpr = [&Ctx](int64_t Value) {
764     return MCConstantExpr::create(Value, Ctx);
765   };
766 
767   auto TryGetMCExprValue = [](const MCExpr *Value, uint64_t &Res) -> bool {
768     int64_t Val;
769     if (Value->evaluateAsAbsolute(Val)) {
770       Res = Val;
771       return true;
772     }
773     return false;
774   };
775 
776   ProgInfo.NumArchVGPR = CreateExpr(Info.NumVGPR);
777   ProgInfo.NumAccVGPR = CreateExpr(Info.NumAGPR);
778   ProgInfo.NumVGPR = CreateExpr(Info.getTotalNumVGPRs(STM));
779   ProgInfo.AccumOffset =
780       CreateExpr(alignTo(std::max(1, Info.NumVGPR), 4) / 4 - 1);
781   ProgInfo.TgSplit = STM.isTgSplitEnabled();
782   ProgInfo.NumSGPR = CreateExpr(Info.NumExplicitSGPR);
783   ProgInfo.ScratchSize = CreateExpr(Info.PrivateSegmentSize);
784   ProgInfo.VCCUsed = CreateExpr(Info.UsesVCC);
785   ProgInfo.FlatUsed = CreateExpr(Info.UsesFlatScratch);
786   ProgInfo.DynamicCallStack =
787       CreateExpr(Info.HasDynamicallySizedStack || Info.HasRecursion);
788 
789   const uint64_t MaxScratchPerWorkitem =
790       STM.getMaxWaveScratchSize() / STM.getWavefrontSize();
791   uint64_t ScratchSize;
792   if (TryGetMCExprValue(ProgInfo.ScratchSize, ScratchSize) &&
793       ScratchSize > MaxScratchPerWorkitem) {
794     DiagnosticInfoStackSize DiagStackSize(MF.getFunction(), ScratchSize,
795                                           MaxScratchPerWorkitem, DS_Error);
796     MF.getFunction().getContext().diagnose(DiagStackSize);
797   }
798 
799   const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
800 
801   // The calculations related to SGPR/VGPR blocks are
802   // duplicated in part in AMDGPUAsmParser::calculateGPRBlocks, and could be
803   // unified.
804   const MCExpr *ExtraSGPRs = AMDGPUMCExpr::createExtraSGPRs(
805       ProgInfo.VCCUsed, ProgInfo.FlatUsed,
806       getTargetStreamer()->getTargetID()->isXnackOnOrAny(), Ctx);
807 
808   // Check the addressable register limit before we add ExtraSGPRs.
809   if (STM.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS &&
810       !STM.hasSGPRInitBug()) {
811     unsigned MaxAddressableNumSGPRs = STM.getAddressableNumSGPRs();
812     uint64_t NumSgpr;
813     if (TryGetMCExprValue(ProgInfo.NumSGPR, NumSgpr) &&
814         NumSgpr > MaxAddressableNumSGPRs) {
815       // This can happen due to a compiler bug or when using inline asm.
816       LLVMContext &Ctx = MF.getFunction().getContext();
817       DiagnosticInfoResourceLimit Diag(
818           MF.getFunction(), "addressable scalar registers", NumSgpr,
819           MaxAddressableNumSGPRs, DS_Error, DK_ResourceLimit);
820       Ctx.diagnose(Diag);
821       ProgInfo.NumSGPR = CreateExpr(MaxAddressableNumSGPRs - 1);
822     }
823   }
824 
825   // Account for extra SGPRs and VGPRs reserved for debugger use.
826   ProgInfo.NumSGPR = MCBinaryExpr::createAdd(ProgInfo.NumSGPR, ExtraSGPRs, Ctx);
827 
828   const Function &F = MF.getFunction();
829 
830   // Ensure there are enough SGPRs and VGPRs for wave dispatch, where wave
831   // dispatch registers are function args.
832   unsigned WaveDispatchNumSGPR = 0, WaveDispatchNumVGPR = 0;
833 
834   if (isShader(F.getCallingConv())) {
835     bool IsPixelShader =
836         F.getCallingConv() == CallingConv::AMDGPU_PS && !STM.isAmdHsaOS();
837 
838     // Calculate the number of VGPR registers based on the SPI input registers
839     uint32_t InputEna = 0;
840     uint32_t InputAddr = 0;
841     unsigned LastEna = 0;
842 
843     if (IsPixelShader) {
844       // Note for IsPixelShader:
845       // By this stage, all enabled inputs are tagged in InputAddr as well.
846       // We will use InputAddr to determine whether the input counts against the
847       // vgpr total and only use the InputEnable to determine the last input
848       // that is relevant - if extra arguments are used, then we have to honour
849       // the InputAddr for any intermediate non-enabled inputs.
850       InputEna = MFI->getPSInputEnable();
851       InputAddr = MFI->getPSInputAddr();
852 
853       // We only need to consider input args up to the last used arg.
854       assert((InputEna || InputAddr) &&
855              "PSInputAddr and PSInputEnable should "
856              "never both be 0 for AMDGPU_PS shaders");
857       // There are some rare circumstances where InputAddr is non-zero and
858       // InputEna can be set to 0. In this case we default to setting LastEna
859       // to 1.
860       LastEna = InputEna ? llvm::Log2_32(InputEna) + 1 : 1;
861     }
862 
863     // FIXME: We should be using the number of registers determined during
864     // calling convention lowering to legalize the types.
865     const DataLayout &DL = F.getDataLayout();
866     unsigned PSArgCount = 0;
867     unsigned IntermediateVGPR = 0;
868     for (auto &Arg : F.args()) {
869       unsigned NumRegs = (DL.getTypeSizeInBits(Arg.getType()) + 31) / 32;
870       if (Arg.hasAttribute(Attribute::InReg)) {
871         WaveDispatchNumSGPR += NumRegs;
872       } else {
873         // If this is a PS shader and we're processing the PS Input args (first
874         // 16 VGPR), use the InputEna and InputAddr bits to define how many
875         // VGPRs are actually used.
876         // Any extra VGPR arguments are handled as normal arguments (and
877         // contribute to the VGPR count whether they're used or not).
878         if (IsPixelShader && PSArgCount < 16) {
879           if ((1 << PSArgCount) & InputAddr) {
880             if (PSArgCount < LastEna)
881               WaveDispatchNumVGPR += NumRegs;
882             else
883               IntermediateVGPR += NumRegs;
884           }
885           PSArgCount++;
886         } else {
887           // If there are extra arguments we have to include the allocation for
888           // the non-used (but enabled with InputAddr) input arguments
889           if (IntermediateVGPR) {
890             WaveDispatchNumVGPR += IntermediateVGPR;
891             IntermediateVGPR = 0;
892           }
893           WaveDispatchNumVGPR += NumRegs;
894         }
895       }
896     }
897     ProgInfo.NumSGPR = AMDGPUMCExpr::createMax(
898         {ProgInfo.NumSGPR, CreateExpr(WaveDispatchNumSGPR)}, Ctx);
899 
900     ProgInfo.NumArchVGPR = AMDGPUMCExpr::createMax(
901         {ProgInfo.NumVGPR, CreateExpr(WaveDispatchNumVGPR)}, Ctx);
902 
903     ProgInfo.NumVGPR = AMDGPUMCExpr::createTotalNumVGPR(
904         ProgInfo.NumAccVGPR, ProgInfo.NumArchVGPR, Ctx);
905   }
906 
907   // Adjust number of registers used to meet default/requested minimum/maximum
908   // number of waves per execution unit request.
909   unsigned MaxWaves = MFI->getMaxWavesPerEU();
910   ProgInfo.NumSGPRsForWavesPerEU =
911       AMDGPUMCExpr::createMax({ProgInfo.NumSGPR, CreateExpr(1ul),
912                                CreateExpr(STM.getMinNumSGPRs(MaxWaves))},
913                               Ctx);
914   ProgInfo.NumVGPRsForWavesPerEU =
915       AMDGPUMCExpr::createMax({ProgInfo.NumVGPR, CreateExpr(1ul),
916                                CreateExpr(STM.getMinNumVGPRs(MaxWaves))},
917                               Ctx);
918 
919   if (STM.getGeneration() <= AMDGPUSubtarget::SEA_ISLANDS ||
920       STM.hasSGPRInitBug()) {
921     unsigned MaxAddressableNumSGPRs = STM.getAddressableNumSGPRs();
922     uint64_t NumSgpr;
923     if (TryGetMCExprValue(ProgInfo.NumSGPR, NumSgpr) &&
924         NumSgpr > MaxAddressableNumSGPRs) {
925       // This can happen due to a compiler bug or when using inline asm to use
926       // the registers which are usually reserved for vcc etc.
927       LLVMContext &Ctx = MF.getFunction().getContext();
928       DiagnosticInfoResourceLimit Diag(MF.getFunction(), "scalar registers",
929                                        NumSgpr, MaxAddressableNumSGPRs,
930                                        DS_Error, DK_ResourceLimit);
931       Ctx.diagnose(Diag);
932       ProgInfo.NumSGPR = CreateExpr(MaxAddressableNumSGPRs);
933       ProgInfo.NumSGPRsForWavesPerEU = CreateExpr(MaxAddressableNumSGPRs);
934     }
935   }
936 
937   if (STM.hasSGPRInitBug()) {
938     ProgInfo.NumSGPR =
939         CreateExpr(AMDGPU::IsaInfo::FIXED_NUM_SGPRS_FOR_INIT_BUG);
940     ProgInfo.NumSGPRsForWavesPerEU =
941         CreateExpr(AMDGPU::IsaInfo::FIXED_NUM_SGPRS_FOR_INIT_BUG);
942   }
943 
944   if (MFI->getNumUserSGPRs() > STM.getMaxNumUserSGPRs()) {
945     LLVMContext &Ctx = MF.getFunction().getContext();
946     DiagnosticInfoResourceLimit Diag(MF.getFunction(), "user SGPRs",
947                                      MFI->getNumUserSGPRs(),
948                                      STM.getMaxNumUserSGPRs(), DS_Error);
949     Ctx.diagnose(Diag);
950   }
951 
952   if (MFI->getLDSSize() >
953       static_cast<unsigned>(STM.getAddressableLocalMemorySize())) {
954     LLVMContext &Ctx = MF.getFunction().getContext();
955     DiagnosticInfoResourceLimit Diag(
956         MF.getFunction(), "local memory", MFI->getLDSSize(),
957         STM.getAddressableLocalMemorySize(), DS_Error);
958     Ctx.diagnose(Diag);
959   }
960   // The MCExpr equivalent of getNumSGPRBlocks/getNumVGPRBlocks:
961   // (alignTo(max(1u, NumGPR), GPREncodingGranule) / GPREncodingGranule) - 1
962   auto GetNumGPRBlocks = [&CreateExpr, &Ctx](const MCExpr *NumGPR,
963                                              unsigned Granule) {
964     const MCExpr *OneConst = CreateExpr(1ul);
965     const MCExpr *GranuleConst = CreateExpr(Granule);
966     const MCExpr *MaxNumGPR = AMDGPUMCExpr::createMax({NumGPR, OneConst}, Ctx);
967     const MCExpr *AlignToGPR =
968         AMDGPUMCExpr::createAlignTo(MaxNumGPR, GranuleConst, Ctx);
969     const MCExpr *DivGPR =
970         MCBinaryExpr::createDiv(AlignToGPR, GranuleConst, Ctx);
971     const MCExpr *SubGPR = MCBinaryExpr::createSub(DivGPR, OneConst, Ctx);
972     return SubGPR;
973   };
974 
975   ProgInfo.SGPRBlocks = GetNumGPRBlocks(ProgInfo.NumSGPRsForWavesPerEU,
976                                         IsaInfo::getSGPREncodingGranule(&STM));
977   ProgInfo.VGPRBlocks = GetNumGPRBlocks(ProgInfo.NumVGPRsForWavesPerEU,
978                                         IsaInfo::getVGPREncodingGranule(&STM));
979 
980   const SIModeRegisterDefaults Mode = MFI->getMode();
981 
982   // Set the value to initialize FP_ROUND and FP_DENORM parts of the mode
983   // register.
984   ProgInfo.FloatMode = getFPMode(Mode);
985 
986   ProgInfo.IEEEMode = Mode.IEEE;
987 
988   // Make clamp modifier on NaN input returns 0.
989   ProgInfo.DX10Clamp = Mode.DX10Clamp;
990 
991   unsigned LDSAlignShift;
992   if (STM.getGeneration() < AMDGPUSubtarget::SEA_ISLANDS) {
993     // LDS is allocated in 64 dword blocks.
994     LDSAlignShift = 8;
995   } else {
996     // LDS is allocated in 128 dword blocks.
997     LDSAlignShift = 9;
998   }
999 
1000   ProgInfo.SGPRSpill = MFI->getNumSpilledSGPRs();
1001   ProgInfo.VGPRSpill = MFI->getNumSpilledVGPRs();
1002 
1003   ProgInfo.LDSSize = MFI->getLDSSize();
1004   ProgInfo.LDSBlocks =
1005       alignTo(ProgInfo.LDSSize, 1ULL << LDSAlignShift) >> LDSAlignShift;
1006 
1007   // The MCExpr equivalent of divideCeil.
1008   auto DivideCeil = [&Ctx](const MCExpr *Numerator, const MCExpr *Denominator) {
1009     const MCExpr *Ceil =
1010         AMDGPUMCExpr::createAlignTo(Numerator, Denominator, Ctx);
1011     return MCBinaryExpr::createDiv(Ceil, Denominator, Ctx);
1012   };
1013 
1014   // Scratch is allocated in 64-dword or 256-dword blocks.
1015   unsigned ScratchAlignShift =
1016       STM.getGeneration() >= AMDGPUSubtarget::GFX11 ? 8 : 10;
1017   // We need to program the hardware with the amount of scratch memory that
1018   // is used by the entire wave.  ProgInfo.ScratchSize is the amount of
1019   // scratch memory used per thread.
1020   ProgInfo.ScratchBlocks = DivideCeil(
1021       MCBinaryExpr::createMul(ProgInfo.ScratchSize,
1022                               CreateExpr(STM.getWavefrontSize()), Ctx),
1023       CreateExpr(1ULL << ScratchAlignShift));
1024 
1025   if (getIsaVersion(getGlobalSTI()->getCPU()).Major >= 10) {
1026     ProgInfo.WgpMode = STM.isCuModeEnabled() ? 0 : 1;
1027     ProgInfo.MemOrdered = 1;
1028   }
1029 
1030   // 0 = X, 1 = XY, 2 = XYZ
1031   unsigned TIDIGCompCnt = 0;
1032   if (MFI->hasWorkItemIDZ())
1033     TIDIGCompCnt = 2;
1034   else if (MFI->hasWorkItemIDY())
1035     TIDIGCompCnt = 1;
1036 
1037   // The private segment wave byte offset is the last of the system SGPRs. We
1038   // initially assumed it was allocated, and may have used it. It shouldn't harm
1039   // anything to disable it if we know the stack isn't used here. We may still
1040   // have emitted code reading it to initialize scratch, but if that's unused
1041   // reading garbage should be OK.
1042   ProgInfo.ScratchEnable = MCBinaryExpr::createLOr(
1043       MCBinaryExpr::createGT(ProgInfo.ScratchBlocks,
1044                              MCConstantExpr::create(0, Ctx), Ctx),
1045       ProgInfo.DynamicCallStack, Ctx);
1046 
1047   ProgInfo.UserSGPR = MFI->getNumUserSGPRs();
1048   // For AMDHSA, TRAP_HANDLER must be zero, as it is populated by the CP.
1049   ProgInfo.TrapHandlerEnable =
1050       STM.isAmdHsaOS() ? 0 : STM.isTrapHandlerEnabled();
1051   ProgInfo.TGIdXEnable = MFI->hasWorkGroupIDX();
1052   ProgInfo.TGIdYEnable = MFI->hasWorkGroupIDY();
1053   ProgInfo.TGIdZEnable = MFI->hasWorkGroupIDZ();
1054   ProgInfo.TGSizeEnable = MFI->hasWorkGroupInfo();
1055   ProgInfo.TIdIGCompCount = TIDIGCompCnt;
1056   ProgInfo.EXCPEnMSB = 0;
1057   // For AMDHSA, LDS_SIZE must be zero, as it is populated by the CP.
1058   ProgInfo.LdsSize = STM.isAmdHsaOS() ? 0 : ProgInfo.LDSBlocks;
1059   ProgInfo.EXCPEnable = 0;
1060 
1061   if (STM.hasGFX90AInsts()) {
1062     // return ((Dst & ~Mask) | (Value << Shift))
1063     auto SetBits = [&Ctx](const MCExpr *Dst, const MCExpr *Value, uint32_t Mask,
1064                           uint32_t Shift) {
1065       auto Shft = MCConstantExpr::create(Shift, Ctx);
1066       auto Msk = MCConstantExpr::create(Mask, Ctx);
1067       Dst = MCBinaryExpr::createAnd(Dst, MCUnaryExpr::createNot(Msk, Ctx), Ctx);
1068       Dst = MCBinaryExpr::createOr(
1069           Dst, MCBinaryExpr::createShl(Value, Shft, Ctx), Ctx);
1070       return Dst;
1071     };
1072 
1073     ProgInfo.ComputePGMRSrc3GFX90A =
1074         SetBits(ProgInfo.ComputePGMRSrc3GFX90A, ProgInfo.AccumOffset,
1075                 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET,
1076                 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET_SHIFT);
1077     ProgInfo.ComputePGMRSrc3GFX90A =
1078         SetBits(ProgInfo.ComputePGMRSrc3GFX90A, CreateExpr(ProgInfo.TgSplit),
1079                 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT,
1080                 amdhsa::COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT_SHIFT);
1081   }
1082 
1083   ProgInfo.Occupancy = AMDGPUMCExpr::createOccupancy(
1084       STM.computeOccupancy(F, ProgInfo.LDSSize), ProgInfo.NumSGPRsForWavesPerEU,
1085       ProgInfo.NumVGPRsForWavesPerEU, STM, Ctx);
1086 
1087   const auto [MinWEU, MaxWEU] =
1088       AMDGPU::getIntegerPairAttribute(F, "amdgpu-waves-per-eu", {0, 0}, true);
1089   uint64_t Occupancy;
1090   if (TryGetMCExprValue(ProgInfo.Occupancy, Occupancy) && Occupancy < MinWEU) {
1091     DiagnosticInfoOptimizationFailure Diag(
1092         F, F.getSubprogram(),
1093         "failed to meet occupancy target given by 'amdgpu-waves-per-eu' in "
1094         "'" +
1095             F.getName() + "': desired occupancy was " + Twine(MinWEU) +
1096             ", final occupancy is " + Twine(Occupancy));
1097     F.getContext().diagnose(Diag);
1098   }
1099 }
1100 
getRsrcReg(CallingConv::ID CallConv)1101 static unsigned getRsrcReg(CallingConv::ID CallConv) {
1102   switch (CallConv) {
1103   default: [[fallthrough]];
1104   case CallingConv::AMDGPU_CS: return R_00B848_COMPUTE_PGM_RSRC1;
1105   case CallingConv::AMDGPU_LS: return R_00B528_SPI_SHADER_PGM_RSRC1_LS;
1106   case CallingConv::AMDGPU_HS: return R_00B428_SPI_SHADER_PGM_RSRC1_HS;
1107   case CallingConv::AMDGPU_ES: return R_00B328_SPI_SHADER_PGM_RSRC1_ES;
1108   case CallingConv::AMDGPU_GS: return R_00B228_SPI_SHADER_PGM_RSRC1_GS;
1109   case CallingConv::AMDGPU_VS: return R_00B128_SPI_SHADER_PGM_RSRC1_VS;
1110   case CallingConv::AMDGPU_PS: return R_00B028_SPI_SHADER_PGM_RSRC1_PS;
1111   }
1112 }
1113 
EmitProgramInfoSI(const MachineFunction & MF,const SIProgramInfo & CurrentProgramInfo)1114 void AMDGPUAsmPrinter::EmitProgramInfoSI(const MachineFunction &MF,
1115                                          const SIProgramInfo &CurrentProgramInfo) {
1116   const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1117   const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
1118   unsigned RsrcReg = getRsrcReg(MF.getFunction().getCallingConv());
1119   MCContext &Ctx = MF.getContext();
1120 
1121   // (((Value) & Mask) << Shift)
1122   auto SetBits = [&Ctx](const MCExpr *Value, uint32_t Mask, uint32_t Shift) {
1123     const MCExpr *msk = MCConstantExpr::create(Mask, Ctx);
1124     const MCExpr *shft = MCConstantExpr::create(Shift, Ctx);
1125     return MCBinaryExpr::createShl(MCBinaryExpr::createAnd(Value, msk, Ctx),
1126                                    shft, Ctx);
1127   };
1128 
1129   auto EmitResolvedOrExpr = [this](const MCExpr *Value, unsigned Size) {
1130     int64_t Val;
1131     if (Value->evaluateAsAbsolute(Val))
1132       OutStreamer->emitIntValue(static_cast<uint64_t>(Val), Size);
1133     else
1134       OutStreamer->emitValue(Value, Size);
1135   };
1136 
1137   if (AMDGPU::isCompute(MF.getFunction().getCallingConv())) {
1138     OutStreamer->emitInt32(R_00B848_COMPUTE_PGM_RSRC1);
1139 
1140     EmitResolvedOrExpr(CurrentProgramInfo.getComputePGMRSrc1(STM, Ctx),
1141                        /*Size=*/4);
1142 
1143     OutStreamer->emitInt32(R_00B84C_COMPUTE_PGM_RSRC2);
1144     EmitResolvedOrExpr(CurrentProgramInfo.getComputePGMRSrc2(Ctx), /*Size=*/4);
1145 
1146     OutStreamer->emitInt32(R_00B860_COMPUTE_TMPRING_SIZE);
1147 
1148     // Sets bits according to S_0286E8_WAVESIZE_* mask and shift values for the
1149     // appropriate generation.
1150     if (STM.getGeneration() >= AMDGPUSubtarget::GFX12) {
1151       EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
1152                                  /*Mask=*/0x3FFFF, /*Shift=*/12),
1153                          /*Size=*/4);
1154     } else if (STM.getGeneration() == AMDGPUSubtarget::GFX11) {
1155       EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
1156                                  /*Mask=*/0x7FFF, /*Shift=*/12),
1157                          /*Size=*/4);
1158     } else {
1159       EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
1160                                  /*Mask=*/0x1FFF, /*Shift=*/12),
1161                          /*Size=*/4);
1162     }
1163 
1164     // TODO: Should probably note flat usage somewhere. SC emits a "FlatPtr32 =
1165     // 0" comment but I don't see a corresponding field in the register spec.
1166   } else {
1167     OutStreamer->emitInt32(RsrcReg);
1168 
1169     const MCExpr *GPRBlocks = MCBinaryExpr::createOr(
1170         SetBits(CurrentProgramInfo.VGPRBlocks, /*Mask=*/0x3F, /*Shift=*/0),
1171         SetBits(CurrentProgramInfo.SGPRBlocks, /*Mask=*/0x0F, /*Shift=*/6),
1172         MF.getContext());
1173     EmitResolvedOrExpr(GPRBlocks, /*Size=*/4);
1174     OutStreamer->emitInt32(R_0286E8_SPI_TMPRING_SIZE);
1175 
1176     // Sets bits according to S_0286E8_WAVESIZE_* mask and shift values for the
1177     // appropriate generation.
1178     if (STM.getGeneration() >= AMDGPUSubtarget::GFX12) {
1179       EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
1180                                  /*Mask=*/0x3FFFF, /*Shift=*/12),
1181                          /*Size=*/4);
1182     } else if (STM.getGeneration() == AMDGPUSubtarget::GFX11) {
1183       EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
1184                                  /*Mask=*/0x7FFF, /*Shift=*/12),
1185                          /*Size=*/4);
1186     } else {
1187       EmitResolvedOrExpr(SetBits(CurrentProgramInfo.ScratchBlocks,
1188                                  /*Mask=*/0x1FFF, /*Shift=*/12),
1189                          /*Size=*/4);
1190     }
1191   }
1192 
1193   if (MF.getFunction().getCallingConv() == CallingConv::AMDGPU_PS) {
1194     OutStreamer->emitInt32(R_00B02C_SPI_SHADER_PGM_RSRC2_PS);
1195     unsigned ExtraLDSSize = STM.getGeneration() >= AMDGPUSubtarget::GFX11
1196                                 ? divideCeil(CurrentProgramInfo.LDSBlocks, 2)
1197                                 : CurrentProgramInfo.LDSBlocks;
1198     OutStreamer->emitInt32(S_00B02C_EXTRA_LDS_SIZE(ExtraLDSSize));
1199     OutStreamer->emitInt32(R_0286CC_SPI_PS_INPUT_ENA);
1200     OutStreamer->emitInt32(MFI->getPSInputEnable());
1201     OutStreamer->emitInt32(R_0286D0_SPI_PS_INPUT_ADDR);
1202     OutStreamer->emitInt32(MFI->getPSInputAddr());
1203   }
1204 
1205   OutStreamer->emitInt32(R_SPILLED_SGPRS);
1206   OutStreamer->emitInt32(MFI->getNumSpilledSGPRs());
1207   OutStreamer->emitInt32(R_SPILLED_VGPRS);
1208   OutStreamer->emitInt32(MFI->getNumSpilledVGPRs());
1209 }
1210 
1211 // Helper function to add common PAL Metadata 3.0+
EmitPALMetadataCommon(AMDGPUPALMetadata * MD,const SIProgramInfo & CurrentProgramInfo,CallingConv::ID CC,const GCNSubtarget & ST)1212 static void EmitPALMetadataCommon(AMDGPUPALMetadata *MD,
1213                                   const SIProgramInfo &CurrentProgramInfo,
1214                                   CallingConv::ID CC, const GCNSubtarget &ST) {
1215   if (ST.hasIEEEMode())
1216     MD->setHwStage(CC, ".ieee_mode", (bool)CurrentProgramInfo.IEEEMode);
1217 
1218   MD->setHwStage(CC, ".wgp_mode", (bool)CurrentProgramInfo.WgpMode);
1219   MD->setHwStage(CC, ".mem_ordered", (bool)CurrentProgramInfo.MemOrdered);
1220 
1221   if (AMDGPU::isCompute(CC)) {
1222     MD->setHwStage(CC, ".trap_present",
1223                    (bool)CurrentProgramInfo.TrapHandlerEnable);
1224     MD->setHwStage(CC, ".excp_en", CurrentProgramInfo.EXCPEnable);
1225   }
1226 
1227   MD->setHwStage(CC, ".lds_size",
1228                  (unsigned)(CurrentProgramInfo.LdsSize *
1229                             getLdsDwGranularity(ST) * sizeof(uint32_t)));
1230 }
1231 
1232 // This is the equivalent of EmitProgramInfoSI above, but for when the OS type
1233 // is AMDPAL.  It stores each compute/SPI register setting and other PAL
1234 // metadata items into the PALMD::Metadata, combining with any provided by the
1235 // frontend as LLVM metadata. Once all functions are written, the PAL metadata
1236 // is then written as a single block in the .note section.
EmitPALMetadata(const MachineFunction & MF,const SIProgramInfo & CurrentProgramInfo)1237 void AMDGPUAsmPrinter::EmitPALMetadata(const MachineFunction &MF,
1238        const SIProgramInfo &CurrentProgramInfo) {
1239   const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1240   auto CC = MF.getFunction().getCallingConv();
1241   auto MD = getTargetStreamer()->getPALMetadata();
1242   auto &Ctx = MF.getContext();
1243 
1244   MD->setEntryPoint(CC, MF.getFunction().getName());
1245   MD->setNumUsedVgprs(CC, CurrentProgramInfo.NumVGPRsForWavesPerEU, Ctx);
1246 
1247   // Only set AGPRs for supported devices
1248   const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
1249   if (STM.hasMAIInsts()) {
1250     MD->setNumUsedAgprs(CC, CurrentProgramInfo.NumAccVGPR);
1251   }
1252 
1253   MD->setNumUsedSgprs(CC, CurrentProgramInfo.NumSGPRsForWavesPerEU, Ctx);
1254   if (MD->getPALMajorVersion() < 3) {
1255     MD->setRsrc1(CC, CurrentProgramInfo.getPGMRSrc1(CC, STM, Ctx), Ctx);
1256     if (AMDGPU::isCompute(CC)) {
1257       MD->setRsrc2(CC, CurrentProgramInfo.getComputePGMRSrc2(Ctx), Ctx);
1258     } else {
1259       const MCExpr *HasScratchBlocks =
1260           MCBinaryExpr::createGT(CurrentProgramInfo.ScratchBlocks,
1261                                  MCConstantExpr::create(0, Ctx), Ctx);
1262       auto [Shift, Mask] = getShiftMask(C_00B84C_SCRATCH_EN);
1263       MD->setRsrc2(CC, maskShiftSet(HasScratchBlocks, Mask, Shift, Ctx), Ctx);
1264     }
1265   } else {
1266     MD->setHwStage(CC, ".debug_mode", (bool)CurrentProgramInfo.DebugMode);
1267     MD->setHwStage(CC, ".scratch_en", msgpack::Type::Boolean,
1268                    CurrentProgramInfo.ScratchEnable);
1269     EmitPALMetadataCommon(MD, CurrentProgramInfo, CC, STM);
1270   }
1271 
1272   // ScratchSize is in bytes, 16 aligned.
1273   MD->setScratchSize(
1274       CC,
1275       AMDGPUMCExpr::createAlignTo(CurrentProgramInfo.ScratchSize,
1276                                   MCConstantExpr::create(16, Ctx), Ctx),
1277       Ctx);
1278 
1279   if (MF.getFunction().getCallingConv() == CallingConv::AMDGPU_PS) {
1280     unsigned ExtraLDSSize = STM.getGeneration() >= AMDGPUSubtarget::GFX11
1281                                 ? divideCeil(CurrentProgramInfo.LDSBlocks, 2)
1282                                 : CurrentProgramInfo.LDSBlocks;
1283     if (MD->getPALMajorVersion() < 3) {
1284       MD->setRsrc2(
1285           CC,
1286           MCConstantExpr::create(S_00B02C_EXTRA_LDS_SIZE(ExtraLDSSize), Ctx),
1287           Ctx);
1288       MD->setSpiPsInputEna(MFI->getPSInputEnable());
1289       MD->setSpiPsInputAddr(MFI->getPSInputAddr());
1290     } else {
1291       // Graphics registers
1292       const unsigned ExtraLdsDwGranularity =
1293           STM.getGeneration() >= AMDGPUSubtarget::GFX11 ? 256 : 128;
1294       MD->setGraphicsRegisters(
1295           ".ps_extra_lds_size",
1296           (unsigned)(ExtraLDSSize * ExtraLdsDwGranularity * sizeof(uint32_t)));
1297 
1298       // Set PsInputEna and PsInputAddr .spi_ps_input_ena and .spi_ps_input_addr
1299       static StringLiteral const PsInputFields[] = {
1300           ".persp_sample_ena",    ".persp_center_ena",
1301           ".persp_centroid_ena",  ".persp_pull_model_ena",
1302           ".linear_sample_ena",   ".linear_center_ena",
1303           ".linear_centroid_ena", ".line_stipple_tex_ena",
1304           ".pos_x_float_ena",     ".pos_y_float_ena",
1305           ".pos_z_float_ena",     ".pos_w_float_ena",
1306           ".front_face_ena",      ".ancillary_ena",
1307           ".sample_coverage_ena", ".pos_fixed_pt_ena"};
1308       unsigned PSInputEna = MFI->getPSInputEnable();
1309       unsigned PSInputAddr = MFI->getPSInputAddr();
1310       for (auto [Idx, Field] : enumerate(PsInputFields)) {
1311         MD->setGraphicsRegisters(".spi_ps_input_ena", Field,
1312                                  (bool)((PSInputEna >> Idx) & 1));
1313         MD->setGraphicsRegisters(".spi_ps_input_addr", Field,
1314                                  (bool)((PSInputAddr >> Idx) & 1));
1315       }
1316     }
1317   }
1318 
1319   // For version 3 and above the wave front size is already set in the metadata
1320   if (MD->getPALMajorVersion() < 3 && STM.isWave32())
1321     MD->setWave32(MF.getFunction().getCallingConv());
1322 }
1323 
emitPALFunctionMetadata(const MachineFunction & MF)1324 void AMDGPUAsmPrinter::emitPALFunctionMetadata(const MachineFunction &MF) {
1325   auto *MD = getTargetStreamer()->getPALMetadata();
1326   const MachineFrameInfo &MFI = MF.getFrameInfo();
1327   StringRef FnName = MF.getFunction().getName();
1328   MD->setFunctionScratchSize(FnName, MFI.getStackSize());
1329   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
1330   MCContext &Ctx = MF.getContext();
1331 
1332   if (MD->getPALMajorVersion() < 3) {
1333     // Set compute registers
1334     MD->setRsrc1(
1335         CallingConv::AMDGPU_CS,
1336         CurrentProgramInfo.getPGMRSrc1(CallingConv::AMDGPU_CS, ST, Ctx), Ctx);
1337     MD->setRsrc2(CallingConv::AMDGPU_CS,
1338                  CurrentProgramInfo.getComputePGMRSrc2(Ctx), Ctx);
1339   } else {
1340     EmitPALMetadataCommon(MD, CurrentProgramInfo, CallingConv::AMDGPU_CS, ST);
1341   }
1342 
1343   // Set optional info
1344   MD->setFunctionLdsSize(FnName, CurrentProgramInfo.LDSSize);
1345   MD->setFunctionNumUsedVgprs(FnName, CurrentProgramInfo.NumVGPRsForWavesPerEU);
1346   MD->setFunctionNumUsedSgprs(FnName, CurrentProgramInfo.NumSGPRsForWavesPerEU);
1347 }
1348 
1349 // This is supposed to be log2(Size)
getElementByteSizeValue(unsigned Size)1350 static amd_element_byte_size_t getElementByteSizeValue(unsigned Size) {
1351   switch (Size) {
1352   case 4:
1353     return AMD_ELEMENT_4_BYTES;
1354   case 8:
1355     return AMD_ELEMENT_8_BYTES;
1356   case 16:
1357     return AMD_ELEMENT_16_BYTES;
1358   default:
1359     llvm_unreachable("invalid private_element_size");
1360   }
1361 }
1362 
getAmdKernelCode(AMDGPUMCKernelCodeT & Out,const SIProgramInfo & CurrentProgramInfo,const MachineFunction & MF) const1363 void AMDGPUAsmPrinter::getAmdKernelCode(AMDGPUMCKernelCodeT &Out,
1364                                         const SIProgramInfo &CurrentProgramInfo,
1365                                         const MachineFunction &MF) const {
1366   const Function &F = MF.getFunction();
1367   assert(F.getCallingConv() == CallingConv::AMDGPU_KERNEL ||
1368          F.getCallingConv() == CallingConv::SPIR_KERNEL);
1369 
1370   const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1371   const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
1372   MCContext &Ctx = MF.getContext();
1373 
1374   Out.initDefault(&STM, Ctx, /*InitMCExpr=*/false);
1375 
1376   Out.compute_pgm_resource1_registers =
1377       CurrentProgramInfo.getComputePGMRSrc1(STM, Ctx);
1378   Out.compute_pgm_resource2_registers =
1379       CurrentProgramInfo.getComputePGMRSrc2(Ctx);
1380   Out.code_properties |= AMD_CODE_PROPERTY_IS_PTR64;
1381 
1382   Out.is_dynamic_callstack = CurrentProgramInfo.DynamicCallStack;
1383 
1384   AMD_HSA_BITS_SET(Out.code_properties, AMD_CODE_PROPERTY_PRIVATE_ELEMENT_SIZE,
1385                    getElementByteSizeValue(STM.getMaxPrivateElementSize(true)));
1386 
1387   const GCNUserSGPRUsageInfo &UserSGPRInfo = MFI->getUserSGPRInfo();
1388   if (UserSGPRInfo.hasPrivateSegmentBuffer()) {
1389     Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER;
1390   }
1391 
1392   if (UserSGPRInfo.hasDispatchPtr())
1393     Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR;
1394 
1395   if (UserSGPRInfo.hasQueuePtr() && CodeObjectVersion < AMDGPU::AMDHSA_COV5)
1396     Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR;
1397 
1398   if (UserSGPRInfo.hasKernargSegmentPtr())
1399     Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR;
1400 
1401   if (UserSGPRInfo.hasDispatchID())
1402     Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID;
1403 
1404   if (UserSGPRInfo.hasFlatScratchInit())
1405     Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT;
1406 
1407   if (UserSGPRInfo.hasPrivateSegmentSize())
1408     Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE;
1409 
1410   if (UserSGPRInfo.hasDispatchPtr())
1411     Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR;
1412 
1413   if (STM.isXNACKEnabled())
1414     Out.code_properties |= AMD_CODE_PROPERTY_IS_XNACK_SUPPORTED;
1415 
1416   Align MaxKernArgAlign;
1417   Out.kernarg_segment_byte_size = STM.getKernArgSegmentSize(F, MaxKernArgAlign);
1418   Out.wavefront_sgpr_count = CurrentProgramInfo.NumSGPR;
1419   Out.workitem_vgpr_count = CurrentProgramInfo.NumVGPR;
1420   Out.workitem_private_segment_byte_size = CurrentProgramInfo.ScratchSize;
1421   Out.workgroup_group_segment_byte_size = CurrentProgramInfo.LDSSize;
1422 
1423   // kernarg_segment_alignment is specified as log of the alignment.
1424   // The minimum alignment is 16.
1425   // FIXME: The metadata treats the minimum as 4?
1426   Out.kernarg_segment_alignment = Log2(std::max(Align(16), MaxKernArgAlign));
1427 }
1428 
PrintAsmOperand(const MachineInstr * MI,unsigned OpNo,const char * ExtraCode,raw_ostream & O)1429 bool AMDGPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
1430                                        const char *ExtraCode, raw_ostream &O) {
1431   // First try the generic code, which knows about modifiers like 'c' and 'n'.
1432   if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O))
1433     return false;
1434 
1435   if (ExtraCode && ExtraCode[0]) {
1436     if (ExtraCode[1] != 0)
1437       return true; // Unknown modifier.
1438 
1439     switch (ExtraCode[0]) {
1440     case 'r':
1441       break;
1442     default:
1443       return true;
1444     }
1445   }
1446 
1447   // TODO: Should be able to support other operand types like globals.
1448   const MachineOperand &MO = MI->getOperand(OpNo);
1449   if (MO.isReg()) {
1450     AMDGPUInstPrinter::printRegOperand(MO.getReg(), O,
1451                                        *MF->getSubtarget().getRegisterInfo());
1452     return false;
1453   }
1454   if (MO.isImm()) {
1455     int64_t Val = MO.getImm();
1456     if (AMDGPU::isInlinableIntLiteral(Val)) {
1457       O << Val;
1458     } else if (isUInt<16>(Val)) {
1459       O << format("0x%" PRIx16, static_cast<uint16_t>(Val));
1460     } else if (isUInt<32>(Val)) {
1461       O << format("0x%" PRIx32, static_cast<uint32_t>(Val));
1462     } else {
1463       O << format("0x%" PRIx64, static_cast<uint64_t>(Val));
1464     }
1465     return false;
1466   }
1467   return true;
1468 }
1469 
getAnalysisUsage(AnalysisUsage & AU) const1470 void AMDGPUAsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
1471   AU.addRequired<AMDGPUResourceUsageAnalysis>();
1472   AU.addPreserved<AMDGPUResourceUsageAnalysis>();
1473   AsmPrinter::getAnalysisUsage(AU);
1474 }
1475 
emitResourceUsageRemarks(const MachineFunction & MF,const SIProgramInfo & CurrentProgramInfo,bool isModuleEntryFunction,bool hasMAIInsts)1476 void AMDGPUAsmPrinter::emitResourceUsageRemarks(
1477     const MachineFunction &MF, const SIProgramInfo &CurrentProgramInfo,
1478     bool isModuleEntryFunction, bool hasMAIInsts) {
1479   if (!ORE)
1480     return;
1481 
1482   const char *Name = "kernel-resource-usage";
1483   const char *Indent = "    ";
1484 
1485   // If the remark is not specifically enabled, do not output to yaml
1486   LLVMContext &Ctx = MF.getFunction().getContext();
1487   if (!Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(Name))
1488     return;
1489 
1490   // Currently non-kernel functions have no resources to emit.
1491   if (!isEntryFunctionCC(MF.getFunction().getCallingConv()))
1492     return;
1493 
1494   auto EmitResourceUsageRemark = [&](StringRef RemarkName,
1495                                      StringRef RemarkLabel, auto Argument) {
1496     // Add an indent for every line besides the line with the kernel name. This
1497     // makes it easier to tell which resource usage go with which kernel since
1498     // the kernel name will always be displayed first.
1499     std::string LabelStr = RemarkLabel.str() + ": ";
1500     if (RemarkName != "FunctionName")
1501       LabelStr = Indent + LabelStr;
1502 
1503     ORE->emit([&]() {
1504       return MachineOptimizationRemarkAnalysis(Name, RemarkName,
1505                                                MF.getFunction().getSubprogram(),
1506                                                &MF.front())
1507              << LabelStr << ore::NV(RemarkName, Argument);
1508     });
1509   };
1510 
1511   // FIXME: Formatting here is pretty nasty because clang does not accept
1512   // newlines from diagnostics. This forces us to emit multiple diagnostic
1513   // remarks to simulate newlines. If and when clang does accept newlines, this
1514   // formatting should be aggregated into one remark with newlines to avoid
1515   // printing multiple diagnostic location and diag opts.
1516   EmitResourceUsageRemark("FunctionName", "Function Name",
1517                           MF.getFunction().getName());
1518   EmitResourceUsageRemark("NumSGPR", "SGPRs",
1519                           getMCExprStr(CurrentProgramInfo.NumSGPR));
1520   EmitResourceUsageRemark("NumVGPR", "VGPRs",
1521                           getMCExprStr(CurrentProgramInfo.NumArchVGPR));
1522   if (hasMAIInsts) {
1523     EmitResourceUsageRemark("NumAGPR", "AGPRs",
1524                             getMCExprStr(CurrentProgramInfo.NumAccVGPR));
1525   }
1526   EmitResourceUsageRemark("ScratchSize", "ScratchSize [bytes/lane]",
1527                           getMCExprStr(CurrentProgramInfo.ScratchSize));
1528   int64_t DynStack;
1529   bool DynStackEvaluatable =
1530       CurrentProgramInfo.DynamicCallStack->evaluateAsAbsolute(DynStack);
1531   StringRef DynamicStackStr =
1532       DynStackEvaluatable && DynStack ? "True" : "False";
1533   EmitResourceUsageRemark("DynamicStack", "Dynamic Stack", DynamicStackStr);
1534   EmitResourceUsageRemark("Occupancy", "Occupancy [waves/SIMD]",
1535                           getMCExprStr(CurrentProgramInfo.Occupancy));
1536   EmitResourceUsageRemark("SGPRSpill", "SGPRs Spill",
1537                           CurrentProgramInfo.SGPRSpill);
1538   EmitResourceUsageRemark("VGPRSpill", "VGPRs Spill",
1539                           CurrentProgramInfo.VGPRSpill);
1540   if (isModuleEntryFunction)
1541     EmitResourceUsageRemark("BytesLDS", "LDS Size [bytes/block]",
1542                             CurrentProgramInfo.LDSSize);
1543 }
1544