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