diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index b541a3a649f..8ca58b82c8b 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -160,7 +160,9 @@ namespace llvm { /// defs for new uses, and it doesn't remove dead defs. /// Dead PHIDef values are marked as unused. /// New dead machine instructions are added to the dead vector. - void shrinkToUses(LiveInterval *li, + /// Return true if the interval may have been separated into multiple + /// connected components. + bool shrinkToUses(LiveInterval *li, SmallVectorImpl *dead = 0); // Interval removal diff --git a/lib/CodeGen/InlineSpiller.cpp b/lib/CodeGen/InlineSpiller.cpp index ff0a1051e7a..ecb00881837 100644 --- a/lib/CodeGen/InlineSpiller.cpp +++ b/lib/CodeGen/InlineSpiller.cpp @@ -460,7 +460,7 @@ bool InlineSpiller::reMaterializeFor(MachineBasicBlock::iterator MI) { } // Alocate a new register for the remat. - LiveInterval &NewLI = Edit->create(MRI, LIS, VRM); + LiveInterval &NewLI = Edit->create(LIS, VRM); NewLI.markNotSpillable(); // Rematting for a copy: Set allocation hint to be the destination register. @@ -685,7 +685,7 @@ void InlineSpiller::spillAroundUses(unsigned Reg) { // Allocate interval around instruction. // FIXME: Infer regclass from instruction alone. - LiveInterval &NewLI = Edit->create(MRI, LIS, VRM); + LiveInterval &NewLI = Edit->create(LIS, VRM); NewLI.markNotSpillable(); if (Reads) diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index f2bf9172012..c47c8397488 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -746,7 +746,7 @@ LiveInterval* LiveIntervals::dupInterval(LiveInterval *li) { /// shrinkToUses - After removing some uses of a register, shrink its live /// range to just the remaining uses. This method does not compute reaching /// defs for new uses, and it doesn't remove dead defs. -void LiveIntervals::shrinkToUses(LiveInterval *li, +bool LiveIntervals::shrinkToUses(LiveInterval *li, SmallVectorImpl *dead) { DEBUG(dbgs() << "Shrink: " << *li << '\n'); assert(TargetRegisterInfo::isVirtualRegister(li->reg) @@ -835,6 +835,7 @@ void LiveIntervals::shrinkToUses(LiveInterval *li, } // Handle dead values. + bool CanSeparate = false; for (LiveInterval::vni_iterator I = li->vni_begin(), E = li->vni_end(); I != E; ++I) { VNInfo *VNI = *I; @@ -848,6 +849,8 @@ void LiveIntervals::shrinkToUses(LiveInterval *li, // This is a dead PHI. Remove it. VNI->setIsUnused(true); NewLI.removeRange(*LII); + DEBUG(dbgs() << "Dead PHI at " << VNI->def << " may separate interval\n"); + CanSeparate = true; } else { // This is a dead def. Make sure the instruction knows. MachineInstr *MI = getInstructionFromIndex(VNI->def); @@ -863,6 +866,7 @@ void LiveIntervals::shrinkToUses(LiveInterval *li, // Move the trimmed ranges back. li->ranges.swap(NewLI.ranges); DEBUG(dbgs() << "Shrunk: " << *li << '\n'); + return CanSeparate; } diff --git a/lib/CodeGen/LiveRangeEdit.cpp b/lib/CodeGen/LiveRangeEdit.cpp index 489d88c1dfb..f5c67b9c748 100644 --- a/lib/CodeGen/LiveRangeEdit.cpp +++ b/lib/CodeGen/LiveRangeEdit.cpp @@ -22,16 +22,16 @@ using namespace llvm; -LiveInterval &LiveRangeEdit::create(MachineRegisterInfo &mri, - LiveIntervals &lis, - VirtRegMap &vrm) { - const TargetRegisterClass *RC = mri.getRegClass(getReg()); - unsigned VReg = mri.createVirtualRegister(RC); - vrm.grow(); - vrm.setIsSplitFromReg(VReg, vrm.getOriginal(getReg())); - LiveInterval &li = lis.getOrCreateInterval(VReg); - newRegs_.push_back(&li); - return li; +LiveInterval &LiveRangeEdit::createFrom(unsigned OldReg, + LiveIntervals &LIS, + VirtRegMap &VRM) { + MachineRegisterInfo &MRI = VRM.getRegInfo(); + unsigned VReg = MRI.createVirtualRegister(MRI.getRegClass(OldReg)); + VRM.grow(); + VRM.setIsSplitFromReg(VReg, VRM.getOriginal(OldReg)); + LiveInterval &LI = LIS.getOrCreateInterval(VReg); + newRegs_.push_back(&LI); + return LI; } void LiveRangeEdit::scanRemattable(LiveIntervals &lis, @@ -137,7 +137,7 @@ void LiveRangeEdit::eraseVirtReg(unsigned Reg, LiveIntervals &LIS) { } void LiveRangeEdit::eliminateDeadDefs(SmallVectorImpl &Dead, - LiveIntervals &LIS, + LiveIntervals &LIS, VirtRegMap &VRM, const TargetInstrInfo &TII) { SetVector, @@ -205,7 +205,20 @@ void LiveRangeEdit::eliminateDeadDefs(SmallVectorImpl &Dead, ToShrink.pop_back(); if (delegate_) delegate_->LRE_WillShrinkVirtReg(LI->reg); - LIS.shrinkToUses(LI, &Dead); + if (!LIS.shrinkToUses(LI, &Dead)) + continue; + + // LI may have been separated, create new intervals. + LI->RenumberValues(LIS); + ConnectedVNInfoEqClasses ConEQ(LIS); + unsigned NumComp = ConEQ.Classify(LI); + if (NumComp <= 1) + continue; + DEBUG(dbgs() << NumComp << " components: " << *LI << '\n'); + SmallVector Dups(1, LI); + for (unsigned i = 1; i != NumComp; ++i) + Dups.push_back(&createFrom(LI->reg, LIS, VRM)); + ConEQ.Distribute(&Dups[0], VRM.getRegInfo()); } } diff --git a/lib/CodeGen/LiveRangeEdit.h b/lib/CodeGen/LiveRangeEdit.h index 2bd34611c24..0846961f5b9 100644 --- a/lib/CodeGen/LiveRangeEdit.h +++ b/lib/CodeGen/LiveRangeEdit.h @@ -65,6 +65,9 @@ private: /// live range trimmed or entirely removed. SmallPtrSet rematted_; + /// createFrom - Create a new virtual register based on OldReg. + LiveInterval &createFrom(unsigned, LiveIntervals&, VirtRegMap &); + /// scanRemattable - Identify the parent_ values that may rematerialize. void scanRemattable(LiveIntervals &lis, const TargetInstrInfo &tii, @@ -110,9 +113,11 @@ public: return uselessRegs_; } - /// create - Create a new register with the same class and stack slot as + /// create - Create a new register with the same class and original slot as /// parent. - LiveInterval &create(MachineRegisterInfo&, LiveIntervals&, VirtRegMap&); + LiveInterval &create(LiveIntervals &LIS, VirtRegMap &VRM) { + return createFrom(getReg(), LIS, VRM); + } /// anyRematerializable - Return true if any parent values may be /// rematerializable. @@ -166,7 +171,7 @@ public: /// (allDefsAreDead returns true). This may cause live intervals to be trimmed /// and further dead efs to be eliminated. void eliminateDeadDefs(SmallVectorImpl &Dead, - LiveIntervals&, + LiveIntervals&, VirtRegMap&, const TargetInstrInfo&); }; diff --git a/lib/CodeGen/SplitKit.cpp b/lib/CodeGen/SplitKit.cpp index 6f7b972c43a..ff00bd8f38c 100644 --- a/lib/CodeGen/SplitKit.cpp +++ b/lib/CodeGen/SplitKit.cpp @@ -538,11 +538,11 @@ void SplitEditor::openIntv() { // Create the complement as index 0. if (Edit->empty()) - Edit->create(MRI, LIS, VRM); + Edit->create(LIS, VRM); // Create the open interval. OpenIdx = Edit->size(); - Edit->create(MRI, LIS, VRM); + Edit->create(LIS, VRM); } SlotIndex SplitEditor::enterIntvBefore(SlotIndex Idx) { @@ -802,7 +802,7 @@ void SplitEditor::deleteRematVictims() { if (Dead.empty()) return; - Edit->eliminateDeadDefs(Dead, LIS, TII); + Edit->eliminateDeadDefs(Dead, LIS, VRM, TII); } void SplitEditor::finish() { @@ -866,7 +866,7 @@ void SplitEditor::finish() { SmallVector dups; dups.push_back(li); for (unsigned i = 1; i != NumComp; ++i) - dups.push_back(&Edit->create(MRI, LIS, VRM)); + dups.push_back(&Edit->create(LIS, VRM)); ConEQ.Distribute(&dups[0], MRI); }