mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-19 04:32:19 +00:00
Switch LiveIntervalUnion from std::set to IntervalMap.
This speeds up RegAllocBasic by 20%, not counting releaseMemory which becomes way faster. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121201 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
da2fdcbb63
commit
953af2c3c5
@ -21,98 +21,50 @@
|
||||
#include <algorithm>
|
||||
using namespace llvm;
|
||||
|
||||
// Find the first segment in the range [SegBegin,Segments.end()) that
|
||||
// intersects with LS. If no intersection is found, return the first SI
|
||||
// such that SI.start >= LS.End.
|
||||
//
|
||||
// This logic is tied to the underlying LiveSegments data structure. For now, we
|
||||
// use set::upper_bound to find the nearest starting position,
|
||||
// then reverse iterate to find the first overlap.
|
||||
//
|
||||
// Upon entry we have SegBegin.Start < LS.End
|
||||
// SegBegin |--...
|
||||
// \ .
|
||||
// LS ...-|
|
||||
//
|
||||
// After set::upper_bound, we have SI.start >= LS.start:
|
||||
// SI |--...
|
||||
// /
|
||||
// LS |--...
|
||||
//
|
||||
// Assuming intervals are disjoint, if an intersection exists, it must be the
|
||||
// segment found or the one immediately preceeding it. We continue reverse
|
||||
// iterating to return the first overlapping segment.
|
||||
LiveIntervalUnion::SegmentIter
|
||||
LiveIntervalUnion::upperBound(SegmentIter SegBegin,
|
||||
const LiveSegment &LS) {
|
||||
assert(LS.End > SegBegin->Start && "segment iterator precondition");
|
||||
|
||||
// Get the next LIU segment such that segI->Start is not less than seg.Start
|
||||
//
|
||||
// FIXME: Once we have a B+tree, we can make good use of SegBegin as a hint to
|
||||
// upper_bound. For now, we're forced to search again from the root each time.
|
||||
SegmentIter SI = Segments.upper_bound(LS);
|
||||
while (SI != SegBegin) {
|
||||
--SI;
|
||||
if (LS.Start >= SI->End)
|
||||
return ++SI;
|
||||
}
|
||||
return SI;
|
||||
}
|
||||
|
||||
// Merge a LiveInterval's segments. Guarantee no overlaps.
|
||||
//
|
||||
// After implementing B+tree, segments will be coalesced.
|
||||
void LiveIntervalUnion::unify(LiveInterval &VirtReg) {
|
||||
if (VirtReg.empty())
|
||||
return;
|
||||
|
||||
// Insert each of the virtual register's live segments into the map.
|
||||
SegmentIter SegPos = Segments.begin();
|
||||
for (LiveInterval::iterator VirtRegI = VirtReg.begin(),
|
||||
VirtRegEnd = VirtReg.end();
|
||||
VirtRegI != VirtRegEnd; ++VirtRegI ) {
|
||||
LiveInterval::iterator RegPos = VirtReg.begin();
|
||||
LiveInterval::iterator RegEnd = VirtReg.end();
|
||||
SegmentIter SegPos = Segments.find(RegPos->start);
|
||||
|
||||
LiveSegment Seg(*VirtRegI, &VirtReg);
|
||||
SegPos = Segments.insert(SegPos, Seg);
|
||||
|
||||
assert(*SegPos == Seg && "need equal val for equal key");
|
||||
#ifndef NDEBUG
|
||||
// Check for overlap (inductively).
|
||||
if (SegPos != Segments.begin()) {
|
||||
assert(llvm::prior(SegPos)->End <= Seg.Start && "overlapping segments" );
|
||||
}
|
||||
SegmentIter NextPos = llvm::next(SegPos);
|
||||
if (NextPos != Segments.end())
|
||||
assert(Seg.End <= NextPos->Start && "overlapping segments" );
|
||||
#endif // NDEBUG
|
||||
for (;;) {
|
||||
SegPos.insert(RegPos->start, RegPos->end, &VirtReg);
|
||||
if (++RegPos == RegEnd)
|
||||
return;
|
||||
SegPos.advanceTo(RegPos->start);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove a live virtual register's segments from this union.
|
||||
void LiveIntervalUnion::extract(const LiveInterval &VirtReg) {
|
||||
void LiveIntervalUnion::extract(LiveInterval &VirtReg) {
|
||||
if (VirtReg.empty())
|
||||
return;
|
||||
|
||||
// Remove each of the virtual register's live segments from the map.
|
||||
SegmentIter SegPos = Segments.begin();
|
||||
for (LiveInterval::const_iterator VirtRegI = VirtReg.begin(),
|
||||
VirtRegEnd = VirtReg.end();
|
||||
VirtRegI != VirtRegEnd; ++VirtRegI) {
|
||||
LiveInterval::iterator RegPos = VirtReg.begin();
|
||||
LiveInterval::iterator RegEnd = VirtReg.end();
|
||||
SegmentIter SegPos = Segments.find(RegPos->start);
|
||||
|
||||
LiveSegment Seg(*VirtRegI, const_cast<LiveInterval*>(&VirtReg));
|
||||
SegPos = upperBound(SegPos, Seg);
|
||||
assert(SegPos != Segments.end() && "missing VirtReg segment");
|
||||
for (;;) {
|
||||
assert(SegPos.value() == &VirtReg && "Inconsistent LiveInterval");
|
||||
SegPos.erase();
|
||||
if (!SegPos.valid())
|
||||
return;
|
||||
|
||||
Segments.erase(SegPos++);
|
||||
// Skip all segments that may have been coalesced.
|
||||
RegPos = VirtReg.advanceTo(RegPos, SegPos.start());
|
||||
if (RegPos == RegEnd)
|
||||
return;
|
||||
|
||||
SegPos.advanceTo(RegPos->start);
|
||||
}
|
||||
}
|
||||
|
||||
raw_ostream& llvm::operator<<(raw_ostream& OS, const LiveSegment &LS) {
|
||||
return OS << '[' << LS.Start << ',' << LS.End << ':' <<
|
||||
LS.VirtReg->reg << ")";
|
||||
}
|
||||
|
||||
void LiveSegment::dump() const {
|
||||
dbgs() << *this << "\n";
|
||||
}
|
||||
|
||||
void
|
||||
LiveIntervalUnion::print(raw_ostream &OS,
|
||||
const AbstractRegisterDescription *RegDesc) const {
|
||||
@ -122,10 +74,9 @@ LiveIntervalUnion::print(raw_ostream &OS,
|
||||
else {
|
||||
OS << RepReg;
|
||||
}
|
||||
for (LiveSegments::const_iterator SI = Segments.begin(),
|
||||
SegEnd = Segments.end(); SI != SegEnd; ++SI) {
|
||||
dbgs() << " " << *SI;
|
||||
}
|
||||
for (LiveSegments::const_iterator SI = Segments.begin(); SI.valid(); ++SI)
|
||||
dbgs() << " [" << SI.start() << ' ' << SI.stop() << "):%reg"
|
||||
<< SI.value()->reg;
|
||||
OS << "\n";
|
||||
}
|
||||
|
||||
@ -136,14 +87,8 @@ void LiveIntervalUnion::dump(const AbstractRegisterDescription *RegDesc) const {
|
||||
#ifndef NDEBUG
|
||||
// Verify the live intervals in this union and add them to the visited set.
|
||||
void LiveIntervalUnion::verify(LiveVirtRegBitSet& VisitedVRegs) {
|
||||
SegmentIter SI = Segments.begin();
|
||||
SegmentIter SegEnd = Segments.end();
|
||||
if (SI == SegEnd) return;
|
||||
VisitedVRegs.set(SI->VirtReg->reg);
|
||||
for (++SI; SI != SegEnd; ++SI) {
|
||||
VisitedVRegs.set(SI->VirtReg->reg);
|
||||
assert(llvm::prior(SI)->End <= SI->Start && "overlapping segments" );
|
||||
}
|
||||
for (SegmentIter SI = Segments.begin(); SI.valid(); ++SI)
|
||||
VisitedVRegs.set(SI.value()->reg);
|
||||
}
|
||||
#endif //!NDEBUG
|
||||
|
||||
@ -169,36 +114,30 @@ void LiveIntervalUnion::Query::findIntersection(InterferenceResult &IR) const {
|
||||
|
||||
// Search until reaching the end of the LiveUnion segments.
|
||||
LiveInterval::iterator VirtRegEnd = VirtReg->end();
|
||||
SegmentIter LiveUnionEnd = LiveUnion->end();
|
||||
while (IR.LiveUnionI != LiveUnionEnd) {
|
||||
|
||||
while (IR.LiveUnionI.valid()) {
|
||||
// Slowly advance the live virtual reg iterator until we surpass the next
|
||||
// segment in LiveUnion.
|
||||
//
|
||||
// Note: If this is ever used for coalescing of fixed registers and we have
|
||||
// a live vreg with thousands of segments, then change this code to use
|
||||
// upperBound instead.
|
||||
while (IR.VirtRegI != VirtRegEnd &&
|
||||
IR.VirtRegI->end <= IR.LiveUnionI->Start)
|
||||
++IR.VirtRegI;
|
||||
IR.VirtRegI = VirtReg->advanceTo(IR.VirtRegI, IR.LiveUnionI.start());
|
||||
if (IR.VirtRegI == VirtRegEnd)
|
||||
break; // Retain current (nonoverlapping) LiveUnionI
|
||||
|
||||
// VirtRegI may have advanced far beyond LiveUnionI,
|
||||
// do a fast intersection test to "catch up"
|
||||
LiveSegment Seg(*IR.VirtRegI, VirtReg);
|
||||
IR.LiveUnionI = LiveUnion->upperBound(IR.LiveUnionI, Seg);
|
||||
// VirtRegI may have advanced far beyond LiveUnionI, catch up.
|
||||
IR.LiveUnionI.advanceTo(IR.VirtRegI->start);
|
||||
|
||||
// Check if no LiveUnionI exists with VirtRegI->Start < LiveUnionI.end
|
||||
if (IR.LiveUnionI == LiveUnionEnd)
|
||||
if (!IR.LiveUnionI.valid())
|
||||
break;
|
||||
if (IR.LiveUnionI->Start < IR.VirtRegI->end) {
|
||||
assert(overlap(*IR.VirtRegI, *IR.LiveUnionI) &&
|
||||
if (IR.LiveUnionI.start() < IR.VirtRegI->end) {
|
||||
assert(overlap(*IR.VirtRegI, IR.LiveUnionI) &&
|
||||
"upperBound postcondition");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (IR.LiveUnionI == LiveUnionEnd)
|
||||
if (!IR.LiveUnionI.valid())
|
||||
IR.VirtRegI = VirtRegEnd;
|
||||
}
|
||||
|
||||
@ -221,18 +160,18 @@ bool LiveIntervalUnion::Query::nextInterference(InterferenceResult &IR) const {
|
||||
|
||||
// Advance either the VirtReg or LiveUnion segment to ensure that we visit all
|
||||
// unique overlapping pairs.
|
||||
if (IR.VirtRegI->end < IR.LiveUnionI->End) {
|
||||
if (IR.VirtRegI->end < IR.LiveUnionI.stop()) {
|
||||
if (++IR.VirtRegI == VirtReg->end())
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if (++IR.LiveUnionI == LiveUnion->end()) {
|
||||
if (!(++IR.LiveUnionI).valid()) {
|
||||
IR.VirtRegI = VirtReg->end();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Short-circuit findIntersection() if possible.
|
||||
if (overlap(*IR.VirtRegI, *IR.LiveUnionI))
|
||||
if (overlap(*IR.VirtRegI, IR.LiveUnionI))
|
||||
return true;
|
||||
|
||||
// Find the next intersection.
|
||||
@ -261,55 +200,47 @@ unsigned LiveIntervalUnion::Query::
|
||||
collectInterferingVRegs(unsigned MaxInterferingRegs) {
|
||||
InterferenceResult IR = firstInterference();
|
||||
LiveInterval::iterator VirtRegEnd = VirtReg->end();
|
||||
SegmentIter LiveUnionEnd = LiveUnion->end();
|
||||
LiveInterval *RecentInterferingVReg = NULL;
|
||||
while (IR.LiveUnionI != LiveUnionEnd) {
|
||||
while (IR.LiveUnionI.valid()) {
|
||||
// Advance the union's iterator to reach an unseen interfering vreg.
|
||||
do {
|
||||
if (IR.LiveUnionI->VirtReg == RecentInterferingVReg)
|
||||
if (IR.LiveUnionI.value() == RecentInterferingVReg)
|
||||
continue;
|
||||
|
||||
if (!isSeenInterference(IR.LiveUnionI->VirtReg))
|
||||
if (!isSeenInterference(IR.LiveUnionI.value()))
|
||||
break;
|
||||
|
||||
// Cache the most recent interfering vreg to bypass isSeenInterference.
|
||||
RecentInterferingVReg = IR.LiveUnionI->VirtReg;
|
||||
RecentInterferingVReg = IR.LiveUnionI.value();
|
||||
|
||||
} while( ++IR.LiveUnionI != LiveUnionEnd);
|
||||
if (IR.LiveUnionI == LiveUnionEnd)
|
||||
} while ((++IR.LiveUnionI).valid());
|
||||
if (!IR.LiveUnionI.valid())
|
||||
break;
|
||||
|
||||
// Advance the VirtReg iterator until surpassing the next segment in
|
||||
// LiveUnion.
|
||||
//
|
||||
// Note: If this is ever used for coalescing of fixed registers and we have
|
||||
// a live virtual register with thousands of segments, then use upperBound
|
||||
// instead.
|
||||
while (IR.VirtRegI != VirtRegEnd &&
|
||||
IR.VirtRegI->end <= IR.LiveUnionI->Start)
|
||||
++IR.VirtRegI;
|
||||
IR.VirtRegI = VirtReg->advanceTo(IR.VirtRegI, IR.LiveUnionI.start());
|
||||
if (IR.VirtRegI == VirtRegEnd)
|
||||
break;
|
||||
|
||||
// Check for intersection with the union's segment.
|
||||
if (overlap(*IR.VirtRegI, *IR.LiveUnionI)) {
|
||||
if (overlap(*IR.VirtRegI, IR.LiveUnionI)) {
|
||||
|
||||
if (!IR.LiveUnionI->VirtReg->isSpillable())
|
||||
if (!IR.LiveUnionI.value()->isSpillable())
|
||||
SeenUnspillableVReg = true;
|
||||
|
||||
InterferingVRegs.push_back(IR.LiveUnionI->VirtReg);
|
||||
InterferingVRegs.push_back(IR.LiveUnionI.value());
|
||||
if (InterferingVRegs.size() == MaxInterferingRegs)
|
||||
return MaxInterferingRegs;
|
||||
|
||||
// Cache the most recent interfering vreg to bypass isSeenInterference.
|
||||
RecentInterferingVReg = IR.LiveUnionI->VirtReg;
|
||||
RecentInterferingVReg = IR.LiveUnionI.value();
|
||||
++IR.LiveUnionI;
|
||||
continue;
|
||||
}
|
||||
// VirtRegI may have advanced far beyond LiveUnionI,
|
||||
// do a fast intersection test to "catch up"
|
||||
LiveSegment Seg(*IR.VirtRegI, VirtReg);
|
||||
IR.LiveUnionI = LiveUnion->upperBound(IR.LiveUnionI, Seg);
|
||||
IR.LiveUnionI.advanceTo(IR.VirtRegI->start);
|
||||
}
|
||||
SeenAllInterferences = true;
|
||||
return InterferingVRegs.size();
|
||||
|
@ -17,8 +17,8 @@
|
||||
#ifndef LLVM_CODEGEN_LIVEINTERVALUNION
|
||||
#define LLVM_CODEGEN_LIVEINTERVALUNION
|
||||
|
||||
#include "llvm/ADT/IntervalMap.h"
|
||||
#include "llvm/CodeGen/LiveInterval.h"
|
||||
#include <set>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -28,58 +28,6 @@ template <unsigned Element> class SparseBitVector;
|
||||
typedef SparseBitVector<128> LiveVirtRegBitSet;
|
||||
#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
|
||||
/// the live virtual register as we iterate over live segments in a union. Note
|
||||
/// that LiveRange is misnamed and actually represents only a single contiguous
|
||||
/// interval within a virtual register's liveness. To limit confusion, in this
|
||||
/// file we refer it as a live segment.
|
||||
///
|
||||
/// Note: This currently represents a half-open interval [Start,End).
|
||||
/// If LiveRange is modified to represent a closed interval, so should this.
|
||||
struct LiveSegment {
|
||||
SlotIndex Start;
|
||||
SlotIndex End;
|
||||
LiveInterval *VirtReg;
|
||||
|
||||
LiveSegment(const LiveRange& LR, LiveInterval *VReg)
|
||||
: Start(LR.start), End(LR.end), VirtReg(VReg) {}
|
||||
|
||||
bool operator==(const LiveSegment &LS) const {
|
||||
return Start == LS.Start && End == LS.End && VirtReg == LS.VirtReg;
|
||||
}
|
||||
|
||||
bool operator!=(const LiveSegment &LS) const {
|
||||
return !operator==(LS);
|
||||
}
|
||||
|
||||
// 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 Idx, const LiveSegment &LS) {
|
||||
return Idx < LS.Start;
|
||||
}
|
||||
|
||||
inline bool operator<(const LiveSegment &LS, SlotIndex Idx) {
|
||||
return LS.Start < Idx;
|
||||
}
|
||||
|
||||
/// Compare a live virtual register segment to a LiveIntervalUnion segment.
|
||||
inline bool overlap(const LiveRange &VirtRegSegment,
|
||||
const LiveSegment &LiveUnionSegment) {
|
||||
return VirtRegSegment.start < LiveUnionSegment.End &&
|
||||
LiveUnionSegment.Start < VirtRegSegment.end;
|
||||
}
|
||||
|
||||
template <> struct isPodLike<LiveSegment> { static const bool value = true; };
|
||||
|
||||
raw_ostream& operator<<(raw_ostream& OS, const LiveSegment &LS);
|
||||
|
||||
/// Abstraction to provide info for the representative register.
|
||||
class AbstractRegisterDescription {
|
||||
public:
|
||||
@ -87,6 +35,13 @@ public:
|
||||
virtual ~AbstractRegisterDescription() {}
|
||||
};
|
||||
|
||||
/// Compare a live virtual register segment to a LiveIntervalUnion segment.
|
||||
inline bool
|
||||
overlap(const LiveRange &VRSeg,
|
||||
const IntervalMap<SlotIndex, LiveInterval*>::const_iterator &LUSeg) {
|
||||
return VRSeg.start < LUSeg.stop() && LUSeg.start() < VRSeg.end;
|
||||
}
|
||||
|
||||
/// 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
|
||||
@ -94,10 +49,8 @@ public:
|
||||
class LiveIntervalUnion {
|
||||
// A set of live virtual register segments that supports fast insertion,
|
||||
// intersection, and removal.
|
||||
//
|
||||
// FIXME: std::set is a placeholder until we decide how to
|
||||
// efficiently represent it. Probably need to roll our own B-tree.
|
||||
typedef std::set<LiveSegment> LiveSegments;
|
||||
// Mapping SlotIndex intervals to virtual register numbers.
|
||||
typedef IntervalMap<SlotIndex, LiveInterval*> LiveSegments;
|
||||
|
||||
public:
|
||||
// SegmentIter can advance to the next segment ordered by starting position
|
||||
@ -105,36 +58,29 @@ public:
|
||||
// to reach the current segment's containing virtual register.
|
||||
typedef LiveSegments::iterator SegmentIter;
|
||||
|
||||
// LiveIntervalUnions share an external allocator.
|
||||
typedef LiveSegments::Allocator Allocator;
|
||||
|
||||
class InterferenceResult;
|
||||
class Query;
|
||||
|
||||
private:
|
||||
unsigned RepReg; // representative register number
|
||||
LiveSegments Segments; // union of virtual reg segements
|
||||
const unsigned RepReg; // representative register number
|
||||
LiveSegments Segments; // union of virtual reg segments
|
||||
|
||||
public:
|
||||
// default ctor avoids placement new
|
||||
LiveIntervalUnion() : RepReg(0) {}
|
||||
|
||||
// Initialize the union by associating it with a representative register
|
||||
// number.
|
||||
void init(unsigned Reg) { RepReg = Reg; }
|
||||
LiveIntervalUnion(unsigned r, Allocator &a) : RepReg(r), Segments(a) {}
|
||||
|
||||
// Iterate over all segments in the union of live virtual registers ordered
|
||||
// by their starting position.
|
||||
SegmentIter begin() { return Segments.begin(); }
|
||||
SegmentIter end() { return Segments.end(); }
|
||||
|
||||
// Return an iterator to the first segment after or including begin that
|
||||
// intersects with LS.
|
||||
SegmentIter upperBound(SegmentIter SegBegin, const LiveSegment &LS);
|
||||
|
||||
// Add a live virtual register to this union and merge its segments.
|
||||
// Holds a nonconst reference to the VirtReg for later maniplution.
|
||||
void unify(LiveInterval &VirtReg);
|
||||
|
||||
// Remove a live virtual register's segments from this union.
|
||||
void extract(const LiveInterval &VirtReg);
|
||||
void extract(LiveInterval &VirtReg);
|
||||
|
||||
void dump(const AbstractRegisterDescription *RegDesc) const;
|
||||
|
||||
@ -171,7 +117,7 @@ public:
|
||||
LiveInterval::iterator virtRegPos() const { return VirtRegI; }
|
||||
|
||||
// Access the LiveUnion segment.
|
||||
SegmentIter liveUnionPos() const { return LiveUnionI; }
|
||||
const SegmentIter &liveUnionPos() const { return LiveUnionI; }
|
||||
|
||||
bool operator==(const InterferenceResult &IR) const {
|
||||
return VirtRegI == IR.VirtRegI && LiveUnionI == IR.LiveUnionI;
|
||||
@ -228,7 +174,7 @@ public:
|
||||
|
||||
bool isInterference(const InterferenceResult &IR) const {
|
||||
if (IR.VirtRegI != VirtReg->end()) {
|
||||
assert(overlap(*IR.VirtRegI, *IR.LiveUnionI) &&
|
||||
assert(overlap(*IR.VirtRegI, IR.LiveUnionI) &&
|
||||
"invalid segment iterators");
|
||||
return true;
|
||||
}
|
||||
|
@ -38,6 +38,7 @@
|
||||
#define LLVM_CODEGEN_REGALLOCBASE
|
||||
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "LiveIntervalUnion.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -69,17 +70,19 @@ class LiveVirtRegQueue;
|
||||
/// live range splitting. LessSpillWeightPriority is provided as a standard
|
||||
/// comparator, but we may add an interface to override it if necessary.
|
||||
class RegAllocBase {
|
||||
LiveIntervalUnion::Allocator UnionAllocator;
|
||||
protected:
|
||||
// Array of LiveIntervalUnions indexed by physical register.
|
||||
class LiveUnionArray {
|
||||
unsigned NumRegs;
|
||||
OwningArrayPtr<LiveIntervalUnion> Array;
|
||||
LiveIntervalUnion *Array;
|
||||
public:
|
||||
LiveUnionArray(): NumRegs(0) {}
|
||||
LiveUnionArray(): NumRegs(0), Array(0) {}
|
||||
~LiveUnionArray() { clear(); }
|
||||
|
||||
unsigned numRegs() const { return NumRegs; }
|
||||
|
||||
void init(unsigned NRegs);
|
||||
void init(LiveIntervalUnion::Allocator &, unsigned NRegs);
|
||||
|
||||
void clear();
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "Spiller.h"
|
||||
#include "VirtRegMap.h"
|
||||
#include "VirtRegRewriter.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/PassAnalysisSupport.h"
|
||||
@ -44,6 +45,7 @@
|
||||
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <cstdlib>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@ -198,12 +200,13 @@ void RegAllocBase::verify() {
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Instantiate a LiveIntervalUnion for each physical register.
|
||||
void RegAllocBase::LiveUnionArray::init(unsigned NRegs) {
|
||||
Array.reset(new LiveIntervalUnion[NRegs]);
|
||||
void RegAllocBase::LiveUnionArray::init(LiveIntervalUnion::Allocator &allocator,
|
||||
unsigned NRegs) {
|
||||
NumRegs = NRegs;
|
||||
for (unsigned RegNum = 0; RegNum < NRegs; ++RegNum) {
|
||||
Array[RegNum].init(RegNum);
|
||||
}
|
||||
Array =
|
||||
static_cast<LiveIntervalUnion*>(malloc(sizeof(LiveIntervalUnion)*NRegs));
|
||||
for (unsigned r = 0; r != NRegs; ++r)
|
||||
new(Array + r) LiveIntervalUnion(r, allocator);
|
||||
}
|
||||
|
||||
void RegAllocBase::init(const TargetRegisterInfo &tri, VirtRegMap &vrm,
|
||||
@ -211,14 +214,19 @@ void RegAllocBase::init(const TargetRegisterInfo &tri, VirtRegMap &vrm,
|
||||
TRI = &tri;
|
||||
VRM = &vrm;
|
||||
LIS = &lis;
|
||||
PhysReg2LiveUnion.init(TRI->getNumRegs());
|
||||
PhysReg2LiveUnion.init(UnionAllocator, TRI->getNumRegs());
|
||||
// Cache an interferece query for each physical reg
|
||||
Queries.reset(new LiveIntervalUnion::Query[PhysReg2LiveUnion.numRegs()]);
|
||||
}
|
||||
|
||||
void RegAllocBase::LiveUnionArray::clear() {
|
||||
if (!Array)
|
||||
return;
|
||||
for (unsigned r = 0; r != NumRegs; ++r)
|
||||
Array[r].~LiveIntervalUnion();
|
||||
free(Array);
|
||||
NumRegs = 0;
|
||||
Array.reset(0);
|
||||
Array = 0;
|
||||
}
|
||||
|
||||
void RegAllocBase::releaseMemory() {
|
||||
@ -427,7 +435,7 @@ unsigned RABasic::selectOrSplit(LiveInterval &VirtReg,
|
||||
return PhysReg;
|
||||
}
|
||||
LiveInterval *interferingVirtReg =
|
||||
Queries[interfReg].firstInterference().liveUnionPos()->VirtReg;
|
||||
Queries[interfReg].firstInterference().liveUnionPos().value();
|
||||
|
||||
// The current VirtReg must either spillable, or one of its interferences
|
||||
// must have less spill weight.
|
||||
@ -474,7 +482,7 @@ void RABasic::addMBBLiveIns() {
|
||||
|
||||
// Find the set of basic blocks which this range is live into...
|
||||
liveInMBBs.clear();
|
||||
if (!LIS->findLiveInMBBs(SI->Start, SI->End, liveInMBBs)) continue;
|
||||
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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user