#ifndef LLVM_CODEGEN_LIVEINTERVAL_H
#define LLVM_CODEGEN_LIVEINTERVAL_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Allocator.h"
#include <iosfwd>
#include <cassert>
#include <climits>
namespace llvm {
class MachineInstr;
class TargetRegisterInfo;
struct LiveInterval;
struct VNInfo {
unsigned id;
unsigned def;
MachineInstr *copy;
bool hasPHIKill : 1;
bool redefByEC : 1;
SmallVector<unsigned, 4> kills;
VNInfo()
: id(~1U), def(~1U), copy(0), hasPHIKill(false), redefByEC(false) {}
VNInfo(unsigned i, unsigned d, MachineInstr *c)
: id(i), def(d), copy(c), hasPHIKill(false), redefByEC(false) {}
};
struct LiveRange {
unsigned start; unsigned end; VNInfo *valno;
LiveRange(unsigned S, unsigned E, VNInfo *V) : start(S), end(E), valno(V) {
assert(S < E && "Cannot create empty or backwards range");
}
bool contains(unsigned I) const {
return start <= I && I < end;
}
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;
}
void dump() const;
void print(std::ostream &os) const;
void print(std::ostream *os) const { if (os) print(*os); }
private:
LiveRange(); };
std::ostream& operator<<(std::ostream& os, const LiveRange &LR);
inline bool operator<(unsigned V, const LiveRange &LR) {
return V < LR.start;
}
inline bool operator<(const LiveRange &LR, unsigned V) {
return LR.start < V;
}
struct LiveInterval {
typedef SmallVector<LiveRange,4> Ranges;
typedef SmallVector<VNInfo*,4> VNInfoList;
unsigned reg; float weight; unsigned short preference; Ranges ranges; VNInfoList valnos;
public:
LiveInterval(unsigned Reg, float Weight, bool IsSS = false)
: reg(Reg), weight(Weight), preference(0) {
if (IsSS)
reg = reg | (1U << (sizeof(unsigned)*CHAR_BIT-1));
}
typedef Ranges::iterator iterator;
iterator begin() { return ranges.begin(); }
iterator end() { return ranges.end(); }
typedef Ranges::const_iterator const_iterator;
const_iterator begin() const { return ranges.begin(); }
const_iterator end() const { return ranges.end(); }
typedef VNInfoList::iterator vni_iterator;
vni_iterator vni_begin() { return valnos.begin(); }
vni_iterator vni_end() { return valnos.end(); }
typedef VNInfoList::const_iterator const_vni_iterator;
const_vni_iterator vni_begin() const { return valnos.begin(); }
const_vni_iterator vni_end() const { return valnos.end(); }
iterator advanceTo(iterator I, unsigned Pos) {
if (Pos >= endNumber())
return end();
while (I->end <= Pos) ++I;
return I;
}
void clear() {
while (!valnos.empty()) {
VNInfo *VNI = valnos.back();
valnos.pop_back();
VNI->~VNInfo();
}
ranges.clear();
}
bool isStackSlot() const {
return reg & (1U << (sizeof(unsigned)*CHAR_BIT-1));
}
int getStackSlotIndex() const {
assert(isStackSlot() && "Interval is not a stack slot interval!");
return reg & ~(1U << (sizeof(unsigned)*CHAR_BIT-1));
}
bool hasAtLeastOneValue() const { return !valnos.empty(); }
bool containsOneValue() const { return valnos.size() == 1; }
unsigned getNumValNums() const { return (unsigned)valnos.size(); }
inline VNInfo *getValNumInfo(unsigned ValNo) {
return valnos[ValNo];
}
inline const VNInfo *getValNumInfo(unsigned ValNo) const {
return valnos[ValNo];
}
void copyValNumInfo(VNInfo *DstValNo, const VNInfo *SrcValNo) {
DstValNo->def = SrcValNo->def;
DstValNo->copy = SrcValNo->copy;
DstValNo->hasPHIKill = SrcValNo->hasPHIKill;
DstValNo->redefByEC = SrcValNo->redefByEC;
DstValNo->kills = SrcValNo->kills;
}
VNInfo *getNextValue(unsigned MIIdx, MachineInstr *CopyMI,
BumpPtrAllocator &VNInfoAllocator) {
#ifdef __GNUC__
unsigned Alignment = (unsigned)__alignof__(VNInfo);
#else
unsigned Alignment = 8;
#endif
VNInfo *VNI =
static_cast<VNInfo*>(VNInfoAllocator.Allocate((unsigned)sizeof(VNInfo),
Alignment));
new (VNI) VNInfo((unsigned)valnos.size(), MIIdx, CopyMI);
valnos.push_back(VNI);
return VNI;
}
static void addKill(VNInfo *VNI, unsigned KillIdx) {
SmallVector<unsigned, 4> &kills = VNI->kills;
if (kills.empty()) {
kills.push_back(KillIdx);
} else {
SmallVector<unsigned, 4>::iterator
I = std::lower_bound(kills.begin(), kills.end(), KillIdx);
kills.insert(I, KillIdx);
}
}
void addKills(VNInfo *VNI, const SmallVector<unsigned, 4> &kills) {
for (unsigned i = 0, e = static_cast<unsigned>(kills.size());
i != e; ++i) {
unsigned KillIdx = kills[i];
if (!liveBeforeAndAt(KillIdx)) {
SmallVector<unsigned, 4>::iterator
I = std::lower_bound(VNI->kills.begin(), VNI->kills.end(), KillIdx);
VNI->kills.insert(I, KillIdx);
}
}
}
static bool removeKill(VNInfo *VNI, unsigned KillIdx) {
SmallVector<unsigned, 4> &kills = VNI->kills;
SmallVector<unsigned, 4>::iterator
I = std::lower_bound(kills.begin(), kills.end(), KillIdx);
if (I != kills.end() && *I == KillIdx) {
kills.erase(I);
return true;
}
return false;
}
static void removeKills(VNInfo *VNI, unsigned Start, unsigned End) {
SmallVector<unsigned, 4> &kills = VNI->kills;
SmallVector<unsigned, 4>::iterator
I = std::lower_bound(kills.begin(), kills.end(), Start);
SmallVector<unsigned, 4>::iterator
E = std::upper_bound(kills.begin(), kills.end(), End);
kills.erase(I, E);
}
static bool isKill(const VNInfo *VNI, unsigned KillIdx) {
const SmallVector<unsigned, 4> &kills = VNI->kills;
SmallVector<unsigned, 4>::const_iterator
I = std::lower_bound(kills.begin(), kills.end(), KillIdx);
return I != kills.end() && *I == KillIdx;
}
bool isOnlyLROfValNo( const LiveRange *LR) {
for (const_iterator I = begin(), E = end(); I != E; ++I) {
const LiveRange *Tmp = I;
if (Tmp != LR && Tmp->valno == LR->valno)
return false;
}
return true;
}
VNInfo* MergeValueNumberInto(VNInfo *V1, VNInfo *V2);
void MergeInClobberRanges(const LiveInterval &Clobbers,
BumpPtrAllocator &VNInfoAllocator);
void MergeInClobberRange(unsigned Start, unsigned End,
BumpPtrAllocator &VNInfoAllocator);
void MergeRangesInAsValue(const LiveInterval &RHS, VNInfo *LHSValNo);
void MergeValueInAsValue(const LiveInterval &RHS,
const VNInfo *RHSValNo, VNInfo *LHSValNo);
void Copy(const LiveInterval &RHS, BumpPtrAllocator &VNInfoAllocator);
bool empty() const { return ranges.empty(); }
unsigned beginNumber() const {
if (empty())
return 0;
return ranges.front().start;
}
unsigned endNumber() const {
if (empty())
return 0;
return ranges.back().end;
}
bool expiredAt(unsigned index) const {
return index >= endNumber();
}
bool liveAt(unsigned index) const;
bool liveBeforeAndAt(unsigned index) const;
const LiveRange *getLiveRangeContaining(unsigned Idx) const {
const_iterator I = FindLiveRangeContaining(Idx);
return I == end() ? 0 : &*I;
}
const_iterator FindLiveRangeContaining(unsigned Idx) const;
iterator FindLiveRangeContaining(unsigned Idx);
VNInfo *findDefinedVNInfo(unsigned DefIdxOrReg) const;
bool overlaps(const LiveInterval& other) const {
return overlapsFrom(other, other.begin());
}
bool overlaps(unsigned Start, unsigned End) const;
bool overlapsFrom(const LiveInterval& other, const_iterator I) const;
void addRange(LiveRange LR) {
addRangeFrom(LR, ranges.begin());
}
void join(LiveInterval &Other, const int *ValNoAssignments,
const int *RHSValNoAssignments,
SmallVector<VNInfo*, 16> &NewVNInfo);
bool isInOneLiveRange(unsigned Start, unsigned End);
void removeRange(unsigned Start, unsigned End, bool RemoveDeadValNo = false);
void removeRange(LiveRange LR, bool RemoveDeadValNo = false) {
removeRange(LR.start, LR.end, RemoveDeadValNo);
}
void removeValNo(VNInfo *ValNo);
unsigned getSize() const;
bool operator<(const LiveInterval& other) const {
return beginNumber() < other.beginNumber();
}
void print(std::ostream &OS, const TargetRegisterInfo *TRI = 0) const;
void print(std::ostream *OS, const TargetRegisterInfo *TRI = 0) const {
if (OS) print(*OS, TRI);
}
void dump() const;
private:
Ranges::iterator addRangeFrom(LiveRange LR, Ranges::iterator From);
void extendIntervalEndTo(Ranges::iterator I, unsigned NewEnd);
Ranges::iterator extendIntervalStartTo(Ranges::iterator I, unsigned NewStr);
LiveInterval& operator=(const LiveInterval& rhs); };
inline std::ostream &operator<<(std::ostream &OS, const LiveInterval &LI) {
LI.print(OS);
return OS;
}
}
#endif