Pull the LiveRange and LiveInterval classes out of LiveIntervals.h (which

will soon be renamed) into their own file.  The new file should not emit
DEBUG output or have other side effects.  The LiveInterval class also now
doesn't know whether its working on registers or some other thing.

In the future we will want to use the LiveInterval class and friends to do
stack packing.  In addition to a code simplification, this will allow us to
do it more easily.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15134 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2004-07-23 17:49:16 +00:00
parent e2eceb5c73
commit fb449b9ea5
6 changed files with 396 additions and 314 deletions

View File

@ -0,0 +1,109 @@
//===-- llvm/CodeGen/LiveInterval.h - Interval representation ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the LiveRange and LiveInterval classes. Given some
// numbering of each the machine instructions an interval [i, j) is said to be a
// live interval for register v if there is no instruction with number j' > j
// such that v is live at j' abd there is no instruction with number i' < i such
// that v is live at i'. In this implementation intervals can have holes,
// i.e. an interval might look like [1,20), [50,65), [1000,1001). Each
// individual range is represented as an instance of LiveRange, and the whole
// interval is represented as an instance of LiveInterval.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_LIVEINTERVAL_H
#define LLVM_CODEGEN_LIVEINTERVAL_H
#include <iosfwd>
#include <vector>
#include <cassert>
namespace llvm {
/// LiveRange structure - This represents a simple register range in the
/// program, with an inclusive start point and an exclusive end point.
/// These ranges are rendered as [start,end).
struct LiveRange {
unsigned start; // Start point of the interval (inclusive)
unsigned end; // End point of the interval (exclusive)
LiveRange(unsigned S, unsigned E) : start(S), end(E) {
assert(S < E && "Cannot create empty or backwards range");
}
bool operator<(const LiveRange &LR) const {
return start < LR.start || (start == LR.start && end < LR.end);
}
bool operator==(const LiveRange &LR) const {
return start == LR.start && end == LR.end;
}
private:
LiveRange(); // DO NOT IMPLEMENT
};
std::ostream& operator<<(std::ostream& os, const LiveRange &LR);
/// LiveInterval - This class represents some number of live ranges for a
/// register or value. This class also contains a bit of register allocator
/// state.
struct LiveInterval {
typedef std::vector<LiveRange> Ranges;
unsigned reg; // the register of this interval
float weight; // weight of this interval
Ranges ranges; // the ranges in which this register is live
bool isDefinedOnce; // True if this interval contains one value.
LiveInterval(unsigned Reg, float Weight)
: reg(Reg), weight(Weight), isDefinedOnce(false) {
}
bool containsOneValue() const { return isDefinedOnce; }
bool empty() const { return ranges.empty(); }
/// start - Return the lowest numbered slot covered by interval.
unsigned start() const {
assert(!empty() && "empty interval for register");
return ranges.front().start;
}
/// end - return the maximum point of the interval of the whole,
/// exclusive.
unsigned end() const {
assert(!empty() && "empty interval for register");
return ranges.back().end;
}
bool expiredAt(unsigned index) const {
return end() <= (index + 1);
}
bool liveAt(unsigned index) const;
bool overlaps(const LiveInterval& other) const;
void addRange(LiveRange R);
void join(const LiveInterval& other);
bool operator<(const LiveInterval& other) const {
return start() < other.start();
}
bool operator==(const LiveInterval& other) const {
return reg == other.reg;
}
private:
Ranges::iterator mergeRangesForward(Ranges::iterator it);
Ranges::iterator mergeRangesBackward(Ranges::iterator it);
};
std::ostream& operator<<(std::ostream& os, const LiveInterval& li);
}
#endif

View File

@ -21,6 +21,7 @@
#define LLVM_CODEGEN_LIVEINTERVALS_H #define LLVM_CODEGEN_LIVEINTERVALS_H
#include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineFunctionPass.h"
#include "LiveInterval.h"
#include <list> #include <list>
namespace llvm { namespace llvm {
@ -29,81 +30,6 @@ namespace llvm {
class MRegisterInfo; class MRegisterInfo;
class VirtRegMap; class VirtRegMap;
/// LiveRange structure - This represents a simple register range in the
/// program, with an inclusive start point and an exclusive end point.
/// These ranges are rendered as [start,end).
struct LiveRange {
unsigned start; // Start point of the interval (inclusive)
unsigned end; // End point of the interval (exclusive)
LiveRange(unsigned S, unsigned E) : start(S), end(E) {
assert(S < E && "Cannot create empty or backwards range");
}
bool operator<(const LiveRange &LR) const {
return start < LR.start || (start == LR.start && end < LR.end);
}
bool operator==(const LiveRange &LR) const {
return start == LR.start && end == LR.end;
}
private:
LiveRange(); // DO NOT IMPLEMENT
};
std::ostream& operator<<(std::ostream& os, const LiveRange &LR);
struct LiveInterval {
typedef std::vector<LiveRange> Ranges;
unsigned reg; // the register of this interval
float weight; // weight of this interval:
// (number of uses *10^loopDepth)
Ranges ranges; // the ranges in which this register is live
bool isDefinedOnce; // True if there is one def of this register
explicit LiveInterval(unsigned r);
bool empty() const { return ranges.empty(); }
bool spilled() const;
/// start - Return the lowest numbered slot covered by interval.
unsigned start() const {
assert(!empty() && "empty interval for register");
return ranges.front().start;
}
/// end - return the maximum point of the interval of the whole,
/// exclusive.
unsigned end() const {
assert(!empty() && "empty interval for register");
return ranges.back().end;
}
bool expiredAt(unsigned index) const {
return end() <= (index + 1);
}
bool liveAt(unsigned index) const;
bool overlaps(const LiveInterval& other) const;
void addRange(LiveRange R);
void join(const LiveInterval& other);
bool operator<(const LiveInterval& other) const {
return start() < other.start();
}
bool operator==(const LiveInterval& other) const {
return reg == other.reg;
}
private:
Ranges::iterator mergeRangesForward(Ranges::iterator it);
Ranges::iterator mergeRangesBackward(Ranges::iterator it);
};
std::ostream& operator<<(std::ostream& os, const LiveInterval& li);
class LiveIntervals : public MachineFunctionPass class LiveIntervals : public MachineFunctionPass
{ {
public: public:

View File

@ -0,0 +1,151 @@
//===-- LiveInterval.cpp - Live Interval Representation -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the LiveRange and LiveInterval classes. Given some
// numbering of each the machine instructions an interval [i, j) is said to be a
// live interval for register v if there is no instruction with number j' > j
// such that v is live at j' abd there is no instruction with number i' < i such
// that v is live at i'. In this implementation intervals can have holes,
// i.e. an interval might look like [1,20), [50,65), [1000,1001). Each
// individual range is represented as an instance of LiveRange, and the whole
// interval is represented as an instance of LiveInterval.
//
//===----------------------------------------------------------------------===//
#include "LiveInterval.h"
#include "Support/STLExtras.h"
#include <ostream>
using namespace llvm;
// An example for liveAt():
//
// this = [1,4), liveAt(0) will return false. The instruction defining
// this spans slots [0,3]. The interval belongs to an spilled
// definition of the variable it represents. This is because slot 1 is
// used (def slot) and spans up to slot 3 (store slot).
//
bool LiveInterval::liveAt(unsigned index) const {
LiveRange dummy(index, index+1);
Ranges::const_iterator r = std::upper_bound(ranges.begin(),
ranges.end(),
dummy);
if (r == ranges.begin())
return false;
--r;
return index >= r->start && index < r->end;
}
// An example for overlaps():
//
// 0: A = ...
// 4: B = ...
// 8: C = A + B ;; last use of A
//
// The live intervals should look like:
//
// A = [3, 11)
// B = [7, x)
// C = [11, y)
//
// A->overlaps(C) should return false since we want to be able to join
// A and C.
bool LiveInterval::overlaps(const LiveInterval& other) const {
Ranges::const_iterator i = ranges.begin();
Ranges::const_iterator ie = ranges.end();
Ranges::const_iterator j = other.ranges.begin();
Ranges::const_iterator je = other.ranges.end();
if (i->start < j->start) {
i = std::upper_bound(i, ie, *j);
if (i != ranges.begin()) --i;
}
else if (j->start < i->start) {
j = std::upper_bound(j, je, *i);
if (j != other.ranges.begin()) --j;
}
while (i != ie && j != je) {
if (i->start == j->start)
return true;
if (i->start > j->start) {
swap(i, j);
swap(ie, je);
}
assert(i->start < j->start);
if (i->end > j->start)
return true;
++i;
}
return false;
}
void LiveInterval::addRange(LiveRange LR) {
Ranges::iterator it =
ranges.insert(std::upper_bound(ranges.begin(), ranges.end(), LR), LR);
mergeRangesBackward(mergeRangesForward(it));
}
void LiveInterval::join(const LiveInterval& other) {
Ranges::iterator cur = ranges.begin();
isDefinedOnce &= other.isDefinedOnce;
for (Ranges::const_iterator i = other.ranges.begin(),
e = other.ranges.end(); i != e; ++i) {
cur = ranges.insert(std::upper_bound(cur, ranges.end(), *i), *i);
cur = mergeRangesBackward(mergeRangesForward(cur));
}
weight += other.weight;
}
LiveInterval::Ranges::iterator
LiveInterval::mergeRangesForward(Ranges::iterator it) {
Ranges::iterator n;
while ((n = next(it)) != ranges.end()) {
if (n->start > it->end)
break;
it->end = std::max(it->end, n->end);
n = ranges.erase(n);
}
return it;
}
LiveInterval::Ranges::iterator
LiveInterval::mergeRangesBackward(Ranges::iterator it) {
while (it != ranges.begin()) {
Ranges::iterator p = prior(it);
if (it->start > p->end)
break;
it->start = std::min(it->start, p->start);
it->end = std::max(it->end, p->end);
it = ranges.erase(p);
}
return it;
}
std::ostream& llvm::operator<<(std::ostream& os, const LiveRange &LR) {
return os << "[" << LR.start << "," << LR.end << ")";
}
std::ostream& llvm::operator<<(std::ostream& os, const LiveInterval& li) {
os << "%reg" << li.reg << ',' << li.weight;
if (li.empty())
return os << "EMPTY";
os << " = ";
for (LiveInterval::Ranges::const_iterator i = li.ranges.begin(),
e = li.ranges.end(); i != e; ++i)
os << *i;
return os;
}

109
lib/CodeGen/LiveInterval.h Normal file
View File

@ -0,0 +1,109 @@
//===-- llvm/CodeGen/LiveInterval.h - Interval representation ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the LiveRange and LiveInterval classes. Given some
// numbering of each the machine instructions an interval [i, j) is said to be a
// live interval for register v if there is no instruction with number j' > j
// such that v is live at j' abd there is no instruction with number i' < i such
// that v is live at i'. In this implementation intervals can have holes,
// i.e. an interval might look like [1,20), [50,65), [1000,1001). Each
// individual range is represented as an instance of LiveRange, and the whole
// interval is represented as an instance of LiveInterval.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_LIVEINTERVAL_H
#define LLVM_CODEGEN_LIVEINTERVAL_H
#include <iosfwd>
#include <vector>
#include <cassert>
namespace llvm {
/// LiveRange structure - This represents a simple register range in the
/// program, with an inclusive start point and an exclusive end point.
/// These ranges are rendered as [start,end).
struct LiveRange {
unsigned start; // Start point of the interval (inclusive)
unsigned end; // End point of the interval (exclusive)
LiveRange(unsigned S, unsigned E) : start(S), end(E) {
assert(S < E && "Cannot create empty or backwards range");
}
bool operator<(const LiveRange &LR) const {
return start < LR.start || (start == LR.start && end < LR.end);
}
bool operator==(const LiveRange &LR) const {
return start == LR.start && end == LR.end;
}
private:
LiveRange(); // DO NOT IMPLEMENT
};
std::ostream& operator<<(std::ostream& os, const LiveRange &LR);
/// LiveInterval - This class represents some number of live ranges for a
/// register or value. This class also contains a bit of register allocator
/// state.
struct LiveInterval {
typedef std::vector<LiveRange> Ranges;
unsigned reg; // the register of this interval
float weight; // weight of this interval
Ranges ranges; // the ranges in which this register is live
bool isDefinedOnce; // True if this interval contains one value.
LiveInterval(unsigned Reg, float Weight)
: reg(Reg), weight(Weight), isDefinedOnce(false) {
}
bool containsOneValue() const { return isDefinedOnce; }
bool empty() const { return ranges.empty(); }
/// start - Return the lowest numbered slot covered by interval.
unsigned start() const {
assert(!empty() && "empty interval for register");
return ranges.front().start;
}
/// end - return the maximum point of the interval of the whole,
/// exclusive.
unsigned end() const {
assert(!empty() && "empty interval for register");
return ranges.back().end;
}
bool expiredAt(unsigned index) const {
return end() <= (index + 1);
}
bool liveAt(unsigned index) const;
bool overlaps(const LiveInterval& other) const;
void addRange(LiveRange R);
void join(const LiveInterval& other);
bool operator<(const LiveInterval& other) const {
return start() < other.start();
}
bool operator==(const LiveInterval& other) const {
return reg == other.reg;
}
private:
Ranges::iterator mergeRangesForward(Ranges::iterator it);
Ranges::iterator mergeRangesBackward(Ranges::iterator it);
};
std::ostream& operator<<(std::ostream& os, const LiveInterval& li);
}
#endif

View File

@ -250,6 +250,7 @@ std::vector<LiveInterval*> LiveIntervals::addIntervalsForSpills(
// the spill weight is now infinity as it // the spill weight is now infinity as it
// cannot be spilled again // cannot be spilled again
nI.weight = HUGE_VAL; nI.weight = HUGE_VAL;
DEBUG(std::cerr << " +" << LiveRange(start, end));
nI.addRange(LiveRange(start, end)); nI.addRange(LiveRange(start, end));
added.push_back(&nI); added.push_back(&nI);
// update live variables // update live variables
@ -309,7 +310,7 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock* mbb,
assert(vi.AliveBlocks.empty() && assert(vi.AliveBlocks.empty() &&
"Shouldn't be alive across any blocks!"); "Shouldn't be alive across any blocks!");
interval.addRange(LiveRange(defIndex, killIdx)); interval.addRange(LiveRange(defIndex, killIdx));
DEBUG(std::cerr << "\n"); DEBUG(std::cerr << " +" << LiveRange(defIndex, killIdx) << "\n");
return; return;
} }
} }
@ -318,9 +319,10 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock* mbb,
// of the defining block, potentially live across some blocks, then is // of the defining block, potentially live across some blocks, then is
// live into some number of blocks, but gets killed. Start by adding a // live into some number of blocks, but gets killed. Start by adding a
// range that goes from this definition to the end of the defining block. // range that goes from this definition to the end of the defining block.
interval.addRange(LiveRange(defIndex, LiveRange NewLR(defIndex, getInstructionIndex(&mbb->back()) +
getInstructionIndex(&mbb->back()) + InstrSlots::NUM);
InstrSlots::NUM)); DEBUG(std::cerr << " +" << NewLR);
interval.addRange(NewLR);
// Iterate over all of the blocks that the variable is completely // Iterate over all of the blocks that the variable is completely
// live in, adding [insrtIndex(begin), instrIndex(end)+4) to the // live in, adding [insrtIndex(begin), instrIndex(end)+4) to the
@ -329,9 +331,10 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock* mbb,
if (vi.AliveBlocks[i]) { if (vi.AliveBlocks[i]) {
MachineBasicBlock* mbb = mf_->getBlockNumbered(i); MachineBasicBlock* mbb = mf_->getBlockNumbered(i);
if (!mbb->empty()) { if (!mbb->empty()) {
interval.addRange(LiveRange( LiveRange LR(getInstructionIndex(&mbb->front()),
getInstructionIndex(&mbb->front()), getInstructionIndex(&mbb->back())+InstrSlots::NUM);
getInstructionIndex(&mbb->back()) + InstrSlots::NUM)); interval.addRange(LR);
DEBUG(std::cerr << " +" << LR);
} }
} }
} }
@ -340,9 +343,10 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock* mbb,
// block to the 'use' slot of the killing instruction. // block to the 'use' slot of the killing instruction.
for (unsigned i = 0, e = vi.Kills.size(); i != e; ++i) { for (unsigned i = 0, e = vi.Kills.size(); i != e; ++i) {
MachineInstr *Kill = vi.Kills[i]; MachineInstr *Kill = vi.Kills[i];
interval.addRange(LiveRange( LiveRange LR(getInstructionIndex(Kill->getParent()->begin()),
getInstructionIndex(Kill->getParent()->begin()), getUseIndex(getInstructionIndex(Kill))+1);
getUseIndex(getInstructionIndex(Kill))+1)); interval.addRange(LR);
DEBUG(std::cerr << " +" << LR);
} }
} else { } else {
@ -359,8 +363,10 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock* mbb,
// the defined value will be live until the end of the basic block it // the defined value will be live until the end of the basic block it
// is defined in. // is defined in.
unsigned defIndex = getDefIndex(getInstructionIndex(mi)); unsigned defIndex = getDefIndex(getInstructionIndex(mi));
interval.addRange(LiveRange(defIndex, LiveRange LR(defIndex,
getInstructionIndex(&mbb->back()) +InstrSlots::NUM)); getInstructionIndex(&mbb->back()) +InstrSlots::NUM);
interval.addRange(LR);
DEBUG(std::cerr << " +" << LR);
} }
interval.isDefinedOnce = false; interval.isDefinedOnce = false;
} }
@ -413,7 +419,7 @@ void LiveIntervals::handlePhysicalRegisterDef(MachineBasicBlock* mbb,
exit: exit:
assert(start < end && "did not find end of interval?"); assert(start < end && "did not find end of interval?");
interval.addRange(LiveRange(start, end)); interval.addRange(LiveRange(start, end));
DEBUG(std::cerr << '\n'); DEBUG(std::cerr << " +" << LiveRange(start, end) << '\n');
} }
void LiveIntervals::handleRegisterDef(MachineBasicBlock* mbb, void LiveIntervals::handleRegisterDef(MachineBasicBlock* mbb,
@ -547,10 +553,11 @@ void LiveIntervals::joinIntervalsInMachineBB(MachineBasicBlock *MBB) {
continue; continue;
} }
// if their intervals do not overlap we join them // if their intervals do not overlap we join them.
if ((intA->isDefinedOnce && intB->isDefinedOnce) || if ((intA->containsOneValue() && intB->containsOneValue()) ||
!intB->overlaps(*intA)) { !intB->overlaps(*intA)) {
intA->join(*intB); intA->join(*intB);
++numJoins;
DEBUG(std::cerr << "Joined. Result = " << *intA << "\n"); DEBUG(std::cerr << "Joined. Result = " << *intA << "\n");
r2iB->second = r2iA->second; r2iB->second = r2iA->second;
r2rMap_.insert(std::make_pair(intB->reg, intA->reg)); r2rMap_.insert(std::make_pair(intB->reg, intA->reg));
@ -582,6 +589,7 @@ void LiveIntervals::joinIntervalsInMachineBB(MachineBasicBlock *MBB) {
if (!intA->overlaps(*intB) && if (!intA->overlaps(*intB) &&
!overlapsAliases(*intA, *intB)) { !overlapsAliases(*intA, *intB)) {
intA->join(*intB); intA->join(*intB);
++numJoins;
DEBUG(std::cerr << "Joined. Result = " << *intA << "\n"); DEBUG(std::cerr << "Joined. Result = " << *intA << "\n");
r2iB->second = r2iA->second; r2iB->second = r2iA->second;
r2rMap_.insert(std::make_pair(intB->reg, intA->reg)); r2rMap_.insert(std::make_pair(intB->reg, intA->reg));
@ -656,158 +664,11 @@ LiveInterval& LiveIntervals::getOrCreateInterval(unsigned reg)
{ {
Reg2IntervalMap::iterator r2iit = r2iMap_.lower_bound(reg); Reg2IntervalMap::iterator r2iit = r2iMap_.lower_bound(reg);
if (r2iit == r2iMap_.end() || r2iit->first != reg) { if (r2iit == r2iMap_.end() || r2iit->first != reg) {
intervals_.push_back(LiveInterval(reg)); float Weight = MRegisterInfo::isPhysicalRegister(reg) ? HUGE_VAL :0.0F;
intervals_.push_back(LiveInterval(reg, Weight));
r2iit = r2iMap_.insert(r2iit, std::make_pair(reg, --intervals_.end())); r2iit = r2iMap_.insert(r2iit, std::make_pair(reg, --intervals_.end()));
} }
return *r2iit->second; return *r2iit->second;
} }
LiveInterval::LiveInterval(unsigned r)
: reg(r),
weight((MRegisterInfo::isPhysicalRegister(r) ? HUGE_VAL : 0.0F)),
isDefinedOnce(false) {
}
bool LiveInterval::spilled() const
{
return (weight == HUGE_VAL &&
MRegisterInfo::isVirtualRegister(reg));
}
// An example for liveAt():
//
// this = [1,4), liveAt(0) will return false. The instruction defining
// this spans slots [0,3]. The interval belongs to an spilled
// definition of the variable it represents. This is because slot 1 is
// used (def slot) and spans up to slot 3 (store slot).
//
bool LiveInterval::liveAt(unsigned index) const
{
LiveRange dummy(index, index+1);
Ranges::const_iterator r = std::upper_bound(ranges.begin(),
ranges.end(),
dummy);
if (r == ranges.begin())
return false;
--r;
return index >= r->start && index < r->end;
}
// An example for overlaps():
//
// 0: A = ...
// 4: B = ...
// 8: C = A + B ;; last use of A
//
// The live intervals should look like:
//
// A = [3, 11)
// B = [7, x)
// C = [11, y)
//
// A->overlaps(C) should return false since we want to be able to join
// A and C.
bool LiveInterval::overlaps(const LiveInterval& other) const
{
Ranges::const_iterator i = ranges.begin();
Ranges::const_iterator ie = ranges.end();
Ranges::const_iterator j = other.ranges.begin();
Ranges::const_iterator je = other.ranges.end();
if (i->start < j->start) {
i = std::upper_bound(i, ie, *j);
if (i != ranges.begin()) --i;
}
else if (j->start < i->start) {
j = std::upper_bound(j, je, *i);
if (j != other.ranges.begin()) --j;
}
while (i != ie && j != je) {
if (i->start == j->start)
return true;
if (i->start > j->start) {
swap(i, j);
swap(ie, je);
}
assert(i->start < j->start);
if (i->end > j->start)
return true;
++i;
}
return false;
}
void LiveInterval::addRange(LiveRange LR) {
DEBUG(std::cerr << " +" << LR);
Ranges::iterator it =
ranges.insert(std::upper_bound(ranges.begin(), ranges.end(), LR), LR);
mergeRangesBackward(mergeRangesForward(it));
}
void LiveInterval::join(const LiveInterval& other)
{
Ranges::iterator cur = ranges.begin();
isDefinedOnce &= other.isDefinedOnce;
for (Ranges::const_iterator i = other.ranges.begin(),
e = other.ranges.end(); i != e; ++i) {
cur = ranges.insert(std::upper_bound(cur, ranges.end(), *i), *i);
cur = mergeRangesForward(cur);
cur = mergeRangesBackward(cur);
}
weight += other.weight;
++numJoins;
}
LiveInterval::Ranges::iterator LiveInterval::
mergeRangesForward(Ranges::iterator it)
{
Ranges::iterator n;
while ((n = next(it)) != ranges.end()) {
if (n->start > it->end)
break;
it->end = std::max(it->end, n->end);
n = ranges.erase(n);
}
return it;
}
LiveInterval::Ranges::iterator LiveInterval::
mergeRangesBackward(Ranges::iterator it)
{
while (it != ranges.begin()) {
Ranges::iterator p = prior(it);
if (it->start > p->end)
break;
it->start = std::min(it->start, p->start);
it->end = std::max(it->end, p->end);
it = ranges.erase(p);
}
return it;
}
std::ostream& llvm::operator<<(std::ostream& os, const LiveRange &LR) {
return os << "[" << LR.start << "," << LR.end << ")";
}
std::ostream& llvm::operator<<(std::ostream& os, const LiveInterval& li)
{
os << "%reg" << li.reg << ',' << li.weight;
if (li.empty())
return os << "EMPTY";
os << " = ";
for (LiveInterval::Ranges::const_iterator i = li.ranges.begin(),
e = li.ranges.end(); i != e; ++i)
os << *i;
return os;
}

View File

@ -21,6 +21,7 @@
#define LLVM_CODEGEN_LIVEINTERVALS_H #define LLVM_CODEGEN_LIVEINTERVALS_H
#include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineFunctionPass.h"
#include "LiveInterval.h"
#include <list> #include <list>
namespace llvm { namespace llvm {
@ -29,81 +30,6 @@ namespace llvm {
class MRegisterInfo; class MRegisterInfo;
class VirtRegMap; class VirtRegMap;
/// LiveRange structure - This represents a simple register range in the
/// program, with an inclusive start point and an exclusive end point.
/// These ranges are rendered as [start,end).
struct LiveRange {
unsigned start; // Start point of the interval (inclusive)
unsigned end; // End point of the interval (exclusive)
LiveRange(unsigned S, unsigned E) : start(S), end(E) {
assert(S < E && "Cannot create empty or backwards range");
}
bool operator<(const LiveRange &LR) const {
return start < LR.start || (start == LR.start && end < LR.end);
}
bool operator==(const LiveRange &LR) const {
return start == LR.start && end == LR.end;
}
private:
LiveRange(); // DO NOT IMPLEMENT
};
std::ostream& operator<<(std::ostream& os, const LiveRange &LR);
struct LiveInterval {
typedef std::vector<LiveRange> Ranges;
unsigned reg; // the register of this interval
float weight; // weight of this interval:
// (number of uses *10^loopDepth)
Ranges ranges; // the ranges in which this register is live
bool isDefinedOnce; // True if there is one def of this register
explicit LiveInterval(unsigned r);
bool empty() const { return ranges.empty(); }
bool spilled() const;
/// start - Return the lowest numbered slot covered by interval.
unsigned start() const {
assert(!empty() && "empty interval for register");
return ranges.front().start;
}
/// end - return the maximum point of the interval of the whole,
/// exclusive.
unsigned end() const {
assert(!empty() && "empty interval for register");
return ranges.back().end;
}
bool expiredAt(unsigned index) const {
return end() <= (index + 1);
}
bool liveAt(unsigned index) const;
bool overlaps(const LiveInterval& other) const;
void addRange(LiveRange R);
void join(const LiveInterval& other);
bool operator<(const LiveInterval& other) const {
return start() < other.start();
}
bool operator==(const LiveInterval& other) const {
return reg == other.reg;
}
private:
Ranges::iterator mergeRangesForward(Ranges::iterator it);
Ranges::iterator mergeRangesBackward(Ranges::iterator it);
};
std::ostream& operator<<(std::ostream& os, const LiveInterval& li);
class LiveIntervals : public MachineFunctionPass class LiveIntervals : public MachineFunctionPass
{ {
public: public: