1 //===-- AMDGPUAsmPrinter.cpp - AMDGPU Assebly printer --------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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.
16 //===----------------------------------------------------------------------===//
20 #include "AMDGPUAsmPrinter.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"
39 static AsmPrinter *createAMDGPUAsmPrinterPass(TargetMachine &tm,
40 MCStreamer &Streamer) {
41 return new AMDGPUAsmPrinter(tm, Streamer);
44 extern "C" void LLVMInitializeR600AsmPrinter() {
45 TargetRegistry::RegisterAsmPrinter(TheAMDGPUTarget, createAMDGPUAsmPrinterPass);
48 AMDGPUAsmPrinter::AMDGPUAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
49 : AsmPrinter(TM, Streamer)
51 DisasmEnabled = TM.getSubtarget<AMDGPUSubtarget>().dumpCode() &&
52 ! Streamer.hasRawTextSupport();
55 /// We need to override this function so we can avoid
56 /// the call to EmitFunctionHeader(), which the MCPureStreamer can't handle.
57 bool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
58 SetupMachineFunction(MF);
59 if (OutStreamer.hasRawTextSupport()) {
60 OutStreamer.EmitRawText("@" + MF.getName() + ":");
63 MCContext &Context = getObjFileLowering().getContext();
64 const MCSectionELF *ConfigSection = Context.getELFSection(".AMDGPU.config",
66 SectionKind::getReadOnly());
67 OutStreamer.SwitchSection(ConfigSection);
68 const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>();
69 if (STM.getGeneration() > AMDGPUSubtarget::NORTHERN_ISLANDS) {
70 EmitProgramInfoSI(MF);
72 EmitProgramInfoR600(MF);
79 OutStreamer.SwitchSection(getObjFileLowering().getTextSection());
83 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
88 OutStreamer.SwitchSection(Context.getELFSection(".AMDGPU.disasm",
90 SectionKind::getReadOnly()));
92 for (size_t i = 0; i < DisasmLines.size(); ++i) {
93 std::string Comment(DisasmLineMaxLen - DisasmLines[i].size(), ' ');
94 Comment += " ; " + HexLines[i] + "\n";
96 OutStreamer.EmitBytes(StringRef(DisasmLines[i]));
97 OutStreamer.EmitBytes(StringRef(Comment));
105 void AMDGPUAsmPrinter::EmitProgramInfoR600(MachineFunction &MF) {
107 bool killPixel = false;
108 const R600RegisterInfo * RI =
109 static_cast<const R600RegisterInfo*>(TM.getRegisterInfo());
110 R600MachineFunctionInfo *MFI = MF.getInfo<R600MachineFunctionInfo>();
111 const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>();
113 for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
115 MachineBasicBlock &MBB = *BB;
116 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
118 MachineInstr &MI = *I;
119 if (MI.getOpcode() == AMDGPU::KILLGT)
121 unsigned numOperands = MI.getNumOperands();
122 for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) {
123 MachineOperand & MO = MI.getOperand(op_idx);
126 unsigned HWReg = RI->getEncodingValue(MO.getReg()) & 0xff;
128 // Register with value > 127 aren't GPR
131 MaxGPR = std::max(MaxGPR, HWReg);
137 if (STM.getGeneration() >= AMDGPUSubtarget::EVERGREEN) {
138 // Evergreen / Northern Islands
139 switch (MFI->ShaderType) {
140 default: // Fall through
141 case ShaderType::COMPUTE: RsrcReg = R_0288D4_SQ_PGM_RESOURCES_LS; break;
142 case ShaderType::GEOMETRY: RsrcReg = R_028878_SQ_PGM_RESOURCES_GS; break;
143 case ShaderType::PIXEL: RsrcReg = R_028844_SQ_PGM_RESOURCES_PS; break;
144 case ShaderType::VERTEX: RsrcReg = R_028860_SQ_PGM_RESOURCES_VS; break;
148 switch (MFI->ShaderType) {
149 default: // Fall through
150 case ShaderType::GEOMETRY: // Fall through
151 case ShaderType::COMPUTE: // Fall through
152 case ShaderType::VERTEX: RsrcReg = R_028868_SQ_PGM_RESOURCES_VS; break;
153 case ShaderType::PIXEL: RsrcReg = R_028850_SQ_PGM_RESOURCES_PS; break;
157 OutStreamer.EmitIntValue(RsrcReg, 4);
158 OutStreamer.EmitIntValue(S_NUM_GPRS(MaxGPR + 1) |
159 S_STACK_SIZE(MFI->StackSize), 4);
160 OutStreamer.EmitIntValue(R_02880C_DB_SHADER_CONTROL, 4);
161 OutStreamer.EmitIntValue(S_02880C_KILL_ENABLE(killPixel), 4);
163 if (MFI->ShaderType == ShaderType::COMPUTE) {
164 OutStreamer.EmitIntValue(R_0288E8_SQ_LDS_ALLOC, 4);
165 OutStreamer.EmitIntValue(RoundUpToAlignment(MFI->LDSSize, 4) >> 2, 4);
169 void AMDGPUAsmPrinter::EmitProgramInfoSI(MachineFunction &MF) {
170 unsigned MaxSGPR = 0;
171 unsigned MaxVGPR = 0;
172 bool VCCUsed = false;
173 const SIRegisterInfo * RI =
174 static_cast<const SIRegisterInfo*>(TM.getRegisterInfo());
176 for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
178 MachineBasicBlock &MBB = *BB;
179 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
181 MachineInstr &MI = *I;
183 unsigned numOperands = MI.getNumOperands();
184 for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) {
185 MachineOperand & MO = MI.getOperand(op_idx);
195 if (reg == AMDGPU::VCC) {
208 if (AMDGPU::SReg_32RegClass.contains(reg)) {
211 } else if (AMDGPU::VReg_32RegClass.contains(reg)) {
214 } else if (AMDGPU::SReg_64RegClass.contains(reg)) {
217 } else if (AMDGPU::VReg_64RegClass.contains(reg)) {
220 } else if (AMDGPU::VReg_96RegClass.contains(reg)) {
223 } else if (AMDGPU::SReg_128RegClass.contains(reg)) {
226 } else if (AMDGPU::VReg_128RegClass.contains(reg)) {
229 } else if (AMDGPU::SReg_256RegClass.contains(reg)) {
232 } else if (AMDGPU::VReg_256RegClass.contains(reg)) {
235 } else if (AMDGPU::VReg_512RegClass.contains(reg)) {
239 assert(!"Unknown register class");
241 hwReg = RI->getEncodingValue(reg) & 0xff;
242 maxUsed = hwReg + width - 1;
244 MaxSGPR = maxUsed > MaxSGPR ? maxUsed : MaxSGPR;
246 MaxVGPR = maxUsed > MaxVGPR ? maxUsed : MaxVGPR;
254 SIMachineFunctionInfo * MFI = MF.getInfo<SIMachineFunctionInfo>();
256 switch (MFI->ShaderType) {
257 default: // Fall through
258 case ShaderType::COMPUTE: RsrcReg = R_00B848_COMPUTE_PGM_RSRC1; break;
259 case ShaderType::GEOMETRY: RsrcReg = R_00B228_SPI_SHADER_PGM_RSRC1_GS; break;
260 case ShaderType::PIXEL: RsrcReg = R_00B028_SPI_SHADER_PGM_RSRC1_PS; break;
261 case ShaderType::VERTEX: RsrcReg = R_00B128_SPI_SHADER_PGM_RSRC1_VS; break;
264 OutStreamer.EmitIntValue(RsrcReg, 4);
265 OutStreamer.EmitIntValue(S_00B028_VGPRS(MaxVGPR / 4) | S_00B028_SGPRS(MaxSGPR / 8), 4);
267 if (MFI->ShaderType == ShaderType::COMPUTE) {
268 OutStreamer.EmitIntValue(R_00B84C_COMPUTE_PGM_RSRC2, 4);
269 OutStreamer.EmitIntValue(S_00B84C_LDS_SIZE(RoundUpToAlignment(MFI->LDSSize, 256) >> 8), 4);
271 if (MFI->ShaderType == ShaderType::PIXEL) {
272 OutStreamer.EmitIntValue(R_00B02C_SPI_SHADER_PGM_RSRC2_PS, 4);
273 OutStreamer.EmitIntValue(S_00B02C_EXTRA_LDS_SIZE(RoundUpToAlignment(MFI->LDSSize, 256) >> 8), 4);
274 OutStreamer.EmitIntValue(R_0286CC_SPI_PS_INPUT_ENA, 4);
275 OutStreamer.EmitIntValue(MFI->PSInputAddr, 4);