OSDN Git Service

radeonsi: initial WIP SI code
[android-x86/external-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 }