Newer
Older
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(
SlotIndex(), 0, lss->getVNInfoAllocator());
Lang Hames
committed
LiveInterval &rhsInterval = lis->getInterval(spilled->reg);
stackInterval.MergeRangesInAsValue(rhsInterval, vni);
}
Lang Hames
committed
bool RegAllocPBQP::mapPBQPToRegAllocOld(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
vregsToAlloc.insert((*itr)->reg);
}
DEBUG(dbgs() << ")\n");
// We need another round if spill intervals were added.
anotherRoundNeeded |= !newSpills.empty();
}
}
return !anotherRoundNeeded;
}
Lang Hames
committed
bool RegAllocPBQP::mapPBQPToRegAlloc(const PBQPRAProblem &problem,
const PBQP::Solution &solution) {
Lang Hames
committed
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
// 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>();
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.
Lang Hames
committed
if (!vregsToAlloc.empty()) {
Lang Hames
committed
bool pbqpAllocComplete = false;
unsigned round = 0;
Lang Hames
committed
if (!pbqpBuilder) {
while (!pbqpAllocComplete) {
DEBUG(dbgs() << " PBQP Regalloc round " << round << ":\n");
Lang Hames
committed
Lang Hames
committed
PBQP::Graph problem = constructPBQPProblemOld();
Lang Hames
committed
PBQP::Solution solution =
PBQP::HeuristicSolver<PBQP::Heuristics::Briggs>::solve(problem);
Lang Hames
committed
pbqpAllocComplete = mapPBQPToRegAllocOld(solution);
Lang Hames
committed
++round;
}
} else {
while (!pbqpAllocComplete) {
DEBUG(dbgs() << " PBQP Regalloc round " << round << ":\n");
std::auto_ptr<PBQPRAProblem> problem =
builder->build(mf, lis, loopInfo, vregsToAlloc);
Lang Hames
committed
PBQP::Solution solution =
PBQP::HeuristicSolver<PBQP::Heuristics::Briggs>::solve(
problem->getGraph());
Lang Hames
committed
Lang Hames
committed
pbqpAllocComplete = mapPBQPToRegAlloc(*problem, solution);
Lang Hames
committed
++round;
}
Lang Hames
committed
}
}
Lang Hames
committed
// Finalise allocation, allocate empty ranges.
finalizeAlloc();
rmf->renderMachineFunction("After PBQP register allocation.", vrm);
Lang Hames
committed
vregsToAlloc.clear();
emptyIntervalVRegs.clear();
Lang Hames
committed
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
}
Lang Hames
committed
FunctionPass* llvm::createPBQPRegisterAllocator(
std::auto_ptr<PBQPBuilder> builder) {
return new RegAllocPBQP(builder);
}
Lang Hames
committed
FunctionPass* llvm::createDefaultPBQPRegisterAllocator() {
if (pbqpCoalescing) {
return createPBQPRegisterAllocator(
std::auto_ptr<PBQPBuilder>(new PBQPBuilderWithCoalescing()));
} // else
return createPBQPRegisterAllocator(
std::auto_ptr<PBQPBuilder>(new PBQPBuilder()));
Lang Hames
committed
}
#undef DEBUG_TYPE