forked from OSchip/llvm-project
Implement single block splitting.
Before spilling a live range, we split it into a separate range for each basic block where it is used. That way we only get one reload per basic block if the new smaller ranges can allocate to a register. This type of splitting is already present in the standard spiller. llvm-svn: 110934
This commit is contained in:
parent
02690ba643
commit
622848b262
|
@ -118,6 +118,15 @@ bool InlineSpiller::split() {
|
||||||
.splitAroundLoop(loop))
|
.splitAroundLoop(loop))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try splitting into single block intervals.
|
||||||
|
SplitAnalysis::BlockPtrSet blocks;
|
||||||
|
if (splitAnalysis_.getMultiUseBlocks(blocks)) {
|
||||||
|
if (SplitEditor(splitAnalysis_, lis_, vrm_, *newIntervals_)
|
||||||
|
.splitSingleBlocks(blocks))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -279,6 +279,33 @@ const MachineLoop *SplitAnalysis::getBestSplitLoop() {
|
||||||
return Best;
|
return Best;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getMultiUseBlocks - if curli has more than one use in a basic block, it
|
||||||
|
/// may be an advantage to split curli for the duration of the block.
|
||||||
|
bool SplitAnalysis::getMultiUseBlocks(BlockPtrSet &Blocks) {
|
||||||
|
// If curli is local to one block, there is no point to splitting it.
|
||||||
|
if (usingBlocks_.size() <= 1)
|
||||||
|
return false;
|
||||||
|
// Add blocks with multiple uses.
|
||||||
|
for (BlockCountMap::iterator I = usingBlocks_.begin(), E = usingBlocks_.end();
|
||||||
|
I != E; ++I)
|
||||||
|
switch (I->second) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
continue;
|
||||||
|
case 2: {
|
||||||
|
// It doesn't pay to split a 2-instr block if it redefines curli.
|
||||||
|
VNInfo *VN1 = curli_->getVNInfoAt(lis_.getMBBStartIdx(I->first));
|
||||||
|
VNInfo *VN2 =
|
||||||
|
curli_->getVNInfoAt(lis_.getMBBEndIdx(I->first).getPrevIndex());
|
||||||
|
// live-in and live-out with a different value.
|
||||||
|
if (VN1 && VN2 && VN1 != VN2)
|
||||||
|
continue;
|
||||||
|
} // Fall through.
|
||||||
|
default:
|
||||||
|
Blocks.insert(I->first);
|
||||||
|
}
|
||||||
|
return !Blocks.empty();
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Split Editor
|
// Split Editor
|
||||||
|
@ -351,6 +378,27 @@ void SplitEditor::openIntv() {
|
||||||
liveThrough_ = false;
|
liveThrough_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// enterIntvBefore - Enter openli before the instruction at Idx. If curli is
|
||||||
|
/// not live before Idx, a COPY is not inserted.
|
||||||
|
void SplitEditor::enterIntvBefore(SlotIndex Idx) {
|
||||||
|
assert(openli_ && "openIntv not called before enterIntvBefore");
|
||||||
|
|
||||||
|
// Copy from curli_ if it is live.
|
||||||
|
if (VNInfo *CurVNI = curli_->getVNInfoAt(Idx.getUseIndex())) {
|
||||||
|
MachineInstr *MI = lis_.getInstructionFromIndex(Idx);
|
||||||
|
assert(MI && "enterIntvBefore called with invalid index");
|
||||||
|
VNInfo *VNI = insertCopy(*openli_, *MI->getParent(), MI);
|
||||||
|
openli_->addRange(LiveRange(VNI->def, Idx.getDefIndex(), VNI));
|
||||||
|
|
||||||
|
// Make sure CurVNI is properly mapped.
|
||||||
|
VNInfo *&mapVNI = valueMap_[CurVNI];
|
||||||
|
// We dont have SSA update yet, so only one entry per value is allowed.
|
||||||
|
assert(!mapVNI && "enterIntvBefore called more than once for the same value");
|
||||||
|
mapVNI = VNI;
|
||||||
|
}
|
||||||
|
DEBUG(dbgs() << " enterIntvBefore " << Idx << ": " << *openli_ << '\n');
|
||||||
|
}
|
||||||
|
|
||||||
/// enterIntvAtEnd - Enter openli at the end of MBB.
|
/// enterIntvAtEnd - Enter openli at the end of MBB.
|
||||||
/// PhiMBB is a successor inside openli where a PHI value is created.
|
/// PhiMBB is a successor inside openli where a PHI value is created.
|
||||||
/// Currently, all entries must share the same PhiMBB.
|
/// Currently, all entries must share the same PhiMBB.
|
||||||
|
@ -435,6 +483,39 @@ void SplitEditor::useIntv(SlotIndex Start, SlotIndex End) {
|
||||||
<< '\n');
|
<< '\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// leaveIntvAfter - Leave openli after the instruction at Idx.
|
||||||
|
void SplitEditor::leaveIntvAfter(SlotIndex Idx) {
|
||||||
|
assert(openli_ && "openIntv not called before leaveIntvAfter");
|
||||||
|
|
||||||
|
const LiveRange *CurLR = curli_->getLiveRangeContaining(Idx.getDefIndex());
|
||||||
|
if (!CurLR || CurLR->end <= Idx.getBoundaryIndex()) {
|
||||||
|
DEBUG(dbgs() << " leaveIntvAfter at " << Idx << ": not live\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Was this value of curli live through openli?
|
||||||
|
if (!openli_->liveAt(CurLR->valno->def)) {
|
||||||
|
DEBUG(dbgs() << " leaveIntvAfter " << Idx << ": using external value\n");
|
||||||
|
liveThrough_ = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We are going to insert a back copy, so we must have a dupli_.
|
||||||
|
LiveRange *DupLR = getDupLI()->getLiveRangeContaining(Idx.getDefIndex());
|
||||||
|
assert(DupLR && "dupli not live into black, but curli is?");
|
||||||
|
|
||||||
|
// Insert the COPY instruction.
|
||||||
|
MachineBasicBlock::iterator I = lis_.getInstructionFromIndex(Idx);
|
||||||
|
MachineInstr *MI = BuildMI(*I->getParent(), llvm::next(I), I->getDebugLoc(),
|
||||||
|
tii_.get(TargetOpcode::COPY), dupli_->reg)
|
||||||
|
.addReg(openli_->reg);
|
||||||
|
SlotIndex CopyIdx = lis_.InsertMachineInstrInMaps(MI).getDefIndex();
|
||||||
|
openli_->addRange(LiveRange(Idx.getDefIndex(), CopyIdx,
|
||||||
|
mapValue(CurLR->valno)));
|
||||||
|
DupLR->valno->def = CopyIdx;
|
||||||
|
DEBUG(dbgs() << " leaveIntvAfter " << Idx << ": " << *openli_ << '\n');
|
||||||
|
}
|
||||||
|
|
||||||
/// leaveIntvAtTop - Leave the interval at the top of MBB.
|
/// leaveIntvAtTop - Leave the interval at the top of MBB.
|
||||||
/// Currently, only one value can leave the interval.
|
/// Currently, only one value can leave the interval.
|
||||||
void SplitEditor::leaveIntvAtTop(MachineBasicBlock &MBB) {
|
void SplitEditor::leaveIntvAtTop(MachineBasicBlock &MBB) {
|
||||||
|
@ -528,6 +609,7 @@ void SplitEditor::closeIntv() {
|
||||||
DEBUG(dbgs() << " dup2 " << *dupli_ << '\n');
|
DEBUG(dbgs() << " dup2 " << *dupli_ << '\n');
|
||||||
}
|
}
|
||||||
openli_ = 0;
|
openli_ = 0;
|
||||||
|
valueMap_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// rewrite - after all the new live ranges have been created, rewrite
|
/// rewrite - after all the new live ranges have been created, rewrite
|
||||||
|
@ -620,3 +702,49 @@ bool SplitEditor::splitAroundLoop(const MachineLoop *Loop) {
|
||||||
return dupli_;
|
return dupli_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Single Block Splitting
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
/// splitSingleBlocks - Split curli into a separate live interval inside each
|
||||||
|
/// 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 SplitEditor::splitSingleBlocks(const SplitAnalysis::BlockPtrSet &Blocks) {
|
||||||
|
DEBUG(dbgs() << "splitSingleBlocks for " << Blocks.size() << " blocks.\n");
|
||||||
|
// Determine the first and last instruction using curli in each block.
|
||||||
|
typedef std::pair<SlotIndex,SlotIndex> IndexPair;
|
||||||
|
typedef DenseMap<const MachineBasicBlock*,IndexPair> IndexPairMap;
|
||||||
|
IndexPairMap MBBRange;
|
||||||
|
for (SplitAnalysis::InstrPtrSet::const_iterator I = sa_.usingInstrs_.begin(),
|
||||||
|
E = sa_.usingInstrs_.end(); I != E; ++I) {
|
||||||
|
const MachineBasicBlock *MBB = (*I)->getParent();
|
||||||
|
if (!Blocks.count(MBB))
|
||||||
|
continue;
|
||||||
|
SlotIndex Idx = lis_.getInstructionIndex(*I);
|
||||||
|
DEBUG(dbgs() << "BB#" << MBB->getNumber() << '\t' << Idx << '\t' << **I);
|
||||||
|
IndexPair &IP = MBBRange[MBB];
|
||||||
|
if (!IP.first.isValid() || Idx < IP.first)
|
||||||
|
IP.first = Idx;
|
||||||
|
if (!IP.second.isValid() || Idx > IP.second)
|
||||||
|
IP.second = Idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new interval for each block.
|
||||||
|
for (SplitAnalysis::BlockPtrSet::const_iterator I = Blocks.begin(),
|
||||||
|
E = Blocks.end(); I != E; ++I) {
|
||||||
|
IndexPair &IP = MBBRange[*I];
|
||||||
|
DEBUG(dbgs() << "Splitting for BB#" << (*I)->getNumber() << ": ["
|
||||||
|
<< IP.first << ';' << IP.second << ")\n");
|
||||||
|
assert(IP.first.isValid() && IP.second.isValid());
|
||||||
|
|
||||||
|
openIntv();
|
||||||
|
enterIntvBefore(IP.first);
|
||||||
|
useIntv(IP.first.getBaseIndex(), IP.second.getBoundaryIndex());
|
||||||
|
leaveIntvAfter(IP.second);
|
||||||
|
closeIntv();
|
||||||
|
}
|
||||||
|
rewrite();
|
||||||
|
return dupli_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,10 +37,6 @@ public:
|
||||||
const MachineLoopInfo &loops_;
|
const MachineLoopInfo &loops_;
|
||||||
const TargetInstrInfo &tii_;
|
const TargetInstrInfo &tii_;
|
||||||
|
|
||||||
private:
|
|
||||||
// Current live interval.
|
|
||||||
const LiveInterval *curli_;
|
|
||||||
|
|
||||||
// Instructions using the the current register.
|
// Instructions using the the current register.
|
||||||
typedef SmallPtrSet<const MachineInstr*, 16> InstrPtrSet;
|
typedef SmallPtrSet<const MachineInstr*, 16> InstrPtrSet;
|
||||||
InstrPtrSet usingInstrs_;
|
InstrPtrSet usingInstrs_;
|
||||||
|
@ -53,6 +49,10 @@ private:
|
||||||
typedef SmallPtrSet<const MachineLoop*, 16> LoopPtrSet;
|
typedef SmallPtrSet<const MachineLoop*, 16> LoopPtrSet;
|
||||||
LoopPtrSet usingLoops_;
|
LoopPtrSet usingLoops_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Current live interval.
|
||||||
|
const LiveInterval *curli_;
|
||||||
|
|
||||||
// Sumarize statistics by counting instructions using curli_.
|
// Sumarize statistics by counting instructions using curli_.
|
||||||
void analyzeUses();
|
void analyzeUses();
|
||||||
|
|
||||||
|
@ -118,6 +118,11 @@ public:
|
||||||
/// getBestSplitLoop - Return the loop where curli may best be split to a
|
/// getBestSplitLoop - Return the loop where curli may best be split to a
|
||||||
/// separate register, or NULL.
|
/// separate register, or NULL.
|
||||||
const MachineLoop *getBestSplitLoop();
|
const MachineLoop *getBestSplitLoop();
|
||||||
|
|
||||||
|
/// getMultiUseBlocks - Add basic blocks to Blocks that may benefit from
|
||||||
|
/// having curli split to a new live interval. Return true if Blocks can be
|
||||||
|
/// passed to SplitEditor::splitSingleBlocks.
|
||||||
|
bool getMultiUseBlocks(BlockPtrSet &Blocks);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// SplitEditor - Edit machine code and LiveIntervals for live range
|
/// SplitEditor - Edit machine code and LiveIntervals for live range
|
||||||
|
@ -156,7 +161,7 @@ class SplitEditor {
|
||||||
/// getDupLI - Ensure dupli is created and return it.
|
/// getDupLI - Ensure dupli is created and return it.
|
||||||
LiveInterval *getDupLI();
|
LiveInterval *getDupLI();
|
||||||
|
|
||||||
/// valueMap_ - Map values in dupli to values in openIntv. These are direct 1-1
|
/// valueMap_ - Map values in cupli to values in openli. These are direct 1-1
|
||||||
/// mappings, and do not include values created by inserted copies.
|
/// mappings, and do not include values created by inserted copies.
|
||||||
DenseMap<const VNInfo*, VNInfo*> valueMap_;
|
DenseMap<const VNInfo*, VNInfo*> valueMap_;
|
||||||
|
|
||||||
|
@ -192,6 +197,10 @@ public:
|
||||||
/// Create a new virtual register and live interval.
|
/// Create a new virtual register and live interval.
|
||||||
void openIntv();
|
void openIntv();
|
||||||
|
|
||||||
|
/// enterIntvBefore - Enter openli before the instruction at Idx. If curli is
|
||||||
|
/// not live before Idx, a COPY is not inserted.
|
||||||
|
void enterIntvBefore(SlotIndex Idx);
|
||||||
|
|
||||||
/// enterIntvAtEnd - Enter openli at the end of MBB.
|
/// enterIntvAtEnd - Enter openli at the end of MBB.
|
||||||
/// PhiMBB is a successor inside openli where a PHI value is created.
|
/// PhiMBB is a successor inside openli where a PHI value is created.
|
||||||
/// Currently, all entries must share the same PhiMBB.
|
/// Currently, all entries must share the same PhiMBB.
|
||||||
|
@ -203,6 +212,9 @@ public:
|
||||||
/// useIntv - indicate that all instructions in range should use openli.
|
/// useIntv - indicate that all instructions in range should use openli.
|
||||||
void useIntv(SlotIndex Start, SlotIndex End);
|
void useIntv(SlotIndex Start, SlotIndex End);
|
||||||
|
|
||||||
|
/// leaveIntvAfter - Leave openli after the instruction at Idx.
|
||||||
|
void leaveIntvAfter(SlotIndex Idx);
|
||||||
|
|
||||||
/// leaveIntvAtTop - Leave the interval at the top of MBB.
|
/// leaveIntvAtTop - Leave the interval at the top of MBB.
|
||||||
/// Currently, only one value can leave the interval.
|
/// Currently, only one value can leave the interval.
|
||||||
void leaveIntvAtTop(MachineBasicBlock &MBB);
|
void leaveIntvAtTop(MachineBasicBlock &MBB);
|
||||||
|
@ -222,6 +234,10 @@ public:
|
||||||
/// curli is still intact, and needs to be spilled or split further.
|
/// curli is still intact, and needs to be spilled or split further.
|
||||||
bool splitAroundLoop(const MachineLoop*);
|
bool splitAroundLoop(const MachineLoop*);
|
||||||
|
|
||||||
|
/// splitSingleBlocks - Split curli into a separate live interval inside each
|
||||||
|
/// 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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue