summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/CodeGen/LiveIntervalUnion.cpp52
-rw-r--r--lib/CodeGen/LiveIntervalUnion.h23
-rw-r--r--lib/CodeGen/RegAllocBase.h5
-rw-r--r--lib/CodeGen/RegAllocBasic.cpp94
4 files changed, 158 insertions, 16 deletions
diff --git a/lib/CodeGen/LiveIntervalUnion.cpp b/lib/CodeGen/LiveIntervalUnion.cpp
index ec502cd51e..dccffbb98e 100644
--- a/lib/CodeGen/LiveIntervalUnion.cpp
+++ b/lib/CodeGen/LiveIntervalUnion.cpp
@@ -15,6 +15,7 @@
#define DEBUG_TYPE "regalloc"
#include "LiveIntervalUnion.h"
+#include "llvm/ADT/SparseBitVector.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -73,12 +74,10 @@ void LiveIntervalUnion::unify(LiveInterval &lvr) {
#ifndef NDEBUG
// check for overlap (inductively)
if (segPos != segments_.begin()) {
- SegmentIter prevPos = segPos;
- --prevPos;
- assert(prevPos->end <= segment.start && "overlapping segments" );
+ assert(llvm::prior(segPos)->end <= segment.start &&
+ "overlapping segments" );
}
- SegmentIter nextPos = segPos;
- ++nextPos;
+ SegmentIter nextPos = llvm::next(segPos);
if (nextPos != segments_.end())
assert(segment.end <= nextPos->start && "overlapping segments" );
#endif // NDEBUG
@@ -98,6 +97,49 @@ void LiveIntervalUnion::extract(const LiveInterval &lvr) {
}
}
+raw_ostream& llvm::operator<<(raw_ostream& os, const LiveSegment &ls) {
+ return os << '[' << ls.start << ',' << ls.end << ':' <<
+ ls.liveVirtReg->reg << ")";
+}
+
+void LiveSegment::dump() const {
+ dbgs() << *this << "\n";
+}
+
+void
+LiveIntervalUnion::print(raw_ostream &os,
+ const AbstractRegisterDescription *rdesc) const {
+ os << "LIU ";
+ if (rdesc != NULL)
+ os << rdesc->getName(repReg_);
+ else {
+ os << repReg_;
+ }
+ for (LiveSegments::const_iterator segI = segments_.begin(),
+ segEnd = segments_.end(); segI != segEnd; ++segI) {
+ dbgs() << " " << *segI;
+ }
+ os << "\n";
+}
+
+void LiveIntervalUnion::dump(const AbstractRegisterDescription *rdesc) const {
+ print(dbgs(), rdesc);
+}
+
+#ifndef NDEBUG
+// Verify the live intervals in this union and add them to the visited set.
+void LiveIntervalUnion::verify(LvrBitSet& visitedVRegs) {
+ SegmentIter segI = segments_.begin();
+ SegmentIter segEnd = segments_.end();
+ if (segI == segEnd) return;
+ visitedVRegs.set(segI->liveVirtReg->reg);
+ for (++segI; segI != segEnd; ++segI) {
+ visitedVRegs.set(segI->liveVirtReg->reg);
+ assert(llvm::prior(segI)->end <= segI->start && "overlapping segments" );
+ }
+}
+#endif //!NDEBUG
+
// Private interface accessed by Query.
//
// Find a pair of segments that intersect, one in the live virtual register
diff --git a/lib/CodeGen/LiveIntervalUnion.h b/lib/CodeGen/LiveIntervalUnion.h
index cb07653368..74499f6821 100644
--- a/lib/CodeGen/LiveIntervalUnion.h
+++ b/lib/CodeGen/LiveIntervalUnion.h
@@ -23,6 +23,12 @@
namespace llvm {
+#ifndef NDEBUG
+// forward declaration
+template <unsigned Element> class SparseBitVector;
+typedef SparseBitVector<128> LvrBitSet;
+#endif
+
/// A LiveSegment is a copy of a LiveRange object used within
/// LiveIntervalUnion. LiveSegment additionally contains a pointer to its
/// original live virtual register (LiveInterval). This allows quick lookup of
@@ -51,6 +57,9 @@ struct LiveSegment {
// Order segments by starting point only--we expect them to be disjoint.
bool operator<(const LiveSegment &ls) const { return start < ls.start; }
+
+ void dump() const;
+ void print(raw_ostream &os) const;
};
inline bool operator<(SlotIndex V, const LiveSegment &ls) {
@@ -74,9 +83,9 @@ raw_ostream& operator<<(raw_ostream& os, const LiveSegment &ls);
class AbstractRegisterDescription {
public:
virtual const char *getName(unsigned reg) const = 0;
- virtual ~AbstractRegisterDescription() { }
+ virtual ~AbstractRegisterDescription() {}
};
-
+
/// Union of live intervals that are strong candidates for coalescing into a
/// single register (either physical or virtual depending on the context). We
/// expect the constituent live intervals to be disjoint, although we may
@@ -133,6 +142,16 @@ public:
// Remove a live virtual register's segments from this union.
void extract(const LiveInterval &lvr);
+ void dump(const AbstractRegisterDescription *regInfo) const;
+
+ // If tri != NULL, use it to decode repReg_
+ void print(raw_ostream &os, const AbstractRegisterDescription *rdesc) const;
+
+#ifndef NDEBUG
+ // Verify the live intervals in this union and add them to the visited set.
+ void verify(LvrBitSet& visitedVRegs);
+#endif
+
/// Cache a single interference test result in the form of two intersecting
/// segments. This allows efficiently iterating over the interferences. The
/// iteration logic is handled by LiveIntervalUnion::Query which may
diff --git a/lib/CodeGen/RegAllocBase.h b/lib/CodeGen/RegAllocBase.h
index f4ca972738..fa595fed8b 100644
--- a/lib/CodeGen/RegAllocBase.h
+++ b/lib/CodeGen/RegAllocBase.h
@@ -128,6 +128,11 @@ protected:
// exists, return the interfering register, which may be preg or an alias.
unsigned checkPhysRegInterference(LiveInterval& lvr, unsigned preg);
+#ifndef NDEBUG
+ // Verify each LiveIntervalUnion.
+ void verify();
+#endif
+
// Helper that spills all live virtual registers currently unified under preg
// that interfere with the most recently queried lvr.
void spillInterferences(unsigned preg,
diff --git a/lib/CodeGen/RegAllocBasic.cpp b/lib/CodeGen/RegAllocBasic.cpp
index a2f9ea274b..cd77d13640 100644
--- a/lib/CodeGen/RegAllocBasic.cpp
+++ b/lib/CodeGen/RegAllocBasic.cpp
@@ -34,6 +34,9 @@
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegisterInfo.h"
+#ifndef NDEBUG
+#include "llvm/ADT/SparseBitVector.h"
+#endif
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
@@ -46,6 +49,19 @@ using namespace llvm;
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"));
+
+class PhysicalRegisterDescription : public AbstractRegisterDescription {
+ const TargetRegisterInfo *tri_;
+public:
+ PhysicalRegisterDescription(const TargetRegisterInfo *tri): tri_(tri) {}
+ virtual const char *getName(unsigned reg) const { return tri_->getName(reg); }
+};
+
namespace {
/// RABasic provides a minimal implementation of the basic register allocation
@@ -153,6 +169,40 @@ void RABasic::releaseMemory() {
RegAllocBase::releaseMemory();
}
+#ifndef NDEBUG
+// Verify each LiveIntervalUnion.
+void RegAllocBase::verify() {
+ LvrBitSet visitedVRegs;
+ OwningArrayPtr<LvrBitSet> unionVRegs(new LvrBitSet[physReg2liu_.numRegs()]);
+ // Verify disjoint unions.
+ for (unsigned preg = 0; preg < physReg2liu_.numRegs(); ++preg) {
+ DEBUG(PhysicalRegisterDescription prd(tri_); physReg2liu_[preg].dump(&prd));
+ LvrBitSet &vregs = unionVRegs[preg];
+ physReg2liu_[preg].verify(vregs);
+ // Union + intersection test could be done efficiently in one pass, but
+ // don't add a method to SparseBitVector unless we really need it.
+ assert(!visitedVRegs.intersects(vregs) && "vreg in multiple unions");
+ visitedVRegs |= vregs;
+ }
+ // Verify vreg coverage.
+ for (LiveIntervals::iterator liItr = lis_->begin(), liEnd = lis_->end();
+ liItr != liEnd; ++liItr) {
+ unsigned reg = liItr->first;
+ LiveInterval &li = *liItr->second;
+ if (li.empty() ) continue;
+ if (TargetRegisterInfo::isPhysicalRegister(reg)) continue;
+ if (!vrm_->hasPhys(reg)) continue; // spilled?
+ unsigned preg = vrm_->getPhys(reg);
+ if (!unionVRegs[preg].test(reg)) {
+ dbgs() << "LiveVirtReg " << reg << " not in union " <<
+ tri_->getName(preg) << "\n";
+ llvm_unreachable("unallocated live vreg");
+ }
+ }
+ // FIXME: I'm not sure how to verify spilled intervals.
+}
+#endif //!NDEBUG
+
//===----------------------------------------------------------------------===//
// RegAllocBase Implementation
//===----------------------------------------------------------------------===//
@@ -222,6 +272,7 @@ void RegAllocBase::seedLiveVirtRegs(LiveVirtRegQueue &lvrQ) {
liItr != liEnd; ++liItr) {
unsigned reg = liItr->first;
LiveInterval &li = *liItr->second;
+ if (li.empty()) continue;
if (TargetRegisterInfo::isPhysicalRegister(reg)) {
physReg2liu_[reg].unify(li);
}
@@ -243,13 +294,14 @@ void RegAllocBase::allocatePhysRegs() {
unsigned availablePhysReg = selectOrSplit(*lvr, splitLVRs);
if (availablePhysReg) {
DEBUG(dbgs() << "allocating: " << tri_->getName(availablePhysReg) <<
- " " << lvr << '\n');
+ " " << *lvr << '\n');
assert(!vrm_->hasPhys(lvr->reg) && "duplicate vreg in interval unions");
vrm_->assignVirt2Phys(lvr->reg, availablePhysReg);
physReg2liu_[availablePhysReg].unify(*lvr);
}
for (LVRVec::iterator lvrI = splitLVRs.begin(), lvrEnd = splitLVRs.end();
lvrI != lvrEnd; ++lvrI) {
+ if ((*lvrI)->empty()) continue;
DEBUG(dbgs() << "queuing new interval: " << **lvrI << "\n");
assert(TargetRegisterInfo::isVirtualRegister((*lvrI)->reg) &&
"expect split value in virtual register");
@@ -274,26 +326,32 @@ unsigned RegAllocBase::checkPhysRegInterference(LiveInterval &lvr,
return 0;
}
-// Spill all live virtual registers currently unified under preg that interfere
-// with lvr.
+// Spill or split all live virtual registers currently unified under preg that
+// interfere with lvr. The newly spilled or split live intervals are returned by
+// appending them to splitLVRs.
void RABasic::spillInterferences(unsigned preg,
SmallVectorImpl<LiveInterval*> &splitLVRs) {
SmallPtrSet<LiveInterval*, 8> spilledLVRs;
LiveIntervalUnion::Query &query = queries_[preg];
+ // Record each interference before mutating either the union or live
+ // intervals.
LiveIntervalUnion::InterferenceResult ir = query.firstInterference();
assert(query.isInterference(ir) && "expect interference");
do {
- LiveInterval *lvr = ir.liuSegPos()->liveVirtReg;
- if (!spilledLVRs.insert(lvr)) continue;
- // Spill the previously allocated lvr.
- SmallVector<LiveInterval*, 1> spillIs; // ignored
- spiller_->spill(lvr, splitLVRs, spillIs);
+ spilledLVRs.insert(ir.liuSegPos()->liveVirtReg);
} while (query.nextInterference(ir));
for (SmallPtrSetIterator<LiveInterval*> lvrI = spilledLVRs.begin(),
lvrEnd = spilledLVRs.end();
lvrI != lvrEnd; ++lvrI ) {
+ LiveInterval& lvr = **lvrI;
+ // Spill the previously allocated lvr.
+ DEBUG(dbgs() << "extracting from " << preg << " " << lvr << '\n');
// Deallocate the interfering lvr by removing it from the preg union.
- physReg2liu_[preg].extract(**lvrI);
+ // Live intervals may not be in a union during modification.
+ physReg2liu_[preg].extract(lvr);
+ // Spill the extracted interval.
+ SmallVector<LiveInterval*, 8> spillIs;
+ spiller_->spill(&lvr, splitLVRs, spillIs);
}
// After extracting segments, the query's results are invalid.
query.clear();
@@ -399,6 +457,24 @@ bool RABasic::runOnMachineFunction(MachineFunction &mf) {
// optional HTML output
DEBUG(rmf_->renderMachineFunction("After basic register allocation.", vrm_));
+ // FIXME: Verification currently must run before VirtRegRewriter. We should
+ // make the rewriter a separate pass and override verifyAnalysis instead. When
+ // that happens, verification naturally falls under VerifyMachineCode.
+#ifndef NDEBUG
+ if (VerifyRegAlloc) {
+ // Verify accuracy of LiveIntervals. The standard machine code verifier
+ // ensures that each LiveIntervals covers all uses of the virtual reg.
+
+ // FIXME: MachineVerifier is currently broken when using the standard
+ // spiller. Enable it for InlineSpiller only.
+ // mf_->verify(this);
+
+ // Verify that LiveIntervals are partitioned into unions and disjoint within
+ // the unions.
+ verify();
+ }
+#endif // !NDEBUG
+
// Run rewriter
std::auto_ptr<VirtRegRewriter> rewriter(createVirtRegRewriter());
rewriter->runOnMachineFunction(*mf_, *vrm_, lis_);