Home | History | Annotate | Download | only in R600
      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 "R600Defines.h"
     23 #include "R600MachineFunctionInfo.h"
     24 #include "R600RegisterInfo.h"
     25 #include "SIDefines.h"
     26 #include "SIMachineFunctionInfo.h"
     27 #include "SIRegisterInfo.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/MathExtras.h"
     33 #include "llvm/Support/TargetRegistry.h"
     34 #include "llvm/Target/TargetLoweringObjectFile.h"
     35 
     36 using namespace llvm;
     37 
     38 
     39 static AsmPrinter *createAMDGPUAsmPrinterPass(TargetMachine &tm,
     40                                               MCStreamer &Streamer) {
     41   return new AMDGPUAsmPrinter(tm, Streamer);
     42 }
     43 
     44 extern "C" void LLVMInitializeR600AsmPrinter() {
     45   TargetRegistry::RegisterAsmPrinter(TheAMDGPUTarget, createAMDGPUAsmPrinterPass);
     46 }
     47 
     48 /// We need to override this function so we can avoid
     49 /// the call to EmitFunctionHeader(), which the MCPureStreamer can't handle.
     50 bool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
     51   const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>();
     52   if (STM.dumpCode()) {
     53 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
     54     MF.dump();
     55 #endif
     56   }
     57   SetupMachineFunction(MF);
     58   if (OutStreamer.hasRawTextSupport()) {
     59     OutStreamer.EmitRawText("@" + MF.getName() + ":");
     60   }
     61 
     62   const MCSectionELF *ConfigSection = getObjFileLowering().getContext()
     63                                               .getELFSection(".AMDGPU.config",
     64                                               ELF::SHT_PROGBITS, 0,
     65                                               SectionKind::getReadOnly());
     66   OutStreamer.SwitchSection(ConfigSection);
     67   if (STM.getGeneration() > AMDGPUSubtarget::NORTHERN_ISLANDS) {
     68     EmitProgramInfoSI(MF);
     69   } else {
     70     EmitProgramInfoR600(MF);
     71   }
     72   OutStreamer.SwitchSection(getObjFileLowering().getTextSection());
     73   EmitFunctionBody();
     74   return false;
     75 }
     76 
     77 void AMDGPUAsmPrinter::EmitProgramInfoR600(MachineFunction &MF) {
     78   unsigned MaxGPR = 0;
     79   bool killPixel = false;
     80   const R600RegisterInfo * RI =
     81                 static_cast<const R600RegisterInfo*>(TM.getRegisterInfo());
     82   R600MachineFunctionInfo *MFI = MF.getInfo<R600MachineFunctionInfo>();
     83   const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>();
     84 
     85   for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
     86                                                   BB != BB_E; ++BB) {
     87     MachineBasicBlock &MBB = *BB;
     88     for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
     89                                                     I != E; ++I) {
     90       MachineInstr &MI = *I;
     91       if (MI.getOpcode() == AMDGPU::KILLGT)
     92         killPixel = true;
     93       unsigned numOperands = MI.getNumOperands();
     94       for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) {
     95         MachineOperand & MO = MI.getOperand(op_idx);
     96         if (!MO.isReg())
     97           continue;
     98         unsigned HWReg = RI->getEncodingValue(MO.getReg()) & 0xff;
     99 
    100         // Register with value > 127 aren't GPR
    101         if (HWReg > 127)
    102           continue;
    103         MaxGPR = std::max(MaxGPR, HWReg);
    104       }
    105     }
    106   }
    107 
    108   unsigned RsrcReg;
    109   if (STM.getGeneration() >= AMDGPUSubtarget::EVERGREEN) {
    110     // Evergreen / Northern Islands
    111     switch (MFI->ShaderType) {
    112     default: // Fall through
    113     case ShaderType::COMPUTE:  RsrcReg = R_0288D4_SQ_PGM_RESOURCES_LS; break;
    114     case ShaderType::GEOMETRY: RsrcReg = R_028878_SQ_PGM_RESOURCES_GS; break;
    115     case ShaderType::PIXEL:    RsrcReg = R_028844_SQ_PGM_RESOURCES_PS; break;
    116     case ShaderType::VERTEX:   RsrcReg = R_028860_SQ_PGM_RESOURCES_VS; break;
    117     }
    118   } else {
    119     // R600 / R700
    120     switch (MFI->ShaderType) {
    121     default: // Fall through
    122     case ShaderType::GEOMETRY: // Fall through
    123     case ShaderType::COMPUTE:  // Fall through
    124     case ShaderType::VERTEX:   RsrcReg = R_028868_SQ_PGM_RESOURCES_VS; break;
    125     case ShaderType::PIXEL:    RsrcReg = R_028850_SQ_PGM_RESOURCES_PS; break;
    126     }
    127   }
    128 
    129   OutStreamer.EmitIntValue(RsrcReg, 4);
    130   OutStreamer.EmitIntValue(S_NUM_GPRS(MaxGPR + 1) |
    131                            S_STACK_SIZE(MFI->StackSize), 4);
    132   OutStreamer.EmitIntValue(R_02880C_DB_SHADER_CONTROL, 4);
    133   OutStreamer.EmitIntValue(S_02880C_KILL_ENABLE(killPixel), 4);
    134 
    135   if (MFI->ShaderType == ShaderType::COMPUTE) {
    136     OutStreamer.EmitIntValue(R_0288E8_SQ_LDS_ALLOC, 4);
    137     OutStreamer.EmitIntValue(RoundUpToAlignment(MFI->LDSSize, 4) >> 2, 4);
    138   }
    139 }
    140 
    141 void AMDGPUAsmPrinter::EmitProgramInfoSI(MachineFunction &MF) {
    142   unsigned MaxSGPR = 0;
    143   unsigned MaxVGPR = 0;
    144   bool VCCUsed = false;
    145   const SIRegisterInfo * RI =
    146                 static_cast<const SIRegisterInfo*>(TM.getRegisterInfo());
    147 
    148   for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
    149                                                   BB != BB_E; ++BB) {
    150     MachineBasicBlock &MBB = *BB;
    151     for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
    152                                                     I != E; ++I) {
    153       MachineInstr &MI = *I;
    154 
    155       unsigned numOperands = MI.getNumOperands();
    156       for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) {
    157         MachineOperand & MO = MI.getOperand(op_idx);
    158         unsigned maxUsed;
    159         unsigned width = 0;
    160         bool isSGPR = false;
    161         unsigned reg;
    162         unsigned hwReg;
    163         if (!MO.isReg()) {
    164           continue;
    165         }
    166         reg = MO.getReg();
    167         if (reg == AMDGPU::VCC) {
    168           VCCUsed = true;
    169           continue;
    170         }
    171         switch (reg) {
    172         default: break;
    173         case AMDGPU::EXEC:
    174         case AMDGPU::M0:
    175           continue;
    176         }
    177 
    178         if (AMDGPU::SReg_32RegClass.contains(reg)) {
    179           isSGPR = true;
    180           width = 1;
    181         } else if (AMDGPU::VReg_32RegClass.contains(reg)) {
    182           isSGPR = false;
    183           width = 1;
    184         } else if (AMDGPU::SReg_64RegClass.contains(reg)) {
    185           isSGPR = true;
    186           width = 2;
    187         } else if (AMDGPU::VReg_64RegClass.contains(reg)) {
    188           isSGPR = false;
    189           width = 2;
    190         } else if (AMDGPU::VReg_96RegClass.contains(reg)) {
    191           isSGPR = false;
    192           width = 3;
    193         } else if (AMDGPU::SReg_128RegClass.contains(reg)) {
    194           isSGPR = true;
    195           width = 4;
    196         } else if (AMDGPU::VReg_128RegClass.contains(reg)) {
    197           isSGPR = false;
    198           width = 4;
    199         } else if (AMDGPU::SReg_256RegClass.contains(reg)) {
    200           isSGPR = true;
    201           width = 8;
    202         } else if (AMDGPU::VReg_256RegClass.contains(reg)) {
    203           isSGPR = false;
    204           width = 8;
    205         } else if (AMDGPU::VReg_512RegClass.contains(reg)) {
    206           isSGPR = false;
    207           width = 16;
    208         } else {
    209           assert(!"Unknown register class");
    210         }
    211         hwReg = RI->getEncodingValue(reg) & 0xff;
    212         maxUsed = hwReg + width - 1;
    213         if (isSGPR) {
    214           MaxSGPR = maxUsed > MaxSGPR ? maxUsed : MaxSGPR;
    215         } else {
    216           MaxVGPR = maxUsed > MaxVGPR ? maxUsed : MaxVGPR;
    217         }
    218       }
    219     }
    220   }
    221   if (VCCUsed) {
    222     MaxSGPR += 2;
    223   }
    224   SIMachineFunctionInfo * MFI = MF.getInfo<SIMachineFunctionInfo>();
    225   unsigned RsrcReg;
    226   switch (MFI->ShaderType) {
    227   default: // Fall through
    228   case ShaderType::COMPUTE:  RsrcReg = R_00B848_COMPUTE_PGM_RSRC1; break;
    229   case ShaderType::GEOMETRY: RsrcReg = R_00B228_SPI_SHADER_PGM_RSRC1_GS; break;
    230   case ShaderType::PIXEL:    RsrcReg = R_00B028_SPI_SHADER_PGM_RSRC1_PS; break;
    231   case ShaderType::VERTEX:   RsrcReg = R_00B128_SPI_SHADER_PGM_RSRC1_VS; break;
    232   }
    233 
    234   OutStreamer.EmitIntValue(RsrcReg, 4);
    235   OutStreamer.EmitIntValue(S_00B028_VGPRS(MaxVGPR / 4) | S_00B028_SGPRS(MaxSGPR / 8), 4);
    236 
    237   if (MFI->ShaderType == ShaderType::COMPUTE) {
    238     OutStreamer.EmitIntValue(R_00B84C_COMPUTE_PGM_RSRC2, 4);
    239     OutStreamer.EmitIntValue(S_00B84C_LDS_SIZE(RoundUpToAlignment(MFI->LDSSize, 256) >> 8), 4);
    240   }
    241   if (MFI->ShaderType == ShaderType::PIXEL) {
    242     OutStreamer.EmitIntValue(R_00B02C_SPI_SHADER_PGM_RSRC2_PS, 4);
    243     OutStreamer.EmitIntValue(S_00B02C_EXTRA_LDS_SIZE(RoundUpToAlignment(MFI->LDSSize, 256) >> 8), 4);
    244     OutStreamer.EmitIntValue(R_0286CC_SPI_PS_INPUT_ENA, 4);
    245     OutStreamer.EmitIntValue(MFI->PSInputAddr, 4);
    246   }
    247 }
    248