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 //===----------------------------------------------------------------------===//
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
17 //===----------------------------------------------------------------------===//
22 #include "AMDGPUUtil.h"
24 #include "SIMachineFunctionInfo.h"
25 #include "llvm/CodeGen/MachineFunctionPass.h"
26 #include "llvm/CodeGen/MachineRegisterInfo.h"
32 class SIAssignInterpRegsPass
: public MachineFunctionPass
{
39 SIAssignInterpRegsPass(TargetMachine
&tm
) :
40 MachineFunctionPass(ID
), TM(tm
) { }
42 virtual bool runOnMachineFunction(MachineFunction
&MF
);
44 const char *getPassName() const { return "SI Assign intrpolation registers"; }
47 } // End anonymous namespace
49 char SIAssignInterpRegsPass::ID
= 0;
51 #define INTERP_VALUES 16
60 FunctionPass
*llvm::createSIAssignInterpRegsPass(TargetMachine
&tm
) {
61 return new SIAssignInterpRegsPass(tm
);
64 bool SIAssignInterpRegsPass::runOnMachineFunction(MachineFunction
&MF
)
67 struct interp_info InterpUse
[INTERP_VALUES
] = {
68 {false, {AMDGPU::PERSP_SAMPLE_I
, AMDGPU::PERSP_SAMPLE_J
}, 2},
69 {false, {AMDGPU::PERSP_CENTER_I
, AMDGPU::PERSP_CENTER_J
}, 2},
70 {false, {AMDGPU::PERSP_CENTROID_I
, AMDGPU::PERSP_CENTROID_J
}, 2},
71 {false, {AMDGPU::PERSP_I_W
, AMDGPU::PERSP_J_W
, AMDGPU::PERSP_1_W
}, 3},
72 {false, {AMDGPU::LINEAR_SAMPLE_I
, AMDGPU::LINEAR_SAMPLE_J
}, 2},
73 {false, {AMDGPU::LINEAR_CENTER_I
, AMDGPU::LINEAR_CENTER_J
}, 2},
74 {false, {AMDGPU::LINEAR_CENTROID_I
, AMDGPU::LINEAR_CENTROID_J
}, 2},
75 {false, {AMDGPU::LINE_STIPPLE_TEX_COORD
}, 1},
76 {false, {AMDGPU::POS_X_FLOAT
}, 1},
77 {false, {AMDGPU::POS_Y_FLOAT
}, 1},
78 {false, {AMDGPU::POS_Z_FLOAT
}, 1},
79 {false, {AMDGPU::POS_W_FLOAT
}, 1},
80 {false, {AMDGPU::FRONT_FACE
}, 1},
81 {false, {AMDGPU::ANCILLARY
}, 1},
82 {false, {AMDGPU::SAMPLE_COVERAGE
}, 1},
83 {false, {AMDGPU::POS_FIXED_PT
}, 1}
86 SIMachineFunctionInfo
* MFI
= MF
.getInfo
<SIMachineFunctionInfo
>();
87 MachineRegisterInfo
&MRI
= MF
.getRegInfo();
89 /* First pass, mark the interpolation values that are used. */
90 for (unsigned interp_idx
= 0; interp_idx
< INTERP_VALUES
; interp_idx
++) {
91 for (unsigned reg_idx
= 0; reg_idx
< InterpUse
[interp_idx
].reg_count
;
93 InterpUse
[interp_idx
].enabled
=
94 !MRI
.use_empty(InterpUse
[interp_idx
].regs
[reg_idx
]);
98 unsigned used_vgprs
= 0;
100 /* Second pass, replace with VGPRs. */
101 for (unsigned interp_idx
= 0; interp_idx
< INTERP_VALUES
; interp_idx
++) {
102 if (!InterpUse
[interp_idx
].enabled
) {
105 MFI
->spi_ps_input_addr
|= (1 << interp_idx
);
107 for (unsigned reg_idx
= 0; reg_idx
< InterpUse
[interp_idx
].reg_count
;
108 reg_idx
++, used_vgprs
++) {
109 unsigned new_reg
= AMDGPU::VReg_32RegisterClass
->getRegister(used_vgprs
);
110 unsigned virt_reg
= MRI
.createVirtualRegister(AMDGPU::VReg_32RegisterClass
);
111 MRI
.replaceRegWith(InterpUse
[interp_idx
].regs
[reg_idx
], virt_reg
);
112 AMDGPU::utilAddLiveIn(&MF
, MRI
, TM
.getInstrInfo(), new_reg
, virt_reg
);