1 //===-- SIAssignInterpRegs.cpp - Assign interpolation registers -----------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// \brief This pass maps the pseudo interpolation registers to the correct physical
14 /// Prior to executing a fragment shader, the GPU loads interpolation
15 /// parameters into physical registers. The specific physical register that each
16 /// interpolation parameter ends up in depends on the type of the interpolation
17 /// parameter as well as how many interpolation parameters are used by the
20 //===----------------------------------------------------------------------===//
26 #include "SIMachineFunctionInfo.h"
27 #include "llvm/CodeGen/MachineFunctionPass.h"
28 #include "llvm/CodeGen/MachineInstrBuilder.h"
29 #include "llvm/CodeGen/MachineRegisterInfo.h"
35 class SIAssignInterpRegsPass : public MachineFunctionPass {
41 void addLiveIn(MachineFunction * MF, MachineRegisterInfo & MRI,
42 unsigned physReg, unsigned virtReg);
45 SIAssignInterpRegsPass(TargetMachine &tm) :
46 MachineFunctionPass(ID), TM(tm) { }
48 virtual bool runOnMachineFunction(MachineFunction &MF);
50 const char *getPassName() const { return "SI Assign intrpolation registers"; }
53 } // End anonymous namespace
55 char SIAssignInterpRegsPass::ID = 0;
57 #define INTERP_VALUES 16
58 #define REQUIRED_VALUE_MAX_INDEX 7
67 FunctionPass *llvm::createSIAssignInterpRegsPass(TargetMachine &tm) {
68 return new SIAssignInterpRegsPass(tm);
71 bool SIAssignInterpRegsPass::runOnMachineFunction(MachineFunction &MF) {
73 struct InterpInfo InterpUse[INTERP_VALUES] = {
74 {false, {AMDGPU::PERSP_SAMPLE_I, AMDGPU::PERSP_SAMPLE_J}, 2},
75 {false, {AMDGPU::PERSP_CENTER_I, AMDGPU::PERSP_CENTER_J}, 2},
76 {false, {AMDGPU::PERSP_CENTROID_I, AMDGPU::PERSP_CENTROID_J}, 2},
77 {false, {AMDGPU::PERSP_I_W, AMDGPU::PERSP_J_W, AMDGPU::PERSP_1_W}, 3},
78 {false, {AMDGPU::LINEAR_SAMPLE_I, AMDGPU::LINEAR_SAMPLE_J}, 2},
79 {false, {AMDGPU::LINEAR_CENTER_I, AMDGPU::LINEAR_CENTER_J}, 2},
80 {false, {AMDGPU::LINEAR_CENTROID_I, AMDGPU::LINEAR_CENTROID_J}, 2},
81 {false, {AMDGPU::LINE_STIPPLE_TEX_COORD}, 1},
82 {false, {AMDGPU::POS_X_FLOAT}, 1},
83 {false, {AMDGPU::POS_Y_FLOAT}, 1},
84 {false, {AMDGPU::POS_Z_FLOAT}, 1},
85 {false, {AMDGPU::POS_W_FLOAT}, 1},
86 {false, {AMDGPU::FRONT_FACE}, 1},
87 {false, {AMDGPU::ANCILLARY}, 1},
88 {false, {AMDGPU::SAMPLE_COVERAGE}, 1},
89 {false, {AMDGPU::POS_FIXED_PT}, 1}
92 SIMachineFunctionInfo * MFI = MF.getInfo<SIMachineFunctionInfo>();
93 // This pass is only needed for pixel shaders.
94 if (MFI->ShaderType != ShaderType::PIXEL) {
97 MachineRegisterInfo &MRI = MF.getRegInfo();
98 bool ForceEnable = true;
100 // First pass, mark the interpolation values that are used.
101 for (unsigned InterpIdx = 0; InterpIdx < INTERP_VALUES; InterpIdx++) {
102 for (unsigned RegIdx = 0; RegIdx < InterpUse[InterpIdx].RegCount;
104 InterpUse[InterpIdx].Enabled = InterpUse[InterpIdx].Enabled ||
105 !MRI.use_empty(InterpUse[InterpIdx].Regs[RegIdx]);
106 if (InterpUse[InterpIdx].Enabled &&
107 InterpIdx <= REQUIRED_VALUE_MAX_INDEX) {
113 // At least one interpolation mode must be enabled or else the GPU will hang.
115 InterpUse[0].Enabled = true;
118 unsigned UsedVgprs = 0;
120 // Second pass, replace with VGPRs.
121 for (unsigned InterpIdx = 0; InterpIdx < INTERP_VALUES; InterpIdx++) {
122 if (!InterpUse[InterpIdx].Enabled) {
125 MFI->SPIPSInputAddr |= (1 << InterpIdx);
127 for (unsigned RegIdx = 0; RegIdx < InterpUse[InterpIdx].RegCount;
128 RegIdx++, UsedVgprs++) {
129 unsigned NewReg = AMDGPU::VReg_32RegClass.getRegister(UsedVgprs);
130 unsigned VirtReg = MRI.createVirtualRegister(&AMDGPU::VReg_32RegClass);
131 MRI.replaceRegWith(InterpUse[InterpIdx].Regs[RegIdx], VirtReg);
132 addLiveIn(&MF, MRI, NewReg, VirtReg);
139 void SIAssignInterpRegsPass::addLiveIn(MachineFunction * MF,
140 MachineRegisterInfo & MRI,
141 unsigned physReg, unsigned virtReg) {
142 const TargetInstrInfo * TII = TM.getInstrInfo();
143 if (!MRI.isLiveIn(physReg)) {
144 MRI.addLiveIn(physReg, virtReg);
145 MF->front().addLiveIn(physReg);
146 BuildMI(MF->front(), MF->front().begin(), DebugLoc(),
147 TII->get(TargetOpcode::COPY), virtReg)
150 MRI.replaceRegWith(virtReg, MRI.getLiveInVirtReg(physReg));