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