blob: f720c7ecb63789a51d138859c554a7db4624c327 [file] [log] [blame]
Tom Stellard75aadc22012-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 Stellard043de4c2013-05-06 17:50:51 +000022#include "R600Defines.h"
Vincent Lejeune117f0752013-04-23 17:34:12 +000023#include "R600MachineFunctionInfo.h"
Vincent Lejeune98a73802013-04-17 15:17:25 +000024#include "R600RegisterInfo.h"
Benjamin Kramerd78bb462013-05-23 17:10:37 +000025#include "SIDefines.h"
26#include "SIMachineFunctionInfo.h"
27#include "SIRegisterInfo.h"
Tom Stellard3a7beafb32013-04-15 17:51:30 +000028#include "llvm/MC/MCContext.h"
29#include "llvm/MC/MCSectionELF.h"
Tom Stellard75aadc22012-12-11 21:25:42 +000030#include "llvm/MC/MCStreamer.h"
Tom Stellard3a7beafb32013-04-15 17:51:30 +000031#include "llvm/Support/ELF.h"
Tom Stellard75aadc22012-12-11 21:25:42 +000032#include "llvm/Support/TargetRegistry.h"
Chandler Carruthbe810232013-01-02 10:22:59 +000033#include "llvm/Target/TargetLoweringObjectFile.h"
Tom Stellard75aadc22012-12-11 21:25:42 +000034
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);
Tom Stellard2e5e7a52013-02-05 17:09:11 +000057 if (OutStreamer.hasRawTextSupport()) {
58 OutStreamer.EmitRawText("@" + MF.getName() + ":");
59 }
Vincent Lejeune98a73802013-04-17 15:17:25 +000060
61 const MCSectionELF *ConfigSection = getObjFileLowering().getContext()
62 .getELFSection(".AMDGPU.config",
Tom Stellard34e40682013-04-24 23:56:14 +000063 ELF::SHT_PROGBITS, 0,
Vincent Lejeune98a73802013-04-17 15:17:25 +000064 SectionKind::getReadOnly());
65 OutStreamer.SwitchSection(ConfigSection);
Tom Stellarda6c6e1b2013-06-07 20:37:48 +000066 if (STM.getGeneration() > AMDGPUSubtarget::NORTHERN_ISLANDS) {
Vincent Lejeune98a73802013-04-17 15:17:25 +000067 EmitProgramInfoSI(MF);
68 } else {
69 EmitProgramInfoR600(MF);
Tom Stellard75aadc22012-12-11 21:25:42 +000070 }
Tom Stellard3a7beafb32013-04-15 17:51:30 +000071 OutStreamer.SwitchSection(getObjFileLowering().getTextSection());
Tom Stellard75aadc22012-12-11 21:25:42 +000072 EmitFunctionBody();
73 return false;
74}
75
Vincent Lejeune98a73802013-04-17 15:17:25 +000076void AMDGPUAsmPrinter::EmitProgramInfoR600(MachineFunction &MF) {
77 unsigned MaxGPR = 0;
Vincent Lejeune4a0beb52013-04-30 00:13:13 +000078 bool killPixel = false;
Vincent Lejeune98a73802013-04-17 15:17:25 +000079 const R600RegisterInfo * RI =
80 static_cast<const R600RegisterInfo*>(TM.getRegisterInfo());
Vincent Lejeune117f0752013-04-23 17:34:12 +000081 R600MachineFunctionInfo *MFI = MF.getInfo<R600MachineFunctionInfo>();
Tom Stellard043de4c2013-05-06 17:50:51 +000082 const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>();
Vincent Lejeune98a73802013-04-17 15:17:25 +000083
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;
Vincent Lejeune4a0beb52013-04-30 00:13:13 +000090 if (MI.getOpcode() == AMDGPU::KILLGT)
91 killPixel = true;
Vincent Lejeune98a73802013-04-17 15:17:25 +000092 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 }
Tom Stellard043de4c2013-05-06 17:50:51 +0000106
107 unsigned RsrcReg;
Tom Stellarda6c6e1b2013-06-07 20:37:48 +0000108 if (STM.getGeneration() >= AMDGPUSubtarget::EVERGREEN) {
Tom Stellard043de4c2013-05-06 17:50:51 +0000109 // 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);
Vincent Lejeune98a73802013-04-17 15:17:25 +0000133}
134
135void AMDGPUAsmPrinter::EmitProgramInfoSI(MachineFunction &MF) {
Tom Stellard75aadc22012-12-11 21:25:42 +0000136 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:
Tom Stellard75aadc22012-12-11 21:25:42 +0000168 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;
Christian Konig8b1ed282013-04-10 08:39:16 +0000184 } else if (AMDGPU::VReg_96RegClass.contains(reg)) {
185 isSGPR = false;
186 width = 3;
Tom Stellard75aadc22012-12-11 21:25:42 +0000187 } 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;
Tom Stellard538ceeb2013-02-07 17:02:09 +0000196 } 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;
Tom Stellard75aadc22012-12-11 21:25:42 +0000202 } else {
203 assert(!"Unknown register class");
204 }
Tom Stellard1c822a82013-02-07 19:39:45 +0000205 hwReg = RI->getEncodingValue(reg) & 0xff;
Tom Stellard75aadc22012-12-11 21:25:42 +0000206 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>();
Tom Stellardcb97e3a2013-04-15 17:51:35 +0000219 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 }
Tom Stellard75aadc22012-12-11 21:25:42 +0000234}