R600/SI: improve vector interpolation
[oota-llvm.git] / lib / Target / R600 / SIInstrInfo.cpp
1 //===-- SIInstrInfo.cpp - SI Instruction Information  ---------------------===//
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 /// \file
11 /// \brief SI Implementation of TargetInstrInfo.
12 //
13 //===----------------------------------------------------------------------===//
14
15
16 #include "SIInstrInfo.h"
17 #include "AMDGPUTargetMachine.h"
18 #include "llvm/CodeGen/MachineInstrBuilder.h"
19 #include "llvm/CodeGen/MachineRegisterInfo.h"
20 #include "llvm/MC/MCInstrDesc.h"
21 #include <stdio.h>
22
23 using namespace llvm;
24
25 SIInstrInfo::SIInstrInfo(AMDGPUTargetMachine &tm)
26   : AMDGPUInstrInfo(tm),
27     RI(tm, *this)
28     { }
29
30 const SIRegisterInfo &SIInstrInfo::getRegisterInfo() const {
31   return RI;
32 }
33
34 void
35 SIInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
36                          MachineBasicBlock::iterator MI, DebugLoc DL,
37                          unsigned DestReg, unsigned SrcReg,
38                          bool KillSrc) const {
39
40   // If we are trying to copy to or from SCC, there is a bug somewhere else in
41   // the backend.  While it may be theoretically possible to do this, it should
42   // never be necessary.
43   assert(DestReg != AMDGPU::SCC && SrcReg != AMDGPU::SCC);
44
45   const int16_t Sub0_15[] = {
46     AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
47     AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
48     AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
49     AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15, 0
50   };
51
52   const int16_t Sub0_7[] = {
53     AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
54     AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7, 0
55   };
56
57   const int16_t Sub0_3[] = {
58     AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3, 0
59   };
60
61   const int16_t Sub0_1[] = {
62     AMDGPU::sub0, AMDGPU::sub1, 0
63   };
64
65   unsigned Opcode;
66   const int16_t *SubIndices;
67
68   if (AMDGPU::M0 == DestReg) {
69     // Check if M0 isn't already set to this value
70     for (MachineBasicBlock::reverse_iterator E = MBB.rend(),
71       I = MachineBasicBlock::reverse_iterator(MI); I != E; ++I) {
72
73       if (!I->definesRegister(AMDGPU::M0))
74         continue;
75
76       unsigned Opc = I->getOpcode();
77       if (Opc != TargetOpcode::COPY && Opc != AMDGPU::S_MOV_B32)
78         break;
79
80       if (!I->readsRegister(SrcReg))
81         break;
82
83       // The copy isn't necessary
84       return;
85     }
86   }
87
88   if (AMDGPU::SReg_32RegClass.contains(DestReg)) {
89     assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
90     BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DestReg)
91             .addReg(SrcReg, getKillRegState(KillSrc));
92     return;
93
94   } else if (AMDGPU::SReg_64RegClass.contains(DestReg)) {
95     assert(AMDGPU::SReg_64RegClass.contains(SrcReg));
96     BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B64), DestReg)
97             .addReg(SrcReg, getKillRegState(KillSrc));
98     return;
99
100   } else if (AMDGPU::SReg_128RegClass.contains(DestReg)) {
101     assert(AMDGPU::SReg_128RegClass.contains(SrcReg));
102     Opcode = AMDGPU::S_MOV_B32;
103     SubIndices = Sub0_3;
104
105   } else if (AMDGPU::SReg_256RegClass.contains(DestReg)) {
106     assert(AMDGPU::SReg_256RegClass.contains(SrcReg));
107     Opcode = AMDGPU::S_MOV_B32;
108     SubIndices = Sub0_7;
109
110   } else if (AMDGPU::SReg_512RegClass.contains(DestReg)) {
111     assert(AMDGPU::SReg_512RegClass.contains(SrcReg));
112     Opcode = AMDGPU::S_MOV_B32;
113     SubIndices = Sub0_15;
114
115   } else if (AMDGPU::VReg_32RegClass.contains(DestReg)) {
116     assert(AMDGPU::VReg_32RegClass.contains(SrcReg) ||
117            AMDGPU::SReg_32RegClass.contains(SrcReg));
118     BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DestReg)
119             .addReg(SrcReg, getKillRegState(KillSrc));
120     return;
121
122   } else if (AMDGPU::VReg_64RegClass.contains(DestReg)) {
123     assert(AMDGPU::VReg_64RegClass.contains(SrcReg) ||
124            AMDGPU::SReg_64RegClass.contains(SrcReg));
125     Opcode = AMDGPU::V_MOV_B32_e32;
126     SubIndices = Sub0_1;
127
128   } else if (AMDGPU::VReg_128RegClass.contains(DestReg)) {
129     assert(AMDGPU::VReg_128RegClass.contains(SrcReg) ||
130            AMDGPU::SReg_128RegClass.contains(SrcReg));
131     Opcode = AMDGPU::V_MOV_B32_e32;
132     SubIndices = Sub0_3;
133
134   } else if (AMDGPU::VReg_256RegClass.contains(DestReg)) {
135     assert(AMDGPU::VReg_256RegClass.contains(SrcReg) ||
136            AMDGPU::SReg_256RegClass.contains(SrcReg));
137     Opcode = AMDGPU::V_MOV_B32_e32;
138     SubIndices = Sub0_7;
139
140   } else if (AMDGPU::VReg_512RegClass.contains(DestReg)) {
141     assert(AMDGPU::VReg_512RegClass.contains(SrcReg) ||
142            AMDGPU::SReg_512RegClass.contains(SrcReg));
143     Opcode = AMDGPU::V_MOV_B32_e32;
144     SubIndices = Sub0_15;
145
146   } else {
147     llvm_unreachable("Can't copy register!");
148   }
149
150   while (unsigned SubIdx = *SubIndices++) {
151     MachineInstrBuilder Builder = BuildMI(MBB, MI, DL,
152       get(Opcode), RI.getSubReg(DestReg, SubIdx));
153
154     Builder.addReg(RI.getSubReg(SrcReg, SubIdx), getKillRegState(KillSrc));
155
156     if (*SubIndices)
157       Builder.addReg(DestReg, RegState::Define | RegState::Implicit);
158   }
159 }
160
161 MachineInstr *SIInstrInfo::commuteInstruction(MachineInstr *MI,
162                                               bool NewMI) const {
163
164   if (MI->getNumOperands() < 3 || !MI->getOperand(1).isReg() ||
165       !MI->getOperand(2).isReg())
166     return 0;
167
168   return TargetInstrInfo::commuteInstruction(MI, NewMI);
169 }
170
171 MachineInstr * SIInstrInfo::getMovImmInstr(MachineFunction *MF, unsigned DstReg,
172                                            int64_t Imm) const {
173   MachineInstr * MI = MF->CreateMachineInstr(get(AMDGPU::V_MOV_B32_e32), DebugLoc());
174   MachineInstrBuilder MIB(*MF, MI);
175   MIB.addReg(DstReg, RegState::Define);
176   MIB.addImm(Imm);
177
178   return MI;
179
180 }
181
182 bool SIInstrInfo::isMov(unsigned Opcode) const {
183   switch(Opcode) {
184   default: return false;
185   case AMDGPU::S_MOV_B32:
186   case AMDGPU::S_MOV_B64:
187   case AMDGPU::V_MOV_B32_e32:
188   case AMDGPU::V_MOV_B32_e64:
189     return true;
190   }
191 }
192
193 bool
194 SIInstrInfo::isSafeToMoveRegClassDefs(const TargetRegisterClass *RC) const {
195   return RC != &AMDGPU::EXECRegRegClass;
196 }
197
198 //===----------------------------------------------------------------------===//
199 // Indirect addressing callbacks
200 //===----------------------------------------------------------------------===//
201
202 unsigned SIInstrInfo::calculateIndirectAddress(unsigned RegIndex,
203                                                  unsigned Channel) const {
204   assert(Channel == 0);
205   return RegIndex;
206 }
207
208
209 int SIInstrInfo::getIndirectIndexBegin(const MachineFunction &MF) const {
210   llvm_unreachable("Unimplemented");
211 }
212
213 int SIInstrInfo::getIndirectIndexEnd(const MachineFunction &MF) const {
214   llvm_unreachable("Unimplemented");
215 }
216
217 const TargetRegisterClass *SIInstrInfo::getIndirectAddrStoreRegClass(
218                                                      unsigned SourceReg) const {
219   llvm_unreachable("Unimplemented");
220 }
221
222 const TargetRegisterClass *SIInstrInfo::getIndirectAddrLoadRegClass() const {
223   llvm_unreachable("Unimplemented");
224 }
225
226 MachineInstrBuilder SIInstrInfo::buildIndirectWrite(
227                                    MachineBasicBlock *MBB,
228                                    MachineBasicBlock::iterator I,
229                                    unsigned ValueReg,
230                                    unsigned Address, unsigned OffsetReg) const {
231   llvm_unreachable("Unimplemented");
232 }
233
234 MachineInstrBuilder SIInstrInfo::buildIndirectRead(
235                                    MachineBasicBlock *MBB,
236                                    MachineBasicBlock::iterator I,
237                                    unsigned ValueReg,
238                                    unsigned Address, unsigned OffsetReg) const {
239   llvm_unreachable("Unimplemented");
240 }
241
242 const TargetRegisterClass *SIInstrInfo::getSuperIndirectRegClass() const {
243   llvm_unreachable("Unimplemented");
244 }