Home | History | Annotate | Download | only in radeon
      1 //===-- SIAssignInterpRegs.cpp - Assign interpolation registers -----------===//
      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 // This pass maps the pseudo interpolation registers to the correct physical
     11 // registers.  Prior to executing a fragment shader, the GPU loads interpolation
     12 // parameters into physical registers.  The specific physical register that each
     13 // interpolation parameter ends up in depends on the type of the interpolation
     14 // parameter as well as how many interpolation parameters are used by the
     15 // shader.
     16 //
     17 //===----------------------------------------------------------------------===//
     18 
     19 
     20 
     21 #include "AMDGPU.h"
     22 #include "AMDIL.h"
     23 #include "SIMachineFunctionInfo.h"
     24 #include "llvm/CodeGen/MachineFunctionPass.h"
     25 #include "llvm/CodeGen/MachineInstrBuilder.h"
     26 #include "llvm/CodeGen/MachineRegisterInfo.h"
     27 
     28 using namespace llvm;
     29 
     30 namespace {
     31 
     32 class SIAssignInterpRegsPass : public MachineFunctionPass {
     33 
     34 private:
     35   static char ID;
     36   TargetMachine &TM;
     37 
     38   void AddLiveIn(MachineFunction * MF,  MachineRegisterInfo & MRI,
     39                  unsigned physReg, unsigned virtReg);
     40 
     41 public:
     42   SIAssignInterpRegsPass(TargetMachine &tm) :
     43     MachineFunctionPass(ID), TM(tm) { }
     44 
     45   virtual bool runOnMachineFunction(MachineFunction &MF);
     46 
     47   const char *getPassName() const { return "SI Assign intrpolation registers"; }
     48 };
     49 
     50 } // End anonymous namespace
     51 
     52 char SIAssignInterpRegsPass::ID = 0;
     53 
     54 #define INTERP_VALUES 16
     55 
     56 struct interp_info {
     57   bool enabled;
     58   unsigned regs[3];
     59   unsigned reg_count;
     60 };
     61 
     62 
     63 FunctionPass *llvm::createSIAssignInterpRegsPass(TargetMachine &tm) {
     64   return new SIAssignInterpRegsPass(tm);
     65 }
     66 
     67 bool SIAssignInterpRegsPass::runOnMachineFunction(MachineFunction &MF)
     68 {
     69 
     70   struct interp_info InterpUse[INTERP_VALUES] = {
     71     {false, {AMDGPU::PERSP_SAMPLE_I, AMDGPU::PERSP_SAMPLE_J}, 2},
     72     {false, {AMDGPU::PERSP_CENTER_I, AMDGPU::PERSP_CENTER_J}, 2},
     73     {false, {AMDGPU::PERSP_CENTROID_I, AMDGPU::PERSP_CENTROID_J}, 2},
     74     {false, {AMDGPU::PERSP_I_W, AMDGPU::PERSP_J_W, AMDGPU::PERSP_1_W}, 3},
     75     {false, {AMDGPU::LINEAR_SAMPLE_I, AMDGPU::LINEAR_SAMPLE_J}, 2},
     76     {false, {AMDGPU::LINEAR_CENTER_I, AMDGPU::LINEAR_CENTER_J}, 2},
     77     {false, {AMDGPU::LINEAR_CENTROID_I, AMDGPU::LINEAR_CENTROID_J}, 2},
     78     {false, {AMDGPU::LINE_STIPPLE_TEX_COORD}, 1},
     79     {false, {AMDGPU::POS_X_FLOAT}, 1},
     80     {false, {AMDGPU::POS_Y_FLOAT}, 1},
     81     {false, {AMDGPU::POS_Z_FLOAT}, 1},
     82     {false, {AMDGPU::POS_W_FLOAT}, 1},
     83     {false, {AMDGPU::FRONT_FACE}, 1},
     84     {false, {AMDGPU::ANCILLARY}, 1},
     85     {false, {AMDGPU::SAMPLE_COVERAGE}, 1},
     86     {false, {AMDGPU::POS_FIXED_PT}, 1}
     87   };
     88 
     89   SIMachineFunctionInfo * MFI = MF.getInfo<SIMachineFunctionInfo>();
     90   MachineRegisterInfo &MRI = MF.getRegInfo();
     91 
     92   /* First pass, mark the interpolation values that are used. */
     93   for (unsigned interp_idx = 0; interp_idx < INTERP_VALUES; interp_idx++) {
     94     for (unsigned reg_idx = 0; reg_idx < InterpUse[interp_idx].reg_count;
     95                                                                reg_idx++) {
     96       InterpUse[interp_idx].enabled =
     97                             !MRI.use_empty(InterpUse[interp_idx].regs[reg_idx]);
     98     }
     99   }
    100 
    101   unsigned used_vgprs = 0;
    102 
    103   /* Second pass, replace with VGPRs. */
    104   for (unsigned interp_idx = 0; interp_idx < INTERP_VALUES; interp_idx++) {
    105     if (!InterpUse[interp_idx].enabled) {
    106       continue;
    107     }
    108     MFI->spi_ps_input_addr |= (1 << interp_idx);
    109 
    110     for (unsigned reg_idx = 0; reg_idx < InterpUse[interp_idx].reg_count;
    111                                                   reg_idx++, used_vgprs++) {
    112       unsigned new_reg = AMDGPU::VReg_32RegClass.getRegister(used_vgprs);
    113       unsigned virt_reg = MRI.createVirtualRegister(&AMDGPU::VReg_32RegClass);
    114       MRI.replaceRegWith(InterpUse[interp_idx].regs[reg_idx], virt_reg);
    115       AddLiveIn(&MF, MRI, new_reg, virt_reg);
    116     }
    117   }
    118 
    119   return false;
    120 }
    121 
    122 void SIAssignInterpRegsPass::AddLiveIn(MachineFunction * MF,
    123                            MachineRegisterInfo & MRI,
    124                            unsigned physReg, unsigned virtReg)
    125 {
    126     const TargetInstrInfo * TII = TM.getInstrInfo();
    127     if (!MRI.isLiveIn(physReg)) {
    128       MRI.addLiveIn(physReg, virtReg);
    129       MF->front().addLiveIn(physReg);
    130       BuildMI(MF->front(), MF->front().begin(), DebugLoc(),
    131               TII->get(TargetOpcode::COPY), virtReg)
    132                 .addReg(physReg);
    133     } else {
    134       MRI.replaceRegWith(virtReg, MRI.getLiveInVirtReg(physReg));
    135     }
    136 }
    137