MI Sched: Track live-thru registers.

When registers must be live throughout the scheduling region, increase
the limit for the register class. Once we exceed the original limit,
they will be spilled, and there's no point further reducing pressure.

This isn't a perfect heuristics but avoids a situation where the
scheduler could become trapped by trying to achieve the impossible.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@187436 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Andrew Trick 2013-07-30 19:59:12 +00:00
parent 1e46fcd989
commit d71efffdcf
3 changed files with 101 additions and 15 deletions

View File

@ -187,6 +187,9 @@ class RegPressureTracker {
/// or RegisterPressure. If requireIntervals is false, LIS are ignored. /// or RegisterPressure. If requireIntervals is false, LIS are ignored.
bool RequireIntervals; bool RequireIntervals;
/// True if UntiedDefs will be populated.
bool TrackUntiedDefs;
/// Register pressure corresponds to liveness before this instruction /// Register pressure corresponds to liveness before this instruction
/// iterator. It may point to the end of the block or a DebugValue rather than /// iterator. It may point to the end of the block or a DebugValue rather than
/// an instruction. /// an instruction.
@ -198,16 +201,24 @@ class RegPressureTracker {
/// Set of live registers. /// Set of live registers.
LiveRegSet LiveRegs; LiveRegSet LiveRegs;
/// Set of vreg defs that start a live range.
SparseSet<unsigned, VirtReg2IndexFunctor> UntiedDefs;
/// Live-through pressure.
std::vector<unsigned> LiveThruPressure;
public: public:
RegPressureTracker(IntervalPressure &rp) : RegPressureTracker(IntervalPressure &rp) :
MF(0), TRI(0), RCI(0), LIS(0), MBB(0), P(rp), RequireIntervals(true) {} MF(0), TRI(0), RCI(0), LIS(0), MBB(0), P(rp), RequireIntervals(true),
TrackUntiedDefs(false) {}
RegPressureTracker(RegionPressure &rp) : RegPressureTracker(RegionPressure &rp) :
MF(0), TRI(0), RCI(0), LIS(0), MBB(0), P(rp), RequireIntervals(false) {} MF(0), TRI(0), RCI(0), LIS(0), MBB(0), P(rp), RequireIntervals(false),
TrackUntiedDefs(false) {}
void init(const MachineFunction *mf, const RegisterClassInfo *rci, void init(const MachineFunction *mf, const RegisterClassInfo *rci,
const LiveIntervals *lis, const MachineBasicBlock *mbb, const LiveIntervals *lis, const MachineBasicBlock *mbb,
MachineBasicBlock::const_iterator pos); MachineBasicBlock::const_iterator pos,
bool ShouldTrackUntiedDefs = false);
/// Force liveness of virtual registers or physical register /// Force liveness of virtual registers or physical register
/// units. Particularly useful to initialize the livein/out state of the /// units. Particularly useful to initialize the livein/out state of the
@ -236,6 +247,17 @@ public:
/// Finalize the region boundaries and recored live ins and live outs. /// Finalize the region boundaries and recored live ins and live outs.
void closeRegion(); void closeRegion();
/// Initialize the LiveThru pressure set based on the untied defs found in
/// RPTracker.
void initLiveThru(const RegPressureTracker &RPTracker);
/// Copy an existing live thru pressure result.
void initLiveThru(ArrayRef<unsigned> PressureSet) {
LiveThruPressure.assign(PressureSet.begin(), PressureSet.end());
}
ArrayRef<unsigned> getLiveThru() const { return LiveThruPressure; }
/// Get the resulting register pressure over the traversed region. /// Get the resulting register pressure over the traversed region.
/// This result is complete if either advance() or recede() has returned true, /// This result is complete if either advance() or recede() has returned true,
/// or if closeRegion() was explicitly invoked. /// or if closeRegion() was explicitly invoked.
@ -308,6 +330,10 @@ public:
return getDownwardPressure(MI, PressureResult, MaxPressureResult); return getDownwardPressure(MI, PressureResult, MaxPressureResult);
} }
bool hasUntiedDef(unsigned VirtReg) const {
return UntiedDefs.count(VirtReg);
}
void dump() const; void dump() const;
protected: protected:
@ -319,6 +345,11 @@ protected:
void bumpUpwardPressure(const MachineInstr *MI); void bumpUpwardPressure(const MachineInstr *MI);
void bumpDownwardPressure(const MachineInstr *MI); void bumpDownwardPressure(const MachineInstr *MI);
}; };
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
void dumpRegSetPressure(ArrayRef<unsigned> SetPressure,
const TargetRegisterInfo *TRI);
#endif
} // end namespace llvm } // end namespace llvm
#endif #endif

View File

@ -464,7 +464,7 @@ void ScheduleDAGMI::initRegPressure() {
// Close the RPTracker to finalize live ins. // Close the RPTracker to finalize live ins.
RPTracker.closeRegion(); RPTracker.closeRegion();
DEBUG(RPTracker.getPressure().dump(TRI)); DEBUG(RPTracker.dump());
// Initialize the live ins and live outs. // Initialize the live ins and live outs.
TopRPTracker.addLiveRegs(RPTracker.getPressure().LiveInRegs); TopRPTracker.addLiveRegs(RPTracker.getPressure().LiveInRegs);
@ -476,6 +476,13 @@ void ScheduleDAGMI::initRegPressure() {
TopRPTracker.closeTop(); TopRPTracker.closeTop();
BotRPTracker.closeBottom(); BotRPTracker.closeBottom();
BotRPTracker.initLiveThru(RPTracker);
if (!BotRPTracker.getLiveThru().empty()) {
TopRPTracker.initLiveThru(BotRPTracker.getLiveThru());
DEBUG(dbgs() << "Live Thru: ";
dumpRegSetPressure(BotRPTracker.getLiveThru(), TRI));
};
// Account for liveness generated by the region boundary. // Account for liveness generated by the region boundary.
if (LiveRegionEnd != RegionEnd) if (LiveRegionEnd != RegionEnd)
BotRPTracker.recede(); BotRPTracker.recede();
@ -579,7 +586,8 @@ void ScheduleDAGMI::schedule() {
/// Build the DAG and setup three register pressure trackers. /// Build the DAG and setup three register pressure trackers.
void ScheduleDAGMI::buildDAGWithRegPressure() { void ScheduleDAGMI::buildDAGWithRegPressure() {
// Initialize the register pressure tracker used by buildSchedGraph. // Initialize the register pressure tracker used by buildSchedGraph.
RPTracker.init(&MF, RegClassInfo, LIS, BB, LiveRegionEnd); RPTracker.init(&MF, RegClassInfo, LIS, BB, LiveRegionEnd,
/*TrackUntiedDefs=*/true);
// Account for liveness generate by the region boundary. // Account for liveness generate by the region boundary.
if (LiveRegionEnd != RegionEnd) if (LiveRegionEnd != RegionEnd)

View File

@ -76,17 +76,22 @@ void RegisterPressure::decrease(unsigned Reg, const TargetRegisterInfo *TRI,
} }
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
static void dumpSetPressure(const std::vector<unsigned> &SetPressure, void llvm::dumpRegSetPressure(ArrayRef<unsigned> SetPressure,
const TargetRegisterInfo *TRI) { const TargetRegisterInfo *TRI) {
bool Empty = true;
for (unsigned i = 0, e = SetPressure.size(); i < e; ++i) { for (unsigned i = 0, e = SetPressure.size(); i < e; ++i) {
if (SetPressure[i] != 0) if (SetPressure[i] != 0) {
dbgs() << TRI->getRegPressureSetName(i) << "=" << SetPressure[i] << '\n'; dbgs() << TRI->getRegPressureSetName(i) << "=" << SetPressure[i] << '\n';
Empty = false;
}
} }
if (Empty)
dbgs() << "\n";
} }
void RegisterPressure::dump(const TargetRegisterInfo *TRI) const { void RegisterPressure::dump(const TargetRegisterInfo *TRI) const {
dbgs() << "Max Pressure: "; dbgs() << "Max Pressure: ";
dumpSetPressure(MaxSetPressure, TRI); dumpRegSetPressure(MaxSetPressure, TRI);
dbgs() << "Live In: "; dbgs() << "Live In: ";
for (unsigned i = 0, e = LiveInRegs.size(); i < e; ++i) for (unsigned i = 0, e = LiveInRegs.size(); i < e; ++i)
dbgs() << PrintReg(LiveInRegs[i], TRI) << " "; dbgs() << PrintReg(LiveInRegs[i], TRI) << " ";
@ -98,8 +103,10 @@ void RegisterPressure::dump(const TargetRegisterInfo *TRI) const {
} }
void RegPressureTracker::dump() const { void RegPressureTracker::dump() const {
dbgs() << "Curr Pressure: "; if (!isTopClosed() || !isBottomClosed()) {
dumpSetPressure(CurrSetPressure, TRI); dbgs() << "Curr Pressure: ";
dumpRegSetPressure(CurrSetPressure, TRI);
}
P.dump(TRI); P.dump(TRI);
} }
#endif #endif
@ -200,13 +207,15 @@ void RegPressureTracker::init(const MachineFunction *mf,
const RegisterClassInfo *rci, const RegisterClassInfo *rci,
const LiveIntervals *lis, const LiveIntervals *lis,
const MachineBasicBlock *mbb, const MachineBasicBlock *mbb,
MachineBasicBlock::const_iterator pos) MachineBasicBlock::const_iterator pos,
bool ShouldTrackUntiedDefs)
{ {
MF = mf; MF = mf;
TRI = MF->getTarget().getRegisterInfo(); TRI = MF->getTarget().getRegisterInfo();
RCI = rci; RCI = rci;
MRI = &MF->getRegInfo(); MRI = &MF->getRegInfo();
MBB = mbb; MBB = mbb;
TrackUntiedDefs = ShouldTrackUntiedDefs;
if (RequireIntervals) { if (RequireIntervals) {
assert(lis && "IntervalPressure requires LiveIntervals"); assert(lis && "IntervalPressure requires LiveIntervals");
@ -215,6 +224,7 @@ void RegPressureTracker::init(const MachineFunction *mf,
CurrPos = pos; CurrPos = pos;
CurrSetPressure.assign(TRI->getNumRegPressureSets(), 0); CurrSetPressure.assign(TRI->getNumRegPressureSets(), 0);
LiveThruPressure.clear();
if (RequireIntervals) if (RequireIntervals)
static_cast<IntervalPressure&>(P).reset(); static_cast<IntervalPressure&>(P).reset();
@ -226,6 +236,9 @@ void RegPressureTracker::init(const MachineFunction *mf,
LiveRegs.PhysRegs.setUniverse(TRI->getNumRegs()); LiveRegs.PhysRegs.setUniverse(TRI->getNumRegs());
LiveRegs.VirtRegs.clear(); LiveRegs.VirtRegs.clear();
LiveRegs.VirtRegs.setUniverse(MRI->getNumVirtRegs()); LiveRegs.VirtRegs.setUniverse(MRI->getNumVirtRegs());
UntiedDefs.clear();
if (TrackUntiedDefs)
UntiedDefs.setUniverse(MRI->getNumVirtRegs());
} }
/// Does this pressure result have a valid top position and live ins. /// Does this pressure result have a valid top position and live ins.
@ -304,6 +317,25 @@ void RegPressureTracker::closeRegion() {
// If both top and bottom are closed, do nothing. // If both top and bottom are closed, do nothing.
} }
/// The register tracker is unaware of global liveness so ignores normal
/// live-thru ranges. However, two-address or coalesced chains can also lead
/// to live ranges with no holes. Count these to inform heuristics that we
/// can never drop below this pressure.
void RegPressureTracker::initLiveThru(const RegPressureTracker &RPTracker) {
LiveThruPressure.assign(TRI->getNumRegPressureSets(), 0);
assert(isBottomClosed() && "need bottom-up tracking to intialize.");
for (unsigned i = 0, e = P.LiveOutRegs.size(); i < e; ++i) {
unsigned Reg = P.LiveOutRegs[i];
if (TargetRegisterInfo::isVirtualRegister(Reg)
&& !RPTracker.hasUntiedDef(Reg)) {
const TargetRegisterClass *RC = MRI->getRegClass(Reg);
increaseSetPressure(LiveThruPressure, LiveThruPressure,
TRI->getRegClassPressureSets(RC),
TRI->getRegClassWeight(RC).RegWeight);
}
}
}
/// \brief Convenient wrapper for checking membership in RegisterOperands. /// \brief Convenient wrapper for checking membership in RegisterOperands.
static bool containsReg(ArrayRef<unsigned> Regs, unsigned Reg) { static bool containsReg(ArrayRef<unsigned> Regs, unsigned Reg) {
return std::find(Regs.begin(), Regs.end(), Reg) != Regs.end(); return std::find(Regs.begin(), Regs.end(), Reg) != Regs.end();
@ -459,11 +491,20 @@ bool RegPressureTracker::recede() {
LiveRegs.insert(Reg); LiveRegs.insert(Reg);
} }
} }
if (TrackUntiedDefs) {
for (unsigned i = 0, e = RegOpers.Defs.size(); i < e; ++i) {
unsigned Reg = RegOpers.Defs[i];
if (TargetRegisterInfo::isVirtualRegister(Reg) && !LiveRegs.contains(Reg))
UntiedDefs.insert(Reg);
}
}
return true; return true;
} }
/// Advance across the current instruction. /// Advance across the current instruction.
bool RegPressureTracker::advance() { bool RegPressureTracker::advance() {
assert(!TrackUntiedDefs && "unsupported mode");
// Check for the bottom of the analyzable region. // Check for the bottom of the analyzable region.
if (CurrPos == MBB->end()) { if (CurrPos == MBB->end()) {
closeRegion(); closeRegion();
@ -533,7 +574,8 @@ bool RegPressureTracker::advance() {
static void computeExcessPressureDelta(ArrayRef<unsigned> OldPressureVec, static void computeExcessPressureDelta(ArrayRef<unsigned> OldPressureVec,
ArrayRef<unsigned> NewPressureVec, ArrayRef<unsigned> NewPressureVec,
RegPressureDelta &Delta, RegPressureDelta &Delta,
const RegisterClassInfo *RCI) { const RegisterClassInfo *RCI,
ArrayRef<unsigned> LiveThruPressureVec) {
int ExcessUnits = 0; int ExcessUnits = 0;
unsigned PSetID = ~0U; unsigned PSetID = ~0U;
for (unsigned i = 0, e = OldPressureVec.size(); i < e; ++i) { for (unsigned i = 0, e = OldPressureVec.size(); i < e; ++i) {
@ -544,6 +586,9 @@ static void computeExcessPressureDelta(ArrayRef<unsigned> OldPressureVec,
continue; continue;
// Only consider change beyond the limit. // Only consider change beyond the limit.
unsigned Limit = RCI->getRegPressureSetLimit(i); unsigned Limit = RCI->getRegPressureSetLimit(i);
if (!LiveThruPressureVec.empty())
Limit += LiveThruPressureVec[i];
if (Limit > POld) { if (Limit > POld) {
if (Limit > PNew) if (Limit > PNew)
PDiff = 0; // Under the limit PDiff = 0; // Under the limit
@ -665,7 +710,8 @@ getMaxUpwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta,
bumpUpwardPressure(MI); bumpUpwardPressure(MI);
computeExcessPressureDelta(SavedPressure, CurrSetPressure, Delta, RCI); computeExcessPressureDelta(SavedPressure, CurrSetPressure, Delta, RCI,
LiveThruPressure);
computeMaxPressureDelta(SavedMaxPressure, P.MaxSetPressure, CriticalPSets, computeMaxPressureDelta(SavedMaxPressure, P.MaxSetPressure, CriticalPSets,
MaxPressureLimit, Delta); MaxPressureLimit, Delta);
assert(Delta.CriticalMax.UnitIncrease >= 0 && assert(Delta.CriticalMax.UnitIncrease >= 0 &&
@ -755,7 +801,8 @@ getMaxDownwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta,
bumpDownwardPressure(MI); bumpDownwardPressure(MI);
computeExcessPressureDelta(SavedPressure, CurrSetPressure, Delta, RCI); computeExcessPressureDelta(SavedPressure, CurrSetPressure, Delta, RCI,
LiveThruPressure);
computeMaxPressureDelta(SavedMaxPressure, P.MaxSetPressure, CriticalPSets, computeMaxPressureDelta(SavedMaxPressure, P.MaxSetPressure, CriticalPSets,
MaxPressureLimit, Delta); MaxPressureLimit, Delta);
assert(Delta.CriticalMax.UnitIncrease >= 0 && assert(Delta.CriticalMax.UnitIncrease >= 0 &&