Get live interval reconstruction several steps closer to working.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@61514 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Owen Anderson 2008-12-31 02:00:25 +00:00
parent d23b799d7d
commit 7d211e299f

View File

@ -173,12 +173,14 @@ namespace {
void RenumberValno(VNInfo* VN); void RenumberValno(VNInfo* VN);
void ReconstructLiveInterval(LiveInterval* LI); void ReconstructLiveInterval(LiveInterval* LI);
VNInfo* PerformPHIConstruction(MachineBasicBlock::iterator use, VNInfo* PerformPHIConstruction(MachineBasicBlock::iterator use,
MachineBasicBlock* MBB,
LiveInterval* LI, LiveInterval* LI,
DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> >& Defs, DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> >& Defs,
DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> >& Uses, DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> >& Uses,
DenseMap<MachineInstr*, VNInfo*>& NewVNs, DenseMap<MachineInstr*, VNInfo*>& NewVNs,
DenseMap<MachineBasicBlock*, VNInfo*>& Visited, DenseMap<MachineBasicBlock*, VNInfo*>& LiveOut,
bool toplevel = false); DenseMap<MachineBasicBlock*, VNInfo*>& Phis,
bool toplevel, bool intrablock);
}; };
} // end anonymous namespace } // end anonymous namespace
@ -589,21 +591,30 @@ PreAllocSplitting::ShrinkWrapToLastUse(MachineBasicBlock *MBB, VNInfo *ValNo,
/// construction algorithm to compute the ranges and valnos for an interval. /// construction algorithm to compute the ranges and valnos for an interval.
VNInfo* PreAllocSplitting::PerformPHIConstruction( VNInfo* PreAllocSplitting::PerformPHIConstruction(
MachineBasicBlock::iterator use, MachineBasicBlock::iterator use,
MachineBasicBlock* MBB,
LiveInterval* LI, LiveInterval* LI,
DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> >& Defs, DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> >& Defs,
DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> >& Uses, DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> >& Uses,
DenseMap<MachineInstr*, VNInfo*>& NewVNs, DenseMap<MachineInstr*, VNInfo*>& NewVNs,
DenseMap<MachineBasicBlock*, VNInfo*>& Visited, DenseMap<MachineBasicBlock*, VNInfo*>& LiveOut,
bool toplevel) { DenseMap<MachineBasicBlock*, VNInfo*>& Phis,
bool toplevel, bool intrablock) {
// Return memoized result if it's available. // Return memoized result if it's available.
if (Visited.count(use->getParent())) if (intrablock && NewVNs.count(use))
return Visited[use->getParent()]; return NewVNs[use];
else if (!intrablock && LiveOut.count(MBB))
return LiveOut[MBB];
// Insert a sentinel into the map (which also acts as the DFS stack) so that
// we won't get stuck in infinite recursion when processing a loop.
if (!intrablock)
LiveOut[MBB] = 0;
typedef DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> > RegMap; typedef DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> > RegMap;
// Check if our block contains any uses or defs. // Check if our block contains any uses or defs.
bool ContainsDefs = Defs.count(use->getParent()); bool ContainsDefs = Defs.count(MBB);
bool ContainsUses = Uses.count(use->getParent()); bool ContainsUses = Uses.count(MBB);
VNInfo* ret = 0; VNInfo* ret = 0;
@ -611,32 +622,42 @@ VNInfo* PreAllocSplitting::PerformPHIConstruction(
if (!ContainsDefs && !ContainsUses) { if (!ContainsDefs && !ContainsUses) {
Fallback: Fallback:
// NOTE: Because this is the fallback case from other cases, we do NOT // NOTE: Because this is the fallback case from other cases, we do NOT
// assume that we are not at toplevel here. // assume that we are not intrablock here.
if (Phis.count(MBB)) return Phis[MBB];
// If there are no uses or defs between our starting point and the beginning unsigned StartIndex = LIs->getMBBStartIdx(MBB);
// of the block, then recursive perform phi construction on our predecessors
MachineBasicBlock* MBB = use->getParent();
DenseMap<MachineBasicBlock*, VNInfo*> IncomingVNs;
for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(),
PE = MBB->pred_end(); PI != PE; ++PI) {
VNInfo* Incoming = PerformPHIConstruction((*PI)->end(), LI, Defs, Uses,
NewVNs, Visited, false);
IncomingVNs[*PI] = Incoming;
}
// If only one VNInfo came back from our predecessors, just use that one... if (MBB->pred_size() == 1) {
if (IncomingVNs.size() == 1) { Phis[MBB] = ret = PerformPHIConstruction((*MBB->pred_begin())->end(),
ret = IncomingVNs.begin()->second; *(MBB->pred_begin()), LI, Defs,
unsigned StartIndex = LIs->getMBBStartIdx(use->getParent()); Uses, NewVNs, LiveOut, Phis,
false, false);
unsigned EndIndex = 0; unsigned EndIndex = 0;
if (toplevel) { if (intrablock) {
EndIndex = LIs->getInstructionIndex(use); EndIndex = LIs->getInstructionIndex(use);
EndIndex = LiveIntervals::getUseIndex(EndIndex); EndIndex = LiveIntervals::getUseIndex(EndIndex);
} else } else
EndIndex = LIs->getMBBEndIdx(use->getParent()); EndIndex = LIs->getMBBEndIdx(MBB);
LI->addRange(LiveRange(StartIndex, EndIndex, ret)); LI->addRange(LiveRange(StartIndex, EndIndex+1, ret));
} else { } else {
Phis[MBB] = ret = LI->getNextValue(~0U, /*FIXME*/ 0,
LIs->getVNInfoAllocator());
if (!intrablock) LiveOut[MBB] = ret;
// If there are no uses or defs between our starting point and the
// beginning of the block, then recursive perform phi construction
// on our predecessors.
DenseMap<MachineBasicBlock*, VNInfo*> IncomingVNs;
for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(),
PE = MBB->pred_end(); PI != PE; ++PI) {
VNInfo* Incoming = PerformPHIConstruction((*PI)->end(), *PI, LI, Defs,
Uses, NewVNs, LiveOut, Phis,
false, false);
if (Incoming != 0)
IncomingVNs[*PI] = Incoming;
}
// Otherwise, merge the incoming VNInfos with a phi join. Create a new // Otherwise, merge the incoming VNInfos with a phi join. Create a new
// VNInfo to represent the joined value. // VNInfo to represent the joined value.
for (DenseMap<MachineBasicBlock*, VNInfo*>::iterator I = for (DenseMap<MachineBasicBlock*, VNInfo*>::iterator I =
@ -646,29 +667,26 @@ VNInfo* PreAllocSplitting::PerformPHIConstruction(
LI->addKill(I->second, KillIndex); LI->addKill(I->second, KillIndex);
} }
unsigned StartIndex = LIs->getMBBStartIdx(use->getParent());
unsigned EndIndex = 0; unsigned EndIndex = 0;
if (toplevel) { if (intrablock) {
EndIndex = LIs->getInstructionIndex(use); EndIndex = LIs->getInstructionIndex(use);
EndIndex = LiveIntervals::getUseIndex(EndIndex); EndIndex = LiveIntervals::getUseIndex(EndIndex);
} else } else
EndIndex = LIs->getMBBEndIdx(use->getParent()); EndIndex = LIs->getMBBEndIdx(MBB);
ret = LI->getNextValue(StartIndex, /*FIXME*/ 0, LI->addRange(LiveRange(StartIndex, EndIndex+1, ret));
LIs->getVNInfoAllocator());
LI->addRange(LiveRange(StartIndex, EndIndex, ret));
} }
} else if (ContainsDefs && !ContainsUses) { } else if (ContainsDefs && !ContainsUses) {
SmallPtrSet<MachineInstr*, 2>& BlockDefs = Defs[use->getParent()]; SmallPtrSet<MachineInstr*, 2>& BlockDefs = Defs[MBB];
// Search for the def in this block. If we don't find it before the // Search for the def in this block. If we don't find it before the
// instruction we care about, go to the fallback case. Note that that // instruction we care about, go to the fallback case. Note that that
// should never happen: this cannot be a toplevel block, so use should // should never happen: this cannot be intrablock, so use should
// always be an end() iterator. // always be an end() iterator.
assert(use == use->getParent()->end() && "No use marked in toplevel block"); assert(use == MBB->end() && "No use marked in intrablock");
MachineBasicBlock::iterator walker = use; MachineBasicBlock::iterator walker = use;
--walker; --walker;
while (walker != use->getParent()->begin()) while (walker != MBB->begin())
if (BlockDefs.count(walker)) { if (BlockDefs.count(walker)) {
break; break;
} else } else
@ -677,23 +695,23 @@ VNInfo* PreAllocSplitting::PerformPHIConstruction(
// Once we've found it, extend its VNInfo to our instruction. // Once we've found it, extend its VNInfo to our instruction.
unsigned DefIndex = LIs->getInstructionIndex(walker); unsigned DefIndex = LIs->getInstructionIndex(walker);
DefIndex = LiveIntervals::getDefIndex(DefIndex); DefIndex = LiveIntervals::getDefIndex(DefIndex);
unsigned EndIndex = LIs->getMBBEndIdx(use->getParent()); unsigned EndIndex = LIs->getMBBEndIdx(MBB);
ret = NewVNs[walker]; ret = NewVNs[walker];
LI->addRange(LiveRange(DefIndex, EndIndex, ret)); LI->addRange(LiveRange(DefIndex, EndIndex+1, ret));
} else if (!ContainsDefs && ContainsUses) { } else if (!ContainsDefs && ContainsUses) {
SmallPtrSet<MachineInstr*, 2>& BlockUses = Uses[use->getParent()]; SmallPtrSet<MachineInstr*, 2>& BlockUses = Uses[MBB];
// Search for the use in this block that precedes the instruction we care // Search for the use in this block that precedes the instruction we care
// about, going to the fallback case if we don't find it. // about, going to the fallback case if we don't find it.
if (use == use->getParent()->begin()) if (use == MBB->begin())
goto Fallback; goto Fallback;
MachineBasicBlock::iterator walker = use; MachineBasicBlock::iterator walker = use;
--walker; --walker;
bool found = false; bool found = false;
while (walker != use->getParent()->begin()) while (walker != MBB->begin())
if (BlockUses.count(walker)) { if (BlockUses.count(walker)) {
found = true; found = true;
break; break;
@ -711,39 +729,39 @@ VNInfo* PreAllocSplitting::PerformPHIConstruction(
unsigned UseIndex = LIs->getInstructionIndex(walker); unsigned UseIndex = LIs->getInstructionIndex(walker);
UseIndex = LiveIntervals::getUseIndex(UseIndex); UseIndex = LiveIntervals::getUseIndex(UseIndex);
unsigned EndIndex = 0; unsigned EndIndex = 0;
if (toplevel) { if (intrablock) {
EndIndex = LIs->getInstructionIndex(walker); EndIndex = LIs->getInstructionIndex(use);
EndIndex = LiveIntervals::getUseIndex(EndIndex); EndIndex = LiveIntervals::getUseIndex(EndIndex);
} else } else
EndIndex = LIs->getMBBEndIdx(use->getParent()); EndIndex = LIs->getMBBEndIdx(MBB);
// Now, recursively phi construct the VNInfo for the use we found, // Now, recursively phi construct the VNInfo for the use we found,
// and then extend it to include the instruction we care about // and then extend it to include the instruction we care about
ret = PerformPHIConstruction(walker, LI, Defs, Uses, ret = PerformPHIConstruction(walker, MBB, LI, Defs, Uses,
NewVNs, Visited, false); NewVNs, LiveOut, Phis, false, true);
// FIXME: Need to set kills properly for inter-block stuff. // FIXME: Need to set kills properly for inter-block stuff.
if (LI->isKill(ret, UseIndex)) LI->removeKill(ret, UseIndex); if (LI->isKill(ret, UseIndex)) LI->removeKill(ret, UseIndex);
if (toplevel) if (intrablock)
LI->addKill(ret, EndIndex); LI->addKill(ret, EndIndex);
LI->addRange(LiveRange(UseIndex, EndIndex, ret)); LI->addRange(LiveRange(UseIndex, EndIndex+1, ret));
} else if (ContainsDefs && ContainsUses){ } else if (ContainsDefs && ContainsUses){
SmallPtrSet<MachineInstr*, 2>& BlockDefs = Defs[use->getParent()]; SmallPtrSet<MachineInstr*, 2>& BlockDefs = Defs[MBB];
SmallPtrSet<MachineInstr*, 2>& BlockUses = Uses[use->getParent()]; SmallPtrSet<MachineInstr*, 2>& BlockUses = Uses[MBB];
// This case is basically a merging of the two preceding case, with the // This case is basically a merging of the two preceding case, with the
// special note that checking for defs must take precedence over checking // special note that checking for defs must take precedence over checking
// for uses, because of two-address instructions. // for uses, because of two-address instructions.
if (use == use->getParent()->begin()) if (use == MBB->begin())
goto Fallback; goto Fallback;
MachineBasicBlock::iterator walker = use; MachineBasicBlock::iterator walker = use;
--walker; --walker;
bool foundDef = false; bool foundDef = false;
bool foundUse = false; bool foundUse = false;
while (walker != use->getParent()->begin()) while (walker != MBB->begin())
if (BlockDefs.count(walker)) { if (BlockDefs.count(walker)) {
foundDef = true; foundDef = true;
break; break;
@ -767,29 +785,30 @@ VNInfo* PreAllocSplitting::PerformPHIConstruction(
StartIndex = foundDef ? LiveIntervals::getDefIndex(StartIndex) : StartIndex = foundDef ? LiveIntervals::getDefIndex(StartIndex) :
LiveIntervals::getUseIndex(StartIndex); LiveIntervals::getUseIndex(StartIndex);
unsigned EndIndex = 0; unsigned EndIndex = 0;
if (toplevel) { if (intrablock) {
EndIndex = LIs->getInstructionIndex(walker); EndIndex = LIs->getInstructionIndex(use);
EndIndex = LiveIntervals::getUseIndex(EndIndex); EndIndex = LiveIntervals::getUseIndex(EndIndex);
} else } else
EndIndex = LIs->getMBBEndIdx(use->getParent()); EndIndex = LIs->getMBBEndIdx(MBB);
if (foundDef) if (foundDef)
ret = NewVNs[walker]; ret = NewVNs[walker];
else else
ret = PerformPHIConstruction(walker, LI, Defs, Uses, ret = PerformPHIConstruction(walker, MBB, LI, Defs, Uses,
NewVNs, Visited, false); NewVNs, LiveOut, Phis, false, true);
if (foundUse && LI->isKill(ret, StartIndex)) if (foundUse && LI->isKill(ret, StartIndex))
LI->removeKill(ret, StartIndex); LI->removeKill(ret, StartIndex);
if (toplevel) { if (intrablock) {
LI->addKill(ret, EndIndex); LI->addKill(ret, EndIndex);
} }
LI->addRange(LiveRange(StartIndex, EndIndex, ret)); LI->addRange(LiveRange(StartIndex, EndIndex+1, ret));
} }
// Memoize results so we don't have to recompute them. // Memoize results so we don't have to recompute them.
if (!toplevel) Visited[use->getParent()] = ret; if (!intrablock) LiveOut[MBB] = ret;
else NewVNs[use] = ret;
return ret; return ret;
} }
@ -829,10 +848,12 @@ void PreAllocSplitting::ReconstructLiveInterval(LiveInterval* LI) {
// Now, actually process every use and use a phi construction algorithm // Now, actually process every use and use a phi construction algorithm
// to walk from it to its reaching definitions, building VNInfos along // to walk from it to its reaching definitions, building VNInfos along
// the way. // the way.
DenseMap<MachineBasicBlock*, VNInfo*> LiveOut;
DenseMap<MachineBasicBlock*, VNInfo*> Phis;
for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(LI->reg), for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(LI->reg),
UE = MRI->use_end(); UI != UE; ++UI) { UE = MRI->use_end(); UI != UE; ++UI) {
DenseMap<MachineBasicBlock*, VNInfo*> Visited; PerformPHIConstruction(&*UI, UI->getParent(), LI, Defs,
PerformPHIConstruction(&*UI, LI, Defs, Uses, NewVNs, Visited, true); Uses, NewVNs, LiveOut, Phis, true, true);
} }
// Add ranges for dead defs // Add ranges for dead defs
@ -840,12 +861,11 @@ void PreAllocSplitting::ReconstructLiveInterval(LiveInterval* LI) {
DE = MRI->def_end(); DI != DE; ++DI) { DE = MRI->def_end(); DI != DE; ++DI) {
unsigned DefIdx = LIs->getInstructionIndex(&*DI); unsigned DefIdx = LIs->getInstructionIndex(&*DI);
DefIdx = LiveIntervals::getDefIndex(DefIdx); DefIdx = LiveIntervals::getDefIndex(DefIdx);
unsigned UseIdx = LiveIntervals::getUseIndex(DefIdx);
if (LI->liveAt(DefIdx)) continue; if (LI->liveAt(DefIdx)) continue;
VNInfo* DeadVN = NewVNs[&*DI]; VNInfo* DeadVN = NewVNs[&*DI];
LI->addRange(LiveRange(DefIdx, UseIdx, DeadVN)); LI->addRange(LiveRange(DefIdx, DefIdx+1, DeadVN));
LI->addKill(DeadVN, DefIdx); LI->addKill(DeadVN, DefIdx);
} }
} }