diff options
-rw-r--r-- | lib/CodeGen/InlineSpiller.cpp | 13 | ||||
-rw-r--r-- | lib/CodeGen/SplitKit.cpp | 75 | ||||
-rw-r--r-- | lib/CodeGen/SplitKit.h | 12 |
3 files changed, 95 insertions, 5 deletions
diff --git a/lib/CodeGen/InlineSpiller.cpp b/lib/CodeGen/InlineSpiller.cpp index 7978372..18dbe9c 100644 --- a/lib/CodeGen/InlineSpiller.cpp +++ b/lib/CodeGen/InlineSpiller.cpp @@ -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; } diff --git a/lib/CodeGen/SplitKit.cpp b/lib/CodeGen/SplitKit.cpp index 8ec2e1e..b919f0d 100644 --- a/lib/CodeGen/SplitKit.cpp +++ b/lib/CodeGen/SplitKit.cpp @@ -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_; +} diff --git a/lib/CodeGen/SplitKit.h b/lib/CodeGen/SplitKit.h index 08f7c56..ad9b92f 100644 --- a/lib/CodeGen/SplitKit.h +++ b/lib/CodeGen/SplitKit.h @@ -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 *); +}; } |