X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FLiveInterval.cpp;h=cfade24b8d876228243cc584a9ee57269b8d05f8;hb=94fca8300d61cc038030c31014116df38b74e986;hp=fd5fe787b6bf07c6ce43970b99e3ae2de0803397;hpb=89bfef003ec71792d078d489566655006b89bc43;p=oota-llvm.git diff --git a/lib/CodeGen/LiveInterval.cpp b/lib/CodeGen/LiveInterval.cpp index fd5fe787b6b..cfade24b8d8 100644 --- a/lib/CodeGen/LiveInterval.cpp +++ b/lib/CodeGen/LiveInterval.cpp @@ -30,20 +30,22 @@ #include using namespace llvm; -// CompEnd - Compare LiveRange end to Pos. -namespace { -struct CompEnd { - bool operator()(SlotIndex Pos, const LiveRange &LR) const { - return Pos < LR.end; - } - bool operator()(const LiveRange &LR, SlotIndex Pos) const { - return LR.end < Pos; - } -}; -} - LiveInterval::iterator LiveInterval::find(SlotIndex Pos) { - return std::upper_bound(begin(), end(), Pos, CompEnd()); + // This algorithm is basically std::upper_bound. + // Unfortunately, std::upper_bound cannot be used with mixed types until we + // adopt C++0x. Many libraries can do it, but not all. + 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; } /// killedInRange - Return true if the interval has kills in [Start,End). @@ -292,6 +294,22 @@ LiveInterval::addRangeFrom(LiveRange LR, iterator From) { return ranges.insert(it, LR); } +/// extendInBlock - If this interval is live before UseIdx in the basic +/// block that starts at StartIdx, extend it to be live at UseIdx and return +/// the value. If there is no live range before UseIdx, return NULL. +VNInfo *LiveInterval::extendInBlock(SlotIndex StartIdx, SlotIndex UseIdx) { + if (empty()) + return 0; + iterator I = std::upper_bound(begin(), end(), UseIdx); + if (I == begin()) + return 0; + --I; + if (I->end <= StartIdx) + return 0; + if (I->end <= UseIdx) + extendIntervalEndTo(I, UseIdx.getNextSlot()); + return I->valno; +} /// removeRange - Remove the specified range from this interval. Note that /// the range must be in a single LiveRange in its entirety. @@ -477,60 +495,19 @@ void LiveInterval::MergeRangesInAsValue(const LiveInterval &RHS, void LiveInterval::MergeValueInAsValue( const LiveInterval &RHS, const VNInfo *RHSValNo, VNInfo *LHSValNo) { - SmallVector ReplacedValNos; - iterator IP = begin(); + // TODO: Make this more efficient. + iterator InsertPos = begin(); for (const_iterator I = RHS.begin(), E = RHS.end(); I != E; ++I) { - assert(I->valno == RHS.getValNumInfo(I->valno->id) && "Bad VNInfo"); if (I->valno != RHSValNo) continue; - SlotIndex Start = I->start, End = I->end; - IP = std::upper_bound(IP, end(), Start); - // If the start of this range overlaps with an existing liverange, trim it. - if (IP != begin() && IP[-1].end > Start) { - if (IP[-1].valno != LHSValNo) { - ReplacedValNos.push_back(IP[-1].valno); - IP[-1].valno = LHSValNo; // Update val#. - } - Start = IP[-1].end; - // Trimmed away the whole range? - if (Start >= End) continue; - } - // If the end of this range overlaps with an existing liverange, trim it. - if (IP != end() && End > IP->start) { - if (IP->valno != LHSValNo) { - ReplacedValNos.push_back(IP->valno); - IP->valno = LHSValNo; // Update val#. - } - End = IP->start; - // If this trimmed away the whole range, ignore it. - if (Start == End) continue; - } - // Map the valno in the other live range to the current live range. - IP = addRangeFrom(LiveRange(Start, End, LHSValNo), IP); - } - - - SmallSet Seen; - for (unsigned i = 0, e = ReplacedValNos.size(); i != e; ++i) { - VNInfo *V1 = ReplacedValNos[i]; - if (Seen.insert(V1)) { - bool isDead = true; - for (const_iterator I = begin(), E = end(); I != E; ++I) - if (I->valno == V1) { - isDead = false; - break; - } - if (isDead) { - // Now that V1 is dead, remove it. - markValNoForDeletion(V1); - } - } + LiveRange Tmp = *I; + Tmp.valno = LHSValNo; + InsertPos = addRangeFrom(Tmp, InsertPos); } } - /// MergeValueNumberInto - This method is called when two value nubmers /// are found to be equivalent. This eliminates V1, replacing all /// LiveRanges with the V1 value number with the V2 value number. This can @@ -584,6 +561,9 @@ VNInfo* LiveInterval::MergeValueNumberInto(VNInfo *V1, VNInfo *V2) { } } + // Merge the relevant flags. + V2->mergeFlags(V1); + // Now that V1 is dead, remove it. markValNoForDeletion(V1); @@ -648,14 +628,9 @@ void LiveRange::dump() const { } void LiveInterval::print(raw_ostream &OS, const TargetRegisterInfo *TRI) const { - if (isStackSlot()) - OS << "SS#" << getStackSlotIndex(); - else if (TRI && TargetRegisterInfo::isPhysicalRegister(reg)) - OS << TRI->getName(reg); - else - OS << "%reg" << reg; - - OS << ',' << weight; + OS << PrintReg(reg, TRI); + if (weight != 0) + OS << ',' << weight; if (empty()) OS << " EMPTY"; @@ -680,10 +655,9 @@ void LiveInterval::print(raw_ostream &OS, const TargetRegisterInfo *TRI) const { if (vni->isUnused()) { OS << "x"; } else { - if (!vni->isDefAccurate() && !vni->isPHIDef()) - OS << "?"; - else - OS << vni->def; + OS << vni->def; + if (vni->isPHIDef()) + OS << "-phidef"; if (vni->hasPHIKill()) OS << "-phikill"; if (vni->hasRedefByEC()) @@ -701,3 +675,101 @@ void LiveInterval::dump() const { void LiveRange::print(raw_ostream &os) const { os << *this; } + +unsigned ConnectedVNInfoEqClasses::Classify(const LiveInterval *LI) { + // Create initial equivalence classes. + EqClass.clear(); + EqClass.grow(LI->getNumValNums()); + + const VNInfo *used = 0, *unused = 0; + + // Determine connections. + for (LiveInterval::const_vni_iterator I = LI->vni_begin(), E = LI->vni_end(); + I != E; ++I) { + const VNInfo *VNI = *I; + // Group all unused values into one class. + 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"); + // Connect to values live out of predecessors. + for (MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), + PE = MBB->pred_end(); PI != PE; ++PI) + if (const VNInfo *PVNI = + LI->getVNInfoAt(LIS.getMBBEndIdx(*PI).getPrevSlot())) + EqClass.join(VNI->id, PVNI->id); + } else { + // Normal value defined by an instruction. Check for two-addr redef. + // FIXME: This could be coincidental. Should we really check for a tied + // operand constraint? + // Note that VNI->def may be a use slot for an early clobber def. + if (const VNInfo *UVNI = LI->getVNInfoAt(VNI->def.getPrevSlot())) + EqClass.join(VNI->id, UVNI->id); + } + } + + // Lump all the unused values in with the last used value. + 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]; + + // Rewrite instructions. + 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; + if (MO.isUse() && MO.isUndef()) + continue; + // DBG_VALUE instructions should have been eliminated earlier. + SlotIndex Idx = LIS.getInstructionIndex(MI); + Idx = MO.isUse() ? Idx.getUseIndex() : Idx.getDefIndex(); + const VNInfo *VNI = LI.getVNInfoAt(Idx); + assert(VNI && "Interval not live at use."); + MO.setReg(LIV[getEqClass(VNI)]->reg); + } + + // Move runs to new intervals. + 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); + + // Transfer VNInfos to their new owners and renumber them. + 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); +}