blob: f3ccce72c5a6204de9fbf5ad394b67e5bef8995e [file] [log] [blame]
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001//===-- 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"
Tom Stellardf07b5372013-05-06 17:50:51 +000022#include "R600Defines.h"
Vincent Lejeune2a746392013-04-23 17:34:12 +000023#include "R600MachineFunctionInfo.h"
Vincent Lejeune141ca7f2013-04-17 15:17:25 +000024#include "R600RegisterInfo.h"
Benjamin Kramer5c352902013-05-23 17:10:37 +000025#include "SIDefines.h"
26#include "SIMachineFunctionInfo.h"
27#include "SIRegisterInfo.h"
Tom Stellardbf1efe62013-04-15 17:51:30 +000028#include "llvm/MC/MCContext.h"
29#include "llvm/MC/MCSectionELF.h"
Tom Stellardf98f2ce2012-12-11 21:25:42 +000030#include "llvm/MC/MCStreamer.h"
Tom Stellardbf1efe62013-04-15 17:51:30 +000031#include "llvm/Support/ELF.h"
Tom Stellarde3d4cbc2013-06-28 15:47:08 +000032#include "llvm/Support/MathExtras.h"
Tom Stellardf98f2ce2012-12-11 21:25:42 +000033#include "llvm/Support/TargetRegistry.h"
Chandler Carruth58a2cbe2013-01-02 10:22:59 +000034#include "llvm/Target/TargetLoweringObjectFile.h"
Tom Stellardf98f2ce2012-12-11 21:25:42 +000035
36using namespace llvm;
37
38
39static AsmPrinter *createAMDGPUAsmPrinterPass(TargetMachine &tm,
40 MCStreamer &Streamer) {
41 return new AMDGPUAsmPrinter(tm, Streamer);
42}
43
44extern "C" void LLVMInitializeR600AsmPrinter() {
45 TargetRegistry::RegisterAsmPrinter(TheAMDGPUTarget, createAMDGPUAsmPrinterPass);
46}
47
Tom Stellardf9318672013-10-12 05:02:51 +000048AMDGPUAsmPrinter::AMDGPUAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
49 : AsmPrinter(TM, Streamer)
50{
51 DisasmEnabled = TM.getSubtarget<AMDGPUSubtarget>().dumpCode() &&
52 ! Streamer.hasRawTextSupport();
53}
54
Tom Stellardf98f2ce2012-12-11 21:25:42 +000055/// We need to override this function so we can avoid
56/// the call to EmitFunctionHeader(), which the MCPureStreamer can't handle.
57bool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
Tom Stellardf98f2ce2012-12-11 21:25:42 +000058 SetupMachineFunction(MF);
Tom Stellard3ce2ec82013-02-05 17:09:11 +000059 if (OutStreamer.hasRawTextSupport()) {
60 OutStreamer.EmitRawText("@" + MF.getName() + ":");
61 }
Vincent Lejeune141ca7f2013-04-17 15:17:25 +000062
Tom Stellardf9318672013-10-12 05:02:51 +000063 MCContext &Context = getObjFileLowering().getContext();
64 const MCSectionELF *ConfigSection = Context.getELFSection(".AMDGPU.config",
Tom Stellard87cba4a2013-04-24 23:56:14 +000065 ELF::SHT_PROGBITS, 0,
Vincent Lejeune141ca7f2013-04-17 15:17:25 +000066 SectionKind::getReadOnly());
67 OutStreamer.SwitchSection(ConfigSection);
Tom Stellardf9318672013-10-12 05:02:51 +000068 const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>();
Tom Stellard3ff0abf2013-06-07 20:37:48 +000069 if (STM.getGeneration() > AMDGPUSubtarget::NORTHERN_ISLANDS) {
Vincent Lejeune141ca7f2013-04-17 15:17:25 +000070 EmitProgramInfoSI(MF);
71 } else {
72 EmitProgramInfoR600(MF);
Tom Stellardf98f2ce2012-12-11 21:25:42 +000073 }
Tom Stellardf9318672013-10-12 05:02:51 +000074
75 DisasmLines.clear();
76 HexLines.clear();
77 DisasmLineMaxLen = 0;
78
Tom Stellardbf1efe62013-04-15 17:51:30 +000079 OutStreamer.SwitchSection(getObjFileLowering().getTextSection());
Tom Stellardf98f2ce2012-12-11 21:25:42 +000080 EmitFunctionBody();
Tom Stellardf9318672013-10-12 05:02:51 +000081
82 if (STM.dumpCode()) {
83#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
84 MF.dump();
85#endif
86
87 if (DisasmEnabled) {
88 OutStreamer.SwitchSection(Context.getELFSection(".AMDGPU.disasm",
89 ELF::SHT_NOTE, 0,
90 SectionKind::getReadOnly()));
91
92 for (size_t i = 0; i < DisasmLines.size(); ++i) {
93 std::string Comment(DisasmLineMaxLen - DisasmLines[i].size(), ' ');
94 Comment += " ; " + HexLines[i] + "\n";
95
96 OutStreamer.EmitBytes(StringRef(DisasmLines[i]));
97 OutStreamer.EmitBytes(StringRef(Comment));
98 }
99 }
100 }
101
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000102 return false;
103}
104
Vincent Lejeune141ca7f2013-04-17 15:17:25 +0000105void AMDGPUAsmPrinter::EmitProgramInfoR600(MachineFunction &MF) {
106 unsigned MaxGPR = 0;
Vincent Lejeune86cdb702013-04-30 00:13:13 +0000107 bool killPixel = false;
Vincent Lejeune141ca7f2013-04-17 15:17:25 +0000108 const R600RegisterInfo * RI =
109 static_cast<const R600RegisterInfo*>(TM.getRegisterInfo());
Vincent Lejeune2a746392013-04-23 17:34:12 +0000110 R600MachineFunctionInfo *MFI = MF.getInfo<R600MachineFunctionInfo>();
Tom Stellardf07b5372013-05-06 17:50:51 +0000111 const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>();
Vincent Lejeune141ca7f2013-04-17 15:17:25 +0000112
113 for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
114 BB != BB_E; ++BB) {
115 MachineBasicBlock &MBB = *BB;
116 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
117 I != E; ++I) {
118 MachineInstr &MI = *I;
Vincent Lejeune86cdb702013-04-30 00:13:13 +0000119 if (MI.getOpcode() == AMDGPU::KILLGT)
120 killPixel = true;
Vincent Lejeune141ca7f2013-04-17 15:17:25 +0000121 unsigned numOperands = MI.getNumOperands();
122 for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) {
123 MachineOperand & MO = MI.getOperand(op_idx);
124 if (!MO.isReg())
125 continue;
126 unsigned HWReg = RI->getEncodingValue(MO.getReg()) & 0xff;
127
128 // Register with value > 127 aren't GPR
129 if (HWReg > 127)
130 continue;
131 MaxGPR = std::max(MaxGPR, HWReg);
132 }
133 }
134 }
Tom Stellardf07b5372013-05-06 17:50:51 +0000135
136 unsigned RsrcReg;
Tom Stellard3ff0abf2013-06-07 20:37:48 +0000137 if (STM.getGeneration() >= AMDGPUSubtarget::EVERGREEN) {
Tom Stellardf07b5372013-05-06 17:50:51 +0000138 // 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;
145 }
146 } else {
147 // R600 / R700
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;
154 }
155 }
156
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);
Tom Stellarde3d4cbc2013-06-28 15:47:08 +0000162
163 if (MFI->ShaderType == ShaderType::COMPUTE) {
164 OutStreamer.EmitIntValue(R_0288E8_SQ_LDS_ALLOC, 4);
165 OutStreamer.EmitIntValue(RoundUpToAlignment(MFI->LDSSize, 4) >> 2, 4);
166 }
Vincent Lejeune141ca7f2013-04-17 15:17:25 +0000167}
168
169void AMDGPUAsmPrinter::EmitProgramInfoSI(MachineFunction &MF) {
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000170 unsigned MaxSGPR = 0;
171 unsigned MaxVGPR = 0;
172 bool VCCUsed = false;
173 const SIRegisterInfo * RI =
174 static_cast<const SIRegisterInfo*>(TM.getRegisterInfo());
175
176 for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
177 BB != BB_E; ++BB) {
178 MachineBasicBlock &MBB = *BB;
179 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
180 I != E; ++I) {
181 MachineInstr &MI = *I;
182
183 unsigned numOperands = MI.getNumOperands();
184 for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) {
185 MachineOperand & MO = MI.getOperand(op_idx);
186 unsigned maxUsed;
187 unsigned width = 0;
188 bool isSGPR = false;
189 unsigned reg;
190 unsigned hwReg;
191 if (!MO.isReg()) {
192 continue;
193 }
194 reg = MO.getReg();
195 if (reg == AMDGPU::VCC) {
196 VCCUsed = true;
197 continue;
198 }
199 switch (reg) {
200 default: break;
201 case AMDGPU::EXEC:
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000202 case AMDGPU::M0:
203 continue;
204 }
205
206 if (AMDGPU::SReg_32RegClass.contains(reg)) {
207 isSGPR = true;
208 width = 1;
209 } else if (AMDGPU::VReg_32RegClass.contains(reg)) {
210 isSGPR = false;
211 width = 1;
212 } else if (AMDGPU::SReg_64RegClass.contains(reg)) {
213 isSGPR = true;
214 width = 2;
215 } else if (AMDGPU::VReg_64RegClass.contains(reg)) {
216 isSGPR = false;
217 width = 2;
Christian Konig4d0e8a82013-04-10 08:39:16 +0000218 } else if (AMDGPU::VReg_96RegClass.contains(reg)) {
219 isSGPR = false;
220 width = 3;
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000221 } else if (AMDGPU::SReg_128RegClass.contains(reg)) {
222 isSGPR = true;
223 width = 4;
224 } else if (AMDGPU::VReg_128RegClass.contains(reg)) {
225 isSGPR = false;
226 width = 4;
227 } else if (AMDGPU::SReg_256RegClass.contains(reg)) {
228 isSGPR = true;
229 width = 8;
Tom Stellard36ba9092013-02-07 17:02:09 +0000230 } else if (AMDGPU::VReg_256RegClass.contains(reg)) {
231 isSGPR = false;
232 width = 8;
233 } else if (AMDGPU::VReg_512RegClass.contains(reg)) {
234 isSGPR = false;
235 width = 16;
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000236 } else {
237 assert(!"Unknown register class");
238 }
Tom Stellard184f5c12013-02-07 19:39:45 +0000239 hwReg = RI->getEncodingValue(reg) & 0xff;
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000240 maxUsed = hwReg + width - 1;
241 if (isSGPR) {
242 MaxSGPR = maxUsed > MaxSGPR ? maxUsed : MaxSGPR;
243 } else {
244 MaxVGPR = maxUsed > MaxVGPR ? maxUsed : MaxVGPR;
245 }
246 }
247 }
248 }
249 if (VCCUsed) {
250 MaxSGPR += 2;
251 }
252 SIMachineFunctionInfo * MFI = MF.getInfo<SIMachineFunctionInfo>();
Tom Stellard9a256302013-04-15 17:51:35 +0000253 unsigned RsrcReg;
254 switch (MFI->ShaderType) {
255 default: // Fall through
256 case ShaderType::COMPUTE: RsrcReg = R_00B848_COMPUTE_PGM_RSRC1; break;
257 case ShaderType::GEOMETRY: RsrcReg = R_00B228_SPI_SHADER_PGM_RSRC1_GS; break;
258 case ShaderType::PIXEL: RsrcReg = R_00B028_SPI_SHADER_PGM_RSRC1_PS; break;
259 case ShaderType::VERTEX: RsrcReg = R_00B128_SPI_SHADER_PGM_RSRC1_VS; break;
260 }
261
262 OutStreamer.EmitIntValue(RsrcReg, 4);
263 OutStreamer.EmitIntValue(S_00B028_VGPRS(MaxVGPR / 4) | S_00B028_SGPRS(MaxSGPR / 8), 4);
Michel Danzera3e39dc2013-07-10 16:37:07 +0000264
265 if (MFI->ShaderType == ShaderType::COMPUTE) {
266 OutStreamer.EmitIntValue(R_00B84C_COMPUTE_PGM_RSRC2, 4);
267 OutStreamer.EmitIntValue(S_00B84C_LDS_SIZE(RoundUpToAlignment(MFI->LDSSize, 256) >> 8), 4);
268 }
Tom Stellard9a256302013-04-15 17:51:35 +0000269 if (MFI->ShaderType == ShaderType::PIXEL) {
Michel Danzera3e39dc2013-07-10 16:37:07 +0000270 OutStreamer.EmitIntValue(R_00B02C_SPI_SHADER_PGM_RSRC2_PS, 4);
271 OutStreamer.EmitIntValue(S_00B02C_EXTRA_LDS_SIZE(RoundUpToAlignment(MFI->LDSSize, 256) >> 8), 4);
Tom Stellard9a256302013-04-15 17:51:35 +0000272 OutStreamer.EmitIntValue(R_0286CC_SPI_PS_INPUT_ENA, 4);
273 OutStreamer.EmitIntValue(MFI->PSInputAddr, 4);
274 }
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000275}