Dead code elimination may separate the live interval into multiple connected components.

I have convinced myself that it can only happen when a phi value dies. When it
happens, allocate new virtual registers for the components.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@127827 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jakob Stoklund Olesen 2011-03-17 20:37:07 +00:00
parent c74513d1b6
commit 6a3dbd3b25
6 changed files with 47 additions and 23 deletions

View File

@ -160,7 +160,9 @@ namespace llvm {
/// defs for new uses, and it doesn't remove dead defs. /// defs for new uses, and it doesn't remove dead defs.
/// Dead PHIDef values are marked as unused. /// Dead PHIDef values are marked as unused.
/// New dead machine instructions are added to the dead vector. /// 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<MachineInstr*> *dead = 0); SmallVectorImpl<MachineInstr*> *dead = 0);
// Interval removal // Interval removal

View File

@ -460,7 +460,7 @@ bool InlineSpiller::reMaterializeFor(MachineBasicBlock::iterator MI) {
} }
// Alocate a new register for the remat. // Alocate a new register for the remat.
LiveInterval &NewLI = Edit->create(MRI, LIS, VRM); LiveInterval &NewLI = Edit->create(LIS, VRM);
NewLI.markNotSpillable(); NewLI.markNotSpillable();
// Rematting for a copy: Set allocation hint to be the destination register. // 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. // Allocate interval around instruction.
// FIXME: Infer regclass from instruction alone. // FIXME: Infer regclass from instruction alone.
LiveInterval &NewLI = Edit->create(MRI, LIS, VRM); LiveInterval &NewLI = Edit->create(LIS, VRM);
NewLI.markNotSpillable(); NewLI.markNotSpillable();
if (Reads) if (Reads)

View File

@ -746,7 +746,7 @@ LiveInterval* LiveIntervals::dupInterval(LiveInterval *li) {
/// shrinkToUses - After removing some uses of a register, shrink its live /// shrinkToUses - After removing some uses of a register, shrink its live
/// range to just the remaining uses. This method does not compute reaching /// range to just the remaining uses. This method does not compute reaching
/// defs for new uses, and it doesn't remove dead defs. /// defs for new uses, and it doesn't remove dead defs.
void LiveIntervals::shrinkToUses(LiveInterval *li, bool LiveIntervals::shrinkToUses(LiveInterval *li,
SmallVectorImpl<MachineInstr*> *dead) { SmallVectorImpl<MachineInstr*> *dead) {
DEBUG(dbgs() << "Shrink: " << *li << '\n'); DEBUG(dbgs() << "Shrink: " << *li << '\n');
assert(TargetRegisterInfo::isVirtualRegister(li->reg) assert(TargetRegisterInfo::isVirtualRegister(li->reg)
@ -835,6 +835,7 @@ void LiveIntervals::shrinkToUses(LiveInterval *li,
} }
// Handle dead values. // Handle dead values.
bool CanSeparate = false;
for (LiveInterval::vni_iterator I = li->vni_begin(), E = li->vni_end(); for (LiveInterval::vni_iterator I = li->vni_begin(), E = li->vni_end();
I != E; ++I) { I != E; ++I) {
VNInfo *VNI = *I; VNInfo *VNI = *I;
@ -848,6 +849,8 @@ void LiveIntervals::shrinkToUses(LiveInterval *li,
// This is a dead PHI. Remove it. // This is a dead PHI. Remove it.
VNI->setIsUnused(true); VNI->setIsUnused(true);
NewLI.removeRange(*LII); NewLI.removeRange(*LII);
DEBUG(dbgs() << "Dead PHI at " << VNI->def << " may separate interval\n");
CanSeparate = true;
} else { } else {
// This is a dead def. Make sure the instruction knows. // This is a dead def. Make sure the instruction knows.
MachineInstr *MI = getInstructionFromIndex(VNI->def); MachineInstr *MI = getInstructionFromIndex(VNI->def);
@ -863,6 +866,7 @@ void LiveIntervals::shrinkToUses(LiveInterval *li,
// Move the trimmed ranges back. // Move the trimmed ranges back.
li->ranges.swap(NewLI.ranges); li->ranges.swap(NewLI.ranges);
DEBUG(dbgs() << "Shrunk: " << *li << '\n'); DEBUG(dbgs() << "Shrunk: " << *li << '\n');
return CanSeparate;
} }

View File

@ -22,16 +22,16 @@
using namespace llvm; using namespace llvm;
LiveInterval &LiveRangeEdit::create(MachineRegisterInfo &mri, LiveInterval &LiveRangeEdit::createFrom(unsigned OldReg,
LiveIntervals &lis, LiveIntervals &LIS,
VirtRegMap &vrm) { VirtRegMap &VRM) {
const TargetRegisterClass *RC = mri.getRegClass(getReg()); MachineRegisterInfo &MRI = VRM.getRegInfo();
unsigned VReg = mri.createVirtualRegister(RC); unsigned VReg = MRI.createVirtualRegister(MRI.getRegClass(OldReg));
vrm.grow(); VRM.grow();
vrm.setIsSplitFromReg(VReg, vrm.getOriginal(getReg())); VRM.setIsSplitFromReg(VReg, VRM.getOriginal(OldReg));
LiveInterval &li = lis.getOrCreateInterval(VReg); LiveInterval &LI = LIS.getOrCreateInterval(VReg);
newRegs_.push_back(&li); newRegs_.push_back(&LI);
return li; return LI;
} }
void LiveRangeEdit::scanRemattable(LiveIntervals &lis, void LiveRangeEdit::scanRemattable(LiveIntervals &lis,
@ -137,7 +137,7 @@ void LiveRangeEdit::eraseVirtReg(unsigned Reg, LiveIntervals &LIS) {
} }
void LiveRangeEdit::eliminateDeadDefs(SmallVectorImpl<MachineInstr*> &Dead, void LiveRangeEdit::eliminateDeadDefs(SmallVectorImpl<MachineInstr*> &Dead,
LiveIntervals &LIS, LiveIntervals &LIS, VirtRegMap &VRM,
const TargetInstrInfo &TII) { const TargetInstrInfo &TII) {
SetVector<LiveInterval*, SetVector<LiveInterval*,
SmallVector<LiveInterval*, 8>, SmallVector<LiveInterval*, 8>,
@ -205,7 +205,20 @@ void LiveRangeEdit::eliminateDeadDefs(SmallVectorImpl<MachineInstr*> &Dead,
ToShrink.pop_back(); ToShrink.pop_back();
if (delegate_) if (delegate_)
delegate_->LRE_WillShrinkVirtReg(LI->reg); 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<LiveInterval*, 8> Dups(1, LI);
for (unsigned i = 1; i != NumComp; ++i)
Dups.push_back(&createFrom(LI->reg, LIS, VRM));
ConEQ.Distribute(&Dups[0], VRM.getRegInfo());
} }
} }

View File

@ -65,6 +65,9 @@ private:
/// live range trimmed or entirely removed. /// live range trimmed or entirely removed.
SmallPtrSet<const VNInfo*,4> rematted_; SmallPtrSet<const VNInfo*,4> rematted_;
/// createFrom - Create a new virtual register based on OldReg.
LiveInterval &createFrom(unsigned, LiveIntervals&, VirtRegMap &);
/// scanRemattable - Identify the parent_ values that may rematerialize. /// scanRemattable - Identify the parent_ values that may rematerialize.
void scanRemattable(LiveIntervals &lis, void scanRemattable(LiveIntervals &lis,
const TargetInstrInfo &tii, const TargetInstrInfo &tii,
@ -110,9 +113,11 @@ public:
return uselessRegs_; 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. /// 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 /// anyRematerializable - Return true if any parent values may be
/// rematerializable. /// rematerializable.
@ -166,7 +171,7 @@ public:
/// (allDefsAreDead returns true). This may cause live intervals to be trimmed /// (allDefsAreDead returns true). This may cause live intervals to be trimmed
/// and further dead efs to be eliminated. /// and further dead efs to be eliminated.
void eliminateDeadDefs(SmallVectorImpl<MachineInstr*> &Dead, void eliminateDeadDefs(SmallVectorImpl<MachineInstr*> &Dead,
LiveIntervals&, LiveIntervals&, VirtRegMap&,
const TargetInstrInfo&); const TargetInstrInfo&);
}; };

View File

@ -538,11 +538,11 @@ void SplitEditor::openIntv() {
// Create the complement as index 0. // Create the complement as index 0.
if (Edit->empty()) if (Edit->empty())
Edit->create(MRI, LIS, VRM); Edit->create(LIS, VRM);
// Create the open interval. // Create the open interval.
OpenIdx = Edit->size(); OpenIdx = Edit->size();
Edit->create(MRI, LIS, VRM); Edit->create(LIS, VRM);
} }
SlotIndex SplitEditor::enterIntvBefore(SlotIndex Idx) { SlotIndex SplitEditor::enterIntvBefore(SlotIndex Idx) {
@ -802,7 +802,7 @@ void SplitEditor::deleteRematVictims() {
if (Dead.empty()) if (Dead.empty())
return; return;
Edit->eliminateDeadDefs(Dead, LIS, TII); Edit->eliminateDeadDefs(Dead, LIS, VRM, TII);
} }
void SplitEditor::finish() { void SplitEditor::finish() {
@ -866,7 +866,7 @@ void SplitEditor::finish() {
SmallVector<LiveInterval*, 8> dups; SmallVector<LiveInterval*, 8> dups;
dups.push_back(li); dups.push_back(li);
for (unsigned i = 1; i != NumComp; ++i) 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); ConEQ.Distribute(&dups[0], MRI);
} }