mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-28 23:43:25 +00:00
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:
parent
e62d58884a
commit
fc412d85c4
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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_;
|
||||
}
|
||||
|
@ -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 *);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user