1
0
mirror of https://github.com/c64scene-ar/llvm-6502.git synced 2025-04-22 00:37:49 +00:00

LiveIntervalAnalysis: Update SubRanges in shrinkToUses().

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@223880 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Matthias Braun 2014-12-10 01:12:18 +00:00
parent 6cdf1d9a8f
commit e59399c28c
2 changed files with 160 additions and 80 deletions
include/llvm/CodeGen
lib/CodeGen

@ -393,14 +393,17 @@ namespace llvm {
/// Compute RegMaskSlots and RegMaskBits.
void computeRegMasks();
/// \brief Walk the values in the given interval and compute which ones
/// are dead. Dead values are not deleted, however:
/// \brief Walk the values in the @p LR live range and compute which ones
/// are dead in live range @p Segments. Dead values are not deleted,
/// however:
/// - Dead PHIDef values are marked as unused.
/// - New dead machine instructions are added to the dead vector.
/// - if @p dead != nullptr then dead operands are marked as such and
/// completely dead machine instructions are added to the @p dead vector.
/// - CanSeparate is set to true if the interval may have been separated
/// into multiple connected components.
void computeDeadValues(LiveInterval *li, LiveRange &LR, bool *CanSeparate,
SmallVectorImpl<MachineInstr*> *dead);
void computeDeadValues(LiveRange &Segments, LiveRange &LR,
bool *CanSeparate = nullptr, unsigned Reg = 0,
SmallVectorImpl<MachineInstr*> *dead = nullptr);
static LiveInterval* createInterval(unsigned Reg);
@ -411,6 +414,12 @@ namespace llvm {
void computeRegUnitRange(LiveRange&, unsigned Unit);
void computeVirtRegInterval(LiveInterval&);
/// Specialized version of
/// shrinkToUses(LiveInterval *li, SmallVectorImpl<MachineInstr*> *dead)
/// that works on a subregister live range and only looks at uses matching
/// the lane mask of the subregister range.
bool shrinkToUses(LiveInterval::SubRange &SR, unsigned Reg);
class HMEditor;
};
} // End llvm namespace

@ -185,7 +185,7 @@ void LiveIntervals::computeVirtRegInterval(LiveInterval &LI) {
LRCalc->reset(MF, getSlotIndexes(), DomTree, &getVNInfoAllocator());
LRCalc->createDeadDefs(LI);
LRCalc->extendToUses(LI);
computeDeadValues(&LI, LI, nullptr, nullptr);
computeDeadValues(LI, LI);
}
void LiveIntervals::computeVirtRegs() {
@ -312,6 +312,70 @@ void LiveIntervals::computeLiveInRegUnits() {
}
static void createSegmentsForValues(LiveRange &LR,
iterator_range<LiveInterval::vni_iterator> VNIs) {
for (auto VNI : VNIs) {
if (VNI->isUnused())
continue;
SlotIndex Def = VNI->def;
LR.addSegment(LiveRange::Segment(Def, Def.getDeadSlot(), VNI));
}
}
typedef SmallVector<std::pair<SlotIndex, VNInfo*>, 16> ShrinkToUsesWorkList;
static void extendSegmentsToUses(LiveRange &LR, const SlotIndexes &Indexes,
ShrinkToUsesWorkList &WorkList,
const LiveRange &OldRange) {
// Keep track of the PHIs that are in use.
SmallPtrSet<VNInfo*, 8> UsedPHIs;
// Blocks that have already been added to WorkList as live-out.
SmallPtrSet<MachineBasicBlock*, 16> LiveOut;
// Extend intervals to reach all uses in WorkList.
while (!WorkList.empty()) {
SlotIndex Idx = WorkList.back().first;
VNInfo *VNI = WorkList.back().second;
WorkList.pop_back();
const MachineBasicBlock *MBB = Indexes.getMBBFromIndex(Idx.getPrevSlot());
SlotIndex BlockStart = Indexes.getMBBStartIdx(MBB);
// Extend the live range for VNI to be live at Idx.
if (VNInfo *ExtVNI = LR.extendInBlock(BlockStart, Idx)) {
assert(ExtVNI == VNI && "Unexpected existing value number");
(void)ExtVNI;
// Is this a PHIDef we haven't seen before?
if (!VNI->isPHIDef() || VNI->def != BlockStart ||
!UsedPHIs.insert(VNI).second)
continue;
// The PHI is live, make sure the predecessors are live-out.
for (auto &Pred : MBB->predecessors()) {
if (!LiveOut.insert(Pred).second)
continue;
SlotIndex Stop = Indexes.getMBBEndIdx(Pred);
// A predecessor is not required to have a live-out value for a PHI.
if (VNInfo *PVNI = OldRange.getVNInfoBefore(Stop))
WorkList.push_back(std::make_pair(Stop, PVNI));
}
continue;
}
// VNI is live-in to MBB.
DEBUG(dbgs() << " live-in at " << BlockStart << '\n');
LR.addSegment(LiveRange::Segment(BlockStart, Idx, VNI));
// Make sure VNI is live-out from the predecessors.
for (auto &Pred : MBB->predecessors()) {
if (!LiveOut.insert(Pred).second)
continue;
SlotIndex Stop = Indexes.getMBBEndIdx(Pred);
assert(OldRange.getVNInfoBefore(Stop) == VNI &&
"Wrong value out of predecessor");
WorkList.push_back(std::make_pair(Stop, VNI));
}
}
}
/// shrinkToUses - After removing some uses of a register, shrink its live
/// range to just the remaining uses. This method does not compute reaching
/// defs for new uses, and it doesn't remove dead defs.
@ -320,11 +384,15 @@ bool LiveIntervals::shrinkToUses(LiveInterval *li,
DEBUG(dbgs() << "Shrink: " << *li << '\n');
assert(TargetRegisterInfo::isVirtualRegister(li->reg)
&& "Can only shrink virtual registers");
// Find all the values used, including PHI kills.
SmallVector<std::pair<SlotIndex, VNInfo*>, 16> WorkList;
// Blocks that have already been added to WorkList as live-out.
SmallPtrSet<MachineBasicBlock*, 16> LiveOut;
// Shrink subregister live ranges.
for (LiveInterval::subrange_iterator I = li->subrange_begin(),
E = li->subrange_end(); I != E; ++I) {
shrinkToUses(*I, li->reg);
}
// Find all the values used, including PHI kills.
ShrinkToUsesWorkList WorkList;
// Visit all instructions reading li->reg.
for (MachineRegisterInfo::reg_instr_iterator
@ -355,65 +423,12 @@ bool LiveIntervals::shrinkToUses(LiveInterval *li,
// Create new live ranges with only minimal live segments per def.
LiveRange NewLR;
for (LiveInterval::vni_iterator I = li->vni_begin(), E = li->vni_end();
I != E; ++I) {
VNInfo *VNI = *I;
if (VNI->isUnused())
continue;
NewLR.addSegment(LiveRange::Segment(VNI->def, VNI->def.getDeadSlot(), VNI));
}
// Keep track of the PHIs that are in use.
SmallPtrSet<VNInfo*, 8> UsedPHIs;
// Extend intervals to reach all uses in WorkList.
while (!WorkList.empty()) {
SlotIndex Idx = WorkList.back().first;
VNInfo *VNI = WorkList.back().second;
WorkList.pop_back();
const MachineBasicBlock *MBB = getMBBFromIndex(Idx.getPrevSlot());
SlotIndex BlockStart = getMBBStartIdx(MBB);
// Extend the live range for VNI to be live at Idx.
if (VNInfo *ExtVNI = NewLR.extendInBlock(BlockStart, Idx)) {
(void)ExtVNI;
assert(ExtVNI == VNI && "Unexpected existing value number");
// Is this a PHIDef we haven't seen before?
if (!VNI->isPHIDef() || VNI->def != BlockStart ||
!UsedPHIs.insert(VNI).second)
continue;
// The PHI is live, make sure the predecessors are live-out.
for (MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(),
PE = MBB->pred_end(); PI != PE; ++PI) {
if (!LiveOut.insert(*PI).second)
continue;
SlotIndex Stop = getMBBEndIdx(*PI);
// A predecessor is not required to have a live-out value for a PHI.
if (VNInfo *PVNI = li->getVNInfoBefore(Stop))
WorkList.push_back(std::make_pair(Stop, PVNI));
}
continue;
}
// VNI is live-in to MBB.
DEBUG(dbgs() << " live-in at " << BlockStart << '\n');
NewLR.addSegment(LiveRange::Segment(BlockStart, Idx, VNI));
// Make sure VNI is live-out from the predecessors.
for (MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(),
PE = MBB->pred_end(); PI != PE; ++PI) {
if (!LiveOut.insert(*PI).second)
continue;
SlotIndex Stop = getMBBEndIdx(*PI);
assert(li->getVNInfoBefore(Stop) == VNI &&
"Wrong value out of predecessor");
WorkList.push_back(std::make_pair(Stop, VNI));
}
}
createSegmentsForValues(NewLR, make_range(li->vni_begin(), li->vni_end()));
extendSegmentsToUses(NewLR, *Indexes, WorkList, *li);
// Handle dead values.
bool CanSeparate = false;
computeDeadValues(li, NewLR, &CanSeparate, dead);
bool CanSeparate;
computeDeadValues(NewLR, *li, &CanSeparate, li->reg, dead);
// Move the trimmed segments back.
li->segments.swap(NewLR.segments);
@ -421,37 +436,93 @@ bool LiveIntervals::shrinkToUses(LiveInterval *li,
return CanSeparate;
}
void LiveIntervals::computeDeadValues(LiveInterval *li,
LiveRange &LR,
bool *CanSeparate,
void LiveIntervals::computeDeadValues(LiveRange &Segments, LiveRange &LR,
bool *CanSeparateRes, unsigned Reg,
SmallVectorImpl<MachineInstr*> *dead) {
for (LiveInterval::vni_iterator I = li->vni_begin(), E = li->vni_end();
I != E; ++I) {
VNInfo *VNI = *I;
bool CanSeparate = false;
for (auto VNI : make_range(LR.vni_begin(), LR.vni_end())) {
if (VNI->isUnused())
continue;
LiveRange::iterator LRI = LR.FindSegmentContaining(VNI->def);
assert(LRI != LR.end() && "Missing segment for PHI");
LiveRange::iterator LRI = Segments.FindSegmentContaining(VNI->def);
assert(LRI != Segments.end() && "Missing segment for PHI");
if (LRI->end != VNI->def.getDeadSlot())
continue;
if (VNI->isPHIDef()) {
// This is a dead PHI. Remove it.
VNI->markUnused();
LR.removeSegment(LRI->start, LRI->end);
Segments.removeSegment(LRI->start, LRI->end);
DEBUG(dbgs() << "Dead PHI at " << VNI->def << " may separate interval\n");
if (CanSeparate)
*CanSeparate = true;
} else {
CanSeparate = true;
} else if (dead != nullptr) {
// This is a dead def. Make sure the instruction knows.
MachineInstr *MI = getInstructionFromIndex(VNI->def);
assert(MI && "No instruction defining live value");
MI->addRegisterDead(li->reg, TRI);
MI->addRegisterDead(Reg, TRI);
if (dead && MI->allDefsAreDead()) {
DEBUG(dbgs() << "All defs dead: " << VNI->def << '\t' << *MI);
dead->push_back(MI);
}
}
}
if (CanSeparateRes != nullptr)
*CanSeparateRes = CanSeparate;
}
bool LiveIntervals::shrinkToUses(LiveInterval::SubRange &SR, unsigned Reg)
{
DEBUG(dbgs() << "Shrink: " << SR << '\n');
assert(TargetRegisterInfo::isVirtualRegister(Reg)
&& "Can only shrink virtual registers");
// Find all the values used, including PHI kills.
ShrinkToUsesWorkList WorkList;
// Visit all instructions reading Reg.
SlotIndex LastIdx;
for (MachineOperand &MO : MRI->reg_operands(Reg)) {
MachineInstr *UseMI = MO.getParent();
if (UseMI->isDebugValue())
continue;
// Maybe the operand is for a subregister we don't care about.
unsigned SubReg = MO.getSubReg();
if (SubReg != 0) {
unsigned SubRegMask = TRI->getSubRegIndexLaneMask(SubReg);
if ((SubRegMask & SR.LaneMask) == 0)
continue;
}
// We only need to visit each instruction once.
SlotIndex Idx = getInstructionIndex(UseMI).getRegSlot();
if (Idx == LastIdx)
continue;
LastIdx = Idx;
LiveQueryResult LRQ = SR.Query(Idx);
VNInfo *VNI = LRQ.valueIn();
// For Subranges it is possible that only undef values are left in that
// part of the subregister, so there is no real liverange at the use
if (!VNI)
continue;
// Special case: An early-clobber tied operand reads and writes the
// register one slot early.
if (VNInfo *DefVNI = LRQ.valueDefined())
Idx = DefVNI->def;
WorkList.push_back(std::make_pair(Idx, VNI));
}
// Create a new live ranges with only minimal live segments per def.
LiveRange NewLR;
createSegmentsForValues(NewLR, make_range(SR.vni_begin(), SR.vni_end()));
extendSegmentsToUses(NewLR, *Indexes, WorkList, SR);
// Handle dead values.
bool CanSeparate;
computeDeadValues(NewLR, SR, &CanSeparate);
// Move the trimmed ranges back.
SR.segments.swap(NewLR.segments);
DEBUG(dbgs() << "Shrunk: " << SR << '\n');
return CanSeparate;
}
void LiveIntervals::extendToIndices(LiveRange &LR,