//===------ RegAllocPBQP.cpp ---- PBQP Register Allocator -------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a Partitioned Boolean Quadratic Programming (PBQP) based
// register allocator for LLVM. This allocator works by constructing a PBQP
// problem representing the register allocation problem under consideration,
// solving this using a PBQP solver, and mapping the solution back to a
// register assignment. If any variables are selected for spilling then spill
// code is inserted and the process repeated.
//
// The PBQP solver (pbqp.c) provided for this allocator uses a heuristic tuned
// for register allocation. For more information on PBQP for register
// allocation, see the following papers:
//
//   (1) Hames, L. and Scholz, B. 2006. Nearly optimal register allocation with
//   PBQP. In Proceedings of the 7th Joint Modular Languages Conference
//   (JMLC'06). LNCS, vol. 4228. Springer, New York, NY, USA. 346-361.
//
//   (2) Scholz, B., Eckstein, E. 2002. Register allocation for irregular
//   architectures. In Proceedings of the Joint Conference on Languages,
//   Compilers and Tools for Embedded Systems (LCTES'02), ACM Press, New York,
//   NY, USA, 139-148.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "regalloc"

#include "PBQP/HeuristicSolver.h"
#include "PBQP/Graph.h"
#include "PBQP/Heuristics/Briggs.h"
#include "RenderMachineFunction.h"
#include "Splitter.h"
#include "VirtRegMap.h"
#include "VirtRegRewriter.h"
#include "llvm/CodeGen/CalcSpillWeights.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/LiveStackAnalysis.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/RegisterCoalescer.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include <limits>
#include <map>
#include <memory>
#include <set>
#include <vector>

using namespace llvm;

static RegisterRegAlloc
registerPBQPRepAlloc("pbqp", "PBQP register allocator",
                       llvm::createPBQPRegisterAllocator);

static cl::opt<bool>
pbqpCoalescing("pbqp-coalescing",
                cl::desc("Attempt coalescing during PBQP register allocation."),
                cl::init(false), cl::Hidden);

static cl::opt<bool>
pbqpPreSplitting("pbqp-pre-splitting",
                 cl::desc("Pre-splite before PBQP register allocation."),
                 cl::init(false), cl::Hidden);

namespace {

  ///
  /// PBQP based allocators solve the register allocation problem by mapping
  /// register allocation problems to Partitioned Boolean Quadratic
  /// Programming problems.
  class PBQPRegAlloc : public MachineFunctionPass {
  public:

    static char ID;

    /// Construct a PBQP register allocator.
    PBQPRegAlloc() : MachineFunctionPass(&ID) {}

    /// Return the pass name.
    virtual const char* getPassName() const {
      return "PBQP Register Allocator";
    }

    /// PBQP analysis usage.
    virtual void getAnalysisUsage(AnalysisUsage &au) const {
      au.addRequired<SlotIndexes>();
      au.addPreserved<SlotIndexes>();
      au.addRequired<LiveIntervals>();
      //au.addRequiredID(SplitCriticalEdgesID);
      au.addRequired<RegisterCoalescer>();
      au.addRequired<CalculateSpillWeights>();
      au.addRequired<LiveStacks>();
      au.addPreserved<LiveStacks>();
      au.addRequired<MachineLoopInfo>();
      au.addPreserved<MachineLoopInfo>();
      if (pbqpPreSplitting)
        au.addRequired<LoopSplitter>();
      au.addRequired<VirtRegMap>();
      au.addRequired<RenderMachineFunction>();
      MachineFunctionPass::getAnalysisUsage(au);
    }

    /// Perform register allocation
    virtual bool runOnMachineFunction(MachineFunction &MF);

  private:

    class LIOrdering {
    public:
      bool operator()(const LiveInterval *li1, const LiveInterval *li2) const {
        return li1->reg < li2->reg;
      }
    };

    typedef std::map<const LiveInterval*, unsigned, LIOrdering> LI2NodeMap;
    typedef std::vector<const LiveInterval*> Node2LIMap;
    typedef std::vector<unsigned> AllowedSet;
    typedef std::vector<AllowedSet> AllowedSetMap;
    typedef std::set<unsigned> RegSet;
    typedef std::pair<unsigned, unsigned> RegPair;
    typedef std::map<RegPair, PBQP::PBQPNum> CoalesceMap;

    typedef std::set<LiveInterval*, LIOrdering> LiveIntervalSet;

    typedef std::vector<PBQP::Graph::NodeItr> NodeVector;

    MachineFunction *mf;
    const TargetMachine *tm;
    const TargetRegisterInfo *tri;
    const TargetInstrInfo *tii;
    const MachineLoopInfo *loopInfo;
    MachineRegisterInfo *mri;

    LiveIntervals *lis;
    LiveStacks *lss;
    VirtRegMap *vrm;

    LI2NodeMap li2Node;
    Node2LIMap node2LI;
    AllowedSetMap allowedSets;
    LiveIntervalSet vregIntervalsToAlloc,
                    emptyVRegIntervals;
    NodeVector problemNodes;


    /// Builds a PBQP cost vector.
    template <typename RegContainer>
    PBQP::Vector buildCostVector(unsigned vReg,
                                 const RegContainer &allowed,
                                 const CoalesceMap &cealesces,
                                 PBQP::PBQPNum spillCost) const;

    /// \brief Builds a PBQP interference matrix.
    ///
    /// @return Either a pointer to a non-zero PBQP matrix representing the
    ///         allocation option costs, or a null pointer for a zero matrix.
    ///
    /// Expects allowed sets for two interfering LiveIntervals. These allowed
    /// sets should contain only allocable registers from the LiveInterval's
    /// register class, with any interfering pre-colored registers removed.
    template <typename RegContainer>
    PBQP::Matrix* buildInterferenceMatrix(const RegContainer &allowed1,
                                          const RegContainer &allowed2) const;

    ///
    /// Expects allowed sets for two potentially coalescable LiveIntervals,
    /// and an estimated benefit due to coalescing. The allowed sets should
    /// contain only allocable registers from the LiveInterval's register
    /// classes, with any interfering pre-colored registers removed.
    template <typename RegContainer>
    PBQP::Matrix* buildCoalescingMatrix(const RegContainer &allowed1,
                                        const RegContainer &allowed2,
                                        PBQP::PBQPNum cBenefit) const;

    /// \brief Finds coalescing opportunities and returns them as a map.
    ///
    /// Any entries in the map are guaranteed coalescable, even if their
    /// corresponding live intervals overlap.
    CoalesceMap findCoalesces();

    /// \brief Finds the initial set of vreg intervals to allocate.
    void findVRegIntervalsToAlloc();

    /// \brief Constructs a PBQP problem representation of the register
    /// allocation problem for this function.
    ///
    /// @return a PBQP solver object for the register allocation problem.
    PBQP::Graph constructPBQPProblem();

    /// \brief Adds a stack interval if the given live interval has been
    /// spilled. Used to support stack slot coloring.
    void addStackInterval(const LiveInterval *spilled,MachineRegisterInfo* mri);

    /// \brief Given a solved PBQP problem maps this solution back to a register
    /// assignment.
    bool mapPBQPToRegAlloc(const PBQP::Solution &solution);

    /// \brief Postprocessing before final spilling. Sets basic block "live in"
    /// variables.
    void finalizeAlloc() const;

  };

  char PBQPRegAlloc::ID = 0;
}


template <typename RegContainer>
PBQP::Vector PBQPRegAlloc::buildCostVector(unsigned vReg,
                                           const RegContainer &allowed,
                                           const CoalesceMap &coalesces,
                                           PBQP::PBQPNum spillCost) const {

  typedef typename RegContainer::const_iterator AllowedItr;

  // Allocate vector. Additional element (0th) used for spill option
  PBQP::Vector v(allowed.size() + 1, 0);

  v[0] = spillCost;

  // Iterate over the allowed registers inserting coalesce benefits if there
  // are any.
  unsigned ai = 0;
  for (AllowedItr itr = allowed.begin(), end = allowed.end();
       itr != end; ++itr, ++ai) {

    unsigned pReg = *itr;

    CoalesceMap::const_iterator cmItr =
      coalesces.find(RegPair(vReg, pReg));

    // No coalesce - on to the next preg.
    if (cmItr == coalesces.end())
      continue;

    // We have a coalesce - insert the benefit.
    v[ai + 1] = -cmItr->second;
  }

  return v;
}

template <typename RegContainer>
PBQP::Matrix* PBQPRegAlloc::buildInterferenceMatrix(
      const RegContainer &allowed1, const RegContainer &allowed2) const {

  typedef typename RegContainer::const_iterator RegContainerIterator;

  // Construct a PBQP matrix representing the cost of allocation options. The
  // rows and columns correspond to the allocation options for the two live
  // intervals.  Elements will be infinite where corresponding registers alias,
  // since we cannot allocate aliasing registers to interfering live intervals.
  // All other elements (non-aliasing combinations) will have zero cost. Note
  // that the spill option (element 0,0) has zero cost, since we can allocate
  // both intervals to memory safely (the cost for each individual allocation
  // to memory is accounted for by the cost vectors for each live interval).
  PBQP::Matrix *m =
    new PBQP::Matrix(allowed1.size() + 1, allowed2.size() + 1, 0);

  // Assume this is a zero matrix until proven otherwise.  Zero matrices occur
  // between interfering live ranges with non-overlapping register sets (e.g.
  // non-overlapping reg classes, or disjoint sets of allowed regs within the
  // same class). The term "overlapping" is used advisedly: sets which do not
  // intersect, but contain registers which alias, will have non-zero matrices.
  // We optimize zero matrices away to improve solver speed.
  bool isZeroMatrix = true;


  // Row index. Starts at 1, since the 0th row is for the spill option, which
  // is always zero.
  unsigned ri = 1;

  // Iterate over allowed sets, insert infinities where required.
  for (RegContainerIterator a1Itr = allowed1.begin(), a1End = allowed1.end();
       a1Itr != a1End; ++a1Itr) {

    // Column index, starts at 1 as for row index.
    unsigned ci = 1;
    unsigned reg1 = *a1Itr;

    for (RegContainerIterator a2Itr = allowed2.begin(), a2End = allowed2.end();
         a2Itr != a2End; ++a2Itr) {

      unsigned reg2 = *a2Itr;

      // If the row/column regs are identical or alias insert an infinity.
      if (tri->regsOverlap(reg1, reg2)) {
        (*m)[ri][ci] = std::numeric_limits<PBQP::PBQPNum>::infinity();
        isZeroMatrix = false;
      }

      ++ci;
    }

    ++ri;
  }

  // If this turns out to be a zero matrix...
  if (isZeroMatrix) {
    // free it and return null.
    delete m;
    return 0;
  }

  // ...otherwise return the cost matrix.
  return m;
}

template <typename RegContainer>
PBQP::Matrix* PBQPRegAlloc::buildCoalescingMatrix(
      const RegContainer &allowed1, const RegContainer &allowed2,
      PBQP::PBQPNum cBenefit) const {

  typedef typename RegContainer::const_iterator RegContainerIterator;

  // Construct a PBQP Matrix representing the benefits of coalescing. As with
  // interference matrices the rows and columns represent allowed registers
  // for the LiveIntervals which are (potentially) to be coalesced. The amount
  // -cBenefit will be placed in any element representing the same register
  // for both intervals.
  PBQP::Matrix *m =
    new PBQP::Matrix(allowed1.size() + 1, allowed2.size() + 1, 0);

  // Reset costs to zero.
  m->reset(0);

  // Assume the matrix is zero till proven otherwise. Zero matrices will be
  // optimized away as in the interference case.
  bool isZeroMatrix = true;

  // Row index. Starts at 1, since the 0th row is for the spill option, which
  // is always zero.
  unsigned ri = 1;

  // Iterate over the allowed sets, insert coalescing benefits where
  // appropriate.
  for (RegContainerIterator a1Itr = allowed1.begin(), a1End = allowed1.end();
       a1Itr != a1End; ++a1Itr) {

    // Column index, starts at 1 as for row index.
    unsigned ci = 1;
    unsigned reg1 = *a1Itr;

    for (RegContainerIterator a2Itr = allowed2.begin(), a2End = allowed2.end();
         a2Itr != a2End; ++a2Itr) {

      // If the row and column represent the same register insert a beneficial
      // cost to preference this allocation - it would allow us to eliminate a
      // move instruction.
      if (reg1 == *a2Itr) {
        (*m)[ri][ci] = -cBenefit;
        isZeroMatrix = false;
      }

      ++ci;
    }

    ++ri;
  }

  // If this turns out to be a zero matrix...
  if (isZeroMatrix) {
    // ...free it and return null.
    delete m;
    return 0;
  }

  return m;
}

PBQPRegAlloc::CoalesceMap PBQPRegAlloc::findCoalesces() {

  typedef MachineFunction::const_iterator MFIterator;
  typedef MachineBasicBlock::const_iterator MBBIterator;
  typedef LiveInterval::const_vni_iterator VNIIterator;

  CoalesceMap coalescesFound;

  // To find coalesces we need to iterate over the function looking for
  // copy instructions.
  for (MFIterator bbItr = mf->begin(), bbEnd = mf->end();
       bbItr != bbEnd; ++bbItr) {

    const MachineBasicBlock *mbb = &*bbItr;

    for (MBBIterator iItr = mbb->begin(), iEnd = mbb->end();
         iItr != iEnd; ++iItr) {

      const MachineInstr *instr = &*iItr;

      // If this isn't a copy then continue to the next instruction.
      if (!instr->isCopy())
        continue;

      unsigned srcReg = instr->getOperand(1).getReg();
      unsigned dstReg = instr->getOperand(0).getReg();

      // If the registers are already the same our job is nice and easy.
      if (dstReg == srcReg)
        continue;

      bool srcRegIsPhysical = TargetRegisterInfo::isPhysicalRegister(srcReg),
           dstRegIsPhysical = TargetRegisterInfo::isPhysicalRegister(dstReg);

      // If both registers are physical then we can't coalesce.
      if (srcRegIsPhysical && dstRegIsPhysical)
        continue;

      // If it's a copy that includes two virtual register but the source and
      // destination classes differ then we can't coalesce.
      if (!srcRegIsPhysical && !dstRegIsPhysical &&
          mri->getRegClass(srcReg) != mri->getRegClass(dstReg))
        continue;

      // If one is physical and one is virtual, check that the physical is
      // allocatable in the class of the virtual.
      if (srcRegIsPhysical && !dstRegIsPhysical) {
        const TargetRegisterClass *dstRegClass = mri->getRegClass(dstReg);
        if (std::find(dstRegClass->allocation_order_begin(*mf),
                      dstRegClass->allocation_order_end(*mf), srcReg) ==
            dstRegClass->allocation_order_end(*mf))
          continue;
      }
      if (!srcRegIsPhysical && dstRegIsPhysical) {
        const TargetRegisterClass *srcRegClass = mri->getRegClass(srcReg);
        if (std::find(srcRegClass->allocation_order_begin(*mf),
                      srcRegClass->allocation_order_end(*mf), dstReg) ==
            srcRegClass->allocation_order_end(*mf))
          continue;
      }

      // If we've made it here we have a copy with compatible register classes.
      // We can probably coalesce, but we need to consider overlap.
      const LiveInterval *srcLI = &lis->getInterval(srcReg),
                         *dstLI = &lis->getInterval(dstReg);

      if (srcLI->overlaps(*dstLI)) {
        // Even in the case of an overlap we might still be able to coalesce,
        // but we need to make sure that no definition of either range occurs
        // while the other range is live.

        // Otherwise start by assuming we're ok.
        bool badDef = false;

        // Test all defs of the source range.
        for (VNIIterator
               vniItr = srcLI->vni_begin(), vniEnd = srcLI->vni_end();
               vniItr != vniEnd; ++vniItr) {

          // If we find a poorly defined def we err on the side of caution.
          if (!(*vniItr)->def.isValid()) {
            badDef = true;
            break;
          }

          // If we find a def that kills the coalescing opportunity then
          // record it and break from the loop.
          if (dstLI->liveAt((*vniItr)->def)) {
            badDef = true;
            break;
          }
        }

        // If we have a bad def give up, continue to the next instruction.
        if (badDef)
          continue;

        // Otherwise test definitions of the destination range.
        for (VNIIterator
               vniItr = dstLI->vni_begin(), vniEnd = dstLI->vni_end();
               vniItr != vniEnd; ++vniItr) {

          // We want to make sure we skip the copy instruction itself.
          if ((*vniItr)->getCopy() == instr)
            continue;

          if (!(*vniItr)->def.isValid()) {
            badDef = true;
            break;
          }

          if (srcLI->liveAt((*vniItr)->def)) {
            badDef = true;
            break;
          }
        }

        // As before a bad def we give up and continue to the next instr.
        if (badDef)
          continue;
      }

      // If we make it to here then either the ranges didn't overlap, or they
      // did, but none of their definitions would prevent us from coalescing.
      // We're good to go with the coalesce.

      float cBenefit = std::pow(10.0f, (float)loopInfo->getLoopDepth(mbb)) / 5.0;

      coalescesFound[RegPair(srcReg, dstReg)] = cBenefit;
      coalescesFound[RegPair(dstReg, srcReg)] = cBenefit;
    }

  }

  return coalescesFound;
}

void PBQPRegAlloc::findVRegIntervalsToAlloc() {

  // Iterate over all live ranges.
  for (LiveIntervals::iterator itr = lis->begin(), end = lis->end();
       itr != end; ++itr) {

    // Ignore physical ones.
    if (TargetRegisterInfo::isPhysicalRegister(itr->first))
      continue;

    LiveInterval *li = itr->second;

    // If this live interval is non-empty we will use pbqp to allocate it.
    // Empty intervals we allocate in a simple post-processing stage in
    // finalizeAlloc.
    if (!li->empty()) {
      vregIntervalsToAlloc.insert(li);
    }
    else {
      emptyVRegIntervals.insert(li);
    }
  }
}

PBQP::Graph PBQPRegAlloc::constructPBQPProblem() {

  typedef std::vector<const LiveInterval*> LIVector;
  typedef std::vector<unsigned> RegVector;

  // This will store the physical intervals for easy reference.
  LIVector physIntervals;

  // Start by clearing the old node <-> live interval mappings & allowed sets
  li2Node.clear();
  node2LI.clear();
  allowedSets.clear();

  // Populate physIntervals, update preg use:
  for (LiveIntervals::iterator itr = lis->begin(), end = lis->end();
       itr != end; ++itr) {

    if (TargetRegisterInfo::isPhysicalRegister(itr->first)) {
      physIntervals.push_back(itr->second);
      mri->setPhysRegUsed(itr->second->reg);
    }
  }

  // Iterate over vreg intervals, construct live interval <-> node number
  //  mappings.
  for (LiveIntervalSet::const_iterator
       itr = vregIntervalsToAlloc.begin(), end = vregIntervalsToAlloc.end();
       itr != end; ++itr) {
    const LiveInterval *li = *itr;

    li2Node[li] = node2LI.size();
    node2LI.push_back(li);
  }

  // Get the set of potential coalesces.
  CoalesceMap coalesces;

  if (pbqpCoalescing) {
    coalesces = findCoalesces();
  }

  // Construct a PBQP solver for this problem
  PBQP::Graph problem;
  problemNodes.resize(vregIntervalsToAlloc.size());

  // Resize allowedSets container appropriately.
  allowedSets.resize(vregIntervalsToAlloc.size());

  // Iterate over virtual register intervals to compute allowed sets...
  for (unsigned node = 0; node < node2LI.size(); ++node) {

    // Grab pointers to the interval and its register class.
    const LiveInterval *li = node2LI[node];
    const TargetRegisterClass *liRC = mri->getRegClass(li->reg);

    // Start by assuming all allocable registers in the class are allowed...
    RegVector liAllowed(liRC->allocation_order_begin(*mf),
                        liRC->allocation_order_end(*mf));

    // Eliminate the physical registers which overlap with this range, along
    // with all their aliases.
    for (LIVector::iterator pItr = physIntervals.begin(),
       pEnd = physIntervals.end(); pItr != pEnd; ++pItr) {

      if (!li->overlaps(**pItr))
        continue;

      unsigned pReg = (*pItr)->reg;

      // If we get here then the live intervals overlap, but we're still ok
      // if they're coalescable.
      if (coalesces.find(RegPair(li->reg, pReg)) != coalesces.end())
        continue;

      // If we get here then we have a genuine exclusion.

      // Remove the overlapping reg...
      RegVector::iterator eraseItr =
        std::find(liAllowed.begin(), liAllowed.end(), pReg);

      if (eraseItr != liAllowed.end())
        liAllowed.erase(eraseItr);

      const unsigned *aliasItr = tri->getAliasSet(pReg);

      if (aliasItr != 0) {
        // ...and its aliases.
        for (; *aliasItr != 0; ++aliasItr) {
          RegVector::iterator eraseItr =
            std::find(liAllowed.begin(), liAllowed.end(), *aliasItr);

          if (eraseItr != liAllowed.end()) {
            liAllowed.erase(eraseItr);
          }
        }
      }
    }

    // Copy the allowed set into a member vector for use when constructing cost
    // vectors & matrices, and mapping PBQP solutions back to assignments.
    allowedSets[node] = AllowedSet(liAllowed.begin(), liAllowed.end());

    // Set the spill cost to the interval weight, or epsilon if the
    // interval weight is zero
    PBQP::PBQPNum spillCost = (li->weight != 0.0) ?
        li->weight : std::numeric_limits<PBQP::PBQPNum>::min();

    // Build a cost vector for this interval.
    problemNodes[node] =
      problem.addNode(
        buildCostVector(li->reg, allowedSets[node], coalesces, spillCost));

  }


  // Now add the cost matrices...
  for (unsigned node1 = 0; node1 < node2LI.size(); ++node1) {
    const LiveInterval *li = node2LI[node1];

    // Test for live range overlaps and insert interference matrices.
    for (unsigned node2 = node1 + 1; node2 < node2LI.size(); ++node2) {
      const LiveInterval *li2 = node2LI[node2];

      CoalesceMap::const_iterator cmItr =
        coalesces.find(RegPair(li->reg, li2->reg));

      PBQP::Matrix *m = 0;

      if (cmItr != coalesces.end()) {
        m = buildCoalescingMatrix(allowedSets[node1], allowedSets[node2],
                                  cmItr->second);
      }
      else if (li->overlaps(*li2)) {
        m = buildInterferenceMatrix(allowedSets[node1], allowedSets[node2]);
      }

      if (m != 0) {
        problem.addEdge(problemNodes[node1],
                        problemNodes[node2],
                        *m);

        delete m;
      }
    }
  }

  assert(problem.getNumNodes() == allowedSets.size());
/*
  std::cerr << "Allocating for " << problem.getNumNodes() << " nodes, "
            << problem.getNumEdges() << " edges.\n";

  problem.printDot(std::cerr);
*/
  // We're done, PBQP problem constructed - return it.
  return problem;
}

void PBQPRegAlloc::addStackInterval(const LiveInterval *spilled,
                                    MachineRegisterInfo* mri) {
  int stackSlot = vrm->getStackSlot(spilled->reg);

  if (stackSlot == VirtRegMap::NO_STACK_SLOT)
    return;

  const TargetRegisterClass *RC = mri->getRegClass(spilled->reg);
  LiveInterval &stackInterval = lss->getOrCreateInterval(stackSlot, RC);

  VNInfo *vni;
  if (stackInterval.getNumValNums() != 0)
    vni = stackInterval.getValNumInfo(0);
  else
    vni = stackInterval.getNextValue(
      SlotIndex(), 0, false, lss->getVNInfoAllocator());

  LiveInterval &rhsInterval = lis->getInterval(spilled->reg);
  stackInterval.MergeRangesInAsValue(rhsInterval, vni);
}

bool PBQPRegAlloc::mapPBQPToRegAlloc(const PBQP::Solution &solution) {

  // Set to true if we have any spills
  bool anotherRoundNeeded = false;

  // Clear the existing allocation.
  vrm->clearAllVirt();

  // Iterate over the nodes mapping the PBQP solution to a register assignment.
  for (unsigned node = 0; node < node2LI.size(); ++node) {
    unsigned virtReg = node2LI[node]->reg,
             allocSelection = solution.getSelection(problemNodes[node]);


    // If the PBQP solution is non-zero it's a physical register...
    if (allocSelection != 0) {
      // Get the physical reg, subtracting 1 to account for the spill option.
      unsigned physReg = allowedSets[node][allocSelection - 1];

      DEBUG(dbgs() << "VREG " << virtReg << " -> "
                   << tri->getName(physReg) << "\n");

      assert(physReg != 0);

      // Add to the virt reg map and update the used phys regs.
      vrm->assignVirt2Phys(virtReg, physReg);
    }
    // ...Otherwise it's a spill.
    else {

      // Make sure we ignore this virtual reg on the next round
      // of allocation
      vregIntervalsToAlloc.erase(&lis->getInterval(virtReg));

      // Insert spill ranges for this live range
      const LiveInterval *spillInterval = node2LI[node];
      double oldSpillWeight = spillInterval->weight;
      SmallVector<LiveInterval*, 8> spillIs;
      std::vector<LiveInterval*> newSpills =
        lis->addIntervalsForSpills(*spillInterval, spillIs, loopInfo, *vrm);
      addStackInterval(spillInterval, mri);

      (void) oldSpillWeight;
      DEBUG(dbgs() << "VREG " << virtReg << " -> SPILLED (Cost: "
                   << oldSpillWeight << ", New vregs: ");

      // Copy any newly inserted live intervals into the list of regs to
      // allocate.
      for (std::vector<LiveInterval*>::const_iterator
           itr = newSpills.begin(), end = newSpills.end();
           itr != end; ++itr) {

        assert(!(*itr)->empty() && "Empty spill range.");

        DEBUG(dbgs() << (*itr)->reg << " ");

        vregIntervalsToAlloc.insert(*itr);
      }

      DEBUG(dbgs() << ")\n");

      // We need another round if spill intervals were added.
      anotherRoundNeeded |= !newSpills.empty();
    }
  }

  return !anotherRoundNeeded;
}

void PBQPRegAlloc::finalizeAlloc() const {
  typedef LiveIntervals::iterator LIIterator;
  typedef LiveInterval::Ranges::const_iterator LRIterator;

  // First allocate registers for the empty intervals.
  for (LiveIntervalSet::const_iterator
         itr = emptyVRegIntervals.begin(), end = emptyVRegIntervals.end();
         itr != end; ++itr) {
    LiveInterval *li = *itr;

    unsigned physReg = vrm->getRegAllocPref(li->reg);

    if (physReg == 0) {
      const TargetRegisterClass *liRC = mri->getRegClass(li->reg);
      physReg = *liRC->allocation_order_begin(*mf);
    }

    vrm->assignVirt2Phys(li->reg, physReg);
  }

  // Finally iterate over the basic blocks to compute and set the live-in sets.
  SmallVector<MachineBasicBlock*, 8> liveInMBBs;
  MachineBasicBlock *entryMBB = &*mf->begin();

  for (LIIterator liItr = lis->begin(), liEnd = lis->end();
       liItr != liEnd; ++liItr) {

    const LiveInterval *li = liItr->second;
    unsigned reg = 0;

    // Get the physical register for this interval
    if (TargetRegisterInfo::isPhysicalRegister(li->reg)) {
      reg = li->reg;
    }
    else if (vrm->isAssignedReg(li->reg)) {
      reg = vrm->getPhys(li->reg);
    }
    else {
      // Ranges which are assigned a stack slot only are ignored.
      continue;
    }

    if (reg == 0) {
      // Filter out zero regs - they're for intervals that were spilled.
      continue;
    }

    // Iterate over the ranges of the current interval...
    for (LRIterator lrItr = li->begin(), lrEnd = li->end();
         lrItr != lrEnd; ++lrItr) {

      // Find the set of basic blocks which this range is live into...
      if (lis->findLiveInMBBs(lrItr->start, lrItr->end,  liveInMBBs)) {
        // And add the physreg for this interval to their live-in sets.
        for (unsigned i = 0; i < liveInMBBs.size(); ++i) {
          if (liveInMBBs[i] != entryMBB) {
            if (!liveInMBBs[i]->isLiveIn(reg)) {
              liveInMBBs[i]->addLiveIn(reg);
            }
          }
        }
        liveInMBBs.clear();
      }
    }
  }

}

bool PBQPRegAlloc::runOnMachineFunction(MachineFunction &MF) {

  mf = &MF;
  tm = &mf->getTarget();
  tri = tm->getRegisterInfo();
  tii = tm->getInstrInfo();
  mri = &mf->getRegInfo(); 

  lis = &getAnalysis<LiveIntervals>();
  lss = &getAnalysis<LiveStacks>();
  loopInfo = &getAnalysis<MachineLoopInfo>();
  RenderMachineFunction *rmf = &getAnalysis<RenderMachineFunction>();

  vrm = &getAnalysis<VirtRegMap>();


  DEBUG(dbgs() << "PBQP Register Allocating for " << mf->getFunction()->getName() << "\n");

  // Allocator main loop:
  //
  // * Map current regalloc problem to a PBQP problem
  // * Solve the PBQP problem
  // * Map the solution back to a register allocation
  // * Spill if necessary
  //
  // This process is continued till no more spills are generated.

  // Find the vreg intervals in need of allocation.
  findVRegIntervalsToAlloc();

  // If there are non-empty intervals allocate them using pbqp.
  if (!vregIntervalsToAlloc.empty()) {

    bool pbqpAllocComplete = false;
    unsigned round = 0;

    while (!pbqpAllocComplete) {
      DEBUG(dbgs() << "  PBQP Regalloc round " << round << ":\n");

      PBQP::Graph problem = constructPBQPProblem();
      PBQP::Solution solution =
        PBQP::HeuristicSolver<PBQP::Heuristics::Briggs>::solve(problem);

      pbqpAllocComplete = mapPBQPToRegAlloc(solution);

      ++round;
    }
  }

  // Finalise allocation, allocate empty ranges.
  finalizeAlloc();

  rmf->renderMachineFunction("After PBQP register allocation.", vrm);

  vregIntervalsToAlloc.clear();
  emptyVRegIntervals.clear();
  li2Node.clear();
  node2LI.clear();
  allowedSets.clear();
  problemNodes.clear();

  DEBUG(dbgs() << "Post alloc VirtRegMap:\n" << *vrm << "\n");

  // Run rewriter
  std::auto_ptr<VirtRegRewriter> rewriter(createVirtRegRewriter());

  rewriter->runOnMachineFunction(*mf, *vrm, lis);

  return true;
}

FunctionPass* llvm::createPBQPRegisterAllocator() {
  return new PBQPRegAlloc();
}


#undef DEBUG_TYPE
