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 "SIMachineFunctionInfo.h"
     23 #include "SIRegisterInfo.h"
     24 #include "llvm/MC/MCStreamer.h"
     25 #include "llvm/Support/TargetRegistry.h"
     26 #include "llvm/Target/TargetLoweringObjectFile.h"
     27 
     28 using namespace llvm;
     29 
     30 
     31 static AsmPrinter *createAMDGPUAsmPrinterPass(TargetMachine &tm,
     32                                               MCStreamer &Streamer) {
     33   return new AMDGPUAsmPrinter(tm, Streamer);
     34 }
     35 
     36 extern "C" void LLVMInitializeR600AsmPrinter() {
     37   TargetRegistry::RegisterAsmPrinter(TheAMDGPUTarget, createAMDGPUAsmPrinterPass);
     38 }
     39 
     40 /// We need to override this function so we can avoid
     41 /// the call to EmitFunctionHeader(), which the MCPureStreamer can't handle.
     42 bool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
     43   const AMDGPUSubtarget &STM = TM.getSubtarget<AMDGPUSubtarget>();
     44   if (STM.dumpCode()) {
     45 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
     46     MF.dump();
     47 #endif
     48   }
     49   SetupMachineFunction(MF);
     50   if (OutStreamer.hasRawTextSupport()) {
     51     OutStreamer.EmitRawText("@" + MF.getName() + ":");
     52   }
     53   OutStreamer.SwitchSection(getObjFileLowering().getTextSection());
     54   if (STM.device()->getGeneration() > AMDGPUDeviceInfo::HD6XXX) {
     55     EmitProgramInfo(MF);
     56   }
     57   EmitFunctionBody();
     58   return false;
     59 }
     60 
     61 void AMDGPUAsmPrinter::EmitProgramInfo(MachineFunction &MF) {
     62   unsigned MaxSGPR = 0;
     63   unsigned MaxVGPR = 0;
     64   bool VCCUsed = false;
     65   const SIRegisterInfo * RI =
     66                 static_cast<const SIRegisterInfo*>(TM.getRegisterInfo());
     67 
     68   for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
     69                                                   BB != BB_E; ++BB) {
     70     MachineBasicBlock &MBB = *BB;
     71     for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
     72                                                     I != E; ++I) {
     73       MachineInstr &MI = *I;
     74 
     75       unsigned numOperands = MI.getNumOperands();
     76       for (unsigned op_idx = 0; op_idx < numOperands; op_idx++) {
     77         MachineOperand & MO = MI.getOperand(op_idx);
     78         unsigned maxUsed;
     79         unsigned width = 0;
     80         bool isSGPR = false;
     81         unsigned reg;
     82         unsigned hwReg;
     83         if (!MO.isReg()) {
     84           continue;
     85         }
     86         reg = MO.getReg();
     87         if (reg == AMDGPU::VCC) {
     88           VCCUsed = true;
     89           continue;
     90         }
     91         switch (reg) {
     92         default: break;
     93         case AMDGPU::EXEC:
     94         case AMDGPU::M0:
     95           continue;
     96         }
     97 
     98         if (AMDGPU::SReg_32RegClass.contains(reg)) {
     99           isSGPR = true;
    100           width = 1;
    101         } else if (AMDGPU::VReg_32RegClass.contains(reg)) {
    102           isSGPR = false;
    103           width = 1;
    104         } else if (AMDGPU::SReg_64RegClass.contains(reg)) {
    105           isSGPR = true;
    106           width = 2;
    107         } else if (AMDGPU::VReg_64RegClass.contains(reg)) {
    108           isSGPR = false;
    109           width = 2;
    110         } else if (AMDGPU::SReg_128RegClass.contains(reg)) {
    111           isSGPR = true;
    112           width = 4;
    113         } else if (AMDGPU::VReg_128RegClass.contains(reg)) {
    114           isSGPR = false;
    115           width = 4;
    116         } else if (AMDGPU::SReg_256RegClass.contains(reg)) {
    117           isSGPR = true;
    118           width = 8;
    119         } else if (AMDGPU::VReg_256RegClass.contains(reg)) {
    120           isSGPR = false;
    121           width = 8;
    122         } else if (AMDGPU::VReg_512RegClass.contains(reg)) {
    123           isSGPR = false;
    124           width = 16;
    125         } else {
    126           assert(!"Unknown register class");
    127         }
    128         hwReg = RI->getEncodingValue(reg) & 0xff;
    129         maxUsed = hwReg + width - 1;
    130         if (isSGPR) {
    131           MaxSGPR = maxUsed > MaxSGPR ? maxUsed : MaxSGPR;
    132         } else {
    133           MaxVGPR = maxUsed > MaxVGPR ? maxUsed : MaxVGPR;
    134         }
    135       }
    136     }
    137   }
    138   if (VCCUsed) {
    139     MaxSGPR += 2;
    140   }
    141   SIMachineFunctionInfo * MFI = MF.getInfo<SIMachineFunctionInfo>();
    142   OutStreamer.EmitIntValue(MaxSGPR + 1, 4);
    143   OutStreamer.EmitIntValue(MaxVGPR + 1, 4);
    144   OutStreamer.EmitIntValue(MFI->PSInputAddr, 4);
    145 }
    146