Implement splitting inside a single block.

When a live range is contained a single block, we can split it around
instruction clusters. The current approach is very primitive, splitting before
and after the largest gap between uses.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@111043 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jakob Stoklund Olesen 2010-08-13 21:18:48 +00:00
parent e62d58884a
commit fc412d85c4
3 changed files with 95 additions and 5 deletions

View File

@ -106,10 +106,6 @@ Spiller *createInlineSpiller(MachineFunctionPass &pass,
/// split - try splitting the current interval into pieces that may allocate
/// separately. Return true if successful.
bool InlineSpiller::split() {
// FIXME: Add intra-MBB splitting.
if (lis_.intervalIsInOneMBB(*li_))
return false;
splitAnalysis_.analyze(li_);
if (const MachineLoop *loop = splitAnalysis_.getBestSplitLoop()) {
@ -127,6 +123,15 @@ bool InlineSpiller::split() {
return true;
}
// Try splitting inside a basic block.
if (const MachineBasicBlock *MBB = splitAnalysis_.getBlockForInsideSplit()) {
if (SplitEditor(splitAnalysis_, lis_, vrm_, *newIntervals_)
.splitInsideBlock(MBB))
return true;
}
// We may have been able to split out some uses, but the original interval is
// intact, and it should still be spilled.
return false;
}

View File

@ -781,3 +781,78 @@ bool SplitEditor::splitSingleBlocks(const SplitAnalysis::BlockPtrSet &Blocks) {
return dupli_;
}
//===----------------------------------------------------------------------===//
// Sub Block Splitting
//===----------------------------------------------------------------------===//
/// getBlockForInsideSplit - If curli is contained inside a single basic block,
/// and it wou pay to subdivide the interval inside that block, return it.
/// Otherwise return NULL. The returned block can be passed to
/// SplitEditor::splitInsideBlock.
const MachineBasicBlock *SplitAnalysis::getBlockForInsideSplit() {
// The interval must be exclusive to one block.
if (usingBlocks_.size() != 1)
return 0;
// Don't to this for less than 4 instructions. We want to be sure that
// splitting actually reduces the instruction count per interval.
if (usingInstrs_.size() < 4)
return 0;
return usingBlocks_.begin()->first;
}
/// splitInsideBlock - Split curli into multiple intervals inside MBB. Return
/// true if curli has been completely replaced, false if curli is still
/// intact, and needs to be spilled or split further.
bool SplitEditor::splitInsideBlock(const MachineBasicBlock *MBB) {
SmallVector<SlotIndex, 32> Uses;
Uses.reserve(sa_.usingInstrs_.size());
for (SplitAnalysis::InstrPtrSet::const_iterator I = sa_.usingInstrs_.begin(),
E = sa_.usingInstrs_.end(); I != E; ++I)
if ((*I)->getParent() == MBB)
Uses.push_back(lis_.getInstructionIndex(*I));
DEBUG(dbgs() << " splitInsideBlock BB#" << MBB->getNumber() << " for "
<< Uses.size() << " instructions.\n");
assert(Uses.size() >= 3 && "Need at least 3 instructions");
array_pod_sort(Uses.begin(), Uses.end());
// Simple algorithm: Find the largest gap between uses as determined by slot
// indices. Create new intervals for instructions before the gap and after the
// gap.
unsigned bestPos = 0;
int bestGap = 0;
DEBUG(dbgs() << " dist (" << Uses[0]);
for (unsigned i = 1, e = Uses.size(); i != e; ++i) {
int g = Uses[i-1].distance(Uses[i]);
DEBUG(dbgs() << ") -" << g << "- (" << Uses[i]);
if (g > bestGap)
bestPos = i, bestGap = g;
}
DEBUG(dbgs() << "), best: -" << bestGap << "-\n");
// bestPos points to the first use after the best gap.
assert(bestPos > 0 && "Invalid gap");
// FIXME: Don't create intervals for low densities.
// First interval before the gap. Don't create single-instr intervals.
if (bestPos > 1) {
openIntv();
enterIntvBefore(Uses.front());
useIntv(Uses.front().getBaseIndex(), Uses[bestPos-1].getBoundaryIndex());
leaveIntvAfter(Uses[bestPos-1]);
closeIntv();
}
// Second interval after the gap.
if (bestPos < Uses.size()-1) {
openIntv();
enterIntvBefore(Uses[bestPos]);
useIntv(Uses[bestPos].getBaseIndex(), Uses.back().getBoundaryIndex());
leaveIntvAfter(Uses.back());
closeIntv();
}
rewrite();
return dupli_;
}

View File

@ -127,6 +127,12 @@ public:
/// having curli split to a new live interval. Return true if Blocks can be
/// passed to SplitEditor::splitSingleBlocks.
bool getMultiUseBlocks(BlockPtrSet &Blocks);
/// getBlockForInsideSplit - If curli is contained inside a single basic block,
/// and it wou pay to subdivide the interval inside that block, return it.
/// Otherwise return NULL. The returned block can be passed to
/// SplitEditor::splitInsideBlock.
const MachineBasicBlock *getBlockForInsideSplit();
};
/// SplitEditor - Edit machine code and LiveIntervals for live range
@ -242,7 +248,11 @@ public:
/// basic block in Blocks. Return true if curli has been completely replaced,
/// false if curli is still intact, and needs to be spilled or split further.
bool splitSingleBlocks(const SplitAnalysis::BlockPtrSet &Blocks);
/// splitInsideBlock - Split curli into multiple intervals inside MBB. Return
/// true if curli has been completely replaced, false if curli is still
/// intact, and needs to be spilled or split further.
bool splitInsideBlock(const MachineBasicBlock *);
};
}