AMDGPUAsmPrinter.cpp revision 141ca7fc6488bfb20ad59854cc12039e16688ed3
1f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//===-- AMDGPUAsmPrinter.cpp - AMDGPU Assebly printer  --------------------===//
2f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//
3f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//                     The LLVM Compiler Infrastructure
4f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//
5f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard// This file is distributed under the University of Illinois Open Source
6f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard// License. See LICENSE.TXT for details.
7f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//
8f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//===----------------------------------------------------------------------===//
9f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//
10f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard/// \file
11f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard///
12f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard/// The AMDGPUAsmPrinter is used to print both assembly string and also binary
13f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard/// code.  When passed an MCAsmStreamer it prints assembly and when passed
14f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard/// an MCObjectStreamer it outputs binary code.
15f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//
16f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//===----------------------------------------------------------------------===//
17f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//
18f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
19f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
20f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "AMDGPUAsmPrinter.h"
21f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "AMDGPU.h"
229a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard#include "SIDefines.h"
23f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "SIMachineFunctionInfo.h"
24f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "SIRegisterInfo.h"
25141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune#include "R600RegisterInfo.h"
26bf1efe642111043eeb7ccaf3da759f4d2d1e4647Tom Stellard#include "llvm/MC/MCContext.h"
27bf1efe642111043eeb7ccaf3da759f4d2d1e4647Tom Stellard#include "llvm/MC/MCSectionELF.h"
28f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "llvm/MC/MCStreamer.h"
29bf1efe642111043eeb7ccaf3da759f4d2d1e4647Tom Stellard#include "llvm/Support/ELF.h"
30f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "llvm/Support/TargetRegistry.h"
3158a2cbef4aac9ee7d530dfb690c78d6fc11a2371Chandler Carruth#include "llvm/Target/TargetLoweringObjectFile.h"
32f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
33f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardusing namespace llvm;
34f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
35f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
36f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardstatic AsmPrinter *createAMDGPUAsmPrinterPass(TargetMachine &tm,
37f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                              MCStreamer &Streamer) {
38f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return new AMDGPUAsmPrinter(tm, Streamer);
39f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
40f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
41f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardextern "C" void LLVMInitializeR600AsmPrinter() {
42f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  TargetRegistry::RegisterAsmPrinter(TheAMDGPUTarget, createAMDGPUAsmPrinterPass);
43f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
44f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
45f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard/// We need to override this function so we can avoid
46f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard/// the call to EmitFunctionHeader(), which the MCPureStreamer can't handle.
47f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
48f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>();
49f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (STM.dumpCode()) {
50f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
51f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MF.dump();
52f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#endif
53f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
54f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  SetupMachineFunction(MF);
553ce2ec847885b004c768869b825be1ff9d98eca3Tom Stellard  if (OutStreamer.hasRawTextSupport()) {
563ce2ec847885b004c768869b825be1ff9d98eca3Tom Stellard    OutStreamer.EmitRawText("@" + MF.getName() + ":");
573ce2ec847885b004c768869b825be1ff9d98eca3Tom Stellard  }
58141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune
59141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune  const MCSectionELF *ConfigSection = getObjFileLowering().getContext()
60141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune                                              .getELFSection(".AMDGPU.config",
61141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune                                              ELF::SHT_NULL, 0,
62141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune                                              SectionKind::getReadOnly());
63141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune  OutStreamer.SwitchSection(ConfigSection);
64f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (STM.device()->getGeneration() > AMDGPUDeviceInfo::HD6XXX) {
65141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune    EmitProgramInfoSI(MF);
66141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune  } else {
67141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune    EmitProgramInfoR600(MF);
68f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
69bf1efe642111043eeb7ccaf3da759f4d2d1e4647Tom Stellard  OutStreamer.SwitchSection(getObjFileLowering().getTextSection());
70f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  EmitFunctionBody();
71f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return false;
72f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
73f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
74141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeunevoid AMDGPUAsmPrinter::EmitProgramInfoR600(MachineFunction &MF) {
75141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune  unsigned MaxGPR = 0;
76141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune  const R600RegisterInfo * RI =
77141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune                static_cast<const R600RegisterInfo*>(TM.getRegisterInfo());
78141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune
79141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune  for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
80141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune                                                  BB != BB_E; ++BB) {
81141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune    MachineBasicBlock &MBB = *BB;
82141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune    for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
83141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune                                                    I != E; ++I) {
84141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune      MachineInstr &MI = *I;
85141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune      unsigned numOperands = MI.getNumOperands();
86141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune      for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) {
87141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune        MachineOperand & MO = MI.getOperand(op_idx);
88141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune        if (!MO.isReg())
89141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune          continue;
90141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune        unsigned HWReg = RI->getEncodingValue(MO.getReg()) & 0xff;
91141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune
92141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune        // Register with value > 127 aren't GPR
93141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune        if (HWReg > 127)
94141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune          continue;
95141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune        MaxGPR = std::max(MaxGPR, HWReg);
96141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune      }
97141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune    }
98141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune  }
99141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune  OutStreamer.EmitIntValue(MaxGPR + 1, 4);
100141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune}
101141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeune
102141ca7fc6488bfb20ad59854cc12039e16688ed3Vincent Lejeunevoid AMDGPUAsmPrinter::EmitProgramInfoSI(MachineFunction &MF) {
103f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  unsigned MaxSGPR = 0;
104f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  unsigned MaxVGPR = 0;
105f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  bool VCCUsed = false;
106f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  const SIRegisterInfo * RI =
107f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                static_cast<const SIRegisterInfo*>(TM.getRegisterInfo());
108f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
109f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
110f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                                  BB != BB_E; ++BB) {
111f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MachineBasicBlock &MBB = *BB;
112f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
113f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                                    I != E; ++I) {
114f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      MachineInstr &MI = *I;
115f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
116f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      unsigned numOperands = MI.getNumOperands();
117f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) {
118f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        MachineOperand & MO = MI.getOperand(op_idx);
119f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        unsigned maxUsed;
120f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        unsigned width = 0;
121f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        bool isSGPR = false;
122f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        unsigned reg;
123f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        unsigned hwReg;
124f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        if (!MO.isReg()) {
125f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard          continue;
126f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        }
127f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        reg = MO.getReg();
128f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        if (reg == AMDGPU::VCC) {
129f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard          VCCUsed = true;
130f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard          continue;
131f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        }
132f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        switch (reg) {
133f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        default: break;
134f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        case AMDGPU::EXEC:
135f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        case AMDGPU::M0:
136f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard          continue;
137f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        }
138f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
139f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        if (AMDGPU::SReg_32RegClass.contains(reg)) {
140f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard          isSGPR = true;
141f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard          width = 1;
142f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        } else if (AMDGPU::VReg_32RegClass.contains(reg)) {
143f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard          isSGPR = false;
144f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard          width = 1;
145f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        } else if (AMDGPU::SReg_64RegClass.contains(reg)) {
146f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard          isSGPR = true;
147f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard          width = 2;
148f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        } else if (AMDGPU::VReg_64RegClass.contains(reg)) {
149f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard          isSGPR = false;
150f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard          width = 2;
1514d0e8a8a3e2e5b98f598acad4d57452b99d52e74Christian Konig        } else if (AMDGPU::VReg_96RegClass.contains(reg)) {
1524d0e8a8a3e2e5b98f598acad4d57452b99d52e74Christian Konig          isSGPR = false;
1534d0e8a8a3e2e5b98f598acad4d57452b99d52e74Christian Konig          width = 3;
154f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        } else if (AMDGPU::SReg_128RegClass.contains(reg)) {
155f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard          isSGPR = true;
156f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard          width = 4;
157f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        } else if (AMDGPU::VReg_128RegClass.contains(reg)) {
158f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard          isSGPR = false;
159f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard          width = 4;
160f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        } else if (AMDGPU::SReg_256RegClass.contains(reg)) {
161f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard          isSGPR = true;
162f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard          width = 8;
16336ba9091843bd1205fe3499ba4b55bbedc6583c9Tom Stellard        } else if (AMDGPU::VReg_256RegClass.contains(reg)) {
16436ba9091843bd1205fe3499ba4b55bbedc6583c9Tom Stellard          isSGPR = false;
16536ba9091843bd1205fe3499ba4b55bbedc6583c9Tom Stellard          width = 8;
16636ba9091843bd1205fe3499ba4b55bbedc6583c9Tom Stellard        } else if (AMDGPU::VReg_512RegClass.contains(reg)) {
16736ba9091843bd1205fe3499ba4b55bbedc6583c9Tom Stellard          isSGPR = false;
16836ba9091843bd1205fe3499ba4b55bbedc6583c9Tom Stellard          width = 16;
169f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        } else {
170f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard          assert(!"Unknown register class");
171f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        }
172184f5c1545e06a99951f14d846a1d853ff19a2b8Tom Stellard        hwReg = RI->getEncodingValue(reg) & 0xff;
173f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        maxUsed = hwReg + width - 1;
174f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        if (isSGPR) {
175f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard          MaxSGPR = maxUsed > MaxSGPR ? maxUsed : MaxSGPR;
176f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        } else {
177f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard          MaxVGPR = maxUsed > MaxVGPR ? maxUsed : MaxVGPR;
178f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard        }
179f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      }
180f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    }
181f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
182f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (VCCUsed) {
183f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MaxSGPR += 2;
184f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
185f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  SIMachineFunctionInfo * MFI = MF.getInfo<SIMachineFunctionInfo>();
1869a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard  unsigned RsrcReg;
1879a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard  switch (MFI->ShaderType) {
1889a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard  default: // Fall through
1899a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard  case ShaderType::COMPUTE:  RsrcReg = R_00B848_COMPUTE_PGM_RSRC1; break;
1909a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard  case ShaderType::GEOMETRY: RsrcReg = R_00B228_SPI_SHADER_PGM_RSRC1_GS; break;
1919a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard  case ShaderType::PIXEL:    RsrcReg = R_00B028_SPI_SHADER_PGM_RSRC1_PS; break;
1929a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard  case ShaderType::VERTEX:   RsrcReg = R_00B128_SPI_SHADER_PGM_RSRC1_VS; break;
1939a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard  }
1949a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard
1959a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard  OutStreamer.EmitIntValue(RsrcReg, 4);
1969a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard  OutStreamer.EmitIntValue(S_00B028_VGPRS(MaxVGPR / 4) | S_00B028_SGPRS(MaxSGPR / 8), 4);
1979a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard  if (MFI->ShaderType == ShaderType::PIXEL) {
1989a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard    OutStreamer.EmitIntValue(R_0286CC_SPI_PS_INPUT_ENA, 4);
1999a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard    OutStreamer.EmitIntValue(MFI->PSInputAddr, 4);
2009a256300f8f61937f5f7a148b9cb09936d103a97Tom Stellard  }
201f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
202