Home | History | Annotate | Download | only in SelectionDAG
      1 //===- ResourcePriorityQueue.cpp - A DFA-oriented priority queue -*- C++ -*-==//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file implements the ResourcePriorityQueue class, which is a
     11 // SchedulingPriorityQueue that prioritizes instructions using DFA state to
     12 // reduce the length of the critical path through the basic block
     13 // on VLIW platforms.
     14 // The scheduler is basically a top-down adaptable list scheduler with DFA
     15 // resource tracking added to the cost function.
     16 // DFA is queried as a state machine to model "packets/bundles" during
     17 // schedule. Currently packets/bundles are discarded at the end of
     18 // scheduling, affecting only order of instructions.
     19 //
     20 //===----------------------------------------------------------------------===//
     21 
     22 #include "llvm/CodeGen/ResourcePriorityQueue.h"
     23 #include "llvm/CodeGen/MachineInstr.h"
     24 #include "llvm/CodeGen/SelectionDAGNodes.h"
     25 #include "llvm/Support/CommandLine.h"
     26 #include "llvm/Support/Debug.h"
     27 #include "llvm/Support/raw_ostream.h"
     28 #include "llvm/Target/TargetLowering.h"
     29 #include "llvm/Target/TargetMachine.h"
     30 #include "llvm/Target/TargetSubtargetInfo.h"
     31 
     32 using namespace llvm;
     33 
     34 #define DEBUG_TYPE "scheduler"
     35 
     36 static cl::opt<bool> DisableDFASched("disable-dfa-sched", cl::Hidden,
     37   cl::ZeroOrMore, cl::init(false),
     38   cl::desc("Disable use of DFA during scheduling"));
     39 
     40 static cl::opt<signed> RegPressureThreshold(
     41   "dfa-sched-reg-pressure-threshold", cl::Hidden, cl::ZeroOrMore, cl::init(5),
     42   cl::desc("Track reg pressure and switch priority to in-depth"));
     43 
     44 ResourcePriorityQueue::ResourcePriorityQueue(SelectionDAGISel *IS)
     45     : Picker(this), InstrItins(IS->MF->getSubtarget().getInstrItineraryData()) {
     46   const TargetSubtargetInfo &STI = IS->MF->getSubtarget();
     47   TRI = STI.getRegisterInfo();
     48   TLI = IS->TLI;
     49   TII = STI.getInstrInfo();
     50   ResourcesModel.reset(TII->CreateTargetScheduleState(STI));
     51   // This hard requirement could be relaxed, but for now
     52   // do not let it proceed.
     53   assert(ResourcesModel && "Unimplemented CreateTargetScheduleState.");
     54 
     55   unsigned NumRC = TRI->getNumRegClasses();
     56   RegLimit.resize(NumRC);
     57   RegPressure.resize(NumRC);
     58   std::fill(RegLimit.begin(), RegLimit.end(), 0);
     59   std::fill(RegPressure.begin(), RegPressure.end(), 0);
     60   for (TargetRegisterInfo::regclass_iterator I = TRI->regclass_begin(),
     61                                              E = TRI->regclass_end();
     62        I != E; ++I)
     63     RegLimit[(*I)->getID()] = TRI->getRegPressureLimit(*I, *IS->MF);
     64 
     65   ParallelLiveRanges = 0;
     66   HorizontalVerticalBalance = 0;
     67 }
     68 
     69 unsigned
     70 ResourcePriorityQueue::numberRCValPredInSU(SUnit *SU, unsigned RCId) {
     71   unsigned NumberDeps = 0;
     72   for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
     73        I != E; ++I) {
     74     if (I->isCtrl())
     75       continue;
     76 
     77     SUnit *PredSU = I->getSUnit();
     78     const SDNode *ScegN = PredSU->getNode();
     79 
     80     if (!ScegN)
     81       continue;
     82 
     83     // If value is passed to CopyToReg, it is probably
     84     // live outside BB.
     85     switch (ScegN->getOpcode()) {
     86       default:  break;
     87       case ISD::TokenFactor:    break;
     88       case ISD::CopyFromReg:    NumberDeps++;  break;
     89       case ISD::CopyToReg:      break;
     90       case ISD::INLINEASM:      break;
     91     }
     92     if (!ScegN->isMachineOpcode())
     93       continue;
     94 
     95     for (unsigned i = 0, e = ScegN->getNumValues(); i != e; ++i) {
     96       MVT VT = ScegN->getSimpleValueType(i);
     97       if (TLI->isTypeLegal(VT)
     98           && (TLI->getRegClassFor(VT)->getID() == RCId)) {
     99         NumberDeps++;
    100         break;
    101       }
    102     }
    103   }
    104   return NumberDeps;
    105 }
    106 
    107 unsigned ResourcePriorityQueue::numberRCValSuccInSU(SUnit *SU,
    108                                                     unsigned RCId) {
    109   unsigned NumberDeps = 0;
    110   for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
    111        I != E; ++I) {
    112     if (I->isCtrl())
    113       continue;
    114 
    115     SUnit *SuccSU = I->getSUnit();
    116     const SDNode *ScegN = SuccSU->getNode();
    117     if (!ScegN)
    118       continue;
    119 
    120     // If value is passed to CopyToReg, it is probably
    121     // live outside BB.
    122     switch (ScegN->getOpcode()) {
    123       default:  break;
    124       case ISD::TokenFactor:    break;
    125       case ISD::CopyFromReg:    break;
    126       case ISD::CopyToReg:      NumberDeps++;  break;
    127       case ISD::INLINEASM:      break;
    128     }
    129     if (!ScegN->isMachineOpcode())
    130       continue;
    131 
    132     for (unsigned i = 0, e = ScegN->getNumOperands(); i != e; ++i) {
    133       const SDValue &Op = ScegN->getOperand(i);
    134       MVT VT = Op.getNode()->getSimpleValueType(Op.getResNo());
    135       if (TLI->isTypeLegal(VT)
    136           && (TLI->getRegClassFor(VT)->getID() == RCId)) {
    137         NumberDeps++;
    138         break;
    139       }
    140     }
    141   }
    142   return NumberDeps;
    143 }
    144 
    145 static unsigned numberCtrlDepsInSU(SUnit *SU) {
    146   unsigned NumberDeps = 0;
    147   for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
    148        I != E; ++I)
    149     if (I->isCtrl())
    150       NumberDeps++;
    151 
    152   return NumberDeps;
    153 }
    154 
    155 static unsigned numberCtrlPredInSU(SUnit *SU) {
    156   unsigned NumberDeps = 0;
    157   for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
    158        I != E; ++I)
    159     if (I->isCtrl())
    160       NumberDeps++;
    161 
    162   return NumberDeps;
    163 }
    164 
    165 ///
    166 /// Initialize nodes.
    167 ///
    168 void ResourcePriorityQueue::initNodes(std::vector<SUnit> &sunits) {
    169   SUnits = &sunits;
    170   NumNodesSolelyBlocking.resize(SUnits->size(), 0);
    171 
    172   for (unsigned i = 0, e = SUnits->size(); i != e; ++i) {
    173     SUnit *SU = &(*SUnits)[i];
    174     initNumRegDefsLeft(SU);
    175     SU->NodeQueueId = 0;
    176   }
    177 }
    178 
    179 /// This heuristic is used if DFA scheduling is not desired
    180 /// for some VLIW platform.
    181 bool resource_sort::operator()(const SUnit *LHS, const SUnit *RHS) const {
    182   // The isScheduleHigh flag allows nodes with wraparound dependencies that
    183   // cannot easily be modeled as edges with latencies to be scheduled as
    184   // soon as possible in a top-down schedule.
    185   if (LHS->isScheduleHigh && !RHS->isScheduleHigh)
    186     return false;
    187 
    188   if (!LHS->isScheduleHigh && RHS->isScheduleHigh)
    189     return true;
    190 
    191   unsigned LHSNum = LHS->NodeNum;
    192   unsigned RHSNum = RHS->NodeNum;
    193 
    194   // The most important heuristic is scheduling the critical path.
    195   unsigned LHSLatency = PQ->getLatency(LHSNum);
    196   unsigned RHSLatency = PQ->getLatency(RHSNum);
    197   if (LHSLatency < RHSLatency) return true;
    198   if (LHSLatency > RHSLatency) return false;
    199 
    200   // After that, if two nodes have identical latencies, look to see if one will
    201   // unblock more other nodes than the other.
    202   unsigned LHSBlocked = PQ->getNumSolelyBlockNodes(LHSNum);
    203   unsigned RHSBlocked = PQ->getNumSolelyBlockNodes(RHSNum);
    204   if (LHSBlocked < RHSBlocked) return true;
    205   if (LHSBlocked > RHSBlocked) return false;
    206 
    207   // Finally, just to provide a stable ordering, use the node number as a
    208   // deciding factor.
    209   return LHSNum < RHSNum;
    210 }
    211 
    212 
    213 /// getSingleUnscheduledPred - If there is exactly one unscheduled predecessor
    214 /// of SU, return it, otherwise return null.
    215 SUnit *ResourcePriorityQueue::getSingleUnscheduledPred(SUnit *SU) {
    216   SUnit *OnlyAvailablePred = nullptr;
    217   for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
    218        I != E; ++I) {
    219     SUnit &Pred = *I->getSUnit();
    220     if (!Pred.isScheduled) {
    221       // We found an available, but not scheduled, predecessor.  If it's the
    222       // only one we have found, keep track of it... otherwise give up.
    223       if (OnlyAvailablePred && OnlyAvailablePred != &Pred)
    224         return nullptr;
    225       OnlyAvailablePred = &Pred;
    226     }
    227   }
    228   return OnlyAvailablePred;
    229 }
    230 
    231 void ResourcePriorityQueue::push(SUnit *SU) {
    232   // Look at all of the successors of this node.  Count the number of nodes that
    233   // this node is the sole unscheduled node for.
    234   unsigned NumNodesBlocking = 0;
    235   for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
    236        I != E; ++I)
    237     if (getSingleUnscheduledPred(I->getSUnit()) == SU)
    238       ++NumNodesBlocking;
    239 
    240   NumNodesSolelyBlocking[SU->NodeNum] = NumNodesBlocking;
    241   Queue.push_back(SU);
    242 }
    243 
    244 /// Check if scheduling of this SU is possible
    245 /// in the current packet.
    246 bool ResourcePriorityQueue::isResourceAvailable(SUnit *SU) {
    247   if (!SU || !SU->getNode())
    248     return false;
    249 
    250   // If this is a compound instruction,
    251   // it is likely to be a call. Do not delay it.
    252   if (SU->getNode()->getGluedNode())
    253     return true;
    254 
    255   // First see if the pipeline could receive this instruction
    256   // in the current cycle.
    257   if (SU->getNode()->isMachineOpcode())
    258     switch (SU->getNode()->getMachineOpcode()) {
    259     default:
    260       if (!ResourcesModel->canReserveResources(&TII->get(
    261           SU->getNode()->getMachineOpcode())))
    262            return false;
    263     case TargetOpcode::EXTRACT_SUBREG:
    264     case TargetOpcode::INSERT_SUBREG:
    265     case TargetOpcode::SUBREG_TO_REG:
    266     case TargetOpcode::REG_SEQUENCE:
    267     case TargetOpcode::IMPLICIT_DEF:
    268         break;
    269     }
    270 
    271   // Now see if there are no other dependencies
    272   // to instructions already in the packet.
    273   for (unsigned i = 0, e = Packet.size(); i != e; ++i)
    274     for (SUnit::const_succ_iterator I = Packet[i]->Succs.begin(),
    275          E = Packet[i]->Succs.end(); I != E; ++I) {
    276       // Since we do not add pseudos to packets, might as well
    277       // ignore order deps.
    278       if (I->isCtrl())
    279         continue;
    280 
    281       if (I->getSUnit() == SU)
    282         return false;
    283     }
    284 
    285   return true;
    286 }
    287 
    288 /// Keep track of available resources.
    289 void ResourcePriorityQueue::reserveResources(SUnit *SU) {
    290   // If this SU does not fit in the packet
    291   // start a new one.
    292   if (!isResourceAvailable(SU) || SU->getNode()->getGluedNode()) {
    293     ResourcesModel->clearResources();
    294     Packet.clear();
    295   }
    296 
    297   if (SU->getNode() && SU->getNode()->isMachineOpcode()) {
    298     switch (SU->getNode()->getMachineOpcode()) {
    299     default:
    300       ResourcesModel->reserveResources(&TII->get(
    301         SU->getNode()->getMachineOpcode()));
    302       break;
    303     case TargetOpcode::EXTRACT_SUBREG:
    304     case TargetOpcode::INSERT_SUBREG:
    305     case TargetOpcode::SUBREG_TO_REG:
    306     case TargetOpcode::REG_SEQUENCE:
    307     case TargetOpcode::IMPLICIT_DEF:
    308       break;
    309     }
    310     Packet.push_back(SU);
    311   }
    312   // Forcefully end packet for PseudoOps.
    313   else {
    314     ResourcesModel->clearResources();
    315     Packet.clear();
    316   }
    317 
    318   // If packet is now full, reset the state so in the next cycle
    319   // we start fresh.
    320   if (Packet.size() >= InstrItins->SchedModel.IssueWidth) {
    321     ResourcesModel->clearResources();
    322     Packet.clear();
    323   }
    324 }
    325 
    326 signed ResourcePriorityQueue::rawRegPressureDelta(SUnit *SU, unsigned RCId) {
    327   signed RegBalance    = 0;
    328 
    329   if (!SU || !SU->getNode() || !SU->getNode()->isMachineOpcode())
    330     return RegBalance;
    331 
    332   // Gen estimate.
    333   for (unsigned i = 0, e = SU->getNode()->getNumValues(); i != e; ++i) {
    334       MVT VT = SU->getNode()->getSimpleValueType(i);
    335       if (TLI->isTypeLegal(VT)
    336           && TLI->getRegClassFor(VT)
    337           && TLI->getRegClassFor(VT)->getID() == RCId)
    338         RegBalance += numberRCValSuccInSU(SU, RCId);
    339   }
    340   // Kill estimate.
    341   for (unsigned i = 0, e = SU->getNode()->getNumOperands(); i != e; ++i) {
    342       const SDValue &Op = SU->getNode()->getOperand(i);
    343       MVT VT = Op.getNode()->getSimpleValueType(Op.getResNo());
    344       if (isa<ConstantSDNode>(Op.getNode()))
    345         continue;
    346 
    347       if (TLI->isTypeLegal(VT) && TLI->getRegClassFor(VT)
    348           && TLI->getRegClassFor(VT)->getID() == RCId)
    349         RegBalance -= numberRCValPredInSU(SU, RCId);
    350   }
    351   return RegBalance;
    352 }
    353 
    354 /// Estimates change in reg pressure from this SU.
    355 /// It is achieved by trivial tracking of defined
    356 /// and used vregs in dependent instructions.
    357 /// The RawPressure flag makes this function to ignore
    358 /// existing reg file sizes, and report raw def/use
    359 /// balance.
    360 signed ResourcePriorityQueue::regPressureDelta(SUnit *SU, bool RawPressure) {
    361   signed RegBalance    = 0;
    362 
    363   if (!SU || !SU->getNode() || !SU->getNode()->isMachineOpcode())
    364     return RegBalance;
    365 
    366   if (RawPressure) {
    367     for (TargetRegisterInfo::regclass_iterator I = TRI->regclass_begin(),
    368              E = TRI->regclass_end(); I != E; ++I) {
    369       const TargetRegisterClass *RC = *I;
    370       RegBalance += rawRegPressureDelta(SU, RC->getID());
    371     }
    372   }
    373   else {
    374     for (TargetRegisterInfo::regclass_iterator I = TRI->regclass_begin(),
    375          E = TRI->regclass_end(); I != E; ++I) {
    376       const TargetRegisterClass *RC = *I;
    377       if ((RegPressure[RC->getID()] +
    378            rawRegPressureDelta(SU, RC->getID()) > 0) &&
    379           (RegPressure[RC->getID()] +
    380            rawRegPressureDelta(SU, RC->getID())  >= RegLimit[RC->getID()]))
    381         RegBalance += rawRegPressureDelta(SU, RC->getID());
    382     }
    383   }
    384 
    385   return RegBalance;
    386 }
    387 
    388 // Constants used to denote relative importance of
    389 // heuristic components for cost computation.
    390 static const unsigned PriorityOne = 200;
    391 static const unsigned PriorityTwo = 50;
    392 static const unsigned PriorityThree = 15;
    393 static const unsigned PriorityFour = 5;
    394 static const unsigned ScaleOne = 20;
    395 static const unsigned ScaleTwo = 10;
    396 static const unsigned ScaleThree = 5;
    397 static const unsigned FactorOne = 2;
    398 
    399 /// Returns single number reflecting benefit of scheduling SU
    400 /// in the current cycle.
    401 signed ResourcePriorityQueue::SUSchedulingCost(SUnit *SU) {
    402   // Initial trivial priority.
    403   signed ResCount = 1;
    404 
    405   // Do not waste time on a node that is already scheduled.
    406   if (SU->isScheduled)
    407     return ResCount;
    408 
    409   // Forced priority is high.
    410   if (SU->isScheduleHigh)
    411     ResCount += PriorityOne;
    412 
    413   // Adaptable scheduling
    414   // A small, but very parallel
    415   // region, where reg pressure is an issue.
    416   if (HorizontalVerticalBalance > RegPressureThreshold) {
    417     // Critical path first
    418     ResCount += (SU->getHeight() * ScaleTwo);
    419     // If resources are available for it, multiply the
    420     // chance of scheduling.
    421     if (isResourceAvailable(SU))
    422       ResCount <<= FactorOne;
    423 
    424     // Consider change to reg pressure from scheduling
    425     // this SU.
    426     ResCount -= (regPressureDelta(SU,true) * ScaleOne);
    427   }
    428   // Default heuristic, greeady and
    429   // critical path driven.
    430   else {
    431     // Critical path first.
    432     ResCount += (SU->getHeight() * ScaleTwo);
    433     // Now see how many instructions is blocked by this SU.
    434     ResCount += (NumNodesSolelyBlocking[SU->NodeNum] * ScaleTwo);
    435     // If resources are available for it, multiply the
    436     // chance of scheduling.
    437     if (isResourceAvailable(SU))
    438       ResCount <<= FactorOne;
    439 
    440     ResCount -= (regPressureDelta(SU) * ScaleTwo);
    441   }
    442 
    443   // These are platform-specific things.
    444   // Will need to go into the back end
    445   // and accessed from here via a hook.
    446   for (SDNode *N = SU->getNode(); N; N = N->getGluedNode()) {
    447     if (N->isMachineOpcode()) {
    448       const MCInstrDesc &TID = TII->get(N->getMachineOpcode());
    449       if (TID.isCall())
    450         ResCount += (PriorityTwo + (ScaleThree*N->getNumValues()));
    451     }
    452     else
    453       switch (N->getOpcode()) {
    454       default:  break;
    455       case ISD::TokenFactor:
    456       case ISD::CopyFromReg:
    457       case ISD::CopyToReg:
    458         ResCount += PriorityFour;
    459         break;
    460 
    461       case ISD::INLINEASM:
    462         ResCount += PriorityThree;
    463         break;
    464       }
    465   }
    466   return ResCount;
    467 }
    468 
    469 
    470 /// Main resource tracking point.
    471 void ResourcePriorityQueue::scheduledNode(SUnit *SU) {
    472   // Use NULL entry as an event marker to reset
    473   // the DFA state.
    474   if (!SU) {
    475     ResourcesModel->clearResources();
    476     Packet.clear();
    477     return;
    478   }
    479 
    480   const SDNode *ScegN = SU->getNode();
    481   // Update reg pressure tracking.
    482   // First update current node.
    483   if (ScegN->isMachineOpcode()) {
    484     // Estimate generated regs.
    485     for (unsigned i = 0, e = ScegN->getNumValues(); i != e; ++i) {
    486       MVT VT = ScegN->getSimpleValueType(i);
    487 
    488       if (TLI->isTypeLegal(VT)) {
    489         const TargetRegisterClass *RC = TLI->getRegClassFor(VT);
    490         if (RC)
    491           RegPressure[RC->getID()] += numberRCValSuccInSU(SU, RC->getID());
    492       }
    493     }
    494     // Estimate killed regs.
    495     for (unsigned i = 0, e = ScegN->getNumOperands(); i != e; ++i) {
    496       const SDValue &Op = ScegN->getOperand(i);
    497       MVT VT = Op.getNode()->getSimpleValueType(Op.getResNo());
    498 
    499       if (TLI->isTypeLegal(VT)) {
    500         const TargetRegisterClass *RC = TLI->getRegClassFor(VT);
    501         if (RC) {
    502           if (RegPressure[RC->getID()] >
    503             (numberRCValPredInSU(SU, RC->getID())))
    504             RegPressure[RC->getID()] -= numberRCValPredInSU(SU, RC->getID());
    505           else RegPressure[RC->getID()] = 0;
    506         }
    507       }
    508     }
    509     for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
    510                               I != E; ++I) {
    511       if (I->isCtrl() || (I->getSUnit()->NumRegDefsLeft == 0))
    512         continue;
    513       --I->getSUnit()->NumRegDefsLeft;
    514     }
    515   }
    516 
    517   // Reserve resources for this SU.
    518   reserveResources(SU);
    519 
    520   // Adjust number of parallel live ranges.
    521   // Heuristic is simple - node with no data successors reduces
    522   // number of live ranges. All others, increase it.
    523   unsigned NumberNonControlDeps = 0;
    524 
    525   for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
    526                                   I != E; ++I) {
    527     adjustPriorityOfUnscheduledPreds(I->getSUnit());
    528     if (!I->isCtrl())
    529       NumberNonControlDeps++;
    530   }
    531 
    532   if (!NumberNonControlDeps) {
    533     if (ParallelLiveRanges >= SU->NumPreds)
    534       ParallelLiveRanges -= SU->NumPreds;
    535     else
    536       ParallelLiveRanges = 0;
    537 
    538   }
    539   else
    540     ParallelLiveRanges += SU->NumRegDefsLeft;
    541 
    542   // Track parallel live chains.
    543   HorizontalVerticalBalance += (SU->Succs.size() - numberCtrlDepsInSU(SU));
    544   HorizontalVerticalBalance -= (SU->Preds.size() - numberCtrlPredInSU(SU));
    545 }
    546 
    547 void ResourcePriorityQueue::initNumRegDefsLeft(SUnit *SU) {
    548   unsigned  NodeNumDefs = 0;
    549   for (SDNode *N = SU->getNode(); N; N = N->getGluedNode())
    550     if (N->isMachineOpcode()) {
    551       const MCInstrDesc &TID = TII->get(N->getMachineOpcode());
    552       // No register need be allocated for this.
    553       if (N->getMachineOpcode() == TargetOpcode::IMPLICIT_DEF) {
    554         NodeNumDefs = 0;
    555         break;
    556       }
    557       NodeNumDefs = std::min(N->getNumValues(), TID.getNumDefs());
    558     }
    559     else
    560       switch(N->getOpcode()) {
    561         default:     break;
    562         case ISD::CopyFromReg:
    563           NodeNumDefs++;
    564           break;
    565         case ISD::INLINEASM:
    566           NodeNumDefs++;
    567           break;
    568       }
    569 
    570   SU->NumRegDefsLeft = NodeNumDefs;
    571 }
    572 
    573 /// adjustPriorityOfUnscheduledPreds - One of the predecessors of SU was just
    574 /// scheduled.  If SU is not itself available, then there is at least one
    575 /// predecessor node that has not been scheduled yet.  If SU has exactly ONE
    576 /// unscheduled predecessor, we want to increase its priority: it getting
    577 /// scheduled will make this node available, so it is better than some other
    578 /// node of the same priority that will not make a node available.
    579 void ResourcePriorityQueue::adjustPriorityOfUnscheduledPreds(SUnit *SU) {
    580   if (SU->isAvailable) return;  // All preds scheduled.
    581 
    582   SUnit *OnlyAvailablePred = getSingleUnscheduledPred(SU);
    583   if (!OnlyAvailablePred || !OnlyAvailablePred->isAvailable)
    584     return;
    585 
    586   // Okay, we found a single predecessor that is available, but not scheduled.
    587   // Since it is available, it must be in the priority queue.  First remove it.
    588   remove(OnlyAvailablePred);
    589 
    590   // Reinsert the node into the priority queue, which recomputes its
    591   // NumNodesSolelyBlocking value.
    592   push(OnlyAvailablePred);
    593 }
    594 
    595 
    596 /// Main access point - returns next instructions
    597 /// to be placed in scheduling sequence.
    598 SUnit *ResourcePriorityQueue::pop() {
    599   if (empty())
    600     return nullptr;
    601 
    602   std::vector<SUnit *>::iterator Best = Queue.begin();
    603   if (!DisableDFASched) {
    604     signed BestCost = SUSchedulingCost(*Best);
    605     for (std::vector<SUnit *>::iterator I = std::next(Queue.begin()),
    606            E = Queue.end(); I != E; ++I) {
    607 
    608       if (SUSchedulingCost(*I) > BestCost) {
    609         BestCost = SUSchedulingCost(*I);
    610         Best = I;
    611       }
    612     }
    613   }
    614   // Use default TD scheduling mechanism.
    615   else {
    616     for (std::vector<SUnit *>::iterator I = std::next(Queue.begin()),
    617        E = Queue.end(); I != E; ++I)
    618       if (Picker(*Best, *I))
    619         Best = I;
    620   }
    621 
    622   SUnit *V = *Best;
    623   if (Best != std::prev(Queue.end()))
    624     std::swap(*Best, Queue.back());
    625 
    626   Queue.pop_back();
    627 
    628   return V;
    629 }
    630 
    631 
    632 void ResourcePriorityQueue::remove(SUnit *SU) {
    633   assert(!Queue.empty() && "Queue is empty!");
    634   std::vector<SUnit *>::iterator I = std::find(Queue.begin(), Queue.end(), SU);
    635   if (I != std::prev(Queue.end()))
    636     std::swap(*I, Queue.back());
    637 
    638   Queue.pop_back();
    639 }
    640