394ee7006ce6b22562c7ab40bcb2476e3d53e556
[mesa.git] / src / gallium / drivers / radeon / R600LowerShaderInstructions.cpp
1 //===-- R600LowerShaderInstructions.cpp - TODO: Add brief description -------===//
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 // TODO: Add full description
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "AMDGPU.h"
15 #include "AMDGPULowerShaderInstructions.h"
16 #include "AMDIL.h"
17 #include "AMDILInstrInfo.h"
18 #include "llvm/CodeGen/MachineFunctionPass.h"
19 #include "llvm/CodeGen/MachineInstrBuilder.h"
20 #include "llvm/CodeGen/MachineRegisterInfo.h"
21
22 using namespace llvm;
23
24 namespace {
25 class R600LowerShaderInstructionsPass : public MachineFunctionPass,
26 public AMDGPULowerShaderInstructionsPass {
27
28 private:
29 static char ID;
30 TargetMachine &TM;
31
32 void lowerEXPORT_REG_FAKE(MachineInstr &MI, MachineBasicBlock &MBB,
33 MachineBasicBlock::iterator I);
34 void lowerLOAD_INPUT(MachineInstr & MI);
35 bool lowerSTORE_OUTPUT(MachineInstr & MI, MachineBasicBlock &MBB,
36 MachineBasicBlock::iterator I);
37
38 public:
39 R600LowerShaderInstructionsPass(TargetMachine &tm) :
40 MachineFunctionPass(ID), TM(tm) { }
41
42 bool runOnMachineFunction(MachineFunction &MF);
43
44 const char *getPassName() const { return "R600 Lower Shader Instructions"; }
45 };
46 } /* End anonymous namespace */
47
48 char R600LowerShaderInstructionsPass::ID = 0;
49
50 FunctionPass *llvm::createR600LowerShaderInstructionsPass(TargetMachine &tm) {
51 return new R600LowerShaderInstructionsPass(tm);
52 }
53
54 #define INSTR_CASE_FLOAT_V(inst) \
55 case AMDIL:: inst##_v4f32: \
56
57 #define INSTR_CASE_FLOAT_S(inst) \
58 case AMDIL:: inst##_f32:
59
60 #define INSTR_CASE_FLOAT(inst) \
61 INSTR_CASE_FLOAT_V(inst) \
62 INSTR_CASE_FLOAT_S(inst)
63 bool R600LowerShaderInstructionsPass::runOnMachineFunction(MachineFunction &MF)
64 {
65 MRI = &MF.getRegInfo();
66
67
68 for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
69 BB != BB_E; ++BB) {
70 MachineBasicBlock &MBB = *BB;
71 for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end();) {
72 MachineInstr &MI = *I;
73 bool deleteInstr = false;
74 switch (MI.getOpcode()) {
75
76 default: break;
77
78 case AMDIL::RESERVE_REG:
79 case AMDIL::EXPORT_REG:
80 deleteInstr = true;
81 break;
82
83 case AMDIL::LOAD_INPUT:
84 lowerLOAD_INPUT(MI);
85 deleteInstr = true;
86 break;
87
88 case AMDIL::STORE_OUTPUT:
89 deleteInstr = lowerSTORE_OUTPUT(MI, MBB, I);
90 break;
91
92 }
93
94 ++I;
95
96 if (deleteInstr) {
97 MI.eraseFromParent();
98 }
99 }
100 }
101
102 return false;
103 }
104
105 /* The goal of this function is to replace the virutal destination register of
106 * a LOAD_INPUT instruction with the correct physical register that will.
107 *
108 * XXX: I don't think this is the right way things assign physical registers,
109 * but I'm not sure of another way to do this.
110 */
111 void R600LowerShaderInstructionsPass::lowerLOAD_INPUT(MachineInstr &MI)
112 {
113 MachineOperand &dst = MI.getOperand(0);
114 MachineOperand &arg = MI.getOperand(1);
115 int64_t inputIndex = arg.getImm();
116 const TargetRegisterClass * inputClass = TM.getRegisterInfo()->getRegClass(AMDIL::R600_TReg32RegClassID);
117 unsigned newRegister = inputClass->getRegister(inputIndex);
118 unsigned dstReg = dst.getReg();
119
120 preloadRegister(MI.getParent()->getParent(), TM.getInstrInfo(), newRegister,
121 dstReg);
122 }
123
124 bool R600LowerShaderInstructionsPass::lowerSTORE_OUTPUT(MachineInstr &MI,
125 MachineBasicBlock &MBB, MachineBasicBlock::iterator I)
126 {
127 MachineOperand &valueOp = MI.getOperand(1);
128 MachineOperand &indexOp = MI.getOperand(2);
129 unsigned valueReg = valueOp.getReg();
130 int64_t outputIndex = indexOp.getImm();
131 const TargetRegisterClass * outputClass = TM.getRegisterInfo()->getRegClass(AMDIL::R600_TReg32RegClassID);
132 unsigned newRegister = outputClass->getRegister(outputIndex);
133
134 BuildMI(MBB, I, MBB.findDebugLoc(I), TM.getInstrInfo()->get(AMDIL::COPY),
135 newRegister)
136 .addReg(valueReg);
137
138 if (!MRI->isLiveOut(newRegister))
139 MRI->addLiveOut(newRegister);
140
141 return true;
142
143 }