Cache the fairly expensive last split point computation and provide a fast

inlined path for the common case.

Most basic blocks don't contain a call that may throw, so the last split point
os simply the first terminator.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128874 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jakob Stoklund Olesen
2011-04-05 04:20:27 +00:00
parent f05b1dcf87
commit 1a7744501a
3 changed files with 58 additions and 14 deletions

View File

@ -305,6 +305,10 @@ public:
/// it returns end() /// it returns end()
iterator getFirstTerminator(); iterator getFirstTerminator();
const_iterator getFirstTerminator() const {
return const_cast<MachineBasicBlock*>(this)->getFirstTerminator();
}
/// getLastNonDebugInstr - returns an iterator to the last non-debug /// getLastNonDebugInstr - returns an iterator to the last non-debug
/// instruction in the basic block, or end() /// instruction in the basic block, or end()
iterator getLastNonDebugInstr(); iterator getLastNonDebugInstr();

View File

@ -48,7 +48,8 @@ SplitAnalysis::SplitAnalysis(const VirtRegMap &vrm,
LIS(lis), LIS(lis),
Loops(mli), Loops(mli),
TII(*MF.getTarget().getInstrInfo()), TII(*MF.getTarget().getInstrInfo()),
CurLI(0) {} CurLI(0),
LastSplitPoint(MF.getNumBlockIDs()) {}
void SplitAnalysis::clear() { void SplitAnalysis::clear() {
UseSlots.clear(); UseSlots.clear();
@ -58,10 +59,39 @@ void SplitAnalysis::clear() {
CurLI = 0; CurLI = 0;
} }
bool SplitAnalysis::canAnalyzeBranch(const MachineBasicBlock *MBB) { SlotIndex SplitAnalysis::computeLastSplitPoint(unsigned Num) {
MachineBasicBlock *T, *F; const MachineBasicBlock *MBB = MF.getBlockNumbered(Num);
SmallVector<MachineOperand, 4> Cond; const MachineBasicBlock *LPad = MBB->getLandingPadSuccessor();
return !TII.AnalyzeBranch(const_cast<MachineBasicBlock&>(*MBB), T, F, Cond); std::pair<SlotIndex, SlotIndex> &LSP = LastSplitPoint[Num];
// Compute split points on the first call. The pair is independent of the
// current live interval.
if (!LSP.first.isValid()) {
MachineBasicBlock::const_iterator FirstTerm = MBB->getFirstTerminator();
if (FirstTerm == MBB->end())
LSP.first = LIS.getMBBEndIdx(MBB);
else
LSP.first = LIS.getInstructionIndex(FirstTerm);
// If there is a landing pad successor, also find the call instruction.
if (!LPad)
return LSP.first;
// There may not be a call instruction (?) in which case we ignore LPad.
LSP.second = LSP.first;
for (MachineBasicBlock::const_iterator I = FirstTerm, E = MBB->begin();
I != E; --I)
if (I->getDesc().isCall()) {
LSP.second = LIS.getInstructionIndex(I);
break;
}
}
// If CurLI is live into a landing pad successor, move the last split point
// back to the call that may throw.
if (LPad && LSP.second.isValid() && !LIS.isLiveInToMBB(*CurLI, LPad))
return LSP.second;
else
return LSP.first;
} }
/// analyzeUses - Count instructions, basic blocks, and loops using CurLI. /// analyzeUses - Count instructions, basic blocks, and loops using CurLI.
@ -125,11 +155,7 @@ bool SplitAnalysis::calcLiveBlockInfo() {
// all successor blocks. If interference reaches LastSplitPoint, it is not // all successor blocks. If interference reaches LastSplitPoint, it is not
// possible to insert a split or reload that makes CurLI live in the // possible to insert a split or reload that makes CurLI live in the
// outgoing bundle. // outgoing bundle.
MachineBasicBlock::iterator LSP = LIS.getLastSplitPoint(*CurLI, BI.MBB); BI.LastSplitPoint = getLastSplitPoint(BI.MBB->getNumber());
if (LSP == BI.MBB->end())
BI.LastSplitPoint = Stop;
else
BI.LastSplitPoint = LIS.getInstructionIndex(LSP);
// LVI is the first live segment overlapping MBB. // LVI is the first live segment overlapping MBB.
BI.LiveIn = LVI->start <= Start; BI.LiveIn = LVI->start <= Start;

View File

@ -93,16 +93,20 @@ private:
// Current live interval. // Current live interval.
const LiveInterval *CurLI; const LiveInterval *CurLI;
/// LastSplitPoint - Last legal split point in each basic block in the current
/// function. The first entry is the first terminator, the second entry is the
/// last valid split point for a variable that is live in to a landing pad
/// successor.
SmallVector<std::pair<SlotIndex, SlotIndex>, 8> LastSplitPoint;
SlotIndex computeLastSplitPoint(unsigned Num);
// Sumarize statistics by counting instructions using CurLI. // Sumarize statistics by counting instructions using CurLI.
void analyzeUses(); void analyzeUses();
/// calcLiveBlockInfo - Compute per-block information about CurLI. /// calcLiveBlockInfo - Compute per-block information about CurLI.
bool calcLiveBlockInfo(); bool calcLiveBlockInfo();
/// canAnalyzeBranch - Return true if MBB ends in a branch that can be
/// analyzed.
bool canAnalyzeBranch(const MachineBasicBlock *MBB);
public: public:
SplitAnalysis(const VirtRegMap &vrm, const LiveIntervals &lis, SplitAnalysis(const VirtRegMap &vrm, const LiveIntervals &lis,
const MachineLoopInfo &mli); const MachineLoopInfo &mli);
@ -118,6 +122,16 @@ public:
/// getParent - Return the last analyzed interval. /// getParent - Return the last analyzed interval.
const LiveInterval &getParent() const { return *CurLI; } const LiveInterval &getParent() const { return *CurLI; }
/// getLastSplitPoint - Return that base index of the last valid split point
/// in the basic block numbered Num.
SlotIndex getLastSplitPoint(unsigned Num) {
// Inline the common simple case.
if (LastSplitPoint[Num].first.isValid() &&
!LastSplitPoint[Num].second.isValid())
return LastSplitPoint[Num].first;
return computeLastSplitPoint(Num);
}
/// hasUses - Return true if MBB has any uses of CurLI. /// hasUses - Return true if MBB has any uses of CurLI.
bool hasUses(const MachineBasicBlock *MBB) const { bool hasUses(const MachineBasicBlock *MBB) const {
return UsingBlocks.lookup(MBB); return UsingBlocks.lookup(MBB);