blob: 9469e0fc6b338d85f1667a3ba51f8c5346888d5d [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();
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000041}
42
Vincent Lejeune21ca0b32013-05-17 16:50:44 +000043void R600SchedStrategy::MoveUnits(std::vector<SUnit *> &QSrc,
44 std::vector<SUnit *> &QDst)
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000045{
Vincent Lejeune21ca0b32013-05-17 16:50:44 +000046 QDst.insert(QDst.end(), QSrc.begin(), QSrc.end());
47 QSrc.clear();
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000048}
49
50SUnit* R600SchedStrategy::pickNode(bool &IsTopNode) {
51 SUnit *SU = 0;
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000052 NextInstKind = IDOther;
53
Vincent Lejeune76fc2d02013-05-17 16:50:56 +000054 IsTopNode = false;
55
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000056 // check if we might want to switch current clause type
Vincent Lejeune76fc2d02013-05-17 16:50:56 +000057 bool AllowSwitchToAlu = (CurEmitted >= InstKindLimit[CurInstKind]) ||
Vincent Lejeune21ca0b32013-05-17 16:50:44 +000058 (Available[CurInstKind].empty());
Vincent Lejeunedcfcf1d2013-05-17 16:49:55 +000059 bool AllowSwitchFromAlu = (CurEmitted >= InstKindLimit[CurInstKind]) &&
Vincent Lejeune21ca0b32013-05-17 16:50:44 +000060 (!Available[IDFetch].empty() || !Available[IDOther].empty());
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000061
Tom Stellardad7ecc62013-06-05 03:43:06 +000062 // We want to scheduled AR defs as soon as possible to make sure they aren't
63 // put in a different ALU clause from their uses.
64 if (!SU && !UnscheduledARDefs.empty()) {
65 SU = UnscheduledARDefs[0];
66 UnscheduledARDefs.erase(UnscheduledARDefs.begin());
67 NextInstKind = IDAlu;
68 }
69
70 if (!SU && ((AllowSwitchToAlu && CurInstKind != IDAlu) ||
71 (!AllowSwitchFromAlu && CurInstKind == IDAlu))) {
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000072 // try to pick ALU
73 SU = pickAlu();
74 if (SU) {
Vincent Lejeunedcfcf1d2013-05-17 16:49:55 +000075 if (CurEmitted >= InstKindLimit[IDAlu])
Vincent Lejeune62f38ca2013-03-05 18:41:32 +000076 CurEmitted = 0;
77 NextInstKind = IDAlu;
78 }
79 }
80
81 if (!SU) {
82 // try to pick FETCH
83 SU = pickOther(IDFetch);
84 if (SU)
85 NextInstKind = IDFetch;
86 }
87
88 // try to pick other
89 if (!SU) {
90 SU = pickOther(IDOther);
91 if (SU)
92 NextInstKind = IDOther;
93 }
94
Tom Stellardad7ecc62013-06-05 03:43:06 +000095 // We want to schedule the AR uses as late as possible to make sure that
96 // the AR defs have been released.
97 if (!SU && !UnscheduledARUses.empty()) {
98 SU = UnscheduledARUses[0];
99 UnscheduledARUses.erase(UnscheduledARUses.begin());
100 NextInstKind = IDAlu;
101 }
102
103
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000104 DEBUG(
105 if (SU) {
Vincent Lejeune76fc2d02013-05-17 16:50:56 +0000106 dbgs() << " ** Pick node **\n";
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000107 SU->dump(DAG);
108 } else {
Vincent Lejeune76fc2d02013-05-17 16:50:56 +0000109 dbgs() << "NO NODE \n";
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000110 for (unsigned i = 0; i < DAG->SUnits.size(); i++) {
111 const SUnit &S = DAG->SUnits[i];
112 if (!S.isScheduled)
113 S.dump(DAG);
114 }
115 }
116 );
117
118 return SU;
119}
120
121void R600SchedStrategy::schedNode(SUnit *SU, bool IsTopNode) {
122
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000123 if (NextInstKind != CurInstKind) {
124 DEBUG(dbgs() << "Instruction Type Switch\n");
125 if (NextInstKind != IDAlu)
126 OccupedSlotsMask = 15;
127 CurEmitted = 0;
128 CurInstKind = NextInstKind;
129 }
130
131 if (CurInstKind == IDAlu) {
132 switch (getAluKind(SU)) {
133 case AluT_XYZW:
134 CurEmitted += 4;
135 break;
136 case AluDiscarded:
137 break;
138 default: {
139 ++CurEmitted;
140 for (MachineInstr::mop_iterator It = SU->getInstr()->operands_begin(),
141 E = SU->getInstr()->operands_end(); It != E; ++It) {
142 MachineOperand &MO = *It;
143 if (MO.isReg() && MO.getReg() == AMDGPU::ALU_LITERAL_X)
144 ++CurEmitted;
145 }
146 }
147 }
148 } else {
149 ++CurEmitted;
150 }
151
152
153 DEBUG(dbgs() << CurEmitted << " Instructions Emitted in this clause\n");
154
155 if (CurInstKind != IDFetch) {
156 MoveUnits(Pending[IDFetch], Available[IDFetch]);
157 }
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000158}
159
160void R600SchedStrategy::releaseTopNode(SUnit *SU) {
Vincent Lejeune76fc2d02013-05-17 16:50:56 +0000161 DEBUG(dbgs() << "Top Releasing ";SU->dump(DAG););
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000162
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000163}
164
165void R600SchedStrategy::releaseBottomNode(SUnit *SU) {
Vincent Lejeune76fc2d02013-05-17 16:50:56 +0000166 DEBUG(dbgs() << "Bottom Releasing ";SU->dump(DAG););
167
168 int IK = getInstKind(SU);
Tom Stellardad7ecc62013-06-05 03:43:06 +0000169
170 // Check for AR register defines
171 for (MachineInstr::const_mop_iterator I = SU->getInstr()->operands_begin(),
172 E = SU->getInstr()->operands_end();
173 I != E; ++I) {
174 if (I->isReg() && I->getReg() == AMDGPU::AR_X) {
175 if (I->isDef()) {
176 UnscheduledARDefs.push_back(SU);
177 } else {
178 UnscheduledARUses.push_back(SU);
179 }
180 return;
181 }
182 }
183
Vincent Lejeune76fc2d02013-05-17 16:50:56 +0000184 // There is no export clause, we can schedule one as soon as its ready
185 if (IK == IDOther)
186 Available[IDOther].push_back(SU);
187 else
188 Pending[IK].push_back(SU);
189
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000190}
191
192bool R600SchedStrategy::regBelongsToClass(unsigned Reg,
193 const TargetRegisterClass *RC) const {
194 if (!TargetRegisterInfo::isVirtualRegister(Reg)) {
195 return RC->contains(Reg);
196 } else {
197 return MRI->getRegClass(Reg) == RC;
198 }
199}
200
201R600SchedStrategy::AluKind R600SchedStrategy::getAluKind(SUnit *SU) const {
202 MachineInstr *MI = SU->getInstr();
203
204 switch (MI->getOpcode()) {
Vincent Lejeune76fc2d02013-05-17 16:50:56 +0000205 case AMDGPU::PRED_X:
206 return AluPredX;
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000207 case AMDGPU::INTERP_PAIR_XY:
208 case AMDGPU::INTERP_PAIR_ZW:
209 case AMDGPU::INTERP_VEC_LOAD:
Vincent Lejeune4ed99172013-05-17 16:50:32 +0000210 case AMDGPU::DOT_4:
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000211 return AluT_XYZW;
212 case AMDGPU::COPY:
Vincent Lejeune76fc2d02013-05-17 16:50:56 +0000213 if (MI->getOperand(1).isUndef()) {
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000214 // MI will become a KILL, don't considers it in scheduling
215 return AluDiscarded;
216 }
217 default:
218 break;
219 }
220
221 // Does the instruction take a whole IG ?
222 if(TII->isVector(*MI) ||
223 TII->isCubeOp(MI->getOpcode()) ||
224 TII->isReductionOp(MI->getOpcode()))
225 return AluT_XYZW;
226
227 // Is the result already assigned to a channel ?
228 unsigned DestSubReg = MI->getOperand(0).getSubReg();
229 switch (DestSubReg) {
230 case AMDGPU::sub0:
231 return AluT_X;
232 case AMDGPU::sub1:
233 return AluT_Y;
234 case AMDGPU::sub2:
235 return AluT_Z;
236 case AMDGPU::sub3:
237 return AluT_W;
238 default:
239 break;
240 }
241
242 // Is the result already member of a X/Y/Z/W class ?
243 unsigned DestReg = MI->getOperand(0).getReg();
244 if (regBelongsToClass(DestReg, &AMDGPU::R600_TReg32_XRegClass) ||
245 regBelongsToClass(DestReg, &AMDGPU::R600_AddrRegClass))
246 return AluT_X;
247 if (regBelongsToClass(DestReg, &AMDGPU::R600_TReg32_YRegClass))
248 return AluT_Y;
249 if (regBelongsToClass(DestReg, &AMDGPU::R600_TReg32_ZRegClass))
250 return AluT_Z;
251 if (regBelongsToClass(DestReg, &AMDGPU::R600_TReg32_WRegClass))
252 return AluT_W;
253 if (regBelongsToClass(DestReg, &AMDGPU::R600_Reg128RegClass))
254 return AluT_XYZW;
255
256 return AluAny;
257
258}
259
260int R600SchedStrategy::getInstKind(SUnit* SU) {
261 int Opcode = SU->getInstr()->getOpcode();
262
Vincent Lejeunef63f85a2013-05-17 16:50:37 +0000263 if (TII->usesTextureCache(Opcode) || TII->usesVertexCache(Opcode))
264 return IDFetch;
265
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000266 if (TII->isALUInstr(Opcode)) {
267 return IDAlu;
268 }
269
270 switch (Opcode) {
Vincent Lejeune76fc2d02013-05-17 16:50:56 +0000271 case AMDGPU::PRED_X:
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000272 case AMDGPU::COPY:
273 case AMDGPU::CONST_COPY:
274 case AMDGPU::INTERP_PAIR_XY:
275 case AMDGPU::INTERP_PAIR_ZW:
276 case AMDGPU::INTERP_VEC_LOAD:
Vincent Lejeune4ed99172013-05-17 16:50:32 +0000277 case AMDGPU::DOT_4:
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000278 return IDAlu;
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000279 default:
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000280 return IDOther;
281 }
282}
283
Vincent Lejeune21ca0b32013-05-17 16:50:44 +0000284SUnit *R600SchedStrategy::PopInst(std::vector<SUnit *> &Q) {
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000285 if (Q.empty())
286 return NULL;
Vincent Lejeune21ca0b32013-05-17 16:50:44 +0000287 for (std::vector<SUnit *>::reverse_iterator It = Q.rbegin(), E = Q.rend();
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000288 It != E; ++It) {
289 SUnit *SU = *It;
Vincent Lejeune3ab0ba32013-03-14 15:50:45 +0000290 InstructionsGroupCandidate.push_back(SU->getInstr());
291 if (TII->canBundle(InstructionsGroupCandidate)) {
292 InstructionsGroupCandidate.pop_back();
Vincent Lejeune21ca0b32013-05-17 16:50:44 +0000293 Q.erase((It + 1).base());
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000294 return SU;
Vincent Lejeune3ab0ba32013-03-14 15:50:45 +0000295 } else {
296 InstructionsGroupCandidate.pop_back();
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000297 }
298 }
299 return NULL;
300}
301
302void R600SchedStrategy::LoadAlu() {
Vincent Lejeune21ca0b32013-05-17 16:50:44 +0000303 std::vector<SUnit *> &QSrc = Pending[IDAlu];
304 for (unsigned i = 0, e = QSrc.size(); i < e; ++i) {
305 AluKind AK = getAluKind(QSrc[i]);
306 AvailableAlus[AK].push_back(QSrc[i]);
307 }
308 QSrc.clear();
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000309}
310
311void R600SchedStrategy::PrepareNextSlot() {
312 DEBUG(dbgs() << "New Slot\n");
313 assert (OccupedSlotsMask && "Slot wasn't filled");
314 OccupedSlotsMask = 0;
Vincent Lejeune3ab0ba32013-03-14 15:50:45 +0000315 InstructionsGroupCandidate.clear();
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000316 LoadAlu();
317}
318
319void R600SchedStrategy::AssignSlot(MachineInstr* MI, unsigned Slot) {
320 unsigned DestReg = MI->getOperand(0).getReg();
321 // PressureRegister crashes if an operand is def and used in the same inst
322 // and we try to constraint its regclass
323 for (MachineInstr::mop_iterator It = MI->operands_begin(),
324 E = MI->operands_end(); It != E; ++It) {
325 MachineOperand &MO = *It;
326 if (MO.isReg() && !MO.isDef() &&
327 MO.getReg() == MI->getOperand(0).getReg())
328 return;
329 }
330 // Constrains the regclass of DestReg to assign it to Slot
331 switch (Slot) {
332 case 0:
333 MRI->constrainRegClass(DestReg, &AMDGPU::R600_TReg32_XRegClass);
334 break;
335 case 1:
336 MRI->constrainRegClass(DestReg, &AMDGPU::R600_TReg32_YRegClass);
337 break;
338 case 2:
339 MRI->constrainRegClass(DestReg, &AMDGPU::R600_TReg32_ZRegClass);
340 break;
341 case 3:
342 MRI->constrainRegClass(DestReg, &AMDGPU::R600_TReg32_WRegClass);
343 break;
344 }
345}
346
347SUnit *R600SchedStrategy::AttemptFillSlot(unsigned Slot) {
348 static const AluKind IndexToID[] = {AluT_X, AluT_Y, AluT_Z, AluT_W};
349 SUnit *SlotedSU = PopInst(AvailableAlus[IndexToID[Slot]]);
Vincent Lejeune21ca0b32013-05-17 16:50:44 +0000350 if (SlotedSU)
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000351 return SlotedSU;
Vincent Lejeune21ca0b32013-05-17 16:50:44 +0000352 SUnit *UnslotedSU = PopInst(AvailableAlus[AluAny]);
353 if (UnslotedSU)
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000354 AssignSlot(UnslotedSU->getInstr(), Slot);
Vincent Lejeune21ca0b32013-05-17 16:50:44 +0000355 return UnslotedSU;
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000356}
357
358bool R600SchedStrategy::isAvailablesAluEmpty() const {
Vincent Lejeune21ca0b32013-05-17 16:50:44 +0000359 return Pending[IDAlu].empty() && AvailableAlus[AluAny].empty() &&
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000360 AvailableAlus[AluT_XYZW].empty() && AvailableAlus[AluT_X].empty() &&
361 AvailableAlus[AluT_Y].empty() && AvailableAlus[AluT_Z].empty() &&
Vincent Lejeune76fc2d02013-05-17 16:50:56 +0000362 AvailableAlus[AluT_W].empty() && AvailableAlus[AluDiscarded].empty() &&
363 AvailableAlus[AluPredX].empty();
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000364}
365
366SUnit* R600SchedStrategy::pickAlu() {
367 while (!isAvailablesAluEmpty()) {
368 if (!OccupedSlotsMask) {
Vincent Lejeune76fc2d02013-05-17 16:50:56 +0000369 // Bottom up scheduling : predX must comes first
370 if (!AvailableAlus[AluPredX].empty()) {
371 OccupedSlotsMask = 15;
372 return PopInst(AvailableAlus[AluPredX]);
373 }
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000374 // Flush physical reg copies (RA will discard them)
375 if (!AvailableAlus[AluDiscarded].empty()) {
376 OccupedSlotsMask = 15;
377 return PopInst(AvailableAlus[AluDiscarded]);
378 }
379 // If there is a T_XYZW alu available, use it
380 if (!AvailableAlus[AluT_XYZW].empty()) {
381 OccupedSlotsMask = 15;
382 return PopInst(AvailableAlus[AluT_XYZW]);
383 }
384 }
Vincent Lejeune76fc2d02013-05-17 16:50:56 +0000385 for (int Chan = 3; Chan > -1; --Chan) {
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000386 bool isOccupied = OccupedSlotsMask & (1 << Chan);
387 if (!isOccupied) {
388 SUnit *SU = AttemptFillSlot(Chan);
389 if (SU) {
390 OccupedSlotsMask |= (1 << Chan);
Vincent Lejeune3ab0ba32013-03-14 15:50:45 +0000391 InstructionsGroupCandidate.push_back(SU->getInstr());
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000392 return SU;
393 }
394 }
395 }
396 PrepareNextSlot();
397 }
398 return NULL;
399}
400
401SUnit* R600SchedStrategy::pickOther(int QID) {
402 SUnit *SU = 0;
Vincent Lejeune21ca0b32013-05-17 16:50:44 +0000403 std::vector<SUnit *> &AQ = Available[QID];
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000404
Vincent Lejeune21ca0b32013-05-17 16:50:44 +0000405 if (AQ.empty()) {
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000406 MoveUnits(Pending[QID], AQ);
407 }
Vincent Lejeune21ca0b32013-05-17 16:50:44 +0000408 if (!AQ.empty()) {
409 SU = AQ.back();
410 AQ.resize(AQ.size() - 1);
Vincent Lejeune62f38ca2013-03-05 18:41:32 +0000411 }
412 return SU;
413}
414