#include "RenderMachineFunction.h"
#include "Spiller.h"
#include "VirtRegMap.h"
-#include "VirtRegRewriter.h"
#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Function.h"
#include "llvm/PassAnalysisSupport.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Timer.h"
-#include <vector>
-#include <queue>
#include <cstdlib>
+#include <queue>
using namespace llvm;
+STATISTIC(NumAssigned , "Number of registers assigned");
+STATISTIC(NumUnassigned , "Number of registers unassigned");
+STATISTIC(NumNewQueued , "Number of new live ranges queued");
+
static RegisterRegAlloc basicRegAlloc("basic", "basic register allocator",
createBasicRegisterAllocator);
// Temporary verification option until we can put verification inside
// MachineVerifier.
-static cl::opt<bool>
-VerifyRegAlloc("verify-regalloc",
- cl::desc("Verify live intervals before renaming"));
+static cl::opt<bool, true>
+VerifyRegAlloc("verify-regalloc", cl::location(RegAllocBase::VerifyEnabled),
+ cl::desc("Verify during register allocation"));
-namespace {
+const char *RegAllocBase::TimerGroupName = "Register Allocation";
+bool RegAllocBase::VerifyEnabled = false;
-class PhysicalRegisterDescription : public AbstractRegisterDescription {
- const TargetRegisterInfo *TRI;
-public:
- PhysicalRegisterDescription(const TargetRegisterInfo *T): TRI(T) {}
- virtual const char *getName(unsigned Reg) const { return TRI->getName(Reg); }
-};
+namespace {
+ struct CompSpillWeight {
+ bool operator()(LiveInterval *A, LiveInterval *B) const {
+ return A->weight < B->weight;
+ }
+ };
+}
+namespace {
/// RABasic provides a minimal implementation of the basic register allocation
/// algorithm. It prioritizes live virtual registers by spill weight and spills
/// whenever a register is unavailable. This is not practical in production but
{
// context
MachineFunction *MF;
- const TargetMachine *TM;
- MachineRegisterInfo *MRI;
-
BitVector ReservedRegs;
// analyses
// state
std::auto_ptr<Spiller> SpillerInstance;
-
+ std::priority_queue<LiveInterval*, std::vector<LiveInterval*>,
+ CompSpillWeight> Queue;
public:
RABasic();
virtual Spiller &spiller() { return *SpillerInstance; }
+ virtual float getPriority(LiveInterval *LI) { return LI->weight; }
+
+ virtual void enqueue(LiveInterval *LI) {
+ Queue.push(LI);
+ }
+
+ virtual LiveInterval *dequeue() {
+ if (Queue.empty())
+ return 0;
+ LiveInterval *LI = Queue.top();
+ Queue.pop();
+ return LI;
+ }
+
virtual unsigned selectOrSplit(LiveInterval &VirtReg,
SmallVectorImpl<LiveInterval*> &SplitVRegs);
virtual bool runOnMachineFunction(MachineFunction &mf);
static char ID;
-
-private:
- void addMBBLiveIns();
};
char RABasic::ID = 0;
// Verify disjoint unions.
for (unsigned PhysReg = 0; PhysReg < PhysReg2LiveUnion.numRegs(); ++PhysReg) {
- DEBUG(PhysicalRegisterDescription PRD(TRI);
- PhysReg2LiveUnion[PhysReg].dump(&PRD));
+ DEBUG(PhysReg2LiveUnion[PhysReg].print(dbgs(), TRI));
LiveVirtRegBitSet &VRegs = unionVRegs[PhysReg];
PhysReg2LiveUnion[PhysReg].verify(VRegs);
// Union + intersection test could be done efficiently in one pass, but
new(Array + r) LiveIntervalUnion(r, allocator);
}
-void RegAllocBase::init(const TargetRegisterInfo &tri, VirtRegMap &vrm,
- LiveIntervals &lis) {
- TRI = &tri;
+void RegAllocBase::init(VirtRegMap &vrm, LiveIntervals &lis) {
+ NamedRegionTimer T("Initialize", TimerGroupName, TimePassesIsEnabled);
+ TRI = &vrm.getTargetRegInfo();
+ MRI = &vrm.getRegInfo();
VRM = &vrm;
LIS = &lis;
PhysReg2LiveUnion.init(UnionAllocator, TRI->getNumRegs());
PhysReg2LiveUnion.clear();
}
-namespace llvm {
-/// This class defines a queue of live virtual registers prioritized by spill
-/// weight. The heaviest vreg is popped first.
-///
-/// Currently, this is trivial wrapper that gives us an opaque type in the
-/// header, but we may later give it a virtual interface for register allocators
-/// to override the priority queue comparator.
-class LiveVirtRegQueue {
- typedef std::priority_queue
- <LiveInterval*, std::vector<LiveInterval*>, LessSpillWeightPriority>
- PriorityQ;
- PriorityQ PQ;
-
-public:
- // Is the queue empty?
- bool empty() { return PQ.empty(); }
-
- // Get the highest priority lvr (top + pop)
- LiveInterval *get() {
- LiveInterval *VirtReg = PQ.top();
- PQ.pop();
- return VirtReg;
- }
- // Add this lvr to the queue
- void push(LiveInterval *VirtReg) {
- PQ.push(VirtReg);
- }
-};
-} // end namespace llvm
-
-// Visit all the live virtual registers. If they are already assigned to a
-// physical register, unify them with the corresponding LiveIntervalUnion,
-// otherwise push them on the priority queue for later assignment.
-void RegAllocBase::seedLiveVirtRegs(LiveVirtRegQueue &VirtRegQ) {
+// Visit all the live registers. If they are already assigned to a physical
+// register, unify them with the corresponding LiveIntervalUnion, otherwise push
+// them on the priority queue for later assignment.
+void RegAllocBase::seedLiveRegs() {
for (LiveIntervals::iterator I = LIS->begin(), E = LIS->end(); I != E; ++I) {
unsigned RegNum = I->first;
LiveInterval &VirtReg = *I->second;
- if (TargetRegisterInfo::isPhysicalRegister(RegNum)) {
+ if (TargetRegisterInfo::isPhysicalRegister(RegNum))
PhysReg2LiveUnion[RegNum].unify(VirtReg);
- }
- else {
- VirtRegQ.push(&VirtReg);
- }
+ else
+ enqueue(&VirtReg);
}
}
+void RegAllocBase::assign(LiveInterval &VirtReg, unsigned PhysReg) {
+ DEBUG(dbgs() << "assigning " << PrintReg(VirtReg.reg, TRI)
+ << " to " << PrintReg(PhysReg, TRI) << '\n');
+ assert(!VRM->hasPhys(VirtReg.reg) && "Duplicate VirtReg assignment");
+ VRM->assignVirt2Phys(VirtReg.reg, PhysReg);
+ PhysReg2LiveUnion[PhysReg].unify(VirtReg);
+ ++NumAssigned;
+}
+
+void RegAllocBase::unassign(LiveInterval &VirtReg, unsigned PhysReg) {
+ DEBUG(dbgs() << "unassigning " << PrintReg(VirtReg.reg, TRI)
+ << " from " << PrintReg(PhysReg, TRI) << '\n');
+ assert(VRM->getPhys(VirtReg.reg) == PhysReg && "Inconsistent unassign");
+ PhysReg2LiveUnion[PhysReg].extract(VirtReg);
+ VRM->clearVirt(VirtReg.reg);
+ ++NumUnassigned;
+}
+
// Top-level driver to manage the queue of unassigned VirtRegs and call the
// selectOrSplit implementation.
void RegAllocBase::allocatePhysRegs() {
-
- // Push each vreg onto a queue or "precolor" by adding it to a physreg union.
- LiveVirtRegQueue VirtRegQ;
- seedLiveVirtRegs(VirtRegQ);
+ seedLiveRegs();
// Continue assigning vregs one at a time to available physical registers.
- while (!VirtRegQ.empty()) {
- // Pop the highest priority vreg.
- LiveInterval *VirtReg = VirtRegQ.get();
-
+ while (LiveInterval *VirtReg = dequeue()) {
// selectOrSplit requests the allocator to return an available physical
// register if possible and populate a list of new live intervals that
// result from splitting.
+ DEBUG(dbgs() << "\nselectOrSplit "
+ << MRI->getRegClass(VirtReg->reg)->getName()
+ << ':' << *VirtReg << '\n');
typedef SmallVector<LiveInterval*, 4> VirtRegVec;
VirtRegVec SplitVRegs;
unsigned AvailablePhysReg = selectOrSplit(*VirtReg, SplitVRegs);
- if (AvailablePhysReg) {
- DEBUG(dbgs() << "allocating: " << TRI->getName(AvailablePhysReg) <<
- " " << *VirtReg << '\n');
- assert(!VRM->hasPhys(VirtReg->reg) && "duplicate vreg in union");
- VRM->assignVirt2Phys(VirtReg->reg, AvailablePhysReg);
- PhysReg2LiveUnion[AvailablePhysReg].unify(*VirtReg);
- }
+ if (AvailablePhysReg)
+ assign(*VirtReg, AvailablePhysReg);
+
for (VirtRegVec::iterator I = SplitVRegs.begin(), E = SplitVRegs.end();
I != E; ++I) {
- LiveInterval* SplitVirtReg = *I;
+ LiveInterval *SplitVirtReg = *I;
if (SplitVirtReg->empty()) continue;
DEBUG(dbgs() << "queuing new interval: " << *SplitVirtReg << "\n");
assert(TargetRegisterInfo::isVirtualRegister(SplitVirtReg->reg) &&
"expect split value in virtual register");
- VirtRegQ.push(SplitVirtReg);
+ enqueue(SplitVirtReg);
+ ++NumNewQueued;
}
}
}
// physical register. Return the interfering register.
unsigned RegAllocBase::checkPhysRegInterference(LiveInterval &VirtReg,
unsigned PhysReg) {
- if (query(VirtReg, PhysReg).checkInterference())
- return PhysReg;
- for (const unsigned *AliasI = TRI->getAliasSet(PhysReg); *AliasI; ++AliasI) {
+ for (const unsigned *AliasI = TRI->getOverlaps(PhysReg); *AliasI; ++AliasI)
if (query(VirtReg, *AliasI).checkInterference())
return *AliasI;
- }
return 0;
}
// Deallocate the interfering vreg by removing it from the union.
// A LiveInterval instance may not be in a union during modification!
- PhysReg2LiveUnion[PhysReg].extract(SpilledVReg);
-
- // Clear the vreg assignment.
- VRM->clearVirt(SpilledVReg.reg);
+ unassign(SpilledVReg, PhysReg);
// Spill the extracted interval.
spiller().spill(&SpilledVReg, SplitVRegs, PendingSpills);
SmallVectorImpl<LiveInterval*> &SplitVRegs) {
// Record each interference and determine if all are spillable before mutating
// either the union or live intervals.
-
- // Collect interferences assigned to the requested physical register.
- LiveIntervalUnion::Query &QPreg = query(VirtReg, PhysReg);
- unsigned NumInterferences = QPreg.collectInterferingVRegs();
- if (QPreg.seenUnspillableVReg()) {
- return false;
- }
+ unsigned NumInterferences = 0;
// Collect interferences assigned to any alias of the physical register.
- for (const unsigned *asI = TRI->getAliasSet(PhysReg); *asI; ++asI) {
+ for (const unsigned *asI = TRI->getOverlaps(PhysReg); *asI; ++asI) {
LiveIntervalUnion::Query &QAlias = query(VirtReg, *asI);
NumInterferences += QAlias.collectInterferingVRegs();
if (QAlias.seenUnspillableVReg()) {
assert(NumInterferences > 0 && "expect interference");
// Spill each interfering vreg allocated to PhysReg or an alias.
- spillReg(VirtReg, PhysReg, SplitVRegs);
- for (const unsigned *AliasI = TRI->getAliasSet(PhysReg); *AliasI; ++AliasI)
+ for (const unsigned *AliasI = TRI->getOverlaps(PhysReg); *AliasI; ++AliasI)
spillReg(VirtReg, *AliasI, SplitVRegs);
return true;
}
+// Add newly allocated physical registers to the MBB live in sets.
+void RegAllocBase::addMBBLiveIns(MachineFunction *MF) {
+ NamedRegionTimer T("MBB Live Ins", TimerGroupName, TimePassesIsEnabled);
+ typedef SmallVector<MachineBasicBlock*, 8> MBBVec;
+ MBBVec liveInMBBs;
+ MachineBasicBlock &entryMBB = *MF->begin();
+
+ for (unsigned PhysReg = 0; PhysReg < PhysReg2LiveUnion.numRegs(); ++PhysReg) {
+ LiveIntervalUnion &LiveUnion = PhysReg2LiveUnion[PhysReg];
+ if (LiveUnion.empty())
+ continue;
+ for (LiveIntervalUnion::SegmentIter SI = LiveUnion.begin(); SI.valid();
+ ++SI) {
+
+ // Find the set of basic blocks which this range is live into...
+ liveInMBBs.clear();
+ if (!LIS->findLiveInMBBs(SI.start(), SI.stop(), liveInMBBs)) continue;
+
+ // And add the physreg for this interval to their live-in sets.
+ for (MBBVec::iterator I = liveInMBBs.begin(), E = liveInMBBs.end();
+ I != E; ++I) {
+ MachineBasicBlock *MBB = *I;
+ if (MBB == &entryMBB) continue;
+ if (MBB->isLiveIn(PhysReg)) continue;
+ MBB->addLiveIn(PhysReg);
+ }
+ }
+ }
+}
+
+
//===----------------------------------------------------------------------===//
// RABasic Implementation
//===----------------------------------------------------------------------===//
// Check for an available register in this class.
const TargetRegisterClass *TRC = MRI->getRegClass(VirtReg.reg);
- DEBUG(dbgs() << "RegClass: " << TRC->getName() << ' ');
for (TargetRegisterClass::iterator I = TRC->allocation_order_begin(*MF),
E = TRC->allocation_order_end(*MF);
LiveInterval *interferingVirtReg =
Queries[interfReg].firstInterference().liveUnionPos().value();
- // The current VirtReg must either spillable, or one of its interferences
+ // The current VirtReg must either be spillable, or one of its interferences
// must have less spill weight.
if (interferingVirtReg->weight < VirtReg.weight ) {
PhysRegSpillCands.push_back(PhysReg);
}
}
// Try to spill another interfering reg with less spill weight.
- //
- // FIXME: RAGreedy will sort this list by spill weight.
for (SmallVectorImpl<unsigned>::iterator PhysRegI = PhysRegSpillCands.begin(),
PhysRegE = PhysRegSpillCands.end(); PhysRegI != PhysRegE; ++PhysRegI) {
return 0;
}
-// Add newly allocated physical registers to the MBB live in sets.
-void RABasic::addMBBLiveIns() {
- typedef SmallVector<MachineBasicBlock*, 8> MBBVec;
- MBBVec liveInMBBs;
- MachineBasicBlock &entryMBB = *MF->begin();
-
- for (unsigned PhysReg = 0; PhysReg < PhysReg2LiveUnion.numRegs(); ++PhysReg) {
- LiveIntervalUnion &LiveUnion = PhysReg2LiveUnion[PhysReg];
-
- for (LiveIntervalUnion::SegmentIter SI = LiveUnion.begin(),
- SegEnd = LiveUnion.end();
- SI != SegEnd; ++SI) {
-
- // Find the set of basic blocks which this range is live into...
- liveInMBBs.clear();
- if (!LIS->findLiveInMBBs(SI.start(), SI.stop(), liveInMBBs)) continue;
-
- // And add the physreg for this interval to their live-in sets.
- for (MBBVec::iterator I = liveInMBBs.begin(), E = liveInMBBs.end();
- I != E; ++I) {
- MachineBasicBlock *MBB = *I;
- if (MBB == &entryMBB) continue;
- if (MBB->isLiveIn(PhysReg)) continue;
- MBB->addLiveIn(PhysReg);
- }
- }
- }
-}
-
bool RABasic::runOnMachineFunction(MachineFunction &mf) {
DEBUG(dbgs() << "********** BASIC REGISTER ALLOCATION **********\n"
<< "********** Function: "
<< ((Value*)mf.getFunction())->getName() << '\n');
MF = &mf;
- TM = &mf.getTarget();
- MRI = &mf.getRegInfo();
-
DEBUG(RMF = &getAnalysis<RenderMachineFunction>());
- const TargetRegisterInfo *TRI = TM->getRegisterInfo();
- RegAllocBase::init(*TRI, getAnalysis<VirtRegMap>(),
- getAnalysis<LiveIntervals>());
+ RegAllocBase::init(getAnalysis<VirtRegMap>(), getAnalysis<LiveIntervals>());
ReservedRegs = TRI->getReservedRegs(*MF);
allocatePhysRegs();
- addMBBLiveIns();
+ addMBBLiveIns(MF);
// Diagnostic output before rewriting
DEBUG(dbgs() << "Post alloc VirtRegMap:\n" << *VRM << "\n");
// make the rewriter a separate pass and override verifyAnalysis instead. When
// that happens, verification naturally falls under VerifyMachineCode.
#ifndef NDEBUG
- if (VerifyRegAlloc) {
+ if (VerifyEnabled) {
// Verify accuracy of LiveIntervals. The standard machine code verifier
// ensures that each LiveIntervals covers all uses of the virtual reg.
// spiller. Always use -spiller=inline with -verify-regalloc. Even with the
// inline spiller, some tests fail to verify because the coalescer does not
// always generate verifiable code.
- MF->verify(this);
+ MF->verify(this, "In RABasic::verify");
// Verify that LiveIntervals are partitioned into unions and disjoint within
// the unions.
#endif // !NDEBUG
// Run rewriter
- std::auto_ptr<VirtRegRewriter> rewriter(createVirtRegRewriter());
- rewriter->runOnMachineFunction(*MF, *VRM, LIS);
+ VRM->rewrite(LIS->getSlotIndexes());
// The pass output is in VirtRegMap. Release all the transient data.
releaseMemory();