9fc4aab136e0fb813b4bb51997f532321d6ee5dd
[mesa.git] / src / gallium / drivers / radeon / SICodeEmitter.cpp
1 //===-- SICodeEmitter.cpp - SI Code Emitter -------------------------------===//
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 // The SI code emitter produces machine code that can be executed directly on
11 // the GPU device.
12 //
13 //===----------------------------------------------------------------------===//
14
15
16 #include "AMDGPU.h"
17 #include "AMDGPUCodeEmitter.h"
18 #include "AMDGPUUtil.h"
19 #include "SIInstrInfo.h"
20 #include "SIMachineFunctionInfo.h"
21 #include "llvm/CodeGen/MachineFunctionPass.h"
22 #include "llvm/CodeGen/MachineInstr.h"
23 #include "llvm/CodeGen/MachineInstrBuilder.h"
24 #include "llvm/Support/FormattedStream.h"
25 #include "llvm/Target/TargetMachine.h"
26
27 #include <map>
28 #include <stdio.h>
29
30 #define LITERAL_REG 255
31 #define VGPR_BIT(src_idx) (1ULL << (9 * src_idx - 1))
32 using namespace llvm;
33
34 namespace {
35
36 class SICodeEmitter : public MachineFunctionPass, public AMDGPUCodeEmitter {
37
38 private:
39 static char ID;
40 formatted_raw_ostream &_OS;
41 const TargetMachine *TM;
42
43 //Program Info
44 unsigned MaxSGPR;
45 unsigned MaxVGPR;
46 unsigned CurrentInstrIndex;
47 std::map<int, unsigned> BBIndexes;
48
49 void InitProgramInfo(MachineFunction &MF);
50 void EmitState(MachineFunction & MF);
51 void emitInstr(MachineInstr &MI);
52
53 void outputBytes(uint64_t value, unsigned bytes);
54 unsigned GPRAlign(const MachineInstr &MI, unsigned OpNo, unsigned shift)
55 const;
56
57 public:
58 SICodeEmitter(formatted_raw_ostream &OS) : MachineFunctionPass(ID),
59 _OS(OS), TM(NULL), MaxSGPR(0), MaxVGPR(0), CurrentInstrIndex(0) { }
60 const char *getPassName() const { return "SI Code Emitter"; }
61 bool runOnMachineFunction(MachineFunction &MF);
62
63 /// getMachineOpValue - Return the encoding for MO
64 virtual uint64_t getMachineOpValue(const MachineInstr &MI,
65 const MachineOperand &MO) const;
66
67 /// GPR4AlignEncode - Encoding for when 4 consectuive registers are used
68 virtual unsigned GPR4AlignEncode(const MachineInstr &MI, unsigned OpNo)
69 const;
70
71 /// GPR2AlignEncode - Encoding for when 2 consecutive registers are used
72 virtual unsigned GPR2AlignEncode(const MachineInstr &MI, unsigned OpNo)
73 const;
74 /// i32LiteralEncode - Encode an i32 literal this is used as an operand
75 /// for an instruction in place of a register.
76 virtual uint64_t i32LiteralEncode(const MachineInstr &MI, unsigned OpNo)
77 const;
78 /// SMRDmemriEncode - Encoding for SMRD indexed loads
79 virtual uint32_t SMRDmemriEncode(const MachineInstr &MI, unsigned OpNo)
80 const;
81
82 /// VOPPostEncode - Post-Encoder method for VOP instructions
83 virtual uint64_t VOPPostEncode(const MachineInstr &MI,
84 uint64_t Value) const;
85 };
86 }
87
88 char SICodeEmitter::ID = 0;
89
90 FunctionPass *llvm::createSICodeEmitterPass(formatted_raw_ostream &OS) {
91 return new SICodeEmitter(OS);
92 }
93
94 void SICodeEmitter::EmitState(MachineFunction & MF) {
95 SIMachineFunctionInfo * MFI = MF.getInfo<SIMachineFunctionInfo>();
96 outputBytes(MaxSGPR + 1, 4);
97 outputBytes(MaxVGPR + 1, 4);
98 outputBytes(MFI->spi_ps_input_addr, 4);
99 }
100
101 void SICodeEmitter::InitProgramInfo(MachineFunction &MF) {
102 unsigned InstrIndex = 0;
103 bool VCCUsed = false;
104 const SIRegisterInfo * RI =
105 static_cast<const SIRegisterInfo*>(TM->getRegisterInfo());
106
107 for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
108 BB != BB_E; ++BB) {
109 MachineBasicBlock &MBB = *BB;
110 BBIndexes[MBB.getNumber()] = InstrIndex;
111 InstrIndex += MBB.size();
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 if (AMDGPU::SReg_32RegClass.contains(reg)) {
133 isSGPR = true;
134 width = 1;
135 } else if (AMDGPU::VReg_32RegClass.contains(reg)) {
136 isSGPR = false;
137 width = 1;
138 } else if (AMDGPU::SReg_64RegClass.contains(reg)) {
139 isSGPR = true;
140 width = 2;
141 } else if (AMDGPU::VReg_64RegClass.contains(reg)) {
142 isSGPR = false;
143 width = 2;
144 } else if (AMDGPU::SReg_128RegClass.contains(reg)) {
145 isSGPR = true;
146 width = 4;
147 } else if (AMDGPU::VReg_128RegClass.contains(reg)) {
148 isSGPR = false;
149 width = 4;
150 } else if (AMDGPU::SReg_256RegClass.contains(reg)) {
151 isSGPR = true;
152 width = 8;
153 } else {
154 assert("!Unknown register class");
155 }
156 hwReg = RI->getHWRegNum(reg);
157 maxUsed = hwReg + width - 1;
158 if (isSGPR) {
159 MaxSGPR = maxUsed > MaxSGPR ? maxUsed : MaxSGPR;
160 } else {
161 MaxVGPR = maxUsed > MaxVGPR ? maxUsed : MaxVGPR;
162 }
163 }
164 }
165 }
166 if (VCCUsed) {
167 MaxSGPR += 2;
168 }
169 }
170
171 bool SICodeEmitter::runOnMachineFunction(MachineFunction &MF)
172 {
173 TM = &MF.getTarget();
174 const AMDGPUSubtarget &STM = TM->getSubtarget<AMDGPUSubtarget>();
175
176 if (STM.dumpCode()) {
177 MF.dump();
178 }
179
180 InitProgramInfo(MF);
181
182 EmitState(MF);
183
184 for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
185 BB != BB_E; ++BB) {
186 MachineBasicBlock &MBB = *BB;
187 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
188 I != E; ++I) {
189 MachineInstr &MI = *I;
190 if (MI.getOpcode() != AMDGPU::KILL && MI.getOpcode() != AMDGPU::RETURN) {
191 emitInstr(MI);
192 CurrentInstrIndex++;
193 }
194 }
195 }
196 // Emit S_END_PGM
197 MachineInstr * End = BuildMI(MF, DebugLoc(),
198 TM->getInstrInfo()->get(AMDGPU::S_ENDPGM));
199 emitInstr(*End);
200 return false;
201 }
202
203 void SICodeEmitter::emitInstr(MachineInstr &MI)
204 {
205 const SIInstrInfo * SII = static_cast<const SIInstrInfo*>(TM->getInstrInfo());
206
207 uint64_t hwInst = getBinaryCodeForInstr(MI);
208
209 if ((hwInst & 0xffffffff) == 0xffffffff) {
210 fprintf(stderr, "Unsupported Instruction: \n");
211 MI.dump();
212 abort();
213 }
214
215 unsigned bytes = SII->getEncodingBytes(MI);
216 outputBytes(hwInst, bytes);
217 }
218
219 uint64_t SICodeEmitter::getMachineOpValue(const MachineInstr &MI,
220 const MachineOperand &MO) const
221 {
222 const SIRegisterInfo * RI =
223 static_cast<const SIRegisterInfo*>(TM->getRegisterInfo());
224
225 switch(MO.getType()) {
226 case MachineOperand::MO_Register:
227 return RI->getBinaryCode(MO.getReg());
228
229 case MachineOperand::MO_Immediate:
230 return MO.getImm();
231
232 case MachineOperand::MO_FPImmediate:
233 // XXX: Not all instructions can use inline literals
234 // XXX: We should make sure this is a 32-bit constant
235 return LITERAL_REG | (MO.getFPImm()->getValueAPF().bitcastToAPInt().getZExtValue() << 32);
236
237 case MachineOperand::MO_MachineBasicBlock:
238 return (*BBIndexes.find(MI.getParent()->getNumber())).second -
239 CurrentInstrIndex - 1;
240 default:
241 llvm_unreachable("Encoding of this operand type is not supported yet.");
242 break;
243 }
244 }
245
246 unsigned SICodeEmitter::GPRAlign(const MachineInstr &MI, unsigned OpNo,
247 unsigned shift) const
248 {
249 const SIRegisterInfo * RI =
250 static_cast<const SIRegisterInfo*>(TM->getRegisterInfo());
251 unsigned regCode = RI->getHWRegNum(MI.getOperand(OpNo).getReg());
252 return regCode >> shift;
253 }
254
255 unsigned SICodeEmitter::GPR4AlignEncode(const MachineInstr &MI,
256 unsigned OpNo) const
257 {
258 return GPRAlign(MI, OpNo, 2);
259 }
260
261 unsigned SICodeEmitter::GPR2AlignEncode(const MachineInstr &MI,
262 unsigned OpNo) const
263 {
264 return GPRAlign(MI, OpNo, 1);
265 }
266
267 uint64_t SICodeEmitter::i32LiteralEncode(const MachineInstr &MI,
268 unsigned OpNo) const
269 {
270 return LITERAL_REG | (MI.getOperand(OpNo).getImm() << 32);
271 }
272
273 #define SMRD_OFFSET_MASK 0xff
274 #define SMRD_IMM_SHIFT 8
275 #define SMRD_SBASE_MASK 0x3f
276 #define SMRD_SBASE_SHIFT 9
277 /// SMRDmemriEncode - This function is responsibe for encoding the offset
278 /// and the base ptr for SMRD instructions it should return a bit string in
279 /// this format:
280 ///
281 /// OFFSET = bits{7-0}
282 /// IMM = bits{8}
283 /// SBASE = bits{14-9}
284 ///
285 uint32_t SICodeEmitter::SMRDmemriEncode(const MachineInstr &MI,
286 unsigned OpNo) const
287 {
288 uint32_t encoding;
289
290 const MachineOperand &OffsetOp = MI.getOperand(OpNo + 1);
291
292 //XXX: Use this function for SMRD loads with register offsets
293 assert(OffsetOp.isImm());
294
295 encoding =
296 (getMachineOpValue(MI, OffsetOp) & SMRD_OFFSET_MASK)
297 | (1 << SMRD_IMM_SHIFT) //XXX If the Offset is a register we shouldn't set this bit
298 | ((GPR2AlignEncode(MI, OpNo) & SMRD_SBASE_MASK) << SMRD_SBASE_SHIFT)
299 ;
300
301 return encoding;
302 }
303
304 /// Set the "VGPR" bit for VOP args that can take either a VGPR or a SGPR.
305 /// XXX: It would be nice if we could handle this without a PostEncode function.
306 uint64_t SICodeEmitter::VOPPostEncode(const MachineInstr &MI,
307 uint64_t Value) const
308 {
309 const SIInstrInfo * SII = static_cast<const SIInstrInfo*>(TM->getInstrInfo());
310 unsigned encodingType = SII->getEncodingType(MI);
311 unsigned numSrcOps;
312 unsigned vgprBitOffset;
313
314 if (encodingType == SIInstrEncodingType::VOP3) {
315 numSrcOps = 3;
316 vgprBitOffset = 32;
317 } else {
318 numSrcOps = 1;
319 vgprBitOffset = 0;
320 }
321
322 // Add one to skip over the destination reg operand.
323 for (unsigned opIdx = 1; opIdx < numSrcOps + 1; opIdx++) {
324 if (!MI.getOperand(opIdx).isReg()) {
325 continue;
326 }
327 unsigned reg = MI.getOperand(opIdx).getReg();
328 if (AMDGPU::VReg_32RegClass.contains(reg)
329 || AMDGPU::VReg_64RegClass.contains(reg)) {
330 Value |= (VGPR_BIT(opIdx)) << vgprBitOffset;
331 }
332 }
333 return Value;
334 }
335
336
337 void SICodeEmitter::outputBytes(uint64_t value, unsigned bytes)
338 {
339 for (unsigned i = 0; i < bytes; i++) {
340 _OS.write((uint8_t) ((value >> (8 * i)) & 0xff));
341 }
342 }