AMDGPUAsmPrinter.cpp revision 256281
1//===-- AMDGPUAsmPrinter.cpp - AMDGPU Assebly printer --------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10/// \file 11/// 12/// The AMDGPUAsmPrinter is used to print both assembly string and also binary 13/// code. When passed an MCAsmStreamer it prints assembly and when passed 14/// an MCObjectStreamer it outputs binary code. 15// 16//===----------------------------------------------------------------------===// 17// 18 19 20#include "AMDGPUAsmPrinter.h" 21#include "AMDGPU.h" 22#include "SIDefines.h" 23#include "SIMachineFunctionInfo.h" 24#include "SIRegisterInfo.h" 25#include "R600Defines.h" 26#include "R600MachineFunctionInfo.h" 27#include "R600RegisterInfo.h" 28#include "llvm/MC/MCContext.h" 29#include "llvm/MC/MCSectionELF.h" 30#include "llvm/MC/MCStreamer.h" 31#include "llvm/Support/ELF.h" 32#include "llvm/Support/TargetRegistry.h" 33#include "llvm/Target/TargetLoweringObjectFile.h" 34 35using namespace llvm; 36 37 38static AsmPrinter *createAMDGPUAsmPrinterPass(TargetMachine &tm, 39 MCStreamer &Streamer) { 40 return new AMDGPUAsmPrinter(tm, Streamer); 41} 42 43extern "C" void LLVMInitializeR600AsmPrinter() { 44 TargetRegistry::RegisterAsmPrinter(TheAMDGPUTarget, createAMDGPUAsmPrinterPass); 45} 46 47/// We need to override this function so we can avoid 48/// the call to EmitFunctionHeader(), which the MCPureStreamer can't handle. 49bool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) { 50 const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>(); 51 if (STM.dumpCode()) { 52#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 53 MF.dump(); 54#endif 55 } 56 SetupMachineFunction(MF); 57 if (OutStreamer.hasRawTextSupport()) { 58 OutStreamer.EmitRawText("@" + MF.getName() + ":"); 59 } 60 61 const MCSectionELF *ConfigSection = getObjFileLowering().getContext() 62 .getELFSection(".AMDGPU.config", 63 ELF::SHT_PROGBITS, 0, 64 SectionKind::getReadOnly()); 65 OutStreamer.SwitchSection(ConfigSection); 66 if (STM.device()->getGeneration() > AMDGPUDeviceInfo::HD6XXX) { 67 EmitProgramInfoSI(MF); 68 } else { 69 EmitProgramInfoR600(MF); 70 } 71 OutStreamer.SwitchSection(getObjFileLowering().getTextSection()); 72 EmitFunctionBody(); 73 return false; 74} 75 76void AMDGPUAsmPrinter::EmitProgramInfoR600(MachineFunction &MF) { 77 unsigned MaxGPR = 0; 78 bool killPixel = false; 79 const R600RegisterInfo * RI = 80 static_cast<const R600RegisterInfo*>(TM.getRegisterInfo()); 81 R600MachineFunctionInfo *MFI = MF.getInfo<R600MachineFunctionInfo>(); 82 const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>(); 83 84 for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end(); 85 BB != BB_E; ++BB) { 86 MachineBasicBlock &MBB = *BB; 87 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); 88 I != E; ++I) { 89 MachineInstr &MI = *I; 90 if (MI.getOpcode() == AMDGPU::KILLGT) 91 killPixel = true; 92 unsigned numOperands = MI.getNumOperands(); 93 for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) { 94 MachineOperand & MO = MI.getOperand(op_idx); 95 if (!MO.isReg()) 96 continue; 97 unsigned HWReg = RI->getEncodingValue(MO.getReg()) & 0xff; 98 99 // Register with value > 127 aren't GPR 100 if (HWReg > 127) 101 continue; 102 MaxGPR = std::max(MaxGPR, HWReg); 103 } 104 } 105 } 106 107 unsigned RsrcReg; 108 if (STM.device()->getGeneration() >= AMDGPUDeviceInfo::HD5XXX) { 109 // Evergreen / Northern Islands 110 switch (MFI->ShaderType) { 111 default: // Fall through 112 case ShaderType::COMPUTE: RsrcReg = R_0288D4_SQ_PGM_RESOURCES_LS; break; 113 case ShaderType::GEOMETRY: RsrcReg = R_028878_SQ_PGM_RESOURCES_GS; break; 114 case ShaderType::PIXEL: RsrcReg = R_028844_SQ_PGM_RESOURCES_PS; break; 115 case ShaderType::VERTEX: RsrcReg = R_028860_SQ_PGM_RESOURCES_VS; break; 116 } 117 } else { 118 // R600 / R700 119 switch (MFI->ShaderType) { 120 default: // Fall through 121 case ShaderType::GEOMETRY: // Fall through 122 case ShaderType::COMPUTE: // Fall through 123 case ShaderType::VERTEX: RsrcReg = R_028868_SQ_PGM_RESOURCES_VS; break; 124 case ShaderType::PIXEL: RsrcReg = R_028850_SQ_PGM_RESOURCES_PS; break; 125 } 126 } 127 128 OutStreamer.EmitIntValue(RsrcReg, 4); 129 OutStreamer.EmitIntValue(S_NUM_GPRS(MaxGPR + 1) | 130 S_STACK_SIZE(MFI->StackSize), 4); 131 OutStreamer.EmitIntValue(R_02880C_DB_SHADER_CONTROL, 4); 132 OutStreamer.EmitIntValue(S_02880C_KILL_ENABLE(killPixel), 4); 133} 134 135void AMDGPUAsmPrinter::EmitProgramInfoSI(MachineFunction &MF) { 136 unsigned MaxSGPR = 0; 137 unsigned MaxVGPR = 0; 138 bool VCCUsed = false; 139 const SIRegisterInfo * RI = 140 static_cast<const SIRegisterInfo*>(TM.getRegisterInfo()); 141 142 for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end(); 143 BB != BB_E; ++BB) { 144 MachineBasicBlock &MBB = *BB; 145 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); 146 I != E; ++I) { 147 MachineInstr &MI = *I; 148 149 unsigned numOperands = MI.getNumOperands(); 150 for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) { 151 MachineOperand & MO = MI.getOperand(op_idx); 152 unsigned maxUsed; 153 unsigned width = 0; 154 bool isSGPR = false; 155 unsigned reg; 156 unsigned hwReg; 157 if (!MO.isReg()) { 158 continue; 159 } 160 reg = MO.getReg(); 161 if (reg == AMDGPU::VCC) { 162 VCCUsed = true; 163 continue; 164 } 165 switch (reg) { 166 default: break; 167 case AMDGPU::EXEC: 168 case AMDGPU::M0: 169 continue; 170 } 171 172 if (AMDGPU::SReg_32RegClass.contains(reg)) { 173 isSGPR = true; 174 width = 1; 175 } else if (AMDGPU::VReg_32RegClass.contains(reg)) { 176 isSGPR = false; 177 width = 1; 178 } else if (AMDGPU::SReg_64RegClass.contains(reg)) { 179 isSGPR = true; 180 width = 2; 181 } else if (AMDGPU::VReg_64RegClass.contains(reg)) { 182 isSGPR = false; 183 width = 2; 184 } else if (AMDGPU::VReg_96RegClass.contains(reg)) { 185 isSGPR = false; 186 width = 3; 187 } else if (AMDGPU::SReg_128RegClass.contains(reg)) { 188 isSGPR = true; 189 width = 4; 190 } else if (AMDGPU::VReg_128RegClass.contains(reg)) { 191 isSGPR = false; 192 width = 4; 193 } else if (AMDGPU::SReg_256RegClass.contains(reg)) { 194 isSGPR = true; 195 width = 8; 196 } else if (AMDGPU::VReg_256RegClass.contains(reg)) { 197 isSGPR = false; 198 width = 8; 199 } else if (AMDGPU::VReg_512RegClass.contains(reg)) { 200 isSGPR = false; 201 width = 16; 202 } else { 203 assert(!"Unknown register class"); 204 } 205 hwReg = RI->getEncodingValue(reg) & 0xff; 206 maxUsed = hwReg + width - 1; 207 if (isSGPR) { 208 MaxSGPR = maxUsed > MaxSGPR ? maxUsed : MaxSGPR; 209 } else { 210 MaxVGPR = maxUsed > MaxVGPR ? maxUsed : MaxVGPR; 211 } 212 } 213 } 214 } 215 if (VCCUsed) { 216 MaxSGPR += 2; 217 } 218 SIMachineFunctionInfo * MFI = MF.getInfo<SIMachineFunctionInfo>(); 219 unsigned RsrcReg; 220 switch (MFI->ShaderType) { 221 default: // Fall through 222 case ShaderType::COMPUTE: RsrcReg = R_00B848_COMPUTE_PGM_RSRC1; break; 223 case ShaderType::GEOMETRY: RsrcReg = R_00B228_SPI_SHADER_PGM_RSRC1_GS; break; 224 case ShaderType::PIXEL: RsrcReg = R_00B028_SPI_SHADER_PGM_RSRC1_PS; break; 225 case ShaderType::VERTEX: RsrcReg = R_00B128_SPI_SHADER_PGM_RSRC1_VS; break; 226 } 227 228 OutStreamer.EmitIntValue(RsrcReg, 4); 229 OutStreamer.EmitIntValue(S_00B028_VGPRS(MaxVGPR / 4) | S_00B028_SGPRS(MaxSGPR / 8), 4); 230 if (MFI->ShaderType == ShaderType::PIXEL) { 231 OutStreamer.EmitIntValue(R_0286CC_SPI_PS_INPUT_ENA, 4); 232 OutStreamer.EmitIntValue(MFI->PSInputAddr, 4); 233 } 234} 235