aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CodeGen
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2004-07-23 17:49:16 +0000
committerChris Lattner <sabre@nondot.org>2004-07-23 17:49:16 +0000
commitfb449b9ea5a37fb411aee7d42f6a76119602288d (patch)
treec5d42282b5229f57efe6af2a1e5f64c56db83875 /lib/CodeGen
parente2eceb5c739285a6c507ac766ab2807429e13101 (diff)
downloadexternal_llvm-fb449b9ea5a37fb411aee7d42f6a76119602288d.zip
external_llvm-fb449b9ea5a37fb411aee7d42f6a76119602288d.tar.gz
external_llvm-fb449b9ea5a37fb411aee7d42f6a76119602288d.tar.bz2
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
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/LiveInterval.cpp151
-rw-r--r--lib/CodeGen/LiveInterval.h109
-rw-r--r--lib/CodeGen/LiveIntervalAnalysis.cpp189
-rw-r--r--lib/CodeGen/LiveIntervalAnalysis.h76
4 files changed, 286 insertions, 239 deletions
diff --git a/lib/CodeGen/LiveInterval.cpp b/lib/CodeGen/LiveInterval.cpp
new file mode 100644
index 0000000..5954b59
--- /dev/null
+++ b/lib/CodeGen/LiveInterval.cpp
@@ -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;
+}
diff --git a/lib/CodeGen/LiveInterval.h b/lib/CodeGen/LiveInterval.h
new file mode 100644
index 0000000..33bc036
--- /dev/null
+++ b/lib/CodeGen/LiveInterval.h
@@ -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
diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp
index d59c114..0d6ea11 100644
--- a/lib/CodeGen/LiveIntervalAnalysis.cpp
+++ b/lib/CodeGen/LiveIntervalAnalysis.cpp
@@ -250,6 +250,7 @@ std::vector<LiveInterval*> LiveIntervals::addIntervalsForSpills(
// the spill weight is now infinity as it
// cannot be spilled again
nI.weight = HUGE_VAL;
+ DEBUG(std::cerr << " +" << LiveRange(start, end));
nI.addRange(LiveRange(start, end));
added.push_back(&nI);
// update live variables
@@ -309,7 +310,7 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock* mbb,
assert(vi.AliveBlocks.empty() &&
"Shouldn't be alive across any blocks!");
interval.addRange(LiveRange(defIndex, killIdx));
- DEBUG(std::cerr << "\n");
+ DEBUG(std::cerr << " +" << LiveRange(defIndex, killIdx) << "\n");
return;
}
}
@@ -318,9 +319,10 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock* mbb,
// of the defining block, potentially live across some blocks, then is
// 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.
- interval.addRange(LiveRange(defIndex,
- getInstructionIndex(&mbb->back()) +
- InstrSlots::NUM));
+ LiveRange NewLR(defIndex, getInstructionIndex(&mbb->back()) +
+ InstrSlots::NUM);
+ DEBUG(std::cerr << " +" << NewLR);
+ interval.addRange(NewLR);
// Iterate over all of the blocks that the variable is completely
// live in, adding [insrtIndex(begin), instrIndex(end)+4) to the
@@ -329,9 +331,10 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock* mbb,
if (vi.AliveBlocks[i]) {
MachineBasicBlock* mbb = mf_->getBlockNumbered(i);
if (!mbb->empty()) {
- interval.addRange(LiveRange(
- getInstructionIndex(&mbb->front()),
- getInstructionIndex(&mbb->back()) + InstrSlots::NUM));
+ LiveRange LR(getInstructionIndex(&mbb->front()),
+ 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.
for (unsigned i = 0, e = vi.Kills.size(); i != e; ++i) {
MachineInstr *Kill = vi.Kills[i];
- interval.addRange(LiveRange(
- getInstructionIndex(Kill->getParent()->begin()),
- getUseIndex(getInstructionIndex(Kill))+1));
+ LiveRange LR(getInstructionIndex(Kill->getParent()->begin()),
+ getUseIndex(getInstructionIndex(Kill))+1);
+ interval.addRange(LR);
+ DEBUG(std::cerr << " +" << LR);
}
} else {
@@ -359,8 +363,10 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock* mbb,
// the defined value will be live until the end of the basic block it
// is defined in.
unsigned defIndex = getDefIndex(getInstructionIndex(mi));
- interval.addRange(LiveRange(defIndex,
- getInstructionIndex(&mbb->back()) +InstrSlots::NUM));
+ LiveRange LR(defIndex,
+ getInstructionIndex(&mbb->back()) +InstrSlots::NUM);
+ interval.addRange(LR);
+ DEBUG(std::cerr << " +" << LR);
}
interval.isDefinedOnce = false;
}
@@ -413,7 +419,7 @@ void LiveIntervals::handlePhysicalRegisterDef(MachineBasicBlock* mbb,
exit:
assert(start < end && "did not find end of interval?");
interval.addRange(LiveRange(start, end));
- DEBUG(std::cerr << '\n');
+ DEBUG(std::cerr << " +" << LiveRange(start, end) << '\n');
}
void LiveIntervals::handleRegisterDef(MachineBasicBlock* mbb,
@@ -547,10 +553,11 @@ void LiveIntervals::joinIntervalsInMachineBB(MachineBasicBlock *MBB) {
continue;
}
- // if their intervals do not overlap we join them
- if ((intA->isDefinedOnce && intB->isDefinedOnce) ||
+ // if their intervals do not overlap we join them.
+ if ((intA->containsOneValue() && intB->containsOneValue()) ||
!intB->overlaps(*intA)) {
intA->join(*intB);
+ ++numJoins;
DEBUG(std::cerr << "Joined. Result = " << *intA << "\n");
r2iB->second = r2iA->second;
r2rMap_.insert(std::make_pair(intB->reg, intA->reg));
@@ -582,6 +589,7 @@ void LiveIntervals::joinIntervalsInMachineBB(MachineBasicBlock *MBB) {
if (!intA->overlaps(*intB) &&
!overlapsAliases(*intA, *intB)) {
intA->join(*intB);
+ ++numJoins;
DEBUG(std::cerr << "Joined. Result = " << *intA << "\n");
r2iB->second = r2iA->second;
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);
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()));
}
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;
-}
diff --git a/lib/CodeGen/LiveIntervalAnalysis.h b/lib/CodeGen/LiveIntervalAnalysis.h
index a70deff..84c8e06 100644
--- a/lib/CodeGen/LiveIntervalAnalysis.h
+++ b/lib/CodeGen/LiveIntervalAnalysis.h
@@ -21,6 +21,7 @@
#define LLVM_CODEGEN_LIVEINTERVALS_H
#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "LiveInterval.h"
#include <list>
namespace llvm {
@@ -29,81 +30,6 @@ namespace llvm {
class MRegisterInfo;
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
{
public: