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
SIInstrInfo(AMDGPUTargetMachine & tm)25 SIInstrInfo::SIInstrInfo(AMDGPUTargetMachine &tm)
26 : AMDGPUInstrInfo(tm),
27 RI(tm)
28 { }
29
getRegisterInfo() const30 const SIRegisterInfo &SIInstrInfo::getRegisterInfo() const {
31 return RI;
32 }
33
34 void
copyPhysReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,DebugLoc DL,unsigned DestReg,unsigned SrcReg,bool KillSrc) const35 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 static 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 static 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 static const int16_t Sub0_3[] = {
58 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3, 0
59 };
60
61 static const int16_t Sub0_2[] = {
62 AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, 0
63 };
64
65 static const int16_t Sub0_1[] = {
66 AMDGPU::sub0, AMDGPU::sub1, 0
67 };
68
69 unsigned Opcode;
70 const int16_t *SubIndices;
71
72 if (AMDGPU::M0 == DestReg) {
73 // Check if M0 isn't already set to this value
74 for (MachineBasicBlock::reverse_iterator E = MBB.rend(),
75 I = MachineBasicBlock::reverse_iterator(MI); I != E; ++I) {
76
77 if (!I->definesRegister(AMDGPU::M0))
78 continue;
79
80 unsigned Opc = I->getOpcode();
81 if (Opc != TargetOpcode::COPY && Opc != AMDGPU::S_MOV_B32)
82 break;
83
84 if (!I->readsRegister(SrcReg))
85 break;
86
87 // The copy isn't necessary
88 return;
89 }
90 }
91
92 if (AMDGPU::SReg_32RegClass.contains(DestReg)) {
93 assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
94 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DestReg)
95 .addReg(SrcReg, getKillRegState(KillSrc));
96 return;
97
98 } else if (AMDGPU::SReg_64RegClass.contains(DestReg)) {
99 assert(AMDGPU::SReg_64RegClass.contains(SrcReg));
100 BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B64), DestReg)
101 .addReg(SrcReg, getKillRegState(KillSrc));
102 return;
103
104 } else if (AMDGPU::SReg_128RegClass.contains(DestReg)) {
105 assert(AMDGPU::SReg_128RegClass.contains(SrcReg));
106 Opcode = AMDGPU::S_MOV_B32;
107 SubIndices = Sub0_3;
108
109 } else if (AMDGPU::SReg_256RegClass.contains(DestReg)) {
110 assert(AMDGPU::SReg_256RegClass.contains(SrcReg));
111 Opcode = AMDGPU::S_MOV_B32;
112 SubIndices = Sub0_7;
113
114 } else if (AMDGPU::SReg_512RegClass.contains(DestReg)) {
115 assert(AMDGPU::SReg_512RegClass.contains(SrcReg));
116 Opcode = AMDGPU::S_MOV_B32;
117 SubIndices = Sub0_15;
118
119 } else if (AMDGPU::VReg_32RegClass.contains(DestReg)) {
120 assert(AMDGPU::VReg_32RegClass.contains(SrcReg) ||
121 AMDGPU::SReg_32RegClass.contains(SrcReg));
122 BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DestReg)
123 .addReg(SrcReg, getKillRegState(KillSrc));
124 return;
125
126 } else if (AMDGPU::VReg_64RegClass.contains(DestReg)) {
127 assert(AMDGPU::VReg_64RegClass.contains(SrcReg) ||
128 AMDGPU::SReg_64RegClass.contains(SrcReg));
129 Opcode = AMDGPU::V_MOV_B32_e32;
130 SubIndices = Sub0_1;
131
132 } else if (AMDGPU::VReg_96RegClass.contains(DestReg)) {
133 assert(AMDGPU::VReg_96RegClass.contains(SrcReg));
134 Opcode = AMDGPU::V_MOV_B32_e32;
135 SubIndices = Sub0_2;
136
137 } else if (AMDGPU::VReg_128RegClass.contains(DestReg)) {
138 assert(AMDGPU::VReg_128RegClass.contains(SrcReg) ||
139 AMDGPU::SReg_128RegClass.contains(SrcReg));
140 Opcode = AMDGPU::V_MOV_B32_e32;
141 SubIndices = Sub0_3;
142
143 } else if (AMDGPU::VReg_256RegClass.contains(DestReg)) {
144 assert(AMDGPU::VReg_256RegClass.contains(SrcReg) ||
145 AMDGPU::SReg_256RegClass.contains(SrcReg));
146 Opcode = AMDGPU::V_MOV_B32_e32;
147 SubIndices = Sub0_7;
148
149 } else if (AMDGPU::VReg_512RegClass.contains(DestReg)) {
150 assert(AMDGPU::VReg_512RegClass.contains(SrcReg) ||
151 AMDGPU::SReg_512RegClass.contains(SrcReg));
152 Opcode = AMDGPU::V_MOV_B32_e32;
153 SubIndices = Sub0_15;
154
155 } else {
156 llvm_unreachable("Can't copy register!");
157 }
158
159 while (unsigned SubIdx = *SubIndices++) {
160 MachineInstrBuilder Builder = BuildMI(MBB, MI, DL,
161 get(Opcode), RI.getSubReg(DestReg, SubIdx));
162
163 Builder.addReg(RI.getSubReg(SrcReg, SubIdx), getKillRegState(KillSrc));
164
165 if (*SubIndices)
166 Builder.addReg(DestReg, RegState::Define | RegState::Implicit);
167 }
168 }
169
commuteOpcode(unsigned Opcode) const170 unsigned SIInstrInfo::commuteOpcode(unsigned Opcode) const {
171
172 int NewOpc;
173
174 // Try to map original to commuted opcode
175 if ((NewOpc = AMDGPU::getCommuteRev(Opcode)) != -1)
176 return NewOpc;
177
178 // Try to map commuted to original opcode
179 if ((NewOpc = AMDGPU::getCommuteOrig(Opcode)) != -1)
180 return NewOpc;
181
182 return Opcode;
183 }
184
commuteInstruction(MachineInstr * MI,bool NewMI) const185 MachineInstr *SIInstrInfo::commuteInstruction(MachineInstr *MI,
186 bool NewMI) const {
187
188 if (MI->getNumOperands() < 3 || !MI->getOperand(1).isReg() ||
189 !MI->getOperand(2).isReg())
190 return 0;
191
192 MI = TargetInstrInfo::commuteInstruction(MI, NewMI);
193
194 if (MI)
195 MI->setDesc(get(commuteOpcode(MI->getOpcode())));
196
197 return MI;
198 }
199
getMovImmInstr(MachineFunction * MF,unsigned DstReg,int64_t Imm) const200 MachineInstr * SIInstrInfo::getMovImmInstr(MachineFunction *MF, unsigned DstReg,
201 int64_t Imm) const {
202 MachineInstr * MI = MF->CreateMachineInstr(get(AMDGPU::V_MOV_B32_e32), DebugLoc());
203 MachineInstrBuilder MIB(*MF, MI);
204 MIB.addReg(DstReg, RegState::Define);
205 MIB.addImm(Imm);
206
207 return MI;
208
209 }
210
isMov(unsigned Opcode) const211 bool SIInstrInfo::isMov(unsigned Opcode) const {
212 switch(Opcode) {
213 default: return false;
214 case AMDGPU::S_MOV_B32:
215 case AMDGPU::S_MOV_B64:
216 case AMDGPU::V_MOV_B32_e32:
217 case AMDGPU::V_MOV_B32_e64:
218 return true;
219 }
220 }
221
222 bool
isSafeToMoveRegClassDefs(const TargetRegisterClass * RC) const223 SIInstrInfo::isSafeToMoveRegClassDefs(const TargetRegisterClass *RC) const {
224 return RC != &AMDGPU::EXECRegRegClass;
225 }
226
227 //===----------------------------------------------------------------------===//
228 // Indirect addressing callbacks
229 //===----------------------------------------------------------------------===//
230
calculateIndirectAddress(unsigned RegIndex,unsigned Channel) const231 unsigned SIInstrInfo::calculateIndirectAddress(unsigned RegIndex,
232 unsigned Channel) const {
233 assert(Channel == 0);
234 return RegIndex;
235 }
236
237
getIndirectIndexBegin(const MachineFunction & MF) const238 int SIInstrInfo::getIndirectIndexBegin(const MachineFunction &MF) const {
239 llvm_unreachable("Unimplemented");
240 }
241
getIndirectIndexEnd(const MachineFunction & MF) const242 int SIInstrInfo::getIndirectIndexEnd(const MachineFunction &MF) const {
243 llvm_unreachable("Unimplemented");
244 }
245
getIndirectAddrStoreRegClass(unsigned SourceReg) const246 const TargetRegisterClass *SIInstrInfo::getIndirectAddrStoreRegClass(
247 unsigned SourceReg) const {
248 llvm_unreachable("Unimplemented");
249 }
250
getIndirectAddrLoadRegClass() const251 const TargetRegisterClass *SIInstrInfo::getIndirectAddrLoadRegClass() const {
252 llvm_unreachable("Unimplemented");
253 }
254
buildIndirectWrite(MachineBasicBlock * MBB,MachineBasicBlock::iterator I,unsigned ValueReg,unsigned Address,unsigned OffsetReg) const255 MachineInstrBuilder SIInstrInfo::buildIndirectWrite(
256 MachineBasicBlock *MBB,
257 MachineBasicBlock::iterator I,
258 unsigned ValueReg,
259 unsigned Address, unsigned OffsetReg) const {
260 llvm_unreachable("Unimplemented");
261 }
262
buildIndirectRead(MachineBasicBlock * MBB,MachineBasicBlock::iterator I,unsigned ValueReg,unsigned Address,unsigned OffsetReg) const263 MachineInstrBuilder SIInstrInfo::buildIndirectRead(
264 MachineBasicBlock *MBB,
265 MachineBasicBlock::iterator I,
266 unsigned ValueReg,
267 unsigned Address, unsigned OffsetReg) const {
268 llvm_unreachable("Unimplemented");
269 }
270
getSuperIndirectRegClass() const271 const TargetRegisterClass *SIInstrInfo::getSuperIndirectRegClass() const {
272 llvm_unreachable("Unimplemented");
273 }
274