Newer
Older
//===------ 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
//
// 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"
Lang Hames
committed
#include "PBQP/HeuristicSolver.h"
Lang Hames
committed
#include "PBQP/Heuristics/Briggs.h"
#include "RenderMachineFunction.h"
Lang Hames
committed
#include "Splitter.h"
#include "VirtRegMap.h"
#include "VirtRegRewriter.h"
#include "llvm/CodeGen/CalcSpillWeights.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
Lang Hames
committed
#include "llvm/CodeGen/LiveStackAnalysis.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"
Daniel Dunbar
committed
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include <limits>
#include <map>
#include <set>
#include <vector>
using namespace llvm;
static RegisterRegAlloc
registerPBQPRepAlloc("pbqp", "PBQP register allocator",
Lang Hames
committed
static cl::opt<bool>
pbqpCoalescing("pbqp-coalescing",
cl::desc("Attempt coalescing during PBQP register allocation."),
cl::init(false), cl::Hidden);
Lang Hames
committed
Lang Hames
committed
static cl::opt<bool>
pbqpPreSplitting("pbqp-pre-splitting",
cl::desc("Pre-splite before PBQP register allocation."),
cl::init(false), cl::Hidden);
namespace {
Lang Hames
committed
///
/// PBQP based allocators solve the register allocation problem by mapping
/// register allocation problems to Partitioned Boolean Quadratic
/// Programming problems.
Nick Lewycky
committed
class PBQPRegAlloc : public MachineFunctionPass {
public:
static char ID;
Lang Hames
committed
/// Construct a PBQP register allocator.
PBQPRegAlloc() : MachineFunctionPass(ID) {}
Lang Hames
committed
/// Return the pass name.
virtual const char* getPassName() const {
return "PBQP Register Allocator";
}
Lang Hames
committed
/// PBQP analysis usage.
virtual void getAnalysisUsage(AnalysisUsage &au) const {
au.addRequired<SlotIndexes>();
au.addPreserved<SlotIndexes>();
Lang Hames
committed
au.addRequired<LiveIntervals>();
//au.addRequiredID(SplitCriticalEdgesID);
au.addRequired<RegisterCoalescer>();
au.addRequired<CalculateSpillWeights>();
Lang Hames
committed
au.addRequired<LiveStacks>();
au.addPreserved<LiveStacks>();
au.addRequired<MachineLoopInfo>();
au.addPreserved<MachineLoopInfo>();
Lang Hames
committed
if (pbqpPreSplitting)
au.addRequired<LoopSplitter>();
Lang Hames
committed
au.addRequired<VirtRegMap>();
au.addRequired<RenderMachineFunction>();
Lang Hames
committed
MachineFunctionPass::getAnalysisUsage(au);
}
Lang Hames
committed
/// 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;
Lang Hames
committed
typedef std::set<unsigned> RegSet;
typedef std::pair<unsigned, unsigned> RegPair;
Lang Hames
committed
typedef std::map<RegPair, PBQP::PBQPNum> CoalesceMap;
Lang Hames
committed
typedef std::set<LiveInterval*, LIOrdering> LiveIntervalSet;
MachineFunction *mf;
const TargetMachine *tm;
const TargetRegisterInfo *tri;
const TargetInstrInfo *tii;
const MachineLoopInfo *loopInfo;
MachineRegisterInfo *mri;
RenderMachineFunction *rmf;
Lang Hames
committed
LiveIntervals *lis;
LiveStacks *lss;
VirtRegMap *vrm;
LI2NodeMap li2Node;
Node2LIMap node2LI;
AllowedSetMap allowedSets;
Lang Hames
committed
LiveIntervalSet vregIntervalsToAlloc,
emptyVRegIntervals;
Lang Hames
committed
/// Builds a PBQP cost vector.
Lang Hames
committed
template <typename RegContainer>
Lang Hames
committed
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.
Lang Hames
committed
template <typename RegContainer>
Lang Hames
committed
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.
Lang Hames
committed
template <typename RegContainer>
Lang Hames
committed
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.
Lang Hames
committed
CoalesceMap findCoalesces();
Lang Hames
committed
/// \brief Finds the initial set of vreg intervals to allocate.
Lang Hames
committed
void findVRegIntervalsToAlloc();
Lang Hames
committed
/// \brief Constructs a PBQP problem representation of the register
/// allocation problem for this function.
///
/// @return a PBQP solver object for the register allocation problem.
Lang Hames
committed
/// \brief Adds a stack interval if the given live interval has been
/// spilled. Used to support stack slot coloring.
Evan Cheng
committed
void addStackInterval(const LiveInterval *spilled,MachineRegisterInfo* mri);
Lang Hames
committed
Lang Hames
committed
/// \brief Given a solved PBQP problem maps this solution back to a register
/// assignment.
bool mapPBQPToRegAlloc(const PBQP::Solution &solution);
Lang Hames
committed
/// \brief Postprocessing before final spilling. Sets basic block "live in"
/// variables.
Lang Hames
committed
void finalizeAlloc() const;
};
char PBQPRegAlloc::ID = 0;
}
Lang Hames
committed
template <typename RegContainer>
Lang Hames
committed
PBQP::Vector PBQPRegAlloc::buildCostVector(unsigned vReg,
const RegContainer &allowed,
const CoalesceMap &coalesces,
PBQP::PBQPNum spillCost) const {
Lang Hames
committed
typedef typename RegContainer::const_iterator AllowedItr;
// Allocate vector. Additional element (0th) used for spill option
Lang Hames
committed
PBQP::Vector v(allowed.size() + 1, 0);
Lang Hames
committed
v[0] = spillCost;
Lang Hames
committed
// 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.
Lang Hames
committed
v[ai + 1] = -cmItr->second;
Lang Hames
committed
}
return v;
}
Lang Hames
committed
template <typename RegContainer>
Lang Hames
committed
PBQP::Matrix* PBQPRegAlloc::buildInterferenceMatrix(
Lang Hames
committed
const RegContainer &allowed1, const RegContainer &allowed2) const {
Lang Hames
committed
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).
Lang Hames
committed
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.
// Iterate over allowed sets, insert infinities where required.
Lang Hames
committed
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;
Lang Hames
committed
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.
Lang Hames
committed
(*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;
}
Lang Hames
committed
template <typename RegContainer>
Lang Hames
committed
PBQP::Matrix* PBQPRegAlloc::buildCoalescingMatrix(
Lang Hames
committed
const RegContainer &allowed1, const RegContainer &allowed2,
Lang Hames
committed
PBQP::PBQPNum cBenefit) const {
Lang Hames
committed
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.
Lang Hames
committed
PBQP::Matrix *m =
new PBQP::Matrix(allowed1.size() + 1, allowed2.size() + 1, 0);
Lang Hames
committed
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
// 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
Lang Hames
committed
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
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;
Lang Hames
committed
CoalesceMap coalescesFound;
Lang Hames
committed
// 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;
Lang Hames
committed
for (MBBIterator iItr = mbb->begin(), iEnd = mbb->end();
iItr != iEnd; ++iItr) {
const MachineInstr *instr = &*iItr;
Lang Hames
committed
// If this isn't a copy then continue to the next instruction.
Jakob Stoklund Olesen
committed
if (!instr->isCopy())
Lang Hames
committed
continue;
Jakob Stoklund Olesen
committed
unsigned srcReg = instr->getOperand(1).getReg();
unsigned dstReg = instr->getOperand(0).getReg();
Lang Hames
committed
// If the registers are already the same our job is nice and easy.
if (dstReg == srcReg)
continue;
Lang Hames
committed
bool srcRegIsPhysical = TargetRegisterInfo::isPhysicalRegister(srcReg),
dstRegIsPhysical = TargetRegisterInfo::isPhysicalRegister(dstReg);
Lang Hames
committed
// If both registers are physical then we can't coalesce.
if (srcRegIsPhysical && dstRegIsPhysical)
continue;
Rafael Espindola
committed
// 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))
Lang Hames
committed
continue;
Rafael Espindola
committed
// 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;
Lang Hames
committed
}
Rafael Espindola
committed
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;
Lang Hames
committed
}
Lang Hames
committed
// If we've made it here we have a copy with compatible register classes.
// We can probably coalesce, but we need to consider overlap.
Lang Hames
committed
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.
Lang Hames
committed
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;
}
Lang Hames
committed
// 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;
}
}
Lang Hames
committed
// If we have a bad def give up, continue to the next instruction.
if (badDef)
continue;
Lang Hames
committed
// Otherwise test definitions of the destination range.
for (VNIIterator
vniItr = dstLI->vni_begin(), vniEnd = dstLI->vni_end();
vniItr != vniEnd; ++vniItr) {
Lang Hames
committed
// We want to make sure we skip the copy instruction itself.
Lang Hames
committed
if ((*vniItr)->getCopy() == instr)
Lang Hames
committed
continue;
if (!(*vniItr)->def.isValid()) {
badDef = true;
break;
}
Lang Hames
committed
if (srcLI->liveAt((*vniItr)->def)) {
badDef = true;
break;
}
}
Lang Hames
committed
// As before a bad def we give up and continue to the next instr.
if (badDef)
continue;
}
Lang Hames
committed
// 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;
Lang Hames
committed
coalescesFound[RegPair(srcReg, dstReg)] = cBenefit;
coalescesFound[RegPair(dstReg, srcReg)] = cBenefit;
}
}
Lang Hames
committed
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);
}
}
}
typedef std::vector<const LiveInterval*> LIVector;
Lang Hames
committed
typedef std::vector<unsigned> RegVector;
Lang Hames
committed
// 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();
Lang Hames
committed
// 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);
}
Lang Hames
committed
}
Lang Hames
committed
// Iterate over vreg intervals, construct live interval <-> node number
// mappings.
Lang Hames
committed
itr = vregIntervalsToAlloc.begin(), end = vregIntervalsToAlloc.end();
itr != end; ++itr) {
const LiveInterval *li = *itr;
Lang Hames
committed
li2Node[li] = node2LI.size();
node2LI.push_back(li);
}
Lang Hames
committed
// Get the set of potential coalesces.
Lang Hames
committed
CoalesceMap coalesces;
if (pbqpCoalescing) {
coalesces = findCoalesces();
}
// Construct a PBQP solver for this problem
PBQP::Graph problem;
problemNodes.resize(vregIntervalsToAlloc.size());
// Resize allowedSets container appropriately.
Lang Hames
committed
allowedSets.resize(vregIntervalsToAlloc.size());
Jim Grosbach
committed
BitVector ReservedRegs = tri->getReservedRegs(*mf);
// 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...
Jim Grosbach
committed
RegVector liAllowed;
TargetRegisterClass::iterator aob = liRC->allocation_order_begin(*mf);
TargetRegisterClass::iterator aoe = liRC->allocation_order_end(*mf);
for (TargetRegisterClass::iterator it = aob; it != aoe; ++it)
if (!ReservedRegs.test(*it))
liAllowed.push_back(*it);
Lang Hames
committed
// 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) {
Lang Hames
committed
if (!li->overlaps(**pItr))
continue;
Lang Hames
committed
unsigned pReg = (*pItr)->reg;
Lang Hames
committed
// 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;
Lang Hames
committed
// If we get here then we have a genuine exclusion.
Lang Hames
committed
// Remove the overlapping reg...
RegVector::iterator eraseItr =
std::find(liAllowed.begin(), liAllowed.end(), pReg);
Lang Hames
committed
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);
Lang Hames
committed
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
Lang Hames
committed
PBQP::PBQPNum spillCost = (li->weight != 0.0) ?
li->weight : std::numeric_limits<PBQP::PBQPNum>::min();
// Build a cost vector for this interval.
Lang Hames
committed
problemNodes[node] =
problem.addNode(
buildCostVector(li->reg, allowedSets[node], coalesces, spillCost));
}
Lang Hames
committed
// 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];
Lang Hames
committed
CoalesceMap::const_iterator cmItr =
coalesces.find(RegPair(li->reg, li2->reg));
Lang Hames
committed
PBQP::Matrix *m = 0;
Lang Hames
committed
if (cmItr != coalesces.end()) {
m = buildCoalescingMatrix(allowedSets[node1], allowedSets[node2],
cmItr->second);
}
else if (li->overlaps(*li2)) {
m = buildInterferenceMatrix(allowedSets[node1], allowedSets[node2]);
}
Lang Hames
committed
if (m != 0) {
Lang Hames
committed
problem.addEdge(problemNodes[node1],
problemNodes[node2],
*m);
Lang Hames
committed
delete m;
}
}
}
Lang Hames
committed
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.
Lang Hames
committed
return problem;
}
Evan Cheng
committed
void PBQPRegAlloc::addStackInterval(const LiveInterval *spilled,
MachineRegisterInfo* mri) {
Lang Hames
committed
int stackSlot = vrm->getStackSlot(spilled->reg);
if (stackSlot == VirtRegMap::NO_STACK_SLOT)
Lang Hames
committed
return;
Evan Cheng
committed
const TargetRegisterClass *RC = mri->getRegClass(spilled->reg);
LiveInterval &stackInterval = lss->getOrCreateInterval(stackSlot, RC);
Lang Hames
committed
VNInfo *vni;
if (stackInterval.getNumValNums() != 0)
vni = stackInterval.getValNumInfo(0);
else
vni = stackInterval.getNextValue(
Lang Hames
committed
LiveInterval &rhsInterval = lis->getInterval(spilled->reg);
stackInterval.MergeRangesInAsValue(rhsInterval, vni);
}
Lang Hames
committed
bool PBQPRegAlloc::mapPBQPToRegAlloc(const PBQP::Solution &solution) {
Lang Hames
committed
// 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) {
Lang Hames
committed
unsigned virtReg = node2LI[node]->reg,
allocSelection = solution.getSelection(problemNodes[node]);
Lang Hames
committed
// 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];
<< tri->getName(physReg) << "\n");
Lang Hames
committed
assert(physReg != 0);
// Add to the virt reg map and update the used phys regs.
Lang Hames
committed
vrm->assignVirt2Phys(virtReg, physReg);
}
// ...Otherwise it's a spill.
else {
// Make sure we ignore this virtual reg on the next round
// of allocation
Lang Hames
committed
vregIntervalsToAlloc.erase(&lis->getInterval(virtReg));
// Insert spill ranges for this live range
Lang Hames
committed
const LiveInterval *spillInterval = node2LI[node];
double oldSpillWeight = spillInterval->weight;
SmallVector<LiveInterval*, 8> spillIs;
rmf->rememberUseDefs(spillInterval);
std::vector<LiveInterval*> newSpills =
Evan Cheng
committed
lis->addIntervalsForSpills(*spillInterval, spillIs, loopInfo, *vrm);
addStackInterval(spillInterval, mri);
rmf->rememberSpills(spillInterval, newSpills);
Lang Hames
committed
DEBUG(dbgs() << "VREG " << virtReg << " -> SPILLED (Cost: "
<< oldSpillWeight << ", New vregs: ");
Lang Hames
committed
// 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.");
Lang Hames
committed
vregIntervalsToAlloc.insert(*itr);
}
// We need another round if spill intervals were added.
anotherRoundNeeded |= !newSpills.empty();
}
}
return !anotherRoundNeeded;
}
Lang Hames
committed
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();
Lang Hames
committed
itr != end; ++itr) {
Lang Hames
committed
unsigned physReg = vrm->getRegAllocPref(li->reg);
Lang Hames
committed
Lang Hames
committed
if (physReg == 0) {
const TargetRegisterClass *liRC = mri->getRegClass(li->reg);
Lang Hames
committed
}
Lang Hames
committed
}
Lang Hames
committed
// 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;
Lang Hames
committed
// 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) {
Lang Hames
committed
// Filter out zero regs - they're for intervals that were spilled.
continue;
}
Lang Hames
committed
// Iterate over the ranges of the current interval...
for (LRIterator lrItr = li->begin(), lrEnd = li->end();
lrItr != lrEnd; ++lrItr) {
Lang Hames
committed
// 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();
}
}
}
Lang Hames
committed
}
bool PBQPRegAlloc::runOnMachineFunction(MachineFunction &MF) {
Lang Hames
committed
mf = &MF;
tm = &mf->getTarget();
tri = tm->getRegisterInfo();
Lang Hames
committed
tii = tm->getInstrInfo();
Lang Hames
committed
lis = &getAnalysis<LiveIntervals>();
lss = &getAnalysis<LiveStacks>();
loopInfo = &getAnalysis<MachineLoopInfo>();
rmf = &getAnalysis<RenderMachineFunction>();
vrm = &getAnalysis<VirtRegMap>();
DEBUG(dbgs() << "PBQP Register Allocating for " << mf->getFunction()->getName() << "\n");
Lang Hames
committed
// 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.
Lang Hames
committed
// Find the vreg intervals in need of allocation.
findVRegIntervalsToAlloc();
Lang Hames
committed
// 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");
Lang Hames
committed
PBQP::Graph problem = constructPBQPProblem();
PBQP::Solution solution =
PBQP::HeuristicSolver<PBQP::Heuristics::Briggs>::solve(problem);
Lang Hames
committed
pbqpAllocComplete = mapPBQPToRegAlloc(solution);
Lang Hames
committed
++round;
}
}
Lang Hames
committed
// Finalise allocation, allocate empty ranges.
finalizeAlloc();
rmf->renderMachineFunction("After PBQP register allocation.", vrm);
Lang Hames
committed
vregIntervalsToAlloc.clear();
emptyVRegIntervals.clear();
li2Node.clear();
node2LI.clear();
allowedSets.clear();
DEBUG(dbgs() << "Post alloc VirtRegMap:\n" << *vrm << "\n");
Lang Hames
committed
// Run rewriter
std::auto_ptr<VirtRegRewriter> rewriter(createVirtRegRewriter());
rewriter->runOnMachineFunction(*mf, *vrm, lis);
Lang Hames
committed
}
FunctionPass* llvm::createPBQPRegisterAllocator() {
return new PBQPRegAlloc();
}
#undef DEBUG_TYPE