//===- ScheduleDAGRRList.cpp - Reg pressure reduction list scheduler ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This implements bottom-up and top-down register pressure reduction list
// schedulers, using standard algorithms.  The basic approach uses a priority
// queue of available nodes to schedule.  One at a time, nodes are taken from
// the priority queue (thus in priority order), checked for legality to
// schedule, and emitted if legal.
//
//===----------------------------------------------------------------------===//

#include "ScheduleDAGSDNodes.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/CodeGen/ScheduleDAG.h"
#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <iterator>
#include <limits>
#include <memory>
#include <utility>
#include <vector>

using namespace llvm;

#define DEBUG_TYPE "pre-RA-sched"

STATISTIC(NumBacktracks, "Number of times scheduler backtracked");
STATISTIC(NumUnfolds,    "Number of nodes unfolded");
STATISTIC(NumDups,       "Number of duplicated nodes");
STATISTIC(NumPRCopies,   "Number of physical register copies");

static RegisterScheduler
  burrListDAGScheduler("list-burr",
                       "Bottom-up register reduction list scheduling",
                       createBURRListDAGScheduler);

static RegisterScheduler
  sourceListDAGScheduler("source",
                         "Similar to list-burr but schedules in source "
                         "order when possible",
                         createSourceListDAGScheduler);

static RegisterScheduler
  hybridListDAGScheduler("list-hybrid",
                         "Bottom-up register pressure aware list scheduling "
                         "which tries to balance latency and register pressure",
                         createHybridListDAGScheduler);

static RegisterScheduler
  ILPListDAGScheduler("list-ilp",
                      "Bottom-up register pressure aware list scheduling "
                      "which tries to balance ILP and register pressure",
                      createILPListDAGScheduler);

static cl::opt<bool> DisableSchedCycles(
  "disable-sched-cycles", cl::Hidden, cl::init(false),
  cl::desc("Disable cycle-level precision during preRA scheduling"));

// Temporary sched=list-ilp flags until the heuristics are robust.
// Some options are also available under sched=list-hybrid.
static cl::opt<bool> DisableSchedRegPressure(
  "disable-sched-reg-pressure", cl::Hidden, cl::init(false),
  cl::desc("Disable regpressure priority in sched=list-ilp"));
static cl::opt<bool> DisableSchedLiveUses(
  "disable-sched-live-uses", cl::Hidden, cl::init(true),
  cl::desc("Disable live use priority in sched=list-ilp"));
static cl::opt<bool> DisableSchedVRegCycle(
  "disable-sched-vrcycle", cl::Hidden, cl::init(false),
  cl::desc("Disable virtual register cycle interference checks"));
static cl::opt<bool> DisableSchedPhysRegJoin(
  "disable-sched-physreg-join", cl::Hidden, cl::init(false),
  cl::desc("Disable physreg def-use affinity"));
static cl::opt<bool> DisableSchedStalls(
  "disable-sched-stalls", cl::Hidden, cl::init(true),
  cl::desc("Disable no-stall priority in sched=list-ilp"));
static cl::opt<bool> DisableSchedCriticalPath(
  "disable-sched-critical-path", cl::Hidden, cl::init(false),
  cl::desc("Disable critical path priority in sched=list-ilp"));
static cl::opt<bool> DisableSchedHeight(
  "disable-sched-height", cl::Hidden, cl::init(false),
  cl::desc("Disable scheduled-height priority in sched=list-ilp"));
static cl::opt<bool> Disable2AddrHack(
  "disable-2addr-hack", cl::Hidden, cl::init(true),
  cl::desc("Disable scheduler's two-address hack"));

static cl::opt<int> MaxReorderWindow(
  "max-sched-reorder", cl::Hidden, cl::init(6),
  cl::desc("Number of instructions to allow ahead of the critical path "
           "in sched=list-ilp"));

static cl::opt<unsigned> AvgIPC(
  "sched-avg-ipc", cl::Hidden, cl::init(1),
  cl::desc("Average inst/cycle whan no target itinerary exists."));

namespace {

//===----------------------------------------------------------------------===//
/// ScheduleDAGRRList - The actual register reduction list scheduler
/// implementation.  This supports both top-down and bottom-up scheduling.
///
class ScheduleDAGRRList : public ScheduleDAGSDNodes {
private:
  /// NeedLatency - True if the scheduler will make use of latency information.
  bool NeedLatency;

  /// AvailableQueue - The priority queue to use for the available SUnits.
  SchedulingPriorityQueue *AvailableQueue;

  /// PendingQueue - This contains all of the instructions whose operands have
  /// been issued, but their results are not ready yet (due to the latency of
  /// the operation).  Once the operands becomes available, the instruction is
  /// added to the AvailableQueue.
  std::vector<SUnit *> PendingQueue;

  /// HazardRec - The hazard recognizer to use.
  ScheduleHazardRecognizer *HazardRec;

  /// CurCycle - The current scheduler state corresponds to this cycle.
  unsigned CurCycle = 0;

  /// MinAvailableCycle - Cycle of the soonest available instruction.
  unsigned MinAvailableCycle;

  /// IssueCount - Count instructions issued in this cycle
  /// Currently valid only for bottom-up scheduling.
  unsigned IssueCount;

  /// LiveRegDefs - A set of physical registers and their definition
  /// that are "live". These nodes must be scheduled before any other nodes that
  /// modifies the registers can be scheduled.
  unsigned NumLiveRegs;
  std::unique_ptr<SUnit*[]> LiveRegDefs;
  std::unique_ptr<SUnit*[]> LiveRegGens;

  // Collect interferences between physical register use/defs.
  // Each interference is an SUnit and set of physical registers.
  SmallVector<SUnit*, 4> Interferences;

  using LRegsMapT = DenseMap<SUnit *, SmallVector<unsigned, 4>>;

  LRegsMapT LRegsMap;

  /// Topo - A topological ordering for SUnits which permits fast IsReachable
  /// and similar queries.
  ScheduleDAGTopologicalSort Topo;

  // Hack to keep track of the inverse of FindCallSeqStart without more crazy
  // DAG crawling.
  DenseMap<SUnit*, SUnit*> CallSeqEndForStart;

public:
  ScheduleDAGRRList(MachineFunction &mf, bool needlatency,
                    SchedulingPriorityQueue *availqueue,
                    CodeGenOpt::Level OptLevel)
    : ScheduleDAGSDNodes(mf),
      NeedLatency(needlatency), AvailableQueue(availqueue),
      Topo(SUnits, nullptr) {
    const TargetSubtargetInfo &STI = mf.getSubtarget();
    if (DisableSchedCycles || !NeedLatency)
      HazardRec = new ScheduleHazardRecognizer();
    else
      HazardRec = STI.getInstrInfo()->CreateTargetHazardRecognizer(&STI, this);
  }

  ~ScheduleDAGRRList() override {
    delete HazardRec;
    delete AvailableQueue;
  }

  void Schedule() override;

  ScheduleHazardRecognizer *getHazardRec() { return HazardRec; }

  /// IsReachable - Checks if SU is reachable from TargetSU.
  bool IsReachable(const SUnit *SU, const SUnit *TargetSU) {
    return Topo.IsReachable(SU, TargetSU);
  }

  /// WillCreateCycle - Returns true if adding an edge from SU to TargetSU will
  /// create a cycle.
  bool WillCreateCycle(SUnit *SU, SUnit *TargetSU) {
    return Topo.WillCreateCycle(SU, TargetSU);
  }

  /// AddPred - adds a predecessor edge to SUnit SU.
  /// This returns true if this is a new predecessor.
  /// Updates the topological ordering if required.
  void AddPred(SUnit *SU, const SDep &D) {
    Topo.AddPred(SU, D.getSUnit());
    SU->addPred(D);
  }

  /// RemovePred - removes a predecessor edge from SUnit SU.
  /// This returns true if an edge was removed.
  /// Updates the topological ordering if required.
  void RemovePred(SUnit *SU, const SDep &D) {
    Topo.RemovePred(SU, D.getSUnit());
    SU->removePred(D);
  }

private:
  bool isReady(SUnit *SU) {
    return DisableSchedCycles || !AvailableQueue->hasReadyFilter() ||
      AvailableQueue->isReady(SU);
  }

  void ReleasePred(SUnit *SU, const SDep *PredEdge);
  void ReleasePredecessors(SUnit *SU);
  void ReleasePending();
  void AdvanceToCycle(unsigned NextCycle);
  void AdvancePastStalls(SUnit *SU);
  void EmitNode(SUnit *SU);
  void ScheduleNodeBottomUp(SUnit*);
  void CapturePred(SDep *PredEdge);
  void UnscheduleNodeBottomUp(SUnit*);
  void RestoreHazardCheckerBottomUp();
  void BacktrackBottomUp(SUnit*, SUnit*);
  SUnit *TryUnfoldSU(SUnit *);
  SUnit *CopyAndMoveSuccessors(SUnit*);
  void InsertCopiesAndMoveSuccs(SUnit*, unsigned,
                                const TargetRegisterClass*,
                                const TargetRegisterClass*,
                                SmallVectorImpl<SUnit*>&);
  bool DelayForLiveRegsBottomUp(SUnit*, SmallVectorImpl<unsigned>&);

  void releaseInterferences(unsigned Reg = 0);

  SUnit *PickNodeToScheduleBottomUp();
  void ListScheduleBottomUp();

  /// CreateNewSUnit - Creates a new SUnit and returns a pointer to it.
  /// Updates the topological ordering if required.
  SUnit *CreateNewSUnit(SDNode *N) {
    unsigned NumSUnits = SUnits.size();
    SUnit *NewNode = newSUnit(N);
    // Update the topological ordering.
    if (NewNode->NodeNum >= NumSUnits)
      Topo.InitDAGTopologicalSorting();
    return NewNode;
  }

  /// CreateClone - Creates a new SUnit from an existing one.
  /// Updates the topological ordering if required.
  SUnit *CreateClone(SUnit *N) {
    unsigned NumSUnits = SUnits.size();
    SUnit *NewNode = Clone(N);
    // Update the topological ordering.
    if (NewNode->NodeNum >= NumSUnits)
      Topo.InitDAGTopologicalSorting();
    return NewNode;
  }

  /// forceUnitLatencies - Register-pressure-reducing scheduling doesn't
  /// need actual latency information but the hybrid scheduler does.
  bool forceUnitLatencies() const override {
    return !NeedLatency;
  }
};

}  // end anonymous namespace

/// GetCostForDef - Looks up the register class and cost for a given definition.
/// Typically this just means looking up the representative register class,
/// but for untyped values (MVT::Untyped) it means inspecting the node's
/// opcode to determine what register class is being generated.
static void GetCostForDef(const ScheduleDAGSDNodes::RegDefIter &RegDefPos,
                          const TargetLowering *TLI,
                          const TargetInstrInfo *TII,
                          const TargetRegisterInfo *TRI,
                          unsigned &RegClass, unsigned &Cost,
                          const MachineFunction &MF) {
  MVT VT = RegDefPos.GetValue();

  // Special handling for untyped values.  These values can only come from
  // the expansion of custom DAG-to-DAG patterns.
  if (VT == MVT::Untyped) {
    const SDNode *Node = RegDefPos.GetNode();

    // Special handling for CopyFromReg of untyped values.
    if (!Node->isMachineOpcode() && Node->getOpcode() == ISD::CopyFromReg) {
      unsigned Reg = cast<RegisterSDNode>(Node->getOperand(1))->getReg();
      const TargetRegisterClass *RC = MF.getRegInfo().getRegClass(Reg);
      RegClass = RC->getID();
      Cost = 1;
      return;
    }

    unsigned Opcode = Node->getMachineOpcode();
    if (Opcode == TargetOpcode::REG_SEQUENCE) {
      unsigned DstRCIdx = cast<ConstantSDNode>(Node->getOperand(0))->getZExtValue();
      const TargetRegisterClass *RC = TRI->getRegClass(DstRCIdx);
      RegClass = RC->getID();
      Cost = 1;
      return;
    }

    unsigned Idx = RegDefPos.GetIdx();
    const MCInstrDesc Desc = TII->get(Opcode);
    const TargetRegisterClass *RC = TII->getRegClass(Desc, Idx, TRI, MF);
    RegClass = RC->getID();
    // FIXME: Cost arbitrarily set to 1 because there doesn't seem to be a
    // better way to determine it.
    Cost = 1;
  } else {
    RegClass = TLI->getRepRegClassFor(VT)->getID();
    Cost = TLI->getRepRegClassCostFor(VT);
  }
}

/// Schedule - Schedule the DAG using list scheduling.
void ScheduleDAGRRList::Schedule() {
  DEBUG(dbgs() << "********** List Scheduling " << printMBBReference(*BB)
               << " '" << BB->getName() << "' **********\n");

  CurCycle = 0;
  IssueCount = 0;
  MinAvailableCycle =
      DisableSchedCycles ? 0 : std::numeric_limits<unsigned>::max();
  NumLiveRegs = 0;
  // Allocate slots for each physical register, plus one for a special register
  // to track the virtual resource of a calling sequence.
  LiveRegDefs.reset(new SUnit*[TRI->getNumRegs() + 1]());
  LiveRegGens.reset(new SUnit*[TRI->getNumRegs() + 1]());
  CallSeqEndForStart.clear();
  assert(Interferences.empty() && LRegsMap.empty() && "stale Interferences");

  // Build the scheduling graph.
  BuildSchedGraph(nullptr);

  DEBUG(for (SUnit &SU : SUnits)
          SU.dumpAll(this));
  Topo.InitDAGTopologicalSorting();

  AvailableQueue->initNodes(SUnits);

  HazardRec->Reset();

  // Execute the actual scheduling loop.
  ListScheduleBottomUp();

  AvailableQueue->releaseState();

  DEBUG({
      dbgs() << "*** Final schedule ***\n";
      dumpSchedule();
      dbgs() << '\n';
    });
}

//===----------------------------------------------------------------------===//
//  Bottom-Up Scheduling
//===----------------------------------------------------------------------===//

/// ReleasePred - Decrement the NumSuccsLeft count of a predecessor. Add it to
/// the AvailableQueue if the count reaches zero. Also update its cycle bound.
void ScheduleDAGRRList::ReleasePred(SUnit *SU, const SDep *PredEdge) {
  SUnit *PredSU = PredEdge->getSUnit();

#ifndef NDEBUG
  if (PredSU->NumSuccsLeft == 0) {
    dbgs() << "*** Scheduling failed! ***\n";
    PredSU->dump(this);
    dbgs() << " has been released too many times!\n";
    llvm_unreachable(nullptr);
  }
#endif
  --PredSU->NumSuccsLeft;

  if (!forceUnitLatencies()) {
    // Updating predecessor's height. This is now the cycle when the
    // predecessor can be scheduled without causing a pipeline stall.
    PredSU->setHeightToAtLeast(SU->getHeight() + PredEdge->getLatency());
  }

  // If all the node's successors are scheduled, this node is ready
  // to be scheduled. Ignore the special EntrySU node.
  if (PredSU->NumSuccsLeft == 0 && PredSU != &EntrySU) {
    PredSU->isAvailable = true;

    unsigned Height = PredSU->getHeight();
    if (Height < MinAvailableCycle)
      MinAvailableCycle = Height;

    if (isReady(PredSU)) {
      AvailableQueue->push(PredSU);
    }
    // CapturePred and others may have left the node in the pending queue, avoid
    // adding it twice.
    else if (!PredSU->isPending) {
      PredSU->isPending = true;
      PendingQueue.push_back(PredSU);
    }
  }
}

/// IsChainDependent - Test if Outer is reachable from Inner through
/// chain dependencies.
static bool IsChainDependent(SDNode *Outer, SDNode *Inner,
                             unsigned NestLevel,
                             const TargetInstrInfo *TII) {
  SDNode *N = Outer;
  while (true) {
    if (N == Inner)
      return true;
    // For a TokenFactor, examine each operand. There may be multiple ways
    // to get to the CALLSEQ_BEGIN, but we need to find the path with the
    // most nesting in order to ensure that we find the corresponding match.
    if (N->getOpcode() == ISD::TokenFactor) {
      for (const SDValue &Op : N->op_values())
        if (IsChainDependent(Op.getNode(), Inner, NestLevel, TII))
          return true;
      return false;
    }
    // Check for a lowered CALLSEQ_BEGIN or CALLSEQ_END.
    if (N->isMachineOpcode()) {
      if (N->getMachineOpcode() == TII->getCallFrameDestroyOpcode()) {
        ++NestLevel;
      } else if (N->getMachineOpcode() == TII->getCallFrameSetupOpcode()) {
        if (NestLevel == 0)
          return false;
        --NestLevel;
      }
    }
    // Otherwise, find the chain and continue climbing.
    for (const SDValue &Op : N->op_values())
      if (Op.getValueType() == MVT::Other) {
        N = Op.getNode();
        goto found_chain_operand;
      }
    return false;
  found_chain_operand:;
    if (N->getOpcode() == ISD::EntryToken)
      return false;
  }
}

/// FindCallSeqStart - Starting from the (lowered) CALLSEQ_END node, locate
/// the corresponding (lowered) CALLSEQ_BEGIN node.
///
/// NestLevel and MaxNested are used in recursion to indcate the current level
/// of nesting of CALLSEQ_BEGIN and CALLSEQ_END pairs, as well as the maximum
/// level seen so far.
///
/// TODO: It would be better to give CALLSEQ_END an explicit operand to point
/// to the corresponding CALLSEQ_BEGIN to avoid needing to search for it.
static SDNode *
FindCallSeqStart(SDNode *N, unsigned &NestLevel, unsigned &MaxNest,
                 const TargetInstrInfo *TII) {
  while (true) {
    // For a TokenFactor, examine each operand. There may be multiple ways
    // to get to the CALLSEQ_BEGIN, but we need to find the path with the
    // most nesting in order to ensure that we find the corresponding match.
    if (N->getOpcode() == ISD::TokenFactor) {
      SDNode *Best = nullptr;
      unsigned BestMaxNest = MaxNest;
      for (const SDValue &Op : N->op_values()) {
        unsigned MyNestLevel = NestLevel;
        unsigned MyMaxNest = MaxNest;
        if (SDNode *New = FindCallSeqStart(Op.getNode(),
                                           MyNestLevel, MyMaxNest, TII))
          if (!Best || (MyMaxNest > BestMaxNest)) {
            Best = New;
            BestMaxNest = MyMaxNest;
          }
      }
      assert(Best);
      MaxNest = BestMaxNest;
      return Best;
    }
    // Check for a lowered CALLSEQ_BEGIN or CALLSEQ_END.
    if (N->isMachineOpcode()) {
      if (N->getMachineOpcode() == TII->getCallFrameDestroyOpcode()) {
        ++NestLevel;
        MaxNest = std::max(MaxNest, NestLevel);
      } else if (N->getMachineOpcode() == TII->getCallFrameSetupOpcode()) {
        assert(NestLevel != 0);
        --NestLevel;
        if (NestLevel == 0)
          return N;
      }
    }
    // Otherwise, find the chain and continue climbing.
    for (const SDValue &Op : N->op_values())
      if (Op.getValueType() == MVT::Other) {
        N = Op.getNode();
        goto found_chain_operand;
      }
    return nullptr;
  found_chain_operand:;
    if (N->getOpcode() == ISD::EntryToken)
      return nullptr;
  }
}

/// Call ReleasePred for each predecessor, then update register live def/gen.
/// Always update LiveRegDefs for a register dependence even if the current SU
/// also defines the register. This effectively create one large live range
/// across a sequence of two-address node. This is important because the
/// entire chain must be scheduled together. Example:
///
/// flags = (3) add
/// flags = (2) addc flags
/// flags = (1) addc flags
///
/// results in
///
/// LiveRegDefs[flags] = 3
/// LiveRegGens[flags] = 1
///
/// If (2) addc is unscheduled, then (1) addc must also be unscheduled to avoid
/// interference on flags.
void ScheduleDAGRRList::ReleasePredecessors(SUnit *SU) {
  // Bottom up: release predecessors
  for (SDep &Pred : SU->Preds) {
    ReleasePred(SU, &Pred);
    if (Pred.isAssignedRegDep()) {
      // This is a physical register dependency and it's impossible or
      // expensive to copy the register. Make sure nothing that can
      // clobber the register is scheduled between the predecessor and
      // this node.
      SUnit *RegDef = LiveRegDefs[Pred.getReg()]; (void)RegDef;
      assert((!RegDef || RegDef == SU || RegDef == Pred.getSUnit()) &&
             "interference on register dependence");
      LiveRegDefs[Pred.getReg()] = Pred.getSUnit();
      if (!LiveRegGens[Pred.getReg()]) {
        ++NumLiveRegs;
        LiveRegGens[Pred.getReg()] = SU;
      }
    }
  }

  // If we're scheduling a lowered CALLSEQ_END, find the corresponding
  // CALLSEQ_BEGIN. Inject an artificial physical register dependence between
  // these nodes, to prevent other calls from being interscheduled with them.
  unsigned CallResource = TRI->getNumRegs();
  if (!LiveRegDefs[CallResource])
    for (SDNode *Node = SU->getNode(); Node; Node = Node->getGluedNode())
      if (Node->isMachineOpcode() &&
          Node->getMachineOpcode() == TII->getCallFrameDestroyOpcode()) {
        unsigned NestLevel = 0;
        unsigned MaxNest = 0;
        SDNode *N = FindCallSeqStart(Node, NestLevel, MaxNest, TII);
        assert(N && "Must find call sequence start");

        SUnit *Def = &SUnits[N->getNodeId()];
        CallSeqEndForStart[Def] = SU;

        ++NumLiveRegs;
        LiveRegDefs[CallResource] = Def;
        LiveRegGens[CallResource] = SU;
        break;
      }
}

/// Check to see if any of the pending instructions are ready to issue.  If
/// so, add them to the available queue.
void ScheduleDAGRRList::ReleasePending() {
  if (DisableSchedCycles) {
    assert(PendingQueue.empty() && "pending instrs not allowed in this mode");
    return;
  }

  // If the available queue is empty, it is safe to reset MinAvailableCycle.
  if (AvailableQueue->empty())
    MinAvailableCycle = std::numeric_limits<unsigned>::max();

  // Check to see if any of the pending instructions are ready to issue.  If
  // so, add them to the available queue.
  for (unsigned i = 0, e = PendingQueue.size(); i != e; ++i) {
    unsigned ReadyCycle = PendingQueue[i]->getHeight();
    if (ReadyCycle < MinAvailableCycle)
      MinAvailableCycle = ReadyCycle;

    if (PendingQueue[i]->isAvailable) {
      if (!isReady(PendingQueue[i]))
          continue;
      AvailableQueue->push(PendingQueue[i]);
    }
    PendingQueue[i]->isPending = false;
    PendingQueue[i] = PendingQueue.back();
    PendingQueue.pop_back();
    --i; --e;
  }
}

/// Move the scheduler state forward by the specified number of Cycles.
void ScheduleDAGRRList::AdvanceToCycle(unsigned NextCycle) {
  if (NextCycle <= CurCycle)
    return;

  IssueCount = 0;
  AvailableQueue->setCurCycle(NextCycle);
  if (!HazardRec->isEnabled()) {
    // Bypass lots of virtual calls in case of long latency.
    CurCycle = NextCycle;
  }
  else {
    for (; CurCycle != NextCycle; ++CurCycle) {
      HazardRec->RecedeCycle();
    }
  }
  // FIXME: Instead of visiting the pending Q each time, set a dirty flag on the
  // available Q to release pending nodes at least once before popping.
  ReleasePending();
}

/// Move the scheduler state forward until the specified node's dependents are
/// ready and can be scheduled with no resource conflicts.
void ScheduleDAGRRList::AdvancePastStalls(SUnit *SU) {
  if (DisableSchedCycles)
    return;

  // FIXME: Nodes such as CopyFromReg probably should not advance the current
  // cycle. Otherwise, we can wrongly mask real stalls. If the non-machine node
  // has predecessors the cycle will be advanced when they are scheduled.
  // But given the crude nature of modeling latency though such nodes, we
  // currently need to treat these nodes like real instructions.
  // if (!SU->getNode() || !SU->getNode()->isMachineOpcode()) return;

  unsigned ReadyCycle = SU->getHeight();

  // Bump CurCycle to account for latency. We assume the latency of other
  // available instructions may be hidden by the stall (not a full pipe stall).
  // This updates the hazard recognizer's cycle before reserving resources for
  // this instruction.
  AdvanceToCycle(ReadyCycle);

  // Calls are scheduled in their preceding cycle, so don't conflict with
  // hazards from instructions after the call. EmitNode will reset the
  // scoreboard state before emitting the call.
  if (SU->isCall)
    return;

  // FIXME: For resource conflicts in very long non-pipelined stages, we
  // should probably skip ahead here to avoid useless scoreboard checks.
  int Stalls = 0;
  while (true) {
    ScheduleHazardRecognizer::HazardType HT =
      HazardRec->getHazardType(SU, -Stalls);

    if (HT == ScheduleHazardRecognizer::NoHazard)
      break;

    ++Stalls;
  }
  AdvanceToCycle(CurCycle + Stalls);
}

/// Record this SUnit in the HazardRecognizer.
/// Does not update CurCycle.
void ScheduleDAGRRList::EmitNode(SUnit *SU) {
  if (!HazardRec->isEnabled())
    return;

  // Check for phys reg copy.
  if (!SU->getNode())
    return;

  switch (SU->getNode()->getOpcode()) {
  default:
    assert(SU->getNode()->isMachineOpcode() &&
           "This target-independent node should not be scheduled.");
    break;
  case ISD::MERGE_VALUES:
  case ISD::TokenFactor:
  case ISD::LIFETIME_START:
  case ISD::LIFETIME_END:
  case ISD::CopyToReg:
  case ISD::CopyFromReg:
  case ISD::EH_LABEL:
    // Noops don't affect the scoreboard state. Copies are likely to be
    // removed.
    return;
  case ISD::INLINEASM:
    // For inline asm, clear the pipeline state.
    HazardRec->Reset();
    return;
  }
  if (SU->isCall) {
    // Calls are scheduled with their preceding instructions. For bottom-up
    // scheduling, clear the pipeline state before emitting.
    HazardRec->Reset();
  }

  HazardRec->EmitInstruction(SU);
}

static void resetVRegCycle(SUnit *SU);

/// ScheduleNodeBottomUp - Add the node to the schedule. Decrement the pending
/// count of its predecessors. If a predecessor pending count is zero, add it to
/// the Available queue.
void ScheduleDAGRRList::ScheduleNodeBottomUp(SUnit *SU) {
  DEBUG(dbgs() << "\n*** Scheduling [" << CurCycle << "]: ");
  DEBUG(SU->dump(this));

#ifndef NDEBUG
  if (CurCycle < SU->getHeight())
    DEBUG(dbgs() << "   Height [" << SU->getHeight()
          << "] pipeline stall!\n");
#endif

  // FIXME: Do not modify node height. It may interfere with
  // backtracking. Instead add a "ready cycle" to SUnit. Before scheduling the
  // node its ready cycle can aid heuristics, and after scheduling it can
  // indicate the scheduled cycle.
  SU->setHeightToAtLeast(CurCycle);

  // Reserve resources for the scheduled instruction.
  EmitNode(SU);

  Sequence.push_back(SU);

  AvailableQueue->scheduledNode(SU);

  // If HazardRec is disabled, and each inst counts as one cycle, then
  // advance CurCycle before ReleasePredecessors to avoid useless pushes to
  // PendingQueue for schedulers that implement HasReadyFilter.
  if (!HazardRec->isEnabled() && AvgIPC < 2)
    AdvanceToCycle(CurCycle + 1);

  // Update liveness of predecessors before successors to avoid treating a
  // two-address node as a live range def.
  ReleasePredecessors(SU);

  // Release all the implicit physical register defs that are live.
  for (SDep &Succ : SU->Succs) {
    // LiveRegDegs[Succ.getReg()] != SU when SU is a two-address node.
    if (Succ.isAssignedRegDep() && LiveRegDefs[Succ.getReg()] == SU) {
      assert(NumLiveRegs > 0 && "NumLiveRegs is already zero!");
      --NumLiveRegs;
      LiveRegDefs[Succ.getReg()] = nullptr;
      LiveRegGens[Succ.getReg()] = nullptr;
      releaseInterferences(Succ.getReg());
    }
  }
  // Release the special call resource dependence, if this is the beginning
  // of a call.
  unsigned CallResource = TRI->getNumRegs();
  if (LiveRegDefs[CallResource] == SU)
    for (const SDNode *SUNode = SU->getNode(); SUNode;
         SUNode = SUNode->getGluedNode()) {
      if (SUNode->isMachineOpcode() &&
          SUNode->getMachineOpcode() == TII->getCallFrameSetupOpcode()) {
        assert(NumLiveRegs > 0 && "NumLiveRegs is already zero!");
        --NumLiveRegs;
        LiveRegDefs[CallResource] = nullptr;
        LiveRegGens[CallResource] = nullptr;
        releaseInterferences(CallResource);
      }
    }

  resetVRegCycle(SU);

  SU->isScheduled = true;

  // Conditions under which the scheduler should eagerly advance the cycle:
  // (1) No available instructions
  // (2) All pipelines full, so available instructions must have hazards.
  //
  // If HazardRec is disabled, the cycle was pre-advanced before calling
  // ReleasePredecessors. In that case, IssueCount should remain 0.
  //
  // Check AvailableQueue after ReleasePredecessors in case of zero latency.
  if (HazardRec->isEnabled() || AvgIPC > 1) {
    if (SU->getNode() && SU->getNode()->isMachineOpcode())
      ++IssueCount;
    if ((HazardRec->isEnabled() && HazardRec->atIssueLimit())
        || (!HazardRec->isEnabled() && IssueCount == AvgIPC))
      AdvanceToCycle(CurCycle + 1);
  }
}

/// CapturePred - This does the opposite of ReleasePred. Since SU is being
/// unscheduled, increase the succ left count of its predecessors. Remove
/// them from AvailableQueue if necessary.
void ScheduleDAGRRList::CapturePred(SDep *PredEdge) {
  SUnit *PredSU = PredEdge->getSUnit();
  if (PredSU->isAvailable) {
    PredSU->isAvailable = false;
    if (!PredSU->isPending)
      AvailableQueue->remove(PredSU);
  }

  assert(PredSU->NumSuccsLeft < std::numeric_limits<unsigned>::max() &&
         "NumSuccsLeft will overflow!");
  ++PredSU->NumSuccsLeft;
}

/// UnscheduleNodeBottomUp - Remove the node from the schedule, update its and
/// its predecessor states to reflect the change.
void ScheduleDAGRRList::UnscheduleNodeBottomUp(SUnit *SU) {
  DEBUG(dbgs() << "*** Unscheduling [" << SU->getHeight() << "]: ");
  DEBUG(SU->dump(this));

  for (SDep &Pred : SU->Preds) {
    CapturePred(&Pred);
    if (Pred.isAssignedRegDep() && SU == LiveRegGens[Pred.getReg()]){
      assert(NumLiveRegs > 0 && "NumLiveRegs is already zero!");
      assert(LiveRegDefs[Pred.getReg()] == Pred.getSUnit() &&
             "Physical register dependency violated?");
      --NumLiveRegs;
      LiveRegDefs[Pred.getReg()] = nullptr;
      LiveRegGens[Pred.getReg()] = nullptr;
      releaseInterferences(Pred.getReg());
    }
  }

  // Reclaim the special call resource dependence, if this is the beginning
  // of a call.
  unsigned CallResource = TRI->getNumRegs();
  for (const SDNode *SUNode = SU->getNode(); SUNode;
       SUNode = SUNode->getGluedNode()) {
    if (SUNode->isMachineOpcode() &&
        SUNode->getMachineOpcode() == TII->getCallFrameSetupOpcode()) {
      SUnit *SeqEnd = CallSeqEndForStart[SU];
      assert(SeqEnd && "Call sequence start/end must be known");
      assert(!LiveRegDefs[CallResource]);
      assert(!LiveRegGens[CallResource]);
      ++NumLiveRegs;
      LiveRegDefs[CallResource] = SU;
      LiveRegGens[CallResource] = SeqEnd;
    }
  }

  // Release the special call resource dependence, if this is the end
  // of a call.
  if (LiveRegGens[CallResource] == SU)
    for (const SDNode *SUNode = SU->getNode(); SUNode;
         SUNode = SUNode->getGluedNode()) {
      if (SUNode->isMachineOpcode() &&
          SUNode->getMachineOpcode() == TII->getCallFrameDestroyOpcode()) {
        assert(NumLiveRegs > 0 && "NumLiveRegs is already zero!");
        assert(LiveRegDefs[CallResource]);
        assert(LiveRegGens[CallResource]);
        --NumLiveRegs;
        LiveRegDefs[CallResource] = nullptr;
        LiveRegGens[CallResource] = nullptr;
        releaseInterferences(CallResource);
      }
    }

  for (auto &Succ : SU->Succs) {
    if (Succ.isAssignedRegDep()) {
      auto Reg = Succ.getReg();
      if (!LiveRegDefs[Reg])
        ++NumLiveRegs;
      // This becomes the nearest def. Note that an earlier def may still be
      // pending if this is a two-address node.
      LiveRegDefs[Reg] = SU;

      // Update LiveRegGen only if was empty before this unscheduling.
      // This is to avoid incorrect updating LiveRegGen set in previous run.
      if (!LiveRegGens[Reg]) {
        // Find the successor with the lowest height.
        LiveRegGens[Reg] = Succ.getSUnit();
        for (auto &Succ2 : SU->Succs) {
          if (Succ2.isAssignedRegDep() && Succ2.getReg() == Reg &&
              Succ2.getSUnit()->getHeight() < LiveRegGens[Reg]->getHeight())
            LiveRegGens[Reg] = Succ2.getSUnit();
        }
      }
    }
  }
  if (SU->getHeight() < MinAvailableCycle)
    MinAvailableCycle = SU->getHeight();

  SU->setHeightDirty();
  SU->isScheduled = false;
  SU->isAvailable = true;
  if (!DisableSchedCycles && AvailableQueue->hasReadyFilter()) {
    // Don't make available until backtracking is complete.
    SU->isPending = true;
    PendingQueue.push_back(SU);
  }
  else {
    AvailableQueue->push(SU);
  }
  AvailableQueue->unscheduledNode(SU);
}

/// After backtracking, the hazard checker needs to be restored to a state
/// corresponding the current cycle.
void ScheduleDAGRRList::RestoreHazardCheckerBottomUp() {
  HazardRec->Reset();

  unsigned LookAhead = std::min((unsigned)Sequence.size(),
                                HazardRec->getMaxLookAhead());
  if (LookAhead == 0)
    return;

  std::vector<SUnit *>::const_iterator I = (Sequence.end() - LookAhead);
  unsigned HazardCycle = (*I)->getHeight();
  for (auto E = Sequence.end(); I != E; ++I) {
    SUnit *SU = *I;
    for (; SU->getHeight() > HazardCycle; ++HazardCycle) {
      HazardRec->RecedeCycle();
    }
    EmitNode(SU);
  }
}

/// BacktrackBottomUp - Backtrack scheduling to a previous cycle specified in
/// BTCycle in order to schedule a specific node.
void ScheduleDAGRRList::BacktrackBottomUp(SUnit *SU, SUnit *BtSU) {
  SUnit *OldSU = Sequence.back();
  while (true) {
    Sequence.pop_back();
    // FIXME: use ready cycle instead of height
    CurCycle = OldSU->getHeight();
    UnscheduleNodeBottomUp(OldSU);
    AvailableQueue->setCurCycle(CurCycle);
    if (OldSU == BtSU)
      break;
    OldSU = Sequence.back();
  }

  assert(!SU->isSucc(OldSU) && "Something is wrong!");

  RestoreHazardCheckerBottomUp();

  ReleasePending();

  ++NumBacktracks;
}

static bool isOperandOf(const SUnit *SU, SDNode *N) {
  for (const SDNode *SUNode = SU->getNode(); SUNode;
       SUNode = SUNode->getGluedNode()) {
    if (SUNode->isOperandOf(N))
      return true;
  }
  return false;
}

/// TryUnfold - Attempt to unfold
SUnit *ScheduleDAGRRList::TryUnfoldSU(SUnit *SU) {
  SDNode *N = SU->getNode();
  // Use while over if to ease fall through.
  SmallVector<SDNode *, 2> NewNodes;
  if (!TII->unfoldMemoryOperand(*DAG, N, NewNodes))
    return nullptr;

  // unfolding an x86 DEC64m operation results in store, dec, load which
  // can't be handled here so quit
  if (NewNodes.size() == 3)
    return nullptr;

  assert(NewNodes.size() == 2 && "Expected a load folding node!");

  N = NewNodes[1];
  SDNode *LoadNode = NewNodes[0];
  unsigned NumVals = N->getNumValues();
  unsigned OldNumVals = SU->getNode()->getNumValues();

  // LoadNode may already exist. This can happen when there is another
  // load from the same location and producing the same type of value
  // but it has different alignment or volatileness.
  bool isNewLoad = true;
  SUnit *LoadSU;
  if (LoadNode->getNodeId() != -1) {
    LoadSU = &SUnits[LoadNode->getNodeId()];
    // If LoadSU has already been scheduled, we should clone it but
    // this would negate the benefit to unfolding so just return SU.
    if (LoadSU->isScheduled)
      return SU;
    isNewLoad = false;
  } else {
    LoadSU = CreateNewSUnit(LoadNode);
    LoadNode->setNodeId(LoadSU->NodeNum);

    InitNumRegDefsLeft(LoadSU);
    computeLatency(LoadSU);
  }

  DEBUG(dbgs() << "Unfolding SU #" << SU->NodeNum << "\n");

  // Now that we are committed to unfolding replace DAG Uses.
  for (unsigned i = 0; i != NumVals; ++i)
    DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), i), SDValue(N, i));
  DAG->ReplaceAllUsesOfValueWith(SDValue(SU->getNode(), OldNumVals - 1),
                                 SDValue(LoadNode, 1));

  SUnit *NewSU = CreateNewSUnit(N);
  assert(N->getNodeId() == -1 && "Node already inserted!");
  N->setNodeId(NewSU->NodeNum);

  const MCInstrDesc &MCID = TII->get(N->getMachineOpcode());
  for (unsigned i = 0; i != MCID.getNumOperands(); ++i) {
    if (MCID.getOperandConstraint(i, MCOI::TIED_TO) != -1) {
      NewSU->isTwoAddress = true;
      break;
    }
  }
  if (MCID.isCommutable())
    NewSU->isCommutable = true;

  InitNumRegDefsLeft(NewSU);
  computeLatency(NewSU);

  // Record all the edges to and from the old SU, by category.
  SmallVector<SDep, 4> ChainPreds;
  SmallVector<SDep, 4> ChainSuccs;
  SmallVector<SDep, 4> LoadPreds;
  SmallVector<SDep, 4> NodePreds;
  SmallVector<SDep, 4> NodeSuccs;
  for (SDep &Pred : SU->Preds) {
    if (Pred.isCtrl())
      ChainPreds.push_back(Pred);
    else if (isOperandOf(Pred.getSUnit(), LoadNode))
      LoadPreds.push_back(Pred);
    else
      NodePreds.push_back(Pred);
  }
  for (SDep &Succ : SU->Succs) {
    if (Succ.isCtrl())
      ChainSuccs.push_back(Succ);
    else
      NodeSuccs.push_back(Succ);
  }

  // Now assign edges to the newly-created nodes.
  for (const SDep &Pred : ChainPreds) {
    RemovePred(SU, Pred);
    if (isNewLoad)
      AddPred(LoadSU, Pred);
  }
  for (const SDep &Pred : LoadPreds) {
    RemovePred(SU, Pred);
    if (isNewLoad)
      AddPred(LoadSU, Pred);
  }
  for (const SDep &Pred : NodePreds) {
    RemovePred(SU, Pred);
    AddPred(NewSU, Pred);
  }
  for (SDep D : NodeSuccs) {
    SUnit *SuccDep = D.getSUnit();
    D.setSUnit(SU);
    RemovePred(SuccDep, D);
    D.setSUnit(NewSU);
    AddPred(SuccDep, D);
    // Balance register pressure.
    if (AvailableQueue->tracksRegPressure() && SuccDep->isScheduled &&
        !D.isCtrl() && NewSU->NumRegDefsLeft > 0)
      --NewSU->NumRegDefsLeft;
  }
  for (SDep D : ChainSuccs) {
    SUnit *SuccDep = D.getSUnit();
    D.setSUnit(SU);
    RemovePred(SuccDep, D);
    if (isNewLoad) {
      D.setSUnit(LoadSU);
      AddPred(SuccDep, D);
    }
  }

  // Add a data dependency to reflect that NewSU reads the value defined
  // by LoadSU.
  SDep D(LoadSU, SDep::Data, 0);
  D.setLatency(LoadSU->Latency);
  AddPred(NewSU, D);

  if (isNewLoad)
    AvailableQueue->addNode(LoadSU);
  AvailableQueue->addNode(NewSU);

  ++NumUnfolds;

  if (NewSU->NumSuccsLeft == 0)
    NewSU->isAvailable = true;

  return NewSU;
}

/// CopyAndMoveSuccessors - Clone the specified node and move its scheduled
/// successors to the newly created node.
SUnit *ScheduleDAGRRList::CopyAndMoveSuccessors(SUnit *SU) {
  SDNode *N = SU->getNode();
  if (!N)
    return nullptr;

  DEBUG(dbgs() << "Considering duplicating the SU\n");
  DEBUG(SU->dump(this));

  if (N->getGluedNode() &&
      !TII->canCopyGluedNodeDuringSchedule(N)) {
    DEBUG(dbgs()
        << "Giving up because it has incoming glue and the target does not "
           "want to copy it\n");
    return nullptr;
  }

  SUnit *NewSU;
  bool TryUnfold = false;
  for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) {
    MVT VT = N->getSimpleValueType(i);
    if (VT == MVT::Glue) {
      DEBUG(dbgs() << "Giving up because it has outgoing glue\n");
      return nullptr;
    } else if (VT == MVT::Other)
      TryUnfold = true;
  }
  for (const SDValue &Op : N->op_values()) {
    MVT VT = Op.getNode()->getSimpleValueType(Op.getResNo());
    if (VT == MVT::Glue && !TII->canCopyGluedNodeDuringSchedule(N)) {
      DEBUG(dbgs() << "Giving up because it one of the operands is glue and "
                      "the target does not want to copy it\n");
      return nullptr;
    }
  }

  // If possible unfold instruction.
  if (TryUnfold) {
    SUnit *UnfoldSU = TryUnfoldSU(SU);
    if (!UnfoldSU)
      return nullptr;
    SU = UnfoldSU;
    N = SU->getNode();
    // If this can be scheduled don't bother duplicating and just return
    if (SU->NumSuccsLeft == 0)
      return SU;
  }

  DEBUG(dbgs() << "    Duplicating SU #" << SU->NodeNum << "\n");
  NewSU = CreateClone(SU);

  // New SUnit has the exact same predecessors.
  for (SDep &Pred : SU->Preds)
    if (!Pred.isArtificial())
      AddPred(NewSU, Pred);

  // Only copy scheduled successors. Cut them from old node's successor
  // list and move them over.
  SmallVector<std::pair<SUnit *, SDep>, 4> DelDeps;
  for (SDep &Succ : SU->Succs) {
    if (Succ.isArtificial())
      continue;
    SUnit *SuccSU = Succ.getSUnit();
    if (SuccSU->isScheduled) {
      SDep D = Succ;
      D.setSUnit(NewSU);
      AddPred(SuccSU, D);
      D.setSUnit(SU);
      DelDeps.push_back(std::make_pair(SuccSU, D));
    }
  }
  for (auto &DelDep : DelDeps)
    RemovePred(DelDep.first, DelDep.second);

  AvailableQueue->updateNode(SU);
  AvailableQueue->addNode(NewSU);

  ++NumDups;
  return NewSU;
}

/// InsertCopiesAndMoveSuccs - Insert register copies and move all
/// scheduled successors of the given SUnit to the last copy.
void ScheduleDAGRRList::InsertCopiesAndMoveSuccs(SUnit *SU, unsigned Reg,
                                              const TargetRegisterClass *DestRC,
                                              const TargetRegisterClass *SrcRC,
                                              SmallVectorImpl<SUnit*> &Copies) {
  SUnit *CopyFromSU = CreateNewSUnit(nullptr);
  CopyFromSU->CopySrcRC = SrcRC;
  CopyFromSU->CopyDstRC = DestRC;

  SUnit *CopyToSU = CreateNewSUnit(nullptr);
  CopyToSU->CopySrcRC = DestRC;
  CopyToSU->CopyDstRC = SrcRC;

  // Only copy scheduled successors. Cut them from old node's successor
  // list and move them over.
  SmallVector<std::pair<SUnit *, SDep>, 4> DelDeps;
  for (SDep &Succ : SU->Succs) {
    if (Succ.isArtificial())
      continue;
    SUnit *SuccSU = Succ.getSUnit();
    if (SuccSU->isScheduled) {
      SDep D = Succ;
      D.setSUnit(CopyToSU);
      AddPred(SuccSU, D);
      DelDeps.push_back(std::make_pair(SuccSU, Succ));
    }
    else {
      // Avoid scheduling the def-side copy before other successors. Otherwise
      // we could introduce another physreg interference on the copy and
      // continue inserting copies indefinitely.
      AddPred(SuccSU, SDep(CopyFromSU, SDep::Artificial));
    }
  }
  for (auto &DelDep : DelDeps)
    RemovePred(DelDep.first, DelDep.second);

  SDep FromDep(SU, SDep::Data, Reg);
  FromDep.setLatency(SU->Latency);
  AddPred(CopyFromSU, FromDep);
  SDep ToDep(CopyFromSU, SDep::Data, 0);
  ToDep.setLatency(CopyFromSU->Latency);
  AddPred(CopyToSU, ToDep);

  AvailableQueue->updateNode(SU);
  AvailableQueue->addNode(CopyFromSU);
  AvailableQueue->addNode(CopyToSU);
  Copies.push_back(CopyFromSU);
  Copies.push_back(CopyToSU);

  ++NumPRCopies;
}

/// getPhysicalRegisterVT - Returns the ValueType of the physical register
/// definition of the specified node.
/// FIXME: Move to SelectionDAG?
static MVT getPhysicalRegisterVT(SDNode *N, unsigned Reg,
                                 const TargetInstrInfo *TII) {
  unsigned NumRes;
  if (N->getOpcode() == ISD::CopyFromReg) {
    // CopyFromReg has: "chain, Val, glue" so operand 1 gives the type.
    NumRes = 1;
  } else {
    const MCInstrDesc &MCID = TII->get(N->getMachineOpcode());
    assert(MCID.ImplicitDefs && "Physical reg def must be in implicit def list!");
    NumRes = MCID.getNumDefs();
    for (const MCPhysReg *ImpDef = MCID.getImplicitDefs(); *ImpDef; ++ImpDef) {
      if (Reg == *ImpDef)
        break;
      ++NumRes;
    }
  }
  return N->getSimpleValueType(NumRes);
}

/// CheckForLiveRegDef - Return true and update live register vector if the
/// specified register def of the specified SUnit clobbers any "live" registers.
static void CheckForLiveRegDef(SUnit *SU, unsigned Reg,
                               SUnit **LiveRegDefs,
                               SmallSet<unsigned, 4> &RegAdded,
                               SmallVectorImpl<unsigned> &LRegs,
                               const TargetRegisterInfo *TRI) {
  for (MCRegAliasIterator AliasI(Reg, TRI, true); AliasI.isValid(); ++AliasI) {

    // Check if Ref is live.
    if (!LiveRegDefs[*AliasI]) continue;

    // Allow multiple uses of the same def.
    if (LiveRegDefs[*AliasI] == SU) continue;

    // Add Reg to the set of interfering live regs.
    if (RegAdded.insert(*AliasI).second) {
      LRegs.push_back(*AliasI);
    }
  }
}

/// CheckForLiveRegDefMasked - Check for any live physregs that are clobbered
/// by RegMask, and add them to LRegs.
static void CheckForLiveRegDefMasked(SUnit *SU, const uint32_t *RegMask,
                                     ArrayRef<SUnit*> LiveRegDefs,
                                     SmallSet<unsigned, 4> &RegAdded,
                                     SmallVectorImpl<unsigned> &LRegs) {
  // Look at all live registers. Skip Reg0 and the special CallResource.
  for (unsigned i = 1, e = LiveRegDefs.size()-1; i != e; ++i) {
    if (!LiveRegDefs[i]) continue;
    if (LiveRegDefs[i] == SU) continue;
    if (!MachineOperand::clobbersPhysReg(RegMask, i)) continue;
    if (RegAdded.insert(i).second)
      LRegs.push_back(i);
  }
}

/// getNodeRegMask - Returns the register mask attached to an SDNode, if any.
static const uint32_t *getNodeRegMask(const SDNode *N) {
  for (const SDValue &Op : N->op_values())
    if (const auto *RegOp = dyn_cast<RegisterMaskSDNode>(Op.getNode()))
      return RegOp->getRegMask();
  return nullptr;
}

/// DelayForLiveRegsBottomUp - Returns true if it is necessary to delay
/// scheduling of the given node to satisfy live physical register dependencies.
/// If the specific node is the last one that's available to schedule, do
/// whatever is necessary (i.e. backtracking or cloning) to make it possible.
bool ScheduleDAGRRList::
DelayForLiveRegsBottomUp(SUnit *SU, SmallVectorImpl<unsigned> &LRegs) {
  if (NumLiveRegs == 0)
    return false;

  SmallSet<unsigned, 4> RegAdded;
  // If this node would clobber any "live" register, then it's not ready.
  //
  // If SU is the currently live definition of the same register that it uses,
  // then we are free to schedule it.
  for (SDep &Pred : SU->Preds) {
    if (Pred.isAssignedRegDep() && LiveRegDefs[Pred.getReg()] != SU)
      CheckForLiveRegDef(Pred.getSUnit(), Pred.getReg(), LiveRegDefs.get(),
                         RegAdded, LRegs, TRI);
  }

  for (SDNode *Node = SU->getNode(); Node; Node = Node->getGluedNode()) {
    if (Node->getOpcode() == ISD::INLINEASM) {
      // Inline asm can clobber physical defs.
      unsigned NumOps = Node->getNumOperands();
      if (Node->getOperand(NumOps-1).getValueType() == MVT::Glue)
        --NumOps;  // Ignore the glue operand.

      for (unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) {
        unsigned Flags =
          cast<ConstantSDNode>(Node->getOperand(i))->getZExtValue();
        unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);

        ++i; // Skip the ID value.
        if (InlineAsm::isRegDefKind(Flags) ||
            InlineAsm::isRegDefEarlyClobberKind(Flags) ||
            InlineAsm::isClobberKind(Flags)) {
          // Check for def of register or earlyclobber register.
          for (; NumVals; --NumVals, ++i) {
            unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
            if (TargetRegisterInfo::isPhysicalRegister(Reg))
              CheckForLiveRegDef(SU, Reg, LiveRegDefs.get(), RegAdded, LRegs, TRI);
          }
        } else
          i += NumVals;
      }
      continue;
    }

    if (!Node->isMachineOpcode())
      continue;
    // If we're in the middle of scheduling a call, don't begin scheduling
    // another call. Also, don't allow any physical registers to be live across
    // the call.
    if (Node->getMachineOpcode() == TII->getCallFrameDestroyOpcode()) {
      // Check the special calling-sequence resource.
      unsigned CallResource = TRI->getNumRegs();
      if (LiveRegDefs[CallResource]) {
        SDNode *Gen = LiveRegGens[CallResource]->getNode();
        while (SDNode *Glued = Gen->getGluedNode())
          Gen = Glued;
        if (!IsChainDependent(Gen, Node, 0, TII) &&
            RegAdded.insert(CallResource).second)
          LRegs.push_back(CallResource);
      }
    }
    if (const uint32_t *RegMask = getNodeRegMask(Node))
      CheckForLiveRegDefMasked(SU, RegMask,
                               makeArrayRef(LiveRegDefs.get(), TRI->getNumRegs()),
                               RegAdded, LRegs);

    const MCInstrDesc &MCID = TII->get(Node->getMachineOpcode());
    if (MCID.hasOptionalDef()) {
      // Most ARM instructions have an OptionalDef for CPSR, to model the S-bit.
      // This operand can be either a def of CPSR, if the S bit is set; or a use
      // of %noreg.  When the OptionalDef is set to a valid register, we need to
      // handle it in the same way as an ImplicitDef.
      for (unsigned i = 0; i < MCID.getNumDefs(); ++i)
        if (MCID.OpInfo[i].isOptionalDef()) {
          const SDValue &OptionalDef = Node->getOperand(i - Node->getNumValues());
          unsigned Reg = cast<RegisterSDNode>(OptionalDef)->getReg();
          CheckForLiveRegDef(SU, Reg, LiveRegDefs.get(), RegAdded, LRegs, TRI);
        }
    }
    if (!MCID.ImplicitDefs)
      continue;
    for (const MCPhysReg *Reg = MCID.getImplicitDefs(); *Reg; ++Reg)
      CheckForLiveRegDef(SU, *Reg, LiveRegDefs.get(), RegAdded, LRegs, TRI);
  }

  return !LRegs.empty();
}

void ScheduleDAGRRList::releaseInterferences(unsigned Reg) {
  // Add the nodes that aren't ready back onto the available list.
  for (unsigned i = Interferences.size(); i > 0; --i) {
    SUnit *SU = Interferences[i-1];
    LRegsMapT::iterator LRegsPos = LRegsMap.find(SU);
    if (Reg) {
      SmallVectorImpl<unsigned> &LRegs = LRegsPos->second;
      if (!is_contained(LRegs, Reg))
        continue;
    }
    SU->isPending = false;
    // The interfering node may no longer be available due to backtracking.
    // Furthermore, it may have been made available again, in which case it is
    // now already in the AvailableQueue.
    if (SU->isAvailable && !SU->NodeQueueId) {
      DEBUG(dbgs() << "    Repushing SU #" << SU->NodeNum << '\n');
      AvailableQueue->push(SU);
    }
    if (i < Interferences.size())
      Interferences[i-1] = Interferences.back();
    Interferences.pop_back();
    LRegsMap.erase(LRegsPos);
  }
}

/// Return a node that can be scheduled in this cycle. Requirements:
/// (1) Ready: latency has been satisfied
/// (2) No Hazards: resources are available
/// (3) No Interferences: may unschedule to break register interferences.
SUnit *ScheduleDAGRRList::PickNodeToScheduleBottomUp() {
  SUnit *CurSU = AvailableQueue->empty() ? nullptr : AvailableQueue->pop();
  auto FindAvailableNode = [&]() {
    while (CurSU) {
      SmallVector<unsigned, 4> LRegs;
      if (!DelayForLiveRegsBottomUp(CurSU, LRegs))
        break;
      DEBUG(dbgs() << "    Interfering reg ";
            if (LRegs[0] == TRI->getNumRegs())
              dbgs() << "CallResource";
            else
              dbgs() << printReg(LRegs[0], TRI);
            dbgs() << " SU #" << CurSU->NodeNum << '\n');
      std::pair<LRegsMapT::iterator, bool> LRegsPair =
        LRegsMap.insert(std::make_pair(CurSU, LRegs));
      if (LRegsPair.second) {
        CurSU->isPending = true;  // This SU is not in AvailableQueue right now.
        Interferences.push_back(CurSU);
      }
      else {
        assert(CurSU->isPending && "Interferences are pending");
        // Update the interference with current live regs.
        LRegsPair.first->second = LRegs;
      }
      CurSU = AvailableQueue->pop();
    }
  };
  FindAvailableNode();
  if (CurSU)
    return CurSU;

  // All candidates are delayed due to live physical reg dependencies.
  // Try backtracking, code duplication, or inserting cross class copies
  // to resolve it.
  for (SUnit *TrySU : Interferences) {
    SmallVectorImpl<unsigned> &LRegs = LRegsMap[TrySU];

    // Try unscheduling up to the point where it's safe to schedule
    // this node.
    SUnit *BtSU = nullptr;
    unsigned LiveCycle = std::numeric_limits<unsigned>::max();
    for (unsigned Reg : LRegs) {
      if (LiveRegGens[Reg]->getHeight() < LiveCycle) {
        BtSU = LiveRegGens[Reg];
        LiveCycle = BtSU->getHeight();
      }
    }
    if (!WillCreateCycle(TrySU, BtSU))  {
      // BacktrackBottomUp mutates Interferences!
      BacktrackBottomUp(TrySU, BtSU);

      // Force the current node to be scheduled before the node that
      // requires the physical reg dep.
      if (BtSU->isAvailable) {
        BtSU->isAvailable = false;
        if (!BtSU->isPending)
          AvailableQueue->remove(BtSU);
      }
      DEBUG(dbgs() << "ARTIFICIAL edge from SU(" << BtSU->NodeNum << ") to SU("
            << TrySU->NodeNum << ")\n");
      AddPred(TrySU, SDep(BtSU, SDep::Artificial));

      // If one or more successors has been unscheduled, then the current
      // node is no longer available.
      if (!TrySU->isAvailable || !TrySU->NodeQueueId) {
        DEBUG(dbgs() << "TrySU not available; choosing node from queue\n");
        CurSU = AvailableQueue->pop();
      } else {
        DEBUG(dbgs() << "TrySU available\n");
        // Available and in AvailableQueue
        AvailableQueue->remove(TrySU);
        CurSU = TrySU;
      }
      FindAvailableNode();
      // Interferences has been mutated. We must break.
      break;
    }
  }

  if (!CurSU) {
    // Can't backtrack. If it's too expensive to copy the value, then try
    // duplicate the nodes that produces these "too expensive to copy"
    // values to break the dependency. In case even that doesn't work,
    // insert cross class copies.
    // If it's not too expensive, i.e. cost != -1, issue copies.
    SUnit *TrySU = Interferences[0];
    SmallVectorImpl<unsigned> &LRegs = LRegsMap[TrySU];
    assert(LRegs.size() == 1 && "Can't handle this yet!");
    unsigned Reg = LRegs[0];
    SUnit *LRDef = LiveRegDefs[Reg];
    MVT VT = getPhysicalRegisterVT(LRDef->getNode(), Reg, TII);
    const TargetRegisterClass *RC =
      TRI->getMinimalPhysRegClass(Reg, VT);
    const TargetRegisterClass *DestRC = TRI->getCrossCopyRegClass(RC);

    // If cross copy register class is the same as RC, then it must be possible
    // copy the value directly. Do not try duplicate the def.
    // If cross copy register class is not the same as RC, then it's possible to
    // copy the value but it require cross register class copies and it is
    // expensive.
    // If cross copy register class is null, then it's not possible to copy
    // the value at all.
    SUnit *NewDef = nullptr;
    if (DestRC != RC) {
      NewDef = CopyAndMoveSuccessors(LRDef);
      if (!DestRC && !NewDef)
        report_fatal_error("Can't handle live physical register dependency!");
    }
    if (!NewDef) {
      // Issue copies, these can be expensive cross register class copies.
      SmallVector<SUnit*, 2> Copies;
      InsertCopiesAndMoveSuccs(LRDef, Reg, DestRC, RC, Copies);
      DEBUG(dbgs() << "    Adding an edge from SU #" << TrySU->NodeNum
            << " to SU #" << Copies.front()->NodeNum << "\n");
      AddPred(TrySU, SDep(Copies.front(), SDep::Artificial));
      NewDef = Copies.back();
    }

    DEBUG(dbgs() << "    Adding an edge from SU #" << NewDef->NodeNum
          << " to SU #" << TrySU->NodeNum << "\n");
    LiveRegDefs[Reg] = NewDef;
    AddPred(NewDef, SDep(TrySU, SDep::Artificial));
    TrySU->isAvailable = false;
    CurSU = NewDef;
  }
  assert(CurSU && "Unable to resolve live physical register dependencies!");
  return CurSU;
}

/// ListScheduleBottomUp - The main loop of list scheduling for bottom-up
/// schedulers.
void ScheduleDAGRRList::ListScheduleBottomUp() {
  // Release any predecessors of the special Exit node.
  ReleasePredecessors(&ExitSU);

  // Add root to Available queue.
  if (!SUnits.empty()) {
    SUnit *RootSU = &SUnits[DAG->getRoot().getNode()->getNodeId()];
    assert(RootSU->Succs.empty() && "Graph root shouldn't have successors!");
    RootSU->isAvailable = true;
    AvailableQueue->push(RootSU);
  }

  // While Available queue is not empty, grab the node with the highest
  // priority. If it is not ready put it back.  Schedule the node.
  Sequence.reserve(SUnits.size());
  while (!AvailableQueue->empty() || !Interferences.empty()) {
    DEBUG(dbgs() << "\nExamining Available:\n";
          AvailableQueue->dump(this));

    // Pick the best node to schedule taking all constraints into
    // consideration.
    SUnit *SU = PickNodeToScheduleBottomUp();

    AdvancePastStalls(SU);

    ScheduleNodeBottomUp(SU);

    while (AvailableQueue->empty() && !PendingQueue.empty()) {
      // Advance the cycle to free resources. Skip ahead to the next ready SU.
      assert(MinAvailableCycle < std::numeric_limits<unsigned>::max() &&
             "MinAvailableCycle uninitialized");
      AdvanceToCycle(std::max(CurCycle + 1, MinAvailableCycle));
    }
  }

  // Reverse the order if it is bottom up.
  std::reverse(Sequence.begin(), Sequence.end());

#ifndef NDEBUG
  VerifyScheduledSequence(/*isBottomUp=*/true);
#endif
}

namespace {

class RegReductionPQBase;

struct queue_sort {
  bool isReady(SUnit* SU, unsigned CurCycle) const { return true; }
};

#ifndef NDEBUG
template<class SF>
struct reverse_sort : public queue_sort {
  SF &SortFunc;

  reverse_sort(SF &sf) : SortFunc(sf) {}

  bool operator()(SUnit* left, SUnit* right) const {
    // reverse left/right rather than simply !SortFunc(left, right)
    // to expose different paths in the comparison logic.
    return SortFunc(right, left);
  }
};
#endif // NDEBUG

/// bu_ls_rr_sort - Priority function for bottom up register pressure
// reduction scheduler.
struct bu_ls_rr_sort : public queue_sort {
  enum {
    IsBottomUp = true,
    HasReadyFilter = false
  };

  RegReductionPQBase *SPQ;

  bu_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {}

  bool operator()(SUnit* left, SUnit* right) const;
};

// src_ls_rr_sort - Priority function for source order scheduler.
struct src_ls_rr_sort : public queue_sort {
  enum {
    IsBottomUp = true,
    HasReadyFilter = false
  };

  RegReductionPQBase *SPQ;

  src_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {}

  bool operator()(SUnit* left, SUnit* right) const;
};

// hybrid_ls_rr_sort - Priority function for hybrid scheduler.
struct hybrid_ls_rr_sort : public queue_sort {
  enum {
    IsBottomUp = true,
    HasReadyFilter = false
  };

  RegReductionPQBase *SPQ;

  hybrid_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {}

  bool isReady(SUnit *SU, unsigned CurCycle) const;

  bool operator()(SUnit* left, SUnit* right) const;
};

// ilp_ls_rr_sort - Priority function for ILP (instruction level parallelism)
// scheduler.
struct ilp_ls_rr_sort : public queue_sort {
  enum {
    IsBottomUp = true,
    HasReadyFilter = false
  };

  RegReductionPQBase *SPQ;

  ilp_ls_rr_sort(RegReductionPQBase *spq) : SPQ(spq) {}

  bool isReady(SUnit *SU, unsigned CurCycle) const;

  bool operator()(SUnit* left, SUnit* right) const;
};

class RegReductionPQBase : public SchedulingPriorityQueue {
protected:
  std::vector<SUnit *> Queue;
  unsigned CurQueueId = 0;
  bool TracksRegPressure;
  bool SrcOrder;

  // SUnits - The SUnits for the current graph.
  std::vector<SUnit> *SUnits;

  MachineFunction &MF;
  const TargetInstrInfo *TII;
  const TargetRegisterInfo *TRI;
  const TargetLowering *TLI;
  ScheduleDAGRRList *scheduleDAG = nullptr;

  // SethiUllmanNumbers - The SethiUllman number for each node.
  std::vector<unsigned> SethiUllmanNumbers;

  /// RegPressure - Tracking current reg pressure per register class.
  std::vector<unsigned> RegPressure;

  /// RegLimit - Tracking the number of allocatable registers per register
  /// class.
  std::vector<unsigned> RegLimit;

public:
  RegReductionPQBase(MachineFunction &mf,
                     bool hasReadyFilter,
                     bool tracksrp,
                     bool srcorder,
                     const TargetInstrInfo *tii,
                     const TargetRegisterInfo *tri,
                     const TargetLowering *tli)
    : SchedulingPriorityQueue(hasReadyFilter), TracksRegPressure(tracksrp),
      SrcOrder(srcorder), MF(mf), TII(tii), TRI(tri), TLI(tli) {
    if (TracksRegPressure) {
      unsigned NumRC = TRI->getNumRegClasses();
      RegLimit.resize(NumRC);
      RegPressure.resize(NumRC);
      std::fill(RegLimit.begin(), RegLimit.end(), 0);
      std::fill(RegPressure.begin(), RegPressure.end(), 0);
      for (const TargetRegisterClass *RC : TRI->regclasses())
        RegLimit[RC->getID()] = tri->getRegPressureLimit(RC, MF);
    }
  }

  void setScheduleDAG(ScheduleDAGRRList *scheduleDag) {
    scheduleDAG = scheduleDag;
  }

  ScheduleHazardRecognizer* getHazardRec() {
    return scheduleDAG->getHazardRec();
  }

  void initNodes(std::vector<SUnit> &sunits) override;

  void addNode(const SUnit *SU) override;

  void updateNode(const SUnit *SU) override;

  void releaseState() override {
    SUnits = nullptr;
    SethiUllmanNumbers.clear();
    std::fill(RegPressure.begin(), RegPressure.end(), 0);
  }

  unsigned getNodePriority(const SUnit *SU) const;

  unsigned getNodeOrdering(const SUnit *SU) const {
    if (!SU->getNode()) return 0;

    return SU->getNode()->getIROrder();
  }

  bool empty() const override { return Queue.empty(); }

  void push(SUnit *U) override {
    assert(!U->NodeQueueId && "Node in the queue already");
    U->NodeQueueId = ++CurQueueId;
    Queue.push_back(U);
  }

  void remove(SUnit *SU) override {
    assert(!Queue.empty() && "Queue is empty!");
    assert(SU->NodeQueueId != 0 && "Not in queue!");
    std::vector<SUnit *>::iterator I = llvm::find(Queue, SU);
    if (I != std::prev(Queue.end()))
      std::swap(*I, Queue.back());
    Queue.pop_back();
    SU->NodeQueueId = 0;
  }

  bool tracksRegPressure() const override { return TracksRegPressure; }

  void dumpRegPressure() const;

  bool HighRegPressure(const SUnit *SU) const;

  bool MayReduceRegPressure(SUnit *SU) const;

  int RegPressureDiff(SUnit *SU, unsigned &LiveUses) const;

  void scheduledNode(SUnit *SU) override;

  void unscheduledNode(SUnit *SU) override;

protected:
  bool canClobber(const SUnit *SU, const SUnit *Op);
  void AddPseudoTwoAddrDeps();
  void PrescheduleNodesWithMultipleUses();
  void CalculateSethiUllmanNumbers();
};

template<class SF>
static SUnit *popFromQueueImpl(std::vector<SUnit *> &Q, SF &Picker) {
  std::vector<SUnit *>::iterator Best = Q.begin();
  for (auto I = std::next(Q.begin()), E = Q.end(); I != E; ++I)
    if (Picker(*Best, *I))
      Best = I;
  SUnit *V = *Best;
  if (Best != std::prev(Q.end()))
    std::swap(*Best, Q.back());
  Q.pop_back();
  return V;
}

template<class SF>
SUnit *popFromQueue(std::vector<SUnit *> &Q, SF &Picker, ScheduleDAG *DAG) {
#ifndef NDEBUG
  if (DAG->StressSched) {
    reverse_sort<SF> RPicker(Picker);
    return popFromQueueImpl(Q, RPicker);
  }
#endif
  (void)DAG;
  return popFromQueueImpl(Q, Picker);
}

//===----------------------------------------------------------------------===//
//                RegReductionPriorityQueue Definition
//===----------------------------------------------------------------------===//
//
// This is a SchedulingPriorityQueue that schedules using Sethi Ullman numbers
// to reduce register pressure.
//
template<class SF>
class RegReductionPriorityQueue : public RegReductionPQBase {
  SF Picker;

public:
  RegReductionPriorityQueue(MachineFunction &mf,
                            bool tracksrp,
                            bool srcorder,
                            const TargetInstrInfo *tii,
                            const TargetRegisterInfo *tri,
                            const TargetLowering *tli)
    : RegReductionPQBase(mf, SF::HasReadyFilter, tracksrp, srcorder,
                         tii, tri, tli),
      Picker(this) {}

  bool isBottomUp() const override { return SF::IsBottomUp; }

  bool isReady(SUnit *U) const override {
    return Picker.HasReadyFilter && Picker.isReady(U, getCurCycle());
  }

  SUnit *pop() override {
    if (Queue.empty()) return nullptr;

    SUnit *V = popFromQueue(Queue, Picker, scheduleDAG);
    V->NodeQueueId = 0;
    return V;
  }

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
  LLVM_DUMP_METHOD void dump(ScheduleDAG *DAG) const override {
    // Emulate pop() without clobbering NodeQueueIds.
    std::vector<SUnit *> DumpQueue = Queue;
    SF DumpPicker = Picker;
    while (!DumpQueue.empty()) {
      SUnit *SU = popFromQueue(DumpQueue, DumpPicker, scheduleDAG);
      dbgs() << "Height " << SU->getHeight() << ": ";
      SU->dump(DAG);
    }
  }
#endif
};

using BURegReductionPriorityQueue = RegReductionPriorityQueue<bu_ls_rr_sort>;
using SrcRegReductionPriorityQueue = RegReductionPriorityQueue<src_ls_rr_sort>;
using HybridBURRPriorityQueue = RegReductionPriorityQueue<hybrid_ls_rr_sort>;
using ILPBURRPriorityQueue = RegReductionPriorityQueue<ilp_ls_rr_sort>;

} // end anonymous namespace

//===----------------------------------------------------------------------===//
//           Static Node Priority for Register Pressure Reduction
//===----------------------------------------------------------------------===//

// Check for special nodes that bypass scheduling heuristics.
// Currently this pushes TokenFactor nodes down, but may be used for other
// pseudo-ops as well.
//
// Return -1 to schedule right above left, 1 for left above right.
// Return 0 if no bias exists.
static int checkSpecialNodes(const SUnit *left, const SUnit *right) {
  bool LSchedLow = left->isScheduleLow;
  bool RSchedLow = right->isScheduleLow;
  if (LSchedLow != RSchedLow)
    return LSchedLow < RSchedLow ? 1 : -1;
  return 0;
}

/// CalcNodeSethiUllmanNumber - Compute Sethi Ullman number.
/// Smaller number is the higher priority.
static unsigned
CalcNodeSethiUllmanNumber(const SUnit *SU, std::vector<unsigned> &SUNumbers) {
  if (SUNumbers[SU->NodeNum] != 0)
    return SUNumbers[SU->NodeNum];

  // Use WorkList to avoid stack overflow on excessively large IRs.
  struct WorkState {
    WorkState(const SUnit *SU) : SU(SU) {}
    const SUnit *SU;
    unsigned PredsProcessed = 0;
  };

  SmallVector<WorkState, 16> WorkList;
  WorkList.push_back(SU);
  while (!WorkList.empty()) {
    auto &Temp = WorkList.back();
    auto *TempSU = Temp.SU;
    bool AllPredsKnown = true;
    // Try to find a non-evaluated pred and push it into the processing stack.
    for (unsigned P = Temp.PredsProcessed; P < TempSU->Preds.size(); ++P) {
      auto &Pred = TempSU->Preds[P];
      if (Pred.isCtrl()) continue;  // ignore chain preds
      SUnit *PredSU = Pred.getSUnit();
      if (SUNumbers[PredSU->NodeNum] == 0) {
#ifndef NDEBUG
        // In debug mode, check that we don't have such element in the stack.
        for (auto It : WorkList)
          assert(It.SU != PredSU && "Trying to push an element twice?");
#endif
        // Next time start processing this one starting from the next pred.
        Temp.PredsProcessed = P + 1;
        WorkList.push_back(PredSU);
        AllPredsKnown = false;
        break;
      }
    }

    if (!AllPredsKnown)
      continue;

    // Once all preds are known, we can calculate the answer for this one.
    unsigned SethiUllmanNumber = 0;
    unsigned Extra = 0;
    for (const SDep &Pred : TempSU->Preds) {
      if (Pred.isCtrl()) continue;  // ignore chain preds
      SUnit *PredSU = Pred.getSUnit();
      unsigned PredSethiUllman = SUNumbers[PredSU->NodeNum];
      assert(PredSethiUllman > 0 && "We should have evaluated this pred!");
      if (PredSethiUllman > SethiUllmanNumber) {
        SethiUllmanNumber = PredSethiUllman;
        Extra = 0;
      } else if (PredSethiUllman == SethiUllmanNumber)
        ++Extra;
    }

    SethiUllmanNumber += Extra;
    if (SethiUllmanNumber == 0)
      SethiUllmanNumber = 1;
    SUNumbers[TempSU->NodeNum] = SethiUllmanNumber;
    WorkList.pop_back();
  }

  assert(SUNumbers[SU->NodeNum] > 0 && "SethiUllman should never be zero!");
  return SUNumbers[SU->NodeNum];
}

/// CalculateSethiUllmanNumbers - Calculate Sethi-Ullman numbers of all
/// scheduling units.
void RegReductionPQBase::CalculateSethiUllmanNumbers() {
  SethiUllmanNumbers.assign(SUnits->size(), 0);

  for (const SUnit &SU : *SUnits)
    CalcNodeSethiUllmanNumber(&SU, SethiUllmanNumbers);
}

void RegReductionPQBase::addNode(const SUnit *SU) {
  unsigned SUSize = SethiUllmanNumbers.size();
  if (SUnits->size() > SUSize)
    SethiUllmanNumbers.resize(SUSize*2, 0);
  CalcNodeSethiUllmanNumber(SU, SethiUllmanNumbers);
}

void RegReductionPQBase::updateNode(const SUnit *SU) {
  SethiUllmanNumbers[SU->NodeNum] = 0;
  CalcNodeSethiUllmanNumber(SU, SethiUllmanNumbers);
}

// Lower priority means schedule further down. For bottom-up scheduling, lower
// priority SUs are scheduled before higher priority SUs.
unsigned RegReductionPQBase::getNodePriority(const SUnit *SU) const {
  assert(SU->NodeNum < SethiUllmanNumbers.size());
  unsigned Opc = SU->getNode() ? SU->getNode()->getOpcode() : 0;
  if (Opc == ISD::TokenFactor || Opc == ISD::CopyToReg)
    // CopyToReg should be close to its uses to facilitate coalescing and
    // avoid spilling.
    return 0;
  if (Opc == TargetOpcode::EXTRACT_SUBREG ||
      Opc == TargetOpcode::SUBREG_TO_REG ||
      Opc == TargetOpcode::INSERT_SUBREG)
    // EXTRACT_SUBREG, INSERT_SUBREG, and SUBREG_TO_REG nodes should be
    // close to their uses to facilitate coalescing.
    return 0;
  if (SU->NumSuccs == 0 && SU->NumPreds != 0)
    // If SU does not have a register use, i.e. it doesn't produce a value
    // that would be consumed (e.g. store), then it terminates a chain of
    // computation.  Give it a large SethiUllman number so it will be
    // scheduled right before its predecessors that it doesn't lengthen
    // their live ranges.
    return 0xffff;
  if (SU->NumPreds == 0 && SU->NumSuccs != 0)
    // If SU does not have a register def, schedule it close to its uses
    // because it does not lengthen any live ranges.
    return 0;
#if 1
  return SethiUllmanNumbers[SU->NodeNum];
#else
  unsigned Priority = SethiUllmanNumbers[SU->NodeNum];
  if (SU->isCallOp) {
    // FIXME: This assumes all of the defs are used as call operands.
    int NP = (int)Priority - SU->getNode()->getNumValues();
    return (NP > 0) ? NP : 0;
  }
  return Priority;
#endif
}

//===----------------------------------------------------------------------===//
//                     Register Pressure Tracking
//===----------------------------------------------------------------------===//

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void RegReductionPQBase::dumpRegPressure() const {
  for (const TargetRegisterClass *RC : TRI->regclasses()) {
    unsigned Id = RC->getID();
    unsigned RP = RegPressure[Id];
    if (!RP) continue;
    DEBUG(dbgs() << TRI->getRegClassName(RC) << ": " << RP << " / "
          << RegLimit[Id] << '\n');
  }
}
#endif

bool RegReductionPQBase::HighRegPressure(const SUnit *SU) const {
  if (!TLI)
    return false;

  for (const SDep &Pred : SU->Preds) {
    if (Pred.isCtrl())
      continue;
    SUnit *PredSU = Pred.getSUnit();
    // NumRegDefsLeft is zero when enough uses of this node have been scheduled
    // to cover the number of registers defined (they are all live).
    if (PredSU->NumRegDefsLeft == 0) {
      continue;
    }
    for (ScheduleDAGSDNodes::RegDefIter RegDefPos(PredSU, scheduleDAG);
         RegDefPos.IsValid(); RegDefPos.Advance()) {
      unsigned RCId, Cost;
      GetCostForDef(RegDefPos, TLI, TII, TRI, RCId, Cost, MF);

      if ((RegPressure[RCId] + Cost) >= RegLimit[RCId])
        return true;
    }
  }
  return false;
}

bool RegReductionPQBase::MayReduceRegPressure(SUnit *SU) const {
  const SDNode *N = SU->getNode();

  if (!N->isMachineOpcode() || !SU->NumSuccs)
    return false;

  unsigned NumDefs = TII->get(N->getMachineOpcode()).getNumDefs();
  for (unsigned i = 0; i != NumDefs; ++i) {
    MVT VT = N->getSimpleValueType(i);
    if (!N->hasAnyUseOfValue(i))
      continue;
    unsigned RCId = TLI->getRepRegClassFor(VT)->getID();
    if (RegPressure[RCId] >= RegLimit[RCId])
      return true;
  }
  return false;
}

// Compute the register pressure contribution by this instruction by count up
// for uses that are not live and down for defs. Only count register classes
// that are already under high pressure. As a side effect, compute the number of
// uses of registers that are already live.
//
// FIXME: This encompasses the logic in HighRegPressure and MayReduceRegPressure
// so could probably be factored.
int RegReductionPQBase::RegPressureDiff(SUnit *SU, unsigned &LiveUses) const {
  LiveUses = 0;
  int PDiff = 0;
  for (const SDep &Pred : SU->Preds) {
    if (Pred.isCtrl())
      continue;
    SUnit *PredSU = Pred.getSUnit();
    // NumRegDefsLeft is zero when enough uses of this node have been scheduled
    // to cover the number of registers defined (they are all live).
    if (PredSU->NumRegDefsLeft == 0) {
      if (PredSU->getNode()->isMachineOpcode())
        ++LiveUses;
      continue;
    }
    for (ScheduleDAGSDNodes::RegDefIter RegDefPos(PredSU, scheduleDAG);
         RegDefPos.IsValid(); RegDefPos.Advance()) {
      MVT VT = RegDefPos.GetValue();
      unsigned RCId = TLI->getRepRegClassFor(VT)->getID();
      if (RegPressure[RCId] >= RegLimit[RCId])
        ++PDiff;
    }
  }
  const SDNode *N = SU->getNode();

  if (!N || !N->isMachineOpcode() || !SU->NumSuccs)
    return PDiff;

  unsigned NumDefs = TII->get(N->getMachineOpcode()).getNumDefs();
  for (unsigned i = 0; i != NumDefs; ++i) {
    MVT VT = N->getSimpleValueType(i);
    if (!N->hasAnyUseOfValue(i))
      continue;
    unsigned RCId = TLI->getRepRegClassFor(VT)->getID();
    if (RegPressure[RCId] >= RegLimit[RCId])
      --PDiff;
  }
  return PDiff;
}

void RegReductionPQBase::scheduledNode(SUnit *SU) {
  if (!TracksRegPressure)
    return;

  if (!SU->getNode())
    return;

  for (const SDep &Pred : SU->Preds) {
    if (Pred.isCtrl())
      continue;
    SUnit *PredSU = Pred.getSUnit();
    // NumRegDefsLeft is zero when enough uses of this node have been scheduled
    // to cover the number of registers defined (they are all live).
    if (PredSU->NumRegDefsLeft == 0) {
      continue;
    }
    // FIXME: The ScheduleDAG currently loses information about which of a
    // node's values is consumed by each dependence. Consequently, if the node
    // defines multiple register classes, we don't know which to pressurize
    // here. Instead the following loop consumes the register defs in an
    // arbitrary order. At least it handles the common case of clustered loads
    // to the same class. For precise liveness, each SDep needs to indicate the
    // result number. But that tightly couples the ScheduleDAG with the
    // SelectionDAG making updates tricky. A simpler hack would be to attach a
    // value type or register class to SDep.
    //
    // The most important aspect of register tracking is balancing the increase
    // here with the reduction further below. Note that this SU may use multiple
    // defs in PredSU. The can't be determined here, but we've already
    // compensated by reducing NumRegDefsLeft in PredSU during
    // ScheduleDAGSDNodes::AddSchedEdges.
    --PredSU->NumRegDefsLeft;
    unsigned SkipRegDefs = PredSU->NumRegDefsLeft;
    for (ScheduleDAGSDNodes::RegDefIter RegDefPos(PredSU, scheduleDAG);
         RegDefPos.IsValid(); RegDefPos.Advance(), --SkipRegDefs) {
      if (SkipRegDefs)
        continue;

      unsigned RCId, Cost;
      GetCostForDef(RegDefPos, TLI, TII, TRI, RCId, Cost, MF);
      RegPressure[RCId] += Cost;
      break;
    }
  }

  // We should have this assert, but there may be dead SDNodes that never
  // materialize as SUnits, so they don't appear to generate liveness.
  //assert(SU->NumRegDefsLeft == 0 && "not all regdefs have scheduled uses");
  int SkipRegDefs = (int)SU->NumRegDefsLeft;
  for (ScheduleDAGSDNodes::RegDefIter RegDefPos(SU, scheduleDAG);
       RegDefPos.IsValid(); RegDefPos.Advance(), --SkipRegDefs) {
    if (SkipRegDefs > 0)
      continue;
    unsigned RCId, Cost;
    GetCostForDef(RegDefPos, TLI, TII, TRI, RCId, Cost, MF);
    if (RegPressure[RCId] < Cost) {
      // Register pressure tracking is imprecise. This can happen. But we try
      // hard not to let it happen because it likely results in poor scheduling.
      DEBUG(dbgs() << "  SU(" << SU->NodeNum << ") has too many regdefs\n");
      RegPressure[RCId] = 0;
    }
    else {
      RegPressure[RCId] -= Cost;
    }
  }
  DEBUG(dumpRegPressure());
}

void RegReductionPQBase::unscheduledNode(SUnit *SU) {
  if (!TracksRegPressure)
    return;

  const SDNode *N = SU->getNode();
  if (!N) return;

  if (!N->isMachineOpcode()) {
    if (N->getOpcode() != ISD::CopyToReg)
      return;
  } else {
    unsigned Opc = N->getMachineOpcode();
    if (Opc == TargetOpcode::EXTRACT_SUBREG ||
        Opc == TargetOpcode::INSERT_SUBREG ||
        Opc == TargetOpcode::SUBREG_TO_REG ||
        Opc == TargetOpcode::REG_SEQUENCE ||
        Opc == TargetOpcode::IMPLICIT_DEF)
      return;
  }

  for (const SDep &Pred : SU->Preds) {
    if (Pred.isCtrl())
      continue;
    SUnit *PredSU = Pred.getSUnit();
    // NumSuccsLeft counts all deps. Don't compare it with NumSuccs which only
    // counts data deps.
    if (PredSU->NumSuccsLeft != PredSU->Succs.size())
      continue;
    const SDNode *PN = PredSU->getNode();
    if (!PN->isMachineOpcode()) {
      if (PN->getOpcode() == ISD::CopyFromReg) {
        MVT VT = PN->getSimpleValueType(0);
        unsigned RCId = TLI->getRepRegClassFor(VT)->getID();
        RegPressure[RCId] += TLI->getRepRegClassCostFor(VT);
      }
      continue;
    }
    unsigned POpc = PN->getMachineOpcode();
    if (POpc == TargetOpcode::IMPLICIT_DEF)
      continue;
    if (POpc == TargetOpcode::EXTRACT_SUBREG ||
        POpc == TargetOpcode::INSERT_SUBREG ||
        POpc == TargetOpcode::SUBREG_TO_REG) {
      MVT VT = PN->getSimpleValueType(0);
      unsigned RCId = TLI->getRepRegClassFor(VT)->getID();
      RegPressure[RCId] += TLI->getRepRegClassCostFor(VT);
      continue;
    }
    unsigned NumDefs = TII->get(PN->getMachineOpcode()).getNumDefs();
    for (unsigned i = 0; i != NumDefs; ++i) {
      MVT VT = PN->getSimpleValueType(i);
      if (!PN->hasAnyUseOfValue(i))
        continue;
      unsigned RCId = TLI->getRepRegClassFor(VT)->getID();
      if (RegPressure[RCId] < TLI->getRepRegClassCostFor(VT))
        // Register pressure tracking is imprecise. This can happen.
        RegPressure[RCId] = 0;
      else
        RegPressure[RCId] -= TLI->getRepRegClassCostFor(VT);
    }
  }

  // Check for isMachineOpcode() as PrescheduleNodesWithMultipleUses()
  // may transfer data dependencies to CopyToReg.
  if (SU->NumSuccs && N->isMachineOpcode()) {
    unsigned NumDefs = TII->get(N->getMachineOpcode()).getNumDefs();
    for (unsigned i = NumDefs, e = N->getNumValues(); i != e; ++i) {
      MVT VT = N->getSimpleValueType(i);
      if (VT == MVT::Glue || VT == MVT::Other)
        continue;
      if (!N->hasAnyUseOfValue(i))
        continue;
      unsigned RCId = TLI->getRepRegClassFor(VT)->getID();
      RegPressure[RCId] += TLI->getRepRegClassCostFor(VT);
    }
  }

  DEBUG(dumpRegPressure());
}

//===----------------------------------------------------------------------===//
//           Dynamic Node Priority for Register Pressure Reduction
//===----------------------------------------------------------------------===//

/// closestSucc - Returns the scheduled cycle of the successor which is
/// closest to the current cycle.
static unsigned closestSucc(const SUnit *SU) {
  unsigned MaxHeight = 0;
  for (const SDep &Succ : SU->Succs) {
    if (Succ.isCtrl()) continue;  // ignore chain succs
    unsigned Height = Succ.getSUnit()->getHeight();
    // If there are bunch of CopyToRegs stacked up, they should be considered
    // to be at the same position.
    if (Succ.getSUnit()->getNode() &&
        Succ.getSUnit()->getNode()->getOpcode() == ISD::CopyToReg)
      Height = closestSucc(Succ.getSUnit())+1;
    if (Height > MaxHeight)
      MaxHeight = Height;
  }
  return MaxHeight;
}

/// calcMaxScratches - Returns an cost estimate of the worse case requirement
/// for scratch registers, i.e. number of data dependencies.
static unsigned calcMaxScratches(const SUnit *SU) {
  unsigned Scratches = 0;
  for (const SDep &Pred : SU->Preds) {
    if (Pred.isCtrl()) continue;  // ignore chain preds
    Scratches++;
  }
  return Scratches;
}

/// hasOnlyLiveInOpers - Return true if SU has only value predecessors that are
/// CopyFromReg from a virtual register.
static bool hasOnlyLiveInOpers(const SUnit *SU) {
  bool RetVal = false;
  for (const SDep &Pred : SU->Preds) {
    if (Pred.isCtrl()) continue;
    const SUnit *PredSU = Pred.getSUnit();
    if (PredSU->getNode() &&
        PredSU->getNode()->getOpcode() == ISD::CopyFromReg) {
      unsigned Reg =
        cast<RegisterSDNode>(PredSU->getNode()->getOperand(1))->getReg();
      if (TargetRegisterInfo::isVirtualRegister(Reg)) {
        RetVal = true;
        continue;
      }
    }
    return false;
  }
  return RetVal;
}

/// hasOnlyLiveOutUses - Return true if SU has only value successors that are
/// CopyToReg to a virtual register. This SU def is probably a liveout and
/// it has no other use. It should be scheduled closer to the terminator.
static bool hasOnlyLiveOutUses(const SUnit *SU) {
  bool RetVal = false;
  for (const SDep &Succ : SU->Succs) {
    if (Succ.isCtrl()) continue;
    const SUnit *SuccSU = Succ.getSUnit();
    if (SuccSU->getNode() && SuccSU->getNode()->getOpcode() == ISD::CopyToReg) {
      unsigned Reg =
        cast<RegisterSDNode>(SuccSU->getNode()->getOperand(1))->getReg();
      if (TargetRegisterInfo::isVirtualRegister(Reg)) {
        RetVal = true;
        continue;
      }
    }
    return false;
  }
  return RetVal;
}

// Set isVRegCycle for a node with only live in opers and live out uses. Also
// set isVRegCycle for its CopyFromReg operands.
//
// This is only relevant for single-block loops, in which case the VRegCycle
// node is likely an induction variable in which the operand and target virtual
// registers should be coalesced (e.g. pre/post increment values). Setting the
// isVRegCycle flag helps the scheduler prioritize other uses of the same
// CopyFromReg so that this node becomes the virtual register "kill". This
// avoids interference between the values live in and out of the block and
// eliminates a copy inside the loop.
static void initVRegCycle(SUnit *SU) {
  if (DisableSchedVRegCycle)
    return;

  if (!hasOnlyLiveInOpers(SU) || !hasOnlyLiveOutUses(SU))
    return;

  DEBUG(dbgs() << "VRegCycle: SU(" << SU->NodeNum << ")\n");

  SU->isVRegCycle = true;

  for (const SDep &Pred : SU->Preds) {
    if (Pred.isCtrl()) continue;
    Pred.getSUnit()->isVRegCycle = true;
  }
}

// After scheduling the definition of a VRegCycle, clear the isVRegCycle flag of
// CopyFromReg operands. We should no longer penalize other uses of this VReg.
static void resetVRegCycle(SUnit *SU) {
  if (!SU->isVRegCycle)
    return;

  for (const SDep &Pred : SU->Preds) {
    if (Pred.isCtrl()) continue;  // ignore chain preds
    SUnit *PredSU = Pred.getSUnit();
    if (PredSU->isVRegCycle) {
      assert(PredSU->getNode()->getOpcode() == ISD::CopyFromReg &&
             "VRegCycle def must be CopyFromReg");
      Pred.getSUnit()->isVRegCycle = false;
    }
  }
}

// Return true if this SUnit uses a CopyFromReg node marked as a VRegCycle. This
// means a node that defines the VRegCycle has not been scheduled yet.
static bool hasVRegCycleUse(const SUnit *SU) {
  // If this SU also defines the VReg, don't hoist it as a "use".
  if (SU->isVRegCycle)
    return false;

  for (const SDep &Pred : SU->Preds) {
    if (Pred.isCtrl()) continue;  // ignore chain preds
    if (Pred.getSUnit()->isVRegCycle &&
        Pred.getSUnit()->getNode()->getOpcode() == ISD::CopyFromReg) {
      DEBUG(dbgs() << "  VReg cycle use: SU (" << SU->NodeNum << ")\n");
      return true;
    }
  }
  return false;
}

// Check for either a dependence (latency) or resource (hazard) stall.
//
// Note: The ScheduleHazardRecognizer interface requires a non-const SU.
static bool BUHasStall(SUnit *SU, int Height, RegReductionPQBase *SPQ) {
  if ((int)SPQ->getCurCycle() < Height) return true;
  if (SPQ->getHazardRec()->getHazardType(SU, 0)
      != ScheduleHazardRecognizer::NoHazard)
    return true;
  return false;
}

// Return -1 if left has higher priority, 1 if right has higher priority.
// Return 0 if latency-based priority is equivalent.
static int BUCompareLatency(SUnit *left, SUnit *right, bool checkPref,
                            RegReductionPQBase *SPQ) {
  // Scheduling an instruction that uses a VReg whose postincrement has not yet
  // been scheduled will induce a copy. Model this as an extra cycle of latency.
  int LPenalty = hasVRegCycleUse(left) ? 1 : 0;
  int RPenalty = hasVRegCycleUse(right) ? 1 : 0;
  int LHeight = (int)left->getHeight() + LPenalty;
  int RHeight = (int)right->getHeight() + RPenalty;

  bool LStall = (!checkPref || left->SchedulingPref == Sched::ILP) &&
    BUHasStall(left, LHeight, SPQ);
  bool RStall = (!checkPref || right->SchedulingPref == Sched::ILP) &&
    BUHasStall(right, RHeight, SPQ);

  // If scheduling one of the node will cause a pipeline stall, delay it.
  // If scheduling either one of the node will cause a pipeline stall, sort
  // them according to their height.
  if (LStall) {
    if (!RStall)
      return 1;
    if (LHeight != RHeight)
      return LHeight > RHeight ? 1 : -1;
  } else if (RStall)
    return -1;

  // If either node is scheduling for latency, sort them by height/depth
  // and latency.
  if (!checkPref || (left->SchedulingPref == Sched::ILP ||
                     right->SchedulingPref == Sched::ILP)) {
    // If neither instruction stalls (!LStall && !RStall) and HazardRecognizer
    // is enabled, grouping instructions by cycle, then its height is already
    // covered so only its depth matters. We also reach this point if both stall
    // but have the same height.
    if (!SPQ->getHazardRec()->isEnabled()) {
      if (LHeight != RHeight)
        return LHeight > RHeight ? 1 : -1;
    }
    int LDepth = left->getDepth() - LPenalty;
    int RDepth = right->getDepth() - RPenalty;
    if (LDepth != RDepth) {
      DEBUG(dbgs() << "  Comparing latency of SU (" << left->NodeNum
            << ") depth " << LDepth << " vs SU (" << right->NodeNum
            << ") depth " << RDepth << "\n");
      return LDepth < RDepth ? 1 : -1;
    }
    if (left->Latency != right->Latency)
      return left->Latency > right->Latency ? 1 : -1;
  }
  return 0;
}

static bool BURRSort(SUnit *left, SUnit *right, RegReductionPQBase *SPQ) {
  // Schedule physical register definitions close to their use. This is
  // motivated by microarchitectures that can fuse cmp+jump macro-ops. But as
  // long as shortening physreg live ranges is generally good, we can defer
  // creating a subtarget hook.
  if (!DisableSchedPhysRegJoin) {
    bool LHasPhysReg = left->hasPhysRegDefs;
    bool RHasPhysReg = right->hasPhysRegDefs;
    if (LHasPhysReg != RHasPhysReg) {
      #ifndef NDEBUG
      static const char *const PhysRegMsg[] = { " has no physreg",
                                                " defines a physreg" };
      #endif
      DEBUG(dbgs() << "  SU (" << left->NodeNum << ") "
            << PhysRegMsg[LHasPhysReg] << " SU(" << right->NodeNum << ") "
            << PhysRegMsg[RHasPhysReg] << "\n");
      return LHasPhysReg < RHasPhysReg;
    }
  }

  // Prioritize by Sethi-Ulmann number and push CopyToReg nodes down.
  unsigned LPriority = SPQ->getNodePriority(left);
  unsigned RPriority = SPQ->getNodePriority(right);

  // Be really careful about hoisting call operands above previous calls.
  // Only allows it if it would reduce register pressure.
  if (left->isCall && right->isCallOp) {
    unsigned RNumVals = right->getNode()->getNumValues();
    RPriority = (RPriority > RNumVals) ? (RPriority - RNumVals) : 0;
  }
  if (right->isCall && left->isCallOp) {
    unsigned LNumVals = left->getNode()->getNumValues();
    LPriority = (LPriority > LNumVals) ? (LPriority - LNumVals) : 0;
  }

  if (LPriority != RPriority)
    return LPriority > RPriority;

  // One or both of the nodes are calls and their sethi-ullman numbers are the
  // same, then keep source order.
  if (left->isCall || right->isCall) {
    unsigned LOrder = SPQ->getNodeOrdering(left);
    unsigned ROrder = SPQ->getNodeOrdering(right);

    // Prefer an ordering where the lower the non-zero order number, the higher
    // the preference.
    if ((LOrder || ROrder) && LOrder != ROrder)
      return LOrder != 0 && (LOrder < ROrder || ROrder == 0);
  }

  // Try schedule def + use closer when Sethi-Ullman numbers are the same.
  // e.g.
  // t1 = op t2, c1
  // t3 = op t4, c2
  //
  // and the following instructions are both ready.
  // t2 = op c3
  // t4 = op c4
  //
  // Then schedule t2 = op first.
  // i.e.
  // t4 = op c4
  // t2 = op c3
  // t1 = op t2, c1
  // t3 = op t4, c2
  //
  // This creates more short live intervals.
  unsigned LDist = closestSucc(left);
  unsigned RDist = closestSucc(right);
  if (LDist != RDist)
    return LDist < RDist;

  // How many registers becomes live when the node is scheduled.
  unsigned LScratch = calcMaxScratches(left);
  unsigned RScratch = calcMaxScratches(right);
  if (LScratch != RScratch)
    return LScratch > RScratch;

  // Comparing latency against a call makes little sense unless the node
  // is register pressure-neutral.
  if ((left->isCall && RPriority > 0) || (right->isCall && LPriority > 0))
    return (left->NodeQueueId > right->NodeQueueId);

  // Do not compare latencies when one or both of the nodes are calls.
  if (!DisableSchedCycles &&
      !(left->isCall || right->isCall)) {
    int result = BUCompareLatency(left, right, false /*checkPref*/, SPQ);
    if (result != 0)
      return result > 0;
  }
  else {
    if (left->getHeight() != right->getHeight())
      return left->getHeight() > right->getHeight();

    if (left->getDepth() != right->getDepth())
      return left->getDepth() < right->getDepth();
  }

  assert(left->NodeQueueId && right->NodeQueueId &&
         "NodeQueueId cannot be zero");
  return (left->NodeQueueId > right->NodeQueueId);
}

// Bottom up
bool bu_ls_rr_sort::operator()(SUnit *left, SUnit *right) const {
  if (int res = checkSpecialNodes(left, right))
    return res > 0;

  return BURRSort(left, right, SPQ);
}

// Source order, otherwise bottom up.
bool src_ls_rr_sort::operator()(SUnit *left, SUnit *right) const {
  if (int res = checkSpecialNodes(left, right))
    return res > 0;

  unsigned LOrder = SPQ->getNodeOrdering(left);
  unsigned ROrder = SPQ->getNodeOrdering(right);

  // Prefer an ordering where the lower the non-zero order number, the higher
  // the preference.
  if ((LOrder || ROrder) && LOrder != ROrder)
    return LOrder != 0 && (LOrder < ROrder || ROrder == 0);

  return BURRSort(left, right, SPQ);
}

// If the time between now and when the instruction will be ready can cover
// the spill code, then avoid adding it to the ready queue. This gives long
// stalls highest priority and allows hoisting across calls. It should also
// speed up processing the available queue.
bool hybrid_ls_rr_sort::isReady(SUnit *SU, unsigned CurCycle) const {
  static const unsigned ReadyDelay = 3;

  if (SPQ->MayReduceRegPressure(SU)) return true;

  if (SU->getHeight() > (CurCycle + ReadyDelay)) return false;

  if (SPQ->getHazardRec()->getHazardType(SU, -ReadyDelay)
      != ScheduleHazardRecognizer::NoHazard)
    return false;

  return true;
}

// Return true if right should be scheduled with higher priority than left.
bool hybrid_ls_rr_sort::operator()(SUnit *left, SUnit *right) const {
  if (int res = checkSpecialNodes(left, right))
    return res > 0;

  if (left->isCall || right->isCall)
    // No way to compute latency of calls.
    return BURRSort(left, right, SPQ);

  bool LHigh = SPQ->HighRegPressure(left);
  bool RHigh = SPQ->HighRegPressure(right);
  // Avoid causing spills. If register pressure is high, schedule for
  // register pressure reduction.
  if (LHigh && !RHigh) {
    DEBUG(dbgs() << "  pressure SU(" << left->NodeNum << ") > SU("
          << right->NodeNum << ")\n");
    return true;
  }
  else if (!LHigh && RHigh) {
    DEBUG(dbgs() << "  pressure SU(" << right->NodeNum << ") > SU("
          << left->NodeNum << ")\n");
    return false;
  }
  if (!LHigh && !RHigh) {
    int result = BUCompareLatency(left, right, true /*checkPref*/, SPQ);
    if (result != 0)
      return result > 0;
  }
  return BURRSort(left, right, SPQ);
}

// Schedule as many instructions in each cycle as possible. So don't make an
// instruction available unless it is ready in the current cycle.
bool ilp_ls_rr_sort::isReady(SUnit *SU, unsigned CurCycle) const {
  if (SU->getHeight() > CurCycle) return false;

  if (SPQ->getHazardRec()->getHazardType(SU, 0)
      != ScheduleHazardRecognizer::NoHazard)
    return false;

  return true;
}

static bool canEnableCoalescing(SUnit *SU) {
  unsigned Opc = SU->getNode() ? SU->getNode()->getOpcode() : 0;
  if (Opc == ISD::TokenFactor || Opc == ISD::CopyToReg)
    // CopyToReg should be close to its uses to facilitate coalescing and
    // avoid spilling.
    return true;

  if (Opc == TargetOpcode::EXTRACT_SUBREG ||
      Opc == TargetOpcode::SUBREG_TO_REG ||
      Opc == TargetOpcode::INSERT_SUBREG)
    // EXTRACT_SUBREG, INSERT_SUBREG, and SUBREG_TO_REG nodes should be
    // close to their uses to facilitate coalescing.
    return true;

  if (SU->NumPreds == 0 && SU->NumSuccs != 0)
    // If SU does not have a register def, schedule it close to its uses
    // because it does not lengthen any live ranges.
    return true;

  return false;
}

// list-ilp is currently an experimental scheduler that allows various
// heuristics to be enabled prior to the normal register reduction logic.
bool ilp_ls_rr_sort::operator()(SUnit *left, SUnit *right) const {
  if (int res = checkSpecialNodes(left, right))
    return res > 0;

  if (left->isCall || right->isCall)
    // No way to compute latency of calls.
    return BURRSort(left, right, SPQ);

  unsigned LLiveUses = 0, RLiveUses = 0;
  int LPDiff = 0, RPDiff = 0;
  if (!DisableSchedRegPressure || !DisableSchedLiveUses) {
    LPDiff = SPQ->RegPressureDiff(left, LLiveUses);
    RPDiff = SPQ->RegPressureDiff(right, RLiveUses);
  }
  if (!DisableSchedRegPressure && LPDiff != RPDiff) {
    DEBUG(dbgs() << "RegPressureDiff SU(" << left->NodeNum << "): " << LPDiff
          << " != SU(" << right->NodeNum << "): " << RPDiff << "\n");
    return LPDiff > RPDiff;
  }

  if (!DisableSchedRegPressure && (LPDiff > 0 || RPDiff > 0)) {
    bool LReduce = canEnableCoalescing(left);
    bool RReduce = canEnableCoalescing(right);
    if (LReduce && !RReduce) return false;
    if (RReduce && !LReduce) return true;
  }

  if (!DisableSchedLiveUses && (LLiveUses != RLiveUses)) {
    DEBUG(dbgs() << "Live uses SU(" << left->NodeNum << "): " << LLiveUses
          << " != SU(" << right->NodeNum << "): " << RLiveUses << "\n");
    return LLiveUses < RLiveUses;
  }

  if (!DisableSchedStalls) {
    bool LStall = BUHasStall(left, left->getHeight(), SPQ);
    bool RStall = BUHasStall(right, right->getHeight(), SPQ);
    if (LStall != RStall)
      return left->getHeight() > right->getHeight();
  }

  if (!DisableSchedCriticalPath) {
    int spread = (int)left->getDepth() - (int)right->getDepth();
    if (std::abs(spread) > MaxReorderWindow) {
      DEBUG(dbgs() << "Depth of SU(" << left->NodeNum << "): "
            << left->getDepth() << " != SU(" << right->NodeNum << "): "
            << right->getDepth() << "\n");
      return left->getDepth() < right->getDepth();
    }
  }

  if (!DisableSchedHeight && left->getHeight() != right->getHeight()) {
    int spread = (int)left->getHeight() - (int)right->getHeight();
    if (std::abs(spread) > MaxReorderWindow)
      return left->getHeight() > right->getHeight();
  }

  return BURRSort(left, right, SPQ);
}

void RegReductionPQBase::initNodes(std::vector<SUnit> &sunits) {
  SUnits = &sunits;
  // Add pseudo dependency edges for two-address nodes.
  if (!Disable2AddrHack)
    AddPseudoTwoAddrDeps();
  // Reroute edges to nodes with multiple uses.
  if (!TracksRegPressure && !SrcOrder)
    PrescheduleNodesWithMultipleUses();
  // Calculate node priorities.
  CalculateSethiUllmanNumbers();

  // For single block loops, mark nodes that look like canonical IV increments.
  if (scheduleDAG->BB->isSuccessor(scheduleDAG->BB))
    for (SUnit &SU : sunits)
      initVRegCycle(&SU);
}

//===----------------------------------------------------------------------===//
//                    Preschedule for Register Pressure
//===----------------------------------------------------------------------===//

bool RegReductionPQBase::canClobber(const SUnit *SU, const SUnit *Op) {
  if (SU->isTwoAddress) {
    unsigned Opc = SU->getNode()->getMachineOpcode();
    const MCInstrDesc &MCID = TII->get(Opc);
    unsigned NumRes = MCID.getNumDefs();
    unsigned NumOps = MCID.getNumOperands() - NumRes;
    for (unsigned i = 0; i != NumOps; ++i) {
      if (MCID.getOperandConstraint(i+NumRes, MCOI::TIED_TO) != -1) {
        SDNode *DU = SU->getNode()->getOperand(i).getNode();
        if (DU->getNodeId() != -1 &&
            Op->OrigNode == &(*SUnits)[DU->getNodeId()])
          return true;
      }
    }
  }
  return false;
}

/// canClobberReachingPhysRegUse - True if SU would clobber one of it's
/// successor's explicit physregs whose definition can reach DepSU.
/// i.e. DepSU should not be scheduled above SU.
static bool canClobberReachingPhysRegUse(const SUnit *DepSU, const SUnit *SU,
                                         ScheduleDAGRRList *scheduleDAG,
                                         const TargetInstrInfo *TII,
                                         const TargetRegisterInfo *TRI) {
  const MCPhysReg *ImpDefs
    = TII->get(SU->getNode()->getMachineOpcode()).getImplicitDefs();
  const uint32_t *RegMask = getNodeRegMask(SU->getNode());
  if(!ImpDefs && !RegMask)
    return false;

  for (const SDep &Succ : SU->Succs) {
    SUnit *SuccSU = Succ.getSUnit();
    for (const SDep &SuccPred : SuccSU->Preds) {
      if (!SuccPred.isAssignedRegDep())
        continue;

      if (RegMask &&
          MachineOperand::clobbersPhysReg(RegMask, SuccPred.getReg()) &&
          scheduleDAG->IsReachable(DepSU, SuccPred.getSUnit()))
        return true;

      if (ImpDefs)
        for (const MCPhysReg *ImpDef = ImpDefs; *ImpDef; ++ImpDef)
          // Return true if SU clobbers this physical register use and the
          // definition of the register reaches from DepSU. IsReachable queries
          // a topological forward sort of the DAG (following the successors).
          if (TRI->regsOverlap(*ImpDef, SuccPred.getReg()) &&
              scheduleDAG->IsReachable(DepSU, SuccPred.getSUnit()))
            return true;
    }
  }
  return false;
}

/// canClobberPhysRegDefs - True if SU would clobber one of SuccSU's
/// physical register defs.
static bool canClobberPhysRegDefs(const SUnit *SuccSU, const SUnit *SU,
                                  const TargetInstrInfo *TII,
                                  const TargetRegisterInfo *TRI) {
  SDNode *N = SuccSU->getNode();
  unsigned NumDefs = TII->get(N->getMachineOpcode()).getNumDefs();
  const MCPhysReg *ImpDefs = TII->get(N->getMachineOpcode()).getImplicitDefs();
  assert(ImpDefs && "Caller should check hasPhysRegDefs");
  for (const SDNode *SUNode = SU->getNode(); SUNode;
       SUNode = SUNode->getGluedNode()) {
    if (!SUNode->isMachineOpcode())
      continue;
    const MCPhysReg *SUImpDefs =
      TII->get(SUNode->getMachineOpcode()).getImplicitDefs();
    const uint32_t *SURegMask = getNodeRegMask(SUNode);
    if (!SUImpDefs && !SURegMask)
      continue;
    for (unsigned i = NumDefs, e = N->getNumValues(); i != e; ++i) {
      MVT VT = N->getSimpleValueType(i);
      if (VT == MVT::Glue || VT == MVT::Other)
        continue;
      if (!N->hasAnyUseOfValue(i))
        continue;
      unsigned Reg = ImpDefs[i - NumDefs];
      if (SURegMask && MachineOperand::clobbersPhysReg(SURegMask, Reg))
        return true;
      if (!SUImpDefs)
        continue;
      for (;*SUImpDefs; ++SUImpDefs) {
        unsigned SUReg = *SUImpDefs;
        if (TRI->regsOverlap(Reg, SUReg))
          return true;
      }
    }
  }
  return false;
}

/// PrescheduleNodesWithMultipleUses - Nodes with multiple uses
/// are not handled well by the general register pressure reduction
/// heuristics. When presented with code like this:
///
///      N
///    / |
///   /  |
///  U  store
///  |
/// ...
///
/// the heuristics tend to push the store up, but since the
/// operand of the store has another use (U), this would increase
/// the length of that other use (the U->N edge).
///
/// This function transforms code like the above to route U's
/// dependence through the store when possible, like this:
///
///      N
///      ||
///      ||
///     store
///       |
///       U
///       |
///      ...
///
/// This results in the store being scheduled immediately
/// after N, which shortens the U->N live range, reducing
/// register pressure.
void RegReductionPQBase::PrescheduleNodesWithMultipleUses() {
  // Visit all the nodes in topological order, working top-down.
  for (SUnit &SU : *SUnits) {
    // For now, only look at nodes with no data successors, such as stores.
    // These are especially important, due to the heuristics in
    // getNodePriority for nodes with no data successors.
    if (SU.NumSuccs != 0)
      continue;
    // For now, only look at nodes with exactly one data predecessor.
    if (SU.NumPreds != 1)
      continue;
    // Avoid prescheduling copies to virtual registers, which don't behave
    // like other nodes from the perspective of scheduling heuristics.
    if (SDNode *N = SU.getNode())
      if (N->getOpcode() == ISD::CopyToReg &&
          TargetRegisterInfo::isVirtualRegister
            (cast<RegisterSDNode>(N->getOperand(1))->getReg()))
        continue;

    // Locate the single data predecessor.
    SUnit *PredSU = nullptr;
    for (const SDep &Pred : SU.Preds)
      if (!Pred.isCtrl()) {
        PredSU = Pred.getSUnit();
        break;
      }
    assert(PredSU);

    // Don't rewrite edges that carry physregs, because that requires additional
    // support infrastructure.
    if (PredSU->hasPhysRegDefs)
      continue;
    // Short-circuit the case where SU is PredSU's only data successor.
    if (PredSU->NumSuccs == 1)
      continue;
    // Avoid prescheduling to copies from virtual registers, which don't behave
    // like other nodes from the perspective of scheduling heuristics.
    if (SDNode *N = SU.getNode())
      if (N->getOpcode() == ISD::CopyFromReg &&
          TargetRegisterInfo::isVirtualRegister
            (cast<RegisterSDNode>(N->getOperand(1))->getReg()))
        continue;

    // Perform checks on the successors of PredSU.
    for (const SDep &PredSucc : PredSU->Succs) {
      SUnit *PredSuccSU = PredSucc.getSUnit();
      if (PredSuccSU == &SU) continue;
      // If PredSU has another successor with no data successors, for
      // now don't attempt to choose either over the other.
      if (PredSuccSU->NumSuccs == 0)
        goto outer_loop_continue;
      // Don't break physical register dependencies.
      if (SU.hasPhysRegClobbers && PredSuccSU->hasPhysRegDefs)
        if (canClobberPhysRegDefs(PredSuccSU, &SU, TII, TRI))
          goto outer_loop_continue;
      // Don't introduce graph cycles.
      if (scheduleDAG->IsReachable(&SU, PredSuccSU))
        goto outer_loop_continue;
    }

    // Ok, the transformation is safe and the heuristics suggest it is
    // profitable. Update the graph.
    DEBUG(dbgs() << "    Prescheduling SU #" << SU.NodeNum
                 << " next to PredSU #" << PredSU->NodeNum
                 << " to guide scheduling in the presence of multiple uses\n");
    for (unsigned i = 0; i != PredSU->Succs.size(); ++i) {
      SDep Edge = PredSU->Succs[i];
      assert(!Edge.isAssignedRegDep());
      SUnit *SuccSU = Edge.getSUnit();
      if (SuccSU != &SU) {
        Edge.setSUnit(PredSU);
        scheduleDAG->RemovePred(SuccSU, Edge);
        scheduleDAG->AddPred(&SU, Edge);
        Edge.setSUnit(&SU);
        scheduleDAG->AddPred(SuccSU, Edge);
        --i;
      }
    }
  outer_loop_continue:;
  }
}

/// AddPseudoTwoAddrDeps - If two nodes share an operand and one of them uses
/// it as a def&use operand. Add a pseudo control edge from it to the other
/// node (if it won't create a cycle) so the two-address one will be scheduled
/// first (lower in the schedule). If both nodes are two-address, favor the
/// one that has a CopyToReg use (more likely to be a loop induction update).
/// If both are two-address, but one is commutable while the other is not
/// commutable, favor the one that's not commutable.
void RegReductionPQBase::AddPseudoTwoAddrDeps() {
  for (SUnit &SU : *SUnits) {
    if (!SU.isTwoAddress)
      continue;

    SDNode *Node = SU.getNode();
    if (!Node || !Node->isMachineOpcode() || SU.getNode()->getGluedNode())
      continue;

    bool isLiveOut = hasOnlyLiveOutUses(&SU);
    unsigned Opc = Node->getMachineOpcode();
    const MCInstrDesc &MCID = TII->get(Opc);
    unsigned NumRes = MCID.getNumDefs();
    unsigned NumOps = MCID.getNumOperands() - NumRes;
    for (unsigned j = 0; j != NumOps; ++j) {
      if (MCID.getOperandConstraint(j+NumRes, MCOI::TIED_TO) == -1)
        continue;
      SDNode *DU = SU.getNode()->getOperand(j).getNode();
      if (DU->getNodeId() == -1)
        continue;
      const SUnit *DUSU = &(*SUnits)[DU->getNodeId()];
      if (!DUSU)
        continue;
      for (const SDep &Succ : DUSU->Succs) {
        if (Succ.isCtrl())
          continue;
        SUnit *SuccSU = Succ.getSUnit();
        if (SuccSU == &SU)
          continue;
        // Be conservative. Ignore if nodes aren't at roughly the same
        // depth and height.
        if (SuccSU->getHeight() < SU.getHeight() &&
            (SU.getHeight() - SuccSU->getHeight()) > 1)
          continue;
        // Skip past COPY_TO_REGCLASS nodes, so that the pseudo edge
        // constrains whatever is using the copy, instead of the copy
        // itself. In the case that the copy is coalesced, this
        // preserves the intent of the pseudo two-address heurietics.
        while (SuccSU->Succs.size() == 1 &&
               SuccSU->getNode()->isMachineOpcode() &&
               SuccSU->getNode()->getMachineOpcode() ==
                 TargetOpcode::COPY_TO_REGCLASS)
          SuccSU = SuccSU->Succs.front().getSUnit();
        // Don't constrain non-instruction nodes.
        if (!SuccSU->getNode() || !SuccSU->getNode()->isMachineOpcode())
          continue;
        // Don't constrain nodes with physical register defs if the
        // predecessor can clobber them.
        if (SuccSU->hasPhysRegDefs && SU.hasPhysRegClobbers) {
          if (canClobberPhysRegDefs(SuccSU, &SU, TII, TRI))
            continue;
        }
        // Don't constrain EXTRACT_SUBREG, INSERT_SUBREG, and SUBREG_TO_REG;
        // these may be coalesced away. We want them close to their uses.
        unsigned SuccOpc = SuccSU->getNode()->getMachineOpcode();
        if (SuccOpc == TargetOpcode::EXTRACT_SUBREG ||
            SuccOpc == TargetOpcode::INSERT_SUBREG ||
            SuccOpc == TargetOpcode::SUBREG_TO_REG)
          continue;
        if (!canClobberReachingPhysRegUse(SuccSU, &SU, scheduleDAG, TII, TRI) &&
            (!canClobber(SuccSU, DUSU) ||
             (isLiveOut && !hasOnlyLiveOutUses(SuccSU)) ||
             (!SU.isCommutable && SuccSU->isCommutable)) &&
            !scheduleDAG->IsReachable(SuccSU, &SU)) {
          DEBUG(dbgs() << "    Adding a pseudo-two-addr edge from SU #"
                       << SU.NodeNum << " to SU #" << SuccSU->NodeNum << "\n");
          scheduleDAG->AddPred(&SU, SDep(SuccSU, SDep::Artificial));
        }
      }
    }
  }
}

//===----------------------------------------------------------------------===//
//                         Public Constructor Functions
//===----------------------------------------------------------------------===//

ScheduleDAGSDNodes *
llvm::createBURRListDAGScheduler(SelectionDAGISel *IS,
                                 CodeGenOpt::Level OptLevel) {
  const TargetSubtargetInfo &STI = IS->MF->getSubtarget();
  const TargetInstrInfo *TII = STI.getInstrInfo();
  const TargetRegisterInfo *TRI = STI.getRegisterInfo();

  BURegReductionPriorityQueue *PQ =
    new BURegReductionPriorityQueue(*IS->MF, false, false, TII, TRI, nullptr);
  ScheduleDAGRRList *SD = new ScheduleDAGRRList(*IS->MF, false, PQ, OptLevel);
  PQ->setScheduleDAG(SD);
  return SD;
}

ScheduleDAGSDNodes *
llvm::createSourceListDAGScheduler(SelectionDAGISel *IS,
                                   CodeGenOpt::Level OptLevel) {
  const TargetSubtargetInfo &STI = IS->MF->getSubtarget();
  const TargetInstrInfo *TII = STI.getInstrInfo();
  const TargetRegisterInfo *TRI = STI.getRegisterInfo();

  SrcRegReductionPriorityQueue *PQ =
    new SrcRegReductionPriorityQueue(*IS->MF, false, true, TII, TRI, nullptr);
  ScheduleDAGRRList *SD = new ScheduleDAGRRList(*IS->MF, false, PQ, OptLevel);
  PQ->setScheduleDAG(SD);
  return SD;
}

ScheduleDAGSDNodes *
llvm::createHybridListDAGScheduler(SelectionDAGISel *IS,
                                   CodeGenOpt::Level OptLevel) {
  const TargetSubtargetInfo &STI = IS->MF->getSubtarget();
  const TargetInstrInfo *TII = STI.getInstrInfo();
  const TargetRegisterInfo *TRI = STI.getRegisterInfo();
  const TargetLowering *TLI = IS->TLI;

  HybridBURRPriorityQueue *PQ =
    new HybridBURRPriorityQueue(*IS->MF, true, false, TII, TRI, TLI);

  ScheduleDAGRRList *SD = new ScheduleDAGRRList(*IS->MF, true, PQ, OptLevel);
  PQ->setScheduleDAG(SD);
  return SD;
}

ScheduleDAGSDNodes *
llvm::createILPListDAGScheduler(SelectionDAGISel *IS,
                                CodeGenOpt::Level OptLevel) {
  const TargetSubtargetInfo &STI = IS->MF->getSubtarget();
  const TargetInstrInfo *TII = STI.getInstrInfo();
  const TargetRegisterInfo *TRI = STI.getRegisterInfo();
  const TargetLowering *TLI = IS->TLI;

  ILPBURRPriorityQueue *PQ =
    new ILPBURRPriorityQueue(*IS->MF, true, false, TII, TRI, TLI);
  ScheduleDAGRRList *SD = new ScheduleDAGRRList(*IS->MF, true, PQ, OptLevel);
  PQ->setScheduleDAG(SD);
  return SD;
}
