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 28using namespace llvm; 29 30namespace { 31 32class SIAssignInterpRegsPass : public MachineFunctionPass { 33 34private: 35 static char ID; 36 TargetMachine &TM; 37 38 void AddLiveIn(MachineFunction * MF, MachineRegisterInfo & MRI, 39 unsigned physReg, unsigned virtReg); 40 41public: 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 52char SIAssignInterpRegsPass::ID = 0; 53 54#define INTERP_VALUES 16 55 56struct interp_info { 57 bool enabled; 58 unsigned regs[3]; 59 unsigned reg_count; 60}; 61 62 63FunctionPass *llvm::createSIAssignInterpRegsPass(TargetMachine &tm) { 64 return new SIAssignInterpRegsPass(tm); 65} 66 67bool 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 122void 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