forked from OSchip/llvm-project
Create two BlockInfo entries when a live range is discontinuous through a block.
Delete the Kill and Def markers in BlockInfo. They are no longer necessary when BlockInfo describes a continuous live range. This only affects the relatively rare kind of basic block where a live range looks like this: |---x o---| Now live range splitting can pretend that it is looking at two blocks: |---x o---| This allows the code to be simplified a bit. llvm-svn: 132245
This commit is contained in:
parent
5cc91b2611
commit
fd3f71ef3a
|
@ -552,7 +552,7 @@ bool RAGreedy::addSplitConstraints(InterferenceCache::Cursor Intf,
|
|||
BC.Entry = SpillPlacement::MustSpill, ++Ins;
|
||||
else if (Intf.first() < BI.FirstUse)
|
||||
BC.Entry = SpillPlacement::PrefSpill, ++Ins;
|
||||
else if (Intf.first() < (BI.LiveThrough ? BI.LastUse : BI.Kill))
|
||||
else if (Intf.first() < BI.LastUse)
|
||||
++Ins;
|
||||
}
|
||||
|
||||
|
@ -562,7 +562,7 @@ bool RAGreedy::addSplitConstraints(InterferenceCache::Cursor Intf,
|
|||
BC.Exit = SpillPlacement::MustSpill, ++Ins;
|
||||
else if (Intf.last() > BI.LastUse)
|
||||
BC.Exit = SpillPlacement::PrefSpill, ++Ins;
|
||||
else if (Intf.last() > (BI.LiveThrough ? BI.FirstUse : BI.Def))
|
||||
else if (Intf.last() > BI.FirstUse)
|
||||
++Ins;
|
||||
}
|
||||
|
||||
|
@ -811,7 +811,7 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg,
|
|||
DEBUG(dbgs() << ", no interference");
|
||||
if (!BI.LiveThrough) {
|
||||
DEBUG(dbgs() << ", not live-through.\n");
|
||||
SE->useIntv(SE->enterIntvBefore(BI.Def), Stop);
|
||||
SE->useIntv(SE->enterIntvBefore(BI.FirstUse), Stop);
|
||||
continue;
|
||||
}
|
||||
if (!RegIn) {
|
||||
|
@ -828,10 +828,10 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg,
|
|||
// Block has interference.
|
||||
DEBUG(dbgs() << ", interference to " << Intf.last());
|
||||
|
||||
if (!BI.LiveThrough && Intf.last() <= BI.Def) {
|
||||
if (!BI.LiveThrough && Intf.last() <= BI.FirstUse) {
|
||||
// The interference doesn't reach the outgoing segment.
|
||||
DEBUG(dbgs() << " doesn't affect def from " << BI.Def << '\n');
|
||||
SE->useIntv(BI.Def, Stop);
|
||||
DEBUG(dbgs() << " doesn't affect def from " << BI.FirstUse << '\n');
|
||||
SE->useIntv(BI.FirstUse, Stop);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -887,7 +887,7 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg,
|
|||
DEBUG(dbgs() << ", no interference");
|
||||
if (!BI.LiveThrough) {
|
||||
DEBUG(dbgs() << ", killed in block.\n");
|
||||
SE->useIntv(Start, SE->leaveIntvAfter(BI.Kill));
|
||||
SE->useIntv(Start, SE->leaveIntvAfter(BI.LastUse));
|
||||
continue;
|
||||
}
|
||||
if (!RegOut) {
|
||||
|
@ -920,10 +920,10 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg,
|
|||
// Block has interference.
|
||||
DEBUG(dbgs() << ", interference from " << Intf.first());
|
||||
|
||||
if (!BI.LiveThrough && Intf.first() >= BI.Kill) {
|
||||
if (!BI.LiveThrough && Intf.first() >= BI.LastUse) {
|
||||
// The interference doesn't reach the outgoing segment.
|
||||
DEBUG(dbgs() << " doesn't affect kill at " << BI.Kill << '\n');
|
||||
SE->useIntv(Start, BI.Kill);
|
||||
DEBUG(dbgs() << " doesn't affect kill at " << BI.LastUse << '\n');
|
||||
SE->useIntv(Start, BI.LastUse);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ void SplitAnalysis::analyzeUses() {
|
|||
/// where CurLI is live.
|
||||
bool SplitAnalysis::calcLiveBlockInfo() {
|
||||
ThroughBlocks.resize(MF.getNumBlockIDs());
|
||||
NumThroughBlocks = 0;
|
||||
NumThroughBlocks = NumGapBlocks = 0;
|
||||
if (CurLI->empty())
|
||||
return true;
|
||||
|
||||
|
@ -164,55 +164,62 @@ bool SplitAnalysis::calcLiveBlockInfo() {
|
|||
SlotIndex Start, Stop;
|
||||
tie(Start, Stop) = LIS.getSlotIndexes()->getMBBRange(BI.MBB);
|
||||
|
||||
// LVI is the first live segment overlapping MBB.
|
||||
BI.LiveIn = LVI->start <= Start;
|
||||
if (!BI.LiveIn)
|
||||
BI.Def = LVI->start;
|
||||
|
||||
// Find the first and last uses in the block.
|
||||
bool Uses = UseI != UseE && *UseI < Stop;
|
||||
if (Uses) {
|
||||
// If the block contains no uses, the range must be live through. At one
|
||||
// point, SimpleRegisterCoalescing could create dangling ranges that ended
|
||||
// mid-block.
|
||||
if (UseI == UseE || *UseI >= Stop) {
|
||||
++NumThroughBlocks;
|
||||
ThroughBlocks.set(BI.MBB->getNumber());
|
||||
// The range shouldn't end mid-block if there are no uses. This shouldn't
|
||||
// happen.
|
||||
if (LVI->end < Stop)
|
||||
return false;
|
||||
} else {
|
||||
// This block has uses. Find the first and last uses in the block.
|
||||
BI.FirstUse = *UseI;
|
||||
assert(BI.FirstUse >= Start);
|
||||
do ++UseI;
|
||||
while (UseI != UseE && *UseI < Stop);
|
||||
BI.LastUse = UseI[-1];
|
||||
assert(BI.LastUse < Stop);
|
||||
}
|
||||
|
||||
// Look for gaps in the live range.
|
||||
bool hasGap = false;
|
||||
BI.LiveOut = true;
|
||||
while (LVI->end < Stop) {
|
||||
SlotIndex LastStop = LVI->end;
|
||||
if (++LVI == LVE || LVI->start >= Stop) {
|
||||
BI.Kill = LastStop;
|
||||
BI.LiveOut = false;
|
||||
break;
|
||||
}
|
||||
if (LastStop < LVI->start) {
|
||||
hasGap = true;
|
||||
BI.Kill = LastStop;
|
||||
BI.Def = LVI->start;
|
||||
}
|
||||
}
|
||||
// LVI is the first live segment overlapping MBB.
|
||||
BI.LiveIn = LVI->start <= Start;
|
||||
|
||||
// Don't set LiveThrough when the block has a gap.
|
||||
BI.LiveThrough = !hasGap && BI.LiveIn && BI.LiveOut;
|
||||
if (Uses)
|
||||
// Look for gaps in the live range.
|
||||
BI.LiveOut = true;
|
||||
while (LVI->end < Stop) {
|
||||
SlotIndex LastStop = LVI->end;
|
||||
if (++LVI == LVE || LVI->start >= Stop) {
|
||||
BI.LiveOut = false;
|
||||
break;
|
||||
}
|
||||
if (LastStop < LVI->start) {
|
||||
// There is a gap in the live range. Create duplicate entries for the
|
||||
// live-in snippet and the live-out snippet.
|
||||
++NumGapBlocks;
|
||||
|
||||
// Push the Live-in part.
|
||||
BI.LiveThrough = false;
|
||||
BI.LiveOut = false;
|
||||
UseBlocks.push_back(BI);
|
||||
UseBlocks.back().LastUse = LastStop;
|
||||
|
||||
// Set up BI for the live-out part.
|
||||
BI.LiveIn = false;
|
||||
BI.LiveOut = true;
|
||||
BI.FirstUse = LVI->start;
|
||||
}
|
||||
}
|
||||
|
||||
// Don't set LiveThrough when the block has a gap.
|
||||
BI.LiveThrough = BI.LiveIn && BI.LiveOut;
|
||||
UseBlocks.push_back(BI);
|
||||
else {
|
||||
++NumThroughBlocks;
|
||||
ThroughBlocks.set(BI.MBB->getNumber());
|
||||
}
|
||||
// FIXME: This should never happen. The live range stops or starts without a
|
||||
// corresponding use. An earlier pass did something wrong.
|
||||
if (!BI.LiveThrough && !Uses)
|
||||
return false;
|
||||
|
||||
// LVI is now at LVE or LVI->end >= Stop.
|
||||
if (LVI == LVE)
|
||||
break;
|
||||
// LVI is now at LVE or LVI->end >= Stop.
|
||||
if (LVI == LVE)
|
||||
break;
|
||||
}
|
||||
|
||||
// Live segment ends exactly at Stop. Move to the next segment.
|
||||
if (LVI->end == Stop && ++LVI == LVE)
|
||||
|
|
|
@ -63,17 +63,22 @@ public:
|
|||
/// 1. | o---x | Internal to block. Variable is only live in this block.
|
||||
/// 2. |---x | Live-in, kill.
|
||||
/// 3. | o---| Def, live-out.
|
||||
/// 4. |---x o---| Live-in, kill, def, live-out.
|
||||
/// 4. |---x o---| Live-in, kill, def, live-out. Counted by NumGapBlocks.
|
||||
/// 5. |---o---o---| Live-through with uses or defs.
|
||||
/// 6. |-----------| Live-through without uses. Transparent.
|
||||
/// 6. |-----------| Live-through without uses. Counted by NumThroughBlocks.
|
||||
///
|
||||
/// Two BlockInfo entries are created for template 4. One for the live-in
|
||||
/// segment, and one for the live-out segment. These entries look as if the
|
||||
/// block were split in the middle where the live range isn't live.
|
||||
///
|
||||
/// Live-through blocks without any uses don't get BlockInfo entries. They
|
||||
/// are simply listed in ThroughBlocks instead.
|
||||
///
|
||||
struct BlockInfo {
|
||||
MachineBasicBlock *MBB;
|
||||
SlotIndex FirstUse; ///< First instr using current reg.
|
||||
SlotIndex LastUse; ///< Last instr using current reg.
|
||||
SlotIndex Kill; ///< Interval end point inside block.
|
||||
SlotIndex Def; ///< Interval start point inside block.
|
||||
bool LiveThrough; ///< Live in whole block (Templ 5. or 6. above).
|
||||
bool LiveThrough; ///< Live in whole block (Templ 5. above).
|
||||
bool LiveIn; ///< Current reg is live in.
|
||||
bool LiveOut; ///< Current reg is live out.
|
||||
};
|
||||
|
@ -91,6 +96,10 @@ private:
|
|||
/// UseBlocks - Blocks where CurLI has uses.
|
||||
SmallVector<BlockInfo, 8> UseBlocks;
|
||||
|
||||
/// NumGapBlocks - Number of duplicate entries in UseBlocks for blocks where
|
||||
/// the live range has a gap.
|
||||
unsigned NumGapBlocks;
|
||||
|
||||
/// ThroughBlocks - Block numbers where CurLI is live through without uses.
|
||||
BitVector ThroughBlocks;
|
||||
|
||||
|
@ -160,7 +169,7 @@ public:
|
|||
|
||||
/// getNumLiveBlocks - Return the number of blocks where CurLI is live.
|
||||
unsigned getNumLiveBlocks() const {
|
||||
return getUseBlocks().size() + getNumThroughBlocks();
|
||||
return getUseBlocks().size() - NumGapBlocks + getNumThroughBlocks();
|
||||
}
|
||||
|
||||
/// countLiveBlocks - Return the number of blocks where li is live. This is
|
||||
|
|
Loading…
Reference in New Issue