• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
SIAssignInterpRegsPass(TargetMachine & tm)42   SIAssignInterpRegsPass(TargetMachine &tm) :
43     MachineFunctionPass(ID), TM(tm) { }
44 
45   virtual bool runOnMachineFunction(MachineFunction &MF);
46 
getPassName() const47   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 
createSIAssignInterpRegsPass(TargetMachine & tm)63 FunctionPass *llvm::createSIAssignInterpRegsPass(TargetMachine &tm) {
64   return new SIAssignInterpRegsPass(tm);
65 }
66 
runOnMachineFunction(MachineFunction & MF)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 
AddLiveIn(MachineFunction * MF,MachineRegisterInfo & MRI,unsigned physReg,unsigned virtReg)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