18f0fd8f6SDimitry Andric //===-- AMDGPUAsmPrinter.cpp - AMDGPU Assebly printer --------------------===// 28f0fd8f6SDimitry Andric // 38f0fd8f6SDimitry Andric // The LLVM Compiler Infrastructure 48f0fd8f6SDimitry Andric // 58f0fd8f6SDimitry Andric // This file is distributed under the University of Illinois Open Source 68f0fd8f6SDimitry Andric // License. See LICENSE.TXT for details. 78f0fd8f6SDimitry Andric // 88f0fd8f6SDimitry Andric //===----------------------------------------------------------------------===// 98f0fd8f6SDimitry Andric // 108f0fd8f6SDimitry Andric /// \file 118f0fd8f6SDimitry Andric /// 128f0fd8f6SDimitry Andric /// The AMDGPUAsmPrinter is used to print both assembly string and also binary 138f0fd8f6SDimitry Andric /// code. When passed an MCAsmStreamer it prints assembly and when passed 148f0fd8f6SDimitry Andric /// an MCObjectStreamer it outputs binary code. 158f0fd8f6SDimitry Andric // 168f0fd8f6SDimitry Andric //===----------------------------------------------------------------------===// 178f0fd8f6SDimitry Andric // 188f0fd8f6SDimitry Andric 198f0fd8f6SDimitry Andric #include "AMDGPUAsmPrinter.h" 207a7e6055SDimitry Andric #include "AMDGPUTargetMachine.h" 213dac3a9bSDimitry Andric #include "MCTargetDesc/AMDGPUTargetStreamer.h" 228f0fd8f6SDimitry Andric #include "InstPrinter/AMDGPUInstPrinter.h" 233dac3a9bSDimitry Andric #include "Utils/AMDGPUBaseInfo.h" 248f0fd8f6SDimitry Andric #include "AMDGPU.h" 258f0fd8f6SDimitry Andric #include "AMDGPUSubtarget.h" 268f0fd8f6SDimitry Andric #include "R600Defines.h" 278f0fd8f6SDimitry Andric #include "R600MachineFunctionInfo.h" 288f0fd8f6SDimitry Andric #include "R600RegisterInfo.h" 298f0fd8f6SDimitry Andric #include "SIDefines.h" 308f0fd8f6SDimitry Andric #include "SIMachineFunctionInfo.h" 313ca95b02SDimitry Andric #include "SIInstrInfo.h" 328f0fd8f6SDimitry Andric #include "SIRegisterInfo.h" 338f0fd8f6SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 343ca95b02SDimitry Andric #include "llvm/IR/DiagnosticInfo.h" 358f0fd8f6SDimitry Andric #include "llvm/MC/MCContext.h" 368f0fd8f6SDimitry Andric #include "llvm/MC/MCSectionELF.h" 378f0fd8f6SDimitry Andric #include "llvm/MC/MCStreamer.h" 388f0fd8f6SDimitry Andric #include "llvm/Support/ELF.h" 398f0fd8f6SDimitry Andric #include "llvm/Support/MathExtras.h" 408f0fd8f6SDimitry Andric #include "llvm/Support/TargetRegistry.h" 418f0fd8f6SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h" 428f0fd8f6SDimitry Andric 438f0fd8f6SDimitry Andric using namespace llvm; 448f0fd8f6SDimitry Andric 458f0fd8f6SDimitry Andric // TODO: This should get the default rounding mode from the kernel. We just set 468f0fd8f6SDimitry Andric // the default here, but this could change if the OpenCL rounding mode pragmas 478f0fd8f6SDimitry Andric // are used. 488f0fd8f6SDimitry Andric // 498f0fd8f6SDimitry Andric // The denormal mode here should match what is reported by the OpenCL runtime 508f0fd8f6SDimitry Andric // for the CL_FP_DENORM bit from CL_DEVICE_{HALF|SINGLE|DOUBLE}_FP_CONFIG, but 518f0fd8f6SDimitry Andric // can also be override to flush with the -cl-denorms-are-zero compiler flag. 528f0fd8f6SDimitry Andric // 538f0fd8f6SDimitry Andric // AMD OpenCL only sets flush none and reports CL_FP_DENORM for double 548f0fd8f6SDimitry Andric // precision, and leaves single precision to flush all and does not report 558f0fd8f6SDimitry Andric // CL_FP_DENORM for CL_DEVICE_SINGLE_FP_CONFIG. Mesa's OpenCL currently reports 568f0fd8f6SDimitry Andric // CL_FP_DENORM for both. 578f0fd8f6SDimitry Andric // 588f0fd8f6SDimitry Andric // FIXME: It seems some instructions do not support single precision denormals 598f0fd8f6SDimitry Andric // regardless of the mode (exp_*_f32, rcp_*_f32, rsq_*_f32, rsq_*f32, sqrt_f32, 608f0fd8f6SDimitry Andric // and sin_f32, cos_f32 on most parts). 618f0fd8f6SDimitry Andric 628f0fd8f6SDimitry Andric // We want to use these instructions, and using fp32 denormals also causes 638f0fd8f6SDimitry Andric // instructions to run at the double precision rate for the device so it's 648f0fd8f6SDimitry Andric // probably best to just report no single precision denormals. 658f0fd8f6SDimitry Andric static uint32_t getFPMode(const MachineFunction &F) { 663ca95b02SDimitry Andric const SISubtarget& ST = F.getSubtarget<SISubtarget>(); 678f0fd8f6SDimitry Andric // TODO: Is there any real use for the flush in only / flush out only modes? 688f0fd8f6SDimitry Andric 698f0fd8f6SDimitry Andric uint32_t FP32Denormals = 708f0fd8f6SDimitry Andric ST.hasFP32Denormals() ? FP_DENORM_FLUSH_NONE : FP_DENORM_FLUSH_IN_FLUSH_OUT; 718f0fd8f6SDimitry Andric 728f0fd8f6SDimitry Andric uint32_t FP64Denormals = 738f0fd8f6SDimitry Andric ST.hasFP64Denormals() ? FP_DENORM_FLUSH_NONE : FP_DENORM_FLUSH_IN_FLUSH_OUT; 748f0fd8f6SDimitry Andric 758f0fd8f6SDimitry Andric return FP_ROUND_MODE_SP(FP_ROUND_ROUND_TO_NEAREST) | 768f0fd8f6SDimitry Andric FP_ROUND_MODE_DP(FP_ROUND_ROUND_TO_NEAREST) | 778f0fd8f6SDimitry Andric FP_DENORM_MODE_SP(FP32Denormals) | 788f0fd8f6SDimitry Andric FP_DENORM_MODE_DP(FP64Denormals); 798f0fd8f6SDimitry Andric } 808f0fd8f6SDimitry Andric 818f0fd8f6SDimitry Andric static AsmPrinter * 828f0fd8f6SDimitry Andric createAMDGPUAsmPrinterPass(TargetMachine &tm, 838f0fd8f6SDimitry Andric std::unique_ptr<MCStreamer> &&Streamer) { 848f0fd8f6SDimitry Andric return new AMDGPUAsmPrinter(tm, std::move(Streamer)); 858f0fd8f6SDimitry Andric } 868f0fd8f6SDimitry Andric 878f0fd8f6SDimitry Andric extern "C" void LLVMInitializeAMDGPUAsmPrinter() { 88d88c1a5aSDimitry Andric TargetRegistry::RegisterAsmPrinter(getTheAMDGPUTarget(), 89d88c1a5aSDimitry Andric createAMDGPUAsmPrinterPass); 90d88c1a5aSDimitry Andric TargetRegistry::RegisterAsmPrinter(getTheGCNTarget(), 91d88c1a5aSDimitry Andric createAMDGPUAsmPrinterPass); 928f0fd8f6SDimitry Andric } 938f0fd8f6SDimitry Andric 948f0fd8f6SDimitry Andric AMDGPUAsmPrinter::AMDGPUAsmPrinter(TargetMachine &TM, 958f0fd8f6SDimitry Andric std::unique_ptr<MCStreamer> Streamer) 967a7e6055SDimitry Andric : AsmPrinter(TM, std::move(Streamer)) { 977a7e6055SDimitry Andric AMDGPUASI = static_cast<AMDGPUTargetMachine*>(&TM)->getAMDGPUAS(); 987a7e6055SDimitry Andric } 998f0fd8f6SDimitry Andric 100d88c1a5aSDimitry Andric StringRef AMDGPUAsmPrinter::getPassName() const { 101d88c1a5aSDimitry Andric return "AMDGPU Assembly Printer"; 102d88c1a5aSDimitry Andric } 103d88c1a5aSDimitry Andric 1047a7e6055SDimitry Andric const MCSubtargetInfo* AMDGPUAsmPrinter::getSTI() const { 1057a7e6055SDimitry Andric return TM.getMCSubtargetInfo(); 1067a7e6055SDimitry Andric } 1077a7e6055SDimitry Andric 1087a7e6055SDimitry Andric AMDGPUTargetStreamer& AMDGPUAsmPrinter::getTargetStreamer() const { 1097a7e6055SDimitry Andric return static_cast<AMDGPUTargetStreamer&>(*OutStreamer->getTargetStreamer()); 1107a7e6055SDimitry Andric } 1117a7e6055SDimitry Andric 112444ed5c5SDimitry Andric void AMDGPUAsmPrinter::EmitStartOfAsmFile(Module &M) { 113444ed5c5SDimitry Andric if (TM.getTargetTriple().getOS() != Triple::AMDHSA) 114444ed5c5SDimitry Andric return; 115444ed5c5SDimitry Andric 1167a7e6055SDimitry Andric AMDGPU::IsaInfo::IsaVersion ISA = 1177a7e6055SDimitry Andric AMDGPU::IsaInfo::getIsaVersion(getSTI()->getFeatureBits()); 118444ed5c5SDimitry Andric 1197a7e6055SDimitry Andric getTargetStreamer().EmitDirectiveHSACodeObjectVersion(2, 1); 1207a7e6055SDimitry Andric getTargetStreamer().EmitDirectiveHSACodeObjectISA( 1217a7e6055SDimitry Andric ISA.Major, ISA.Minor, ISA.Stepping, "AMD", "AMDGPU"); 1227a7e6055SDimitry Andric getTargetStreamer().EmitStartOfCodeObjectMetadata(M); 1237a7e6055SDimitry Andric } 124444ed5c5SDimitry Andric 1257a7e6055SDimitry Andric void AMDGPUAsmPrinter::EmitEndOfAsmFile(Module &M) { 1267a7e6055SDimitry Andric if (TM.getTargetTriple().getOS() != Triple::AMDHSA) 1277a7e6055SDimitry Andric return; 1283ca95b02SDimitry Andric 1297a7e6055SDimitry Andric getTargetStreamer().EmitEndOfCodeObjectMetadata(); 130444ed5c5SDimitry Andric } 131444ed5c5SDimitry Andric 132d88c1a5aSDimitry Andric bool AMDGPUAsmPrinter::isBlockOnlyReachableByFallthrough( 133d88c1a5aSDimitry Andric const MachineBasicBlock *MBB) const { 134d88c1a5aSDimitry Andric if (!AsmPrinter::isBlockOnlyReachableByFallthrough(MBB)) 135d88c1a5aSDimitry Andric return false; 136d88c1a5aSDimitry Andric 137d88c1a5aSDimitry Andric if (MBB->empty()) 138d88c1a5aSDimitry Andric return true; 139d88c1a5aSDimitry Andric 140d88c1a5aSDimitry Andric // If this is a block implementing a long branch, an expression relative to 141d88c1a5aSDimitry Andric // the start of the block is needed. to the start of the block. 142d88c1a5aSDimitry Andric // XXX - Is there a smarter way to check this? 143d88c1a5aSDimitry Andric return (MBB->back().getOpcode() != AMDGPU::S_SETPC_B64); 144d88c1a5aSDimitry Andric } 145d88c1a5aSDimitry Andric 1463dac3a9bSDimitry Andric void AMDGPUAsmPrinter::EmitFunctionBodyStart() { 1476bc11b14SDimitry Andric const AMDGPUMachineFunction *MFI = MF->getInfo<AMDGPUMachineFunction>(); 1486bc11b14SDimitry Andric if (!MFI->isEntryFunction()) 1496bc11b14SDimitry Andric return; 1506bc11b14SDimitry Andric 1513dac3a9bSDimitry Andric const AMDGPUSubtarget &STM = MF->getSubtarget<AMDGPUSubtarget>(); 1523dac3a9bSDimitry Andric SIProgramInfo KernelInfo; 1537a7e6055SDimitry Andric amd_kernel_code_t KernelCode; 15498221d2eSDimitry Andric if (STM.isAmdCodeObjectV2(*MF)) { 1553dac3a9bSDimitry Andric getSIProgramInfo(KernelInfo, *MF); 1567a7e6055SDimitry Andric getAmdKernelCode(KernelCode, KernelInfo, *MF); 1577a7e6055SDimitry Andric 1587a7e6055SDimitry Andric OutStreamer->SwitchSection(getObjFileLowering().getTextSection()); 1597a7e6055SDimitry Andric getTargetStreamer().EmitAMDKernelCodeT(KernelCode); 1603dac3a9bSDimitry Andric } 1617a7e6055SDimitry Andric 1627a7e6055SDimitry Andric if (TM.getTargetTriple().getOS() != Triple::AMDHSA) 1637a7e6055SDimitry Andric return; 1647a7e6055SDimitry Andric getTargetStreamer().EmitKernelCodeObjectMetadata(*MF->getFunction(), 1657a7e6055SDimitry Andric KernelCode); 1663dac3a9bSDimitry Andric } 1673dac3a9bSDimitry Andric 1687d523365SDimitry Andric void AMDGPUAsmPrinter::EmitFunctionEntryLabel() { 1697d523365SDimitry Andric const SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>(); 1707d523365SDimitry Andric const AMDGPUSubtarget &STM = MF->getSubtarget<AMDGPUSubtarget>(); 1717a7e6055SDimitry Andric if (MFI->isEntryFunction() && STM.isAmdCodeObjectV2(*MF)) { 172d88c1a5aSDimitry Andric SmallString<128> SymbolName; 173d88c1a5aSDimitry Andric getNameWithPrefix(SymbolName, MF->getFunction()), 1747a7e6055SDimitry Andric getTargetStreamer().EmitAMDGPUSymbolType( 1757a7e6055SDimitry Andric SymbolName, ELF::STT_AMDGPU_HSA_KERNEL); 1767d523365SDimitry Andric } 1778f0fd8f6SDimitry Andric 1787d523365SDimitry Andric AsmPrinter::EmitFunctionEntryLabel(); 1797d523365SDimitry Andric } 1807d523365SDimitry Andric 1817d523365SDimitry Andric void AMDGPUAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { 1827d523365SDimitry Andric 1837d523365SDimitry Andric // Group segment variables aren't emitted in HSA. 1847a7e6055SDimitry Andric if (AMDGPU::isGroupSegment(GV, AMDGPUASI)) 1857d523365SDimitry Andric return; 1867d523365SDimitry Andric 1873ca95b02SDimitry Andric AsmPrinter::EmitGlobalVariable(GV); 1888f0fd8f6SDimitry Andric } 1898f0fd8f6SDimitry Andric 1908f0fd8f6SDimitry Andric bool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) { 1916bc11b14SDimitry Andric const AMDGPUMachineFunction *MFI = MF.getInfo<AMDGPUMachineFunction>(); 1928f0fd8f6SDimitry Andric 1938f0fd8f6SDimitry Andric // The starting address of all shader programs must be 256 bytes aligned. 1946bc11b14SDimitry Andric // Regular functions just need the basic required instruction alignment. 1956bc11b14SDimitry Andric MF.setAlignment(MFI->isEntryFunction() ? 8 : 2); 1968f0fd8f6SDimitry Andric 1978f0fd8f6SDimitry Andric SetupMachineFunction(MF); 1988f0fd8f6SDimitry Andric 19995ec533aSDimitry Andric const AMDGPUSubtarget &STM = MF.getSubtarget<AMDGPUSubtarget>(); 2008f0fd8f6SDimitry Andric MCContext &Context = getObjFileLowering().getContext(); 20195ec533aSDimitry Andric if (!STM.isAmdHsaOS()) { 2028f0fd8f6SDimitry Andric MCSectionELF *ConfigSection = 2038f0fd8f6SDimitry Andric Context.getELFSection(".AMDGPU.config", ELF::SHT_PROGBITS, 0); 2048f0fd8f6SDimitry Andric OutStreamer->SwitchSection(ConfigSection); 20595ec533aSDimitry Andric } 2068f0fd8f6SDimitry Andric 2078f0fd8f6SDimitry Andric SIProgramInfo KernelInfo; 2083dac3a9bSDimitry Andric if (STM.getGeneration() >= AMDGPUSubtarget::SOUTHERN_ISLANDS) { 2098f0fd8f6SDimitry Andric getSIProgramInfo(KernelInfo, MF); 2107d523365SDimitry Andric if (!STM.isAmdHsaOS()) { 2118f0fd8f6SDimitry Andric EmitProgramInfoSI(MF, KernelInfo); 2123dac3a9bSDimitry Andric } 2138f0fd8f6SDimitry Andric } else { 2148f0fd8f6SDimitry Andric EmitProgramInfoR600(MF); 2158f0fd8f6SDimitry Andric } 2168f0fd8f6SDimitry Andric 2178f0fd8f6SDimitry Andric DisasmLines.clear(); 2188f0fd8f6SDimitry Andric HexLines.clear(); 2198f0fd8f6SDimitry Andric DisasmLineMaxLen = 0; 2208f0fd8f6SDimitry Andric 2218f0fd8f6SDimitry Andric EmitFunctionBody(); 2228f0fd8f6SDimitry Andric 2238f0fd8f6SDimitry Andric if (isVerbose()) { 2248f0fd8f6SDimitry Andric MCSectionELF *CommentSection = 2258f0fd8f6SDimitry Andric Context.getELFSection(".AMDGPU.csdata", ELF::SHT_PROGBITS, 0); 2268f0fd8f6SDimitry Andric OutStreamer->SwitchSection(CommentSection); 2278f0fd8f6SDimitry Andric 2288f0fd8f6SDimitry Andric if (STM.getGeneration() >= AMDGPUSubtarget::SOUTHERN_ISLANDS) { 2296bc11b14SDimitry Andric if (MFI->isEntryFunction()) { 2308f0fd8f6SDimitry Andric OutStreamer->emitRawComment(" Kernel info:", false); 2316bc11b14SDimitry Andric } else { 2326bc11b14SDimitry Andric OutStreamer->emitRawComment(" Function info:", false); 2336bc11b14SDimitry Andric } 2346bc11b14SDimitry Andric 2356bc11b14SDimitry Andric OutStreamer->emitRawComment(" codeLenInByte = " + 2366bc11b14SDimitry Andric Twine(getFunctionCodeSize(MF)), false); 2378f0fd8f6SDimitry Andric OutStreamer->emitRawComment(" NumSgprs: " + Twine(KernelInfo.NumSGPR), 2388f0fd8f6SDimitry Andric false); 2398f0fd8f6SDimitry Andric OutStreamer->emitRawComment(" NumVgprs: " + Twine(KernelInfo.NumVGPR), 2408f0fd8f6SDimitry Andric false); 2416bc11b14SDimitry Andric 2428f0fd8f6SDimitry Andric OutStreamer->emitRawComment(" FloatMode: " + Twine(KernelInfo.FloatMode), 2438f0fd8f6SDimitry Andric false); 2448f0fd8f6SDimitry Andric OutStreamer->emitRawComment(" IeeeMode: " + Twine(KernelInfo.IEEEMode), 2458f0fd8f6SDimitry Andric false); 2468f0fd8f6SDimitry Andric OutStreamer->emitRawComment(" ScratchSize: " + Twine(KernelInfo.ScratchSize), 2478f0fd8f6SDimitry Andric false); 2483ca95b02SDimitry Andric OutStreamer->emitRawComment(" LDSByteSize: " + Twine(KernelInfo.LDSSize) + 2493ca95b02SDimitry Andric " bytes/workgroup (compile time only)", false); 2503ca95b02SDimitry Andric 2516bc11b14SDimitry Andric if (!MFI->isEntryFunction()) 2526bc11b14SDimitry Andric return false; 2536bc11b14SDimitry Andric 254d88c1a5aSDimitry Andric OutStreamer->emitRawComment(" SGPRBlocks: " + 255d88c1a5aSDimitry Andric Twine(KernelInfo.SGPRBlocks), false); 256d88c1a5aSDimitry Andric OutStreamer->emitRawComment(" VGPRBlocks: " + 257d88c1a5aSDimitry Andric Twine(KernelInfo.VGPRBlocks), false); 258d88c1a5aSDimitry Andric 259d88c1a5aSDimitry Andric OutStreamer->emitRawComment(" NumSGPRsForWavesPerEU: " + 260d88c1a5aSDimitry Andric Twine(KernelInfo.NumSGPRsForWavesPerEU), false); 261d88c1a5aSDimitry Andric OutStreamer->emitRawComment(" NumVGPRsForWavesPerEU: " + 262d88c1a5aSDimitry Andric Twine(KernelInfo.NumVGPRsForWavesPerEU), false); 263d88c1a5aSDimitry Andric 2643ca95b02SDimitry Andric OutStreamer->emitRawComment(" ReservedVGPRFirst: " + Twine(KernelInfo.ReservedVGPRFirst), 2653ca95b02SDimitry Andric false); 2663ca95b02SDimitry Andric OutStreamer->emitRawComment(" ReservedVGPRCount: " + Twine(KernelInfo.ReservedVGPRCount), 2673ca95b02SDimitry Andric false); 2683ca95b02SDimitry Andric 2693ca95b02SDimitry Andric if (MF.getSubtarget<SISubtarget>().debuggerEmitPrologue()) { 2703ca95b02SDimitry Andric OutStreamer->emitRawComment(" DebuggerWavefrontPrivateSegmentOffsetSGPR: s" + 2713ca95b02SDimitry Andric Twine(KernelInfo.DebuggerWavefrontPrivateSegmentOffsetSGPR), false); 2723ca95b02SDimitry Andric OutStreamer->emitRawComment(" DebuggerPrivateSegmentBufferSGPR: s" + 2733ca95b02SDimitry Andric Twine(KernelInfo.DebuggerPrivateSegmentBufferSGPR), false); 2743ca95b02SDimitry Andric } 2757d523365SDimitry Andric 2767d523365SDimitry Andric OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:USER_SGPR: " + 2777d523365SDimitry Andric Twine(G_00B84C_USER_SGPR(KernelInfo.ComputePGMRSrc2)), 2787d523365SDimitry Andric false); 2797a7e6055SDimitry Andric OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TRAP_HANDLER: " + 2807a7e6055SDimitry Andric Twine(G_00B84C_TRAP_HANDLER(KernelInfo.ComputePGMRSrc2)), 2817a7e6055SDimitry Andric false); 2827d523365SDimitry Andric OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TGID_X_EN: " + 2837d523365SDimitry Andric Twine(G_00B84C_TGID_X_EN(KernelInfo.ComputePGMRSrc2)), 2847d523365SDimitry Andric false); 2857d523365SDimitry Andric OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TGID_Y_EN: " + 2867d523365SDimitry Andric Twine(G_00B84C_TGID_Y_EN(KernelInfo.ComputePGMRSrc2)), 2877d523365SDimitry Andric false); 2887d523365SDimitry Andric OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TGID_Z_EN: " + 2897d523365SDimitry Andric Twine(G_00B84C_TGID_Z_EN(KernelInfo.ComputePGMRSrc2)), 2907d523365SDimitry Andric false); 2917d523365SDimitry Andric OutStreamer->emitRawComment(" COMPUTE_PGM_RSRC2:TIDIG_COMP_CNT: " + 2927d523365SDimitry Andric Twine(G_00B84C_TIDIG_COMP_CNT(KernelInfo.ComputePGMRSrc2)), 2937d523365SDimitry Andric false); 2947d523365SDimitry Andric 2958f0fd8f6SDimitry Andric } else { 2968f0fd8f6SDimitry Andric R600MachineFunctionInfo *MFI = MF.getInfo<R600MachineFunctionInfo>(); 2978f0fd8f6SDimitry Andric OutStreamer->emitRawComment( 298d88c1a5aSDimitry Andric Twine("SQ_PGM_RESOURCES:STACK_SIZE = " + Twine(MFI->CFStackSize))); 2998f0fd8f6SDimitry Andric } 3008f0fd8f6SDimitry Andric } 3018f0fd8f6SDimitry Andric 3028f0fd8f6SDimitry Andric if (STM.dumpCode()) { 3038f0fd8f6SDimitry Andric 3048f0fd8f6SDimitry Andric OutStreamer->SwitchSection( 3058f0fd8f6SDimitry Andric Context.getELFSection(".AMDGPU.disasm", ELF::SHT_NOTE, 0)); 3068f0fd8f6SDimitry Andric 3078f0fd8f6SDimitry Andric for (size_t i = 0; i < DisasmLines.size(); ++i) { 3088f0fd8f6SDimitry Andric std::string Comment(DisasmLineMaxLen - DisasmLines[i].size(), ' '); 3098f0fd8f6SDimitry Andric Comment += " ; " + HexLines[i] + "\n"; 3108f0fd8f6SDimitry Andric 3118f0fd8f6SDimitry Andric OutStreamer->EmitBytes(StringRef(DisasmLines[i])); 3128f0fd8f6SDimitry Andric OutStreamer->EmitBytes(StringRef(Comment)); 3138f0fd8f6SDimitry Andric } 3148f0fd8f6SDimitry Andric } 3158f0fd8f6SDimitry Andric 3168f0fd8f6SDimitry Andric return false; 3178f0fd8f6SDimitry Andric } 3188f0fd8f6SDimitry Andric 3198f0fd8f6SDimitry Andric void AMDGPUAsmPrinter::EmitProgramInfoR600(const MachineFunction &MF) { 3208f0fd8f6SDimitry Andric unsigned MaxGPR = 0; 3218f0fd8f6SDimitry Andric bool killPixel = false; 3223ca95b02SDimitry Andric const R600Subtarget &STM = MF.getSubtarget<R600Subtarget>(); 3233ca95b02SDimitry Andric const R600RegisterInfo *RI = STM.getRegisterInfo(); 3248f0fd8f6SDimitry Andric const R600MachineFunctionInfo *MFI = MF.getInfo<R600MachineFunctionInfo>(); 3258f0fd8f6SDimitry Andric 3268f0fd8f6SDimitry Andric for (const MachineBasicBlock &MBB : MF) { 3278f0fd8f6SDimitry Andric for (const MachineInstr &MI : MBB) { 3288f0fd8f6SDimitry Andric if (MI.getOpcode() == AMDGPU::KILLGT) 3298f0fd8f6SDimitry Andric killPixel = true; 3308f0fd8f6SDimitry Andric unsigned numOperands = MI.getNumOperands(); 3318f0fd8f6SDimitry Andric for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) { 3328f0fd8f6SDimitry Andric const MachineOperand &MO = MI.getOperand(op_idx); 3338f0fd8f6SDimitry Andric if (!MO.isReg()) 3348f0fd8f6SDimitry Andric continue; 3356bc11b14SDimitry Andric unsigned HWReg = RI->getHWRegIndex(MO.getReg()); 3368f0fd8f6SDimitry Andric 3378f0fd8f6SDimitry Andric // Register with value > 127 aren't GPR 3388f0fd8f6SDimitry Andric if (HWReg > 127) 3398f0fd8f6SDimitry Andric continue; 3408f0fd8f6SDimitry Andric MaxGPR = std::max(MaxGPR, HWReg); 3418f0fd8f6SDimitry Andric } 3428f0fd8f6SDimitry Andric } 3438f0fd8f6SDimitry Andric } 3448f0fd8f6SDimitry Andric 3458f0fd8f6SDimitry Andric unsigned RsrcReg; 3463ca95b02SDimitry Andric if (STM.getGeneration() >= R600Subtarget::EVERGREEN) { 3478f0fd8f6SDimitry Andric // Evergreen / Northern Islands 3483ca95b02SDimitry Andric switch (MF.getFunction()->getCallingConv()) { 349d88c1a5aSDimitry Andric default: LLVM_FALLTHROUGH; 3503ca95b02SDimitry Andric case CallingConv::AMDGPU_CS: RsrcReg = R_0288D4_SQ_PGM_RESOURCES_LS; break; 3513ca95b02SDimitry Andric case CallingConv::AMDGPU_GS: RsrcReg = R_028878_SQ_PGM_RESOURCES_GS; break; 3523ca95b02SDimitry Andric case CallingConv::AMDGPU_PS: RsrcReg = R_028844_SQ_PGM_RESOURCES_PS; break; 3533ca95b02SDimitry Andric case CallingConv::AMDGPU_VS: RsrcReg = R_028860_SQ_PGM_RESOURCES_VS; break; 3548f0fd8f6SDimitry Andric } 3558f0fd8f6SDimitry Andric } else { 3568f0fd8f6SDimitry Andric // R600 / R700 3573ca95b02SDimitry Andric switch (MF.getFunction()->getCallingConv()) { 358d88c1a5aSDimitry Andric default: LLVM_FALLTHROUGH; 359d88c1a5aSDimitry Andric case CallingConv::AMDGPU_GS: LLVM_FALLTHROUGH; 360d88c1a5aSDimitry Andric case CallingConv::AMDGPU_CS: LLVM_FALLTHROUGH; 3613ca95b02SDimitry Andric case CallingConv::AMDGPU_VS: RsrcReg = R_028868_SQ_PGM_RESOURCES_VS; break; 3623ca95b02SDimitry Andric case CallingConv::AMDGPU_PS: RsrcReg = R_028850_SQ_PGM_RESOURCES_PS; break; 3638f0fd8f6SDimitry Andric } 3648f0fd8f6SDimitry Andric } 3658f0fd8f6SDimitry Andric 3668f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(RsrcReg, 4); 3678f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(S_NUM_GPRS(MaxGPR + 1) | 368d88c1a5aSDimitry Andric S_STACK_SIZE(MFI->CFStackSize), 4); 3698f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(R_02880C_DB_SHADER_CONTROL, 4); 3708f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(S_02880C_KILL_ENABLE(killPixel), 4); 3718f0fd8f6SDimitry Andric 3723ca95b02SDimitry Andric if (AMDGPU::isCompute(MF.getFunction()->getCallingConv())) { 3738f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(R_0288E8_SQ_LDS_ALLOC, 4); 374d88c1a5aSDimitry Andric OutStreamer->EmitIntValue(alignTo(MFI->getLDSSize(), 4) >> 2, 4); 3758f0fd8f6SDimitry Andric } 3768f0fd8f6SDimitry Andric } 3778f0fd8f6SDimitry Andric 3786bc11b14SDimitry Andric uint64_t AMDGPUAsmPrinter::getFunctionCodeSize(const MachineFunction &MF) const { 3793ca95b02SDimitry Andric const SISubtarget &STM = MF.getSubtarget<SISubtarget>(); 3803ca95b02SDimitry Andric const SIInstrInfo *TII = STM.getInstrInfo(); 3818f0fd8f6SDimitry Andric 3826bc11b14SDimitry Andric uint64_t CodeSize = 0; 3836bc11b14SDimitry Andric 3848f0fd8f6SDimitry Andric for (const MachineBasicBlock &MBB : MF) { 3858f0fd8f6SDimitry Andric for (const MachineInstr &MI : MBB) { 3868f0fd8f6SDimitry Andric // TODO: CodeSize should account for multiple functions. 3879a4b3118SDimitry Andric 3889a4b3118SDimitry Andric // TODO: Should we count size of debug info? 3899a4b3118SDimitry Andric if (MI.isDebugValue()) 3909a4b3118SDimitry Andric continue; 3919a4b3118SDimitry Andric 3923ca95b02SDimitry Andric CodeSize += TII->getInstSizeInBytes(MI); 3936bc11b14SDimitry Andric } 3946bc11b14SDimitry Andric } 3958f0fd8f6SDimitry Andric 3966bc11b14SDimitry Andric return CodeSize; 3976bc11b14SDimitry Andric } 3988f0fd8f6SDimitry Andric 3996bc11b14SDimitry Andric static bool hasAnyNonFlatUseOfReg(const MachineRegisterInfo &MRI, 4006bc11b14SDimitry Andric const SIInstrInfo &TII, 4016bc11b14SDimitry Andric unsigned Reg) { 4026bc11b14SDimitry Andric for (const MachineOperand &UseOp : MRI.reg_operands(Reg)) { 4036bc11b14SDimitry Andric if (!UseOp.isImplicit() || !TII.isFLAT(*UseOp.getParent())) 4046bc11b14SDimitry Andric return true; 4056bc11b14SDimitry Andric } 4068f0fd8f6SDimitry Andric 4076bc11b14SDimitry Andric return false; 4086bc11b14SDimitry Andric } 4097d523365SDimitry Andric 4106bc11b14SDimitry Andric void AMDGPUAsmPrinter::getSIProgramInfo(SIProgramInfo &ProgInfo, 4116bc11b14SDimitry Andric const MachineFunction &MF) const { 4126bc11b14SDimitry Andric const SISubtarget &STM = MF.getSubtarget<SISubtarget>(); 4136bc11b14SDimitry Andric const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>(); 4146bc11b14SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo(); 4156bc11b14SDimitry Andric const SIInstrInfo *TII = STM.getInstrInfo(); 4166bc11b14SDimitry Andric const SIRegisterInfo *RI = &TII->getRegisterInfo(); 4177d523365SDimitry Andric 4187d523365SDimitry Andric 4196bc11b14SDimitry Andric MCPhysReg NumVGPRReg = AMDGPU::NoRegister; 4206bc11b14SDimitry Andric for (MCPhysReg Reg : reverse(AMDGPU::VGPR_32RegClass.getRegisters())) { 4216bc11b14SDimitry Andric if (MRI.isPhysRegUsed(Reg)) { 4226bc11b14SDimitry Andric NumVGPRReg = Reg; 4237d523365SDimitry Andric break; 4248f0fd8f6SDimitry Andric } 4256bc11b14SDimitry Andric } 4268f0fd8f6SDimitry Andric 4276bc11b14SDimitry Andric MCPhysReg NumSGPRReg = AMDGPU::NoRegister; 4286bc11b14SDimitry Andric for (MCPhysReg Reg : reverse(AMDGPU::SGPR_32RegClass.getRegisters())) { 4296bc11b14SDimitry Andric if (MRI.isPhysRegUsed(Reg)) { 4306bc11b14SDimitry Andric NumSGPRReg = Reg; 4316bc11b14SDimitry Andric break; 4328f0fd8f6SDimitry Andric } 4338f0fd8f6SDimitry Andric } 4348f0fd8f6SDimitry Andric 4356bc11b14SDimitry Andric // We found the maximum register index. They start at 0, so add one to get the 4366bc11b14SDimitry Andric // number of registers. 4376bc11b14SDimitry Andric ProgInfo.NumVGPR = NumVGPRReg == AMDGPU::NoRegister ? 0 : 4386bc11b14SDimitry Andric RI->getHWRegIndex(NumVGPRReg) + 1; 4396bc11b14SDimitry Andric ProgInfo.NumSGPR = NumSGPRReg == AMDGPU::NoRegister ? 0 : 4406bc11b14SDimitry Andric RI->getHWRegIndex(NumSGPRReg) + 1; 441444ed5c5SDimitry Andric unsigned ExtraSGPRs = 0; 442444ed5c5SDimitry Andric 4436bc11b14SDimitry Andric ProgInfo.VCCUsed = MRI.isPhysRegUsed(AMDGPU::VCC_LO) || 4446bc11b14SDimitry Andric MRI.isPhysRegUsed(AMDGPU::VCC_HI); 4456bc11b14SDimitry Andric if (ProgInfo.VCCUsed) 446444ed5c5SDimitry Andric ExtraSGPRs = 2; 447444ed5c5SDimitry Andric 4486bc11b14SDimitry Andric ProgInfo.FlatUsed = MRI.isPhysRegUsed(AMDGPU::FLAT_SCR_LO) || 4496bc11b14SDimitry Andric MRI.isPhysRegUsed(AMDGPU::FLAT_SCR_HI); 4506bc11b14SDimitry Andric 4516bc11b14SDimitry Andric // Even if FLAT_SCRATCH is implicitly used, it has no effect if flat 4526bc11b14SDimitry Andric // instructions aren't used to access the scratch buffer. Inline assembly 4536bc11b14SDimitry Andric // may need it though. 4546bc11b14SDimitry Andric // 4556bc11b14SDimitry Andric // If we only have implicit uses of flat_scr on flat instructions, it is not 4566bc11b14SDimitry Andric // really needed. 4576bc11b14SDimitry Andric if (ProgInfo.FlatUsed && !MFI->hasFlatScratchInit() && 4586bc11b14SDimitry Andric (!hasAnyNonFlatUseOfReg(MRI, *TII, AMDGPU::FLAT_SCR) && 4596bc11b14SDimitry Andric !hasAnyNonFlatUseOfReg(MRI, *TII, AMDGPU::FLAT_SCR_LO) && 4606bc11b14SDimitry Andric !hasAnyNonFlatUseOfReg(MRI, *TII, AMDGPU::FLAT_SCR_HI))) { 4616bc11b14SDimitry Andric ProgInfo.FlatUsed = false; 4626bc11b14SDimitry Andric } 4636bc11b14SDimitry Andric 4643ca95b02SDimitry Andric if (STM.getGeneration() < SISubtarget::VOLCANIC_ISLANDS) { 4656bc11b14SDimitry Andric if (ProgInfo.FlatUsed) 466444ed5c5SDimitry Andric ExtraSGPRs = 4; 467444ed5c5SDimitry Andric } else { 468444ed5c5SDimitry Andric if (STM.isXNACKEnabled()) 469444ed5c5SDimitry Andric ExtraSGPRs = 4; 4708f0fd8f6SDimitry Andric 4716bc11b14SDimitry Andric if (ProgInfo.FlatUsed) 472444ed5c5SDimitry Andric ExtraSGPRs = 6; 4737d523365SDimitry Andric } 4748f0fd8f6SDimitry Andric 4757a7e6055SDimitry Andric unsigned ExtraVGPRs = STM.getReservedNumVGPRs(MF); 4763ca95b02SDimitry Andric 477d88c1a5aSDimitry Andric // Check the addressable register limit before we add ExtraSGPRs. 478d88c1a5aSDimitry Andric if (STM.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS && 479d88c1a5aSDimitry Andric !STM.hasSGPRInitBug()) { 4807a7e6055SDimitry Andric unsigned MaxAddressableNumSGPRs = STM.getAddressableNumSGPRs(); 4816bc11b14SDimitry Andric if (ProgInfo.NumSGPR > MaxAddressableNumSGPRs) { 482d88c1a5aSDimitry Andric // This can happen due to a compiler bug or when using inline asm. 483d88c1a5aSDimitry Andric LLVMContext &Ctx = MF.getFunction()->getContext(); 484d88c1a5aSDimitry Andric DiagnosticInfoResourceLimit Diag(*MF.getFunction(), 485d88c1a5aSDimitry Andric "addressable scalar registers", 4866bc11b14SDimitry Andric ProgInfo.NumSGPR, DS_Error, 4877a7e6055SDimitry Andric DK_ResourceLimit, 4887a7e6055SDimitry Andric MaxAddressableNumSGPRs); 489d88c1a5aSDimitry Andric Ctx.diagnose(Diag); 4906bc11b14SDimitry Andric ProgInfo.NumSGPR = MaxAddressableNumSGPRs - 1; 491d88c1a5aSDimitry Andric } 492d88c1a5aSDimitry Andric } 493d88c1a5aSDimitry Andric 494d88c1a5aSDimitry Andric // Account for extra SGPRs and VGPRs reserved for debugger use. 4956bc11b14SDimitry Andric ProgInfo.NumSGPR += ExtraSGPRs; 4966bc11b14SDimitry Andric ProgInfo.NumVGPR += ExtraVGPRs; 4978f0fd8f6SDimitry Andric 498d88c1a5aSDimitry Andric // Adjust number of registers used to meet default/requested minimum/maximum 499d88c1a5aSDimitry Andric // number of waves per execution unit request. 500d88c1a5aSDimitry Andric ProgInfo.NumSGPRsForWavesPerEU = std::max( 5016bc11b14SDimitry Andric std::max(ProgInfo.NumSGPR, 1u), STM.getMinNumSGPRs(MFI->getMaxWavesPerEU())); 502d88c1a5aSDimitry Andric ProgInfo.NumVGPRsForWavesPerEU = std::max( 5036bc11b14SDimitry Andric std::max(ProgInfo.NumVGPR, 1u), STM.getMinNumVGPRs(MFI->getMaxWavesPerEU())); 504d88c1a5aSDimitry Andric 505d88c1a5aSDimitry Andric if (STM.getGeneration() <= AMDGPUSubtarget::SEA_ISLANDS || 506d88c1a5aSDimitry Andric STM.hasSGPRInitBug()) { 5077a7e6055SDimitry Andric unsigned MaxAddressableNumSGPRs = STM.getAddressableNumSGPRs(); 5087a7e6055SDimitry Andric if (ProgInfo.NumSGPR > MaxAddressableNumSGPRs) { 5097a7e6055SDimitry Andric // This can happen due to a compiler bug or when using inline asm to use 5107a7e6055SDimitry Andric // the registers which are usually reserved for vcc etc. 5118f0fd8f6SDimitry Andric LLVMContext &Ctx = MF.getFunction()->getContext(); 5123ca95b02SDimitry Andric DiagnosticInfoResourceLimit Diag(*MF.getFunction(), 513d88c1a5aSDimitry Andric "scalar registers", 514d88c1a5aSDimitry Andric ProgInfo.NumSGPR, DS_Error, 5157a7e6055SDimitry Andric DK_ResourceLimit, 5167a7e6055SDimitry Andric MaxAddressableNumSGPRs); 5173ca95b02SDimitry Andric Ctx.diagnose(Diag); 5187a7e6055SDimitry Andric ProgInfo.NumSGPR = MaxAddressableNumSGPRs; 5197a7e6055SDimitry Andric ProgInfo.NumSGPRsForWavesPerEU = MaxAddressableNumSGPRs; 520d88c1a5aSDimitry Andric } 5218f0fd8f6SDimitry Andric } 5228f0fd8f6SDimitry Andric 523d88c1a5aSDimitry Andric if (STM.hasSGPRInitBug()) { 5247a7e6055SDimitry Andric ProgInfo.NumSGPR = 5257a7e6055SDimitry Andric AMDGPU::IsaInfo::FIXED_NUM_SGPRS_FOR_INIT_BUG; 5267a7e6055SDimitry Andric ProgInfo.NumSGPRsForWavesPerEU = 5277a7e6055SDimitry Andric AMDGPU::IsaInfo::FIXED_NUM_SGPRS_FOR_INIT_BUG; 5288f0fd8f6SDimitry Andric } 5298f0fd8f6SDimitry Andric 5306bc11b14SDimitry Andric if (MFI->getNumUserSGPRs() > STM.getMaxNumUserSGPRs()) { 5317d523365SDimitry Andric LLVMContext &Ctx = MF.getFunction()->getContext(); 5323ca95b02SDimitry Andric DiagnosticInfoResourceLimit Diag(*MF.getFunction(), "user SGPRs", 5336bc11b14SDimitry Andric MFI->getNumUserSGPRs(), DS_Error); 5343ca95b02SDimitry Andric Ctx.diagnose(Diag); 5353ca95b02SDimitry Andric } 5363ca95b02SDimitry Andric 537d88c1a5aSDimitry Andric if (MFI->getLDSSize() > static_cast<unsigned>(STM.getLocalMemorySize())) { 5383ca95b02SDimitry Andric LLVMContext &Ctx = MF.getFunction()->getContext(); 5393ca95b02SDimitry Andric DiagnosticInfoResourceLimit Diag(*MF.getFunction(), "local memory", 540d88c1a5aSDimitry Andric MFI->getLDSSize(), DS_Error); 5413ca95b02SDimitry Andric Ctx.diagnose(Diag); 5427d523365SDimitry Andric } 5437d523365SDimitry Andric 544d88c1a5aSDimitry Andric // SGPRBlocks is actual number of SGPR blocks minus 1. 545d88c1a5aSDimitry Andric ProgInfo.SGPRBlocks = alignTo(ProgInfo.NumSGPRsForWavesPerEU, 5467a7e6055SDimitry Andric STM.getSGPREncodingGranule()); 5477a7e6055SDimitry Andric ProgInfo.SGPRBlocks = ProgInfo.SGPRBlocks / STM.getSGPREncodingGranule() - 1; 548d88c1a5aSDimitry Andric 549d88c1a5aSDimitry Andric // VGPRBlocks is actual number of VGPR blocks minus 1. 550d88c1a5aSDimitry Andric ProgInfo.VGPRBlocks = alignTo(ProgInfo.NumVGPRsForWavesPerEU, 5517a7e6055SDimitry Andric STM.getVGPREncodingGranule()); 5527a7e6055SDimitry Andric ProgInfo.VGPRBlocks = ProgInfo.VGPRBlocks / STM.getVGPREncodingGranule() - 1; 5537a7e6055SDimitry Andric 5547a7e6055SDimitry Andric // Record first reserved VGPR and number of reserved VGPRs. 5556bc11b14SDimitry Andric ProgInfo.ReservedVGPRFirst = STM.debuggerReserveRegs() ? ProgInfo.NumVGPR : 0; 5567a7e6055SDimitry Andric ProgInfo.ReservedVGPRCount = STM.getReservedNumVGPRs(MF); 5577a7e6055SDimitry Andric 5587a7e6055SDimitry Andric // Update DebuggerWavefrontPrivateSegmentOffsetSGPR and 5597a7e6055SDimitry Andric // DebuggerPrivateSegmentBufferSGPR fields if "amdgpu-debugger-emit-prologue" 5607a7e6055SDimitry Andric // attribute was requested. 5617a7e6055SDimitry Andric if (STM.debuggerEmitPrologue()) { 5627a7e6055SDimitry Andric ProgInfo.DebuggerWavefrontPrivateSegmentOffsetSGPR = 5637a7e6055SDimitry Andric RI->getHWRegIndex(MFI->getScratchWaveOffsetReg()); 5647a7e6055SDimitry Andric ProgInfo.DebuggerPrivateSegmentBufferSGPR = 5657a7e6055SDimitry Andric RI->getHWRegIndex(MFI->getScratchRSrcReg()); 5667a7e6055SDimitry Andric } 567d88c1a5aSDimitry Andric 5688f0fd8f6SDimitry Andric // Set the value to initialize FP_ROUND and FP_DENORM parts of the mode 5698f0fd8f6SDimitry Andric // register. 5708f0fd8f6SDimitry Andric ProgInfo.FloatMode = getFPMode(MF); 5718f0fd8f6SDimitry Andric 572d88c1a5aSDimitry Andric ProgInfo.IEEEMode = STM.enableIEEEBit(MF); 5738f0fd8f6SDimitry Andric 5743ca95b02SDimitry Andric // Make clamp modifier on NaN input returns 0. 5757a7e6055SDimitry Andric ProgInfo.DX10Clamp = STM.enableDX10Clamp(); 5768f0fd8f6SDimitry Andric 577d88c1a5aSDimitry Andric const MachineFrameInfo &FrameInfo = MF.getFrameInfo(); 578d88c1a5aSDimitry Andric ProgInfo.ScratchSize = FrameInfo.getStackSize(); 5798f0fd8f6SDimitry Andric 5808f0fd8f6SDimitry Andric unsigned LDSAlignShift; 5813ca95b02SDimitry Andric if (STM.getGeneration() < SISubtarget::SEA_ISLANDS) { 5828f0fd8f6SDimitry Andric // LDS is allocated in 64 dword blocks. 5838f0fd8f6SDimitry Andric LDSAlignShift = 8; 5848f0fd8f6SDimitry Andric } else { 5858f0fd8f6SDimitry Andric // LDS is allocated in 128 dword blocks. 5868f0fd8f6SDimitry Andric LDSAlignShift = 9; 5878f0fd8f6SDimitry Andric } 5888f0fd8f6SDimitry Andric 589d88c1a5aSDimitry Andric unsigned LDSSpillSize = 5906bc11b14SDimitry Andric MFI->getLDSWaveSpillSize() * MFI->getMaxFlatWorkGroupSize(); 5918f0fd8f6SDimitry Andric 592d88c1a5aSDimitry Andric ProgInfo.LDSSize = MFI->getLDSSize() + LDSSpillSize; 5938f0fd8f6SDimitry Andric ProgInfo.LDSBlocks = 5943ca95b02SDimitry Andric alignTo(ProgInfo.LDSSize, 1ULL << LDSAlignShift) >> LDSAlignShift; 5958f0fd8f6SDimitry Andric 5968f0fd8f6SDimitry Andric // Scratch is allocated in 256 dword blocks. 5978f0fd8f6SDimitry Andric unsigned ScratchAlignShift = 10; 5988f0fd8f6SDimitry Andric // We need to program the hardware with the amount of scratch memory that 5998f0fd8f6SDimitry Andric // is used by the entire wave. ProgInfo.ScratchSize is the amount of 6008f0fd8f6SDimitry Andric // scratch memory used per thread. 6018f0fd8f6SDimitry Andric ProgInfo.ScratchBlocks = 6023ca95b02SDimitry Andric alignTo(ProgInfo.ScratchSize * STM.getWavefrontSize(), 6033ca95b02SDimitry Andric 1ULL << ScratchAlignShift) >> 6043ca95b02SDimitry Andric ScratchAlignShift; 6058f0fd8f6SDimitry Andric 6068f0fd8f6SDimitry Andric ProgInfo.ComputePGMRSrc1 = 6078f0fd8f6SDimitry Andric S_00B848_VGPRS(ProgInfo.VGPRBlocks) | 6088f0fd8f6SDimitry Andric S_00B848_SGPRS(ProgInfo.SGPRBlocks) | 6098f0fd8f6SDimitry Andric S_00B848_PRIORITY(ProgInfo.Priority) | 6108f0fd8f6SDimitry Andric S_00B848_FLOAT_MODE(ProgInfo.FloatMode) | 6118f0fd8f6SDimitry Andric S_00B848_PRIV(ProgInfo.Priv) | 6128f0fd8f6SDimitry Andric S_00B848_DX10_CLAMP(ProgInfo.DX10Clamp) | 6137d523365SDimitry Andric S_00B848_DEBUG_MODE(ProgInfo.DebugMode) | 6148f0fd8f6SDimitry Andric S_00B848_IEEE_MODE(ProgInfo.IEEEMode); 6158f0fd8f6SDimitry Andric 6167d523365SDimitry Andric // 0 = X, 1 = XY, 2 = XYZ 6177d523365SDimitry Andric unsigned TIDIGCompCnt = 0; 6187d523365SDimitry Andric if (MFI->hasWorkItemIDZ()) 6197d523365SDimitry Andric TIDIGCompCnt = 2; 6207d523365SDimitry Andric else if (MFI->hasWorkItemIDY()) 6217d523365SDimitry Andric TIDIGCompCnt = 1; 6227d523365SDimitry Andric 6238f0fd8f6SDimitry Andric ProgInfo.ComputePGMRSrc2 = 6248f0fd8f6SDimitry Andric S_00B84C_SCRATCH_EN(ProgInfo.ScratchBlocks > 0) | 6257d523365SDimitry Andric S_00B84C_USER_SGPR(MFI->getNumUserSGPRs()) | 6267a7e6055SDimitry Andric S_00B84C_TRAP_HANDLER(STM.isTrapHandlerEnabled()) | 6277d523365SDimitry Andric S_00B84C_TGID_X_EN(MFI->hasWorkGroupIDX()) | 6287d523365SDimitry Andric S_00B84C_TGID_Y_EN(MFI->hasWorkGroupIDY()) | 6297d523365SDimitry Andric S_00B84C_TGID_Z_EN(MFI->hasWorkGroupIDZ()) | 6307d523365SDimitry Andric S_00B84C_TG_SIZE_EN(MFI->hasWorkGroupInfo()) | 6317d523365SDimitry Andric S_00B84C_TIDIG_COMP_CNT(TIDIGCompCnt) | 6327d523365SDimitry Andric S_00B84C_EXCP_EN_MSB(0) | 6337d523365SDimitry Andric S_00B84C_LDS_SIZE(ProgInfo.LDSBlocks) | 6347d523365SDimitry Andric S_00B84C_EXCP_EN(0); 6358f0fd8f6SDimitry Andric } 6368f0fd8f6SDimitry Andric 6373ca95b02SDimitry Andric static unsigned getRsrcReg(CallingConv::ID CallConv) { 6383ca95b02SDimitry Andric switch (CallConv) { 639d88c1a5aSDimitry Andric default: LLVM_FALLTHROUGH; 6403ca95b02SDimitry Andric case CallingConv::AMDGPU_CS: return R_00B848_COMPUTE_PGM_RSRC1; 6413ca95b02SDimitry Andric case CallingConv::AMDGPU_GS: return R_00B228_SPI_SHADER_PGM_RSRC1_GS; 6423ca95b02SDimitry Andric case CallingConv::AMDGPU_PS: return R_00B028_SPI_SHADER_PGM_RSRC1_PS; 6433ca95b02SDimitry Andric case CallingConv::AMDGPU_VS: return R_00B128_SPI_SHADER_PGM_RSRC1_VS; 6448f0fd8f6SDimitry Andric } 6458f0fd8f6SDimitry Andric } 6468f0fd8f6SDimitry Andric 6478f0fd8f6SDimitry Andric void AMDGPUAsmPrinter::EmitProgramInfoSI(const MachineFunction &MF, 6488f0fd8f6SDimitry Andric const SIProgramInfo &KernelInfo) { 6493ca95b02SDimitry Andric const SISubtarget &STM = MF.getSubtarget<SISubtarget>(); 6508f0fd8f6SDimitry Andric const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>(); 6513ca95b02SDimitry Andric unsigned RsrcReg = getRsrcReg(MF.getFunction()->getCallingConv()); 6528f0fd8f6SDimitry Andric 6533ca95b02SDimitry Andric if (AMDGPU::isCompute(MF.getFunction()->getCallingConv())) { 6548f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(R_00B848_COMPUTE_PGM_RSRC1, 4); 6558f0fd8f6SDimitry Andric 6568f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(KernelInfo.ComputePGMRSrc1, 4); 6578f0fd8f6SDimitry Andric 6588f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(R_00B84C_COMPUTE_PGM_RSRC2, 4); 6598f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(KernelInfo.ComputePGMRSrc2, 4); 6608f0fd8f6SDimitry Andric 6618f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(R_00B860_COMPUTE_TMPRING_SIZE, 4); 6628f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(S_00B860_WAVESIZE(KernelInfo.ScratchBlocks), 4); 6638f0fd8f6SDimitry Andric 6648f0fd8f6SDimitry Andric // TODO: Should probably note flat usage somewhere. SC emits a "FlatPtr32 = 6658f0fd8f6SDimitry Andric // 0" comment but I don't see a corresponding field in the register spec. 6668f0fd8f6SDimitry Andric } else { 6678f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(RsrcReg, 4); 6688f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(S_00B028_VGPRS(KernelInfo.VGPRBlocks) | 6698f0fd8f6SDimitry Andric S_00B028_SGPRS(KernelInfo.SGPRBlocks), 4); 6703ca95b02SDimitry Andric if (STM.isVGPRSpillingEnabled(*MF.getFunction())) { 6718f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(R_0286E8_SPI_TMPRING_SIZE, 4); 6728f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(S_0286E8_WAVESIZE(KernelInfo.ScratchBlocks), 4); 6738f0fd8f6SDimitry Andric } 6748f0fd8f6SDimitry Andric } 6758f0fd8f6SDimitry Andric 6763ca95b02SDimitry Andric if (MF.getFunction()->getCallingConv() == CallingConv::AMDGPU_PS) { 6778f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(R_00B02C_SPI_SHADER_PGM_RSRC2_PS, 4); 6788f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(S_00B02C_EXTRA_LDS_SIZE(KernelInfo.LDSBlocks), 4); 6798f0fd8f6SDimitry Andric OutStreamer->EmitIntValue(R_0286CC_SPI_PS_INPUT_ENA, 4); 6807a7e6055SDimitry Andric OutStreamer->EmitIntValue(MFI->getPSInputEnable(), 4); 681444ed5c5SDimitry Andric OutStreamer->EmitIntValue(R_0286D0_SPI_PS_INPUT_ADDR, 4); 682444ed5c5SDimitry Andric OutStreamer->EmitIntValue(MFI->getPSInputAddr(), 4); 6838f0fd8f6SDimitry Andric } 6843ca95b02SDimitry Andric 6853ca95b02SDimitry Andric OutStreamer->EmitIntValue(R_SPILLED_SGPRS, 4); 6863ca95b02SDimitry Andric OutStreamer->EmitIntValue(MFI->getNumSpilledSGPRs(), 4); 6873ca95b02SDimitry Andric OutStreamer->EmitIntValue(R_SPILLED_VGPRS, 4); 6883ca95b02SDimitry Andric OutStreamer->EmitIntValue(MFI->getNumSpilledVGPRs(), 4); 6893ca95b02SDimitry Andric } 6903ca95b02SDimitry Andric 6913ca95b02SDimitry Andric // This is supposed to be log2(Size) 6923ca95b02SDimitry Andric static amd_element_byte_size_t getElementByteSizeValue(unsigned Size) { 6933ca95b02SDimitry Andric switch (Size) { 6943ca95b02SDimitry Andric case 4: 6953ca95b02SDimitry Andric return AMD_ELEMENT_4_BYTES; 6963ca95b02SDimitry Andric case 8: 6973ca95b02SDimitry Andric return AMD_ELEMENT_8_BYTES; 6983ca95b02SDimitry Andric case 16: 6993ca95b02SDimitry Andric return AMD_ELEMENT_16_BYTES; 7003ca95b02SDimitry Andric default: 7013ca95b02SDimitry Andric llvm_unreachable("invalid private_element_size"); 7023ca95b02SDimitry Andric } 7038f0fd8f6SDimitry Andric } 7048f0fd8f6SDimitry Andric 7057a7e6055SDimitry Andric void AMDGPUAsmPrinter::getAmdKernelCode(amd_kernel_code_t &Out, 7067a7e6055SDimitry Andric const SIProgramInfo &KernelInfo, 7077a7e6055SDimitry Andric const MachineFunction &MF) const { 7088f0fd8f6SDimitry Andric const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>(); 7093ca95b02SDimitry Andric const SISubtarget &STM = MF.getSubtarget<SISubtarget>(); 7108f0fd8f6SDimitry Andric 7117a7e6055SDimitry Andric AMDGPU::initDefaultAMDKernelCodeT(Out, STM.getFeatureBits()); 7128f0fd8f6SDimitry Andric 7137a7e6055SDimitry Andric Out.compute_pgm_resource_registers = 7148f0fd8f6SDimitry Andric KernelInfo.ComputePGMRSrc1 | 7158f0fd8f6SDimitry Andric (KernelInfo.ComputePGMRSrc2 << 32); 7167a7e6055SDimitry Andric Out.code_properties = AMD_CODE_PROPERTY_IS_PTR64; 7177d523365SDimitry Andric 7187a7e6055SDimitry Andric AMD_HSA_BITS_SET(Out.code_properties, 7193ca95b02SDimitry Andric AMD_CODE_PROPERTY_PRIVATE_ELEMENT_SIZE, 7203ca95b02SDimitry Andric getElementByteSizeValue(STM.getMaxPrivateElementSize())); 7213ca95b02SDimitry Andric 7227d523365SDimitry Andric if (MFI->hasPrivateSegmentBuffer()) { 7237a7e6055SDimitry Andric Out.code_properties |= 7247d523365SDimitry Andric AMD_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER; 7257d523365SDimitry Andric } 7267d523365SDimitry Andric 7277d523365SDimitry Andric if (MFI->hasDispatchPtr()) 7287a7e6055SDimitry Andric Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR; 7297d523365SDimitry Andric 7307d523365SDimitry Andric if (MFI->hasQueuePtr()) 7317a7e6055SDimitry Andric Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR; 7327d523365SDimitry Andric 7337d523365SDimitry Andric if (MFI->hasKernargSegmentPtr()) 7347a7e6055SDimitry Andric Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR; 7357d523365SDimitry Andric 7367d523365SDimitry Andric if (MFI->hasDispatchID()) 7377a7e6055SDimitry Andric Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID; 7387d523365SDimitry Andric 7397d523365SDimitry Andric if (MFI->hasFlatScratchInit()) 7407a7e6055SDimitry Andric Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT; 7417d523365SDimitry Andric 7427d523365SDimitry Andric if (MFI->hasGridWorkgroupCountX()) { 7437a7e6055SDimitry Andric Out.code_properties |= 7447d523365SDimitry Andric AMD_CODE_PROPERTY_ENABLE_SGPR_GRID_WORKGROUP_COUNT_X; 7457d523365SDimitry Andric } 7467d523365SDimitry Andric 7477d523365SDimitry Andric if (MFI->hasGridWorkgroupCountY()) { 7487a7e6055SDimitry Andric Out.code_properties |= 7497d523365SDimitry Andric AMD_CODE_PROPERTY_ENABLE_SGPR_GRID_WORKGROUP_COUNT_Y; 7507d523365SDimitry Andric } 7517d523365SDimitry Andric 7527d523365SDimitry Andric if (MFI->hasGridWorkgroupCountZ()) { 7537a7e6055SDimitry Andric Out.code_properties |= 7547d523365SDimitry Andric AMD_CODE_PROPERTY_ENABLE_SGPR_GRID_WORKGROUP_COUNT_Z; 7557d523365SDimitry Andric } 7567d523365SDimitry Andric 7577d523365SDimitry Andric if (MFI->hasDispatchPtr()) 7587a7e6055SDimitry Andric Out.code_properties |= AMD_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR; 7598f0fd8f6SDimitry Andric 7603ca95b02SDimitry Andric if (STM.debuggerSupported()) 7617a7e6055SDimitry Andric Out.code_properties |= AMD_CODE_PROPERTY_IS_DEBUG_SUPPORTED; 7623ca95b02SDimitry Andric 7634d0b32cdSDimitry Andric if (STM.isXNACKEnabled()) 7647a7e6055SDimitry Andric Out.code_properties |= AMD_CODE_PROPERTY_IS_XNACK_SUPPORTED; 7654d0b32cdSDimitry Andric 766d88c1a5aSDimitry Andric // FIXME: Should use getKernArgSize 7677a7e6055SDimitry Andric Out.kernarg_segment_byte_size = 76898221d2eSDimitry Andric STM.getKernArgSegmentSize(MF, MFI->getABIArgOffset()); 7697a7e6055SDimitry Andric Out.wavefront_sgpr_count = KernelInfo.NumSGPR; 7707a7e6055SDimitry Andric Out.workitem_vgpr_count = KernelInfo.NumVGPR; 7717a7e6055SDimitry Andric Out.workitem_private_segment_byte_size = KernelInfo.ScratchSize; 7727a7e6055SDimitry Andric Out.workgroup_group_segment_byte_size = KernelInfo.LDSSize; 7737a7e6055SDimitry Andric Out.reserved_vgpr_first = KernelInfo.ReservedVGPRFirst; 7747a7e6055SDimitry Andric Out.reserved_vgpr_count = KernelInfo.ReservedVGPRCount; 7753ca95b02SDimitry Andric 776d88c1a5aSDimitry Andric // These alignment values are specified in powers of two, so alignment = 777d88c1a5aSDimitry Andric // 2^n. The minimum alignment is 2^4 = 16. 7787a7e6055SDimitry Andric Out.kernarg_segment_alignment = std::max((size_t)4, 779d88c1a5aSDimitry Andric countTrailingZeros(MFI->getMaxKernArgAlign())); 780d88c1a5aSDimitry Andric 7813ca95b02SDimitry Andric if (STM.debuggerEmitPrologue()) { 7827a7e6055SDimitry Andric Out.debug_wavefront_private_segment_offset_sgpr = 7833ca95b02SDimitry Andric KernelInfo.DebuggerWavefrontPrivateSegmentOffsetSGPR; 7847a7e6055SDimitry Andric Out.debug_private_segment_buffer_sgpr = 7853ca95b02SDimitry Andric KernelInfo.DebuggerPrivateSegmentBufferSGPR; 7863ca95b02SDimitry Andric } 7878f0fd8f6SDimitry Andric } 7888f0fd8f6SDimitry Andric 7898f0fd8f6SDimitry Andric bool AMDGPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 7908f0fd8f6SDimitry Andric unsigned AsmVariant, 7918f0fd8f6SDimitry Andric const char *ExtraCode, raw_ostream &O) { 7928f0fd8f6SDimitry Andric if (ExtraCode && ExtraCode[0]) { 7938f0fd8f6SDimitry Andric if (ExtraCode[1] != 0) 7948f0fd8f6SDimitry Andric return true; // Unknown modifier. 7958f0fd8f6SDimitry Andric 7968f0fd8f6SDimitry Andric switch (ExtraCode[0]) { 7978f0fd8f6SDimitry Andric default: 7988f0fd8f6SDimitry Andric // See if this is a generic print operand 7998f0fd8f6SDimitry Andric return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O); 8008f0fd8f6SDimitry Andric case 'r': 8018f0fd8f6SDimitry Andric break; 8028f0fd8f6SDimitry Andric } 8038f0fd8f6SDimitry Andric } 8048f0fd8f6SDimitry Andric 8058f0fd8f6SDimitry Andric AMDGPUInstPrinter::printRegOperand(MI->getOperand(OpNo).getReg(), O, 8068f0fd8f6SDimitry Andric *TM.getSubtargetImpl(*MF->getFunction())->getRegisterInfo()); 8078f0fd8f6SDimitry Andric return false; 8088f0fd8f6SDimitry Andric } 809