aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/RegAllocBasic.cpp
diff options
context:
space:
mode:
authorJakob Stoklund Olesen <stoklund@2pi.dk>2010-12-08 22:22:41 +0000
committerJakob Stoklund Olesen <stoklund@2pi.dk>2010-12-08 22:22:41 +0000
commitd0bec3e62c98b1f0ef3a41db8f95599b2014c131 (patch)
treef7d59ce492f28ed769151e5e41a1c86255786c62 /lib/CodeGen/RegAllocBasic.cpp
parentbece04845e6746fd162bc36e79a6cfd095165c23 (diff)
downloadexternal_llvm-d0bec3e62c98b1f0ef3a41db8f95599b2014c131.zip
external_llvm-d0bec3e62c98b1f0ef3a41db8f95599b2014c131.tar.gz
external_llvm-d0bec3e62c98b1f0ef3a41db8f95599b2014c131.tar.bz2
Store (priority,regnum) pairs in the priority queue instead of providing an
abstract priority queue interface in subclasses that want to override the priority calculations. Subclasses must provide a getPriority() implementation instead. This approach requires less code as long as priorities are expressable as simple floats, and it avoids the dangers of defining potentially expensive priority comparison functions. It also should speed up priority_queue operations since they no longer have to chase pointers when comparing registers. This is not measurable, though. Preferably, we shouldn't use floats to guide code generation. The use of floats here is derived from the use of floats for spill weights. Spill weights have a dynamic range that doesn't lend itself easily to a fixpoint implementation. When someone invents a stable spill weight representation, it can be reused for allocation priorities. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121294 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/RegAllocBasic.cpp')
-rw-r--r--lib/CodeGen/RegAllocBasic.cpp63
1 files changed, 17 insertions, 46 deletions
diff --git a/lib/CodeGen/RegAllocBasic.cpp b/lib/CodeGen/RegAllocBasic.cpp
index d0e6355..88446aa 100644
--- a/lib/CodeGen/RegAllocBasic.cpp
+++ b/lib/CodeGen/RegAllocBasic.cpp
@@ -43,8 +43,6 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
-#include <vector>
-#include <queue>
#include <cstdlib>
using namespace llvm;
@@ -103,6 +101,8 @@ public:
virtual Spiller &spiller() { return *SpillerInstance; }
+ virtual float getPriority(LiveInterval *LI) { return LI->weight; }
+
virtual unsigned selectOrSplit(LiveInterval &VirtReg,
SmallVectorImpl<LiveInterval*> &SplitVRegs);
@@ -230,49 +230,18 @@ void RegAllocBase::releaseMemory() {
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) {
+void RegAllocBase::
+seedLiveVirtRegs(std::priority_queue<std::pair<float, unsigned> > &VirtRegQ) {
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
+ VirtRegQ.push(std::make_pair(getPriority(&VirtReg), RegNum));
}
}
@@ -281,27 +250,28 @@ void RegAllocBase::seedLiveVirtRegs(LiveVirtRegQueue &VirtRegQ) {
void RegAllocBase::allocatePhysRegs() {
// Push each vreg onto a queue or "precolor" by adding it to a physreg union.
- LiveVirtRegQueue VirtRegQ;
+ std::priority_queue<std::pair<float, unsigned> > VirtRegQ;
seedLiveVirtRegs(VirtRegQ);
// Continue assigning vregs one at a time to available physical registers.
while (!VirtRegQ.empty()) {
// Pop the highest priority vreg.
- LiveInterval *VirtReg = VirtRegQ.get();
+ LiveInterval &VirtReg = LIS->getInterval(VirtRegQ.top().second);
+ VirtRegQ.pop();
// selectOrSplit requests the allocator to return an available physical
// register if possible and populate a list of new live intervals that
// result from splitting.
typedef SmallVector<LiveInterval*, 4> VirtRegVec;
VirtRegVec SplitVRegs;
- unsigned AvailablePhysReg = selectOrSplit(*VirtReg, 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);
+ " " << VirtReg << '\n');
+ assert(!VRM->hasPhys(VirtReg.reg) && "duplicate vreg in union");
+ VRM->assignVirt2Phys(VirtReg.reg, AvailablePhysReg);
+ PhysReg2LiveUnion[AvailablePhysReg].unify(VirtReg);
}
for (VirtRegVec::iterator I = SplitVRegs.begin(), E = SplitVRegs.end();
I != E; ++I) {
@@ -310,7 +280,8 @@ void RegAllocBase::allocatePhysRegs() {
DEBUG(dbgs() << "queuing new interval: " << *SplitVirtReg << "\n");
assert(TargetRegisterInfo::isVirtualRegister(SplitVirtReg->reg) &&
"expect split value in virtual register");
- VirtRegQ.push(SplitVirtReg);
+ VirtRegQ.push(std::make_pair(getPriority(SplitVirtReg),
+ SplitVirtReg->reg));
}
}
}