blob: d8a380de839c543ce30194267e136b2f221fc496 [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 Stellardcb97e3a2013-04-15 17:51:35 +000022#include "SIDefines.h"
Tom Stellard75aadc22012-12-11 21:25:42 +000023#include "SIMachineFunctionInfo.h"
24#include "SIRegisterInfo.h"
Vincent Lejeune98a73802013-04-17 15:17:25 +000025#include "R600RegisterInfo.h"
Tom Stellard3a7beafb32013-04-15 17:51:30 +000026#include "llvm/MC/MCContext.h"
27#include "llvm/MC/MCSectionELF.h"
Tom Stellard75aadc22012-12-11 21:25:42 +000028#include "llvm/MC/MCStreamer.h"
Tom Stellard3a7beafb32013-04-15 17:51:30 +000029#include "llvm/Support/ELF.h"
Tom Stellard75aadc22012-12-11 21:25:42 +000030#include "llvm/Support/TargetRegistry.h"
Chandler Carruthbe810232013-01-02 10:22:59 +000031#include "llvm/Target/TargetLoweringObjectFile.h"
Tom Stellard75aadc22012-12-11 21:25:42 +000032
33using namespace llvm;
34
35
36static AsmPrinter *createAMDGPUAsmPrinterPass(TargetMachine &tm,
37 MCStreamer &Streamer) {
38 return new AMDGPUAsmPrinter(tm, Streamer);
39}
40
41extern "C" void LLVMInitializeR600AsmPrinter() {
42 TargetRegistry::RegisterAsmPrinter(TheAMDGPUTarget, createAMDGPUAsmPrinterPass);
43}
44
45/// We need to override this function so we can avoid
46/// the call to EmitFunctionHeader(), which the MCPureStreamer can't handle.
47bool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
48 const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>();
49 if (STM.dumpCode()) {
50#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
51 MF.dump();
52#endif
53 }
54 SetupMachineFunction(MF);
Tom Stellard2e5e7a52013-02-05 17:09:11 +000055 if (OutStreamer.hasRawTextSupport()) {
56 OutStreamer.EmitRawText("@" + MF.getName() + ":");
57 }
Vincent Lejeune98a73802013-04-17 15:17:25 +000058
59 const MCSectionELF *ConfigSection = getObjFileLowering().getContext()
60 .getELFSection(".AMDGPU.config",
61 ELF::SHT_NULL, 0,
62 SectionKind::getReadOnly());
63 OutStreamer.SwitchSection(ConfigSection);
Tom Stellard75aadc22012-12-11 21:25:42 +000064 if (STM.device()->getGeneration() > AMDGPUDeviceInfo::HD6XXX) {
Vincent Lejeune98a73802013-04-17 15:17:25 +000065 EmitProgramInfoSI(MF);
66 } else {
67 EmitProgramInfoR600(MF);
Tom Stellard75aadc22012-12-11 21:25:42 +000068 }
Tom Stellard3a7beafb32013-04-15 17:51:30 +000069 OutStreamer.SwitchSection(getObjFileLowering().getTextSection());
Tom Stellard75aadc22012-12-11 21:25:42 +000070 EmitFunctionBody();
71 return false;
72}
73
Vincent Lejeune98a73802013-04-17 15:17:25 +000074void AMDGPUAsmPrinter::EmitProgramInfoR600(MachineFunction &MF) {
75 unsigned MaxGPR = 0;
76 const R600RegisterInfo * RI =
77 static_cast<const R600RegisterInfo*>(TM.getRegisterInfo());
78
79 for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
80 BB != BB_E; ++BB) {
81 MachineBasicBlock &MBB = *BB;
82 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
83 I != E; ++I) {
84 MachineInstr &MI = *I;
85 unsigned numOperands = MI.getNumOperands();
86 for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) {
87 MachineOperand & MO = MI.getOperand(op_idx);
88 if (!MO.isReg())
89 continue;
90 unsigned HWReg = RI->getEncodingValue(MO.getReg()) & 0xff;
91
92 // Register with value > 127 aren't GPR
93 if (HWReg > 127)
94 continue;
95 MaxGPR = std::max(MaxGPR, HWReg);
96 }
97 }
98 }
99 OutStreamer.EmitIntValue(MaxGPR + 1, 4);
100}
101
102void AMDGPUAsmPrinter::EmitProgramInfoSI(MachineFunction &MF) {
Tom Stellard75aadc22012-12-11 21:25:42 +0000103 unsigned MaxSGPR = 0;
104 unsigned MaxVGPR = 0;
105 bool VCCUsed = false;
106 const SIRegisterInfo * RI =
107 static_cast<const SIRegisterInfo*>(TM.getRegisterInfo());
108
109 for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
110 BB != BB_E; ++BB) {
111 MachineBasicBlock &MBB = *BB;
112 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
113 I != E; ++I) {
114 MachineInstr &MI = *I;
115
116 unsigned numOperands = MI.getNumOperands();
117 for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) {
118 MachineOperand & MO = MI.getOperand(op_idx);
119 unsigned maxUsed;
120 unsigned width = 0;
121 bool isSGPR = false;
122 unsigned reg;
123 unsigned hwReg;
124 if (!MO.isReg()) {
125 continue;
126 }
127 reg = MO.getReg();
128 if (reg == AMDGPU::VCC) {
129 VCCUsed = true;
130 continue;
131 }
132 switch (reg) {
133 default: break;
134 case AMDGPU::EXEC:
Tom Stellard75aadc22012-12-11 21:25:42 +0000135 case AMDGPU::M0:
136 continue;
137 }
138
139 if (AMDGPU::SReg_32RegClass.contains(reg)) {
140 isSGPR = true;
141 width = 1;
142 } else if (AMDGPU::VReg_32RegClass.contains(reg)) {
143 isSGPR = false;
144 width = 1;
145 } else if (AMDGPU::SReg_64RegClass.contains(reg)) {
146 isSGPR = true;
147 width = 2;
148 } else if (AMDGPU::VReg_64RegClass.contains(reg)) {
149 isSGPR = false;
150 width = 2;
Christian Konig8b1ed282013-04-10 08:39:16 +0000151 } else if (AMDGPU::VReg_96RegClass.contains(reg)) {
152 isSGPR = false;
153 width = 3;
Tom Stellard75aadc22012-12-11 21:25:42 +0000154 } else if (AMDGPU::SReg_128RegClass.contains(reg)) {
155 isSGPR = true;
156 width = 4;
157 } else if (AMDGPU::VReg_128RegClass.contains(reg)) {
158 isSGPR = false;
159 width = 4;
160 } else if (AMDGPU::SReg_256RegClass.contains(reg)) {
161 isSGPR = true;
162 width = 8;
Tom Stellard538ceeb2013-02-07 17:02:09 +0000163 } else if (AMDGPU::VReg_256RegClass.contains(reg)) {
164 isSGPR = false;
165 width = 8;
166 } else if (AMDGPU::VReg_512RegClass.contains(reg)) {
167 isSGPR = false;
168 width = 16;
Tom Stellard75aadc22012-12-11 21:25:42 +0000169 } else {
170 assert(!"Unknown register class");
171 }
Tom Stellard1c822a82013-02-07 19:39:45 +0000172 hwReg = RI->getEncodingValue(reg) & 0xff;
Tom Stellard75aadc22012-12-11 21:25:42 +0000173 maxUsed = hwReg + width - 1;
174 if (isSGPR) {
175 MaxSGPR = maxUsed > MaxSGPR ? maxUsed : MaxSGPR;
176 } else {
177 MaxVGPR = maxUsed > MaxVGPR ? maxUsed : MaxVGPR;
178 }
179 }
180 }
181 }
182 if (VCCUsed) {
183 MaxSGPR += 2;
184 }
185 SIMachineFunctionInfo * MFI = MF.getInfo<SIMachineFunctionInfo>();
Tom Stellardcb97e3a2013-04-15 17:51:35 +0000186 unsigned RsrcReg;
187 switch (MFI->ShaderType) {
188 default: // Fall through
189 case ShaderType::COMPUTE: RsrcReg = R_00B848_COMPUTE_PGM_RSRC1; break;
190 case ShaderType::GEOMETRY: RsrcReg = R_00B228_SPI_SHADER_PGM_RSRC1_GS; break;
191 case ShaderType::PIXEL: RsrcReg = R_00B028_SPI_SHADER_PGM_RSRC1_PS; break;
192 case ShaderType::VERTEX: RsrcReg = R_00B128_SPI_SHADER_PGM_RSRC1_VS; break;
193 }
194
195 OutStreamer.EmitIntValue(RsrcReg, 4);
196 OutStreamer.EmitIntValue(S_00B028_VGPRS(MaxVGPR / 4) | S_00B028_SGPRS(MaxSGPR / 8), 4);
197 if (MFI->ShaderType == ShaderType::PIXEL) {
198 OutStreamer.EmitIntValue(R_0286CC_SPI_PS_INPUT_ENA, 4);
199 OutStreamer.EmitIntValue(MFI->PSInputAddr, 4);
200 }
Tom Stellard75aadc22012-12-11 21:25:42 +0000201}