#include "llvm/CodeGen/LiveInterval.h"
#include "RegisterCoalescer.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include <algorithm>
using namespace llvm;
LiveInterval::iterator LiveInterval::find(SlotIndex Pos) {
if (empty() || Pos >= endIndex())
return end();
iterator I = begin();
size_t Len = ranges.size();
do {
size_t Mid = Len >> 1;
if (Pos < I[Mid].end)
Len = Mid;
else
I += Mid + 1, Len -= Mid + 1;
} while (Len);
return I;
}
VNInfo *LiveInterval::createDeadDef(SlotIndex Def,
VNInfo::Allocator &VNInfoAllocator) {
assert(!Def.isDead() && "Cannot define a value at the dead slot");
iterator I = find(Def);
if (I == end()) {
VNInfo *VNI = getNextValue(Def, VNInfoAllocator);
ranges.push_back(LiveRange(Def, Def.getDeadSlot(), VNI));
return VNI;
}
if (SlotIndex::isSameInstr(Def, I->start)) {
assert(I->valno->def == I->start && "Inconsistent existing value def");
Def = std::min(Def, I->start);
if (Def != I->start)
I->start = I->valno->def = Def;
return I->valno;
}
assert(SlotIndex::isEarlierInstr(Def, I->start) && "Already live at def");
VNInfo *VNI = getNextValue(Def, VNInfoAllocator);
ranges.insert(I, LiveRange(Def, Def.getDeadSlot(), VNI));
return VNI;
}
bool LiveInterval::overlapsFrom(const LiveInterval& other,
const_iterator StartPos) const {
assert(!empty() && "empty interval");
const_iterator i = begin();
const_iterator ie = end();
const_iterator j = StartPos;
const_iterator je = other.end();
assert((StartPos->start <= i->start || StartPos == other.begin()) &&
StartPos != other.end() && "Bogus start position hint!");
if (i->start < j->start) {
i = std::upper_bound(i, ie, j->start);
if (i != ranges.begin()) --i;
} else if (j->start < i->start) {
++StartPos;
if (StartPos != other.end() && StartPos->start <= i->start) {
assert(StartPos < other.end() && i < end());
j = std::upper_bound(j, je, i->start);
if (j != other.ranges.begin()) --j;
}
} else {
return true;
}
if (j == je) return false;
while (i != ie) {
if (i->start > j->start) {
std::swap(i, j);
std::swap(ie, je);
}
if (i->end > j->start)
return true;
++i;
}
return false;
}
bool LiveInterval::overlaps(const LiveInterval &Other,
const CoalescerPair &CP,
const SlotIndexes &Indexes) const {
assert(!empty() && "empty interval");
if (Other.empty())
return false;
const_iterator I = find(Other.beginIndex());
const_iterator IE = end();
if (I == IE)
return false;
const_iterator J = Other.find(I->start);
const_iterator JE = Other.end();
if (J == JE)
return false;
for (;;) {
assert(J->end >= I->start);
if (J->start < I->end) {
SlotIndex Def = std::max(I->start, J->start);
if (Def.isBlock() ||
!CP.isCoalescable(Indexes.getInstructionFromIndex(Def)))
return true;
}
if (J->end > I->end) {
std::swap(I, J);
std::swap(IE, JE);
}
do
if (++J == JE)
return false;
while (J->end < I->start);
}
}
bool LiveInterval::overlaps(SlotIndex Start, SlotIndex End) const {
assert(Start < End && "Invalid range");
const_iterator I = std::lower_bound(begin(), end(), End);
return I != begin() && (--I)->end > Start;
}
void LiveInterval::markValNoForDeletion(VNInfo *ValNo) {
if (ValNo->id == getNumValNums()-1) {
do {
valnos.pop_back();
} while (!valnos.empty() && valnos.back()->isUnused());
} else {
ValNo->markUnused();
}
}
void LiveInterval::RenumberValues(LiveIntervals &lis) {
SmallPtrSet<VNInfo*, 8> Seen;
valnos.clear();
for (const_iterator I = begin(), E = end(); I != E; ++I) {
VNInfo *VNI = I->valno;
if (!Seen.insert(VNI))
continue;
assert(!VNI->isUnused() && "Unused valno used by live range");
VNI->id = (unsigned)valnos.size();
valnos.push_back(VNI);
}
}
void LiveInterval::extendIntervalEndTo(Ranges::iterator I, SlotIndex NewEnd) {
assert(I != ranges.end() && "Not a valid interval!");
VNInfo *ValNo = I->valno;
Ranges::iterator MergeTo = llvm::next(I);
for (; MergeTo != ranges.end() && NewEnd >= MergeTo->end; ++MergeTo) {
assert(MergeTo->valno == ValNo && "Cannot merge with differing values!");
}
I->end = std::max(NewEnd, prior(MergeTo)->end);
if (MergeTo != ranges.end() && MergeTo->start <= I->end &&
MergeTo->valno == ValNo) {
I->end = MergeTo->end;
++MergeTo;
}
ranges.erase(llvm::next(I), MergeTo);
}
LiveInterval::Ranges::iterator
LiveInterval::extendIntervalStartTo(Ranges::iterator I, SlotIndex NewStart) {
assert(I != ranges.end() && "Not a valid interval!");
VNInfo *ValNo = I->valno;
Ranges::iterator MergeTo = I;
do {
if (MergeTo == ranges.begin()) {
I->start = NewStart;
ranges.erase(MergeTo, I);
return I;
}
assert(MergeTo->valno == ValNo && "Cannot merge with differing values!");
--MergeTo;
} while (NewStart <= MergeTo->start);
if (MergeTo->end >= NewStart && MergeTo->valno == ValNo) {
MergeTo->end = I->end;
} else {
++MergeTo;
MergeTo->start = NewStart;
MergeTo->end = I->end;
}
ranges.erase(llvm::next(MergeTo), llvm::next(I));
return MergeTo;
}
LiveInterval::iterator
LiveInterval::addRangeFrom(LiveRange LR, iterator From) {
SlotIndex Start = LR.start, End = LR.end;
iterator it = std::upper_bound(From, ranges.end(), Start);
if (it != ranges.begin()) {
iterator B = prior(it);
if (LR.valno == B->valno) {
if (B->start <= Start && B->end >= Start) {
extendIntervalEndTo(B, End);
return B;
}
} else {
assert(B->end <= Start &&
"Cannot overlap two LiveRanges with differing ValID's"
" (did you def the same reg twice in a MachineInstr?)");
}
}
if (it != ranges.end()) {
if (LR.valno == it->valno) {
if (it->start <= End) {
it = extendIntervalStartTo(it, Start);
if (End > it->end)
extendIntervalEndTo(it, End);
return it;
}
} else {
assert(it->start >= End &&
"Cannot overlap two LiveRanges with differing ValID's");
}
}
return ranges.insert(it, LR);
}
VNInfo *LiveInterval::extendInBlock(SlotIndex StartIdx, SlotIndex Kill) {
if (empty())
return 0;
iterator I = std::upper_bound(begin(), end(), Kill.getPrevSlot());
if (I == begin())
return 0;
--I;
if (I->end <= StartIdx)
return 0;
if (I->end < Kill)
extendIntervalEndTo(I, Kill);
return I->valno;
}
void LiveInterval::removeRange(SlotIndex Start, SlotIndex End,
bool RemoveDeadValNo) {
Ranges::iterator I = find(Start);
assert(I != ranges.end() && "Range is not in interval!");
assert(I->containsRange(Start, End) && "Range is not entirely in interval!");
VNInfo *ValNo = I->valno;
if (I->start == Start) {
if (I->end == End) {
if (RemoveDeadValNo) {
bool isDead = true;
for (const_iterator II = begin(), EE = end(); II != EE; ++II)
if (II != I && II->valno == ValNo) {
isDead = false;
break;
}
if (isDead) {
markValNoForDeletion(ValNo);
}
}
ranges.erase(I); } else
I->start = End;
return;
}
if (I->end == End) {
I->end = Start;
return;
}
SlotIndex OldEnd = I->end;
I->end = Start;
ranges.insert(llvm::next(I), LiveRange(End, OldEnd, ValNo));
}
void LiveInterval::removeValNo(VNInfo *ValNo) {
if (empty()) return;
Ranges::iterator I = ranges.end();
Ranges::iterator E = ranges.begin();
do {
--I;
if (I->valno == ValNo)
ranges.erase(I);
} while (I != E);
markValNoForDeletion(ValNo);
}
void LiveInterval::join(LiveInterval &Other,
const int *LHSValNoAssignments,
const int *RHSValNoAssignments,
SmallVector<VNInfo*, 16> &NewVNInfo,
MachineRegisterInfo *MRI) {
verify();
bool MustMapCurValNos = false;
unsigned NumVals = getNumValNums();
unsigned NumNewVals = NewVNInfo.size();
for (unsigned i = 0; i != NumVals; ++i) {
unsigned LHSValID = LHSValNoAssignments[i];
if (i != LHSValID ||
(NewVNInfo[LHSValID] && NewVNInfo[LHSValID] != getValNumInfo(i))) {
MustMapCurValNos = true;
break;
}
}
if (MustMapCurValNos && !empty()) {
iterator OutIt = begin();
OutIt->valno = NewVNInfo[LHSValNoAssignments[OutIt->valno->id]];
for (iterator I = next(OutIt), E = end(); I != E; ++I) {
VNInfo* nextValNo = NewVNInfo[LHSValNoAssignments[I->valno->id]];
assert(nextValNo != 0 && "Huh?");
if (OutIt->valno == nextValNo && OutIt->end == I->start) {
OutIt->end = I->end;
} else {
++OutIt;
OutIt->valno = nextValNo;
if (OutIt != I) {
OutIt->start = I->start;
OutIt->end = I->end;
}
}
}
++OutIt;
ranges.erase(OutIt, end());
}
SmallVector<unsigned, 16> OtherAssignments;
for (iterator I = Other.begin(), E = Other.end(); I != E; ++I)
OtherAssignments.push_back(RHSValNoAssignments[I->valno->id]);
unsigned NumValNos = 0;
for (unsigned i = 0; i < NumNewVals; ++i) {
VNInfo *VNI = NewVNInfo[i];
if (VNI) {
if (NumValNos >= NumVals)
valnos.push_back(VNI);
else
valnos[NumValNos] = VNI;
VNI->id = NumValNos++; }
}
if (NumNewVals < NumVals)
valnos.resize(NumNewVals);
unsigned RangeNo = 0;
for (iterator I = Other.begin(), E = Other.end(); I != E; ++I, ++RangeNo) {
I->valno = NewVNInfo[OtherAssignments[RangeNo]];
assert(I->valno && "Adding a dead range?");
}
mergeIntervalRanges(Other);
verify();
}
void LiveInterval::mergeIntervalRanges(const LiveInterval &RHS,
VNInfo *LHSValNo,
const VNInfo *RHSValNo) {
if (RHS.empty())
return;
verify();
const_iterator RI = RHS.begin(), RE = RHS.end();
iterator LE = end(), LI = std::upper_bound(begin(), LE, *RI);
SmallVector<LiveRange, 4> NewRanges;
iterator ReplaceI = LI;
if (LI != begin()) {
ReplaceI = llvm::prior(LI);
NewRanges.push_back(*ReplaceI);
}
while (LI != LE && RI != RE) {
if (RHSValNo && RI->valno != RHSValNo) {
++RI;
continue;
}
LiveRange R = *LI;
if (*RI < R) {
R = *RI;
++RI;
if (LHSValNo)
R.valno = LHSValNo;
} else {
++LI;
}
if (NewRanges.empty()) {
NewRanges.push_back(R);
continue;
}
LiveRange &LastR = NewRanges.back();
if (R.valno == LastR.valno) {
if (R.start <= LastR.end) {
LastR.end = std::max(LastR.end, R.end);
continue;
}
} else {
assert(R.start >= LastR.end &&
"Cannot overlap two LiveRanges with differing ValID's");
}
NewRanges.push_back(R);
}
assert(RI == RE || LI == LE);
if (!NewRanges.empty())
for (; LI != LE && (LI->valno == NewRanges.back().valno &&
LI->start <= NewRanges.back().end);
++LI)
NewRanges.back().end = std::max(NewRanges.back().end, LI->end);
SmallVectorImpl<LiveRange>::iterator NRI = NewRanges.begin(),
NRE = NewRanges.end();
for (; ReplaceI != LI && NRI != NRE; ++ReplaceI, ++NRI)
*ReplaceI = *NRI;
if (NRI == NRE)
ranges.erase(ReplaceI, LI);
else
ranges.insert(LI, NRI, NRE);
for (; RI != RE; ++RI) {
LiveRange R = *RI;
if (LHSValNo)
R.valno = LHSValNo;
if (!ranges.empty() &&
ranges.back().valno == R.valno && R.start <= ranges.back().end)
ranges.back().end = std::max(ranges.back().end, R.end);
else
ranges.push_back(R);
}
verify();
}
void LiveInterval::MergeRangesInAsValue(const LiveInterval &RHS,
VNInfo *LHSValNo) {
mergeIntervalRanges(RHS, LHSValNo);
}
void LiveInterval::MergeValueInAsValue(const LiveInterval &RHS,
const VNInfo *RHSValNo,
VNInfo *LHSValNo) {
mergeIntervalRanges(RHS, LHSValNo, RHSValNo);
}
VNInfo* LiveInterval::MergeValueNumberInto(VNInfo *V1, VNInfo *V2) {
assert(V1 != V2 && "Identical value#'s are always equivalent!");
if (V1->id < V2->id) {
V1->copyFrom(*V2);
std::swap(V1, V2);
}
for (iterator I = begin(); I != end(); ) {
iterator LR = I++;
if (LR->valno != V1) continue;
if (LR != begin()) {
iterator Prev = LR-1;
if (Prev->valno == V2 && Prev->end == LR->start) {
Prev->end = LR->end;
ranges.erase(LR);
I = Prev+1;
LR = Prev;
}
}
LR->valno = V2;
if (I != end()) {
if (I->start == LR->end && I->valno == V2) {
LR->end = I->end;
ranges.erase(I);
I = LR+1;
}
}
}
markValNoForDeletion(V1);
return V2;
}
unsigned LiveInterval::getSize() const {
unsigned Sum = 0;
for (const_iterator I = begin(), E = end(); I != E; ++I)
Sum += I->start.distance(I->end);
return Sum;
}
raw_ostream& llvm::operator<<(raw_ostream& os, const LiveRange &LR) {
return os << '[' << LR.start << ',' << LR.end << ':' << LR.valno->id << ")";
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void LiveRange::dump() const {
dbgs() << *this << "\n";
}
#endif
void LiveInterval::print(raw_ostream &OS) const {
if (empty())
OS << "EMPTY";
else {
for (LiveInterval::Ranges::const_iterator I = ranges.begin(),
E = ranges.end(); I != E; ++I) {
OS << *I;
assert(I->valno == getValNumInfo(I->valno->id) && "Bad VNInfo");
}
}
if (getNumValNums()) {
OS << " ";
unsigned vnum = 0;
for (const_vni_iterator i = vni_begin(), e = vni_end(); i != e;
++i, ++vnum) {
const VNInfo *vni = *i;
if (vnum) OS << " ";
OS << vnum << "@";
if (vni->isUnused()) {
OS << "x";
} else {
OS << vni->def;
if (vni->isPHIDef())
OS << "-phi";
}
}
}
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void LiveInterval::dump() const {
dbgs() << *this << "\n";
}
#endif
#ifndef NDEBUG
void LiveInterval::verify() const {
for (const_iterator I = begin(), E = end(); I != E; ++I) {
assert(I->start.isValid());
assert(I->end.isValid());
assert(I->start < I->end);
assert(I->valno != 0);
assert(I->valno == valnos[I->valno->id]);
if (llvm::next(I) != E) {
assert(I->end <= llvm::next(I)->start);
if (I->end == llvm::next(I)->start)
assert(I->valno != llvm::next(I)->valno);
}
}
}
#endif
void LiveRange::print(raw_ostream &os) const {
os << *this;
}
unsigned ConnectedVNInfoEqClasses::Classify(const LiveInterval *LI) {
EqClass.clear();
EqClass.grow(LI->getNumValNums());
const VNInfo *used = 0, *unused = 0;
for (LiveInterval::const_vni_iterator I = LI->vni_begin(), E = LI->vni_end();
I != E; ++I) {
const VNInfo *VNI = *I;
if (VNI->isUnused()) {
if (unused)
EqClass.join(unused->id, VNI->id);
unused = VNI;
continue;
}
used = VNI;
if (VNI->isPHIDef()) {
const MachineBasicBlock *MBB = LIS.getMBBFromIndex(VNI->def);
assert(MBB && "Phi-def has no defining MBB");
for (MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(),
PE = MBB->pred_end(); PI != PE; ++PI)
if (const VNInfo *PVNI = LI->getVNInfoBefore(LIS.getMBBEndIdx(*PI)))
EqClass.join(VNI->id, PVNI->id);
} else {
if (const VNInfo *UVNI = LI->getVNInfoBefore(VNI->def))
EqClass.join(VNI->id, UVNI->id);
}
}
if (used && unused)
EqClass.join(used->id, unused->id);
EqClass.compress();
return EqClass.getNumClasses();
}
void ConnectedVNInfoEqClasses::Distribute(LiveInterval *LIV[],
MachineRegisterInfo &MRI) {
assert(LIV[0] && "LIV[0] must be set");
LiveInterval &LI = *LIV[0];
for (MachineRegisterInfo::reg_iterator RI = MRI.reg_begin(LI.reg),
RE = MRI.reg_end(); RI != RE;) {
MachineOperand &MO = RI.getOperand();
MachineInstr *MI = MO.getParent();
++RI;
SlotIndex Idx;
if (MI->isDebugValue())
Idx = LIS.getSlotIndexes()->getIndexBefore(MI);
else
Idx = LIS.getInstructionIndex(MI);
LiveRangeQuery LRQ(LI, Idx);
const VNInfo *VNI = MO.readsReg() ? LRQ.valueIn() : LRQ.valueDefined();
if (!VNI)
continue;
MO.setReg(LIV[getEqClass(VNI)]->reg);
}
LiveInterval::iterator J = LI.begin(), E = LI.end();
while (J != E && EqClass[J->valno->id] == 0)
++J;
for (LiveInterval::iterator I = J; I != E; ++I) {
if (unsigned eq = EqClass[I->valno->id]) {
assert((LIV[eq]->empty() || LIV[eq]->expiredAt(I->start)) &&
"New intervals should be empty");
LIV[eq]->ranges.push_back(*I);
} else
*J++ = *I;
}
LI.ranges.erase(J, E);
unsigned j = 0, e = LI.getNumValNums();
while (j != e && EqClass[j] == 0)
++j;
for (unsigned i = j; i != e; ++i) {
VNInfo *VNI = LI.getValNumInfo(i);
if (unsigned eq = EqClass[i]) {
VNI->id = LIV[eq]->getNumValNums();
LIV[eq]->valnos.push_back(VNI);
} else {
VNI->id = j;
LI.valnos[j++] = VNI;
}
}
LI.valnos.resize(j);
}