- Rewrite code that update register live interval that's split.

- Create and update spill slot live intervals.
- Lots of bug fixes.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@58367 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2008-10-29 05:06:14 +00:00
parent 980e842153
commit d0e32c5d5c
5 changed files with 199 additions and 86 deletions

View File

@ -260,7 +260,12 @@ namespace llvm {
/// findLiveInMBBs - Given a live range, if the value of the range /// findLiveInMBBs - Given a live range, if the value of the range
/// is live in any MBB returns true as well as the list of basic blocks /// is live in any MBB returns true as well as the list of basic blocks
/// in which the value is live. /// in which the value is live.
bool findLiveInMBBs(const LiveRange &LR, bool findLiveInMBBs(unsigned Start, unsigned End,
SmallVectorImpl<MachineBasicBlock*> &MBBs) const;
/// findReachableMBBs - Return a list MBB that can be reached via any
/// branch or fallthroughs. Return true if the list is not empty.
bool findReachableMBBs(unsigned Start, unsigned End,
SmallVectorImpl<MachineBasicBlock*> &MBBs) const; SmallVectorImpl<MachineBasicBlock*> &MBBs) const;
// Interval creation // Interval creation

View File

@ -52,6 +52,22 @@ namespace llvm {
return I->second; return I->second;
} }
LiveInterval &getInterval(int Slot) {
SS2IntervalMap::iterator I = s2iMap.find(Slot);
assert(I != s2iMap.end() && "Interval does not exist for stack slot");
return I->second;
}
const LiveInterval &getInterval(int Slot) const {
SS2IntervalMap::const_iterator I = s2iMap.find(Slot);
assert(I != s2iMap.end() && "Interval does not exist for stack slot");
return I->second;
}
bool hasInterval(unsigned reg) const {
return s2iMap.count(reg);
}
BumpPtrAllocator& getVNInfoAllocator() { return VNInfoAllocator; } BumpPtrAllocator& getVNInfoAllocator() { return VNInfoAllocator; }
virtual void getAnalysisUsage(AnalysisUsage &AU) const; virtual void getAnalysisUsage(AnalysisUsage &AU) const;

View File

@ -751,14 +751,14 @@ void LiveIntervals::computeIntervals() {
} }
} }
bool LiveIntervals::findLiveInMBBs(const LiveRange &LR, bool LiveIntervals::findLiveInMBBs(unsigned Start, unsigned End,
SmallVectorImpl<MachineBasicBlock*> &MBBs) const { SmallVectorImpl<MachineBasicBlock*> &MBBs) const {
std::vector<IdxMBBPair>::const_iterator I = std::vector<IdxMBBPair>::const_iterator I =
std::lower_bound(Idx2MBBMap.begin(), Idx2MBBMap.end(), LR.start); std::lower_bound(Idx2MBBMap.begin(), Idx2MBBMap.end(), Start);
bool ResVal = false; bool ResVal = false;
while (I != Idx2MBBMap.end()) { while (I != Idx2MBBMap.end()) {
if (LR.end <= I->first) if (I->first > End)
break; break;
MBBs.push_back(I->second); MBBs.push_back(I->second);
ResVal = true; ResVal = true;
@ -767,6 +767,27 @@ bool LiveIntervals::findLiveInMBBs(const LiveRange &LR,
return ResVal; return ResVal;
} }
bool LiveIntervals::findReachableMBBs(unsigned Start, unsigned End,
SmallVectorImpl<MachineBasicBlock*> &MBBs) const {
std::vector<IdxMBBPair>::const_iterator I =
std::lower_bound(Idx2MBBMap.begin(), Idx2MBBMap.end(), Start);
bool ResVal = false;
while (I != Idx2MBBMap.end()) {
if (I->first > End)
break;
MachineBasicBlock *MBB = I->second;
if (getMBBEndIdx(MBB) > End)
break;
for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(),
SE = MBB->succ_end(); SI != SE; ++SI)
MBBs.push_back(*SI);
ResVal = true;
++I;
}
return ResVal;
}
LiveInterval* LiveIntervals::createInterval(unsigned reg) { LiveInterval* LiveIntervals::createInterval(unsigned reg) {
float Weight = TargetRegisterInfo::isPhysicalRegister(reg) ? float Weight = TargetRegisterInfo::isPhysicalRegister(reg) ?
HUGE_VALF : 0.0F; HUGE_VALF : 0.0F;

View File

@ -16,6 +16,7 @@
#define DEBUG_TYPE "pre-alloc-split" #define DEBUG_TYPE "pre-alloc-split"
#include "llvm/CodeGen/LiveIntervalAnalysis.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/LiveStackAnalysis.h"
#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineLoopInfo.h"
@ -28,9 +29,9 @@
#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h" #include "llvm/ADT/Statistic.h"
#include <map>
using namespace llvm; using namespace llvm;
static cl::opt<int> PreSplitLimit("pre-split-limit", cl::init(-1), cl::Hidden); static cl::opt<int> PreSplitLimit("pre-split-limit", cl::init(-1), cl::Hidden);
@ -39,12 +40,13 @@ STATISTIC(NumSplits, "Number of intervals split");
namespace { namespace {
class VISIBILITY_HIDDEN PreAllocSplitting : public MachineFunctionPass { class VISIBILITY_HIDDEN PreAllocSplitting : public MachineFunctionPass {
MachineFunction *CurMF; MachineFunction *CurrMF;
const TargetMachine *TM; const TargetMachine *TM;
const TargetInstrInfo *TII; const TargetInstrInfo *TII;
MachineFrameInfo *MFI; MachineFrameInfo *MFI;
MachineRegisterInfo *MRI; MachineRegisterInfo *MRI;
LiveIntervals *LIs; LiveIntervals *LIs;
LiveStacks *LSs;
// Barrier - Current barrier being processed. // Barrier - Current barrier being processed.
MachineInstr *Barrier; MachineInstr *Barrier;
@ -58,10 +60,14 @@ namespace {
// CurrLI - Current live interval being split. // CurrLI - Current live interval being split.
LiveInterval *CurrLI; LiveInterval *CurrLI;
// LIValNoSSMap - A map from live interval and val# pairs to spill slots. // CurrSLI - Current stack slot live interval.
// This records what live interval's val# has been split and what spill LiveInterval *CurrSLI;
// slot was used.
std::map<std::pair<unsigned, unsigned>, int> LIValNoSSMap; // CurrSValNo - Current val# for the stack slot live interval.
VNInfo *CurrSValNo;
// IntervalSSMap - A map from live interval to spill slots.
DenseMap<unsigned, int> IntervalSSMap;
// RestoreMIs - All the restores inserted due to live interval splitting. // RestoreMIs - All the restores inserted due to live interval splitting.
SmallPtrSet<MachineInstr*, 8> RestoreMIs; SmallPtrSet<MachineInstr*, 8> RestoreMIs;
@ -75,6 +81,8 @@ namespace {
virtual void getAnalysisUsage(AnalysisUsage &AU) const { virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<LiveIntervals>(); AU.addRequired<LiveIntervals>();
AU.addPreserved<LiveIntervals>(); AU.addPreserved<LiveIntervals>();
AU.addRequired<LiveStacks>();
AU.addPreserved<LiveStacks>();
AU.addPreserved<RegisterCoalescer>(); AU.addPreserved<RegisterCoalescer>();
if (StrongPHIElim) if (StrongPHIElim)
AU.addPreservedID(StrongPHIEliminationID); AU.addPreservedID(StrongPHIEliminationID);
@ -84,7 +92,7 @@ namespace {
} }
virtual void releaseMemory() { virtual void releaseMemory() {
LIValNoSSMap.clear(); IntervalSSMap.clear();
RestoreMIs.clear(); RestoreMIs.clear();
} }
@ -114,13 +122,15 @@ namespace {
findRestorePoint(MachineBasicBlock*, MachineInstr*, unsigned, findRestorePoint(MachineBasicBlock*, MachineInstr*, unsigned,
SmallPtrSet<MachineInstr*, 4>&, unsigned&); SmallPtrSet<MachineInstr*, 4>&, unsigned&);
void RecordSplit(unsigned, unsigned, unsigned, int); int CreateSpillStackSlot(unsigned, const TargetRegisterClass *);
bool isAlreadySplit(unsigned, unsigned, int&); bool IsAvailableInStack(unsigned, unsigned, int&) const;
void UpdateIntervalForSplit(VNInfo*, unsigned, unsigned); void UpdateSpillSlotInterval(VNInfo*, unsigned, unsigned);
bool ShrinkWrapToLastUse(MachineBasicBlock*, void UpdateRegisterInterval(VNInfo*, unsigned, unsigned);
bool ShrinkWrapToLastUse(MachineBasicBlock*, VNInfo*,
SmallVector<MachineOperand*, 4>&, SmallVector<MachineOperand*, 4>&,
SmallPtrSet<MachineInstr*, 4>&); SmallPtrSet<MachineInstr*, 4>&);
@ -252,38 +262,101 @@ PreAllocSplitting::findRestorePoint(MachineBasicBlock *MBB, MachineInstr *MI,
return Pt; return Pt;
} }
/// RecordSplit - Given a register live interval is split, remember the spill /// CreateSpillStackSlot - Create a stack slot for the live interval being
/// slot where the val#s are in. /// split. If the live interval was previously split, just reuse the same
void PreAllocSplitting::RecordSplit(unsigned Reg, unsigned SpillIndex, /// slot.
unsigned RestoreIndex, int SS) { int PreAllocSplitting::CreateSpillStackSlot(unsigned Reg,
const LiveRange *LR = NULL; const TargetRegisterClass *RC) {
if (SpillIndex) { int SS;
LR = CurrLI->getLiveRangeContaining(LIs->getUseIndex(SpillIndex)); DenseMap<unsigned, int>::iterator I = IntervalSSMap.find(Reg);
LIValNoSSMap.insert(std::make_pair(std::make_pair(CurrLI->reg, if (I != IntervalSSMap.end()) {
LR->valno->id), SS)); SS = I->second;
} else {
SS = MFI->CreateStackObject(RC->getSize(), RC->getAlignment());
IntervalSSMap[Reg] = SS;
} }
LR = CurrLI->getLiveRangeContaining(LIs->getDefIndex(RestoreIndex));
LIValNoSSMap.insert(std::make_pair(std::make_pair(CurrLI->reg, // Create live interval for stack slot.
LR->valno->id), SS)); CurrSLI = &LSs->getOrCreateInterval(SS);
if (CurrSLI->getNumValNums())
CurrSValNo = CurrSLI->getValNumInfo(0);
else
CurrSValNo = CurrSLI->getNextValue(~0U, 0, LSs->getVNInfoAllocator());
return SS;
} }
/// isAlreadySplit - Return if a given val# of a register live interval is already /// IsAvailableInStack - Return true if register is available in a split stack
/// split. Also return by reference the spill stock where the value is. /// slot at the specified index.
bool PreAllocSplitting::isAlreadySplit(unsigned Reg, unsigned ValNoId, int &SS){ bool
std::map<std::pair<unsigned, unsigned>, int>::iterator I = PreAllocSplitting::IsAvailableInStack(unsigned Reg, unsigned Index, int &SS) const {
LIValNoSSMap.find(std::make_pair(Reg, ValNoId)); DenseMap<unsigned, int>::iterator I = IntervalSSMap.find(Reg);
if (I == LIValNoSSMap.end()) if (I == IntervalSSMap.end())
return false; return false;
SS = I->second; if (LSs->getInterval(I->second).liveAt(Index)) {
return true; SS = I->second;
return true;
}
return false;
} }
/// UpdateIntervalForSplit - Given the specified val# of the current live /// UpdateSpillSlotInterval - Given the specified val# of the register live
/// interval is being split, and the split and rejoin indices, update the live /// interval being split, and the spill and restore indicies, update the live
/// interval of the spill stack slot.
void
PreAllocSplitting::UpdateSpillSlotInterval(VNInfo *ValNo, unsigned SpillIndex,
unsigned RestoreIndex) {
const LiveRange *LR = CurrLI->getLiveRangeContaining(SpillIndex);
if (LR->contains(RestoreIndex)) {
LiveRange SLR(SpillIndex, RestoreIndex, CurrSValNo);
CurrSLI->addRange(SLR);
return;
}
SmallPtrSet<const LiveRange*, 4> Processed;
LiveRange SLR(SpillIndex, LR->end, CurrSValNo);
CurrSLI->addRange(SLR);
Processed.insert(LR);
// Start from the spill mbb, figure out the extend of the spill slot's
// live interval.
SmallVector<MachineBasicBlock*, 4> WorkList;
MachineBasicBlock *MBB = LIs->getMBBFromIndex(SpillIndex);
if (LR->end > LIs->getMBBEndIdx(MBB))
// If live range extend beyond end of mbb, add successors to work list.
for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(),
SE = MBB->succ_end(); SI != SE; ++SI)
WorkList.push_back(*SI);
// Live range may cross multiple basic blocks, add all reachable mbbs to
// the work list.
LIs->findReachableMBBs(LR->start, LR->end, WorkList);
while (!WorkList.empty()) {
MachineBasicBlock *MBB = WorkList.back();
WorkList.pop_back();
unsigned Idx = LIs->getMBBStartIdx(MBB);
LR = CurrLI->getLiveRangeContaining(Idx);
if (LR && LR->valno == ValNo && !Processed.count(LR)) {
if (LR->contains(RestoreIndex)) {
// Spill slot live interval stops at the restore.
LiveRange SLR(LR->start, RestoreIndex, CurrSValNo);
CurrSLI->addRange(SLR);
LIs->findReachableMBBs(LR->start, RestoreIndex, WorkList);
} else {
LiveRange SLR(LR->start, LR->end, CurrSValNo);
CurrSLI->addRange(SLR);
LIs->findReachableMBBs(LR->start, LR->end, WorkList);
}
Processed.insert(LR);
}
}
}
/// UpdateRegisterInterval - Given the specified val# of the current live
/// interval is being split, and the spill and restore indices, update the live
/// interval accordingly. /// interval accordingly.
void void
PreAllocSplitting::UpdateIntervalForSplit(VNInfo *ValNo, unsigned SplitIndex, PreAllocSplitting::UpdateRegisterInterval(VNInfo *ValNo, unsigned SpillIndex,
unsigned JoinIndex) { unsigned RestoreIndex) {
SmallVector<std::pair<unsigned,unsigned>, 4> Before; SmallVector<std::pair<unsigned,unsigned>, 4> Before;
SmallVector<std::pair<unsigned,unsigned>, 4> After; SmallVector<std::pair<unsigned,unsigned>, 4> After;
SmallVector<unsigned, 4> BeforeKills; SmallVector<unsigned, 4> BeforeKills;
@ -292,20 +365,22 @@ PreAllocSplitting::UpdateIntervalForSplit(VNInfo *ValNo, unsigned SplitIndex,
// First, let's figure out which parts of the live interval is now defined // First, let's figure out which parts of the live interval is now defined
// by the restore, which are defined by the original definition. // by the restore, which are defined by the original definition.
const LiveRange *LR = CurrLI->getLiveRangeContaining(JoinIndex); const LiveRange *LR = CurrLI->getLiveRangeContaining(RestoreIndex);
After.push_back(std::make_pair(JoinIndex, LR->end)); After.push_back(std::make_pair(RestoreIndex, LR->end));
if (CurrLI->isKill(ValNo, LR->end)) if (CurrLI->isKill(ValNo, LR->end))
AfterKills.push_back(LR->end); AfterKills.push_back(LR->end);
assert(LR->contains(SplitIndex)); assert(LR->contains(SpillIndex));
if (SplitIndex > LR->start) { if (SpillIndex > LR->start) {
Before.push_back(std::make_pair(LR->start, SplitIndex)); Before.push_back(std::make_pair(LR->start, SpillIndex));
BeforeKills.push_back(SplitIndex); BeforeKills.push_back(SpillIndex);
} }
Processed.insert(LR); 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; SmallVector<MachineBasicBlock*, 4> WorkList;
MachineBasicBlock *MBB = LIs->getMBBFromIndex(LR->end-1); MachineBasicBlock *MBB = LIs->getMBBFromIndex(RestoreIndex);
for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(),
SE = MBB->succ_end(); SI != SE; ++SI) SE = MBB->succ_end(); SI != SE; ++SI)
WorkList.push_back(*SI); WorkList.push_back(*SI);
@ -321,15 +396,9 @@ PreAllocSplitting::UpdateIntervalForSplit(VNInfo *ValNo, unsigned SplitIndex,
AfterKills.push_back(LR->end); AfterKills.push_back(LR->end);
Idx = LIs->getMBBEndIdx(MBB); Idx = LIs->getMBBEndIdx(MBB);
if (LR->end > Idx) { if (LR->end > Idx) {
for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), // Live range extend beyond at least one mbb. Let's see what other
SE = MBB->succ_end(); SI != SE; ++SI) // mbbs it reaches.
WorkList.push_back(*SI); LIs->findReachableMBBs(LR->start, LR->end, WorkList);
if (LR->end > Idx+1) {
MBB = LIs->getMBBFromIndex(LR->end-1);
for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(),
SE = MBB->succ_end(); SI != SE; ++SI)
WorkList.push_back(*SI);
}
} }
Processed.insert(LR); Processed.insert(LR);
} }
@ -359,7 +428,7 @@ PreAllocSplitting::UpdateIntervalForSplit(VNInfo *ValNo, unsigned SplitIndex,
VNInfo *AValNo = (After.empty()) VNInfo *AValNo = (After.empty())
? NULL ? NULL
: CurrLI->getNextValue(JoinIndex,0, LIs->getVNInfoAllocator()); : CurrLI->getNextValue(RestoreIndex, 0, LIs->getVNInfoAllocator());
if (AValNo) { if (AValNo) {
AValNo->hasPHIKill = HasPHIKill; AValNo->hasPHIKill = HasPHIKill;
CurrLI->addKills(AValNo, AfterKills); CurrLI->addKills(AValNo, AfterKills);
@ -382,7 +451,7 @@ PreAllocSplitting::UpdateIntervalForSplit(VNInfo *ValNo, unsigned SplitIndex,
/// from last use to the end of the mbb). In case mbb is the where the barrier /// 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. /// is, remove from the last use to the barrier.
bool bool
PreAllocSplitting::ShrinkWrapToLastUse(MachineBasicBlock *MBB, PreAllocSplitting::ShrinkWrapToLastUse(MachineBasicBlock *MBB, VNInfo *ValNo,
SmallVector<MachineOperand*, 4> &Uses, SmallVector<MachineOperand*, 4> &Uses,
SmallPtrSet<MachineInstr*, 4> &UseMIs) { SmallPtrSet<MachineInstr*, 4> &UseMIs) {
MachineOperand *LastMO = 0; MachineOperand *LastMO = 0;
@ -399,7 +468,8 @@ PreAllocSplitting::ShrinkWrapToLastUse(MachineBasicBlock *MBB,
MII = Barrier; MII = Barrier;
else else
MII = MBB->end(); MII = MBB->end();
while (--MII != MEE) { while (MII != MEE) {
--MII;
MachineInstr *UseMI = &*MII; MachineInstr *UseMI = &*MII;
if (!UseMIs.count(UseMI)) if (!UseMIs.count(UseMI))
continue; continue;
@ -429,6 +499,8 @@ PreAllocSplitting::ShrinkWrapToLastUse(MachineBasicBlock *MBB,
if (MBB == BarrierMBB) if (MBB == BarrierMBB)
RangeEnd = LIs->getUseIndex(BarrierIdx)+1; RangeEnd = LIs->getUseIndex(BarrierIdx)+1;
CurrLI->removeRange(RangeStart, RangeEnd); CurrLI->removeRange(RangeStart, RangeEnd);
if (LastMI)
CurrLI->addKill(ValNo, RangeStart);
// Return true if the last use becomes a new kill. // Return true if the last use becomes a new kill.
return LastMI; return LastMI;
@ -469,12 +541,10 @@ PreAllocSplitting::ShrinkWrapLiveInterval(VNInfo *ValNo, MachineBasicBlock *MBB,
// At least one use in this mbb, lets look for the kill. // At least one use in this mbb, lets look for the kill.
DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 4> >::iterator DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 4> >::iterator
UMII2 = UseMIs.find(MBB); UMII2 = UseMIs.find(MBB);
if (ShrinkWrapToLastUse(MBB, UMII->second, UMII2->second)) if (ShrinkWrapToLastUse(MBB, ValNo, UMII->second, UMII2->second))
// Found a kill, shrink wrapping of this path ends here. // Found a kill, shrink wrapping of this path ends here.
return; return;
} else if (MBB == DefMBB) { } else if (MBB == DefMBB) {
assert(LIValNoSSMap.find(std::make_pair(CurrLI->reg, ValNo->id)) !=
LIValNoSSMap.end() && "Why wasn't def spilled?");
// There are no uses after the def. // There are no uses after the def.
MachineInstr *DefMI = LIs->getInstructionFromIndex(ValNo->def); MachineInstr *DefMI = LIs->getInstructionFromIndex(ValNo->def);
assert(RestoreMIs.count(DefMI) && "Not defined by a join?"); assert(RestoreMIs.count(DefMI) && "Not defined by a join?");
@ -560,7 +630,6 @@ bool PreAllocSplitting::SplitRegLiveInterval(LiveInterval *LI) {
unsigned SpillIndex = 0; unsigned SpillIndex = 0;
MachineInstr *SpillMI = NULL; MachineInstr *SpillMI = NULL;
int SS = -1; int SS = -1;
bool PrevSpilled = isAlreadySplit(CurrLI->reg, ValNo->id, SS);
if (ValNo->def == ~0U) { if (ValNo->def == ~0U) {
// If it's defined by a phi, we must split just before the barrier. // If it's defined by a phi, we must split just before the barrier.
MachineBasicBlock::iterator SpillPt = MachineBasicBlock::iterator SpillPt =
@ -568,18 +637,15 @@ bool PreAllocSplitting::SplitRegLiveInterval(LiveInterval *LI) {
if (SpillPt == BarrierMBB->begin()) if (SpillPt == BarrierMBB->begin())
return false; // No gap to insert spill. return false; // No gap to insert spill.
// Add spill. // Add spill.
if (!PrevSpilled) SS = CreateSpillStackSlot(CurrLI->reg, RC);
// If previously split, reuse the spill slot.
SS = MFI->CreateStackObject(RC->getSize(), RC->getAlignment());
TII->storeRegToStackSlot(*BarrierMBB, SpillPt, CurrLI->reg, true, SS, RC); TII->storeRegToStackSlot(*BarrierMBB, SpillPt, CurrLI->reg, true, SS, RC);
SpillMI = prior(SpillPt); SpillMI = prior(SpillPt);
LIs->InsertMachineInstrInMaps(SpillMI, SpillIndex); LIs->InsertMachineInstrInMaps(SpillMI, SpillIndex);
} else if (!PrevSpilled) { } else if (!IsAvailableInStack(CurrLI->reg, RestoreIndex, SS)) {
if (!DefMI)
// Def is dead. Do nothing.
return false;
// If it's already split, just restore the value. There is no need to spill // If it's already split, just restore the value. There is no need to spill
// the def again. // the def again.
if (!DefMI)
return false; // Def is dead. Do nothing.
// Check if it's possible to insert a spill after the def MI. // Check if it's possible to insert a spill after the def MI.
MachineBasicBlock::iterator SpillPt; MachineBasicBlock::iterator SpillPt;
if (DefMBB == BarrierMBB) { if (DefMBB == BarrierMBB) {
@ -592,10 +658,9 @@ bool PreAllocSplitting::SplitRegLiveInterval(LiveInterval *LI) {
if (SpillPt == DefMBB->end()) if (SpillPt == DefMBB->end())
return false; // No gap to insert spill. return false; // No gap to insert spill.
} }
SS = MFI->CreateStackObject(RC->getSize(), RC->getAlignment());
// Add spill. The store instruction kills the register if def is before // Add spill. The store instruction kills the register if def is before
// the barrier in the barrier block. // the barrier in the barrier block.
SS = CreateSpillStackSlot(CurrLI->reg, RC);
TII->storeRegToStackSlot(*DefMBB, SpillPt, CurrLI->reg, TII->storeRegToStackSlot(*DefMBB, SpillPt, CurrLI->reg,
DefMBB == BarrierMBB, SS, RC); DefMBB == BarrierMBB, SS, RC);
SpillMI = prior(SpillPt); SpillMI = prior(SpillPt);
@ -603,7 +668,6 @@ bool PreAllocSplitting::SplitRegLiveInterval(LiveInterval *LI) {
} }
// Add restore. // Add restore.
// FIXME: Create live interval for stack slot.
TII->loadRegFromStackSlot(*BarrierMBB, RestorePt, CurrLI->reg, SS, RC); TII->loadRegFromStackSlot(*BarrierMBB, RestorePt, CurrLI->reg, SS, RC);
MachineInstr *LoadMI = prior(RestorePt); MachineInstr *LoadMI = prior(RestorePt);
LIs->InsertMachineInstrInMaps(LoadMI, RestoreIndex); LIs->InsertMachineInstrInMaps(LoadMI, RestoreIndex);
@ -613,16 +677,24 @@ bool PreAllocSplitting::SplitRegLiveInterval(LiveInterval *LI) {
// create a hole in the interval. // create a hole in the interval.
if (!DefMBB || if (!DefMBB ||
(SpillMI && SpillMI->getParent() == BarrierMBB)) { (SpillMI && SpillMI->getParent() == BarrierMBB)) {
UpdateIntervalForSplit(ValNo, LIs->getUseIndex(SpillIndex)+1, // Update spill stack slot live interval.
LIs->getDefIndex(RestoreIndex)); UpdateSpillSlotInterval(ValNo, LIs->getUseIndex(SpillIndex)+1,
LIs->getDefIndex(RestoreIndex));
// Record val# values are in the specific spill slot. UpdateRegisterInterval(ValNo, LIs->getUseIndex(SpillIndex)+1,
RecordSplit(CurrLI->reg, SpillIndex, RestoreIndex, SS); LIs->getDefIndex(RestoreIndex));
++NumSplits; ++NumSplits;
return true; return true;
} }
// Update spill stack slot live interval.
if (SpillIndex)
// If value is already in stack at the restore point, there is
// no need to update the live interval.
UpdateSpillSlotInterval(ValNo, LIs->getUseIndex(SpillIndex)+1,
LIs->getDefIndex(RestoreIndex));
// Shrink wrap the live interval by walking up the CFG and find the // Shrink wrap the live interval by walking up the CFG and find the
// new kills. // new kills.
// Now let's find all the uses of the val#. // Now let's find all the uses of the val#.
@ -666,10 +738,8 @@ bool PreAllocSplitting::SplitRegLiveInterval(LiveInterval *LI) {
// Remove live range from barrier to the restore. FIXME: Find a better // Remove live range from barrier to the restore. FIXME: Find a better
// point to re-start the live interval. // point to re-start the live interval.
UpdateIntervalForSplit(ValNo, LIs->getUseIndex(BarrierIdx)+1, UpdateRegisterInterval(ValNo, LIs->getUseIndex(BarrierIdx)+1,
LIs->getDefIndex(RestoreIndex)); LIs->getDefIndex(RestoreIndex));
// Record val# values are in the specific spill slot.
RecordSplit(CurrLI->reg, SpillIndex, RestoreIndex, SS);
++NumSplits; ++NumSplits;
return true; return true;
@ -712,12 +782,13 @@ PreAllocSplitting::SplitRegLiveIntervals(const TargetRegisterClass **RCs) {
} }
bool PreAllocSplitting::runOnMachineFunction(MachineFunction &MF) { bool PreAllocSplitting::runOnMachineFunction(MachineFunction &MF) {
CurMF = &MF; CurrMF = &MF;
TM = &MF.getTarget(); TM = &MF.getTarget();
TII = TM->getInstrInfo(); TII = TM->getInstrInfo();
MFI = MF.getFrameInfo(); MFI = MF.getFrameInfo();
MRI = &MF.getRegInfo(); MRI = &MF.getRegInfo();
LIs = &getAnalysis<LiveIntervals>(); LIs = &getAnalysis<LiveIntervals>();
LSs = &getAnalysis<LiveStacks>();
bool MadeChange = false; bool MadeChange = false;

View File

@ -410,7 +410,7 @@ void RALinScan::linearScan()
for (LiveInterval::Ranges::const_iterator I = cur.begin(), E = cur.end(); for (LiveInterval::Ranges::const_iterator I = cur.begin(), E = cur.end();
I != E; ++I) { I != E; ++I) {
const LiveRange &LR = *I; const LiveRange &LR = *I;
if (li_->findLiveInMBBs(LR, LiveInMBBs)) { if (li_->findLiveInMBBs(LR.start, LR.end, LiveInMBBs)) {
for (unsigned i = 0, e = LiveInMBBs.size(); i != e; ++i) for (unsigned i = 0, e = LiveInMBBs.size(); i != e; ++i)
if (LiveInMBBs[i] != EntryMBB) if (LiveInMBBs[i] != EntryMBB)
LiveInMBBs[i]->addLiveIn(Reg); LiveInMBBs[i]->addLiveIn(Reg);