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