HexagonMachineScheduler.cpp revision 3e59040810d0e6e04269ac8f781fa44df6088458
1//===- HexagonMachineScheduler.cpp - MI Scheduler for Hexagon -------------===//
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// MachineScheduler schedules machine instructions after phi elimination. It
11// preserves LiveIntervals so it can be invoked before register allocation.
12//
13//===----------------------------------------------------------------------===//
14
15#define DEBUG_TYPE "misched"
16
17#include "HexagonMachineScheduler.h"
18
19#include <queue>
20
21using namespace llvm;
22
23static cl::opt<bool> ForceTopDown("vliw-misched-topdown", cl::Hidden,
24                                  cl::desc("Force top-down list scheduling"));
25static cl::opt<bool> ForceBottomUp("vliw-misched-bottomup", cl::Hidden,
26                                   cl::desc("Force bottom-up list scheduling"));
27
28#ifndef NDEBUG
29static cl::opt<bool> ViewMISchedDAGs("vliw-view-misched-dags", cl::Hidden,
30  cl::desc("Pop up a window to show MISched dags after they are processed"));
31
32static cl::opt<unsigned> MISchedCutoff("vliw-misched-cutoff", cl::Hidden,
33  cl::desc("Stop scheduling after N instructions"), cl::init(~0U));
34#else
35static bool ViewMISchedDAGs = false;
36#endif // NDEBUG
37
38/// Decrement this iterator until reaching the top or a non-debug instr.
39static MachineBasicBlock::iterator
40priorNonDebug(MachineBasicBlock::iterator I, MachineBasicBlock::iterator Beg) {
41  assert(I != Beg && "reached the top of the region, cannot decrement");
42  while (--I != Beg) {
43    if (!I->isDebugValue())
44      break;
45  }
46  return I;
47}
48
49/// If this iterator is a debug value, increment until reaching the End or a
50/// non-debug instruction.
51static MachineBasicBlock::iterator
52nextIfDebug(MachineBasicBlock::iterator I, MachineBasicBlock::iterator End) {
53  for(; I != End; ++I) {
54    if (!I->isDebugValue())
55      break;
56  }
57  return I;
58}
59
60/// ReleaseSucc - Decrement the NumPredsLeft count of a successor. When
61/// NumPredsLeft reaches zero, release the successor node.
62///
63/// FIXME: Adjust SuccSU height based on MinLatency.
64void VLIWMachineScheduler::releaseSucc(SUnit *SU, SDep *SuccEdge) {
65  SUnit *SuccSU = SuccEdge->getSUnit();
66
67#ifndef NDEBUG
68  if (SuccSU->NumPredsLeft == 0) {
69    dbgs() << "*** Scheduling failed! ***\n";
70    SuccSU->dump(this);
71    dbgs() << " has been released too many times!\n";
72    llvm_unreachable(0);
73  }
74#endif
75  --SuccSU->NumPredsLeft;
76  if (SuccSU->NumPredsLeft == 0 && SuccSU != &ExitSU)
77    SchedImpl->releaseTopNode(SuccSU);
78}
79
80/// releaseSuccessors - Call releaseSucc on each of SU's successors.
81void VLIWMachineScheduler::releaseSuccessors(SUnit *SU) {
82  for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
83       I != E; ++I) {
84    releaseSucc(SU, &*I);
85  }
86}
87
88/// ReleasePred - Decrement the NumSuccsLeft count of a predecessor. When
89/// NumSuccsLeft reaches zero, release the predecessor node.
90///
91/// FIXME: Adjust PredSU height based on MinLatency.
92void VLIWMachineScheduler::releasePred(SUnit *SU, SDep *PredEdge) {
93  SUnit *PredSU = PredEdge->getSUnit();
94
95#ifndef NDEBUG
96  if (PredSU->NumSuccsLeft == 0) {
97    dbgs() << "*** Scheduling failed! ***\n";
98    PredSU->dump(this);
99    dbgs() << " has been released too many times!\n";
100    llvm_unreachable(0);
101  }
102#endif
103  --PredSU->NumSuccsLeft;
104  if (PredSU->NumSuccsLeft == 0 && PredSU != &EntrySU)
105    SchedImpl->releaseBottomNode(PredSU);
106}
107
108/// releasePredecessors - Call releasePred on each of SU's predecessors.
109void VLIWMachineScheduler::releasePredecessors(SUnit *SU) {
110  for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
111       I != E; ++I) {
112    releasePred(SU, &*I);
113  }
114}
115
116void VLIWMachineScheduler::moveInstruction(MachineInstr *MI,
117                                    MachineBasicBlock::iterator InsertPos) {
118  // Advance RegionBegin if the first instruction moves down.
119  if (&*RegionBegin == MI)
120    ++RegionBegin;
121
122  // Update the instruction stream.
123  BB->splice(InsertPos, BB, MI);
124
125  // Update LiveIntervals
126  LIS->handleMove(MI);
127
128  // Recede RegionBegin if an instruction moves above the first.
129  if (RegionBegin == InsertPos)
130    RegionBegin = MI;
131}
132
133bool VLIWMachineScheduler::checkSchedLimit() {
134#ifndef NDEBUG
135  if (NumInstrsScheduled == MISchedCutoff && MISchedCutoff != ~0U) {
136    CurrentTop = CurrentBottom;
137    return false;
138  }
139  ++NumInstrsScheduled;
140#endif
141  return true;
142}
143
144/// enterRegion - Called back from MachineScheduler::runOnMachineFunction after
145/// crossing a scheduling boundary. [begin, end) includes all instructions in
146/// the region, including the boundary itself and single-instruction regions
147/// that don't get scheduled.
148void VLIWMachineScheduler::enterRegion(MachineBasicBlock *bb,
149                                MachineBasicBlock::iterator begin,
150                                MachineBasicBlock::iterator end,
151                                unsigned endcount)
152{
153  ScheduleDAGInstrs::enterRegion(bb, begin, end, endcount);
154
155  // For convenience remember the end of the liveness region.
156  LiveRegionEnd =
157    (RegionEnd == bb->end()) ? RegionEnd : llvm::next(RegionEnd);
158}
159
160// Setup the register pressure trackers for the top scheduled top and bottom
161// scheduled regions.
162void VLIWMachineScheduler::initRegPressure() {
163  TopRPTracker.init(&MF, RegClassInfo, LIS, BB, RegionBegin);
164  BotRPTracker.init(&MF, RegClassInfo, LIS, BB, LiveRegionEnd);
165
166  // Close the RPTracker to finalize live ins.
167  RPTracker.closeRegion();
168
169  DEBUG(RPTracker.getPressure().dump(TRI));
170
171  // Initialize the live ins and live outs.
172  TopRPTracker.addLiveRegs(RPTracker.getPressure().LiveInRegs);
173  BotRPTracker.addLiveRegs(RPTracker.getPressure().LiveOutRegs);
174
175  // Close one end of the tracker so we can call
176  // getMaxUpward/DownwardPressureDelta before advancing across any
177  // instructions. This converts currently live regs into live ins/outs.
178  TopRPTracker.closeTop();
179  BotRPTracker.closeBottom();
180
181  // Account for liveness generated by the region boundary.
182  if (LiveRegionEnd != RegionEnd)
183    BotRPTracker.recede();
184
185  assert(BotRPTracker.getPos() == RegionEnd && "Can't find the region bottom");
186
187  // Cache the list of excess pressure sets in this region. This will also track
188  // the max pressure in the scheduled code for these sets.
189  RegionCriticalPSets.clear();
190  std::vector<unsigned> RegionPressure = RPTracker.getPressure().MaxSetPressure;
191  for (unsigned i = 0, e = RegionPressure.size(); i < e; ++i) {
192    unsigned Limit = TRI->getRegPressureSetLimit(i);
193    if (RegionPressure[i] > Limit)
194      RegionCriticalPSets.push_back(PressureElement(i, 0));
195  }
196  DEBUG(dbgs() << "Excess PSets: ";
197        for (unsigned i = 0, e = RegionCriticalPSets.size(); i != e; ++i)
198          dbgs() << TRI->getRegPressureSetName(
199            RegionCriticalPSets[i].PSetID) << " ";
200        dbgs() << "\n");
201
202  // Reset resource state.
203  TopResourceModel->resetPacketState();
204  TopResourceModel->resetDFA();
205  BotResourceModel->resetPacketState();
206  BotResourceModel->resetDFA();
207  TotalPackets = 0;
208}
209
210// FIXME: When the pressure tracker deals in pressure differences then we won't
211// iterate over all RegionCriticalPSets[i].
212void VLIWMachineScheduler::
213updateScheduledPressure(std::vector<unsigned> NewMaxPressure) {
214  for (unsigned i = 0, e = RegionCriticalPSets.size(); i < e; ++i) {
215    unsigned ID = RegionCriticalPSets[i].PSetID;
216    int &MaxUnits = RegionCriticalPSets[i].UnitIncrease;
217    if ((int)NewMaxPressure[ID] > MaxUnits)
218      MaxUnits = NewMaxPressure[ID];
219  }
220}
221
222/// Check if scheduling of this SU is possible
223/// in the current packet.
224/// It is _not_ precise (statefull), it is more like
225/// another heuristic. Many corner cases are figured
226/// empirically.
227bool VLIWResourceModel::isResourceAvailable(SUnit *SU) {
228  if (!SU || !SU->getInstr())
229    return false;
230
231  // First see if the pipeline could receive this instruction
232  // in the current cycle.
233  switch (SU->getInstr()->getOpcode()) {
234  default:
235    if (!ResourcesModel->canReserveResources(SU->getInstr()))
236      return false;
237  case TargetOpcode::EXTRACT_SUBREG:
238  case TargetOpcode::INSERT_SUBREG:
239  case TargetOpcode::SUBREG_TO_REG:
240  case TargetOpcode::REG_SEQUENCE:
241  case TargetOpcode::IMPLICIT_DEF:
242  case TargetOpcode::COPY:
243  case TargetOpcode::INLINEASM:
244    break;
245  }
246
247  // Now see if there are no other dependencies to instructions already
248  // in the packet.
249  for (unsigned i = 0, e = Packet.size(); i != e; ++i) {
250    if (Packet[i]->Succs.size() == 0)
251      continue;
252    for (SUnit::const_succ_iterator I = Packet[i]->Succs.begin(),
253         E = Packet[i]->Succs.end(); I != E; ++I) {
254      // Since we do not add pseudos to packets, might as well
255      // ignore order dependencies.
256      if (I->isCtrl())
257        continue;
258
259      if (I->getSUnit() == SU)
260        return false;
261    }
262  }
263  return true;
264}
265
266/// Keep track of available resources.
267void VLIWResourceModel::reserveResources(SUnit *SU) {
268  // If this SU does not fit in the packet
269  // start a new one.
270  if (!isResourceAvailable(SU)) {
271    ResourcesModel->clearResources();
272    Packet.clear();
273    TotalPackets++;
274  }
275
276  switch (SU->getInstr()->getOpcode()) {
277  default:
278    ResourcesModel->reserveResources(SU->getInstr());
279    break;
280  case TargetOpcode::EXTRACT_SUBREG:
281  case TargetOpcode::INSERT_SUBREG:
282  case TargetOpcode::SUBREG_TO_REG:
283  case TargetOpcode::REG_SEQUENCE:
284  case TargetOpcode::IMPLICIT_DEF:
285  case TargetOpcode::KILL:
286  case TargetOpcode::PROLOG_LABEL:
287  case TargetOpcode::EH_LABEL:
288  case TargetOpcode::COPY:
289  case TargetOpcode::INLINEASM:
290    break;
291  }
292  Packet.push_back(SU);
293
294#ifndef NDEBUG
295  DEBUG(dbgs() << "Packet[" << TotalPackets << "]:\n");
296  for (unsigned i = 0, e = Packet.size(); i != e; ++i) {
297    DEBUG(dbgs() << "\t[" << i << "] SU(");
298    DEBUG(dbgs() << Packet[i]->NodeNum << ")\n");
299  }
300#endif
301
302  // If packet is now full, reset the state so in the next cycle
303  // we start fresh.
304  if (Packet.size() >= InstrItins->SchedModel->IssueWidth) {
305    ResourcesModel->clearResources();
306    Packet.clear();
307    TotalPackets++;
308  }
309}
310
311// Release all DAG roots for scheduling.
312void VLIWMachineScheduler::releaseRoots() {
313  SmallVector<SUnit*, 16> BotRoots;
314
315  for (std::vector<SUnit>::iterator
316         I = SUnits.begin(), E = SUnits.end(); I != E; ++I) {
317    // A SUnit is ready to top schedule if it has no predecessors.
318    if (I->Preds.empty())
319      SchedImpl->releaseTopNode(&(*I));
320    // A SUnit is ready to bottom schedule if it has no successors.
321    if (I->Succs.empty())
322      BotRoots.push_back(&(*I));
323  }
324  // Release bottom roots in reverse order so the higher priority nodes appear
325  // first. This is more natural and slightly more efficient.
326  for (SmallVectorImpl<SUnit*>::const_reverse_iterator
327         I = BotRoots.rbegin(), E = BotRoots.rend(); I != E; ++I)
328    SchedImpl->releaseBottomNode(*I);
329}
330
331/// schedule - Called back from MachineScheduler::runOnMachineFunction
332/// after setting up the current scheduling region. [RegionBegin, RegionEnd)
333/// only includes instructions that have DAG nodes, not scheduling boundaries.
334void VLIWMachineScheduler::schedule() {
335  DEBUG(dbgs()
336        << "********** MI Converging Scheduling VLIW BB#" << BB->getNumber()
337        << " " << BB->getName()
338        << " in_func " << BB->getParent()->getFunction()->getName()
339        << " at loop depth "  << MLI->getLoopDepth(BB)
340        << " \n");
341
342  // Initialize the register pressure tracker used by buildSchedGraph.
343  RPTracker.init(&MF, RegClassInfo, LIS, BB, LiveRegionEnd);
344
345  // Account for liveness generate by the region boundary.
346  if (LiveRegionEnd != RegionEnd)
347    RPTracker.recede();
348
349  // Build the DAG, and compute current register pressure.
350  buildSchedGraph(AA, &RPTracker);
351
352  // Initialize top/bottom trackers after computing region pressure.
353  initRegPressure();
354
355  DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su)
356          SUnits[su].dumpAll(this));
357
358  if (ViewMISchedDAGs) viewGraph();
359
360  SchedImpl->initialize(this);
361
362  // Release edges from the special Entry node or to the special Exit node.
363  releaseSuccessors(&EntrySU);
364  releasePredecessors(&ExitSU);
365
366  // Release all DAG roots for scheduling.
367  releaseRoots();
368
369  CurrentTop = nextIfDebug(RegionBegin, RegionEnd);
370  CurrentBottom = RegionEnd;
371  bool IsTopNode = false;
372  while (SUnit *SU = SchedImpl->pickNode(IsTopNode)) {
373    if (!checkSchedLimit())
374      break;
375
376    // Move the instruction to its new location in the instruction stream.
377    MachineInstr *MI = SU->getInstr();
378
379    if (IsTopNode) {
380      assert(SU->isTopReady() && "node still has unscheduled dependencies");
381      if (&*CurrentTop == MI)
382        CurrentTop = nextIfDebug(++CurrentTop, CurrentBottom);
383      else {
384        moveInstruction(MI, CurrentTop);
385        TopRPTracker.setPos(MI);
386      }
387
388      // Update top scheduled pressure.
389      TopRPTracker.advance();
390      assert(TopRPTracker.getPos() == CurrentTop && "out of sync");
391      updateScheduledPressure(TopRPTracker.getPressure().MaxSetPressure);
392
393      // Update DFA state.
394      TopResourceModel->reserveResources(SU);
395
396      // Release dependent instructions for scheduling.
397      releaseSuccessors(SU);
398    }
399    else {
400      assert(SU->isBottomReady() && "node still has unscheduled dependencies");
401      MachineBasicBlock::iterator priorII =
402        priorNonDebug(CurrentBottom, CurrentTop);
403      if (&*priorII == MI)
404        CurrentBottom = priorII;
405      else {
406        if (&*CurrentTop == MI) {
407          CurrentTop = nextIfDebug(++CurrentTop, priorII);
408          TopRPTracker.setPos(CurrentTop);
409        }
410        moveInstruction(MI, CurrentBottom);
411        CurrentBottom = MI;
412      }
413      // Update bottom scheduled pressure.
414      BotRPTracker.recede();
415      assert(BotRPTracker.getPos() == CurrentBottom && "out of sync");
416      updateScheduledPressure(BotRPTracker.getPressure().MaxSetPressure);
417
418      // Update DFA state.
419      BotResourceModel->reserveResources(SU);
420
421      // Release dependent instructions for scheduling.
422      releasePredecessors(SU);
423    }
424    SU->isScheduled = true;
425    SchedImpl->schedNode(SU, IsTopNode);
426  }
427  assert(CurrentTop == CurrentBottom && "Nonempty unscheduled zone.");
428
429  DEBUG(dbgs() << "Final schedule has " << TopResourceModel->getTotalPackets() +
430        BotResourceModel->getTotalPackets()<< "packets.\n");
431
432  placeDebugValues();
433}
434
435/// Reinsert any remaining debug_values, just like the PostRA scheduler.
436void VLIWMachineScheduler::placeDebugValues() {
437  // If first instruction was a DBG_VALUE then put it back.
438  if (FirstDbgValue) {
439    BB->splice(RegionBegin, BB, FirstDbgValue);
440    RegionBegin = FirstDbgValue;
441  }
442
443  for (std::vector<std::pair<MachineInstr *, MachineInstr *> >::iterator
444         DI = DbgValues.end(), DE = DbgValues.begin(); DI != DE; --DI) {
445    std::pair<MachineInstr *, MachineInstr *> P = *prior(DI);
446    MachineInstr *DbgValue = P.first;
447    MachineBasicBlock::iterator OrigPrevMI = P.second;
448    BB->splice(++OrigPrevMI, BB, DbgValue);
449    if (OrigPrevMI == llvm::prior(RegionEnd))
450      RegionEnd = DbgValue;
451  }
452  DbgValues.clear();
453  FirstDbgValue = NULL;
454}
455
456void ConvergingVLIWScheduler::initialize(VLIWMachineScheduler *dag) {
457  DAG = dag;
458  TRI = DAG->TRI;
459  Top.DAG = dag;
460  Bot.DAG = dag;
461
462  // Initialize the HazardRecognizers.
463  const TargetMachine &TM = DAG->MF.getTarget();
464  const InstrItineraryData *Itin = TM.getInstrItineraryData();
465  Top.HazardRec = TM.getInstrInfo()->CreateTargetMIHazardRecognizer(Itin, DAG);
466  Bot.HazardRec = TM.getInstrInfo()->CreateTargetMIHazardRecognizer(Itin, DAG);
467
468  assert((!ForceTopDown || !ForceBottomUp) &&
469         "-misched-topdown incompatible with -misched-bottomup");
470}
471
472void ConvergingVLIWScheduler::releaseTopNode(SUnit *SU) {
473  if (SU->isScheduled)
474    return;
475
476  for (SUnit::succ_iterator I = SU->Preds.begin(), E = SU->Preds.end();
477       I != E; ++I) {
478    unsigned PredReadyCycle = I->getSUnit()->TopReadyCycle;
479    unsigned MinLatency = I->getMinLatency();
480#ifndef NDEBUG
481    Top.MaxMinLatency = std::max(MinLatency, Top.MaxMinLatency);
482#endif
483    if (SU->TopReadyCycle < PredReadyCycle + MinLatency)
484      SU->TopReadyCycle = PredReadyCycle + MinLatency;
485  }
486  Top.releaseNode(SU, SU->TopReadyCycle);
487}
488
489void ConvergingVLIWScheduler::releaseBottomNode(SUnit *SU) {
490  if (SU->isScheduled)
491    return;
492
493  assert(SU->getInstr() && "Scheduled SUnit must have instr");
494
495  for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
496       I != E; ++I) {
497    unsigned SuccReadyCycle = I->getSUnit()->BotReadyCycle;
498    unsigned MinLatency = I->getMinLatency();
499#ifndef NDEBUG
500    Bot.MaxMinLatency = std::max(MinLatency, Bot.MaxMinLatency);
501#endif
502    if (SU->BotReadyCycle < SuccReadyCycle + MinLatency)
503      SU->BotReadyCycle = SuccReadyCycle + MinLatency;
504  }
505  Bot.releaseNode(SU, SU->BotReadyCycle);
506}
507
508/// Does this SU have a hazard within the current instruction group.
509///
510/// The scheduler supports two modes of hazard recognition. The first is the
511/// ScheduleHazardRecognizer API. It is a fully general hazard recognizer that
512/// supports highly complicated in-order reservation tables
513/// (ScoreboardHazardRecognizer) and arbitrary target-specific logic.
514///
515/// The second is a streamlined mechanism that checks for hazards based on
516/// simple counters that the scheduler itself maintains. It explicitly checks
517/// for instruction dispatch limitations, including the number of micro-ops that
518/// can dispatch per cycle.
519///
520/// TODO: Also check whether the SU must start a new group.
521bool ConvergingVLIWScheduler::SchedBoundary::checkHazard(SUnit *SU) {
522  if (HazardRec->isEnabled())
523    return HazardRec->getHazardType(SU) != ScheduleHazardRecognizer::NoHazard;
524
525  if (IssueCount + DAG->getNumMicroOps(SU->getInstr()) > DAG->getIssueWidth())
526    return true;
527
528  return false;
529}
530
531void ConvergingVLIWScheduler::SchedBoundary::releaseNode(SUnit *SU,
532                                                     unsigned ReadyCycle) {
533  if (ReadyCycle < MinReadyCycle)
534    MinReadyCycle = ReadyCycle;
535
536  // Check for interlocks first. For the purpose of other heuristics, an
537  // instruction that cannot issue appears as if it's not in the ReadyQueue.
538  if (ReadyCycle > CurrCycle || checkHazard(SU))
539
540    Pending.push(SU);
541  else
542    Available.push(SU);
543}
544
545/// Move the boundary of scheduled code by one cycle.
546void ConvergingVLIWScheduler::SchedBoundary::bumpCycle() {
547  unsigned Width = DAG->getIssueWidth();
548  IssueCount = (IssueCount <= Width) ? 0 : IssueCount - Width;
549
550  assert(MinReadyCycle < UINT_MAX && "MinReadyCycle uninitialized");
551  unsigned NextCycle = std::max(CurrCycle + 1, MinReadyCycle);
552
553  if (!HazardRec->isEnabled()) {
554    // Bypass HazardRec virtual calls.
555    CurrCycle = NextCycle;
556  }
557  else {
558    // Bypass getHazardType calls in case of long latency.
559    for (; CurrCycle != NextCycle; ++CurrCycle) {
560      if (isTop())
561        HazardRec->AdvanceCycle();
562      else
563        HazardRec->RecedeCycle();
564    }
565  }
566  CheckPending = true;
567
568  DEBUG(dbgs() << "*** " << Available.getName() << " cycle "
569        << CurrCycle << '\n');
570}
571
572/// Move the boundary of scheduled code by one SUnit.
573void ConvergingVLIWScheduler::SchedBoundary::bumpNode(SUnit *SU) {
574
575  // Update the reservation table.
576  if (HazardRec->isEnabled()) {
577    if (!isTop() && SU->isCall) {
578      // Calls are scheduled with their preceding instructions. For bottom-up
579      // scheduling, clear the pipeline state before emitting.
580      HazardRec->Reset();
581    }
582    HazardRec->EmitInstruction(SU);
583  }
584  // Check the instruction group dispatch limit.
585  // TODO: Check if this SU must end a dispatch group.
586  IssueCount += DAG->getNumMicroOps(SU->getInstr());
587  if (IssueCount >= DAG->getIssueWidth()) {
588    DEBUG(dbgs() << "*** Max instrs at cycle " << CurrCycle << '\n');
589    bumpCycle();
590  }
591}
592
593/// Release pending ready nodes in to the available queue. This makes them
594/// visible to heuristics.
595void ConvergingVLIWScheduler::SchedBoundary::releasePending() {
596  // If the available queue is empty, it is safe to reset MinReadyCycle.
597  if (Available.empty())
598    MinReadyCycle = UINT_MAX;
599
600  // Check to see if any of the pending instructions are ready to issue.  If
601  // so, add them to the available queue.
602  for (unsigned i = 0, e = Pending.size(); i != e; ++i) {
603    SUnit *SU = *(Pending.begin()+i);
604    unsigned ReadyCycle = isTop() ? SU->TopReadyCycle : SU->BotReadyCycle;
605
606    if (ReadyCycle < MinReadyCycle)
607      MinReadyCycle = ReadyCycle;
608
609    if (ReadyCycle > CurrCycle)
610      continue;
611
612    if (checkHazard(SU))
613      continue;
614
615    Available.push(SU);
616    Pending.remove(Pending.begin()+i);
617    --i; --e;
618  }
619  CheckPending = false;
620}
621
622/// Remove SU from the ready set for this boundary.
623void ConvergingVLIWScheduler::SchedBoundary::removeReady(SUnit *SU) {
624  if (Available.isInQueue(SU))
625    Available.remove(Available.find(SU));
626  else {
627    assert(Pending.isInQueue(SU) && "bad ready count");
628    Pending.remove(Pending.find(SU));
629  }
630}
631
632/// If this queue only has one ready candidate, return it. As a side effect,
633/// advance the cycle until at least one node is ready. If multiple instructions
634/// are ready, return NULL.
635SUnit *ConvergingVLIWScheduler::SchedBoundary::pickOnlyChoice() {
636  if (CheckPending)
637    releasePending();
638
639  for (unsigned i = 0; Available.empty(); ++i) {
640    assert(i <= (HazardRec->getMaxLookAhead() + MaxMinLatency) &&
641           "permanent hazard"); (void)i;
642    bumpCycle();
643    releasePending();
644  }
645  if (Available.size() == 1)
646    return *Available.begin();
647  return NULL;
648}
649
650#ifndef NDEBUG
651void ConvergingVLIWScheduler::traceCandidate(const char *Label, const ReadyQueue &Q,
652                                         SUnit *SU, PressureElement P) {
653  dbgs() << Label << " " << Q.getName() << " ";
654  if (P.isValid())
655    dbgs() << TRI->getRegPressureSetName(P.PSetID) << ":" << P.UnitIncrease
656           << " ";
657  else
658    dbgs() << "     ";
659  SU->dump(DAG);
660}
661#endif
662
663// Constants used to denote relative importance of
664// heuristic components for cost computation.
665static const unsigned PriorityOne = 200;
666static const unsigned PriorityThree = 50;
667static const unsigned ScaleTwo = 10;
668static const unsigned FactorOne = 2;
669
670/// Single point to compute overall scheduling cost.
671/// TODO: More heuristics will be used soon.
672int ConvergingVLIWScheduler::SchedulingCost(ReadyQueue &Q, SUnit *SU,
673                                            SchedCandidate &Candidate,
674                                            RegPressureDelta &Delta,
675                                            bool verbose) {
676  // Initial trivial priority.
677  int ResCount = 1;
678
679  // Do not waste time on a node that is already scheduled.
680  if (!SU || SU->isScheduled)
681    return ResCount;
682
683  // Forced priority is high.
684  if (SU->isScheduleHigh)
685    ResCount += PriorityOne;
686
687  // Critical path first.
688  if (Q.getID() == TopQID)
689    ResCount += (SU->getHeight() * ScaleTwo);
690  else
691    ResCount += (SU->getDepth() * ScaleTwo);
692
693  // If resources are available for it, multiply the
694  // chance of scheduling.
695  if (DAG->getTopResourceModel()->isResourceAvailable(SU))
696    ResCount <<= FactorOne;
697
698  // Factor in reg pressure as a heuristic.
699  ResCount -= (Delta.Excess.UnitIncrease * PriorityThree);
700  ResCount -= (Delta.CriticalMax.UnitIncrease * PriorityThree);
701
702  DEBUG(if (verbose) dbgs() << " Total(" << ResCount << ")");
703
704  return ResCount;
705}
706
707/// Pick the best candidate from the top queue.
708///
709/// TODO: getMaxPressureDelta results can be mostly cached for each SUnit during
710/// DAG building. To adjust for the current scheduling location we need to
711/// maintain the number of vreg uses remaining to be top-scheduled.
712ConvergingVLIWScheduler::CandResult ConvergingVLIWScheduler::
713pickNodeFromQueue(ReadyQueue &Q, const RegPressureTracker &RPTracker,
714                  SchedCandidate &Candidate) {
715  DEBUG(Q.dump());
716
717  // getMaxPressureDelta temporarily modifies the tracker.
718  RegPressureTracker &TempTracker = const_cast<RegPressureTracker&>(RPTracker);
719
720  // BestSU remains NULL if no top candidates beat the best existing candidate.
721  CandResult FoundCandidate = NoCand;
722  for (ReadyQueue::iterator I = Q.begin(), E = Q.end(); I != E; ++I) {
723    RegPressureDelta RPDelta;
724    TempTracker.getMaxPressureDelta((*I)->getInstr(), RPDelta,
725                                    DAG->getRegionCriticalPSets(),
726                                    DAG->getRegPressure().MaxSetPressure);
727
728    int CurrentCost = SchedulingCost(Q, *I, Candidate, RPDelta, false);
729
730    // Initialize the candidate if needed.
731    if (!Candidate.SU) {
732      Candidate.SU = *I;
733      Candidate.RPDelta = RPDelta;
734      Candidate.SCost = CurrentCost;
735      FoundCandidate = NodeOrder;
736      continue;
737    }
738
739
740    // Best cost.
741    if (CurrentCost > Candidate.SCost) {
742      DEBUG(traceCandidate("CCAND", Q, *I));
743      Candidate.SU = *I;
744      Candidate.RPDelta = RPDelta;
745      Candidate.SCost = CurrentCost;
746      FoundCandidate = BestCost;
747      continue;
748    }
749
750    // Fall through to original instruction order.
751    // Only consider node order if Candidate was chosen from this Q.
752    if (FoundCandidate == NoCand)
753      continue;
754  }
755  return FoundCandidate;
756}
757
758/// Pick the best candidate node from either the top or bottom queue.
759SUnit *ConvergingVLIWScheduler::pickNodeBidrectional(bool &IsTopNode) {
760  // Schedule as far as possible in the direction of no choice. This is most
761  // efficient, but also provides the best heuristics for CriticalPSets.
762  if (SUnit *SU = Bot.pickOnlyChoice()) {
763    IsTopNode = false;
764    return SU;
765  }
766  if (SUnit *SU = Top.pickOnlyChoice()) {
767    IsTopNode = true;
768    return SU;
769  }
770  SchedCandidate BotCand;
771  // Prefer bottom scheduling when heuristics are silent.
772  CandResult BotResult = pickNodeFromQueue(Bot.Available,
773                                           DAG->getBotRPTracker(), BotCand);
774  assert(BotResult != NoCand && "failed to find the first candidate");
775
776  // If either Q has a single candidate that provides the least increase in
777  // Excess pressure, we can immediately schedule from that Q.
778  //
779  // RegionCriticalPSets summarizes the pressure within the scheduled region and
780  // affects picking from either Q. If scheduling in one direction must
781  // increase pressure for one of the excess PSets, then schedule in that
782  // direction first to provide more freedom in the other direction.
783  if (BotResult == SingleExcess || BotResult == SingleCritical) {
784    IsTopNode = false;
785    return BotCand.SU;
786  }
787  // Check if the top Q has a better candidate.
788  SchedCandidate TopCand;
789  CandResult TopResult = pickNodeFromQueue(Top.Available,
790                                           DAG->getTopRPTracker(), TopCand);
791  assert(TopResult != NoCand && "failed to find the first candidate");
792
793  if (TopResult == SingleExcess || TopResult == SingleCritical) {
794    IsTopNode = true;
795    return TopCand.SU;
796  }
797  // If either Q has a single candidate that minimizes pressure above the
798  // original region's pressure pick it.
799  if (BotResult == SingleMax) {
800    IsTopNode = false;
801    return BotCand.SU;
802  }
803  if (TopResult == SingleMax) {
804    IsTopNode = true;
805    return TopCand.SU;
806  }
807  if (TopCand.SCost > BotCand.SCost) {
808    IsTopNode = true;
809    return TopCand.SU;
810  }
811  // Otherwise prefer the bottom candidate in node order.
812  IsTopNode = false;
813  return BotCand.SU;
814}
815
816/// Pick the best node to balance the schedule. Implements MachineSchedStrategy.
817SUnit *ConvergingVLIWScheduler::pickNode(bool &IsTopNode) {
818  if (DAG->top() == DAG->bottom()) {
819    assert(Top.Available.empty() && Top.Pending.empty() &&
820           Bot.Available.empty() && Bot.Pending.empty() && "ReadyQ garbage");
821    return NULL;
822  }
823  SUnit *SU;
824  if (ForceTopDown) {
825    SU = Top.pickOnlyChoice();
826    if (!SU) {
827      SchedCandidate TopCand;
828      CandResult TopResult =
829        pickNodeFromQueue(Top.Available, DAG->getTopRPTracker(), TopCand);
830      assert(TopResult != NoCand && "failed to find the first candidate");
831      (void)TopResult;
832      SU = TopCand.SU;
833    }
834    IsTopNode = true;
835  } else if (ForceBottomUp) {
836    SU = Bot.pickOnlyChoice();
837    if (!SU) {
838      SchedCandidate BotCand;
839      CandResult BotResult =
840        pickNodeFromQueue(Bot.Available, DAG->getBotRPTracker(), BotCand);
841      assert(BotResult != NoCand && "failed to find the first candidate");
842      (void)BotResult;
843      SU = BotCand.SU;
844    }
845    IsTopNode = false;
846  } else {
847    SU = pickNodeBidrectional(IsTopNode);
848  }
849  if (SU->isTopReady())
850    Top.removeReady(SU);
851  if (SU->isBottomReady())
852    Bot.removeReady(SU);
853
854  DEBUG(dbgs() << "*** " << (IsTopNode ? "Top" : "Bottom")
855        << " Scheduling Instruction in cycle "
856        << (IsTopNode ? Top.CurrCycle : Bot.CurrCycle) << '\n';
857        SU->dump(DAG));
858  return SU;
859}
860
861/// Update the scheduler's state after scheduling a node. This is the same node
862/// that was just returned by pickNode(). However, VLIWMachineScheduler needs to update
863/// it's state based on the current cycle before MachineSchedStrategy does.
864void ConvergingVLIWScheduler::schedNode(SUnit *SU, bool IsTopNode) {
865  if (IsTopNode) {
866    SU->TopReadyCycle = Top.CurrCycle;
867    Top.bumpNode(SU);
868  }
869  else {
870    SU->BotReadyCycle = Bot.CurrCycle;
871    Bot.bumpNode(SU);
872  }
873}
874
875