/// or RegisterPressure. If requireIntervals is false, LIS are ignored.
bool RequireIntervals;
+ /// True if UntiedDefs will be populated.
+ bool TrackUntiedDefs;
+
/// Register pressure corresponds to liveness before this instruction
/// iterator. It may point to the end of the block or a DebugValue rather than
/// an instruction.
/// Set of live registers.
LiveRegSet LiveRegs;
+ /// Set of vreg defs that start a live range.
+ SparseSet<unsigned, VirtReg2IndexFunctor> UntiedDefs;
+ /// Live-through pressure.
+ std::vector<unsigned> LiveThruPressure;
+
public:
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) :
- 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,
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
/// units. Particularly useful to initialize the livein/out state of the
/// Finalize the region boundaries and recored live ins and live outs.
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.
/// This result is complete if either advance() or recede() has returned true,
/// or if closeRegion() was explicitly invoked.
return getDownwardPressure(MI, PressureResult, MaxPressureResult);
}
+ bool hasUntiedDef(unsigned VirtReg) const {
+ return UntiedDefs.count(VirtReg);
+ }
+
void dump() const;
protected:
void bumpUpwardPressure(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
#endif
// Close the RPTracker to finalize live ins.
RPTracker.closeRegion();
- DEBUG(RPTracker.getPressure().dump(TRI));
+ DEBUG(RPTracker.dump());
// Initialize the live ins and live outs.
TopRPTracker.addLiveRegs(RPTracker.getPressure().LiveInRegs);
TopRPTracker.closeTop();
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.
if (LiveRegionEnd != RegionEnd)
BotRPTracker.recede();
/// Build the DAG and setup three register pressure trackers.
void ScheduleDAGMI::buildDAGWithRegPressure() {
// 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.
if (LiveRegionEnd != RegionEnd)
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
-static void dumpSetPressure(const std::vector<unsigned> &SetPressure,
- const TargetRegisterInfo *TRI) {
+void llvm::dumpRegSetPressure(ArrayRef<unsigned> SetPressure,
+ const TargetRegisterInfo *TRI) {
+ bool Empty = true;
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';
+ Empty = false;
+ }
}
+ if (Empty)
+ dbgs() << "\n";
}
void RegisterPressure::dump(const TargetRegisterInfo *TRI) const {
dbgs() << "Max Pressure: ";
- dumpSetPressure(MaxSetPressure, TRI);
+ dumpRegSetPressure(MaxSetPressure, TRI);
dbgs() << "Live In: ";
for (unsigned i = 0, e = LiveInRegs.size(); i < e; ++i)
dbgs() << PrintReg(LiveInRegs[i], TRI) << " ";
}
void RegPressureTracker::dump() const {
- dbgs() << "Curr Pressure: ";
- dumpSetPressure(CurrSetPressure, TRI);
+ if (!isTopClosed() || !isBottomClosed()) {
+ dbgs() << "Curr Pressure: ";
+ dumpRegSetPressure(CurrSetPressure, TRI);
+ }
P.dump(TRI);
}
#endif
const RegisterClassInfo *rci,
const LiveIntervals *lis,
const MachineBasicBlock *mbb,
- MachineBasicBlock::const_iterator pos)
+ MachineBasicBlock::const_iterator pos,
+ bool ShouldTrackUntiedDefs)
{
MF = mf;
TRI = MF->getTarget().getRegisterInfo();
RCI = rci;
MRI = &MF->getRegInfo();
MBB = mbb;
+ TrackUntiedDefs = ShouldTrackUntiedDefs;
if (RequireIntervals) {
assert(lis && "IntervalPressure requires LiveIntervals");
CurrPos = pos;
CurrSetPressure.assign(TRI->getNumRegPressureSets(), 0);
+ LiveThruPressure.clear();
if (RequireIntervals)
static_cast<IntervalPressure&>(P).reset();
LiveRegs.PhysRegs.setUniverse(TRI->getNumRegs());
LiveRegs.VirtRegs.clear();
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.
// 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.
static bool containsReg(ArrayRef<unsigned> Regs, unsigned Reg) {
return std::find(Regs.begin(), Regs.end(), Reg) != Regs.end();
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;
}
/// Advance across the current instruction.
bool RegPressureTracker::advance() {
+ assert(!TrackUntiedDefs && "unsupported mode");
+
// Check for the bottom of the analyzable region.
if (CurrPos == MBB->end()) {
closeRegion();
static void computeExcessPressureDelta(ArrayRef<unsigned> OldPressureVec,
ArrayRef<unsigned> NewPressureVec,
RegPressureDelta &Delta,
- const RegisterClassInfo *RCI) {
+ const RegisterClassInfo *RCI,
+ ArrayRef<unsigned> LiveThruPressureVec) {
int ExcessUnits = 0;
unsigned PSetID = ~0U;
for (unsigned i = 0, e = OldPressureVec.size(); i < e; ++i) {
continue;
// Only consider change beyond the limit.
unsigned Limit = RCI->getRegPressureSetLimit(i);
+ if (!LiveThruPressureVec.empty())
+ Limit += LiveThruPressureVec[i];
+
if (Limit > POld) {
if (Limit > PNew)
PDiff = 0; // Under the limit
bumpUpwardPressure(MI);
- computeExcessPressureDelta(SavedPressure, CurrSetPressure, Delta, RCI);
+ computeExcessPressureDelta(SavedPressure, CurrSetPressure, Delta, RCI,
+ LiveThruPressure);
computeMaxPressureDelta(SavedMaxPressure, P.MaxSetPressure, CriticalPSets,
MaxPressureLimit, Delta);
assert(Delta.CriticalMax.UnitIncrease >= 0 &&
bumpDownwardPressure(MI);
- computeExcessPressureDelta(SavedPressure, CurrSetPressure, Delta, RCI);
+ computeExcessPressureDelta(SavedPressure, CurrSetPressure, Delta, RCI,
+ LiveThruPressure);
computeMaxPressureDelta(SavedMaxPressure, P.MaxSetPressure, CriticalPSets,
MaxPressureLimit, Delta);
assert(Delta.CriticalMax.UnitIncrease >= 0 &&