-//===-- llvm/CodeGen/LiveInterval.h - Live Interval Analysis ----*- C++ -*-===//
+//===-- LiveIntervalAnalysis.h - Live Interval Analysis ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
//
//===----------------------------------------------------------------------===//
//
-// This file implements the LiveInterval analysis pass. Given some
-// numbering of each the machine instructions (in this implemention
-// depth-first order) 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)
+// This file implements the LiveInterval analysis pass. Given some numbering of
+// each the machine instructions (in this implemention depth-first order) 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).
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CODEGEN_LIVEINTERVALS_H
-#define LLVM_CODEGEN_LIVEINTERVALS_H
+#ifndef LLVM_CODEGEN_LIVEINTERVAL_ANALYSIS_H
+#define LLVM_CODEGEN_LIVEINTERVAL_ANALYSIS_H
#include "llvm/CodeGen/MachineFunctionPass.h"
-#include <list>
+#include "LiveInterval.h"
namespace llvm {
class MRegisterInfo;
class VirtRegMap;
- class LiveIntervals : public MachineFunctionPass
- {
- public:
- struct Interval {
- typedef std::pair<unsigned, unsigned> Range;
- typedef std::vector<Range> Ranges;
- typedef std::vector<unsigned> Defs;
- 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
- Defs defs;
- Interval(unsigned r);
-
- bool empty() const { return ranges.empty(); }
-
- bool spilled() const;
-
- unsigned start() const {
- assert(!empty() && "empty interval for register");
- return ranges.front().first;
- }
-
- unsigned end() const {
- assert(!empty() && "empty interval for register");
- return ranges.back().second;
- }
-
- bool expiredAt(unsigned index) const {
- return end() <= (index + 1);
- }
-
- bool liveAt(unsigned index) const;
-
- bool overlaps(const Interval& other) const;
-
- void addRange(unsigned start, unsigned end);
-
- void join(const Interval& other);
-
- private:
- Ranges::iterator mergeRangesForward(Ranges::iterator it);
-
- Ranges::iterator mergeRangesBackward(Ranges::iterator it);
- };
-
- struct StartPointComp {
- bool operator()(const Interval& lhs, const Interval& rhs) {
- return lhs.ranges.front().first < rhs.ranges.front().first;
- }
- };
-
- struct EndPointComp {
- bool operator()(const Interval& lhs, const Interval& rhs) {
- return lhs.ranges.back().second < rhs.ranges.back().second;
- }
- };
-
- typedef std::list<Interval> Intervals;
-
- private:
+ class LiveIntervals : public MachineFunctionPass {
MachineFunction* mf_;
const TargetMachine* tm_;
const MRegisterInfo* mri_;
- MachineBasicBlock* currentMbb_;
- MachineBasicBlock::iterator currentInstr_;
LiveVariables* lv_;
- typedef std::map<unsigned, MachineBasicBlock*> MbbIndex2MbbMap;
- MbbIndex2MbbMap mbbi2mbbMap_;
-
typedef std::map<MachineInstr*, unsigned> Mi2IndexMap;
Mi2IndexMap mi2iMap_;
typedef std::vector<MachineInstr*> Index2MiMap;
Index2MiMap i2miMap_;
- typedef std::map<unsigned, Intervals::iterator> Reg2IntervalMap;
+ typedef std::map<unsigned, LiveInterval> Reg2IntervalMap;
Reg2IntervalMap r2iMap_;
typedef std::map<unsigned, unsigned> Reg2RegMap;
Reg2RegMap r2rMap_;
- Intervals intervals_;
-
public:
struct InstrSlots
{
return getBaseIndex(index) + InstrSlots::STORE;
}
- virtual void getAnalysisUsage(AnalysisUsage &AU) const;
- virtual void releaseMemory();
+ // FIXME: this should really be a const_iterator
+ typedef Reg2IntervalMap::iterator iterator;
+ iterator begin() { return r2iMap_.begin(); }
+ iterator end() { return r2iMap_.end(); }
+ unsigned getNumIntervals() const { return r2iMap_.size(); }
- /// runOnMachineFunction - pass entry point
- virtual bool runOnMachineFunction(MachineFunction&);
+ LiveInterval &getInterval(unsigned reg) {
+ Reg2IntervalMap::iterator I = r2iMap_.find(reg);
+ assert(I != r2iMap_.end() && "Interval does not exist for register");
+ return I->second;
+ }
- Interval& getInterval(unsigned reg) {
- assert(r2iMap_.count(reg)&& "Interval does not exist for register");
- return *r2iMap_.find(reg)->second;
+ const LiveInterval &getInterval(unsigned reg) const {
+ Reg2IntervalMap::const_iterator I = r2iMap_.find(reg);
+ assert(I != r2iMap_.end() && "Interval does not exist for register");
+ return I->second;
}
/// getInstructionIndex - returns the base index of instr
- unsigned getInstructionIndex(MachineInstr* instr) const;
+ unsigned getInstructionIndex(MachineInstr* instr) const {
+ Mi2IndexMap::const_iterator it = mi2iMap_.find(instr);
+ assert(it != mi2iMap_.end() && "Invalid instruction!");
+ return it->second;
+ }
/// getInstructionFromIndex - given an index in any slot of an
/// instruction return a pointer the instruction
- MachineInstr* getInstructionFromIndex(unsigned index) const;
+ MachineInstr* getInstructionFromIndex(unsigned index) const {
+ index /= InstrSlots::NUM; // convert index to vector index
+ assert(index < i2miMap_.size() &&
+ "index does not correspond to an instruction");
+ return i2miMap_[index];
+ }
+
+ std::vector<LiveInterval*> addIntervalsForSpills(const LiveInterval& i,
+ VirtRegMap& vrm,
+ int slot);
- Intervals& getIntervals() { return intervals_; }
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const;
+ virtual void releaseMemory();
- void updateSpilledInterval(Interval& i, VirtRegMap& vrm, int slot);
+ /// runOnMachineFunction - pass entry point
+ virtual bool runOnMachineFunction(MachineFunction&);
private:
/// computeIntervals - compute live intervals
/// joinIntervals - join compatible live intervals
void joinIntervals();
+ /// joinIntervalsInMachineBB - Join intervals based on move
+ /// instructions in the specified basic block.
+ void joinIntervalsInMachineBB(MachineBasicBlock *MBB);
+
/// handleRegisterDef - update intervals for a register def
/// (calls handlePhysicalRegisterDef and
/// handleVirtualRegisterDef)
/// register def
void handleVirtualRegisterDef(MachineBasicBlock* mbb,
MachineBasicBlock::iterator mi,
- Interval& interval);
+ LiveInterval& interval);
/// handlePhysicalRegisterDef - update intervals for a
/// physical register def
void handlePhysicalRegisterDef(MachineBasicBlock* mbb,
MachineBasicBlock::iterator mi,
- Interval& interval);
+ LiveInterval& interval);
- bool overlapsAliases(const Interval& lhs, const Interval& rhs) const;
+ /// Return true if the two specified registers belong to different
+ /// register classes. The registers may be either phys or virt regs.
+ bool differingRegisterClasses(unsigned RegA, unsigned RegB) const;
+ bool overlapsAliases(const LiveInterval *lhs,
+ const LiveInterval *rhs) const;
- Interval& getOrCreateInterval(unsigned reg);
+ static LiveInterval createInterval(unsigned Reg);
+
+ LiveInterval &getOrCreateInterval(unsigned reg) {
+ Reg2IntervalMap::iterator I = r2iMap_.find(reg);
+ if (I == r2iMap_.end())
+ I = r2iMap_.insert(I, std::make_pair(reg, createInterval(reg)));
+ return I->second;
+ }
/// rep - returns the representative of this register
- unsigned rep(unsigned reg);
+ unsigned rep(unsigned reg) {
+ Reg2RegMap::iterator it = r2rMap_.find(reg);
+ if (it != r2rMap_.end())
+ return it->second = rep(it->second);
+ return reg;
+ }
void printRegName(unsigned reg) const;
};
- inline bool operator==(const LiveIntervals::Interval& lhs,
- const LiveIntervals::Interval& rhs) {
- return lhs.reg == rhs.reg;
- }
-
- std::ostream& operator<<(std::ostream& os,
- const LiveIntervals::Interval& li);
-
} // End llvm namespace
#endif