xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/VLIWMachineScheduler.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10eae32dcSDimitry Andric //===- VLIWMachineScheduler.cpp - VLIW-Focused Scheduling Pass ------------===//
20eae32dcSDimitry Andric //
30eae32dcSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40eae32dcSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50eae32dcSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60eae32dcSDimitry Andric //
70eae32dcSDimitry Andric //===----------------------------------------------------------------------===//
80eae32dcSDimitry Andric //
90eae32dcSDimitry Andric // MachineScheduler schedules machine instructions after phi elimination. It
100eae32dcSDimitry Andric // preserves LiveIntervals so it can be invoked before register allocation.
110eae32dcSDimitry Andric //
120eae32dcSDimitry Andric //===----------------------------------------------------------------------===//
130eae32dcSDimitry Andric 
140eae32dcSDimitry Andric #include "llvm/CodeGen/VLIWMachineScheduler.h"
150eae32dcSDimitry Andric #include "llvm/ADT/SmallVector.h"
160eae32dcSDimitry Andric #include "llvm/CodeGen/DFAPacketizer.h"
170eae32dcSDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
180eae32dcSDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
190eae32dcSDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
200eae32dcSDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h"
210eae32dcSDimitry Andric #include "llvm/CodeGen/RegisterClassInfo.h"
220eae32dcSDimitry Andric #include "llvm/CodeGen/RegisterPressure.h"
230eae32dcSDimitry Andric #include "llvm/CodeGen/ScheduleDAG.h"
240eae32dcSDimitry Andric #include "llvm/CodeGen/ScheduleHazardRecognizer.h"
250eae32dcSDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
260eae32dcSDimitry Andric #include "llvm/CodeGen/TargetOpcodes.h"
270eae32dcSDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
280eae32dcSDimitry Andric #include "llvm/CodeGen/TargetSchedule.h"
290eae32dcSDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
300eae32dcSDimitry Andric #include "llvm/Support/CommandLine.h"
310eae32dcSDimitry Andric #include "llvm/Support/Debug.h"
320eae32dcSDimitry Andric #include "llvm/Support/raw_ostream.h"
330eae32dcSDimitry Andric #include <algorithm>
340eae32dcSDimitry Andric #include <cassert>
350eae32dcSDimitry Andric #include <iomanip>
360eae32dcSDimitry Andric #include <limits>
370eae32dcSDimitry Andric #include <memory>
380eae32dcSDimitry Andric #include <sstream>
390eae32dcSDimitry Andric 
400eae32dcSDimitry Andric using namespace llvm;
410eae32dcSDimitry Andric 
420eae32dcSDimitry Andric #define DEBUG_TYPE "machine-scheduler"
430eae32dcSDimitry Andric 
440eae32dcSDimitry Andric static cl::opt<bool> IgnoreBBRegPressure("ignore-bb-reg-pressure", cl::Hidden,
4581ad6265SDimitry Andric                                          cl::init(false));
460eae32dcSDimitry Andric 
470eae32dcSDimitry Andric static cl::opt<bool> UseNewerCandidate("use-newer-candidate", cl::Hidden,
4881ad6265SDimitry Andric                                        cl::init(true));
490eae32dcSDimitry Andric 
500eae32dcSDimitry Andric static cl::opt<unsigned> SchedDebugVerboseLevel("misched-verbose-level",
5181ad6265SDimitry Andric                                                 cl::Hidden, cl::init(1));
520eae32dcSDimitry Andric 
530eae32dcSDimitry Andric // Check if the scheduler should penalize instructions that are available to
540eae32dcSDimitry Andric // early due to a zero-latency dependence.
550eae32dcSDimitry Andric static cl::opt<bool> CheckEarlyAvail("check-early-avail", cl::Hidden,
5681ad6265SDimitry Andric                                      cl::init(true));
570eae32dcSDimitry Andric 
580eae32dcSDimitry Andric // This value is used to determine if a register class is a high pressure set.
590eae32dcSDimitry Andric // We compute the maximum number of registers needed and divided by the total
600eae32dcSDimitry Andric // available. Then, we compare the result to this value.
610eae32dcSDimitry Andric static cl::opt<float> RPThreshold("vliw-misched-reg-pressure", cl::Hidden,
620eae32dcSDimitry Andric                                   cl::init(0.75f),
630eae32dcSDimitry Andric                                   cl::desc("High register pressure threhold."));
640eae32dcSDimitry Andric 
650eae32dcSDimitry Andric VLIWResourceModel::VLIWResourceModel(const TargetSubtargetInfo &STI,
660eae32dcSDimitry Andric                                      const TargetSchedModel *SM)
670eae32dcSDimitry Andric     : TII(STI.getInstrInfo()), SchedModel(SM) {
680eae32dcSDimitry Andric   ResourcesModel = createPacketizer(STI);
690eae32dcSDimitry Andric 
700eae32dcSDimitry Andric   // This hard requirement could be relaxed,
710eae32dcSDimitry Andric   // but for now do not let it proceed.
720eae32dcSDimitry Andric   assert(ResourcesModel && "Unimplemented CreateTargetScheduleState.");
730eae32dcSDimitry Andric 
740eae32dcSDimitry Andric   Packet.reserve(SchedModel->getIssueWidth());
750eae32dcSDimitry Andric   Packet.clear();
760eae32dcSDimitry Andric   ResourcesModel->clearResources();
770eae32dcSDimitry Andric }
780eae32dcSDimitry Andric 
790eae32dcSDimitry Andric void VLIWResourceModel::reset() {
800eae32dcSDimitry Andric   Packet.clear();
810eae32dcSDimitry Andric   ResourcesModel->clearResources();
820eae32dcSDimitry Andric }
830eae32dcSDimitry Andric 
840eae32dcSDimitry Andric VLIWResourceModel::~VLIWResourceModel() { delete ResourcesModel; }
850eae32dcSDimitry Andric 
860eae32dcSDimitry Andric /// Return true if there is a dependence between SUd and SUu.
870eae32dcSDimitry Andric bool VLIWResourceModel::hasDependence(const SUnit *SUd, const SUnit *SUu) {
880eae32dcSDimitry Andric   if (SUd->Succs.size() == 0)
890eae32dcSDimitry Andric     return false;
900eae32dcSDimitry Andric 
910eae32dcSDimitry Andric   for (const auto &S : SUd->Succs) {
920eae32dcSDimitry Andric     // Since we do not add pseudos to packets, might as well
930eae32dcSDimitry Andric     // ignore order dependencies.
940eae32dcSDimitry Andric     if (S.isCtrl())
950eae32dcSDimitry Andric       continue;
960eae32dcSDimitry Andric 
970eae32dcSDimitry Andric     if (S.getSUnit() == SUu && S.getLatency() > 0)
980eae32dcSDimitry Andric       return true;
990eae32dcSDimitry Andric   }
1000eae32dcSDimitry Andric   return false;
1010eae32dcSDimitry Andric }
1020eae32dcSDimitry Andric 
1030eae32dcSDimitry Andric /// Check if scheduling of this SU is possible
1040eae32dcSDimitry Andric /// in the current packet.
1050eae32dcSDimitry Andric /// It is _not_ precise (statefull), it is more like
1060eae32dcSDimitry Andric /// another heuristic. Many corner cases are figured
1070eae32dcSDimitry Andric /// empirically.
1080eae32dcSDimitry Andric bool VLIWResourceModel::isResourceAvailable(SUnit *SU, bool IsTop) {
1090eae32dcSDimitry Andric   if (!SU || !SU->getInstr())
1100eae32dcSDimitry Andric     return false;
1110eae32dcSDimitry Andric 
1120eae32dcSDimitry Andric   // First see if the pipeline could receive this instruction
1130eae32dcSDimitry Andric   // in the current cycle.
1140eae32dcSDimitry Andric   switch (SU->getInstr()->getOpcode()) {
1150eae32dcSDimitry Andric   default:
1160eae32dcSDimitry Andric     if (!ResourcesModel->canReserveResources(*SU->getInstr()))
1170eae32dcSDimitry Andric       return false;
1180eae32dcSDimitry Andric     break;
1190eae32dcSDimitry Andric   case TargetOpcode::EXTRACT_SUBREG:
1200eae32dcSDimitry Andric   case TargetOpcode::INSERT_SUBREG:
1210eae32dcSDimitry Andric   case TargetOpcode::SUBREG_TO_REG:
1220eae32dcSDimitry Andric   case TargetOpcode::REG_SEQUENCE:
1230eae32dcSDimitry Andric   case TargetOpcode::IMPLICIT_DEF:
1240eae32dcSDimitry Andric   case TargetOpcode::COPY:
1250eae32dcSDimitry Andric   case TargetOpcode::INLINEASM:
1260eae32dcSDimitry Andric   case TargetOpcode::INLINEASM_BR:
1270eae32dcSDimitry Andric     break;
1280eae32dcSDimitry Andric   }
1290eae32dcSDimitry Andric 
1300eae32dcSDimitry Andric   // Now see if there are no other dependencies to instructions already
1310eae32dcSDimitry Andric   // in the packet.
1320eae32dcSDimitry Andric   if (IsTop) {
133*0fca6ea1SDimitry Andric     for (const SUnit *U : Packet)
134*0fca6ea1SDimitry Andric       if (hasDependence(U, SU))
1350eae32dcSDimitry Andric         return false;
1360eae32dcSDimitry Andric   } else {
137*0fca6ea1SDimitry Andric     for (const SUnit *U : Packet)
138*0fca6ea1SDimitry Andric       if (hasDependence(SU, U))
1390eae32dcSDimitry Andric         return false;
1400eae32dcSDimitry Andric   }
1410eae32dcSDimitry Andric   return true;
1420eae32dcSDimitry Andric }
1430eae32dcSDimitry Andric 
1440eae32dcSDimitry Andric /// Keep track of available resources.
1450eae32dcSDimitry Andric bool VLIWResourceModel::reserveResources(SUnit *SU, bool IsTop) {
1460eae32dcSDimitry Andric   bool startNewCycle = false;
1470eae32dcSDimitry Andric   // Artificially reset state.
1480eae32dcSDimitry Andric   if (!SU) {
1490eae32dcSDimitry Andric     reset();
1500eae32dcSDimitry Andric     TotalPackets++;
1510eae32dcSDimitry Andric     return false;
1520eae32dcSDimitry Andric   }
1530eae32dcSDimitry Andric   // If this SU does not fit in the packet or the packet is now full
1540eae32dcSDimitry Andric   // start a new one.
1550eae32dcSDimitry Andric   if (!isResourceAvailable(SU, IsTop) ||
1560eae32dcSDimitry Andric       Packet.size() >= SchedModel->getIssueWidth()) {
1570eae32dcSDimitry Andric     reset();
1580eae32dcSDimitry Andric     TotalPackets++;
1590eae32dcSDimitry Andric     startNewCycle = true;
1600eae32dcSDimitry Andric   }
1610eae32dcSDimitry Andric 
1620eae32dcSDimitry Andric   switch (SU->getInstr()->getOpcode()) {
1630eae32dcSDimitry Andric   default:
1640eae32dcSDimitry Andric     ResourcesModel->reserveResources(*SU->getInstr());
1650eae32dcSDimitry Andric     break;
1660eae32dcSDimitry Andric   case TargetOpcode::EXTRACT_SUBREG:
1670eae32dcSDimitry Andric   case TargetOpcode::INSERT_SUBREG:
1680eae32dcSDimitry Andric   case TargetOpcode::SUBREG_TO_REG:
1690eae32dcSDimitry Andric   case TargetOpcode::REG_SEQUENCE:
1700eae32dcSDimitry Andric   case TargetOpcode::IMPLICIT_DEF:
1710eae32dcSDimitry Andric   case TargetOpcode::KILL:
1720eae32dcSDimitry Andric   case TargetOpcode::CFI_INSTRUCTION:
1730eae32dcSDimitry Andric   case TargetOpcode::EH_LABEL:
1740eae32dcSDimitry Andric   case TargetOpcode::COPY:
1750eae32dcSDimitry Andric   case TargetOpcode::INLINEASM:
1760eae32dcSDimitry Andric   case TargetOpcode::INLINEASM_BR:
1770eae32dcSDimitry Andric     break;
1780eae32dcSDimitry Andric   }
1790eae32dcSDimitry Andric   Packet.push_back(SU);
1800eae32dcSDimitry Andric 
1810eae32dcSDimitry Andric #ifndef NDEBUG
1820eae32dcSDimitry Andric   LLVM_DEBUG(dbgs() << "Packet[" << TotalPackets << "]:\n");
1830eae32dcSDimitry Andric   for (unsigned i = 0, e = Packet.size(); i != e; ++i) {
1840eae32dcSDimitry Andric     LLVM_DEBUG(dbgs() << "\t[" << i << "] SU(");
1850eae32dcSDimitry Andric     LLVM_DEBUG(dbgs() << Packet[i]->NodeNum << ")\t");
1860eae32dcSDimitry Andric     LLVM_DEBUG(Packet[i]->getInstr()->dump());
1870eae32dcSDimitry Andric   }
1880eae32dcSDimitry Andric #endif
1890eae32dcSDimitry Andric 
1900eae32dcSDimitry Andric   return startNewCycle;
1910eae32dcSDimitry Andric }
1920eae32dcSDimitry Andric 
1930eae32dcSDimitry Andric DFAPacketizer *
1940eae32dcSDimitry Andric VLIWResourceModel::createPacketizer(const TargetSubtargetInfo &STI) const {
1950eae32dcSDimitry Andric   return STI.getInstrInfo()->CreateTargetScheduleState(STI);
1960eae32dcSDimitry Andric }
1970eae32dcSDimitry Andric 
1980eae32dcSDimitry Andric /// schedule - Called back from MachineScheduler::runOnMachineFunction
1990eae32dcSDimitry Andric /// after setting up the current scheduling region. [RegionBegin, RegionEnd)
2000eae32dcSDimitry Andric /// only includes instructions that have DAG nodes, not scheduling boundaries.
2010eae32dcSDimitry Andric void VLIWMachineScheduler::schedule() {
2020eae32dcSDimitry Andric   LLVM_DEBUG(dbgs() << "********** MI Converging Scheduling VLIW "
2030eae32dcSDimitry Andric                     << printMBBReference(*BB) << " " << BB->getName()
2040eae32dcSDimitry Andric                     << " in_func " << BB->getParent()->getName()
2050eae32dcSDimitry Andric                     << " at loop depth " << MLI->getLoopDepth(BB) << " \n");
2060eae32dcSDimitry Andric 
2070eae32dcSDimitry Andric   buildDAGWithRegPressure();
2080eae32dcSDimitry Andric 
2090eae32dcSDimitry Andric   Topo.InitDAGTopologicalSorting();
2100eae32dcSDimitry Andric 
2110eae32dcSDimitry Andric   // Postprocess the DAG to add platform-specific artificial dependencies.
21206c3fb27SDimitry Andric   postProcessDAG();
2130eae32dcSDimitry Andric 
2140eae32dcSDimitry Andric   SmallVector<SUnit *, 8> TopRoots, BotRoots;
2150eae32dcSDimitry Andric   findRootsAndBiasEdges(TopRoots, BotRoots);
2160eae32dcSDimitry Andric 
2170eae32dcSDimitry Andric   // Initialize the strategy before modifying the DAG.
2180eae32dcSDimitry Andric   SchedImpl->initialize(this);
2190eae32dcSDimitry Andric 
2200eae32dcSDimitry Andric   LLVM_DEBUG({
2210eae32dcSDimitry Andric     unsigned maxH = 0;
2220eae32dcSDimitry Andric     for (const SUnit &SU : SUnits)
2230eae32dcSDimitry Andric       if (SU.getHeight() > maxH)
2240eae32dcSDimitry Andric         maxH = SU.getHeight();
2250eae32dcSDimitry Andric     dbgs() << "Max Height " << maxH << "\n";
2260eae32dcSDimitry Andric   });
2270eae32dcSDimitry Andric   LLVM_DEBUG({
2280eae32dcSDimitry Andric     unsigned maxD = 0;
2290eae32dcSDimitry Andric     for (const SUnit &SU : SUnits)
2300eae32dcSDimitry Andric       if (SU.getDepth() > maxD)
2310eae32dcSDimitry Andric         maxD = SU.getDepth();
2320eae32dcSDimitry Andric     dbgs() << "Max Depth " << maxD << "\n";
2330eae32dcSDimitry Andric   });
2340eae32dcSDimitry Andric   LLVM_DEBUG(dump());
2350eae32dcSDimitry Andric   if (ViewMISchedDAGs)
2360eae32dcSDimitry Andric     viewGraph();
2370eae32dcSDimitry Andric 
2380eae32dcSDimitry Andric   initQueues(TopRoots, BotRoots);
2390eae32dcSDimitry Andric 
2400eae32dcSDimitry Andric   bool IsTopNode = false;
2410eae32dcSDimitry Andric   while (true) {
2420eae32dcSDimitry Andric     LLVM_DEBUG(
2430eae32dcSDimitry Andric         dbgs() << "** VLIWMachineScheduler::schedule picking next node\n");
2440eae32dcSDimitry Andric     SUnit *SU = SchedImpl->pickNode(IsTopNode);
2450eae32dcSDimitry Andric     if (!SU)
2460eae32dcSDimitry Andric       break;
2470eae32dcSDimitry Andric 
2480eae32dcSDimitry Andric     if (!checkSchedLimit())
2490eae32dcSDimitry Andric       break;
2500eae32dcSDimitry Andric 
2510eae32dcSDimitry Andric     scheduleMI(SU, IsTopNode);
2520eae32dcSDimitry Andric 
2530eae32dcSDimitry Andric     // Notify the scheduling strategy after updating the DAG.
2540eae32dcSDimitry Andric     SchedImpl->schedNode(SU, IsTopNode);
2550eae32dcSDimitry Andric 
2560eae32dcSDimitry Andric     updateQueues(SU, IsTopNode);
2570eae32dcSDimitry Andric   }
2580eae32dcSDimitry Andric   assert(CurrentTop == CurrentBottom && "Nonempty unscheduled zone.");
2590eae32dcSDimitry Andric 
2600eae32dcSDimitry Andric   placeDebugValues();
2610eae32dcSDimitry Andric 
2620eae32dcSDimitry Andric   LLVM_DEBUG({
2630eae32dcSDimitry Andric     dbgs() << "*** Final schedule for "
2640eae32dcSDimitry Andric            << printMBBReference(*begin()->getParent()) << " ***\n";
2650eae32dcSDimitry Andric     dumpSchedule();
2660eae32dcSDimitry Andric     dbgs() << '\n';
2670eae32dcSDimitry Andric   });
2680eae32dcSDimitry Andric }
2690eae32dcSDimitry Andric 
2700eae32dcSDimitry Andric void ConvergingVLIWScheduler::initialize(ScheduleDAGMI *dag) {
2710eae32dcSDimitry Andric   DAG = static_cast<VLIWMachineScheduler *>(dag);
2720eae32dcSDimitry Andric   SchedModel = DAG->getSchedModel();
2730eae32dcSDimitry Andric 
2740eae32dcSDimitry Andric   Top.init(DAG, SchedModel);
2750eae32dcSDimitry Andric   Bot.init(DAG, SchedModel);
2760eae32dcSDimitry Andric 
2770eae32dcSDimitry Andric   // Initialize the HazardRecognizers. If itineraries don't exist, are empty, or
2780eae32dcSDimitry Andric   // are disabled, then these HazardRecs will be disabled.
2790eae32dcSDimitry Andric   const InstrItineraryData *Itin = DAG->getSchedModel()->getInstrItineraries();
2800eae32dcSDimitry Andric   const TargetSubtargetInfo &STI = DAG->MF.getSubtarget();
2810eae32dcSDimitry Andric   const TargetInstrInfo *TII = STI.getInstrInfo();
2820eae32dcSDimitry Andric   delete Top.HazardRec;
2830eae32dcSDimitry Andric   delete Bot.HazardRec;
2840eae32dcSDimitry Andric   Top.HazardRec = TII->CreateTargetMIHazardRecognizer(Itin, DAG);
2850eae32dcSDimitry Andric   Bot.HazardRec = TII->CreateTargetMIHazardRecognizer(Itin, DAG);
2860eae32dcSDimitry Andric 
2870eae32dcSDimitry Andric   delete Top.ResourceModel;
2880eae32dcSDimitry Andric   delete Bot.ResourceModel;
2890eae32dcSDimitry Andric   Top.ResourceModel = createVLIWResourceModel(STI, DAG->getSchedModel());
2900eae32dcSDimitry Andric   Bot.ResourceModel = createVLIWResourceModel(STI, DAG->getSchedModel());
2910eae32dcSDimitry Andric 
2920eae32dcSDimitry Andric   const std::vector<unsigned> &MaxPressure =
2930eae32dcSDimitry Andric       DAG->getRegPressure().MaxSetPressure;
29404eeddc0SDimitry Andric   HighPressureSets.assign(MaxPressure.size(), false);
2950eae32dcSDimitry Andric   for (unsigned i = 0, e = MaxPressure.size(); i < e; ++i) {
2960eae32dcSDimitry Andric     unsigned Limit = DAG->getRegClassInfo()->getRegPressureSetLimit(i);
2970eae32dcSDimitry Andric     HighPressureSets[i] =
2980eae32dcSDimitry Andric         ((float)MaxPressure[i] > ((float)Limit * RPThreshold));
2990eae32dcSDimitry Andric   }
3000eae32dcSDimitry Andric 
3010eae32dcSDimitry Andric   assert((!ForceTopDown || !ForceBottomUp) &&
3020eae32dcSDimitry Andric          "-misched-topdown incompatible with -misched-bottomup");
3030eae32dcSDimitry Andric }
3040eae32dcSDimitry Andric 
3050eae32dcSDimitry Andric VLIWResourceModel *ConvergingVLIWScheduler::createVLIWResourceModel(
3060eae32dcSDimitry Andric     const TargetSubtargetInfo &STI, const TargetSchedModel *SchedModel) const {
3070eae32dcSDimitry Andric   return new VLIWResourceModel(STI, SchedModel);
3080eae32dcSDimitry Andric }
3090eae32dcSDimitry Andric 
3100eae32dcSDimitry Andric void ConvergingVLIWScheduler::releaseTopNode(SUnit *SU) {
3110eae32dcSDimitry Andric   for (const SDep &PI : SU->Preds) {
3120eae32dcSDimitry Andric     unsigned PredReadyCycle = PI.getSUnit()->TopReadyCycle;
3130eae32dcSDimitry Andric     unsigned MinLatency = PI.getLatency();
3140eae32dcSDimitry Andric #ifndef NDEBUG
3150eae32dcSDimitry Andric     Top.MaxMinLatency = std::max(MinLatency, Top.MaxMinLatency);
3160eae32dcSDimitry Andric #endif
3170eae32dcSDimitry Andric     if (SU->TopReadyCycle < PredReadyCycle + MinLatency)
3180eae32dcSDimitry Andric       SU->TopReadyCycle = PredReadyCycle + MinLatency;
3190eae32dcSDimitry Andric   }
3200eae32dcSDimitry Andric 
3210eae32dcSDimitry Andric   if (!SU->isScheduled)
3220eae32dcSDimitry Andric     Top.releaseNode(SU, SU->TopReadyCycle);
3230eae32dcSDimitry Andric }
3240eae32dcSDimitry Andric 
3250eae32dcSDimitry Andric void ConvergingVLIWScheduler::releaseBottomNode(SUnit *SU) {
3260eae32dcSDimitry Andric   assert(SU->getInstr() && "Scheduled SUnit must have instr");
3270eae32dcSDimitry Andric 
3280eae32dcSDimitry Andric   for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end(); I != E;
3290eae32dcSDimitry Andric        ++I) {
3300eae32dcSDimitry Andric     unsigned SuccReadyCycle = I->getSUnit()->BotReadyCycle;
3310eae32dcSDimitry Andric     unsigned MinLatency = I->getLatency();
3320eae32dcSDimitry Andric #ifndef NDEBUG
3330eae32dcSDimitry Andric     Bot.MaxMinLatency = std::max(MinLatency, Bot.MaxMinLatency);
3340eae32dcSDimitry Andric #endif
3350eae32dcSDimitry Andric     if (SU->BotReadyCycle < SuccReadyCycle + MinLatency)
3360eae32dcSDimitry Andric       SU->BotReadyCycle = SuccReadyCycle + MinLatency;
3370eae32dcSDimitry Andric   }
3380eae32dcSDimitry Andric 
3390eae32dcSDimitry Andric   if (!SU->isScheduled)
3400eae32dcSDimitry Andric     Bot.releaseNode(SU, SU->BotReadyCycle);
3410eae32dcSDimitry Andric }
3420eae32dcSDimitry Andric 
3430eae32dcSDimitry Andric ConvergingVLIWScheduler::VLIWSchedBoundary::~VLIWSchedBoundary() {
3440eae32dcSDimitry Andric   delete ResourceModel;
3450eae32dcSDimitry Andric   delete HazardRec;
3460eae32dcSDimitry Andric }
3470eae32dcSDimitry Andric 
3480eae32dcSDimitry Andric /// Does this SU have a hazard within the current instruction group.
3490eae32dcSDimitry Andric ///
3500eae32dcSDimitry Andric /// The scheduler supports two modes of hazard recognition. The first is the
3510eae32dcSDimitry Andric /// ScheduleHazardRecognizer API. It is a fully general hazard recognizer that
3520eae32dcSDimitry Andric /// supports highly complicated in-order reservation tables
3530eae32dcSDimitry Andric /// (ScoreboardHazardRecognizer) and arbitrary target-specific logic.
3540eae32dcSDimitry Andric ///
3550eae32dcSDimitry Andric /// The second is a streamlined mechanism that checks for hazards based on
3560eae32dcSDimitry Andric /// simple counters that the scheduler itself maintains. It explicitly checks
3570eae32dcSDimitry Andric /// for instruction dispatch limitations, including the number of micro-ops that
3580eae32dcSDimitry Andric /// can dispatch per cycle.
3590eae32dcSDimitry Andric ///
3600eae32dcSDimitry Andric /// TODO: Also check whether the SU must start a new group.
3610eae32dcSDimitry Andric bool ConvergingVLIWScheduler::VLIWSchedBoundary::checkHazard(SUnit *SU) {
3620eae32dcSDimitry Andric   if (HazardRec->isEnabled())
3630eae32dcSDimitry Andric     return HazardRec->getHazardType(SU) != ScheduleHazardRecognizer::NoHazard;
3640eae32dcSDimitry Andric 
3650eae32dcSDimitry Andric   unsigned uops = SchedModel->getNumMicroOps(SU->getInstr());
3660eae32dcSDimitry Andric   if (IssueCount + uops > SchedModel->getIssueWidth())
3670eae32dcSDimitry Andric     return true;
3680eae32dcSDimitry Andric 
3690eae32dcSDimitry Andric   return false;
3700eae32dcSDimitry Andric }
3710eae32dcSDimitry Andric 
3720eae32dcSDimitry Andric void ConvergingVLIWScheduler::VLIWSchedBoundary::releaseNode(
3730eae32dcSDimitry Andric     SUnit *SU, unsigned ReadyCycle) {
3740eae32dcSDimitry Andric   if (ReadyCycle < MinReadyCycle)
3750eae32dcSDimitry Andric     MinReadyCycle = ReadyCycle;
3760eae32dcSDimitry Andric 
3770eae32dcSDimitry Andric   // Check for interlocks first. For the purpose of other heuristics, an
3780eae32dcSDimitry Andric   // instruction that cannot issue appears as if it's not in the ReadyQueue.
3790eae32dcSDimitry Andric   if (ReadyCycle > CurrCycle || checkHazard(SU))
3800eae32dcSDimitry Andric 
3810eae32dcSDimitry Andric     Pending.push(SU);
3820eae32dcSDimitry Andric   else
3830eae32dcSDimitry Andric     Available.push(SU);
3840eae32dcSDimitry Andric }
3850eae32dcSDimitry Andric 
3860eae32dcSDimitry Andric /// Move the boundary of scheduled code by one cycle.
3870eae32dcSDimitry Andric void ConvergingVLIWScheduler::VLIWSchedBoundary::bumpCycle() {
3880eae32dcSDimitry Andric   unsigned Width = SchedModel->getIssueWidth();
3890eae32dcSDimitry Andric   IssueCount = (IssueCount <= Width) ? 0 : IssueCount - Width;
3900eae32dcSDimitry Andric 
3910eae32dcSDimitry Andric   assert(MinReadyCycle < std::numeric_limits<unsigned>::max() &&
3920eae32dcSDimitry Andric          "MinReadyCycle uninitialized");
3930eae32dcSDimitry Andric   unsigned NextCycle = std::max(CurrCycle + 1, MinReadyCycle);
3940eae32dcSDimitry Andric 
3950eae32dcSDimitry Andric   if (!HazardRec->isEnabled()) {
3960eae32dcSDimitry Andric     // Bypass HazardRec virtual calls.
3970eae32dcSDimitry Andric     CurrCycle = NextCycle;
3980eae32dcSDimitry Andric   } else {
3990eae32dcSDimitry Andric     // Bypass getHazardType calls in case of long latency.
4000eae32dcSDimitry Andric     for (; CurrCycle != NextCycle; ++CurrCycle) {
4010eae32dcSDimitry Andric       if (isTop())
4020eae32dcSDimitry Andric         HazardRec->AdvanceCycle();
4030eae32dcSDimitry Andric       else
4040eae32dcSDimitry Andric         HazardRec->RecedeCycle();
4050eae32dcSDimitry Andric     }
4060eae32dcSDimitry Andric   }
4070eae32dcSDimitry Andric   CheckPending = true;
4080eae32dcSDimitry Andric 
4090eae32dcSDimitry Andric   LLVM_DEBUG(dbgs() << "*** Next cycle " << Available.getName() << " cycle "
4100eae32dcSDimitry Andric                     << CurrCycle << '\n');
4110eae32dcSDimitry Andric }
4120eae32dcSDimitry Andric 
4130eae32dcSDimitry Andric /// Move the boundary of scheduled code by one SUnit.
4140eae32dcSDimitry Andric void ConvergingVLIWScheduler::VLIWSchedBoundary::bumpNode(SUnit *SU) {
4150eae32dcSDimitry Andric   bool startNewCycle = false;
4160eae32dcSDimitry Andric 
4170eae32dcSDimitry Andric   // Update the reservation table.
4180eae32dcSDimitry Andric   if (HazardRec->isEnabled()) {
4190eae32dcSDimitry Andric     if (!isTop() && SU->isCall) {
4200eae32dcSDimitry Andric       // Calls are scheduled with their preceding instructions. For bottom-up
4210eae32dcSDimitry Andric       // scheduling, clear the pipeline state before emitting.
4220eae32dcSDimitry Andric       HazardRec->Reset();
4230eae32dcSDimitry Andric     }
4240eae32dcSDimitry Andric     HazardRec->EmitInstruction(SU);
4250eae32dcSDimitry Andric   }
4260eae32dcSDimitry Andric 
4270eae32dcSDimitry Andric   // Update DFA model.
4280eae32dcSDimitry Andric   startNewCycle = ResourceModel->reserveResources(SU, isTop());
4290eae32dcSDimitry Andric 
4300eae32dcSDimitry Andric   // Check the instruction group dispatch limit.
4310eae32dcSDimitry Andric   // TODO: Check if this SU must end a dispatch group.
4320eae32dcSDimitry Andric   IssueCount += SchedModel->getNumMicroOps(SU->getInstr());
4330eae32dcSDimitry Andric   if (startNewCycle) {
4340eae32dcSDimitry Andric     LLVM_DEBUG(dbgs() << "*** Max instrs at cycle " << CurrCycle << '\n');
4350eae32dcSDimitry Andric     bumpCycle();
4360eae32dcSDimitry Andric   } else
4370eae32dcSDimitry Andric     LLVM_DEBUG(dbgs() << "*** IssueCount " << IssueCount << " at cycle "
4380eae32dcSDimitry Andric                       << CurrCycle << '\n');
4390eae32dcSDimitry Andric }
4400eae32dcSDimitry Andric 
4410eae32dcSDimitry Andric /// Release pending ready nodes in to the available queue. This makes them
4420eae32dcSDimitry Andric /// visible to heuristics.
4430eae32dcSDimitry Andric void ConvergingVLIWScheduler::VLIWSchedBoundary::releasePending() {
4440eae32dcSDimitry Andric   // If the available queue is empty, it is safe to reset MinReadyCycle.
4450eae32dcSDimitry Andric   if (Available.empty())
4460eae32dcSDimitry Andric     MinReadyCycle = std::numeric_limits<unsigned>::max();
4470eae32dcSDimitry Andric 
4480eae32dcSDimitry Andric   // Check to see if any of the pending instructions are ready to issue.  If
4490eae32dcSDimitry Andric   // so, add them to the available queue.
4500eae32dcSDimitry Andric   for (unsigned i = 0, e = Pending.size(); i != e; ++i) {
4510eae32dcSDimitry Andric     SUnit *SU = *(Pending.begin() + i);
4520eae32dcSDimitry Andric     unsigned ReadyCycle = isTop() ? SU->TopReadyCycle : SU->BotReadyCycle;
4530eae32dcSDimitry Andric 
4540eae32dcSDimitry Andric     if (ReadyCycle < MinReadyCycle)
4550eae32dcSDimitry Andric       MinReadyCycle = ReadyCycle;
4560eae32dcSDimitry Andric 
4570eae32dcSDimitry Andric     if (ReadyCycle > CurrCycle)
4580eae32dcSDimitry Andric       continue;
4590eae32dcSDimitry Andric 
4600eae32dcSDimitry Andric     if (checkHazard(SU))
4610eae32dcSDimitry Andric       continue;
4620eae32dcSDimitry Andric 
4630eae32dcSDimitry Andric     Available.push(SU);
4640eae32dcSDimitry Andric     Pending.remove(Pending.begin() + i);
4650eae32dcSDimitry Andric     --i;
4660eae32dcSDimitry Andric     --e;
4670eae32dcSDimitry Andric   }
4680eae32dcSDimitry Andric   CheckPending = false;
4690eae32dcSDimitry Andric }
4700eae32dcSDimitry Andric 
4710eae32dcSDimitry Andric /// Remove SU from the ready set for this boundary.
4720eae32dcSDimitry Andric void ConvergingVLIWScheduler::VLIWSchedBoundary::removeReady(SUnit *SU) {
4730eae32dcSDimitry Andric   if (Available.isInQueue(SU))
4740eae32dcSDimitry Andric     Available.remove(Available.find(SU));
4750eae32dcSDimitry Andric   else {
4760eae32dcSDimitry Andric     assert(Pending.isInQueue(SU) && "bad ready count");
4770eae32dcSDimitry Andric     Pending.remove(Pending.find(SU));
4780eae32dcSDimitry Andric   }
4790eae32dcSDimitry Andric }
4800eae32dcSDimitry Andric 
4810eae32dcSDimitry Andric /// If this queue only has one ready candidate, return it. As a side effect,
4820eae32dcSDimitry Andric /// advance the cycle until at least one node is ready. If multiple instructions
4830eae32dcSDimitry Andric /// are ready, return NULL.
4840eae32dcSDimitry Andric SUnit *ConvergingVLIWScheduler::VLIWSchedBoundary::pickOnlyChoice() {
4850eae32dcSDimitry Andric   if (CheckPending)
4860eae32dcSDimitry Andric     releasePending();
4870eae32dcSDimitry Andric 
4880eae32dcSDimitry Andric   auto AdvanceCycle = [this]() {
4890eae32dcSDimitry Andric     if (Available.empty())
4900eae32dcSDimitry Andric       return true;
4910eae32dcSDimitry Andric     if (Available.size() == 1 && Pending.size() > 0)
4920eae32dcSDimitry Andric       return !ResourceModel->isResourceAvailable(*Available.begin(), isTop()) ||
4930eae32dcSDimitry Andric              getWeakLeft(*Available.begin(), isTop()) != 0;
4940eae32dcSDimitry Andric     return false;
4950eae32dcSDimitry Andric   };
4960eae32dcSDimitry Andric   for (unsigned i = 0; AdvanceCycle(); ++i) {
4970eae32dcSDimitry Andric     assert(i <= (HazardRec->getMaxLookAhead() + MaxMinLatency) &&
4980eae32dcSDimitry Andric            "permanent hazard");
4990eae32dcSDimitry Andric     (void)i;
5000eae32dcSDimitry Andric     ResourceModel->reserveResources(nullptr, isTop());
5010eae32dcSDimitry Andric     bumpCycle();
5020eae32dcSDimitry Andric     releasePending();
5030eae32dcSDimitry Andric   }
5040eae32dcSDimitry Andric   if (Available.size() == 1)
5050eae32dcSDimitry Andric     return *Available.begin();
5060eae32dcSDimitry Andric   return nullptr;
5070eae32dcSDimitry Andric }
5080eae32dcSDimitry Andric 
5090eae32dcSDimitry Andric #ifndef NDEBUG
5100eae32dcSDimitry Andric void ConvergingVLIWScheduler::traceCandidate(const char *Label,
5110eae32dcSDimitry Andric                                              const ReadyQueue &Q, SUnit *SU,
5120eae32dcSDimitry Andric                                              int Cost, PressureChange P) {
5130eae32dcSDimitry Andric   dbgs() << Label << " " << Q.getName() << " ";
5140eae32dcSDimitry Andric   if (P.isValid())
5150eae32dcSDimitry Andric     dbgs() << DAG->TRI->getRegPressureSetName(P.getPSet()) << ":"
5160eae32dcSDimitry Andric            << P.getUnitInc() << " ";
5170eae32dcSDimitry Andric   else
5180eae32dcSDimitry Andric     dbgs() << "     ";
5190eae32dcSDimitry Andric   dbgs() << "cost(" << Cost << ")\t";
5200eae32dcSDimitry Andric   DAG->dumpNode(*SU);
5210eae32dcSDimitry Andric }
5220eae32dcSDimitry Andric 
5230eae32dcSDimitry Andric // Very detailed queue dump, to be used with higher verbosity levels.
5240eae32dcSDimitry Andric void ConvergingVLIWScheduler::readyQueueVerboseDump(
5250eae32dcSDimitry Andric     const RegPressureTracker &RPTracker, SchedCandidate &Candidate,
5260eae32dcSDimitry Andric     ReadyQueue &Q) {
5270eae32dcSDimitry Andric   RegPressureTracker &TempTracker = const_cast<RegPressureTracker &>(RPTracker);
5280eae32dcSDimitry Andric 
5290eae32dcSDimitry Andric   dbgs() << ">>> " << Q.getName() << "\n";
5300eae32dcSDimitry Andric   for (ReadyQueue::iterator I = Q.begin(), E = Q.end(); I != E; ++I) {
5310eae32dcSDimitry Andric     RegPressureDelta RPDelta;
5320eae32dcSDimitry Andric     TempTracker.getMaxPressureDelta((*I)->getInstr(), RPDelta,
5330eae32dcSDimitry Andric                                     DAG->getRegionCriticalPSets(),
5340eae32dcSDimitry Andric                                     DAG->getRegPressure().MaxSetPressure);
5350eae32dcSDimitry Andric     std::stringstream dbgstr;
5360eae32dcSDimitry Andric     dbgstr << "SU(" << std::setw(3) << (*I)->NodeNum << ")";
5370eae32dcSDimitry Andric     dbgs() << dbgstr.str();
5380eae32dcSDimitry Andric     SchedulingCost(Q, *I, Candidate, RPDelta, true);
5390eae32dcSDimitry Andric     dbgs() << "\t";
5400eae32dcSDimitry Andric     (*I)->getInstr()->dump();
5410eae32dcSDimitry Andric   }
5420eae32dcSDimitry Andric   dbgs() << "\n";
5430eae32dcSDimitry Andric }
5440eae32dcSDimitry Andric #endif
5450eae32dcSDimitry Andric 
5460eae32dcSDimitry Andric /// isSingleUnscheduledPred - If SU2 is the only unscheduled predecessor
5470eae32dcSDimitry Andric /// of SU, return true (we may have duplicates)
5480eae32dcSDimitry Andric static inline bool isSingleUnscheduledPred(SUnit *SU, SUnit *SU2) {
5490eae32dcSDimitry Andric   if (SU->NumPredsLeft == 0)
5500eae32dcSDimitry Andric     return false;
5510eae32dcSDimitry Andric 
5520eae32dcSDimitry Andric   for (auto &Pred : SU->Preds) {
5530eae32dcSDimitry Andric     // We found an available, but not scheduled, predecessor.
5540eae32dcSDimitry Andric     if (!Pred.getSUnit()->isScheduled && (Pred.getSUnit() != SU2))
5550eae32dcSDimitry Andric       return false;
5560eae32dcSDimitry Andric   }
5570eae32dcSDimitry Andric 
5580eae32dcSDimitry Andric   return true;
5590eae32dcSDimitry Andric }
5600eae32dcSDimitry Andric 
5610eae32dcSDimitry Andric /// isSingleUnscheduledSucc - If SU2 is the only unscheduled successor
5620eae32dcSDimitry Andric /// of SU, return true (we may have duplicates)
5630eae32dcSDimitry Andric static inline bool isSingleUnscheduledSucc(SUnit *SU, SUnit *SU2) {
5640eae32dcSDimitry Andric   if (SU->NumSuccsLeft == 0)
5650eae32dcSDimitry Andric     return false;
5660eae32dcSDimitry Andric 
5670eae32dcSDimitry Andric   for (auto &Succ : SU->Succs) {
5680eae32dcSDimitry Andric     // We found an available, but not scheduled, successor.
5690eae32dcSDimitry Andric     if (!Succ.getSUnit()->isScheduled && (Succ.getSUnit() != SU2))
5700eae32dcSDimitry Andric       return false;
5710eae32dcSDimitry Andric   }
5720eae32dcSDimitry Andric   return true;
5730eae32dcSDimitry Andric }
5740eae32dcSDimitry Andric 
5750eae32dcSDimitry Andric /// Check if the instruction changes the register pressure of a register in the
5760eae32dcSDimitry Andric /// high pressure set. The function returns a negative value if the pressure
5770eae32dcSDimitry Andric /// decreases and a positive value is the pressure increases. If the instruction
5780eae32dcSDimitry Andric /// doesn't use a high pressure register or doesn't change the register
5790eae32dcSDimitry Andric /// pressure, then return 0.
5800eae32dcSDimitry Andric int ConvergingVLIWScheduler::pressureChange(const SUnit *SU, bool isBotUp) {
5810eae32dcSDimitry Andric   PressureDiff &PD = DAG->getPressureDiff(SU);
582fcaf7f86SDimitry Andric   for (const auto &P : PD) {
5830eae32dcSDimitry Andric     if (!P.isValid())
5840eae32dcSDimitry Andric       continue;
585bdd1243dSDimitry Andric     // The pressure differences are computed bottom-up, so the comparison for
5860eae32dcSDimitry Andric     // an increase is positive in the bottom direction, but negative in the
5870eae32dcSDimitry Andric     //  top-down direction.
5880eae32dcSDimitry Andric     if (HighPressureSets[P.getPSet()])
5890eae32dcSDimitry Andric       return (isBotUp ? P.getUnitInc() : -P.getUnitInc());
5900eae32dcSDimitry Andric   }
5910eae32dcSDimitry Andric   return 0;
5920eae32dcSDimitry Andric }
5930eae32dcSDimitry Andric 
5940eae32dcSDimitry Andric /// Single point to compute overall scheduling cost.
5950eae32dcSDimitry Andric /// TODO: More heuristics will be used soon.
5960eae32dcSDimitry Andric int ConvergingVLIWScheduler::SchedulingCost(ReadyQueue &Q, SUnit *SU,
5970eae32dcSDimitry Andric                                             SchedCandidate &Candidate,
5980eae32dcSDimitry Andric                                             RegPressureDelta &Delta,
5990eae32dcSDimitry Andric                                             bool verbose) {
6000eae32dcSDimitry Andric   // Initial trivial priority.
6010eae32dcSDimitry Andric   int ResCount = 1;
6020eae32dcSDimitry Andric 
6030eae32dcSDimitry Andric   // Do not waste time on a node that is already scheduled.
6040eae32dcSDimitry Andric   if (!SU || SU->isScheduled)
6050eae32dcSDimitry Andric     return ResCount;
6060eae32dcSDimitry Andric 
6070eae32dcSDimitry Andric   LLVM_DEBUG(if (verbose) dbgs()
6080eae32dcSDimitry Andric              << ((Q.getID() == TopQID) ? "(top|" : "(bot|"));
6090eae32dcSDimitry Andric   // Forced priority is high.
6100eae32dcSDimitry Andric   if (SU->isScheduleHigh) {
6110eae32dcSDimitry Andric     ResCount += PriorityOne;
6120eae32dcSDimitry Andric     LLVM_DEBUG(dbgs() << "H|");
6130eae32dcSDimitry Andric   }
6140eae32dcSDimitry Andric 
6150eae32dcSDimitry Andric   unsigned IsAvailableAmt = 0;
6160eae32dcSDimitry Andric   // Critical path first.
6170eae32dcSDimitry Andric   if (Q.getID() == TopQID) {
6180eae32dcSDimitry Andric     if (Top.isLatencyBound(SU)) {
6190eae32dcSDimitry Andric       LLVM_DEBUG(if (verbose) dbgs() << "LB|");
6200eae32dcSDimitry Andric       ResCount += (SU->getHeight() * ScaleTwo);
6210eae32dcSDimitry Andric     }
6220eae32dcSDimitry Andric 
6230eae32dcSDimitry Andric     LLVM_DEBUG(if (verbose) {
6240eae32dcSDimitry Andric       std::stringstream dbgstr;
6250eae32dcSDimitry Andric       dbgstr << "h" << std::setw(3) << SU->getHeight() << "|";
6260eae32dcSDimitry Andric       dbgs() << dbgstr.str();
6270eae32dcSDimitry Andric     });
6280eae32dcSDimitry Andric 
6290eae32dcSDimitry Andric     // If resources are available for it, multiply the
6300eae32dcSDimitry Andric     // chance of scheduling.
6310eae32dcSDimitry Andric     if (Top.ResourceModel->isResourceAvailable(SU, true)) {
6320eae32dcSDimitry Andric       IsAvailableAmt = (PriorityTwo + PriorityThree);
6330eae32dcSDimitry Andric       ResCount += IsAvailableAmt;
6340eae32dcSDimitry Andric       LLVM_DEBUG(if (verbose) dbgs() << "A|");
6350eae32dcSDimitry Andric     } else
6360eae32dcSDimitry Andric       LLVM_DEBUG(if (verbose) dbgs() << " |");
6370eae32dcSDimitry Andric   } else {
6380eae32dcSDimitry Andric     if (Bot.isLatencyBound(SU)) {
6390eae32dcSDimitry Andric       LLVM_DEBUG(if (verbose) dbgs() << "LB|");
6400eae32dcSDimitry Andric       ResCount += (SU->getDepth() * ScaleTwo);
6410eae32dcSDimitry Andric     }
6420eae32dcSDimitry Andric 
6430eae32dcSDimitry Andric     LLVM_DEBUG(if (verbose) {
6440eae32dcSDimitry Andric       std::stringstream dbgstr;
6450eae32dcSDimitry Andric       dbgstr << "d" << std::setw(3) << SU->getDepth() << "|";
6460eae32dcSDimitry Andric       dbgs() << dbgstr.str();
6470eae32dcSDimitry Andric     });
6480eae32dcSDimitry Andric 
6490eae32dcSDimitry Andric     // If resources are available for it, multiply the
6500eae32dcSDimitry Andric     // chance of scheduling.
6510eae32dcSDimitry Andric     if (Bot.ResourceModel->isResourceAvailable(SU, false)) {
6520eae32dcSDimitry Andric       IsAvailableAmt = (PriorityTwo + PriorityThree);
6530eae32dcSDimitry Andric       ResCount += IsAvailableAmt;
6540eae32dcSDimitry Andric       LLVM_DEBUG(if (verbose) dbgs() << "A|");
6550eae32dcSDimitry Andric     } else
6560eae32dcSDimitry Andric       LLVM_DEBUG(if (verbose) dbgs() << " |");
6570eae32dcSDimitry Andric   }
6580eae32dcSDimitry Andric 
6590eae32dcSDimitry Andric   unsigned NumNodesBlocking = 0;
6600eae32dcSDimitry Andric   if (Q.getID() == TopQID) {
6610eae32dcSDimitry Andric     // How many SUs does it block from scheduling?
6620eae32dcSDimitry Andric     // Look at all of the successors of this node.
6630eae32dcSDimitry Andric     // Count the number of nodes that
6640eae32dcSDimitry Andric     // this node is the sole unscheduled node for.
6650eae32dcSDimitry Andric     if (Top.isLatencyBound(SU))
6660eae32dcSDimitry Andric       for (const SDep &SI : SU->Succs)
6670eae32dcSDimitry Andric         if (isSingleUnscheduledPred(SI.getSUnit(), SU))
6680eae32dcSDimitry Andric           ++NumNodesBlocking;
6690eae32dcSDimitry Andric   } else {
6700eae32dcSDimitry Andric     // How many unscheduled predecessors block this node?
6710eae32dcSDimitry Andric     if (Bot.isLatencyBound(SU))
6720eae32dcSDimitry Andric       for (const SDep &PI : SU->Preds)
6730eae32dcSDimitry Andric         if (isSingleUnscheduledSucc(PI.getSUnit(), SU))
6740eae32dcSDimitry Andric           ++NumNodesBlocking;
6750eae32dcSDimitry Andric   }
6760eae32dcSDimitry Andric   ResCount += (NumNodesBlocking * ScaleTwo);
6770eae32dcSDimitry Andric 
6780eae32dcSDimitry Andric   LLVM_DEBUG(if (verbose) {
6790eae32dcSDimitry Andric     std::stringstream dbgstr;
6800eae32dcSDimitry Andric     dbgstr << "blk " << std::setw(2) << NumNodesBlocking << ")|";
6810eae32dcSDimitry Andric     dbgs() << dbgstr.str();
6820eae32dcSDimitry Andric   });
6830eae32dcSDimitry Andric 
6840eae32dcSDimitry Andric   // Factor in reg pressure as a heuristic.
6850eae32dcSDimitry Andric   if (!IgnoreBBRegPressure) {
6860eae32dcSDimitry Andric     // Decrease priority by the amount that register pressure exceeds the limit.
6870eae32dcSDimitry Andric     ResCount -= (Delta.Excess.getUnitInc() * PriorityOne);
6880eae32dcSDimitry Andric     // Decrease priority if register pressure exceeds the limit.
6890eae32dcSDimitry Andric     ResCount -= (Delta.CriticalMax.getUnitInc() * PriorityOne);
6900eae32dcSDimitry Andric     // Decrease priority slightly if register pressure would increase over the
6910eae32dcSDimitry Andric     // current maximum.
6920eae32dcSDimitry Andric     ResCount -= (Delta.CurrentMax.getUnitInc() * PriorityTwo);
6930eae32dcSDimitry Andric     // If there are register pressure issues, then we remove the value added for
6940eae32dcSDimitry Andric     // the instruction being available. The rationale is that we really don't
6950eae32dcSDimitry Andric     // want to schedule an instruction that causes a spill.
6960eae32dcSDimitry Andric     if (IsAvailableAmt && pressureChange(SU, Q.getID() != TopQID) > 0 &&
6970eae32dcSDimitry Andric         (Delta.Excess.getUnitInc() || Delta.CriticalMax.getUnitInc() ||
6980eae32dcSDimitry Andric          Delta.CurrentMax.getUnitInc()))
6990eae32dcSDimitry Andric       ResCount -= IsAvailableAmt;
7000eae32dcSDimitry Andric     LLVM_DEBUG(if (verbose) {
7010eae32dcSDimitry Andric       dbgs() << "RP " << Delta.Excess.getUnitInc() << "/"
7020eae32dcSDimitry Andric              << Delta.CriticalMax.getUnitInc() << "/"
7030eae32dcSDimitry Andric              << Delta.CurrentMax.getUnitInc() << ")|";
7040eae32dcSDimitry Andric     });
7050eae32dcSDimitry Andric   }
7060eae32dcSDimitry Andric 
7070eae32dcSDimitry Andric   // Give preference to a zero latency instruction if the dependent
7080eae32dcSDimitry Andric   // instruction is in the current packet.
7090eae32dcSDimitry Andric   if (Q.getID() == TopQID && getWeakLeft(SU, true) == 0) {
7100eae32dcSDimitry Andric     for (const SDep &PI : SU->Preds) {
7110eae32dcSDimitry Andric       if (!PI.getSUnit()->getInstr()->isPseudo() && PI.isAssignedRegDep() &&
7120eae32dcSDimitry Andric           PI.getLatency() == 0 &&
7130eae32dcSDimitry Andric           Top.ResourceModel->isInPacket(PI.getSUnit())) {
7140eae32dcSDimitry Andric         ResCount += PriorityThree;
7150eae32dcSDimitry Andric         LLVM_DEBUG(if (verbose) dbgs() << "Z|");
7160eae32dcSDimitry Andric       }
7170eae32dcSDimitry Andric     }
7180eae32dcSDimitry Andric   } else if (Q.getID() == BotQID && getWeakLeft(SU, false) == 0) {
7190eae32dcSDimitry Andric     for (const SDep &SI : SU->Succs) {
7200eae32dcSDimitry Andric       if (!SI.getSUnit()->getInstr()->isPseudo() && SI.isAssignedRegDep() &&
7210eae32dcSDimitry Andric           SI.getLatency() == 0 &&
7220eae32dcSDimitry Andric           Bot.ResourceModel->isInPacket(SI.getSUnit())) {
7230eae32dcSDimitry Andric         ResCount += PriorityThree;
7240eae32dcSDimitry Andric         LLVM_DEBUG(if (verbose) dbgs() << "Z|");
7250eae32dcSDimitry Andric       }
7260eae32dcSDimitry Andric     }
7270eae32dcSDimitry Andric   }
7280eae32dcSDimitry Andric 
7290eae32dcSDimitry Andric   // If the instruction has a non-zero latency dependence with an instruction in
7300eae32dcSDimitry Andric   // the current packet, then it should not be scheduled yet. The case occurs
7310eae32dcSDimitry Andric   // when the dependent instruction is scheduled in a new packet, so the
7320eae32dcSDimitry Andric   // scheduler updates the current cycle and pending instructions become
7330eae32dcSDimitry Andric   // available.
7340eae32dcSDimitry Andric   if (CheckEarlyAvail) {
7350eae32dcSDimitry Andric     if (Q.getID() == TopQID) {
7360eae32dcSDimitry Andric       for (const auto &PI : SU->Preds) {
7370eae32dcSDimitry Andric         if (PI.getLatency() > 0 &&
7380eae32dcSDimitry Andric             Top.ResourceModel->isInPacket(PI.getSUnit())) {
7390eae32dcSDimitry Andric           ResCount -= PriorityOne;
7400eae32dcSDimitry Andric           LLVM_DEBUG(if (verbose) dbgs() << "D|");
7410eae32dcSDimitry Andric         }
7420eae32dcSDimitry Andric       }
7430eae32dcSDimitry Andric     } else {
7440eae32dcSDimitry Andric       for (const auto &SI : SU->Succs) {
7450eae32dcSDimitry Andric         if (SI.getLatency() > 0 &&
7460eae32dcSDimitry Andric             Bot.ResourceModel->isInPacket(SI.getSUnit())) {
7470eae32dcSDimitry Andric           ResCount -= PriorityOne;
7480eae32dcSDimitry Andric           LLVM_DEBUG(if (verbose) dbgs() << "D|");
7490eae32dcSDimitry Andric         }
7500eae32dcSDimitry Andric       }
7510eae32dcSDimitry Andric     }
7520eae32dcSDimitry Andric   }
7530eae32dcSDimitry Andric 
7540eae32dcSDimitry Andric   LLVM_DEBUG(if (verbose) {
7550eae32dcSDimitry Andric     std::stringstream dbgstr;
7560eae32dcSDimitry Andric     dbgstr << "Total " << std::setw(4) << ResCount << ")";
7570eae32dcSDimitry Andric     dbgs() << dbgstr.str();
7580eae32dcSDimitry Andric   });
7590eae32dcSDimitry Andric 
7600eae32dcSDimitry Andric   return ResCount;
7610eae32dcSDimitry Andric }
7620eae32dcSDimitry Andric 
7630eae32dcSDimitry Andric /// Pick the best candidate from the top queue.
7640eae32dcSDimitry Andric ///
7650eae32dcSDimitry Andric /// TODO: getMaxPressureDelta results can be mostly cached for each SUnit during
7660eae32dcSDimitry Andric /// DAG building. To adjust for the current scheduling location we need to
7670eae32dcSDimitry Andric /// maintain the number of vreg uses remaining to be top-scheduled.
7680eae32dcSDimitry Andric ConvergingVLIWScheduler::CandResult
7690eae32dcSDimitry Andric ConvergingVLIWScheduler::pickNodeFromQueue(VLIWSchedBoundary &Zone,
7700eae32dcSDimitry Andric                                            const RegPressureTracker &RPTracker,
7710eae32dcSDimitry Andric                                            SchedCandidate &Candidate) {
7720eae32dcSDimitry Andric   ReadyQueue &Q = Zone.Available;
7730eae32dcSDimitry Andric   LLVM_DEBUG(if (SchedDebugVerboseLevel > 1)
7740eae32dcSDimitry Andric                  readyQueueVerboseDump(RPTracker, Candidate, Q);
7750eae32dcSDimitry Andric              else Q.dump(););
7760eae32dcSDimitry Andric 
7770eae32dcSDimitry Andric   // getMaxPressureDelta temporarily modifies the tracker.
7780eae32dcSDimitry Andric   RegPressureTracker &TempTracker = const_cast<RegPressureTracker &>(RPTracker);
7790eae32dcSDimitry Andric 
7800eae32dcSDimitry Andric   // BestSU remains NULL if no top candidates beat the best existing candidate.
7810eae32dcSDimitry Andric   CandResult FoundCandidate = NoCand;
7820eae32dcSDimitry Andric   for (ReadyQueue::iterator I = Q.begin(), E = Q.end(); I != E; ++I) {
7830eae32dcSDimitry Andric     RegPressureDelta RPDelta;
7840eae32dcSDimitry Andric     TempTracker.getMaxPressureDelta((*I)->getInstr(), RPDelta,
7850eae32dcSDimitry Andric                                     DAG->getRegionCriticalPSets(),
7860eae32dcSDimitry Andric                                     DAG->getRegPressure().MaxSetPressure);
7870eae32dcSDimitry Andric 
7880eae32dcSDimitry Andric     int CurrentCost = SchedulingCost(Q, *I, Candidate, RPDelta, false);
7890eae32dcSDimitry Andric 
7900eae32dcSDimitry Andric     // Initialize the candidate if needed.
7910eae32dcSDimitry Andric     if (!Candidate.SU) {
7920eae32dcSDimitry Andric       LLVM_DEBUG(traceCandidate("DCAND", Q, *I, CurrentCost));
7930eae32dcSDimitry Andric       Candidate.SU = *I;
7940eae32dcSDimitry Andric       Candidate.RPDelta = RPDelta;
7950eae32dcSDimitry Andric       Candidate.SCost = CurrentCost;
7960eae32dcSDimitry Andric       FoundCandidate = NodeOrder;
7970eae32dcSDimitry Andric       continue;
7980eae32dcSDimitry Andric     }
7990eae32dcSDimitry Andric 
8000eae32dcSDimitry Andric     // Choose node order for negative cost candidates. There is no good
8010eae32dcSDimitry Andric     // candidate in this case.
8020eae32dcSDimitry Andric     if (CurrentCost < 0 && Candidate.SCost < 0) {
8030eae32dcSDimitry Andric       if ((Q.getID() == TopQID && (*I)->NodeNum < Candidate.SU->NodeNum) ||
8040eae32dcSDimitry Andric           (Q.getID() == BotQID && (*I)->NodeNum > Candidate.SU->NodeNum)) {
8050eae32dcSDimitry Andric         LLVM_DEBUG(traceCandidate("NCAND", Q, *I, CurrentCost));
8060eae32dcSDimitry Andric         Candidate.SU = *I;
8070eae32dcSDimitry Andric         Candidate.RPDelta = RPDelta;
8080eae32dcSDimitry Andric         Candidate.SCost = CurrentCost;
8090eae32dcSDimitry Andric         FoundCandidate = NodeOrder;
8100eae32dcSDimitry Andric       }
8110eae32dcSDimitry Andric       continue;
8120eae32dcSDimitry Andric     }
8130eae32dcSDimitry Andric 
8140eae32dcSDimitry Andric     // Best cost.
8150eae32dcSDimitry Andric     if (CurrentCost > Candidate.SCost) {
8160eae32dcSDimitry Andric       LLVM_DEBUG(traceCandidate("CCAND", Q, *I, CurrentCost));
8170eae32dcSDimitry Andric       Candidate.SU = *I;
8180eae32dcSDimitry Andric       Candidate.RPDelta = RPDelta;
8190eae32dcSDimitry Andric       Candidate.SCost = CurrentCost;
8200eae32dcSDimitry Andric       FoundCandidate = BestCost;
8210eae32dcSDimitry Andric       continue;
8220eae32dcSDimitry Andric     }
8230eae32dcSDimitry Andric 
8240eae32dcSDimitry Andric     // Choose an instruction that does not depend on an artificial edge.
8250eae32dcSDimitry Andric     unsigned CurrWeak = getWeakLeft(*I, (Q.getID() == TopQID));
8260eae32dcSDimitry Andric     unsigned CandWeak = getWeakLeft(Candidate.SU, (Q.getID() == TopQID));
8270eae32dcSDimitry Andric     if (CurrWeak != CandWeak) {
8280eae32dcSDimitry Andric       if (CurrWeak < CandWeak) {
8290eae32dcSDimitry Andric         LLVM_DEBUG(traceCandidate("WCAND", Q, *I, CurrentCost));
8300eae32dcSDimitry Andric         Candidate.SU = *I;
8310eae32dcSDimitry Andric         Candidate.RPDelta = RPDelta;
8320eae32dcSDimitry Andric         Candidate.SCost = CurrentCost;
8330eae32dcSDimitry Andric         FoundCandidate = Weak;
8340eae32dcSDimitry Andric       }
8350eae32dcSDimitry Andric       continue;
8360eae32dcSDimitry Andric     }
8370eae32dcSDimitry Andric 
8380eae32dcSDimitry Andric     if (CurrentCost == Candidate.SCost && Zone.isLatencyBound(*I)) {
8390eae32dcSDimitry Andric       unsigned CurrSize, CandSize;
8400eae32dcSDimitry Andric       if (Q.getID() == TopQID) {
8410eae32dcSDimitry Andric         CurrSize = (*I)->Succs.size();
8420eae32dcSDimitry Andric         CandSize = Candidate.SU->Succs.size();
8430eae32dcSDimitry Andric       } else {
8440eae32dcSDimitry Andric         CurrSize = (*I)->Preds.size();
8450eae32dcSDimitry Andric         CandSize = Candidate.SU->Preds.size();
8460eae32dcSDimitry Andric       }
8470eae32dcSDimitry Andric       if (CurrSize > CandSize) {
8480eae32dcSDimitry Andric         LLVM_DEBUG(traceCandidate("SPCAND", Q, *I, CurrentCost));
8490eae32dcSDimitry Andric         Candidate.SU = *I;
8500eae32dcSDimitry Andric         Candidate.RPDelta = RPDelta;
8510eae32dcSDimitry Andric         Candidate.SCost = CurrentCost;
8520eae32dcSDimitry Andric         FoundCandidate = BestCost;
8530eae32dcSDimitry Andric       }
8540eae32dcSDimitry Andric       // Keep the old candidate if it's a better candidate. That is, don't use
8550eae32dcSDimitry Andric       // the subsequent tie breaker.
8560eae32dcSDimitry Andric       if (CurrSize != CandSize)
8570eae32dcSDimitry Andric         continue;
8580eae32dcSDimitry Andric     }
8590eae32dcSDimitry Andric 
8600eae32dcSDimitry Andric     // Tie breaker.
8610eae32dcSDimitry Andric     // To avoid scheduling indeterminism, we need a tie breaker
8620eae32dcSDimitry Andric     // for the case when cost is identical for two nodes.
8630eae32dcSDimitry Andric     if (UseNewerCandidate && CurrentCost == Candidate.SCost) {
8640eae32dcSDimitry Andric       if ((Q.getID() == TopQID && (*I)->NodeNum < Candidate.SU->NodeNum) ||
8650eae32dcSDimitry Andric           (Q.getID() == BotQID && (*I)->NodeNum > Candidate.SU->NodeNum)) {
8660eae32dcSDimitry Andric         LLVM_DEBUG(traceCandidate("TCAND", Q, *I, CurrentCost));
8670eae32dcSDimitry Andric         Candidate.SU = *I;
8680eae32dcSDimitry Andric         Candidate.RPDelta = RPDelta;
8690eae32dcSDimitry Andric         Candidate.SCost = CurrentCost;
8700eae32dcSDimitry Andric         FoundCandidate = NodeOrder;
8710eae32dcSDimitry Andric         continue;
8720eae32dcSDimitry Andric       }
8730eae32dcSDimitry Andric     }
8740eae32dcSDimitry Andric 
8750eae32dcSDimitry Andric     // Fall through to original instruction order.
8760eae32dcSDimitry Andric     // Only consider node order if Candidate was chosen from this Q.
8770eae32dcSDimitry Andric     if (FoundCandidate == NoCand)
8780eae32dcSDimitry Andric       continue;
8790eae32dcSDimitry Andric   }
8800eae32dcSDimitry Andric   return FoundCandidate;
8810eae32dcSDimitry Andric }
8820eae32dcSDimitry Andric 
8830eae32dcSDimitry Andric /// Pick the best candidate node from either the top or bottom queue.
8840eae32dcSDimitry Andric SUnit *ConvergingVLIWScheduler::pickNodeBidrectional(bool &IsTopNode) {
8850eae32dcSDimitry Andric   // Schedule as far as possible in the direction of no choice. This is most
8860eae32dcSDimitry Andric   // efficient, but also provides the best heuristics for CriticalPSets.
8870eae32dcSDimitry Andric   if (SUnit *SU = Bot.pickOnlyChoice()) {
8880eae32dcSDimitry Andric     LLVM_DEBUG(dbgs() << "Picked only Bottom\n");
8890eae32dcSDimitry Andric     IsTopNode = false;
8900eae32dcSDimitry Andric     return SU;
8910eae32dcSDimitry Andric   }
8920eae32dcSDimitry Andric   if (SUnit *SU = Top.pickOnlyChoice()) {
8930eae32dcSDimitry Andric     LLVM_DEBUG(dbgs() << "Picked only Top\n");
8940eae32dcSDimitry Andric     IsTopNode = true;
8950eae32dcSDimitry Andric     return SU;
8960eae32dcSDimitry Andric   }
8970eae32dcSDimitry Andric   SchedCandidate BotCand;
8980eae32dcSDimitry Andric   // Prefer bottom scheduling when heuristics are silent.
8990eae32dcSDimitry Andric   CandResult BotResult =
9000eae32dcSDimitry Andric       pickNodeFromQueue(Bot, DAG->getBotRPTracker(), BotCand);
9010eae32dcSDimitry Andric   assert(BotResult != NoCand && "failed to find the first candidate");
9020eae32dcSDimitry Andric 
9030eae32dcSDimitry Andric   // If either Q has a single candidate that provides the least increase in
9040eae32dcSDimitry Andric   // Excess pressure, we can immediately schedule from that Q.
9050eae32dcSDimitry Andric   //
9060eae32dcSDimitry Andric   // RegionCriticalPSets summarizes the pressure within the scheduled region and
9070eae32dcSDimitry Andric   // affects picking from either Q. If scheduling in one direction must
9080eae32dcSDimitry Andric   // increase pressure for one of the excess PSets, then schedule in that
9090eae32dcSDimitry Andric   // direction first to provide more freedom in the other direction.
9100eae32dcSDimitry Andric   if (BotResult == SingleExcess || BotResult == SingleCritical) {
9110eae32dcSDimitry Andric     LLVM_DEBUG(dbgs() << "Prefered Bottom Node\n");
9120eae32dcSDimitry Andric     IsTopNode = false;
9130eae32dcSDimitry Andric     return BotCand.SU;
9140eae32dcSDimitry Andric   }
9150eae32dcSDimitry Andric   // Check if the top Q has a better candidate.
9160eae32dcSDimitry Andric   SchedCandidate TopCand;
9170eae32dcSDimitry Andric   CandResult TopResult =
9180eae32dcSDimitry Andric       pickNodeFromQueue(Top, DAG->getTopRPTracker(), TopCand);
9190eae32dcSDimitry Andric   assert(TopResult != NoCand && "failed to find the first candidate");
9200eae32dcSDimitry Andric 
9210eae32dcSDimitry Andric   if (TopResult == SingleExcess || TopResult == SingleCritical) {
9220eae32dcSDimitry Andric     LLVM_DEBUG(dbgs() << "Prefered Top Node\n");
9230eae32dcSDimitry Andric     IsTopNode = true;
9240eae32dcSDimitry Andric     return TopCand.SU;
9250eae32dcSDimitry Andric   }
9260eae32dcSDimitry Andric   // If either Q has a single candidate that minimizes pressure above the
9270eae32dcSDimitry Andric   // original region's pressure pick it.
9280eae32dcSDimitry Andric   if (BotResult == SingleMax) {
9290eae32dcSDimitry Andric     LLVM_DEBUG(dbgs() << "Prefered Bottom Node SingleMax\n");
9300eae32dcSDimitry Andric     IsTopNode = false;
9310eae32dcSDimitry Andric     return BotCand.SU;
9320eae32dcSDimitry Andric   }
9330eae32dcSDimitry Andric   if (TopResult == SingleMax) {
9340eae32dcSDimitry Andric     LLVM_DEBUG(dbgs() << "Prefered Top Node SingleMax\n");
9350eae32dcSDimitry Andric     IsTopNode = true;
9360eae32dcSDimitry Andric     return TopCand.SU;
9370eae32dcSDimitry Andric   }
9380eae32dcSDimitry Andric   if (TopCand.SCost > BotCand.SCost) {
9390eae32dcSDimitry Andric     LLVM_DEBUG(dbgs() << "Prefered Top Node Cost\n");
9400eae32dcSDimitry Andric     IsTopNode = true;
9410eae32dcSDimitry Andric     return TopCand.SU;
9420eae32dcSDimitry Andric   }
9430eae32dcSDimitry Andric   // Otherwise prefer the bottom candidate in node order.
9440eae32dcSDimitry Andric   LLVM_DEBUG(dbgs() << "Prefered Bottom in Node order\n");
9450eae32dcSDimitry Andric   IsTopNode = false;
9460eae32dcSDimitry Andric   return BotCand.SU;
9470eae32dcSDimitry Andric }
9480eae32dcSDimitry Andric 
9490eae32dcSDimitry Andric /// Pick the best node to balance the schedule. Implements MachineSchedStrategy.
9500eae32dcSDimitry Andric SUnit *ConvergingVLIWScheduler::pickNode(bool &IsTopNode) {
9510eae32dcSDimitry Andric   if (DAG->top() == DAG->bottom()) {
9520eae32dcSDimitry Andric     assert(Top.Available.empty() && Top.Pending.empty() &&
9530eae32dcSDimitry Andric            Bot.Available.empty() && Bot.Pending.empty() && "ReadyQ garbage");
9540eae32dcSDimitry Andric     return nullptr;
9550eae32dcSDimitry Andric   }
9560eae32dcSDimitry Andric   SUnit *SU;
9570eae32dcSDimitry Andric   if (ForceTopDown) {
9580eae32dcSDimitry Andric     SU = Top.pickOnlyChoice();
9590eae32dcSDimitry Andric     if (!SU) {
9600eae32dcSDimitry Andric       SchedCandidate TopCand;
9610eae32dcSDimitry Andric       CandResult TopResult =
9620eae32dcSDimitry Andric           pickNodeFromQueue(Top, DAG->getTopRPTracker(), TopCand);
9630eae32dcSDimitry Andric       assert(TopResult != NoCand && "failed to find the first candidate");
9640eae32dcSDimitry Andric       (void)TopResult;
9650eae32dcSDimitry Andric       SU = TopCand.SU;
9660eae32dcSDimitry Andric     }
9670eae32dcSDimitry Andric     IsTopNode = true;
9680eae32dcSDimitry Andric   } else if (ForceBottomUp) {
9690eae32dcSDimitry Andric     SU = Bot.pickOnlyChoice();
9700eae32dcSDimitry Andric     if (!SU) {
9710eae32dcSDimitry Andric       SchedCandidate BotCand;
9720eae32dcSDimitry Andric       CandResult BotResult =
9730eae32dcSDimitry Andric           pickNodeFromQueue(Bot, DAG->getBotRPTracker(), BotCand);
9740eae32dcSDimitry Andric       assert(BotResult != NoCand && "failed to find the first candidate");
9750eae32dcSDimitry Andric       (void)BotResult;
9760eae32dcSDimitry Andric       SU = BotCand.SU;
9770eae32dcSDimitry Andric     }
9780eae32dcSDimitry Andric     IsTopNode = false;
9790eae32dcSDimitry Andric   } else {
9800eae32dcSDimitry Andric     SU = pickNodeBidrectional(IsTopNode);
9810eae32dcSDimitry Andric   }
9820eae32dcSDimitry Andric   if (SU->isTopReady())
9830eae32dcSDimitry Andric     Top.removeReady(SU);
9840eae32dcSDimitry Andric   if (SU->isBottomReady())
9850eae32dcSDimitry Andric     Bot.removeReady(SU);
9860eae32dcSDimitry Andric 
9870eae32dcSDimitry Andric   LLVM_DEBUG(dbgs() << "*** " << (IsTopNode ? "Top" : "Bottom")
9880eae32dcSDimitry Andric                     << " Scheduling instruction in cycle "
9890eae32dcSDimitry Andric                     << (IsTopNode ? Top.CurrCycle : Bot.CurrCycle) << " ("
9900eae32dcSDimitry Andric                     << reportPackets() << ")\n";
9910eae32dcSDimitry Andric              DAG->dumpNode(*SU));
9920eae32dcSDimitry Andric   return SU;
9930eae32dcSDimitry Andric }
9940eae32dcSDimitry Andric 
9950eae32dcSDimitry Andric /// Update the scheduler's state after scheduling a node. This is the same node
9960eae32dcSDimitry Andric /// that was just returned by pickNode(). However, VLIWMachineScheduler needs
9970eae32dcSDimitry Andric /// to update it's state based on the current cycle before MachineSchedStrategy
9980eae32dcSDimitry Andric /// does.
9990eae32dcSDimitry Andric void ConvergingVLIWScheduler::schedNode(SUnit *SU, bool IsTopNode) {
10000eae32dcSDimitry Andric   if (IsTopNode) {
10010eae32dcSDimitry Andric     Top.bumpNode(SU);
10020eae32dcSDimitry Andric     SU->TopReadyCycle = Top.CurrCycle;
10030eae32dcSDimitry Andric   } else {
10040eae32dcSDimitry Andric     Bot.bumpNode(SU);
10050eae32dcSDimitry Andric     SU->BotReadyCycle = Bot.CurrCycle;
10060eae32dcSDimitry Andric   }
10070eae32dcSDimitry Andric }
1008