#include "llvm/CodeGen/RegisterClassInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetMachine.h"
using namespace llvm;
}
}
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+LLVM_DUMP_METHOD
void llvm::dumpRegSetPressure(ArrayRef<unsigned> SetPressure,
const TargetRegisterInfo *TRI) {
bool Empty = true;
dbgs() << "\n";
}
+LLVM_DUMP_METHOD
void RegisterPressure::dump(const TargetRegisterInfo *TRI) const {
dbgs() << "Max Pressure: ";
dumpRegSetPressure(MaxSetPressure, TRI);
+}
+
+LLVM_DUMP_METHOD
+void RegPressureTracker::dump() const {
+ if (!isTopClosed() || !isBottomClosed()) {
+ dbgs() << "Curr Pressure: ";
+ dumpRegSetPressure(CurrSetPressure, TRI);
+ }
+ P.dump(TRI);
dbgs() << "Live In: ";
for (unsigned i = 0, e = LiveInRegs.size(); i < e; ++i)
- dbgs() << PrintReg(LiveInRegs[i], TRI) << " ";
+ dbgs() << PrintVRegOrUnit(LiveInRegs[i], TRI) << " ";
dbgs() << '\n';
dbgs() << "Live Out: ";
for (unsigned i = 0, e = LiveOutRegs.size(); i < e; ++i)
- dbgs() << PrintReg(LiveOutRegs[i], TRI) << " ";
+ dbgs() << PrintVRegOrUnit(LiveOutRegs[i], TRI) << " ";
dbgs() << '\n';
}
-void RegPressureTracker::dump() const {
- if (!isTopClosed() || !isBottomClosed()) {
- dbgs() << "Curr Pressure: ";
- dumpRegSetPressure(CurrSetPressure, TRI);
+void PressureDiff::dump(const TargetRegisterInfo &TRI) const {
+ for (const PressureChange &Change : *this) {
+ if (!Change.isValid() || Change.getUnitInc() == 0)
+ continue;
+ dbgs() << " " << TRI.getRegPressureSetName(Change.getPSet())
+ << " " << Change.getUnitInc();
}
- P.dump(TRI);
+ dbgs() << '\n';
}
-#endif
/// Increase the current pressure as impacted by these registers and bump
/// the high water mark if needed.
void IntervalPressure::reset() {
TopIdx = BottomIdx = SlotIndex();
MaxSetPressure.clear();
- LiveInRegs.clear();
- LiveOutRegs.clear();
}
/// Clear the result so it can be used for another round of pressure tracking.
void RegionPressure::reset() {
TopPos = BottomPos = MachineBasicBlock::const_iterator();
MaxSetPressure.clear();
- LiveInRegs.clear();
- LiveOutRegs.clear();
}
/// If the current top is not less than or equal to the next index, open it.
if (TopIdx <= NextTop)
return;
TopIdx = SlotIndex();
- LiveInRegs.clear();
}
/// If the current top is the previous instruction (before receding), open it.
if (TopPos != PrevTop)
return;
TopPos = MachineBasicBlock::const_iterator();
- LiveInRegs.clear();
}
/// If the current bottom is not greater than the previous index, open it.
if (BottomIdx > PrevBottom)
return;
BottomIdx = SlotIndex();
- LiveInRegs.clear();
}
/// If the current bottom is the previous instr (before advancing), open it.
if (BottomPos != PrevBottom)
return;
BottomPos = MachineBasicBlock::const_iterator();
- LiveInRegs.clear();
}
-const LiveInterval *RegPressureTracker::getInterval(unsigned Reg) const {
+const LiveRange *RegPressureTracker::getLiveRange(unsigned Reg) const {
if (TargetRegisterInfo::isVirtualRegister(Reg))
return &LIS->getInterval(Reg);
return LIS->getCachedRegUnit(Reg);
}
+void RegPressureTracker::reset() {
+ MBB = nullptr;
+ LIS = nullptr;
+
+ CurrSetPressure.clear();
+ LiveThruPressure.clear();
+ P.MaxSetPressure.clear();
+
+ if (RequireIntervals)
+ static_cast<IntervalPressure&>(P).reset();
+ else
+ static_cast<RegionPressure&>(P).reset();
+ LiveInRegs.clear();
+ LiveOutRegs.clear();
+
+ LiveRegs.PhysRegs.clear();
+ LiveRegs.VirtRegs.clear();
+ UntiedDefs.clear();
+}
+
/// Setup the RegPressureTracker.
///
/// TODO: Add support for pressure without LiveIntervals.
MachineBasicBlock::const_iterator pos,
bool ShouldTrackUntiedDefs)
{
+ reset();
+
MF = mf;
- TRI = MF->getTarget().getRegisterInfo();
+ TRI = MF->getSubtarget().getRegisterInfo();
RCI = rci;
MRI = &MF->getRegInfo();
MBB = mbb;
CurrPos = pos;
CurrSetPressure.assign(TRI->getNumRegPressureSets(), 0);
- LiveThruPressure.clear();
- if (RequireIntervals)
- static_cast<IntervalPressure&>(P).reset();
- else
- static_cast<RegionPressure&>(P).reset();
P.MaxSetPressure = CurrSetPressure;
- LiveRegs.PhysRegs.clear();
LiveRegs.PhysRegs.setUniverse(TRI->getNumRegs());
- LiveRegs.VirtRegs.clear();
LiveRegs.VirtRegs.setUniverse(MRI->getNumVirtRegs());
- UntiedDefs.clear();
if (TrackUntiedDefs)
UntiedDefs.setUniverse(MRI->getNumVirtRegs());
}
else
static_cast<RegionPressure&>(P).TopPos = CurrPos;
- assert(P.LiveInRegs.empty() && "inconsistent max pressure result");
- P.LiveInRegs.reserve(LiveRegs.PhysRegs.size() + LiveRegs.VirtRegs.size());
- P.LiveInRegs.append(LiveRegs.PhysRegs.begin(), LiveRegs.PhysRegs.end());
- for (SparseSet<unsigned>::const_iterator I =
- LiveRegs.VirtRegs.begin(), E = LiveRegs.VirtRegs.end(); I != E; ++I)
- P.LiveInRegs.push_back(*I);
- std::sort(P.LiveInRegs.begin(), P.LiveInRegs.end());
- P.LiveInRegs.erase(std::unique(P.LiveInRegs.begin(), P.LiveInRegs.end()),
- P.LiveInRegs.end());
+ assert(LiveInRegs.empty() && "inconsistent max pressure result");
+ LiveInRegs.reserve(LiveRegs.PhysRegs.size() + LiveRegs.VirtRegs.size());
+ LiveInRegs.append(LiveRegs.PhysRegs.begin(), LiveRegs.PhysRegs.end());
+ LiveInRegs.append(LiveRegs.VirtRegs.begin(), LiveRegs.VirtRegs.end());
}
/// Set the boundary for the bottom of the region and summarize live outs.
else
static_cast<RegionPressure&>(P).BottomPos = CurrPos;
- assert(P.LiveOutRegs.empty() && "inconsistent max pressure result");
- P.LiveOutRegs.reserve(LiveRegs.PhysRegs.size() + LiveRegs.VirtRegs.size());
- P.LiveOutRegs.append(LiveRegs.PhysRegs.begin(), LiveRegs.PhysRegs.end());
- for (SparseSet<unsigned>::const_iterator I =
- LiveRegs.VirtRegs.begin(), E = LiveRegs.VirtRegs.end(); I != E; ++I)
- P.LiveOutRegs.push_back(*I);
- std::sort(P.LiveOutRegs.begin(), P.LiveOutRegs.end());
- P.LiveOutRegs.erase(std::unique(P.LiveOutRegs.begin(), P.LiveOutRegs.end()),
- P.LiveOutRegs.end());
+ assert(LiveOutRegs.empty() && "inconsistent max pressure result");
+ LiveOutRegs.reserve(LiveRegs.PhysRegs.size() + LiveRegs.VirtRegs.size());
+ LiveOutRegs.append(LiveRegs.PhysRegs.begin(), LiveRegs.PhysRegs.end());
+ LiveOutRegs.append(LiveRegs.VirtRegs.begin(), LiveRegs.VirtRegs.end());
}
/// Finalize the region boundaries and record live ins and live outs.
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];
+ for (unsigned i = 0, e = LiveOutRegs.size(); i < e; ++i) {
+ unsigned Reg = LiveOutRegs[i];
if (TargetRegisterInfo::isVirtualRegister(Reg)
&& !RPTracker.hasUntiedDef(Reg)) {
increaseSetPressure(LiveThruPressure, MRI->getPressureSets(Reg));
return std::find(RegUnits.begin(), RegUnits.end(), RegUnit) != RegUnits.end();
}
+namespace {
/// Collect this instruction's unique uses and defs into SmallVectors for
/// processing defs and uses in order.
///
}
}
};
+} // namespace
/// Collect physical and virtual register operands.
static void collectOperands(const MachineInstr *MI,
/// Add Reg to the live in set and increase max pressure.
void RegPressureTracker::discoverLiveIn(unsigned Reg) {
assert(!LiveRegs.contains(Reg) && "avoid bumping max pressure twice");
- if (containsReg(P.LiveInRegs, Reg))
+ if (containsReg(LiveInRegs, Reg))
return;
// At live in discovery, unconditionally increase the high water mark.
- P.LiveInRegs.push_back(Reg);
+ LiveInRegs.push_back(Reg);
increaseSetPressure(P.MaxSetPressure, MRI->getPressureSets(Reg));
}
/// Add Reg to the live out set and increase max pressure.
void RegPressureTracker::discoverLiveOut(unsigned Reg) {
assert(!LiveRegs.contains(Reg) && "avoid bumping max pressure twice");
- if (containsReg(P.LiveOutRegs, Reg))
+ if (containsReg(LiveOutRegs, Reg))
return;
// At live out discovery, unconditionally increase the high water mark.
- P.LiveOutRegs.push_back(Reg);
+ LiveOutRegs.push_back(Reg);
increaseSetPressure(P.MaxSetPressure, MRI->getPressureSets(Reg));
}
SlotIdx = LIS->getInstructionIndex(CurrPos).getRegSlot();
// Open the top of the region using slot indexes.
- if (RequireIntervals && isTopClosed())
- static_cast<IntervalPressure&>(P).openTop(SlotIdx);
+ if (isTopClosed()) {
+ if (RequireIntervals)
+ static_cast<IntervalPressure&>(P).openTop(SlotIdx);
+ LiveInRegs.clear();
+ }
RegisterOperands RegOpers(TRI, MRI);
collectOperands(CurrPos, RegOpers);
// TODO: consider earlyclobbers?
for (unsigned i = 0, e = RegOpers.Defs.size(); i < e; ++i) {
unsigned Reg = RegOpers.Defs[i];
- if (LiveRegs.erase(Reg))
- decreaseRegPressure(Reg);
- else
- discoverLiveOut(Reg);
+ bool DeadDef = false;
+ if (RequireIntervals) {
+ const LiveRange *LR = getLiveRange(Reg);
+ if (LR) {
+ LiveQueryResult LRQ = LR->Query(SlotIdx);
+ DeadDef = LRQ.isDeadDef();
+ }
+ }
+ if (DeadDef) {
+ // LiveIntervals knows this is a dead even though it's MachineOperand is
+ // not flagged as such. Since this register will not be recorded as
+ // live-out, increase its PDiff value to avoid underflowing pressure.
+ if (PDiff)
+ PDiff->addPressureChange(Reg, false, MRI);
+ } else {
+ if (LiveRegs.erase(Reg))
+ decreaseRegPressure(Reg);
+ else
+ discoverLiveOut(Reg);
+ }
}
// Generate liveness for uses.
if (!LiveRegs.contains(Reg)) {
// Adjust liveouts if LiveIntervals are available.
if (RequireIntervals) {
- const LiveInterval *LI = getInterval(Reg);
- // Check if this LR is killed and not redefined here.
- if (LI) {
- LiveRangeQuery LRQ(*LI, SlotIdx);
+ const LiveRange *LR = getLiveRange(Reg);
+ if (LR) {
+ LiveQueryResult LRQ = LR->Query(SlotIdx);
if (!LRQ.isKill() && !LRQ.valueDefined())
discoverLiveOut(Reg);
}
static_cast<IntervalPressure&>(P).openBottom(SlotIdx);
else
static_cast<RegionPressure&>(P).openBottom(CurrPos);
+ LiveOutRegs.clear();
}
RegisterOperands RegOpers(TRI, MRI);
// Kill liveness at last uses.
bool lastUse = false;
if (RequireIntervals) {
- const LiveInterval *LI = getInterval(Reg);
- lastUse = LI && LiveRangeQuery(*LI, SlotIdx).isKill();
+ const LiveRange *LR = getLiveRange(Reg);
+ lastUse = LR && LR->Query(SlotIdx).isKill();
}
else {
// Allocatable physregs are always single-use before register rewriting.
// Kill liveness at live defs.
for (unsigned i = 0, e = RegOpers.Defs.size(); i < e; ++i) {
unsigned Reg = RegOpers.Defs[i];
- if (!containsReg(RegOpers.Uses, Reg))
- decreaseRegPressure(Reg);
+ bool DeadDef = false;
+ if (RequireIntervals) {
+ const LiveRange *LR = getLiveRange(Reg);
+ if (LR) {
+ SlotIndex SlotIdx = LIS->getInstructionIndex(MI);
+ LiveQueryResult LRQ = LR->Query(SlotIdx);
+ DeadDef = LRQ.isDeadDef();
+ }
+ }
+ if (!DeadDef) {
+ if (!containsReg(RegOpers.Uses, Reg))
+ decreaseRegPressure(Reg);
+ }
}
// Generate liveness for uses.
for (unsigned i = 0, e = RegOpers.Uses.size(); i < e; ++i) {
///
/// This assumes that the current LiveOut set is sufficient.
///
-/// FIXME: This is expensive for an on-the-fly query. We need to cache the
-/// result per-SUnit with enough information to adjust for the current
-/// scheduling position. But this works as a proof of concept.
+/// This is expensive for an on-the-fly query because it calls
+/// bumpUpwardPressure to recompute the pressure sets based on current
+/// liveness. This mainly exists to verify correctness, e.g. with
+/// -verify-misched. getUpwardPressureDelta is the fast version of this query
+/// that uses the per-SUnit cache of the PressureDiff.
void RegPressureTracker::
getMaxUpwardPressureDelta(const MachineInstr *MI, PressureDiff *PDiff,
RegPressureDelta &Delta,
RegPressureDelta Delta2;
getUpwardPressureDelta(MI, *PDiff, Delta2, CriticalPSets, MaxPressureLimit);
if (Delta != Delta2) {
+ dbgs() << "PDiff: ";
+ PDiff->dump(*TRI);
dbgs() << "DELTA: " << *MI;
if (Delta.Excess.isValid())
dbgs() << "Excess1 " << TRI->getRegPressureSetName(Delta.Excess.getPSet())
#endif
}
-/// This is a prototype of the fast version of querying register pressure that
-/// does not directly depend on current liveness. It's still slow because we
-/// recompute pressure change on-the-fly. This implementation only exists to
-/// prove correctness.
+/// This is the fast version of querying register pressure that does not
+/// directly depend on current liveness.
///
/// @param Delta captures information needed for heuristics.
///
SlotIndex PriorUseIdx, SlotIndex NextUseIdx,
const MachineRegisterInfo *MRI,
const LiveIntervals *LIS) {
- for (MachineRegisterInfo::use_nodbg_iterator
- UI = MRI->use_nodbg_begin(Reg), UE = MRI->use_nodbg_end();
- UI != UE; UI.skipInstruction()) {
+ for (MachineRegisterInfo::use_instr_nodbg_iterator
+ UI = MRI->use_instr_nodbg_begin(Reg),
+ UE = MRI->use_instr_nodbg_end(); UI != UE; ++UI) {
const MachineInstr* MI = &*UI;
if (MI->isDebugValue())
continue;
// FIXME: allow the caller to pass in the list of vreg uses that remain
// to be bottom-scheduled to avoid searching uses at each query.
SlotIndex CurrIdx = getCurrSlot();
- const LiveInterval *LI = getInterval(Reg);
- if (LI) {
- LiveRangeQuery LRQ(*LI, SlotIdx);
- if (LRQ.isKill() && !findUseBetween(Reg, CurrIdx, SlotIdx, MRI, LIS))
+ const LiveRange *LR = getLiveRange(Reg);
+ if (LR) {
+ LiveQueryResult LRQ = LR->Query(SlotIdx);
+ if (LRQ.isKill() && !findUseBetween(Reg, CurrIdx, SlotIdx, MRI, LIS)) {
decreaseRegPressure(Reg);
+ }
}
}
else if (!TargetRegisterInfo::isVirtualRegister(Reg)) {
/// register units of that pressure set introduced by this instruction.
///
/// This assumes that the current LiveIn set is sufficient.
+///
+/// This is expensive for an on-the-fly query because it calls
+/// bumpDownwardPressure to recompute the pressure sets based on current
+/// liveness. We don't yet have a fast version of downward pressure tracking
+/// analogous to getUpwardPressureDelta.
void RegPressureTracker::
getMaxDownwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta,
ArrayRef<PressureChange> CriticalPSets,