blob: 29f3e1a7d5a5c3865698cd6427831754a29a0980 [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"
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000019#include "llvm/CodeGen/LiveIntervalAnalysis.h"
Benjamin Kramer5c352902013-05-23 17:10:37 +000020#include "llvm/CodeGen/MachineRegisterInfo.h"
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000021#include "llvm/Pass.h"
22#include "llvm/PassManager.h"
NAKAMURA Takumi3f179b52013-03-11 08:19:28 +000023#include "llvm/Support/raw_ostream.h"
NAKAMURA Takumi3f179b52013-03-11 08:19:28 +000024
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000025using namespace llvm;
26
27void R600SchedStrategy::initialize(ScheduleDAGMI *dag) {
28
29 DAG = dag;
30 TII = static_cast<const R600InstrInfo*>(DAG->TII);
31 TRI = static_cast<const R600RegisterInfo*>(DAG->TRI);
32 MRI = &DAG->MRI;
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000033 CurInstKind = IDOther;
34 CurEmitted = 0;
35 OccupedSlotsMask = 15;
Vincent Lejeunedae2a202013-04-03 16:49:34 +000036 InstKindLimit[IDAlu] = TII->getMaxAlusPerClause();
Vincent Lejeune76fc2d02013-05-17 16:50:56 +000037 InstKindLimit[IDOther] = 32;
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000038
39 const AMDGPUSubtarget &ST = DAG->TM.getSubtarget<AMDGPUSubtarget>();
Vincent Lejeunedcfcf1d2013-05-17 16:49:55 +000040 InstKindLimit[IDFetch] = ST.getTexVTXClauseSize();
Tom Stellard3ff0abf2013-06-07 20:37:48 +000041
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000042}
43
Vincent Lejeune21ca0b32013-05-17 16:50:44 +000044void R600SchedStrategy::MoveUnits(std::vector<SUnit *> &QSrc,
45 std::vector<SUnit *> &QDst)
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000046{
Vincent Lejeune21ca0b32013-05-17 16:50:44 +000047 QDst.insert(QDst.end(), QSrc.begin(), QSrc.end());
48 QSrc.clear();
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000049}
50
51SUnit* R600SchedStrategy::pickNode(bool &IsTopNode) {
52 SUnit *SU = 0;
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000053 NextInstKind = IDOther;
54
Vincent Lejeune76fc2d02013-05-17 16:50:56 +000055 IsTopNode = false;
56
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000057 // check if we might want to switch current clause type
Vincent Lejeune76fc2d02013-05-17 16:50:56 +000058 bool AllowSwitchToAlu = (CurEmitted >= InstKindLimit[CurInstKind]) ||
Vincent Lejeune21ca0b32013-05-17 16:50:44 +000059 (Available[CurInstKind].empty());
Vincent Lejeunedcfcf1d2013-05-17 16:49:55 +000060 bool AllowSwitchFromAlu = (CurEmitted >= InstKindLimit[CurInstKind]) &&
Vincent Lejeune21ca0b32013-05-17 16:50:44 +000061 (!Available[IDFetch].empty() || !Available[IDOther].empty());
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000062
Tom Stellardad7ecc62013-06-05 03:43:06 +000063 // We want to scheduled AR defs as soon as possible to make sure they aren't
64 // put in a different ALU clause from their uses.
65 if (!SU && !UnscheduledARDefs.empty()) {
66 SU = UnscheduledARDefs[0];
67 UnscheduledARDefs.erase(UnscheduledARDefs.begin());
68 NextInstKind = IDAlu;
69 }
70
71 if (!SU && ((AllowSwitchToAlu && CurInstKind != IDAlu) ||
72 (!AllowSwitchFromAlu && CurInstKind == IDAlu))) {
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000073 // try to pick ALU
74 SU = pickAlu();
Vincent Lejeune51211972013-06-05 20:27:35 +000075 if (!SU && !PhysicalRegCopy.empty()) {
76 SU = PhysicalRegCopy.front();
77 PhysicalRegCopy.erase(PhysicalRegCopy.begin());
78 }
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000079 if (SU) {
Vincent Lejeunedcfcf1d2013-05-17 16:49:55 +000080 if (CurEmitted >= InstKindLimit[IDAlu])
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000081 CurEmitted = 0;
82 NextInstKind = IDAlu;
83 }
84 }
85
86 if (!SU) {
87 // try to pick FETCH
88 SU = pickOther(IDFetch);
89 if (SU)
90 NextInstKind = IDFetch;
91 }
92
93 // try to pick other
94 if (!SU) {
95 SU = pickOther(IDOther);
96 if (SU)
97 NextInstKind = IDOther;
98 }
99
Tom Stellardad7ecc62013-06-05 03:43:06 +0000100 // We want to schedule the AR uses as late as possible to make sure that
101 // the AR defs have been released.
102 if (!SU && !UnscheduledARUses.empty()) {
103 SU = UnscheduledARUses[0];
104 UnscheduledARUses.erase(UnscheduledARUses.begin());
105 NextInstKind = IDAlu;
106 }
107
108
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000109 DEBUG(
110 if (SU) {
Vincent Lejeune76fc2d02013-05-17 16:50:56 +0000111 dbgs() << " ** Pick node **\n";
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000112 SU->dump(DAG);
113 } else {
Vincent Lejeune76fc2d02013-05-17 16:50:56 +0000114 dbgs() << "NO NODE \n";
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000115 for (unsigned i = 0; i < DAG->SUnits.size(); i++) {
116 const SUnit &S = DAG->SUnits[i];
117 if (!S.isScheduled)
118 S.dump(DAG);
119 }
120 }
121 );
122
123 return SU;
124}
125
126void R600SchedStrategy::schedNode(SUnit *SU, bool IsTopNode) {
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000127 if (NextInstKind != CurInstKind) {
128 DEBUG(dbgs() << "Instruction Type Switch\n");
129 if (NextInstKind != IDAlu)
130 OccupedSlotsMask = 15;
131 CurEmitted = 0;
132 CurInstKind = NextInstKind;
133 }
134
135 if (CurInstKind == IDAlu) {
136 switch (getAluKind(SU)) {
137 case AluT_XYZW:
138 CurEmitted += 4;
139 break;
140 case AluDiscarded:
141 break;
142 default: {
143 ++CurEmitted;
144 for (MachineInstr::mop_iterator It = SU->getInstr()->operands_begin(),
145 E = SU->getInstr()->operands_end(); It != E; ++It) {
146 MachineOperand &MO = *It;
147 if (MO.isReg() && MO.getReg() == AMDGPU::ALU_LITERAL_X)
148 ++CurEmitted;
149 }
150 }
151 }
152 } else {
153 ++CurEmitted;
154 }
155
156
157 DEBUG(dbgs() << CurEmitted << " Instructions Emitted in this clause\n");
158
159 if (CurInstKind != IDFetch) {
160 MoveUnits(Pending[IDFetch], Available[IDFetch]);
161 }
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000162}
163
Vincent Lejeune51211972013-06-05 20:27:35 +0000164static bool
165isPhysicalRegCopy(MachineInstr *MI) {
166 if (MI->getOpcode() != AMDGPU::COPY)
167 return false;
168
169 return !TargetRegisterInfo::isVirtualRegister(MI->getOperand(1).getReg());
170}
171
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000172void R600SchedStrategy::releaseTopNode(SUnit *SU) {
Vincent Lejeune76fc2d02013-05-17 16:50:56 +0000173 DEBUG(dbgs() << "Top Releasing ";SU->dump(DAG););
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000174}
175
176void R600SchedStrategy::releaseBottomNode(SUnit *SU) {
Vincent Lejeune76fc2d02013-05-17 16:50:56 +0000177 DEBUG(dbgs() << "Bottom Releasing ";SU->dump(DAG););
Vincent Lejeune51211972013-06-05 20:27:35 +0000178 if (isPhysicalRegCopy(SU->getInstr())) {
179 PhysicalRegCopy.push_back(SU);
180 return;
181 }
Vincent Lejeune76fc2d02013-05-17 16:50:56 +0000182
183 int IK = getInstKind(SU);
Tom Stellardad7ecc62013-06-05 03:43:06 +0000184
185 // Check for AR register defines
186 for (MachineInstr::const_mop_iterator I = SU->getInstr()->operands_begin(),
187 E = SU->getInstr()->operands_end();
188 I != E; ++I) {
189 if (I->isReg() && I->getReg() == AMDGPU::AR_X) {
190 if (I->isDef()) {
191 UnscheduledARDefs.push_back(SU);
192 } else {
193 UnscheduledARUses.push_back(SU);
194 }
195 return;
196 }
197 }
198
Vincent Lejeune76fc2d02013-05-17 16:50:56 +0000199 // There is no export clause, we can schedule one as soon as its ready
200 if (IK == IDOther)
201 Available[IDOther].push_back(SU);
202 else
203 Pending[IK].push_back(SU);
204
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000205}
206
207bool R600SchedStrategy::regBelongsToClass(unsigned Reg,
208 const TargetRegisterClass *RC) const {
209 if (!TargetRegisterInfo::isVirtualRegister(Reg)) {
210 return RC->contains(Reg);
211 } else {
212 return MRI->getRegClass(Reg) == RC;
213 }
214}
215
216R600SchedStrategy::AluKind R600SchedStrategy::getAluKind(SUnit *SU) const {
217 MachineInstr *MI = SU->getInstr();
218
219 switch (MI->getOpcode()) {
Vincent Lejeune76fc2d02013-05-17 16:50:56 +0000220 case AMDGPU::PRED_X:
221 return AluPredX;
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000222 case AMDGPU::INTERP_PAIR_XY:
223 case AMDGPU::INTERP_PAIR_ZW:
224 case AMDGPU::INTERP_VEC_LOAD:
Vincent Lejeune4ed99172013-05-17 16:50:32 +0000225 case AMDGPU::DOT_4:
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000226 return AluT_XYZW;
227 case AMDGPU::COPY:
Vincent Lejeune76fc2d02013-05-17 16:50:56 +0000228 if (MI->getOperand(1).isUndef()) {
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000229 // MI will become a KILL, don't considers it in scheduling
230 return AluDiscarded;
231 }
232 default:
233 break;
234 }
235
236 // Does the instruction take a whole IG ?
237 if(TII->isVector(*MI) ||
238 TII->isCubeOp(MI->getOpcode()) ||
239 TII->isReductionOp(MI->getOpcode()))
240 return AluT_XYZW;
241
242 // Is the result already assigned to a channel ?
243 unsigned DestSubReg = MI->getOperand(0).getSubReg();
244 switch (DestSubReg) {
245 case AMDGPU::sub0:
246 return AluT_X;
247 case AMDGPU::sub1:
248 return AluT_Y;
249 case AMDGPU::sub2:
250 return AluT_Z;
251 case AMDGPU::sub3:
252 return AluT_W;
253 default:
254 break;
255 }
256
257 // Is the result already member of a X/Y/Z/W class ?
258 unsigned DestReg = MI->getOperand(0).getReg();
259 if (regBelongsToClass(DestReg, &AMDGPU::R600_TReg32_XRegClass) ||
260 regBelongsToClass(DestReg, &AMDGPU::R600_AddrRegClass))
261 return AluT_X;
262 if (regBelongsToClass(DestReg, &AMDGPU::R600_TReg32_YRegClass))
263 return AluT_Y;
264 if (regBelongsToClass(DestReg, &AMDGPU::R600_TReg32_ZRegClass))
265 return AluT_Z;
266 if (regBelongsToClass(DestReg, &AMDGPU::R600_TReg32_WRegClass))
267 return AluT_W;
268 if (regBelongsToClass(DestReg, &AMDGPU::R600_Reg128RegClass))
269 return AluT_XYZW;
270
271 return AluAny;
272
273}
274
275int R600SchedStrategy::getInstKind(SUnit* SU) {
276 int Opcode = SU->getInstr()->getOpcode();
277
Vincent Lejeunef63f85a2013-05-17 16:50:37 +0000278 if (TII->usesTextureCache(Opcode) || TII->usesVertexCache(Opcode))
279 return IDFetch;
280
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000281 if (TII->isALUInstr(Opcode)) {
282 return IDAlu;
283 }
284
285 switch (Opcode) {
Vincent Lejeune76fc2d02013-05-17 16:50:56 +0000286 case AMDGPU::PRED_X:
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000287 case AMDGPU::COPY:
288 case AMDGPU::CONST_COPY:
289 case AMDGPU::INTERP_PAIR_XY:
290 case AMDGPU::INTERP_PAIR_ZW:
291 case AMDGPU::INTERP_VEC_LOAD:
Vincent Lejeune4ed99172013-05-17 16:50:32 +0000292 case AMDGPU::DOT_4:
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000293 return IDAlu;
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000294 default:
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000295 return IDOther;
296 }
297}
298
Vincent Lejeune21ca0b32013-05-17 16:50:44 +0000299SUnit *R600SchedStrategy::PopInst(std::vector<SUnit *> &Q) {
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000300 if (Q.empty())
301 return NULL;
Vincent Lejeune21ca0b32013-05-17 16:50:44 +0000302 for (std::vector<SUnit *>::reverse_iterator It = Q.rbegin(), E = Q.rend();
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000303 It != E; ++It) {
304 SUnit *SU = *It;
Vincent Lejeune3ab0ba32013-03-14 15:50:45 +0000305 InstructionsGroupCandidate.push_back(SU->getInstr());
306 if (TII->canBundle(InstructionsGroupCandidate)) {
307 InstructionsGroupCandidate.pop_back();
Vincent Lejeune21ca0b32013-05-17 16:50:44 +0000308 Q.erase((It + 1).base());
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000309 return SU;
Vincent Lejeune3ab0ba32013-03-14 15:50:45 +0000310 } else {
311 InstructionsGroupCandidate.pop_back();
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000312 }
313 }
314 return NULL;
315}
316
317void R600SchedStrategy::LoadAlu() {
Vincent Lejeune21ca0b32013-05-17 16:50:44 +0000318 std::vector<SUnit *> &QSrc = Pending[IDAlu];
319 for (unsigned i = 0, e = QSrc.size(); i < e; ++i) {
320 AluKind AK = getAluKind(QSrc[i]);
321 AvailableAlus[AK].push_back(QSrc[i]);
322 }
323 QSrc.clear();
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000324}
325
326void R600SchedStrategy::PrepareNextSlot() {
327 DEBUG(dbgs() << "New Slot\n");
328 assert (OccupedSlotsMask && "Slot wasn't filled");
329 OccupedSlotsMask = 0;
Vincent Lejeune3ab0ba32013-03-14 15:50:45 +0000330 InstructionsGroupCandidate.clear();
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000331 LoadAlu();
332}
333
334void R600SchedStrategy::AssignSlot(MachineInstr* MI, unsigned Slot) {
335 unsigned DestReg = MI->getOperand(0).getReg();
336 // PressureRegister crashes if an operand is def and used in the same inst
337 // and we try to constraint its regclass
338 for (MachineInstr::mop_iterator It = MI->operands_begin(),
339 E = MI->operands_end(); It != E; ++It) {
340 MachineOperand &MO = *It;
341 if (MO.isReg() && !MO.isDef() &&
342 MO.getReg() == MI->getOperand(0).getReg())
343 return;
344 }
345 // Constrains the regclass of DestReg to assign it to Slot
346 switch (Slot) {
347 case 0:
348 MRI->constrainRegClass(DestReg, &AMDGPU::R600_TReg32_XRegClass);
349 break;
350 case 1:
351 MRI->constrainRegClass(DestReg, &AMDGPU::R600_TReg32_YRegClass);
352 break;
353 case 2:
354 MRI->constrainRegClass(DestReg, &AMDGPU::R600_TReg32_ZRegClass);
355 break;
356 case 3:
357 MRI->constrainRegClass(DestReg, &AMDGPU::R600_TReg32_WRegClass);
358 break;
359 }
360}
361
362SUnit *R600SchedStrategy::AttemptFillSlot(unsigned Slot) {
363 static const AluKind IndexToID[] = {AluT_X, AluT_Y, AluT_Z, AluT_W};
364 SUnit *SlotedSU = PopInst(AvailableAlus[IndexToID[Slot]]);
Vincent Lejeune21ca0b32013-05-17 16:50:44 +0000365 if (SlotedSU)
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000366 return SlotedSU;
Vincent Lejeune21ca0b32013-05-17 16:50:44 +0000367 SUnit *UnslotedSU = PopInst(AvailableAlus[AluAny]);
368 if (UnslotedSU)
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000369 AssignSlot(UnslotedSU->getInstr(), Slot);
Vincent Lejeune21ca0b32013-05-17 16:50:44 +0000370 return UnslotedSU;
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000371}
372
373bool R600SchedStrategy::isAvailablesAluEmpty() const {
Vincent Lejeune21ca0b32013-05-17 16:50:44 +0000374 return Pending[IDAlu].empty() && AvailableAlus[AluAny].empty() &&
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000375 AvailableAlus[AluT_XYZW].empty() && AvailableAlus[AluT_X].empty() &&
376 AvailableAlus[AluT_Y].empty() && AvailableAlus[AluT_Z].empty() &&
Vincent Lejeune76fc2d02013-05-17 16:50:56 +0000377 AvailableAlus[AluT_W].empty() && AvailableAlus[AluDiscarded].empty() &&
378 AvailableAlus[AluPredX].empty();
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000379}
380
381SUnit* R600SchedStrategy::pickAlu() {
382 while (!isAvailablesAluEmpty()) {
383 if (!OccupedSlotsMask) {
Vincent Lejeune76fc2d02013-05-17 16:50:56 +0000384 // Bottom up scheduling : predX must comes first
385 if (!AvailableAlus[AluPredX].empty()) {
386 OccupedSlotsMask = 15;
387 return PopInst(AvailableAlus[AluPredX]);
388 }
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000389 // Flush physical reg copies (RA will discard them)
390 if (!AvailableAlus[AluDiscarded].empty()) {
391 OccupedSlotsMask = 15;
392 return PopInst(AvailableAlus[AluDiscarded]);
393 }
394 // If there is a T_XYZW alu available, use it
395 if (!AvailableAlus[AluT_XYZW].empty()) {
396 OccupedSlotsMask = 15;
397 return PopInst(AvailableAlus[AluT_XYZW]);
398 }
399 }
Vincent Lejeune76fc2d02013-05-17 16:50:56 +0000400 for (int Chan = 3; Chan > -1; --Chan) {
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000401 bool isOccupied = OccupedSlotsMask & (1 << Chan);
402 if (!isOccupied) {
403 SUnit *SU = AttemptFillSlot(Chan);
404 if (SU) {
405 OccupedSlotsMask |= (1 << Chan);
Vincent Lejeune3ab0ba32013-03-14 15:50:45 +0000406 InstructionsGroupCandidate.push_back(SU->getInstr());
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000407 return SU;
408 }
409 }
410 }
411 PrepareNextSlot();
412 }
413 return NULL;
414}
415
416SUnit* R600SchedStrategy::pickOther(int QID) {
417 SUnit *SU = 0;
Vincent Lejeune21ca0b32013-05-17 16:50:44 +0000418 std::vector<SUnit *> &AQ = Available[QID];
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000419
Vincent Lejeune21ca0b32013-05-17 16:50:44 +0000420 if (AQ.empty()) {
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000421 MoveUnits(Pending[QID], AQ);
422 }
Vincent Lejeune21ca0b32013-05-17 16:50:44 +0000423 if (!AQ.empty()) {
424 SU = AQ.back();
425 AQ.resize(AQ.size() - 1);
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000426 }
427 return SU;
428}
429