forked from OSchip/llvm-project
parent
a39c83d118
commit
e7fa3c37c6
|
@ -139,11 +139,26 @@ namespace {
|
|||
|
||||
void UpdateSpillSlotInterval(VNInfo*, unsigned, unsigned);
|
||||
|
||||
VNInfo* UpdateRegisterInterval(VNInfo*, unsigned, unsigned);
|
||||
|
||||
bool ShrinkWrapToLastUse(MachineBasicBlock*, VNInfo*,
|
||||
SmallVector<MachineOperand*, 4>&,
|
||||
SmallPtrSet<MachineInstr*, 4>&);
|
||||
|
||||
void ShrinkWrapLiveInterval(VNInfo*, MachineBasicBlock*, MachineBasicBlock*,
|
||||
MachineBasicBlock*, SmallPtrSet<MachineBasicBlock*, 8>&,
|
||||
DenseMap<MachineBasicBlock*, SmallVector<MachineOperand*, 4> >&,
|
||||
DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 4> >&,
|
||||
SmallVector<MachineBasicBlock*, 4>&);
|
||||
|
||||
bool SplitRegLiveInterval(LiveInterval*);
|
||||
|
||||
bool SplitRegLiveIntervals(const TargetRegisterClass **,
|
||||
SmallPtrSet<LiveInterval*, 8>&);
|
||||
|
||||
void RepairLiveInterval(LiveInterval* CurrLI, VNInfo* ValNo,
|
||||
MachineInstr* DefMI, unsigned RestoreIdx);
|
||||
|
||||
bool createsNewJoin(LiveRange* LR, MachineBasicBlock* DefMBB,
|
||||
MachineBasicBlock* BarrierMBB);
|
||||
bool Rematerialize(unsigned vreg, VNInfo* ValNo,
|
||||
|
@ -408,6 +423,176 @@ PreAllocSplitting::UpdateSpillSlotInterval(VNInfo *ValNo, unsigned SpillIndex,
|
|||
}
|
||||
}
|
||||
|
||||
/// UpdateRegisterInterval - Given the specified val# of the current live
|
||||
/// interval is being split, and the spill and restore indices, update the live
|
||||
/// interval accordingly.
|
||||
VNInfo*
|
||||
PreAllocSplitting::UpdateRegisterInterval(VNInfo *ValNo, unsigned SpillIndex,
|
||||
unsigned RestoreIndex) {
|
||||
assert(LIs->getMBBFromIndex(RestoreIndex) == BarrierMBB &&
|
||||
"Expect restore in the barrier mbb");
|
||||
|
||||
SmallVector<std::pair<unsigned,unsigned>, 4> Before;
|
||||
SmallVector<std::pair<unsigned,unsigned>, 4> After;
|
||||
SmallVector<unsigned, 4> BeforeKills;
|
||||
SmallVector<unsigned, 4> AfterKills;
|
||||
SmallPtrSet<const LiveRange*, 4> Processed;
|
||||
|
||||
// First, let's figure out which parts of the live interval is now defined
|
||||
// by the restore, which are defined by the original definition.
|
||||
const LiveRange *LR = CurrLI->getLiveRangeContaining(RestoreIndex);
|
||||
After.push_back(std::make_pair(RestoreIndex, LR->end));
|
||||
if (CurrLI->isKill(ValNo, LR->end))
|
||||
AfterKills.push_back(LR->end);
|
||||
|
||||
assert(LR->contains(SpillIndex));
|
||||
if (SpillIndex > LR->start) {
|
||||
Before.push_back(std::make_pair(LR->start, SpillIndex));
|
||||
BeforeKills.push_back(SpillIndex);
|
||||
}
|
||||
Processed.insert(LR);
|
||||
|
||||
// Start from the restore mbb, figure out what part of the live interval
|
||||
// are defined by the restore.
|
||||
SmallVector<MachineBasicBlock*, 4> WorkList;
|
||||
MachineBasicBlock *MBB = BarrierMBB;
|
||||
for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(),
|
||||
SE = MBB->succ_end(); SI != SE; ++SI)
|
||||
WorkList.push_back(*SI);
|
||||
|
||||
SmallPtrSet<MachineBasicBlock*, 4> ProcessedBlocks;
|
||||
ProcessedBlocks.insert(MBB);
|
||||
|
||||
while (!WorkList.empty()) {
|
||||
MBB = WorkList.back();
|
||||
WorkList.pop_back();
|
||||
unsigned Idx = LIs->getMBBStartIdx(MBB);
|
||||
LR = CurrLI->getLiveRangeContaining(Idx);
|
||||
if (LR && LR->valno == ValNo && !Processed.count(LR)) {
|
||||
After.push_back(std::make_pair(LR->start, LR->end));
|
||||
if (CurrLI->isKill(ValNo, LR->end))
|
||||
AfterKills.push_back(LR->end);
|
||||
Idx = LIs->getMBBEndIdx(MBB);
|
||||
if (LR->end > Idx) {
|
||||
// Live range extend beyond at least one mbb. Let's see what other
|
||||
// mbbs it reaches.
|
||||
LIs->findReachableMBBs(LR->start, LR->end, WorkList);
|
||||
}
|
||||
Processed.insert(LR);
|
||||
}
|
||||
|
||||
ProcessedBlocks.insert(MBB);
|
||||
if (LR)
|
||||
for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(),
|
||||
SE = MBB->succ_end(); SI != SE; ++SI)
|
||||
if (!ProcessedBlocks.count(*SI))
|
||||
WorkList.push_back(*SI);
|
||||
}
|
||||
|
||||
for (LiveInterval::iterator I = CurrLI->begin(), E = CurrLI->end();
|
||||
I != E; ++I) {
|
||||
LiveRange *LR = I;
|
||||
if (LR->valno == ValNo && !Processed.count(LR)) {
|
||||
Before.push_back(std::make_pair(LR->start, LR->end));
|
||||
if (CurrLI->isKill(ValNo, LR->end))
|
||||
BeforeKills.push_back(LR->end);
|
||||
}
|
||||
}
|
||||
|
||||
// Now create new val#s to represent the live ranges defined by the old def
|
||||
// those defined by the restore.
|
||||
unsigned AfterDef = ValNo->def;
|
||||
MachineInstr *AfterCopy = ValNo->copy;
|
||||
bool HasPHIKill = ValNo->hasPHIKill;
|
||||
CurrLI->removeValNo(ValNo);
|
||||
VNInfo *BValNo = (Before.empty())
|
||||
? NULL
|
||||
: CurrLI->getNextValue(AfterDef, AfterCopy, LIs->getVNInfoAllocator());
|
||||
if (BValNo)
|
||||
CurrLI->addKills(BValNo, BeforeKills);
|
||||
|
||||
VNInfo *AValNo = (After.empty())
|
||||
? NULL
|
||||
: CurrLI->getNextValue(RestoreIndex, 0, LIs->getVNInfoAllocator());
|
||||
if (AValNo) {
|
||||
AValNo->hasPHIKill = HasPHIKill;
|
||||
CurrLI->addKills(AValNo, AfterKills);
|
||||
}
|
||||
|
||||
for (unsigned i = 0, e = Before.size(); i != e; ++i) {
|
||||
unsigned Start = Before[i].first;
|
||||
unsigned End = Before[i].second;
|
||||
CurrLI->addRange(LiveRange(Start, End, BValNo));
|
||||
}
|
||||
for (unsigned i = 0, e = After.size(); i != e; ++i) {
|
||||
unsigned Start = After[i].first;
|
||||
unsigned End = After[i].second;
|
||||
CurrLI->addRange(LiveRange(Start, End, AValNo));
|
||||
}
|
||||
|
||||
return AValNo;
|
||||
}
|
||||
|
||||
/// ShrinkWrapToLastUse - There are uses of the current live interval in the
|
||||
/// given block, shrink wrap the live interval to the last use (i.e. remove
|
||||
/// from last use to the end of the mbb). In case mbb is the where the barrier
|
||||
/// is, remove from the last use to the barrier.
|
||||
bool
|
||||
PreAllocSplitting::ShrinkWrapToLastUse(MachineBasicBlock *MBB, VNInfo *ValNo,
|
||||
SmallVector<MachineOperand*, 4> &Uses,
|
||||
SmallPtrSet<MachineInstr*, 4> &UseMIs) {
|
||||
MachineOperand *LastMO = 0;
|
||||
MachineInstr *LastMI = 0;
|
||||
if (MBB != BarrierMBB && Uses.size() == 1) {
|
||||
// Single use, no need to traverse the block. We can't assume this for the
|
||||
// barrier bb though since the use is probably below the barrier.
|
||||
LastMO = Uses[0];
|
||||
LastMI = LastMO->getParent();
|
||||
} else {
|
||||
MachineBasicBlock::iterator MEE = MBB->begin();
|
||||
MachineBasicBlock::iterator MII;
|
||||
if (MBB == BarrierMBB)
|
||||
MII = Barrier;
|
||||
else
|
||||
MII = MBB->end();
|
||||
while (MII != MEE) {
|
||||
--MII;
|
||||
MachineInstr *UseMI = &*MII;
|
||||
if (!UseMIs.count(UseMI))
|
||||
continue;
|
||||
for (unsigned i = 0, e = UseMI->getNumOperands(); i != e; ++i) {
|
||||
MachineOperand &MO = UseMI->getOperand(i);
|
||||
if (MO.isReg() && MO.getReg() == CurrLI->reg) {
|
||||
LastMO = &MO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
LastMI = UseMI;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Cut off live range from last use (or beginning of the mbb if there
|
||||
// are no uses in it) to the end of the mbb.
|
||||
unsigned RangeStart, RangeEnd = LIs->getMBBEndIdx(MBB)+1;
|
||||
if (LastMI) {
|
||||
RangeStart = LIs->getUseIndex(LIs->getInstructionIndex(LastMI))+1;
|
||||
assert(!LastMO->isKill() && "Last use already terminates the interval?");
|
||||
LastMO->setIsKill();
|
||||
} else {
|
||||
assert(MBB == BarrierMBB);
|
||||
RangeStart = LIs->getMBBStartIdx(MBB);
|
||||
}
|
||||
if (MBB == BarrierMBB)
|
||||
RangeEnd = LIs->getUseIndex(BarrierIdx)+1;
|
||||
CurrLI->removeRange(RangeStart, RangeEnd);
|
||||
if (LastMI)
|
||||
CurrLI->addKill(ValNo, RangeStart);
|
||||
|
||||
// Return true if the last use becomes a new kill.
|
||||
return LastMI;
|
||||
}
|
||||
|
||||
/// PerformPHIConstruction - From properly set up use and def lists, use a PHI
|
||||
/// construction algorithm to compute the ranges and valnos for an interval.
|
||||
VNInfo* PreAllocSplitting::PerformPHIConstruction(
|
||||
|
@ -705,6 +890,142 @@ void PreAllocSplitting::ReconstructLiveInterval(LiveInterval* LI) {
|
|||
}
|
||||
}
|
||||
|
||||
/// ShrinkWrapLiveInterval - Recursively traverse the predecessor
|
||||
/// chain to find the new 'kills' and shrink wrap the live interval to the
|
||||
/// new kill indices.
|
||||
void
|
||||
PreAllocSplitting::ShrinkWrapLiveInterval(VNInfo *ValNo, MachineBasicBlock *MBB,
|
||||
MachineBasicBlock *SuccMBB, MachineBasicBlock *DefMBB,
|
||||
SmallPtrSet<MachineBasicBlock*, 8> &Visited,
|
||||
DenseMap<MachineBasicBlock*, SmallVector<MachineOperand*, 4> > &Uses,
|
||||
DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 4> > &UseMIs,
|
||||
SmallVector<MachineBasicBlock*, 4> &UseMBBs) {
|
||||
if (Visited.count(MBB))
|
||||
return;
|
||||
|
||||
// If live interval is live in another successor path, then we can't process
|
||||
// this block. But we may able to do so after all the successors have been
|
||||
// processed.
|
||||
if (MBB != BarrierMBB) {
|
||||
for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(),
|
||||
SE = MBB->succ_end(); SI != SE; ++SI) {
|
||||
MachineBasicBlock *SMBB = *SI;
|
||||
if (SMBB == SuccMBB)
|
||||
continue;
|
||||
if (CurrLI->liveAt(LIs->getMBBStartIdx(SMBB)))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Visited.insert(MBB);
|
||||
|
||||
DenseMap<MachineBasicBlock*, SmallVector<MachineOperand*, 4> >::iterator
|
||||
UMII = Uses.find(MBB);
|
||||
if (UMII != Uses.end()) {
|
||||
// At least one use in this mbb, lets look for the kill.
|
||||
DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 4> >::iterator
|
||||
UMII2 = UseMIs.find(MBB);
|
||||
if (ShrinkWrapToLastUse(MBB, ValNo, UMII->second, UMII2->second))
|
||||
// Found a kill, shrink wrapping of this path ends here.
|
||||
return;
|
||||
} else if (MBB == DefMBB) {
|
||||
// There are no uses after the def.
|
||||
MachineInstr *DefMI = LIs->getInstructionFromIndex(ValNo->def);
|
||||
if (UseMBBs.empty()) {
|
||||
// The only use must be below barrier in the barrier block. It's safe to
|
||||
// remove the def.
|
||||
LIs->RemoveMachineInstrFromMaps(DefMI);
|
||||
DefMI->eraseFromParent();
|
||||
CurrLI->removeRange(ValNo->def, LIs->getMBBEndIdx(MBB)+1);
|
||||
}
|
||||
} else if (MBB == BarrierMBB) {
|
||||
// Remove entire live range from start of mbb to barrier.
|
||||
CurrLI->removeRange(LIs->getMBBStartIdx(MBB),
|
||||
LIs->getUseIndex(BarrierIdx)+1);
|
||||
} else {
|
||||
// Remove entire live range of the mbb out of the live interval.
|
||||
CurrLI->removeRange(LIs->getMBBStartIdx(MBB), LIs->getMBBEndIdx(MBB)+1);
|
||||
}
|
||||
|
||||
if (MBB == DefMBB)
|
||||
// Reached the def mbb, stop traversing this path further.
|
||||
return;
|
||||
|
||||
// Traverse the pathes up the predecessor chains further.
|
||||
for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(),
|
||||
PE = MBB->pred_end(); PI != PE; ++PI) {
|
||||
MachineBasicBlock *Pred = *PI;
|
||||
if (Pred == MBB)
|
||||
continue;
|
||||
if (Pred == DefMBB && ValNo->hasPHIKill)
|
||||
// Pred is the def bb and the def reaches other val#s, we must
|
||||
// allow the value to be live out of the bb.
|
||||
continue;
|
||||
if (!CurrLI->liveAt(LIs->getMBBEndIdx(Pred)-1))
|
||||
return;
|
||||
ShrinkWrapLiveInterval(ValNo, Pred, MBB, DefMBB, Visited,
|
||||
Uses, UseMIs, UseMBBs);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void PreAllocSplitting::RepairLiveInterval(LiveInterval* CurrLI,
|
||||
VNInfo* ValNo,
|
||||
MachineInstr* DefMI,
|
||||
unsigned RestoreIdx) {
|
||||
// Shrink wrap the live interval by walking up the CFG and find the
|
||||
// new kills.
|
||||
// Now let's find all the uses of the val#.
|
||||
DenseMap<MachineBasicBlock*, SmallVector<MachineOperand*, 4> > Uses;
|
||||
DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 4> > UseMIs;
|
||||
SmallPtrSet<MachineBasicBlock*, 4> Seen;
|
||||
SmallVector<MachineBasicBlock*, 4> UseMBBs;
|
||||
for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(CurrLI->reg),
|
||||
UE = MRI->use_end(); UI != UE; ++UI) {
|
||||
MachineOperand &UseMO = UI.getOperand();
|
||||
MachineInstr *UseMI = UseMO.getParent();
|
||||
unsigned UseIdx = LIs->getInstructionIndex(UseMI);
|
||||
LiveInterval::iterator ULR = CurrLI->FindLiveRangeContaining(UseIdx);
|
||||
if (ULR->valno != ValNo)
|
||||
continue;
|
||||
MachineBasicBlock *UseMBB = UseMI->getParent();
|
||||
// Remember which other mbb's use this val#.
|
||||
if (Seen.insert(UseMBB) && UseMBB != BarrierMBB)
|
||||
UseMBBs.push_back(UseMBB);
|
||||
DenseMap<MachineBasicBlock*, SmallVector<MachineOperand*, 4> >::iterator
|
||||
UMII = Uses.find(UseMBB);
|
||||
if (UMII != Uses.end()) {
|
||||
DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 4> >::iterator
|
||||
UMII2 = UseMIs.find(UseMBB);
|
||||
UMII->second.push_back(&UseMO);
|
||||
UMII2->second.insert(UseMI);
|
||||
} else {
|
||||
SmallVector<MachineOperand*, 4> Ops;
|
||||
Ops.push_back(&UseMO);
|
||||
Uses.insert(std::make_pair(UseMBB, Ops));
|
||||
SmallPtrSet<MachineInstr*, 4> MIs;
|
||||
MIs.insert(UseMI);
|
||||
UseMIs.insert(std::make_pair(UseMBB, MIs));
|
||||
}
|
||||
}
|
||||
|
||||
// Walk up the predecessor chains.
|
||||
SmallPtrSet<MachineBasicBlock*, 8> Visited;
|
||||
ShrinkWrapLiveInterval(ValNo, BarrierMBB, NULL, DefMI->getParent(), Visited,
|
||||
Uses, UseMIs, UseMBBs);
|
||||
|
||||
// Remove live range from barrier to the restore. FIXME: Find a better
|
||||
// point to re-start the live interval.
|
||||
VNInfo* AfterValNo = UpdateRegisterInterval(ValNo,
|
||||
LIs->getUseIndex(BarrierIdx)+1,
|
||||
LIs->getDefIndex(RestoreIdx));
|
||||
|
||||
// Attempt to renumber the new valno into a new vreg.
|
||||
RenumberValno(AfterValNo);
|
||||
}
|
||||
|
||||
/// RenumberValno - Split the given valno out into a new vreg, allowing it to
|
||||
/// be allocated to a different register. This function creates a new vreg,
|
||||
/// copies the valno and its live ranges over to the new vreg's interval,
|
||||
|
|
Loading…
Reference in New Issue