AMDGPUAsmPrinter.cpp revision 256281
1//===-- 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"
22#include "SIDefines.h"
23#include "SIMachineFunctionInfo.h"
24#include "SIRegisterInfo.h"
25#include "R600Defines.h"
26#include "R600MachineFunctionInfo.h"
27#include "R600RegisterInfo.h"
28#include "llvm/MC/MCContext.h"
29#include "llvm/MC/MCSectionELF.h"
30#include "llvm/MC/MCStreamer.h"
31#include "llvm/Support/ELF.h"
32#include "llvm/Support/TargetRegistry.h"
33#include "llvm/Target/TargetLoweringObjectFile.h"
34
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);
57  if (OutStreamer.hasRawTextSupport()) {
58    OutStreamer.EmitRawText("@" + MF.getName() + ":");
59  }
60
61  const MCSectionELF *ConfigSection = getObjFileLowering().getContext()
62                                              .getELFSection(".AMDGPU.config",
63                                              ELF::SHT_PROGBITS, 0,
64                                              SectionKind::getReadOnly());
65  OutStreamer.SwitchSection(ConfigSection);
66  if (STM.device()->getGeneration() > AMDGPUDeviceInfo::HD6XXX) {
67    EmitProgramInfoSI(MF);
68  } else {
69    EmitProgramInfoR600(MF);
70  }
71  OutStreamer.SwitchSection(getObjFileLowering().getTextSection());
72  EmitFunctionBody();
73  return false;
74}
75
76void AMDGPUAsmPrinter::EmitProgramInfoR600(MachineFunction &MF) {
77  unsigned MaxGPR = 0;
78  bool killPixel = false;
79  const R600RegisterInfo * RI =
80                static_cast<const R600RegisterInfo*>(TM.getRegisterInfo());
81  R600MachineFunctionInfo *MFI = MF.getInfo<R600MachineFunctionInfo>();
82  const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>();
83
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;
90      if (MI.getOpcode() == AMDGPU::KILLGT)
91        killPixel = true;
92      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  }
106
107  unsigned RsrcReg;
108  if (STM.device()->getGeneration() >= AMDGPUDeviceInfo::HD5XXX) {
109    // 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);
133}
134
135void AMDGPUAsmPrinter::EmitProgramInfoSI(MachineFunction &MF) {
136  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:
168        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;
184        } else if (AMDGPU::VReg_96RegClass.contains(reg)) {
185          isSGPR = false;
186          width = 3;
187        } 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;
196        } 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;
202        } else {
203          assert(!"Unknown register class");
204        }
205        hwReg = RI->getEncodingValue(reg) & 0xff;
206        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>();
219  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  }
234}
235