Line data Source code
1 : //===-- 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 : /// R600 Machine Scheduler interface
12 : //
13 : //===----------------------------------------------------------------------===//
14 :
15 : #include "R600MachineScheduler.h"
16 : #include "AMDGPUSubtarget.h"
17 : #include "R600InstrInfo.h"
18 : #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
19 : #include "llvm/CodeGen/MachineRegisterInfo.h"
20 : #include "llvm/IR/LegacyPassManager.h"
21 : #include "llvm/Pass.h"
22 : #include "llvm/Support/raw_ostream.h"
23 :
24 : using namespace llvm;
25 :
26 : #define DEBUG_TYPE "machine-scheduler"
27 :
28 2342 : void R600SchedStrategy::initialize(ScheduleDAGMI *dag) {
29 : assert(dag->hasVRegLiveness() && "R600SchedStrategy needs vreg liveness");
30 2342 : DAG = static_cast<ScheduleDAGMILive*>(dag);
31 2342 : const R600Subtarget &ST = DAG->MF.getSubtarget<R600Subtarget>();
32 2342 : TII = static_cast<const R600InstrInfo*>(DAG->TII);
33 2342 : TRI = static_cast<const R600RegisterInfo*>(DAG->TRI);
34 2342 : VLIW5 = !ST.hasCaymanISA();
35 2342 : MRI = &DAG->MRI;
36 2342 : CurInstKind = IDOther;
37 2342 : CurEmitted = 0;
38 2342 : OccupedSlotsMask = 31;
39 2342 : InstKindLimit[IDAlu] = TII->getMaxAlusPerClause();
40 2342 : InstKindLimit[IDOther] = 32;
41 2342 : InstKindLimit[IDFetch] = ST.getTexVTXClauseSize();
42 2342 : AluInstCount = 0;
43 2342 : FetchInstCount = 0;
44 2342 : }
45 :
46 63204 : void R600SchedStrategy::MoveUnits(std::vector<SUnit *> &QSrc,
47 : std::vector<SUnit *> &QDst)
48 : {
49 63204 : QDst.insert(QDst.end(), QSrc.begin(), QSrc.end());
50 : QSrc.clear();
51 63204 : }
52 :
53 : static unsigned getWFCountLimitedByGPR(unsigned GPRCount) {
54 : assert (GPRCount && "GPRCount cannot be 0");
55 4321 : return 248 / GPRCount;
56 : }
57 :
58 56614 : SUnit* R600SchedStrategy::pickNode(bool &IsTopNode) {
59 : SUnit *SU = nullptr;
60 56614 : NextInstKind = IDOther;
61 :
62 56614 : IsTopNode = false;
63 :
64 : // check if we might want to switch current clause type
65 56614 : bool AllowSwitchToAlu = (CurEmitted >= InstKindLimit[CurInstKind]) ||
66 56379 : (Available[CurInstKind].empty());
67 56614 : bool AllowSwitchFromAlu = (CurEmitted >= InstKindLimit[CurInstKind]) &&
68 201 : (!Available[IDFetch].empty() || !Available[IDOther].empty());
69 :
70 56614 : if (CurInstKind == IDAlu && !Available[IDFetch].empty()) {
71 : // We use the heuristic provided by AMD Accelerated Parallel Processing
72 : // OpenCL Programming Guide :
73 : // The approx. number of WF that allows TEX inst to hide ALU inst is :
74 : // 500 (cycles for TEX) / (AluFetchRatio * 8 (cycles for ALU))
75 : float ALUFetchRationEstimate =
76 4322 : (AluInstCount + AvailablesAluCount() + Pending[IDAlu].size()) /
77 4322 : (FetchInstCount + Available[IDFetch].size());
78 4322 : if (ALUFetchRationEstimate == 0) {
79 : AllowSwitchFromAlu = true;
80 : } else {
81 4321 : unsigned NeededWF = 62.5f / ALUFetchRationEstimate;
82 : LLVM_DEBUG(dbgs() << NeededWF << " approx. Wavefronts Required\n");
83 : // We assume the local GPR requirements to be "dominated" by the requirement
84 : // of the TEX clause (which consumes 128 bits regs) ; ALU inst before and
85 : // after TEX are indeed likely to consume or generate values from/for the
86 : // TEX clause.
87 : // Available[IDFetch].size() * 2 : GPRs required in the Fetch clause
88 : // We assume that fetch instructions are either TnXYZW = TEX TnXYZW (need
89 : // one GPR) or TmXYZW = TnXYZW (need 2 GPR).
90 : // (TODO : use RegisterPressure)
91 : // If we are going too use too many GPR, we flush Fetch instruction to lower
92 : // register pressure on 128 bits regs.
93 4321 : unsigned NearRegisterRequirement = 2 * Available[IDFetch].size();
94 4321 : if (NeededWF > getWFCountLimitedByGPR(NearRegisterRequirement))
95 : AllowSwitchFromAlu = true;
96 : }
97 : }
98 :
99 56614 : if (!SU && ((AllowSwitchToAlu && CurInstKind != IDAlu) ||
100 51889 : (!AllowSwitchFromAlu && CurInstKind == IDAlu))) {
101 : // try to pick ALU
102 51435 : SU = pickAlu();
103 51435 : if (!SU && !PhysicalRegCopy.empty()) {
104 1745 : SU = PhysicalRegCopy.front();
105 1745 : PhysicalRegCopy.erase(PhysicalRegCopy.begin());
106 : }
107 51435 : if (SU) {
108 46810 : if (CurEmitted >= InstKindLimit[IDAlu])
109 193 : CurEmitted = 0;
110 46810 : NextInstKind = IDAlu;
111 : }
112 : }
113 :
114 51435 : if (!SU) {
115 : // try to pick FETCH
116 9804 : SU = pickOther(IDFetch);
117 9804 : if (SU)
118 1983 : NextInstKind = IDFetch;
119 : }
120 :
121 : // try to pick other
122 56614 : if (!SU) {
123 7821 : SU = pickOther(IDOther);
124 7821 : if (SU)
125 5479 : NextInstKind = IDOther;
126 : }
127 :
128 : LLVM_DEBUG(if (SU) {
129 : dbgs() << " ** Pick node **\n";
130 : DAG->dumpNode(*SU);
131 : } else {
132 : dbgs() << "NO NODE \n";
133 : for (unsigned i = 0; i < DAG->SUnits.size(); i++) {
134 : const SUnit &S = DAG->SUnits[i];
135 : if (!S.isScheduled)
136 : DAG->dumpNode(S);
137 : }
138 : });
139 :
140 56614 : return SU;
141 : }
142 :
143 54272 : void R600SchedStrategy::schedNode(SUnit *SU, bool IsTopNode) {
144 54272 : if (NextInstKind != CurInstKind) {
145 : LLVM_DEBUG(dbgs() << "Instruction Type Switch\n");
146 6453 : if (NextInstKind != IDAlu)
147 2221 : OccupedSlotsMask |= 31;
148 6453 : CurEmitted = 0;
149 6453 : CurInstKind = NextInstKind;
150 : }
151 :
152 54272 : if (CurInstKind == IDAlu) {
153 46810 : AluInstCount ++;
154 46810 : switch (getAluKind(SU)) {
155 132 : case AluT_XYZW:
156 132 : CurEmitted += 4;
157 132 : break;
158 : case AluDiscarded:
159 : break;
160 46678 : default: {
161 46678 : ++CurEmitted;
162 847021 : for (MachineInstr::mop_iterator It = SU->getInstr()->operands_begin(),
163 893699 : E = SU->getInstr()->operands_end(); It != E; ++It) {
164 : MachineOperand &MO = *It;
165 847021 : if (MO.isReg() && MO.getReg() == R600::ALU_LITERAL_X)
166 21080 : ++CurEmitted;
167 46678 : }
168 : }
169 : }
170 : } else {
171 7462 : ++CurEmitted;
172 : }
173 :
174 : LLVM_DEBUG(dbgs() << CurEmitted << " Instructions Emitted in this clause\n");
175 :
176 54272 : if (CurInstKind != IDFetch) {
177 52289 : MoveUnits(Pending[IDFetch], Available[IDFetch]);
178 : } else
179 1983 : FetchInstCount++;
180 54272 : }
181 :
182 : static bool
183 : isPhysicalRegCopy(MachineInstr *MI) {
184 54272 : if (MI->getOpcode() != R600::COPY)
185 : return false;
186 :
187 2421 : return !TargetRegisterInfo::isVirtualRegister(MI->getOperand(1).getReg());
188 : }
189 :
190 10619 : void R600SchedStrategy::releaseTopNode(SUnit *SU) {
191 : LLVM_DEBUG(dbgs() << "Top Releasing "; DAG->dumpNode(*SU));
192 10619 : }
193 :
194 54272 : void R600SchedStrategy::releaseBottomNode(SUnit *SU) {
195 : LLVM_DEBUG(dbgs() << "Bottom Releasing "; DAG->dumpNode(*SU));
196 54272 : if (isPhysicalRegCopy(SU->getInstr())) {
197 1745 : PhysicalRegCopy.push_back(SU);
198 1745 : return;
199 : }
200 :
201 52527 : int IK = getInstKind(SU);
202 :
203 : // There is no export clause, we can schedule one as soon as its ready
204 52527 : if (IK == IDOther)
205 5479 : Available[IDOther].push_back(SU);
206 : else
207 47048 : Pending[IK].push_back(SU);
208 :
209 : }
210 :
211 306104 : bool R600SchedStrategy::regBelongsToClass(unsigned Reg,
212 : const TargetRegisterClass *RC) const {
213 306104 : if (!TargetRegisterInfo::isVirtualRegister(Reg)) {
214 0 : return RC->contains(Reg);
215 : } else {
216 612208 : return MRI->getRegClass(Reg) == RC;
217 : }
218 : }
219 :
220 91875 : R600SchedStrategy::AluKind R600SchedStrategy::getAluKind(SUnit *SU) const {
221 91875 : MachineInstr *MI = SU->getInstr();
222 :
223 91875 : if (TII->isTransOnly(*MI))
224 : return AluTrans;
225 :
226 180070 : switch (MI->getOpcode()) {
227 : case R600::PRED_X:
228 : return AluPredX;
229 62 : case R600::INTERP_PAIR_XY:
230 : case R600::INTERP_PAIR_ZW:
231 : case R600::INTERP_VEC_LOAD:
232 : case R600::DOT_4:
233 62 : return AluT_XYZW;
234 3097 : case R600::COPY:
235 6194 : if (MI->getOperand(1).isUndef()) {
236 : // MI will become a KILL, don't considers it in scheduling
237 : return AluDiscarded;
238 : }
239 : default:
240 : break;
241 : }
242 :
243 : // Does the instruction take a whole IG ?
244 : // XXX: Is it possible to add a helper function in R600InstrInfo that can
245 : // be used here and in R600PacketizerList::isSoloInstruction() ?
246 179518 : if(TII->isVector(*MI) ||
247 269133 : TII->isCubeOp(MI->getOpcode()) ||
248 358940 : TII->isReductionOp(MI->getOpcode()) ||
249 89711 : MI->getOpcode() == R600::GROUP_BARRIER) {
250 104 : return AluT_XYZW;
251 : }
252 :
253 89703 : if (TII->isLDSInstr(MI->getOpcode())) {
254 : return AluT_X;
255 : }
256 :
257 : // Is the result already assigned to a channel ?
258 82757 : unsigned DestSubReg = MI->getOperand(0).getSubReg();
259 : switch (DestSubReg) {
260 : case R600::sub0:
261 : return AluT_X;
262 : case R600::sub1:
263 : return AluT_Y;
264 : case R600::sub2:
265 : return AluT_Z;
266 : case R600::sub3:
267 : return AluT_W;
268 : default:
269 : break;
270 : }
271 :
272 : // Is the result already member of a X/Y/Z/W class ?
273 66708 : unsigned DestReg = MI->getOperand(0).getReg();
274 121666 : if (regBelongsToClass(DestReg, &R600::R600_TReg32_XRegClass) ||
275 54958 : regBelongsToClass(DestReg, &R600::R600_AddrRegClass))
276 11750 : return AluT_X;
277 54958 : if (regBelongsToClass(DestReg, &R600::R600_TReg32_YRegClass))
278 : return AluT_Y;
279 52456 : if (regBelongsToClass(DestReg, &R600::R600_TReg32_ZRegClass))
280 : return AluT_Z;
281 48583 : if (regBelongsToClass(DestReg, &R600::R600_TReg32_WRegClass))
282 : return AluT_W;
283 28441 : if (regBelongsToClass(DestReg, &R600::R600_Reg128RegClass))
284 : return AluT_XYZW;
285 :
286 : // LDS src registers cannot be used in the Trans slot.
287 28392 : if (TII->readsLDSSrcReg(*MI))
288 0 : return AluT_XYZW;
289 :
290 : return AluAny;
291 : }
292 :
293 52527 : int R600SchedStrategy::getInstKind(SUnit* SU) {
294 52527 : int Opcode = SU->getInstr()->getOpcode();
295 :
296 52527 : if (TII->usesTextureCache(Opcode) || TII->usesVertexCache(Opcode))
297 1983 : return IDFetch;
298 :
299 50544 : if (TII->isALUInstr(Opcode)) {
300 : return IDAlu;
301 : }
302 :
303 6269 : switch (Opcode) {
304 : case R600::PRED_X:
305 : case R600::COPY:
306 : case R600::CONST_COPY:
307 : case R600::INTERP_PAIR_XY:
308 : case R600::INTERP_PAIR_ZW:
309 : case R600::INTERP_VEC_LOAD:
310 : case R600::DOT_4:
311 : return IDAlu;
312 5479 : default:
313 5479 : return IDOther;
314 : }
315 : }
316 :
317 236640 : SUnit *R600SchedStrategy::PopInst(std::vector<SUnit *> &Q, bool AnyALU) {
318 236640 : if (Q.empty())
319 : return nullptr;
320 : for (std::vector<SUnit *>::reverse_iterator It = Q.rbegin(), E = Q.rend();
321 47447 : It != E; ++It) {
322 46559 : SUnit *SU = *It;
323 46559 : InstructionsGroupCandidate.push_back(SU->getInstr());
324 46559 : if (TII->fitsConstReadLimitations(InstructionsGroupCandidate) &&
325 13361 : (!AnyALU || !TII->isVectorOnly(*SU->getInstr()))) {
326 : InstructionsGroupCandidate.pop_back();
327 : Q.erase((It + 1).base());
328 : return SU;
329 : } else {
330 : InstructionsGroupCandidate.pop_back();
331 : }
332 : }
333 : return nullptr;
334 : }
335 :
336 21701 : void R600SchedStrategy::LoadAlu() {
337 : std::vector<SUnit *> &QSrc = Pending[IDAlu];
338 88467 : for (unsigned i = 0, e = QSrc.size(); i < e; ++i) {
339 90130 : AluKind AK = getAluKind(QSrc[i]);
340 90130 : AvailableAlus[AK].push_back(QSrc[i]);
341 : }
342 : QSrc.clear();
343 21701 : }
344 :
345 21701 : void R600SchedStrategy::PrepareNextSlot() {
346 : LLVM_DEBUG(dbgs() << "New Slot\n");
347 : assert (OccupedSlotsMask && "Slot wasn't filled");
348 21701 : OccupedSlotsMask = 0;
349 : // if (HwGen == AMDGPUSubtarget::NORTHERN_ISLANDS)
350 : // OccupedSlotsMask |= 16;
351 : InstructionsGroupCandidate.clear();
352 21701 : LoadAlu();
353 21701 : }
354 :
355 28103 : void R600SchedStrategy::AssignSlot(MachineInstr* MI, unsigned Slot) {
356 56206 : int DstIndex = TII->getOperandIdx(MI->getOpcode(), R600::OpName::dst);
357 28103 : if (DstIndex == -1) {
358 : return;
359 : }
360 28052 : unsigned DestReg = MI->getOperand(DstIndex).getReg();
361 : // PressureRegister crashes if an operand is def and used in the same inst
362 : // and we try to constraint its regclass
363 570753 : for (MachineInstr::mop_iterator It = MI->operands_begin(),
364 598805 : E = MI->operands_end(); It != E; ++It) {
365 : MachineOperand &MO = *It;
366 570760 : if (MO.isReg() && !MO.isDef() &&
367 87404 : MO.getReg() == DestReg)
368 : return;
369 : }
370 : // Constrains the regclass of DestReg to assign it to Slot
371 28045 : switch (Slot) {
372 1714 : case 0:
373 1714 : MRI->constrainRegClass(DestReg, &R600::R600_TReg32_XRegClass);
374 1714 : break;
375 2462 : case 1:
376 2462 : MRI->constrainRegClass(DestReg, &R600::R600_TReg32_YRegClass);
377 2462 : break;
378 3831 : case 2:
379 3831 : MRI->constrainRegClass(DestReg, &R600::R600_TReg32_ZRegClass);
380 3831 : break;
381 20038 : case 3:
382 20038 : MRI->constrainRegClass(DestReg, &R600::R600_TReg32_WRegClass);
383 20038 : break;
384 : }
385 : }
386 :
387 125715 : SUnit *R600SchedStrategy::AttemptFillSlot(unsigned Slot, bool AnyAlu) {
388 : static const AluKind IndexToID[] = {AluT_X, AluT_Y, AluT_Z, AluT_W};
389 125715 : SUnit *SlotedSU = PopInst(AvailableAlus[IndexToID[Slot]], AnyAlu);
390 125715 : if (SlotedSU)
391 : return SlotedSU;
392 109839 : SUnit *UnslotedSU = PopInst(AvailableAlus[AluAny], AnyAlu);
393 109839 : if (UnslotedSU)
394 28103 : AssignSlot(UnslotedSU->getInstr(), Slot);
395 : return UnslotedSU;
396 : }
397 :
398 77458 : unsigned R600SchedStrategy::AvailablesAluCount() const {
399 309832 : return AvailableAlus[AluAny].size() + AvailableAlus[AluT_XYZW].size() +
400 309832 : AvailableAlus[AluT_X].size() + AvailableAlus[AluT_Y].size() +
401 309832 : AvailableAlus[AluT_Z].size() + AvailableAlus[AluT_W].size() +
402 309832 : AvailableAlus[AluTrans].size() + AvailableAlus[AluDiscarded].size() +
403 154916 : AvailableAlus[AluPredX].size();
404 : }
405 :
406 51435 : SUnit* R600SchedStrategy::pickAlu() {
407 73136 : while (AvailablesAluCount() || !Pending[IDAlu].empty()) {
408 66766 : if (!OccupedSlotsMask) {
409 : // Bottom up scheduling : predX must comes first
410 21701 : if (!AvailableAlus[AluPredX].empty()) {
411 83 : OccupedSlotsMask |= 31;
412 83 : return PopInst(AvailableAlus[AluPredX], false);
413 : }
414 : // Flush physical reg copies (RA will discard them)
415 21618 : if (!AvailableAlus[AluDiscarded].empty()) {
416 0 : OccupedSlotsMask |= 31;
417 0 : return PopInst(AvailableAlus[AluDiscarded], false);
418 : }
419 : // If there is a T_XYZW alu available, use it
420 21618 : if (!AvailableAlus[AluT_XYZW].empty()) {
421 83 : OccupedSlotsMask |= 15;
422 83 : return PopInst(AvailableAlus[AluT_XYZW], false);
423 : }
424 : }
425 66600 : bool TransSlotOccuped = OccupedSlotsMask & 16;
426 66600 : if (!TransSlotOccuped && VLIW5) {
427 24014 : if (!AvailableAlus[AluTrans].empty()) {
428 920 : OccupedSlotsMask |= 16;
429 920 : return PopInst(AvailableAlus[AluTrans], false);
430 : }
431 23094 : SUnit *SU = AttemptFillSlot(3, true);
432 23094 : if (SU) {
433 12423 : OccupedSlotsMask |= 16;
434 12423 : return SU;
435 : }
436 : }
437 191486 : for (int Chan = 3; Chan > -1; --Chan) {
438 169785 : bool isOccupied = OccupedSlotsMask & (1 << Chan);
439 169785 : if (!isOccupied) {
440 102621 : SUnit *SU = AttemptFillSlot(Chan, false);
441 102621 : if (SU) {
442 31556 : OccupedSlotsMask |= (1 << Chan);
443 31556 : InstructionsGroupCandidate.push_back(SU->getInstr());
444 31556 : return SU;
445 : }
446 : }
447 : }
448 21701 : PrepareNextSlot();
449 : }
450 : return nullptr;
451 : }
452 :
453 17625 : SUnit* R600SchedStrategy::pickOther(int QID) {
454 : SUnit *SU = nullptr;
455 17625 : std::vector<SUnit *> &AQ = Available[QID];
456 :
457 17625 : if (AQ.empty()) {
458 10915 : MoveUnits(Pending[QID], AQ);
459 : }
460 17625 : if (!AQ.empty()) {
461 7462 : SU = AQ.back();
462 : AQ.pop_back();
463 : }
464 17625 : return SU;
465 : }
|