1 //===-- AMDGPUAsmPrinter.cpp - AMDGPU assembly printer -------------------===//
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
7 //===----------------------------------------------------------------------===//
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.
15 //===----------------------------------------------------------------------===//
18 #include "AMDGPUAsmPrinter.h"
20 #include "AMDGPUSubtarget.h"
21 #include "AMDGPUTargetMachine.h"
22 #include "MCTargetDesc/AMDGPUInstPrinter.h"
23 #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
24 #include "MCTargetDesc/AMDGPUTargetStreamer.h"
25 #include "R600AsmPrinter.h"
26 #include "R600Defines.h"
27 #include "R600MachineFunctionInfo.h"
28 #include "R600RegisterInfo.h"
29 #include "SIDefines.h"
30 #include "SIInstrInfo.h"
31 #include "SIMachineFunctionInfo.h"
32 #include "SIRegisterInfo.h"
33 #include "TargetInfo/AMDGPUTargetInfo.h"
34 #include "Utils/AMDGPUBaseInfo.h"
35 #include "llvm/BinaryFormat/ELF.h"
36 #include "llvm/CodeGen/MachineFrameInfo.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/Support/AMDGPUMetadata.h"
43 #include "llvm/Support/MathExtras.h"
44 #include "llvm/Support/TargetParser.h"
45 #include "llvm/Support/TargetRegistry.h"
46 #include "llvm/Target/TargetLoweringObjectFile.h"
49 using namespace llvm::AMDGPU;
50 using namespace llvm::AMDGPU::HSAMD;
52 // TODO: This should get the default rounding mode from the kernel. We just set
53 // the default here, but this could change if the OpenCL rounding mode pragmas
56 // The denormal mode here should match what is reported by the OpenCL runtime
57 // for the CL_FP_DENORM bit from CL_DEVICE_{HALF|SINGLE|DOUBLE}_FP_CONFIG, but
58 // can also be override to flush with the -cl-denorms-are-zero compiler flag.
60 // AMD OpenCL only sets flush none and reports CL_FP_DENORM for double
61 // precision, and leaves single precision to flush all and does not report
62 // CL_FP_DENORM for CL_DEVICE_SINGLE_FP_CONFIG. Mesa's OpenCL currently reports
63 // CL_FP_DENORM for both.
65 // FIXME: It seems some instructions do not support single precision denormals
66 // regardless of the mode (exp_*_f32, rcp_*_f32, rsq_*_f32, rsq_*f32, sqrt_f32,
67 // and sin_f32, cos_f32 on most parts).
69 // We want to use these instructions, and using fp32 denormals also causes
70 // instructions to run at the double precision rate for the device so it's
71 // probably best to just report no single precision denormals.
72 static uint32_t getFPMode(const MachineFunction &F) {
73 const GCNSubtarget& ST = F.getSubtarget<GCNSubtarget>();
74 // TODO: Is there any real use for the flush in only / flush out only modes?
76 uint32_t FP32Denormals =
77 ST.hasFP32Denormals() ? FP_DENORM_FLUSH_NONE : FP_DENORM_FLUSH_IN_FLUSH_OUT;
79 uint32_t FP64Denormals =
80 ST.hasFP64Denormals() ? FP_DENORM_FLUSH_NONE : FP_DENORM_FLUSH_IN_FLUSH_OUT;
82 return FP_ROUND_MODE_SP(FP_ROUND_ROUND_TO_NEAREST) |
83 FP_ROUND_MODE_DP(FP_ROUND_ROUND_TO_NEAREST) |
84 FP_DENORM_MODE_SP(FP32Denormals) |
85 FP_DENORM_MODE_DP(FP64Denormals);
89 createAMDGPUAsmPrinterPass(TargetMachine &tm,
90 std::unique_ptr<MCStreamer> &&Streamer) {
91 return new AMDGPUAsmPrinter(tm, std::move(Streamer));
94 extern "C" void LLVMInitializeAMDGPUAsmPrinter() {
95 TargetRegistry::RegisterAsmPrinter(getTheAMDGPUTarget(),
96 llvm::createR600AsmPrinterPass);
97 TargetRegistry::RegisterAsmPrinter(getTheGCNTarget(),
98 createAMDGPUAsmPrinterPass);
101 AMDGPUAsmPrinter::AMDGPUAsmPrinter(TargetMachine &TM,
102 std::unique_ptr<MCStreamer> Streamer)
103 : AsmPrinter(TM, std::move(Streamer)) {
104 if (IsaInfo::hasCodeObjectV3(getGlobalSTI()))
105 HSAMetadataStream.reset(new MetadataStreamerV3());
107 HSAMetadataStream.reset(new MetadataStreamerV2());
110 StringRef AMDGPUAsmPrinter::getPassName() const {
111 return "AMDGPU Assembly Printer";
114 const MCSubtargetInfo *AMDGPUAsmPrinter::getGlobalSTI() const {
115 return TM.getMCSubtargetInfo();
118 AMDGPUTargetStreamer* AMDGPUAsmPrinter::getTargetStreamer() const {
121 return static_cast<AMDGPUTargetStreamer*>(OutStreamer->getTargetStreamer());
124 void AMDGPUAsmPrinter::EmitStartOfAsmFile(Module &M) {
125 if (IsaInfo::hasCodeObjectV3(getGlobalSTI())) {
126 std::string ExpectedTarget;
127 raw_string_ostream ExpectedTargetOS(ExpectedTarget);
128 IsaInfo::streamIsaVersion(getGlobalSTI(), ExpectedTargetOS);
130 getTargetStreamer()->EmitDirectiveAMDGCNTarget(ExpectedTarget);
133 if (TM.getTargetTriple().getOS() != Triple::AMDHSA &&
134 TM.getTargetTriple().getOS() != Triple::AMDPAL)
137 if (TM.getTargetTriple().getOS() == Triple::AMDHSA)
138 HSAMetadataStream->begin(M);
140 if (TM.getTargetTriple().getOS() == Triple::AMDPAL)
141 getTargetStreamer()->getPALMetadata()->readFromIR(M);
143 if (IsaInfo::hasCodeObjectV3(getGlobalSTI()))
146 // HSA emits NT_AMDGPU_HSA_CODE_OBJECT_VERSION for code objects v2.
147 if (TM.getTargetTriple().getOS() == Triple::AMDHSA)
148 getTargetStreamer()->EmitDirectiveHSACodeObjectVersion(2, 1);
150 // HSA and PAL emit NT_AMDGPU_HSA_ISA for code objects v2.
151 IsaVersion Version = getIsaVersion(getGlobalSTI()->getCPU());
152 getTargetStreamer()->EmitDirectiveHSACodeObjectISA(
153 Version.Major, Version.Minor, Version.Stepping, "AMD", "AMDGPU");
156 void AMDGPUAsmPrinter::EmitEndOfAsmFile(Module &M) {
157 // Following code requires TargetStreamer to be present.
158 if (!getTargetStreamer())
161 if (!IsaInfo::hasCodeObjectV3(getGlobalSTI())) {
162 // Emit ISA Version (NT_AMD_AMDGPU_ISA).
163 std::string ISAVersionString;
164 raw_string_ostream ISAVersionStream(ISAVersionString);
165 IsaInfo::streamIsaVersion(getGlobalSTI(), ISAVersionStream);
166 getTargetStreamer()->EmitISAVersion(ISAVersionStream.str());
169 // Emit HSA Metadata (NT_AMD_AMDGPU_HSA_METADATA).
170 if (TM.getTargetTriple().getOS() == Triple::AMDHSA) {
171 HSAMetadataStream->end();
172 bool Success = HSAMetadataStream->emitTo(*getTargetStreamer());
174 assert(Success && "Malformed HSA Metadata");
178 bool AMDGPUAsmPrinter::isBlockOnlyReachableByFallthrough(
179 const MachineBasicBlock *MBB) const {
180 if (!AsmPrinter::isBlockOnlyReachableByFallthrough(MBB))
186 // If this is a block implementing a long branch, an expression relative to
187 // the start of the block is needed. to the start of the block.
188 // XXX - Is there a smarter way to check this?
189 return (MBB->back().getOpcode() != AMDGPU::S_SETPC_B64);
192 void AMDGPUAsmPrinter::EmitFunctionBodyStart() {
193 const SIMachineFunctionInfo &MFI = *MF->getInfo<SIMachineFunctionInfo>();
194 if (!MFI.isEntryFunction())
197 const GCNSubtarget &STM = MF->getSubtarget<GCNSubtarget>();
198 const Function &F = MF->getFunction();
199 if (!STM.hasCodeObjectV3() && STM.isAmdHsaOrMesa(F) &&
200 (F.getCallingConv() == CallingConv::AMDGPU_KERNEL ||
201 F.getCallingConv() == CallingConv::SPIR_KERNEL)) {
202 amd_kernel_code_t KernelCode;
203 getAmdKernelCode(KernelCode, CurrentProgramInfo, *MF);
204 getTargetStreamer()->EmitAMDKernelCodeT(KernelCode);
207 if (STM.isAmdHsaOS())
208 HSAMetadataStream->emitKernel(*MF, CurrentProgramInfo);
210 DumpCodeInstEmitter = nullptr;
211 if (STM.dumpCode()) {
212 // For -dumpcode, get the assembler out of the streamer, even if it does
213 // not really want to let us have it. This only works with -filetype=obj.
214 bool SaveFlag = OutStreamer->getUseAssemblerInfoForParsing();
215 OutStreamer->setUseAssemblerInfoForParsing(true);
216 MCAssembler *Assembler = OutStreamer->getAssemblerPtr();
217 OutStreamer->setUseAssemblerInfoForParsing(SaveFlag);
219 DumpCodeInstEmitter = Assembler->getEmitterPtr();
223 void AMDGPUAsmPrinter::EmitFunctionBodyEnd() {
224 const SIMachineFunctionInfo &MFI = *MF->getInfo<SIMachineFunctionInfo>();
225 if (!MFI.isEntryFunction())
228 if (!IsaInfo::hasCodeObjectV3(getGlobalSTI()) ||
229 TM.getTargetTriple().getOS() != Triple::AMDHSA)
232 auto &Streamer = getTargetStreamer()->getStreamer();
233 auto &Context = Streamer.getContext();
234 auto &ObjectFileInfo = *Context.getObjectFileInfo();
235 auto &ReadOnlySection = *ObjectFileInfo.getReadOnlySection();
237 Streamer.PushSection();
238 Streamer.SwitchSection(&ReadOnlySection);
240 // CP microcode requires the kernel descriptor to be allocated on 64 byte
242 Streamer.EmitValueToAlignment(64, 0, 1, 0);
243 if (ReadOnlySection.getAlignment() < 64)
244 ReadOnlySection.setAlignment(64);
246 const MCSubtargetInfo &STI = MF->getSubtarget();
248 SmallString<128> KernelName;
249 getNameWithPrefix(KernelName, &MF->getFunction());
250 getTargetStreamer()->EmitAmdhsaKernelDescriptor(
251 STI, KernelName, getAmdhsaKernelDescriptor(*MF, CurrentProgramInfo),
252 CurrentProgramInfo.NumVGPRsForWavesPerEU,
253 CurrentProgramInfo.NumSGPRsForWavesPerEU -
254 IsaInfo::getNumExtraSGPRs(&STI,
255 CurrentProgramInfo.VCCUsed,
256 CurrentProgramInfo.FlatUsed),
257 CurrentProgramInfo.VCCUsed, CurrentProgramInfo.FlatUsed,
260 Streamer.PopSection();
263 void AMDGPUAsmPrinter::EmitFunctionEntryLabel() {
264 if (IsaInfo::hasCodeObjectV3(getGlobalSTI()) &&
265 TM.getTargetTriple().getOS() == Triple::AMDHSA) {
266 AsmPrinter::EmitFunctionEntryLabel();
270 const SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>();
271 const GCNSubtarget &STM = MF->getSubtarget<GCNSubtarget>();
272 if (MFI->isEntryFunction() && STM.isAmdHsaOrMesa(MF->getFunction())) {
273 SmallString<128> SymbolName;
274 getNameWithPrefix(SymbolName, &MF->getFunction()),
275 getTargetStreamer()->EmitAMDGPUSymbolType(
276 SymbolName, ELF::STT_AMDGPU_HSA_KERNEL);
278 if (DumpCodeInstEmitter) {
279 // Disassemble function name label to text.
280 DisasmLines.push_back(MF->getName().str() + ":");
281 DisasmLineMaxLen = std::max(DisasmLineMaxLen, DisasmLines.back().size());
282 HexLines.push_back("");
285 AsmPrinter::EmitFunctionEntryLabel();
288 void AMDGPUAsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) const {
289 if (DumpCodeInstEmitter && !isBlockOnlyReachableByFallthrough(&MBB)) {
290 // Write a line for the basic block label if it is not only fallthrough.
291 DisasmLines.push_back(
292 (Twine("BB") + Twine(getFunctionNumber())
293 + "_" + Twine(MBB.getNumber()) + ":").str());
294 DisasmLineMaxLen = std::max(DisasmLineMaxLen, DisasmLines.back().size());
295 HexLines.push_back("");
297 AsmPrinter::EmitBasicBlockStart(MBB);
300 void AMDGPUAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
302 // Group segment variables aren't emitted in HSA.
303 if (AMDGPU::isGroupSegment(GV))
306 AsmPrinter::EmitGlobalVariable(GV);
309 bool AMDGPUAsmPrinter::doFinalization(Module &M) {
310 CallGraphResourceInfo.clear();
312 if (AMDGPU::isGFX10(*getGlobalSTI())) {
313 OutStreamer->SwitchSection(getObjFileLowering().getTextSection());
314 getTargetStreamer()->EmitCodeEnd();
317 return AsmPrinter::doFinalization(M);
320 // Print comments that apply to both callable functions and entry points.
321 void AMDGPUAsmPrinter::emitCommonFunctionComments(
324 uint64_t ScratchSize,
326 const AMDGPUMachineFunction *MFI) {
327 OutStreamer->emitRawComment(" codeLenInByte = " + Twine(CodeSize), false);
328 OutStreamer->emitRawComment(" NumSgprs: " + Twine(NumSGPR), false);
329 OutStreamer->emitRawComment(" NumVgprs: " + Twine(NumVGPR), false);
330 OutStreamer->emitRawComment(" ScratchSize: " + Twine(ScratchSize), false);
331 OutStreamer->emitRawComment(" MemoryBound: " + Twine(MFI->isMemoryBound()),
335 uint16_t AMDGPUAsmPrinter::getAmdhsaKernelCodeProperties(
336 const MachineFunction &MF) const {
337 const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
338 uint16_t KernelCodeProperties = 0;
340 if (MFI.hasPrivateSegmentBuffer()) {
341 KernelCodeProperties |=
342 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER;
344 if (MFI.hasDispatchPtr()) {
345 KernelCodeProperties |=
346 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR;
348 if (MFI.hasQueuePtr()) {
349 KernelCodeProperties |=
350 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR;
352 if (MFI.hasKernargSegmentPtr()) {
353 KernelCodeProperties |=
354 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR;
356 if (MFI.hasDispatchID()) {
357 KernelCodeProperties |=
358 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID;
360 if (MFI.hasFlatScratchInit()) {
361 KernelCodeProperties |=
362 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT;
365 return KernelCodeProperties;
368 amdhsa::kernel_descriptor_t AMDGPUAsmPrinter::getAmdhsaKernelDescriptor(
369 const MachineFunction &MF,
370 const SIProgramInfo &PI) const {
371 amdhsa::kernel_descriptor_t KernelDescriptor;
372 memset(&KernelDescriptor, 0x0, sizeof(KernelDescriptor));
374 assert(isUInt<32>(PI.ScratchSize));
375 assert(isUInt<32>(PI.ComputePGMRSrc1));
376 assert(isUInt<32>(PI.ComputePGMRSrc2));
378 KernelDescriptor.group_segment_fixed_size = PI.LDSSize;
379 KernelDescriptor.private_segment_fixed_size = PI.ScratchSize;
380 KernelDescriptor.compute_pgm_rsrc1 = PI.ComputePGMRSrc1;
381 KernelDescriptor.compute_pgm_rsrc2 = PI.ComputePGMRSrc2;
382 KernelDescriptor.kernel_code_properties = getAmdhsaKernelCodeProperties(MF);
384 return KernelDescriptor;
387 bool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
388 CurrentProgramInfo = SIProgramInfo();
390 const AMDGPUMachineFunction *MFI = MF.getInfo<AMDGPUMachineFunction>();
392 // The starting address of all shader programs must be 256 bytes aligned.
393 // Regular functions just need the basic required instruction alignment.
394 MF.setAlignment(MFI->isEntryFunction() ? 8 : 2);
396 SetupMachineFunction(MF);
398 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
399 MCContext &Context = getObjFileLowering().getContext();
400 // FIXME: This should be an explicit check for Mesa.
401 if (!STM.isAmdHsaOS() && !STM.isAmdPalOS()) {
402 MCSectionELF *ConfigSection =
403 Context.getELFSection(".AMDGPU.config", ELF::SHT_PROGBITS, 0);
404 OutStreamer->SwitchSection(ConfigSection);
407 if (MFI->isEntryFunction()) {
408 getSIProgramInfo(CurrentProgramInfo, MF);
410 auto I = CallGraphResourceInfo.insert(
411 std::make_pair(&MF.getFunction(), SIFunctionResourceInfo()));
412 SIFunctionResourceInfo &Info = I.first->second;
413 assert(I.second && "should only be called once per function");
414 Info = analyzeResourceUsage(MF);
417 if (STM.isAmdPalOS())
418 EmitPALMetadata(MF, CurrentProgramInfo);
419 else if (!STM.isAmdHsaOS()) {
420 EmitProgramInfoSI(MF, CurrentProgramInfo);
425 DisasmLineMaxLen = 0;
430 MCSectionELF *CommentSection =
431 Context.getELFSection(".AMDGPU.csdata", ELF::SHT_PROGBITS, 0);
432 OutStreamer->SwitchSection(CommentSection);
434 if (!MFI->isEntryFunction()) {
435 OutStreamer->emitRawComment(" Function info:", false);
436 SIFunctionResourceInfo &Info = CallGraphResourceInfo[&MF.getFunction()];
437 emitCommonFunctionComments(
439 Info.getTotalNumSGPRs(MF.getSubtarget<GCNSubtarget>()),
440 Info.PrivateSegmentSize,
441 getFunctionCodeSize(MF), MFI);
445 OutStreamer->emitRawComment(" Kernel info:", false);
446 emitCommonFunctionComments(CurrentProgramInfo.NumVGPR,
447 CurrentProgramInfo.NumSGPR,
448 CurrentProgramInfo.ScratchSize,
449 getFunctionCodeSize(MF), MFI);
451 OutStreamer->emitRawComment(
452 " FloatMode: " + Twine(CurrentProgramInfo.FloatMode), false);
453 OutStreamer->emitRawComment(
454 " IeeeMode: " + Twine(CurrentProgramInfo.IEEEMode), false);
455 OutStreamer->emitRawComment(
456 " LDSByteSize: " + Twine(CurrentProgramInfo.LDSSize) +
457 " bytes/workgroup (compile time only)", false);
459 OutStreamer->emitRawComment(
460 " SGPRBlocks: " + Twine(CurrentProgramInfo.SGPRBlocks), false);
461 OutStreamer->emitRawComment(
462 " VGPRBlocks: " + Twine(CurrentProgramInfo.VGPRBlocks), false);
464 OutStreamer->emitRawComment(
465 " NumSGPRsForWavesPerEU: " +
466 Twine(CurrentProgramInfo.NumSGPRsForWavesPerEU), false);
467 OutStreamer->emitRawComment(
468 " NumVGPRsForWavesPerEU: " +
469 Twine(CurrentProgramInfo.NumVGPRsForWavesPerEU), false);
471 OutStreamer->emitRawComment(
472 " WaveLimiterHint : " + Twine(MFI->needsWaveLimiter()), false);
474 OutStreamer->emitRawComment(
475 " COMPUTE_PGM_RSRC2:USER_SGPR: " +
476 Twine(G_00B84C_USER_SGPR(CurrentProgramInfo.ComputePGMRSrc2)), false);
477 OutStreamer->emitRawComment(
478 " COMPUTE_PGM_RSRC2:TRAP_HANDLER: " +
479 Twine(G_00B84C_TRAP_HANDLER(CurrentProgramInfo.ComputePGMRSrc2)), false);
480 OutStreamer->emitRawComment(
481 " COMPUTE_PGM_RSRC2:TGID_X_EN: " +
482 Twine(G_00B84C_TGID_X_EN(CurrentProgramInfo.ComputePGMRSrc2)), false);
483 OutStreamer->emitRawComment(
484 " COMPUTE_PGM_RSRC2:TGID_Y_EN: " +
485 Twine(G_00B84C_TGID_Y_EN(CurrentProgramInfo.ComputePGMRSrc2)), false);
486 OutStreamer->emitRawComment(
487 " COMPUTE_PGM_RSRC2:TGID_Z_EN: " +
488 Twine(G_00B84C_TGID_Z_EN(CurrentProgramInfo.ComputePGMRSrc2)), false);
489 OutStreamer->emitRawComment(
490 " COMPUTE_PGM_RSRC2:TIDIG_COMP_CNT: " +
491 Twine(G_00B84C_TIDIG_COMP_CNT(CurrentProgramInfo.ComputePGMRSrc2)),
495 if (DumpCodeInstEmitter) {
497 OutStreamer->SwitchSection(
498 Context.getELFSection(".AMDGPU.disasm", ELF::SHT_NOTE, 0));
500 for (size_t i = 0; i < DisasmLines.size(); ++i) {
501 std::string Comment = "\n";
502 if (!HexLines[i].empty()) {
503 Comment = std::string(DisasmLineMaxLen - DisasmLines[i].size(), ' ');
504 Comment += " ; " + HexLines[i] + "\n";
507 OutStreamer->EmitBytes(StringRef(DisasmLines[i]));
508 OutStreamer->EmitBytes(StringRef(Comment));
515 uint64_t AMDGPUAsmPrinter::getFunctionCodeSize(const MachineFunction &MF) const {
516 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
517 const SIInstrInfo *TII = STM.getInstrInfo();
519 uint64_t CodeSize = 0;
521 for (const MachineBasicBlock &MBB : MF) {
522 for (const MachineInstr &MI : MBB) {
523 // TODO: CodeSize should account for multiple functions.
525 // TODO: Should we count size of debug info?
526 if (MI.isDebugInstr())
529 CodeSize += TII->getInstSizeInBytes(MI);
536 static bool hasAnyNonFlatUseOfReg(const MachineRegisterInfo &MRI,
537 const SIInstrInfo &TII,
539 for (const MachineOperand &UseOp : MRI.reg_operands(Reg)) {
540 if (!UseOp.isImplicit() || !TII.isFLAT(*UseOp.getParent()))
547 int32_t AMDGPUAsmPrinter::SIFunctionResourceInfo::getTotalNumSGPRs(
548 const GCNSubtarget &ST) const {
549 return NumExplicitSGPR + IsaInfo::getNumExtraSGPRs(&ST,
550 UsesVCC, UsesFlatScratch);
553 AMDGPUAsmPrinter::SIFunctionResourceInfo AMDGPUAsmPrinter::analyzeResourceUsage(
554 const MachineFunction &MF) const {
555 SIFunctionResourceInfo Info;
557 const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
558 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
559 const MachineFrameInfo &FrameInfo = MF.getFrameInfo();
560 const MachineRegisterInfo &MRI = MF.getRegInfo();
561 const SIInstrInfo *TII = ST.getInstrInfo();
562 const SIRegisterInfo &TRI = TII->getRegisterInfo();
564 Info.UsesFlatScratch = MRI.isPhysRegUsed(AMDGPU::FLAT_SCR_LO) ||
565 MRI.isPhysRegUsed(AMDGPU::FLAT_SCR_HI);
567 // Even if FLAT_SCRATCH is implicitly used, it has no effect if flat
568 // instructions aren't used to access the scratch buffer. Inline assembly may
571 // If we only have implicit uses of flat_scr on flat instructions, it is not
573 if (Info.UsesFlatScratch && !MFI->hasFlatScratchInit() &&
574 (!hasAnyNonFlatUseOfReg(MRI, *TII, AMDGPU::FLAT_SCR) &&
575 !hasAnyNonFlatUseOfReg(MRI, *TII, AMDGPU::FLAT_SCR_LO) &&
576 !hasAnyNonFlatUseOfReg(MRI, *TII, AMDGPU::FLAT_SCR_HI))) {
577 Info.UsesFlatScratch = false;
580 Info.HasDynamicallySizedStack = FrameInfo.hasVarSizedObjects();
581 Info.PrivateSegmentSize = FrameInfo.getStackSize();
582 if (MFI->isStackRealigned())
583 Info.PrivateSegmentSize += FrameInfo.getMaxAlignment();
586 Info.UsesVCC = MRI.isPhysRegUsed(AMDGPU::VCC_LO) ||
587 MRI.isPhysRegUsed(AMDGPU::VCC_HI);
589 // If there are no calls, MachineRegisterInfo can tell us the used register
591 // A tail call isn't considered a call for MachineFrameInfo's purposes.
592 if (!FrameInfo.hasCalls() && !FrameInfo.hasTailCall()) {
593 MCPhysReg HighestVGPRReg = AMDGPU::NoRegister;
594 for (MCPhysReg Reg : reverse(AMDGPU::VGPR_32RegClass.getRegisters())) {
595 if (MRI.isPhysRegUsed(Reg)) {
596 HighestVGPRReg = Reg;
601 MCPhysReg HighestSGPRReg = AMDGPU::NoRegister;
602 for (MCPhysReg Reg : reverse(AMDGPU::SGPR_32RegClass.getRegisters())) {
603 if (MRI.isPhysRegUsed(Reg)) {
604 HighestSGPRReg = Reg;
609 // We found the maximum register index. They start at 0, so add one to get the
610 // number of registers.
611 Info.NumVGPR = HighestVGPRReg == AMDGPU::NoRegister ? 0 :
612 TRI.getHWRegIndex(HighestVGPRReg) + 1;
613 Info.NumExplicitSGPR = HighestSGPRReg == AMDGPU::NoRegister ? 0 :
614 TRI.getHWRegIndex(HighestSGPRReg) + 1;
619 int32_t MaxVGPR = -1;
620 int32_t MaxSGPR = -1;
621 uint64_t CalleeFrameSize = 0;
623 for (const MachineBasicBlock &MBB : MF) {
624 for (const MachineInstr &MI : MBB) {
625 // TODO: Check regmasks? Do they occur anywhere except calls?
626 for (const MachineOperand &MO : MI.operands()) {
633 unsigned Reg = MO.getReg();
636 case AMDGPU::EXEC_LO:
637 case AMDGPU::EXEC_HI:
640 case AMDGPU::SRC_SHARED_BASE:
641 case AMDGPU::SRC_SHARED_LIMIT:
642 case AMDGPU::SRC_PRIVATE_BASE:
643 case AMDGPU::SRC_PRIVATE_LIMIT:
644 case AMDGPU::SGPR_NULL:
647 case AMDGPU::SRC_POPS_EXITING_WAVE_ID:
648 llvm_unreachable("src_pops_exiting_wave_id should not be used");
650 case AMDGPU::NoRegister:
651 assert(MI.isDebugInstr());
660 case AMDGPU::FLAT_SCR:
661 case AMDGPU::FLAT_SCR_LO:
662 case AMDGPU::FLAT_SCR_HI:
665 case AMDGPU::XNACK_MASK:
666 case AMDGPU::XNACK_MASK_LO:
667 case AMDGPU::XNACK_MASK_HI:
668 llvm_unreachable("xnack_mask registers should not be used");
670 case AMDGPU::LDS_DIRECT:
671 llvm_unreachable("lds_direct register should not be used");
679 llvm_unreachable("trap handler registers should not be used");
681 case AMDGPU::SRC_VCCZ:
682 llvm_unreachable("src_vccz register should not be used");
684 case AMDGPU::SRC_EXECZ:
685 llvm_unreachable("src_execz register should not be used");
687 case AMDGPU::SRC_SCC:
688 llvm_unreachable("src_scc register should not be used");
694 if (AMDGPU::SReg_32RegClass.contains(Reg)) {
695 assert(!AMDGPU::TTMP_32RegClass.contains(Reg) &&
696 "trap handler registers should not be used");
699 } else if (AMDGPU::VGPR_32RegClass.contains(Reg)) {
702 } else if (AMDGPU::SReg_64RegClass.contains(Reg)) {
703 assert(!AMDGPU::TTMP_64RegClass.contains(Reg) &&
704 "trap handler registers should not be used");
707 } else if (AMDGPU::VReg_64RegClass.contains(Reg)) {
710 } else if (AMDGPU::VReg_96RegClass.contains(Reg)) {
713 } else if (AMDGPU::SReg_128RegClass.contains(Reg)) {
714 assert(!AMDGPU::TTMP_128RegClass.contains(Reg) &&
715 "trap handler registers should not be used");
718 } else if (AMDGPU::VReg_128RegClass.contains(Reg)) {
721 } else if (AMDGPU::SReg_256RegClass.contains(Reg)) {
722 assert(!AMDGPU::TTMP_256RegClass.contains(Reg) &&
723 "trap handler registers should not be used");
726 } else if (AMDGPU::VReg_256RegClass.contains(Reg)) {
729 } else if (AMDGPU::SReg_512RegClass.contains(Reg)) {
730 assert(!AMDGPU::TTMP_512RegClass.contains(Reg) &&
731 "trap handler registers should not be used");
734 } else if (AMDGPU::VReg_512RegClass.contains(Reg)) {
737 } else if (AMDGPU::SReg_96RegClass.contains(Reg)) {
741 llvm_unreachable("Unknown register class");
743 unsigned HWReg = TRI.getHWRegIndex(Reg);
744 int MaxUsed = HWReg + Width - 1;
746 MaxSGPR = MaxUsed > MaxSGPR ? MaxUsed : MaxSGPR;
748 MaxVGPR = MaxUsed > MaxVGPR ? MaxUsed : MaxVGPR;
753 // Pseudo used just to encode the underlying global. Is there a better
754 // way to track this?
756 const MachineOperand *CalleeOp
757 = TII->getNamedOperand(MI, AMDGPU::OpName::callee);
758 const Function *Callee = cast<Function>(CalleeOp->getGlobal());
759 if (Callee->isDeclaration()) {
760 // If this is a call to an external function, we can't do much. Make
761 // conservative guesses.
763 // 48 SGPRs - vcc, - flat_scr, -xnack
765 47 - IsaInfo::getNumExtraSGPRs(&ST, true, ST.hasFlatAddressSpace());
766 MaxSGPR = std::max(MaxSGPR, MaxSGPRGuess);
767 MaxVGPR = std::max(MaxVGPR, 23);
769 CalleeFrameSize = std::max(CalleeFrameSize, UINT64_C(16384));
771 Info.UsesFlatScratch = ST.hasFlatAddressSpace();
772 Info.HasDynamicallySizedStack = true;
774 // We force CodeGen to run in SCC order, so the callee's register
775 // usage etc. should be the cumulative usage of all callees.
777 auto I = CallGraphResourceInfo.find(Callee);
778 if (I == CallGraphResourceInfo.end()) {
779 // Avoid crashing on undefined behavior with an illegal call to a
780 // kernel. If a callsite's calling convention doesn't match the
781 // function's, it's undefined behavior. If the callsite calling
782 // convention does match, that would have errored earlier.
783 // FIXME: The verifier shouldn't allow this.
784 if (AMDGPU::isEntryFunctionCC(Callee->getCallingConv()))
785 report_fatal_error("invalid call to entry function");
787 llvm_unreachable("callee should have been handled before caller");
790 MaxSGPR = std::max(I->second.NumExplicitSGPR - 1, MaxSGPR);
791 MaxVGPR = std::max(I->second.NumVGPR - 1, MaxVGPR);
793 = std::max(I->second.PrivateSegmentSize, CalleeFrameSize);
794 Info.UsesVCC |= I->second.UsesVCC;
795 Info.UsesFlatScratch |= I->second.UsesFlatScratch;
796 Info.HasDynamicallySizedStack |= I->second.HasDynamicallySizedStack;
797 Info.HasRecursion |= I->second.HasRecursion;
800 if (!Callee->doesNotRecurse())
801 Info.HasRecursion = true;
806 Info.NumExplicitSGPR = MaxSGPR + 1;
807 Info.NumVGPR = MaxVGPR + 1;
808 Info.PrivateSegmentSize += CalleeFrameSize;
813 void AMDGPUAsmPrinter::getSIProgramInfo(SIProgramInfo &ProgInfo,
814 const MachineFunction &MF) {
815 SIFunctionResourceInfo Info = analyzeResourceUsage(MF);
817 ProgInfo.NumVGPR = Info.NumVGPR;
818 ProgInfo.NumSGPR = Info.NumExplicitSGPR;
819 ProgInfo.ScratchSize = Info.PrivateSegmentSize;
820 ProgInfo.VCCUsed = Info.UsesVCC;
821 ProgInfo.FlatUsed = Info.UsesFlatScratch;
822 ProgInfo.DynamicCallStack = Info.HasDynamicallySizedStack || Info.HasRecursion;
824 if (!isUInt<32>(ProgInfo.ScratchSize)) {
825 DiagnosticInfoStackSize DiagStackSize(MF.getFunction(),
826 ProgInfo.ScratchSize, DS_Error);
827 MF.getFunction().getContext().diagnose(DiagStackSize);
830 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
831 const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
833 // TODO(scott.linder): The calculations related to SGPR/VGPR blocks are
834 // duplicated in part in AMDGPUAsmParser::calculateGPRBlocks, and could be
836 unsigned ExtraSGPRs = IsaInfo::getNumExtraSGPRs(
837 &STM, ProgInfo.VCCUsed, ProgInfo.FlatUsed);
839 // Check the addressable register limit before we add ExtraSGPRs.
840 if (STM.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS &&
841 !STM.hasSGPRInitBug()) {
842 unsigned MaxAddressableNumSGPRs = STM.getAddressableNumSGPRs();
843 if (ProgInfo.NumSGPR > MaxAddressableNumSGPRs) {
844 // This can happen due to a compiler bug or when using inline asm.
845 LLVMContext &Ctx = MF.getFunction().getContext();
846 DiagnosticInfoResourceLimit Diag(MF.getFunction(),
847 "addressable scalar registers",
848 ProgInfo.NumSGPR, DS_Error,
850 MaxAddressableNumSGPRs);
852 ProgInfo.NumSGPR = MaxAddressableNumSGPRs - 1;
856 // Account for extra SGPRs and VGPRs reserved for debugger use.
857 ProgInfo.NumSGPR += ExtraSGPRs;
859 // Ensure there are enough SGPRs and VGPRs for wave dispatch, where wave
860 // dispatch registers are function args.
861 unsigned WaveDispatchNumSGPR = 0, WaveDispatchNumVGPR = 0;
862 for (auto &Arg : MF.getFunction().args()) {
863 unsigned NumRegs = (Arg.getType()->getPrimitiveSizeInBits() + 31) / 32;
864 if (Arg.hasAttribute(Attribute::InReg))
865 WaveDispatchNumSGPR += NumRegs;
867 WaveDispatchNumVGPR += NumRegs;
869 ProgInfo.NumSGPR = std::max(ProgInfo.NumSGPR, WaveDispatchNumSGPR);
870 ProgInfo.NumVGPR = std::max(ProgInfo.NumVGPR, WaveDispatchNumVGPR);
872 // Adjust number of registers used to meet default/requested minimum/maximum
873 // number of waves per execution unit request.
874 ProgInfo.NumSGPRsForWavesPerEU = std::max(
875 std::max(ProgInfo.NumSGPR, 1u), STM.getMinNumSGPRs(MFI->getMaxWavesPerEU()));
876 ProgInfo.NumVGPRsForWavesPerEU = std::max(
877 std::max(ProgInfo.NumVGPR, 1u), STM.getMinNumVGPRs(MFI->getMaxWavesPerEU()));
879 if (STM.getGeneration() <= AMDGPUSubtarget::SEA_ISLANDS ||
880 STM.hasSGPRInitBug()) {
881 unsigned MaxAddressableNumSGPRs = STM.getAddressableNumSGPRs();
882 if (ProgInfo.NumSGPR > MaxAddressableNumSGPRs) {
883 // This can happen due to a compiler bug or when using inline asm to use
884 // the registers which are usually reserved for vcc etc.
885 LLVMContext &Ctx = MF.getFunction().getContext();
886 DiagnosticInfoResourceLimit Diag(MF.getFunction(),
888 ProgInfo.NumSGPR, DS_Error,
890 MaxAddressableNumSGPRs);
892 ProgInfo.NumSGPR = MaxAddressableNumSGPRs;
893 ProgInfo.NumSGPRsForWavesPerEU = MaxAddressableNumSGPRs;
897 if (STM.hasSGPRInitBug()) {
899 AMDGPU::IsaInfo::FIXED_NUM_SGPRS_FOR_INIT_BUG;
900 ProgInfo.NumSGPRsForWavesPerEU =
901 AMDGPU::IsaInfo::FIXED_NUM_SGPRS_FOR_INIT_BUG;
904 if (MFI->getNumUserSGPRs() > STM.getMaxNumUserSGPRs()) {
905 LLVMContext &Ctx = MF.getFunction().getContext();
906 DiagnosticInfoResourceLimit Diag(MF.getFunction(), "user SGPRs",
907 MFI->getNumUserSGPRs(), DS_Error);
911 if (MFI->getLDSSize() > static_cast<unsigned>(STM.getLocalMemorySize())) {
912 LLVMContext &Ctx = MF.getFunction().getContext();
913 DiagnosticInfoResourceLimit Diag(MF.getFunction(), "local memory",
914 MFI->getLDSSize(), DS_Error);
918 ProgInfo.SGPRBlocks = IsaInfo::getNumSGPRBlocks(
919 &STM, ProgInfo.NumSGPRsForWavesPerEU);
920 ProgInfo.VGPRBlocks = IsaInfo::getNumVGPRBlocks(
921 &STM, ProgInfo.NumVGPRsForWavesPerEU);
923 // Set the value to initialize FP_ROUND and FP_DENORM parts of the mode
925 ProgInfo.FloatMode = getFPMode(MF);
927 const SIModeRegisterDefaults Mode = MFI->getMode();
928 ProgInfo.IEEEMode = Mode.IEEE;
930 // Make clamp modifier on NaN input returns 0.
931 ProgInfo.DX10Clamp = Mode.DX10Clamp;
933 unsigned LDSAlignShift;
934 if (STM.getGeneration() < AMDGPUSubtarget::SEA_ISLANDS) {
935 // LDS is allocated in 64 dword blocks.
938 // LDS is allocated in 128 dword blocks.
942 unsigned LDSSpillSize =
943 MFI->getLDSWaveSpillSize() * MFI->getMaxFlatWorkGroupSize();
945 ProgInfo.LDSSize = MFI->getLDSSize() + LDSSpillSize;
947 alignTo(ProgInfo.LDSSize, 1ULL << LDSAlignShift) >> LDSAlignShift;
949 // Scratch is allocated in 256 dword blocks.
950 unsigned ScratchAlignShift = 10;
951 // We need to program the hardware with the amount of scratch memory that
952 // is used by the entire wave. ProgInfo.ScratchSize is the amount of
953 // scratch memory used per thread.
954 ProgInfo.ScratchBlocks =
955 alignTo(ProgInfo.ScratchSize * STM.getWavefrontSize(),
956 1ULL << ScratchAlignShift) >>
959 if (getIsaVersion(getGlobalSTI()->getCPU()).Major >= 10) {
960 ProgInfo.WgpMode = STM.isCuModeEnabled() ? 0 : 1;
961 ProgInfo.MemOrdered = 1;
964 ProgInfo.ComputePGMRSrc1 =
965 S_00B848_VGPRS(ProgInfo.VGPRBlocks) |
966 S_00B848_SGPRS(ProgInfo.SGPRBlocks) |
967 S_00B848_PRIORITY(ProgInfo.Priority) |
968 S_00B848_FLOAT_MODE(ProgInfo.FloatMode) |
969 S_00B848_PRIV(ProgInfo.Priv) |
970 S_00B848_DX10_CLAMP(ProgInfo.DX10Clamp) |
971 S_00B848_DEBUG_MODE(ProgInfo.DebugMode) |
972 S_00B848_IEEE_MODE(ProgInfo.IEEEMode) |
973 S_00B848_WGP_MODE(ProgInfo.WgpMode) |
974 S_00B848_MEM_ORDERED(ProgInfo.MemOrdered);
976 // 0 = X, 1 = XY, 2 = XYZ
977 unsigned TIDIGCompCnt = 0;
978 if (MFI->hasWorkItemIDZ())
980 else if (MFI->hasWorkItemIDY())
983 ProgInfo.ComputePGMRSrc2 =
984 S_00B84C_SCRATCH_EN(ProgInfo.ScratchBlocks > 0) |
985 S_00B84C_USER_SGPR(MFI->getNumUserSGPRs()) |
986 // For AMDHSA, TRAP_HANDLER must be zero, as it is populated by the CP.
987 S_00B84C_TRAP_HANDLER(STM.isAmdHsaOS() ? 0 : STM.isTrapHandlerEnabled()) |
988 S_00B84C_TGID_X_EN(MFI->hasWorkGroupIDX()) |
989 S_00B84C_TGID_Y_EN(MFI->hasWorkGroupIDY()) |
990 S_00B84C_TGID_Z_EN(MFI->hasWorkGroupIDZ()) |
991 S_00B84C_TG_SIZE_EN(MFI->hasWorkGroupInfo()) |
992 S_00B84C_TIDIG_COMP_CNT(TIDIGCompCnt) |
993 S_00B84C_EXCP_EN_MSB(0) |
994 // For AMDHSA, LDS_SIZE must be zero, as it is populated by the CP.
995 S_00B84C_LDS_SIZE(STM.isAmdHsaOS() ? 0 : ProgInfo.LDSBlocks) |
999 static unsigned getRsrcReg(CallingConv::ID CallConv) {
1001 default: LLVM_FALLTHROUGH;
1002 case CallingConv::AMDGPU_CS: return R_00B848_COMPUTE_PGM_RSRC1;
1003 case CallingConv::AMDGPU_LS: return R_00B528_SPI_SHADER_PGM_RSRC1_LS;
1004 case CallingConv::AMDGPU_HS: return R_00B428_SPI_SHADER_PGM_RSRC1_HS;
1005 case CallingConv::AMDGPU_ES: return R_00B328_SPI_SHADER_PGM_RSRC1_ES;
1006 case CallingConv::AMDGPU_GS: return R_00B228_SPI_SHADER_PGM_RSRC1_GS;
1007 case CallingConv::AMDGPU_VS: return R_00B128_SPI_SHADER_PGM_RSRC1_VS;
1008 case CallingConv::AMDGPU_PS: return R_00B028_SPI_SHADER_PGM_RSRC1_PS;
1012 void AMDGPUAsmPrinter::EmitProgramInfoSI(const MachineFunction &MF,
1013 const SIProgramInfo &CurrentProgramInfo) {
1014 const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1015 unsigned RsrcReg = getRsrcReg(MF.getFunction().getCallingConv());
1017 if (AMDGPU::isCompute(MF.getFunction().getCallingConv())) {
1018 OutStreamer->EmitIntValue(R_00B848_COMPUTE_PGM_RSRC1, 4);
1020 OutStreamer->EmitIntValue(CurrentProgramInfo.ComputePGMRSrc1, 4);
1022 OutStreamer->EmitIntValue(R_00B84C_COMPUTE_PGM_RSRC2, 4);
1023 OutStreamer->EmitIntValue(CurrentProgramInfo.ComputePGMRSrc2, 4);
1025 OutStreamer->EmitIntValue(R_00B860_COMPUTE_TMPRING_SIZE, 4);
1026 OutStreamer->EmitIntValue(S_00B860_WAVESIZE(CurrentProgramInfo.ScratchBlocks), 4);
1028 // TODO: Should probably note flat usage somewhere. SC emits a "FlatPtr32 =
1029 // 0" comment but I don't see a corresponding field in the register spec.
1031 OutStreamer->EmitIntValue(RsrcReg, 4);
1032 OutStreamer->EmitIntValue(S_00B028_VGPRS(CurrentProgramInfo.VGPRBlocks) |
1033 S_00B028_SGPRS(CurrentProgramInfo.SGPRBlocks), 4);
1034 OutStreamer->EmitIntValue(R_0286E8_SPI_TMPRING_SIZE, 4);
1035 OutStreamer->EmitIntValue(
1036 S_0286E8_WAVESIZE(CurrentProgramInfo.ScratchBlocks), 4);
1039 if (MF.getFunction().getCallingConv() == CallingConv::AMDGPU_PS) {
1040 OutStreamer->EmitIntValue(R_00B02C_SPI_SHADER_PGM_RSRC2_PS, 4);
1041 OutStreamer->EmitIntValue(S_00B02C_EXTRA_LDS_SIZE(CurrentProgramInfo.LDSBlocks), 4);
1042 OutStreamer->EmitIntValue(R_0286CC_SPI_PS_INPUT_ENA, 4);
1043 OutStreamer->EmitIntValue(MFI->getPSInputEnable(), 4);
1044 OutStreamer->EmitIntValue(R_0286D0_SPI_PS_INPUT_ADDR, 4);
1045 OutStreamer->EmitIntValue(MFI->getPSInputAddr(), 4);
1048 OutStreamer->EmitIntValue(R_SPILLED_SGPRS, 4);
1049 OutStreamer->EmitIntValue(MFI->getNumSpilledSGPRs(), 4);
1050 OutStreamer->EmitIntValue(R_SPILLED_VGPRS, 4);
1051 OutStreamer->EmitIntValue(MFI->getNumSpilledVGPRs(), 4);
1054 // This is the equivalent of EmitProgramInfoSI above, but for when the OS type
1055 // is AMDPAL. It stores each compute/SPI register setting and other PAL
1056 // metadata items into the PALMD::Metadata, combining with any provided by the
1057 // frontend as LLVM metadata. Once all functions are written, the PAL metadata
1058 // is then written as a single block in the .note section.
1059 void AMDGPUAsmPrinter::EmitPALMetadata(const MachineFunction &MF,
1060 const SIProgramInfo &CurrentProgramInfo) {
1061 const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1062 auto CC = MF.getFunction().getCallingConv();
1063 auto MD = getTargetStreamer()->getPALMetadata();
1065 MD->setEntryPoint(CC, MF.getFunction().getName());
1066 MD->setNumUsedVgprs(CC, CurrentProgramInfo.NumVGPRsForWavesPerEU);
1067 MD->setNumUsedSgprs(CC, CurrentProgramInfo.NumSGPRsForWavesPerEU);
1068 if (AMDGPU::isCompute(MF.getFunction().getCallingConv())) {
1069 MD->setRsrc1(CC, CurrentProgramInfo.ComputePGMRSrc1);
1070 MD->setRsrc2(CC, CurrentProgramInfo.ComputePGMRSrc2);
1072 MD->setRsrc1(CC, S_00B028_VGPRS(CurrentProgramInfo.VGPRBlocks) |
1073 S_00B028_SGPRS(CurrentProgramInfo.SGPRBlocks));
1074 if (CurrentProgramInfo.ScratchBlocks > 0)
1075 MD->setRsrc2(CC, S_00B84C_SCRATCH_EN(1));
1077 // ScratchSize is in bytes, 16 aligned.
1078 MD->setScratchSize(CC, alignTo(CurrentProgramInfo.ScratchSize, 16));
1079 if (MF.getFunction().getCallingConv() == CallingConv::AMDGPU_PS) {
1080 MD->setRsrc2(CC, S_00B02C_EXTRA_LDS_SIZE(CurrentProgramInfo.LDSBlocks));
1081 MD->setSpiPsInputEna(MFI->getPSInputEnable());
1082 MD->setSpiPsInputAddr(MFI->getPSInputAddr());
1086 // This is supposed to be log2(Size)
1087 static amd_element_byte_size_t getElementByteSizeValue(unsigned Size) {
1090 return AMD_ELEMENT_4_BYTES;
1092 return AMD_ELEMENT_8_BYTES;
1094 return AMD_ELEMENT_16_BYTES;
1096 llvm_unreachable("invalid private_element_size");
1100 void AMDGPUAsmPrinter::getAmdKernelCode(amd_kernel_code_t &Out,
1101 const SIProgramInfo &CurrentProgramInfo,
1102 const MachineFunction &MF) const {
1103 const Function &F = MF.getFunction();
1104 assert(F.getCallingConv() == CallingConv::AMDGPU_KERNEL ||
1105 F.getCallingConv() == CallingConv::SPIR_KERNEL);
1107 const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
1108 const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
1110 AMDGPU::initDefaultAMDKernelCodeT(Out, &STM);
1112 Out.compute_pgm_resource_registers =
1113 CurrentProgramInfo.ComputePGMRSrc1 |
1114 (CurrentProgramInfo.ComputePGMRSrc2 << 32);
1115 Out.code_properties |= AMD_CODE_PROPERTY_IS_PTR64;
1117 if (CurrentProgramInfo.DynamicCallStack)
1118 Out.code_properties |= AMD_CODE_PROPERTY_IS_DYNAMIC_CALLSTACK;
1120 AMD_HSA_BITS_SET(Out.code_properties,
1121 AMD_CODE_PROPERTY_PRIVATE_ELEMENT_SIZE,
1122 getElementByteSizeValue(STM.getMaxPrivateElementSize()));
1124 if (MFI->hasPrivateSegmentBuffer()) {
1125 Out.code_properties |=
1126 AMD_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER;
1129 if (MFI->hasDispatchPtr())
1130 Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR;
1132 if (MFI->hasQueuePtr())
1133 Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR;
1135 if (MFI->hasKernargSegmentPtr())
1136 Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR;
1138 if (MFI->hasDispatchID())
1139 Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID;
1141 if (MFI->hasFlatScratchInit())
1142 Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT;
1144 if (MFI->hasDispatchPtr())
1145 Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR;
1147 if (STM.isXNACKEnabled())
1148 Out.code_properties |= AMD_CODE_PROPERTY_IS_XNACK_SUPPORTED;
1150 unsigned MaxKernArgAlign;
1151 Out.kernarg_segment_byte_size = STM.getKernArgSegmentSize(F, MaxKernArgAlign);
1152 Out.wavefront_sgpr_count = CurrentProgramInfo.NumSGPR;
1153 Out.workitem_vgpr_count = CurrentProgramInfo.NumVGPR;
1154 Out.workitem_private_segment_byte_size = CurrentProgramInfo.ScratchSize;
1155 Out.workgroup_group_segment_byte_size = CurrentProgramInfo.LDSSize;
1157 // These alignment values are specified in powers of two, so alignment =
1158 // 2^n. The minimum alignment is 2^4 = 16.
1159 Out.kernarg_segment_alignment = std::max<size_t>(4,
1160 countTrailingZeros(MaxKernArgAlign));
1163 bool AMDGPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
1164 const char *ExtraCode, raw_ostream &O) {
1165 // First try the generic code, which knows about modifiers like 'c' and 'n'.
1166 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O))
1169 if (ExtraCode && ExtraCode[0]) {
1170 if (ExtraCode[1] != 0)
1171 return true; // Unknown modifier.
1173 switch (ExtraCode[0]) {
1181 // TODO: Should be able to support other operand types like globals.
1182 const MachineOperand &MO = MI->getOperand(OpNo);
1184 AMDGPUInstPrinter::printRegOperand(MO.getReg(), O,
1185 *MF->getSubtarget().getRegisterInfo());