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"
#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"
Lang Hames
committed
#include "llvm/CodeGen/RegAllocPBQP.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
Lang Hames
committed
#include "llvm/CodeGen/PBQP/HeuristicSolver.h"
#include "llvm/CodeGen/PBQP/Graph.h"
#include "llvm/CodeGen/PBQP/Heuristics/Briggs.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 <memory>
#include <set>
#include <vector>
Lang Hames
committed
namespace llvm {
using namespace PBQP;
using namespace PBQP::Heuristics;
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>
pbqpBuilder("pbqp-builder",
cl::desc("Use new builder system."),
cl::init(false), cl::Hidden);
Lang Hames
committed
static cl::opt<bool>
pbqpPreSplitting("pbqp-pre-splitting",
cl::desc("Pre-splite before PBQP register allocation."),
cl::init(false), cl::Hidden);
Lang Hames
committed
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
char RegAllocPBQP::ID = 0;
unsigned PBQPRAProblem::getVRegForNode(PBQP::Graph::ConstNodeItr node) const {
Node2VReg::const_iterator vregItr = node2VReg.find(node);
assert(vregItr != node2VReg.end() && "No vreg for node.");
return vregItr->second;
}
PBQP::Graph::NodeItr PBQPRAProblem::getNodeForVReg(unsigned vreg) const {
VReg2Node::const_iterator nodeItr = vreg2Node.find(vreg);
assert(nodeItr != vreg2Node.end() && "No node for vreg.");
return nodeItr->second;
}
const PBQPRAProblem::AllowedSet&
PBQPRAProblem::getAllowedSet(unsigned vreg) const {
AllowedSetMap::const_iterator allowedSetItr = allowedSets.find(vreg);
assert(allowedSetItr != allowedSets.end() && "No pregs for vreg.");
const AllowedSet &allowedSet = allowedSetItr->second;
return allowedSet;
}
unsigned PBQPRAProblem::getPRegForOption(unsigned vreg, unsigned option) const {
assert(isPRegOption(vreg, option) && "Not a preg option.");
const AllowedSet& allowedSet = getAllowedSet(vreg);
assert(option <= allowedSet.size() && "Option outside allowed set.");
return allowedSet[option - 1];
}
std::auto_ptr<PBQPRAProblem> PBQPBuilder::build(
MachineFunction *mf,
const LiveIntervals *lis,
const RegSet &vregs) {
typedef std::vector<const LiveInterval*> LIVector;
MachineRegisterInfo *mri = &mf->getRegInfo();
const TargetRegisterInfo *tri = mf->getTarget().getRegisterInfo();
std::auto_ptr<PBQPRAProblem> p(new PBQPRAProblem());
PBQP::Graph &g = p->getGraph();
RegSet pregs;
// Collect the set of preg intervals, record that they're used in the MF.
for (LiveIntervals::const_iterator itr = lis->begin(), end = lis->end();
itr != end; ++itr) {
if (TargetRegisterInfo::isPhysicalRegister(itr->first)) {
pregs.insert(itr->first);
mri->setPhysRegUsed(itr->first);
}
}
BitVector reservedRegs = tri->getReservedRegs(*mf);
// Iterate over vregs.
for (RegSet::const_iterator vregItr = vregs.begin(), vregEnd = vregs.end();
vregItr != vregEnd; ++vregItr) {
unsigned vreg = *vregItr;
const TargetRegisterClass *trc = mri->getRegClass(vreg);
const LiveInterval *vregLI = &lis->getInterval(vreg);
// Compute an initial allowed set for the current vreg.
typedef std::vector<unsigned> VRAllowed;
VRAllowed vrAllowed;
for (TargetRegisterClass::iterator aoItr = trc->allocation_order_begin(*mf),
aoEnd = trc->allocation_order_end(*mf);
aoItr != aoEnd; ++aoItr) {
unsigned preg = *aoItr;
if (!reservedRegs.test(preg)) {
vrAllowed.push_back(preg);
}
}
// Remove any physical registers which overlap.
for (RegSet::const_iterator pregItr = pregs.begin(),
pregEnd = pregs.end();
pregItr != pregEnd; ++pregItr) {
unsigned preg = *pregItr;
const LiveInterval *pregLI = &lis->getInterval(preg);
if (pregLI->empty())
continue;
if (!vregLI->overlaps(*pregLI))
continue;
Lang Hames
committed
// Remove the register from the allowed set.
VRAllowed::iterator eraseItr =
std::find(vrAllowed.begin(), vrAllowed.end(), preg);
Lang Hames
committed
if (eraseItr != vrAllowed.end()) {
vrAllowed.erase(eraseItr);
}
Lang Hames
committed
// Also remove any aliases.
const unsigned *aliasItr = tri->getAliasSet(preg);
if (aliasItr != 0) {
for (; *aliasItr != 0; ++aliasItr) {
VRAllowed::iterator eraseItr =
std::find(vrAllowed.begin(), vrAllowed.end(), *aliasItr);
Lang Hames
committed
if (eraseItr != vrAllowed.end()) {
vrAllowed.erase(eraseItr);
}
}
}
}
Lang Hames
committed
// Construct the node.
PBQP::Graph::NodeItr node =
g.addNode(PBQP::Vector(vrAllowed.size() + 1, 0));
// Record the mapping and allowed set in the problem.
p->recordVReg(vreg, node, vrAllowed.begin(), vrAllowed.end());
PBQP::PBQPNum spillCost = (vregLI->weight != 0.0) ?
vregLI->weight : std::numeric_limits<PBQP::PBQPNum>::min();
addSpillCosts(g.getNodeCosts(node), spillCost);
}
for (RegSet::const_iterator vr1Itr = vregs.begin(), vrEnd = vregs.end();
Lang Hames
committed
vr1Itr != vrEnd; ++vr1Itr) {
unsigned vr1 = *vr1Itr;
const LiveInterval &l1 = lis->getInterval(vr1);
const PBQPRAProblem::AllowedSet &vr1Allowed = p->getAllowedSet(vr1);
for (RegSet::iterator vr2Itr = llvm::next(vr1Itr);
vr2Itr != vrEnd; ++vr2Itr) {
unsigned vr2 = *vr2Itr;
const LiveInterval &l2 = lis->getInterval(vr2);
const PBQPRAProblem::AllowedSet &vr2Allowed = p->getAllowedSet(vr2);
assert(!l2.empty() && "Empty interval in vreg set?");
if (l1.overlaps(l2)) {
PBQP::Graph::EdgeItr edge =
g.addEdge(p->getNodeForVReg(vr1), p->getNodeForVReg(vr2),
PBQP::Matrix(vr1Allowed.size()+1, vr2Allowed.size()+1, 0));
addInterferenceCosts(g.getEdgeCosts(edge), vr1Allowed, vr2Allowed, tri);
}
}
Lang Hames
committed
}
return p;
}
void PBQPBuilder::addSpillCosts(PBQP::Vector &costVec,
PBQP::PBQPNum spillCost) {
costVec[0] = spillCost;
}
void PBQPBuilder::addInterferenceCosts(PBQP::Matrix &costMat,
const PBQPRAProblem::AllowedSet &vr1Allowed,
const PBQPRAProblem::AllowedSet &vr2Allowed,
const TargetRegisterInfo *tri) {
assert(costMat.getRows() == vr1Allowed.size() + 1 && "Matrix height mismatch.");
assert(costMat.getCols() == vr2Allowed.size() + 1 && "Matrix width mismatch.");
Lang Hames
committed
for (unsigned i = 0; i < vr1Allowed.size(); ++i) {
unsigned preg1 = vr1Allowed[i];
Lang Hames
committed
for (unsigned j = 0; j < vr2Allowed.size(); ++j) {
unsigned preg2 = vr2Allowed[j];
Lang Hames
committed
if (tri->regsOverlap(preg1, preg2)) {
costMat[i + 1][j + 1] = std::numeric_limits<PBQP::PBQPNum>::infinity();
Lang Hames
committed
}
}
}
Lang Hames
committed
void RegAllocPBQP::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);
}
Lang Hames
committed
template <typename RegContainer>
Lang Hames
committed
PBQP::Vector RegAllocPBQP::buildCostVector(unsigned vReg,
Lang Hames
committed
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* RegAllocPBQP::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* RegAllocPBQP::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
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
// 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
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;
}
Lang Hames
committed
RegAllocPBQP::CoalesceMap RegAllocPBQP::findCoalesces() {
Lang Hames
committed
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;
}
Lang Hames
committed
void RegAllocPBQP::findVRegIntervalsToAlloc() {
Lang Hames
committed
// 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()) {
Lang Hames
committed
vregsToAlloc.insert(li->reg);
Lang Hames
committed
}
else {
Lang Hames
committed
emptyIntervalVRegs.insert(li->reg);
Lang Hames
committed
}
}
}
Lang Hames
committed
PBQP::Graph RegAllocPBQP::constructPBQPProblem() {
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
for (RegSet::const_iterator itr = vregsToAlloc.begin(),
end = vregsToAlloc.end();
Lang Hames
committed
itr != end; ++itr) {
Lang Hames
committed
const LiveInterval *li = &lis->getInterval(*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
Lang Hames
committed
problemNodes.resize(vregsToAlloc.size());
// Resize allowedSets container appropriately.
Lang Hames
committed
allowedSets.resize(vregsToAlloc.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.
Lang Hames
committed
if (coalesces.find(RegPair(li->reg, pReg)) != coalesces.end()) {
DEBUG(dbgs() << "CoalescingOverride: (" << li->reg << ", " << pReg << ")\n");
Lang Hames
committed
continue;
Lang Hames
committed
}
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;
}
Lang Hames
committed
void RegAllocPBQP::addStackInterval(const LiveInterval *spilled,
Evan Cheng
committed
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 RegAllocPBQP::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];
Lang Hames
committed
<< tri->getName(physReg) << " (Option: " << allocSelection << ")\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
vregsToAlloc.erase(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
Lang Hames
committed
DEBUG(dbgs() << "VREG " << virtReg << " -> SPILLED (Option: 0, 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
Lang Hames
committed
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
vregsToAlloc.insert((*itr)->reg);
}
DEBUG(dbgs() << ")\n");
// We need another round if spill intervals were added.
anotherRoundNeeded |= !newSpills.empty();
}
}
return !anotherRoundNeeded;
}
bool RegAllocPBQP::mapPBQPToRegAlloc2(const PBQPRAProblem &problem,
const PBQP::Solution &solution) {
// Set to true if we have any spills
bool anotherRoundNeeded = false;
// Clear the existing allocation.
vrm->clearAllVirt();
const PBQP::Graph &g = problem.getGraph();
// Iterate over the nodes mapping the PBQP solution to a register
// assignment.
for (PBQP::Graph::ConstNodeItr node = g.nodesBegin(),
nodeEnd = g.nodesEnd();
node != nodeEnd; ++node) {
unsigned vreg = problem.getVRegForNode(node);
unsigned alloc = solution.getSelection(node);
if (problem.isPRegOption(vreg, alloc)) {
unsigned preg = problem.getPRegForOption(vreg, alloc);
DEBUG(dbgs() << "VREG " << vreg << " -> " << tri->getName(preg) << "\n");
assert(preg != 0 && "Invalid preg selected.");
vrm->assignVirt2Phys(vreg, preg);
} else if (problem.isSpillOption(vreg, alloc)) {
vregsToAlloc.erase(vreg);
const LiveInterval* spillInterval = &lis->getInterval(vreg);
double oldWeight = spillInterval->weight;
SmallVector<LiveInterval*, 8> spillIs;
rmf->rememberUseDefs(spillInterval);
std::vector<LiveInterval*> newSpills =
lis->addIntervalsForSpills(*spillInterval, spillIs, loopInfo, *vrm);
addStackInterval(spillInterval, mri);
rmf->rememberSpills(spillInterval, newSpills);
(void) oldWeight;
DEBUG(dbgs() << "VREG " << vreg << " -> SPILLED (Cost: "
<< oldWeight << ", 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 << " ");
vregsToAlloc.insert((*itr)->reg);
Lang Hames
committed
}
// We need another round if spill intervals were added.
anotherRoundNeeded |= !newSpills.empty();
Lang Hames
committed
} else {
assert(false && "Unknown allocation option.");
}
}
return !anotherRoundNeeded;
}
Lang Hames
committed
void RegAllocPBQP::finalizeAlloc() const {
Lang Hames
committed
typedef LiveIntervals::iterator LIIterator;
typedef LiveInterval::Ranges::const_iterator LRIterator;
// First allocate registers for the empty intervals.
Lang Hames
committed
for (RegSet::const_iterator
itr = emptyIntervalVRegs.begin(), end = emptyIntervalVRegs.end();
Lang Hames
committed
itr != end; ++itr) {
Lang Hames
committed
LiveInterval *li = &lis->getInterval(*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
}
Lang Hames
committed
bool RegAllocPBQP::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>();