1 //===-- R600MachineScheduler.cpp - R600 Scheduler Interface -*- C++ -*-----===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// \brief R600 Machine Scheduler interface
12 // TODO: Scheduling is optimised for VLIW4 arch, modify it to support TRANS slot
14 //===----------------------------------------------------------------------===//
16 #define DEBUG_TYPE "misched"
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"
23 #include "llvm/Support/raw_ostream.h"
28 void R600SchedStrategy::initialize(ScheduleDAGMI *dag) {
31 TII = static_cast<const R600InstrInfo*>(DAG->TII);
32 TRI = static_cast<const R600RegisterInfo*>(DAG->TRI);
34 Available[IDAlu]->clear();
35 Available[IDFetch]->clear();
36 Available[IDOther]->clear();
37 CurInstKind = IDOther;
39 OccupedSlotsMask = 15;
40 InstKindLimit[IDAlu] = TII->getMaxAlusPerClause();
43 const AMDGPUSubtarget &ST = DAG->TM.getSubtarget<AMDGPUSubtarget>();
44 if (ST.device()->getGeneration() <= AMDGPUDeviceInfo::HD5XXX) {
45 InstKindLimit[IDFetch] = 7; // 8 minus 1 for security
47 InstKindLimit[IDFetch] = 15; // 16 minus 1 for security
51 void R600SchedStrategy::MoveUnits(ReadyQueue *QSrc, ReadyQueue *QDst)
55 for (ReadyQueue::iterator I = QSrc->begin(),
56 E = QSrc->end(); I != E; ++I) {
57 (*I)->NodeQueueId &= ~QSrc->getID();
63 SUnit* R600SchedStrategy::pickNode(bool &IsTopNode) {
66 NextInstKind = IDOther;
68 // check if we might want to switch current clause type
69 bool AllowSwitchToAlu = (CurInstKind == IDOther) ||
70 (CurEmitted > InstKindLimit[CurInstKind]) ||
71 (Available[CurInstKind]->empty());
72 bool AllowSwitchFromAlu = (CurEmitted > InstKindLimit[CurInstKind]) &&
73 (!Available[IDFetch]->empty() || !Available[IDOther]->empty());
75 if ((AllowSwitchToAlu && CurInstKind != IDAlu) ||
76 (!AllowSwitchFromAlu && CurInstKind == IDAlu)) {
80 if (CurEmitted > InstKindLimit[IDAlu])
88 SU = pickOther(IDFetch);
90 NextInstKind = IDFetch;
95 SU = pickOther(IDOther);
97 NextInstKind = IDOther;
102 dbgs() << "picked node: ";
105 dbgs() << "NO NODE ";
106 for (int i = 0; i < IDLast; ++i) {
107 Available[i]->dump();
110 for (unsigned i = 0; i < DAG->SUnits.size(); i++) {
111 const SUnit &S = DAG->SUnits[i];
121 void R600SchedStrategy::schedNode(SUnit *SU, bool IsTopNode) {
123 DEBUG(dbgs() << "scheduled: ");
124 DEBUG(SU->dump(DAG));
126 if (NextInstKind != CurInstKind) {
127 DEBUG(dbgs() << "Instruction Type Switch\n");
128 if (NextInstKind != IDAlu)
129 OccupedSlotsMask = 15;
131 CurInstKind = NextInstKind;
134 if (CurInstKind == IDAlu) {
135 switch (getAluKind(SU)) {
143 for (MachineInstr::mop_iterator It = SU->getInstr()->operands_begin(),
144 E = SU->getInstr()->operands_end(); It != E; ++It) {
145 MachineOperand &MO = *It;
146 if (MO.isReg() && MO.getReg() == AMDGPU::ALU_LITERAL_X)
156 DEBUG(dbgs() << CurEmitted << " Instructions Emitted in this clause\n");
158 if (CurInstKind != IDFetch) {
159 MoveUnits(Pending[IDFetch], Available[IDFetch]);
161 MoveUnits(Pending[IDOther], Available[IDOther]);
164 void R600SchedStrategy::releaseTopNode(SUnit *SU) {
165 int IK = getInstKind(SU);
167 DEBUG(dbgs() << IK << " <= ");
168 DEBUG(SU->dump(DAG));
170 Pending[IK]->push(SU);
173 void R600SchedStrategy::releaseBottomNode(SUnit *SU) {
176 bool R600SchedStrategy::regBelongsToClass(unsigned Reg,
177 const TargetRegisterClass *RC) const {
178 if (!TargetRegisterInfo::isVirtualRegister(Reg)) {
179 return RC->contains(Reg);
181 return MRI->getRegClass(Reg) == RC;
185 R600SchedStrategy::AluKind R600SchedStrategy::getAluKind(SUnit *SU) const {
186 MachineInstr *MI = SU->getInstr();
188 switch (MI->getOpcode()) {
189 case AMDGPU::INTERP_PAIR_XY:
190 case AMDGPU::INTERP_PAIR_ZW:
191 case AMDGPU::INTERP_VEC_LOAD:
194 if (TargetRegisterInfo::isPhysicalRegister(MI->getOperand(1).getReg())) {
195 // %vregX = COPY Tn_X is likely to be discarded in favor of an
196 // assignement of Tn_X to %vregX, don't considers it in scheduling
199 else if (MI->getOperand(1).isUndef()) {
200 // MI will become a KILL, don't considers it in scheduling
207 // Does the instruction take a whole IG ?
208 if(TII->isVector(*MI) ||
209 TII->isCubeOp(MI->getOpcode()) ||
210 TII->isReductionOp(MI->getOpcode()))
213 // Is the result already assigned to a channel ?
214 unsigned DestSubReg = MI->getOperand(0).getSubReg();
215 switch (DestSubReg) {
228 // Is the result already member of a X/Y/Z/W class ?
229 unsigned DestReg = MI->getOperand(0).getReg();
230 if (regBelongsToClass(DestReg, &AMDGPU::R600_TReg32_XRegClass) ||
231 regBelongsToClass(DestReg, &AMDGPU::R600_AddrRegClass))
233 if (regBelongsToClass(DestReg, &AMDGPU::R600_TReg32_YRegClass))
235 if (regBelongsToClass(DestReg, &AMDGPU::R600_TReg32_ZRegClass))
237 if (regBelongsToClass(DestReg, &AMDGPU::R600_TReg32_WRegClass))
239 if (regBelongsToClass(DestReg, &AMDGPU::R600_Reg128RegClass))
246 int R600SchedStrategy::getInstKind(SUnit* SU) {
247 int Opcode = SU->getInstr()->getOpcode();
249 if (TII->isALUInstr(Opcode)) {
255 case AMDGPU::CONST_COPY:
256 case AMDGPU::INTERP_PAIR_XY:
257 case AMDGPU::INTERP_PAIR_ZW:
258 case AMDGPU::INTERP_VEC_LOAD:
259 case AMDGPU::DOT4_eg_pseudo:
260 case AMDGPU::DOT4_r600_pseudo:
262 case AMDGPU::TEX_VTX_CONSTBUF:
263 case AMDGPU::TEX_VTX_TEXBUF:
265 case AMDGPU::TEX_GET_TEXTURE_RESINFO:
266 case AMDGPU::TEX_GET_GRADIENTS_H:
267 case AMDGPU::TEX_GET_GRADIENTS_V:
268 case AMDGPU::TEX_SET_GRADIENTS_H:
269 case AMDGPU::TEX_SET_GRADIENTS_V:
270 case AMDGPU::TEX_SAMPLE:
271 case AMDGPU::TEX_SAMPLE_C:
272 case AMDGPU::TEX_SAMPLE_L:
273 case AMDGPU::TEX_SAMPLE_C_L:
274 case AMDGPU::TEX_SAMPLE_LB:
275 case AMDGPU::TEX_SAMPLE_C_LB:
276 case AMDGPU::TEX_SAMPLE_G:
277 case AMDGPU::TEX_SAMPLE_C_G:
279 case AMDGPU::TXD_SHADOW:
283 dbgs() << "other inst: ";
290 SUnit *R600SchedStrategy::PopInst(std::multiset<SUnit *, CompareSUnit> &Q) {
293 for (std::set<SUnit *, CompareSUnit>::iterator It = Q.begin(), E = Q.end();
296 InstructionsGroupCandidate.push_back(SU->getInstr());
297 if (TII->canBundle(InstructionsGroupCandidate)) {
298 InstructionsGroupCandidate.pop_back();
302 InstructionsGroupCandidate.pop_back();
308 void R600SchedStrategy::LoadAlu() {
309 ReadyQueue *QSrc = Pending[IDAlu];
310 for (ReadyQueue::iterator I = QSrc->begin(),
311 E = QSrc->end(); I != E; ++I) {
312 (*I)->NodeQueueId &= ~QSrc->getID();
313 AluKind AK = getAluKind(*I);
314 AvailableAlus[AK].insert(*I);
319 void R600SchedStrategy::PrepareNextSlot() {
320 DEBUG(dbgs() << "New Slot\n");
321 assert (OccupedSlotsMask && "Slot wasn't filled");
322 OccupedSlotsMask = 0;
323 InstructionsGroupCandidate.clear();
327 void R600SchedStrategy::AssignSlot(MachineInstr* MI, unsigned Slot) {
328 unsigned DestReg = MI->getOperand(0).getReg();
329 // PressureRegister crashes if an operand is def and used in the same inst
330 // and we try to constraint its regclass
331 for (MachineInstr::mop_iterator It = MI->operands_begin(),
332 E = MI->operands_end(); It != E; ++It) {
333 MachineOperand &MO = *It;
334 if (MO.isReg() && !MO.isDef() &&
335 MO.getReg() == MI->getOperand(0).getReg())
338 // Constrains the regclass of DestReg to assign it to Slot
341 MRI->constrainRegClass(DestReg, &AMDGPU::R600_TReg32_XRegClass);
344 MRI->constrainRegClass(DestReg, &AMDGPU::R600_TReg32_YRegClass);
347 MRI->constrainRegClass(DestReg, &AMDGPU::R600_TReg32_ZRegClass);
350 MRI->constrainRegClass(DestReg, &AMDGPU::R600_TReg32_WRegClass);
355 SUnit *R600SchedStrategy::AttemptFillSlot(unsigned Slot) {
356 static const AluKind IndexToID[] = {AluT_X, AluT_Y, AluT_Z, AluT_W};
357 SUnit *SlotedSU = PopInst(AvailableAlus[IndexToID[Slot]]);
358 SUnit *UnslotedSU = PopInst(AvailableAlus[AluAny]);
361 } else if (!SlotedSU) {
362 AssignSlot(UnslotedSU->getInstr(), Slot);
365 //Determine which one to pick (the lesser one)
366 if (CompareSUnit()(SlotedSU, UnslotedSU)) {
367 AvailableAlus[AluAny].insert(UnslotedSU);
370 AvailableAlus[IndexToID[Slot]].insert(SlotedSU);
371 AssignSlot(UnslotedSU->getInstr(), Slot);
377 bool R600SchedStrategy::isAvailablesAluEmpty() const {
378 return Pending[IDAlu]->empty() && AvailableAlus[AluAny].empty() &&
379 AvailableAlus[AluT_XYZW].empty() && AvailableAlus[AluT_X].empty() &&
380 AvailableAlus[AluT_Y].empty() && AvailableAlus[AluT_Z].empty() &&
381 AvailableAlus[AluT_W].empty() && AvailableAlus[AluDiscarded].empty();
384 SUnit* R600SchedStrategy::pickAlu() {
385 while (!isAvailablesAluEmpty()) {
386 if (!OccupedSlotsMask) {
387 // Flush physical reg copies (RA will discard them)
388 if (!AvailableAlus[AluDiscarded].empty()) {
389 OccupedSlotsMask = 15;
390 return PopInst(AvailableAlus[AluDiscarded]);
392 // If there is a T_XYZW alu available, use it
393 if (!AvailableAlus[AluT_XYZW].empty()) {
394 OccupedSlotsMask = 15;
395 return PopInst(AvailableAlus[AluT_XYZW]);
398 for (unsigned Chan = 0; Chan < 4; ++Chan) {
399 bool isOccupied = OccupedSlotsMask & (1 << Chan);
401 SUnit *SU = AttemptFillSlot(Chan);
403 OccupedSlotsMask |= (1 << Chan);
404 InstructionsGroupCandidate.push_back(SU->getInstr());
414 SUnit* R600SchedStrategy::pickOther(int QID) {
416 ReadyQueue *AQ = Available[QID];
419 MoveUnits(Pending[QID], AQ);
423 AQ->remove(AQ->begin());