blob: 5bf1e33f4010ea7d969314f20a0dea909c4672c7 [file] [log] [blame]
Vincent Lejeune62f38ca2013-03-05 18:41:32 +00001//===-- R600MachineScheduler.cpp - R600 Scheduler Interface -*- C++ -*-----===//
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 R600 Machine Scheduler interface
12// TODO: Scheduling is optimised for VLIW4 arch, modify it to support TRANS slot
13//
14//===----------------------------------------------------------------------===//
15
16#define DEBUG_TYPE "misched"
17
18#include "R600MachineScheduler.h"
19#include "llvm/CodeGen/MachineRegisterInfo.h"
20#include "llvm/CodeGen/LiveIntervalAnalysis.h"
21#include "llvm/Pass.h"
22#include "llvm/PassManager.h"
NAKAMURA Takumi3f179b52013-03-11 08:19:28 +000023#include "llvm/Support/raw_ostream.h"
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000024#include <set>
NAKAMURA Takumi3f179b52013-03-11 08:19:28 +000025
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000026using namespace llvm;
27
28void R600SchedStrategy::initialize(ScheduleDAGMI *dag) {
29
30 DAG = dag;
31 TII = static_cast<const R600InstrInfo*>(DAG->TII);
32 TRI = static_cast<const R600RegisterInfo*>(DAG->TRI);
33 MRI = &DAG->MRI;
34 Available[IDAlu]->clear();
35 Available[IDFetch]->clear();
36 Available[IDOther]->clear();
37 CurInstKind = IDOther;
38 CurEmitted = 0;
39 OccupedSlotsMask = 15;
Vincent Lejeunedae2a202013-04-03 16:49:34 +000040 InstKindLimit[IDAlu] = TII->getMaxAlusPerClause();
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000041
42
43 const AMDGPUSubtarget &ST = DAG->TM.getSubtarget<AMDGPUSubtarget>();
Vincent Lejeunedcfcf1d2013-05-17 16:49:55 +000044 InstKindLimit[IDFetch] = ST.getTexVTXClauseSize();
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000045}
46
47void R600SchedStrategy::MoveUnits(ReadyQueue *QSrc, ReadyQueue *QDst)
48{
49 if (QSrc->empty())
50 return;
51 for (ReadyQueue::iterator I = QSrc->begin(),
52 E = QSrc->end(); I != E; ++I) {
53 (*I)->NodeQueueId &= ~QSrc->getID();
54 QDst->push(*I);
55 }
56 QSrc->clear();
57}
58
59SUnit* R600SchedStrategy::pickNode(bool &IsTopNode) {
60 SUnit *SU = 0;
61 IsTopNode = true;
62 NextInstKind = IDOther;
63
64 // check if we might want to switch current clause type
65 bool AllowSwitchToAlu = (CurInstKind == IDOther) ||
Vincent Lejeunedcfcf1d2013-05-17 16:49:55 +000066 (CurEmitted >= InstKindLimit[CurInstKind]) ||
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000067 (Available[CurInstKind]->empty());
Vincent Lejeunedcfcf1d2013-05-17 16:49:55 +000068 bool AllowSwitchFromAlu = (CurEmitted >= InstKindLimit[CurInstKind]) &&
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000069 (!Available[IDFetch]->empty() || !Available[IDOther]->empty());
70
71 if ((AllowSwitchToAlu && CurInstKind != IDAlu) ||
72 (!AllowSwitchFromAlu && CurInstKind == IDAlu)) {
73 // try to pick ALU
74 SU = pickAlu();
75 if (SU) {
Vincent Lejeunedcfcf1d2013-05-17 16:49:55 +000076 if (CurEmitted >= InstKindLimit[IDAlu])
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000077 CurEmitted = 0;
78 NextInstKind = IDAlu;
79 }
80 }
81
82 if (!SU) {
83 // try to pick FETCH
84 SU = pickOther(IDFetch);
85 if (SU)
86 NextInstKind = IDFetch;
87 }
88
89 // try to pick other
90 if (!SU) {
91 SU = pickOther(IDOther);
92 if (SU)
93 NextInstKind = IDOther;
94 }
95
96 DEBUG(
97 if (SU) {
98 dbgs() << "picked node: ";
99 SU->dump(DAG);
100 } else {
101 dbgs() << "NO NODE ";
102 for (int i = 0; i < IDLast; ++i) {
103 Available[i]->dump();
104 Pending[i]->dump();
105 }
106 for (unsigned i = 0; i < DAG->SUnits.size(); i++) {
107 const SUnit &S = DAG->SUnits[i];
108 if (!S.isScheduled)
109 S.dump(DAG);
110 }
111 }
112 );
113
114 return SU;
115}
116
117void R600SchedStrategy::schedNode(SUnit *SU, bool IsTopNode) {
118
119 DEBUG(dbgs() << "scheduled: ");
120 DEBUG(SU->dump(DAG));
121
122 if (NextInstKind != CurInstKind) {
123 DEBUG(dbgs() << "Instruction Type Switch\n");
124 if (NextInstKind != IDAlu)
125 OccupedSlotsMask = 15;
126 CurEmitted = 0;
127 CurInstKind = NextInstKind;
128 }
129
130 if (CurInstKind == IDAlu) {
131 switch (getAluKind(SU)) {
132 case AluT_XYZW:
133 CurEmitted += 4;
134 break;
135 case AluDiscarded:
136 break;
137 default: {
138 ++CurEmitted;
139 for (MachineInstr::mop_iterator It = SU->getInstr()->operands_begin(),
140 E = SU->getInstr()->operands_end(); It != E; ++It) {
141 MachineOperand &MO = *It;
142 if (MO.isReg() && MO.getReg() == AMDGPU::ALU_LITERAL_X)
143 ++CurEmitted;
144 }
145 }
146 }
147 } else {
148 ++CurEmitted;
149 }
150
151
152 DEBUG(dbgs() << CurEmitted << " Instructions Emitted in this clause\n");
153
154 if (CurInstKind != IDFetch) {
155 MoveUnits(Pending[IDFetch], Available[IDFetch]);
156 }
157 MoveUnits(Pending[IDOther], Available[IDOther]);
158}
159
160void R600SchedStrategy::releaseTopNode(SUnit *SU) {
161 int IK = getInstKind(SU);
162
163 DEBUG(dbgs() << IK << " <= ");
164 DEBUG(SU->dump(DAG));
165
166 Pending[IK]->push(SU);
167}
168
169void R600SchedStrategy::releaseBottomNode(SUnit *SU) {
170}
171
172bool R600SchedStrategy::regBelongsToClass(unsigned Reg,
173 const TargetRegisterClass *RC) const {
174 if (!TargetRegisterInfo::isVirtualRegister(Reg)) {
175 return RC->contains(Reg);
176 } else {
177 return MRI->getRegClass(Reg) == RC;
178 }
179}
180
181R600SchedStrategy::AluKind R600SchedStrategy::getAluKind(SUnit *SU) const {
182 MachineInstr *MI = SU->getInstr();
183
184 switch (MI->getOpcode()) {
185 case AMDGPU::INTERP_PAIR_XY:
186 case AMDGPU::INTERP_PAIR_ZW:
187 case AMDGPU::INTERP_VEC_LOAD:
Vincent Lejeune4ed99172013-05-17 16:50:32 +0000188 case AMDGPU::DOT_4:
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000189 return AluT_XYZW;
190 case AMDGPU::COPY:
191 if (TargetRegisterInfo::isPhysicalRegister(MI->getOperand(1).getReg())) {
192 // %vregX = COPY Tn_X is likely to be discarded in favor of an
193 // assignement of Tn_X to %vregX, don't considers it in scheduling
194 return AluDiscarded;
195 }
196 else if (MI->getOperand(1).isUndef()) {
197 // MI will become a KILL, don't considers it in scheduling
198 return AluDiscarded;
199 }
200 default:
201 break;
202 }
203
204 // Does the instruction take a whole IG ?
205 if(TII->isVector(*MI) ||
206 TII->isCubeOp(MI->getOpcode()) ||
207 TII->isReductionOp(MI->getOpcode()))
208 return AluT_XYZW;
209
210 // Is the result already assigned to a channel ?
211 unsigned DestSubReg = MI->getOperand(0).getSubReg();
212 switch (DestSubReg) {
213 case AMDGPU::sub0:
214 return AluT_X;
215 case AMDGPU::sub1:
216 return AluT_Y;
217 case AMDGPU::sub2:
218 return AluT_Z;
219 case AMDGPU::sub3:
220 return AluT_W;
221 default:
222 break;
223 }
224
225 // Is the result already member of a X/Y/Z/W class ?
226 unsigned DestReg = MI->getOperand(0).getReg();
227 if (regBelongsToClass(DestReg, &AMDGPU::R600_TReg32_XRegClass) ||
228 regBelongsToClass(DestReg, &AMDGPU::R600_AddrRegClass))
229 return AluT_X;
230 if (regBelongsToClass(DestReg, &AMDGPU::R600_TReg32_YRegClass))
231 return AluT_Y;
232 if (regBelongsToClass(DestReg, &AMDGPU::R600_TReg32_ZRegClass))
233 return AluT_Z;
234 if (regBelongsToClass(DestReg, &AMDGPU::R600_TReg32_WRegClass))
235 return AluT_W;
236 if (regBelongsToClass(DestReg, &AMDGPU::R600_Reg128RegClass))
237 return AluT_XYZW;
238
239 return AluAny;
240
241}
242
243int R600SchedStrategy::getInstKind(SUnit* SU) {
244 int Opcode = SU->getInstr()->getOpcode();
245
Vincent Lejeunef63f85a2013-05-17 16:50:37 +0000246 if (TII->usesTextureCache(Opcode) || TII->usesVertexCache(Opcode))
247 return IDFetch;
248
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000249 if (TII->isALUInstr(Opcode)) {
250 return IDAlu;
251 }
252
253 switch (Opcode) {
254 case AMDGPU::COPY:
255 case AMDGPU::CONST_COPY:
256 case AMDGPU::INTERP_PAIR_XY:
257 case AMDGPU::INTERP_PAIR_ZW:
258 case AMDGPU::INTERP_VEC_LOAD:
Vincent Lejeune4ed99172013-05-17 16:50:32 +0000259 case AMDGPU::DOT_4:
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000260 return IDAlu;
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000261 default:
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000262 return IDOther;
263 }
264}
265
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000266SUnit *R600SchedStrategy::PopInst(std::multiset<SUnit *, CompareSUnit> &Q) {
267 if (Q.empty())
268 return NULL;
269 for (std::set<SUnit *, CompareSUnit>::iterator It = Q.begin(), E = Q.end();
270 It != E; ++It) {
271 SUnit *SU = *It;
Vincent Lejeune3ab0ba32013-03-14 15:50:45 +0000272 InstructionsGroupCandidate.push_back(SU->getInstr());
273 if (TII->canBundle(InstructionsGroupCandidate)) {
274 InstructionsGroupCandidate.pop_back();
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000275 Q.erase(It);
276 return SU;
Vincent Lejeune3ab0ba32013-03-14 15:50:45 +0000277 } else {
278 InstructionsGroupCandidate.pop_back();
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000279 }
280 }
281 return NULL;
282}
283
284void R600SchedStrategy::LoadAlu() {
285 ReadyQueue *QSrc = Pending[IDAlu];
286 for (ReadyQueue::iterator I = QSrc->begin(),
287 E = QSrc->end(); I != E; ++I) {
288 (*I)->NodeQueueId &= ~QSrc->getID();
289 AluKind AK = getAluKind(*I);
290 AvailableAlus[AK].insert(*I);
291 }
292 QSrc->clear();
293}
294
295void R600SchedStrategy::PrepareNextSlot() {
296 DEBUG(dbgs() << "New Slot\n");
297 assert (OccupedSlotsMask && "Slot wasn't filled");
298 OccupedSlotsMask = 0;
Vincent Lejeune3ab0ba32013-03-14 15:50:45 +0000299 InstructionsGroupCandidate.clear();
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000300 LoadAlu();
301}
302
303void R600SchedStrategy::AssignSlot(MachineInstr* MI, unsigned Slot) {
304 unsigned DestReg = MI->getOperand(0).getReg();
305 // PressureRegister crashes if an operand is def and used in the same inst
306 // and we try to constraint its regclass
307 for (MachineInstr::mop_iterator It = MI->operands_begin(),
308 E = MI->operands_end(); It != E; ++It) {
309 MachineOperand &MO = *It;
310 if (MO.isReg() && !MO.isDef() &&
311 MO.getReg() == MI->getOperand(0).getReg())
312 return;
313 }
314 // Constrains the regclass of DestReg to assign it to Slot
315 switch (Slot) {
316 case 0:
317 MRI->constrainRegClass(DestReg, &AMDGPU::R600_TReg32_XRegClass);
318 break;
319 case 1:
320 MRI->constrainRegClass(DestReg, &AMDGPU::R600_TReg32_YRegClass);
321 break;
322 case 2:
323 MRI->constrainRegClass(DestReg, &AMDGPU::R600_TReg32_ZRegClass);
324 break;
325 case 3:
326 MRI->constrainRegClass(DestReg, &AMDGPU::R600_TReg32_WRegClass);
327 break;
328 }
329}
330
331SUnit *R600SchedStrategy::AttemptFillSlot(unsigned Slot) {
332 static const AluKind IndexToID[] = {AluT_X, AluT_Y, AluT_Z, AluT_W};
333 SUnit *SlotedSU = PopInst(AvailableAlus[IndexToID[Slot]]);
334 SUnit *UnslotedSU = PopInst(AvailableAlus[AluAny]);
335 if (!UnslotedSU) {
336 return SlotedSU;
337 } else if (!SlotedSU) {
338 AssignSlot(UnslotedSU->getInstr(), Slot);
339 return UnslotedSU;
340 } else {
341 //Determine which one to pick (the lesser one)
342 if (CompareSUnit()(SlotedSU, UnslotedSU)) {
343 AvailableAlus[AluAny].insert(UnslotedSU);
344 return SlotedSU;
345 } else {
346 AvailableAlus[IndexToID[Slot]].insert(SlotedSU);
347 AssignSlot(UnslotedSU->getInstr(), Slot);
348 return UnslotedSU;
349 }
350 }
351}
352
353bool R600SchedStrategy::isAvailablesAluEmpty() const {
354 return Pending[IDAlu]->empty() && AvailableAlus[AluAny].empty() &&
355 AvailableAlus[AluT_XYZW].empty() && AvailableAlus[AluT_X].empty() &&
356 AvailableAlus[AluT_Y].empty() && AvailableAlus[AluT_Z].empty() &&
357 AvailableAlus[AluT_W].empty() && AvailableAlus[AluDiscarded].empty();
358}
359
360SUnit* R600SchedStrategy::pickAlu() {
361 while (!isAvailablesAluEmpty()) {
362 if (!OccupedSlotsMask) {
363 // Flush physical reg copies (RA will discard them)
364 if (!AvailableAlus[AluDiscarded].empty()) {
365 OccupedSlotsMask = 15;
366 return PopInst(AvailableAlus[AluDiscarded]);
367 }
368 // If there is a T_XYZW alu available, use it
369 if (!AvailableAlus[AluT_XYZW].empty()) {
370 OccupedSlotsMask = 15;
371 return PopInst(AvailableAlus[AluT_XYZW]);
372 }
373 }
374 for (unsigned Chan = 0; Chan < 4; ++Chan) {
375 bool isOccupied = OccupedSlotsMask & (1 << Chan);
376 if (!isOccupied) {
377 SUnit *SU = AttemptFillSlot(Chan);
378 if (SU) {
379 OccupedSlotsMask |= (1 << Chan);
Vincent Lejeune3ab0ba32013-03-14 15:50:45 +0000380 InstructionsGroupCandidate.push_back(SU->getInstr());
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000381 return SU;
382 }
383 }
384 }
385 PrepareNextSlot();
386 }
387 return NULL;
388}
389
390SUnit* R600SchedStrategy::pickOther(int QID) {
391 SUnit *SU = 0;
392 ReadyQueue *AQ = Available[QID];
393
394 if (AQ->empty()) {
395 MoveUnits(Pending[QID], AQ);
396 }
397 if (!AQ->empty()) {
398 SU = *AQ->begin();
399 AQ->remove(AQ->begin());
400 }
401 return SU;
402}
403