mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
mi-sched: Precompute a PressureDiff for each instruction, adjust for liveness later.
Created SUPressureDiffs array to hold the per node PDiff computed during DAG building. Added a getUpwardPressureDelta API that will soon replace the old one. Compute PressureDelta here from the precomputed PressureDiffs. Updating for liveness will come next. llvm-svn: 189640
This commit is contained in:
parent
07bcdd6b9c
commit
3c849ec211
@ -221,14 +221,17 @@ protected:
|
||||
|
||||
MachineBasicBlock::iterator LiveRegionEnd;
|
||||
|
||||
/// Register pressure in this region computed by buildSchedGraph.
|
||||
// Map each SU to its summary of pressure changes.
|
||||
PressureDiffs SUPressureDiffs;
|
||||
|
||||
/// Register pressure in this region computed by initRegPressure.
|
||||
IntervalPressure RegPressure;
|
||||
RegPressureTracker RPTracker;
|
||||
|
||||
/// List of pressure sets that exceed the target's pressure limit before
|
||||
/// scheduling, listed in increasing set ID order. Each pressure set is paired
|
||||
/// with its max pressure in the currently scheduled regions.
|
||||
std::vector<PressureElement> RegionCriticalPSets;
|
||||
std::vector<PressureChange> RegionCriticalPSets;
|
||||
|
||||
/// The top of the unscheduled zone.
|
||||
MachineBasicBlock::iterator CurrentTop;
|
||||
@ -314,10 +317,14 @@ public:
|
||||
/// Get register pressure for the entire scheduling region before scheduling.
|
||||
const IntervalPressure &getRegPressure() const { return RegPressure; }
|
||||
|
||||
const std::vector<PressureElement> &getRegionCriticalPSets() const {
|
||||
const std::vector<PressureChange> &getRegionCriticalPSets() const {
|
||||
return RegionCriticalPSets;
|
||||
}
|
||||
|
||||
PressureDiff &getPressureDiff(const SUnit *SU) {
|
||||
return SUPressureDiffs[SU->NodeNum];
|
||||
}
|
||||
|
||||
const SUnit *getNextClusterPred() const { return NextClusterPred; }
|
||||
|
||||
const SUnit *getNextClusterSucc() const { return NextClusterSucc; }
|
||||
|
@ -89,20 +89,85 @@ struct RegionPressure : RegisterPressure {
|
||||
void openBottom(MachineBasicBlock::const_iterator PrevBottom);
|
||||
};
|
||||
|
||||
/// An element of pressure difference that identifies the pressure set and
|
||||
/// amount of increase or decrease in units of pressure.
|
||||
struct PressureElement {
|
||||
unsigned PSetID;
|
||||
int UnitIncrease;
|
||||
/// Capture a change in pressure for a single pressure set. UnitInc may be
|
||||
/// expressed in terms of upward or downward pressure depending on the client
|
||||
/// and will be dynamically adjusted for current liveness.
|
||||
///
|
||||
/// Pressure increments are tiny, typically 1-2 units, and this is only for
|
||||
/// heuristics, so we don't check UnitInc overflow. Instead, we may have a
|
||||
/// higher level assert that pressure is consistent within a region. We also
|
||||
/// effectively ignore dead defs which don't affect heuristics much.
|
||||
class PressureChange {
|
||||
uint16_t PSetID; // ID+1. 0=Invalid.
|
||||
int16_t UnitInc;
|
||||
public:
|
||||
PressureChange(): PSetID(0), UnitInc(0) {}
|
||||
PressureChange(unsigned id): PSetID(id+1), UnitInc(0) {
|
||||
assert(id < UINT16_MAX && "PSetID overflow.");
|
||||
}
|
||||
|
||||
PressureElement(): PSetID(~0U), UnitIncrease(0) {}
|
||||
PressureElement(unsigned id, int inc): PSetID(id), UnitIncrease(inc) {}
|
||||
bool isValid() const { return PSetID > 0; }
|
||||
|
||||
bool isValid() const { return PSetID != ~0U; }
|
||||
unsigned getPSet() const {
|
||||
assert(isValid() && "invalid PressureChange");
|
||||
return PSetID - 1;
|
||||
}
|
||||
|
||||
// If signed PSetID is negative, it is invalid; convert it to INT_MAX to give
|
||||
// it lowest priority.
|
||||
int PSetRank() const { return PSetID & INT_MAX; }
|
||||
int getUnitInc() const { return UnitInc; }
|
||||
|
||||
void setUnitInc(int Inc) { UnitInc = Inc; }
|
||||
|
||||
// If PSetID is invalid, convert to INT_MAX to give it lowest priority.
|
||||
int getRank() const { return (PSetID - 1) & INT_MAX; }
|
||||
|
||||
bool operator==(const PressureChange &RHS) const {
|
||||
return PSetID == RHS.PSetID && UnitInc == RHS.UnitInc;
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct isPodLike<PressureChange> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
/// List of PressureChanges in order of increasing, unique PSetID.
|
||||
///
|
||||
/// Use a small fixed number, because we can fit more PressureChanges in an
|
||||
/// empty SmallVector than ever need to be tracked per register class. If more
|
||||
/// PSets are affected, then we only track the most constrained.
|
||||
class PressureDiff {
|
||||
// The initial design was for MaxPSets=4, but that requires PSet partitions,
|
||||
// which are not yet implemented. (PSet partitions are equivalent PSets given
|
||||
// the register classes actually in use within the scheduling region.)
|
||||
enum { MaxPSets = 16 };
|
||||
|
||||
PressureChange PressureChanges[MaxPSets];
|
||||
public:
|
||||
typedef PressureChange* iterator;
|
||||
typedef const PressureChange* const_iterator;
|
||||
iterator begin() { return &PressureChanges[0]; }
|
||||
iterator end() { return &PressureChanges[MaxPSets]; }
|
||||
|
||||
void addPressureChange(unsigned RegUnit, bool IsDec,
|
||||
const MachineRegisterInfo *MRI);
|
||||
};
|
||||
|
||||
/// Array of PressureDiffs.
|
||||
class PressureDiffs {
|
||||
PressureDiff *PDiffArray;
|
||||
unsigned Size;
|
||||
unsigned Max;
|
||||
public:
|
||||
PressureDiffs(): PDiffArray(0), Size(0), Max(0) {}
|
||||
|
||||
void init(unsigned N);
|
||||
|
||||
PressureDiff &operator[](unsigned Idx) {
|
||||
assert(Idx < Size && "PressureDiff index out of bounds");
|
||||
return PDiffArray[Idx];
|
||||
}
|
||||
const PressureDiff &operator[](unsigned Idx) const {
|
||||
return const_cast<PressureDiffs*>(this)->operator[](Idx);
|
||||
}
|
||||
};
|
||||
|
||||
/// Store the effects of a change in pressure on things that MI scheduler cares
|
||||
@ -120,11 +185,19 @@ struct PressureElement {
|
||||
/// CurrentMax records the largest increase in the tracker's max pressure that
|
||||
/// exceeds the current limit for some pressure set determined by the client.
|
||||
struct RegPressureDelta {
|
||||
PressureElement Excess;
|
||||
PressureElement CriticalMax;
|
||||
PressureElement CurrentMax;
|
||||
PressureChange Excess;
|
||||
PressureChange CriticalMax;
|
||||
PressureChange CurrentMax;
|
||||
|
||||
RegPressureDelta() {}
|
||||
|
||||
bool operator==(const RegPressureDelta &RHS) const {
|
||||
return Excess == RHS.Excess && CriticalMax == RHS.CriticalMax
|
||||
&& CurrentMax == RHS.CurrentMax;
|
||||
}
|
||||
bool operator!=(const RegPressureDelta &RHS) const {
|
||||
return !operator==(RHS);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief A set of live virtual registers and physical register units.
|
||||
@ -135,7 +208,7 @@ struct LiveRegSet {
|
||||
SparseSet<unsigned> PhysRegs;
|
||||
SparseSet<unsigned, VirtReg2IndexFunctor> VirtRegs;
|
||||
|
||||
bool contains(unsigned Reg) {
|
||||
bool contains(unsigned Reg) const {
|
||||
if (TargetRegisterInfo::isVirtualRegister(Reg))
|
||||
return VirtRegs.count(Reg);
|
||||
return PhysRegs.count(Reg);
|
||||
@ -239,7 +312,7 @@ public:
|
||||
SlotIndex getCurrSlot() const;
|
||||
|
||||
/// Recede across the previous instruction.
|
||||
bool recede();
|
||||
bool recede(PressureDiff *PDiff = 0);
|
||||
|
||||
/// Advance across the current instruction.
|
||||
bool advance();
|
||||
@ -282,31 +355,39 @@ public:
|
||||
/// limit based on the tracker's current pressure, and record the number of
|
||||
/// excess register units of that pressure set introduced by this instruction.
|
||||
void getMaxUpwardPressureDelta(const MachineInstr *MI,
|
||||
PressureDiff *PDiff,
|
||||
RegPressureDelta &Delta,
|
||||
ArrayRef<PressureElement> CriticalPSets,
|
||||
ArrayRef<PressureChange> CriticalPSets,
|
||||
ArrayRef<unsigned> MaxPressureLimit);
|
||||
|
||||
void getUpwardPressureDelta(const MachineInstr *MI,
|
||||
/*const*/ PressureDiff &PDiff,
|
||||
RegPressureDelta &Delta,
|
||||
ArrayRef<PressureChange> CriticalPSets,
|
||||
ArrayRef<unsigned> MaxPressureLimit) const;
|
||||
|
||||
/// Consider the pressure increase caused by traversing this instruction
|
||||
/// top-down. Find the pressure set with the most change beyond its pressure
|
||||
/// limit based on the tracker's current pressure, and record the number of
|
||||
/// excess register units of that pressure set introduced by this instruction.
|
||||
void getMaxDownwardPressureDelta(const MachineInstr *MI,
|
||||
RegPressureDelta &Delta,
|
||||
ArrayRef<PressureElement> CriticalPSets,
|
||||
ArrayRef<PressureChange> CriticalPSets,
|
||||
ArrayRef<unsigned> MaxPressureLimit);
|
||||
|
||||
/// Find the pressure set with the most change beyond its pressure limit after
|
||||
/// traversing this instruction either upward or downward depending on the
|
||||
/// closed end of the current region.
|
||||
void getMaxPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta,
|
||||
ArrayRef<PressureElement> CriticalPSets,
|
||||
void getMaxPressureDelta(const MachineInstr *MI,
|
||||
RegPressureDelta &Delta,
|
||||
ArrayRef<PressureChange> CriticalPSets,
|
||||
ArrayRef<unsigned> MaxPressureLimit) {
|
||||
if (isTopClosed())
|
||||
return getMaxDownwardPressureDelta(MI, Delta, CriticalPSets,
|
||||
MaxPressureLimit);
|
||||
|
||||
assert(isBottomClosed() && "Uninitialized pressure tracker");
|
||||
return getMaxUpwardPressureDelta(MI, Delta, CriticalPSets,
|
||||
return getMaxUpwardPressureDelta(MI, 0, Delta, CriticalPSets,
|
||||
MaxPressureLimit);
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@ namespace llvm {
|
||||
class MachineDominatorTree;
|
||||
class LiveIntervals;
|
||||
class RegPressureTracker;
|
||||
class PressureDiffs;
|
||||
|
||||
/// An individual mapping from virtual register number to SUnit.
|
||||
struct VReg2SUnit {
|
||||
@ -195,7 +196,8 @@ namespace llvm {
|
||||
|
||||
/// buildSchedGraph - Build SUnits from the MachineBasicBlock that we are
|
||||
/// input.
|
||||
void buildSchedGraph(AliasAnalysis *AA, RegPressureTracker *RPTracker = 0);
|
||||
void buildSchedGraph(AliasAnalysis *AA, RegPressureTracker *RPTracker = 0,
|
||||
PressureDiffs *PDiffs = 0);
|
||||
|
||||
/// addSchedBarrierDeps - Add dependencies from instructions in the current
|
||||
/// list of instructions being scheduled to scheduling barrier. We want to
|
||||
|
@ -505,13 +505,13 @@ void ScheduleDAGMI::initRegPressure() {
|
||||
DEBUG(dbgs() << TRI->getRegPressureSetName(i)
|
||||
<< " Limit " << Limit
|
||||
<< " Actual " << RegionPressure[i] << "\n");
|
||||
RegionCriticalPSets.push_back(PressureElement(i, 0));
|
||||
RegionCriticalPSets.push_back(PressureChange(i));
|
||||
}
|
||||
}
|
||||
DEBUG(dbgs() << "Excess PSets: ";
|
||||
for (unsigned i = 0, e = RegionCriticalPSets.size(); i != e; ++i)
|
||||
dbgs() << TRI->getRegPressureSetName(
|
||||
RegionCriticalPSets[i].PSetID) << " ";
|
||||
RegionCriticalPSets[i].getPSet()) << " ";
|
||||
dbgs() << "\n");
|
||||
}
|
||||
|
||||
@ -520,10 +520,10 @@ void ScheduleDAGMI::initRegPressure() {
|
||||
void ScheduleDAGMI::
|
||||
updateScheduledPressure(const std::vector<unsigned> &NewMaxPressure) {
|
||||
for (unsigned i = 0, e = RegionCriticalPSets.size(); i < e; ++i) {
|
||||
unsigned ID = RegionCriticalPSets[i].PSetID;
|
||||
int &MaxUnits = RegionCriticalPSets[i].UnitIncrease;
|
||||
if ((int)NewMaxPressure[ID] > MaxUnits)
|
||||
MaxUnits = NewMaxPressure[ID];
|
||||
unsigned ID = RegionCriticalPSets[i].getPSet();
|
||||
if ((int)NewMaxPressure[ID] > RegionCriticalPSets[i].getUnitInc()
|
||||
&& NewMaxPressure[ID] <= INT16_MAX)
|
||||
RegionCriticalPSets[i].setUnitInc(NewMaxPressure[ID]);
|
||||
}
|
||||
DEBUG(
|
||||
for (unsigned i = 0, e = NewMaxPressure.size(); i < e; ++i) {
|
||||
@ -599,7 +599,7 @@ void ScheduleDAGMI::buildDAGWithRegPressure() {
|
||||
RPTracker.recede();
|
||||
|
||||
// Build the DAG, and compute current register pressure.
|
||||
buildSchedGraph(AA, &RPTracker);
|
||||
buildSchedGraph(AA, &RPTracker, &SUPressureDiffs);
|
||||
|
||||
// Initialize top/bottom trackers after computing region pressure.
|
||||
initRegPressure();
|
||||
@ -2177,26 +2177,28 @@ static bool tryGreater(int TryVal, int CandVal,
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool tryPressure(const PressureElement &TryP,
|
||||
const PressureElement &CandP,
|
||||
static bool tryPressure(const PressureChange &TryP,
|
||||
const PressureChange &CandP,
|
||||
ConvergingScheduler::SchedCandidate &TryCand,
|
||||
ConvergingScheduler::SchedCandidate &Cand,
|
||||
ConvergingScheduler::CandReason Reason) {
|
||||
// If both candidates affect the same set, go with the smallest increase.
|
||||
if (TryP.PSetID == CandP.PSetID) {
|
||||
return tryLess(TryP.UnitIncrease, CandP.UnitIncrease, TryCand, Cand,
|
||||
Reason);
|
||||
}
|
||||
// If one candidate decreases and the other increases, go with it.
|
||||
if (tryLess(TryP.UnitIncrease < 0, CandP.UnitIncrease < 0, TryCand, Cand,
|
||||
Reason)) {
|
||||
return true;
|
||||
if (TryP.isValid() && CandP.isValid()) {
|
||||
// If both candidates affect the same set, go with the smallest increase.
|
||||
if (TryP.getPSet() == CandP.getPSet()) {
|
||||
return tryLess(TryP.getUnitInc(), CandP.getUnitInc(), TryCand, Cand,
|
||||
Reason);
|
||||
}
|
||||
// If one candidate decreases and the other increases, go with it.
|
||||
if (tryLess(TryP.getUnitInc() < 0, CandP.getUnitInc() < 0, TryCand, Cand,
|
||||
Reason)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// If TryP has lower Rank, it has a higher priority.
|
||||
int TryRank = TryP.PSetRank();
|
||||
int CandRank = CandP.PSetRank();
|
||||
int TryRank = TryP.getRank();
|
||||
int CandRank = CandP.getRank();
|
||||
// If the candidates are decreasing pressure, reverse priority.
|
||||
if (TryP.UnitIncrease < 0)
|
||||
if (TryP.getUnitInc() < 0)
|
||||
std::swap(TryRank, CandRank);
|
||||
return tryGreater(TryRank, CandRank, TryCand, Cand, Reason);
|
||||
}
|
||||
@ -2277,9 +2279,31 @@ void ConvergingScheduler::tryCandidate(SchedCandidate &Cand,
|
||||
RegPressureTracker &TempTracker) {
|
||||
|
||||
// Always initialize TryCand's RPDelta.
|
||||
TempTracker.getMaxPressureDelta(TryCand.SU->getInstr(), TryCand.RPDelta,
|
||||
DAG->getRegionCriticalPSets(),
|
||||
DAG->getRegPressure().MaxSetPressure);
|
||||
if (Zone.isTop()) {
|
||||
TempTracker.getMaxDownwardPressureDelta(
|
||||
TryCand.SU->getInstr(),
|
||||
TryCand.RPDelta,
|
||||
DAG->getRegionCriticalPSets(),
|
||||
DAG->getRegPressure().MaxSetPressure);
|
||||
}
|
||||
else {
|
||||
if (VerifyScheduling) {
|
||||
TempTracker.getMaxUpwardPressureDelta(
|
||||
TryCand.SU->getInstr(),
|
||||
&DAG->getPressureDiff(TryCand.SU),
|
||||
TryCand.RPDelta,
|
||||
DAG->getRegionCriticalPSets(),
|
||||
DAG->getRegPressure().MaxSetPressure);
|
||||
}
|
||||
else {
|
||||
RPTracker.getUpwardPressureDelta(
|
||||
TryCand.SU->getInstr(),
|
||||
DAG->getPressureDiff(TryCand.SU),
|
||||
TryCand.RPDelta,
|
||||
DAG->getRegionCriticalPSets(),
|
||||
DAG->getRegPressure().MaxSetPressure);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the candidate if needed.
|
||||
if (!Cand.isValid()) {
|
||||
@ -2385,7 +2409,7 @@ const char *ConvergingScheduler::getReasonStr(
|
||||
}
|
||||
|
||||
void ConvergingScheduler::traceCandidate(const SchedCandidate &Cand) {
|
||||
PressureElement P;
|
||||
PressureChange P;
|
||||
unsigned ResIdx = 0;
|
||||
unsigned Latency = 0;
|
||||
switch (Cand.Reason) {
|
||||
@ -2421,8 +2445,8 @@ void ConvergingScheduler::traceCandidate(const SchedCandidate &Cand) {
|
||||
}
|
||||
dbgs() << " SU(" << Cand.SU->NodeNum << ") " << getReasonStr(Cand.Reason);
|
||||
if (P.isValid())
|
||||
dbgs() << " " << TRI->getRegPressureSetName(P.PSetID)
|
||||
<< ":" << P.UnitIncrease << " ";
|
||||
dbgs() << " " << TRI->getRegPressureSetName(P.getPSet())
|
||||
<< ":" << P.getUnitInc() << " ";
|
||||
else
|
||||
dbgs() << " ";
|
||||
if (ResIdx)
|
||||
|
@ -294,9 +294,12 @@ static bool containsReg(ArrayRef<unsigned> RegUnits, unsigned RegUnit) {
|
||||
|
||||
/// Collect this instruction's unique uses and defs into SmallVectors for
|
||||
/// processing defs and uses in order.
|
||||
///
|
||||
/// FIXME: always ignore tied opers
|
||||
class RegisterOperands {
|
||||
const TargetRegisterInfo *TRI;
|
||||
const MachineRegisterInfo *MRI;
|
||||
bool IgnoreDead;
|
||||
|
||||
public:
|
||||
SmallVector<unsigned, 8> Uses;
|
||||
@ -304,7 +307,8 @@ public:
|
||||
SmallVector<unsigned, 8> DeadDefs;
|
||||
|
||||
RegisterOperands(const TargetRegisterInfo *tri,
|
||||
const MachineRegisterInfo *mri): TRI(tri), MRI(mri) {}
|
||||
const MachineRegisterInfo *mri, bool ID = false):
|
||||
TRI(tri), MRI(mri), IgnoreDead(ID) {}
|
||||
|
||||
/// Push this operand's register onto the correct vector.
|
||||
void collect(const MachineOperand &MO) {
|
||||
@ -313,8 +317,10 @@ public:
|
||||
if (MO.readsReg())
|
||||
pushRegUnits(MO.getReg(), Uses);
|
||||
if (MO.isDef()) {
|
||||
if (MO.isDead())
|
||||
pushRegUnits(MO.getReg(), DeadDefs);
|
||||
if (MO.isDead()) {
|
||||
if (!IgnoreDead)
|
||||
pushRegUnits(MO.getReg(), DeadDefs);
|
||||
}
|
||||
else
|
||||
pushRegUnits(MO.getReg(), Defs);
|
||||
}
|
||||
@ -350,6 +356,57 @@ static void collectOperands(const MachineInstr *MI,
|
||||
RegOpers.DeadDefs.erase(I, RegOpers.DeadDefs.end());
|
||||
}
|
||||
|
||||
/// Initialize an array of N PressureDiffs.
|
||||
void PressureDiffs::init(unsigned N) {
|
||||
Size = N;
|
||||
if (N <= Max) {
|
||||
memset(PDiffArray, 0, N * sizeof(PressureDiff));
|
||||
return;
|
||||
}
|
||||
Max = Size;
|
||||
free(PDiffArray);
|
||||
PDiffArray = reinterpret_cast<PressureDiff*>(calloc(N, sizeof(PressureDiff)));
|
||||
}
|
||||
|
||||
/// Add a change in pressure to the pressure diff of a given instruction.
|
||||
void PressureDiff::addPressureChange(unsigned RegUnit, bool IsDec,
|
||||
const MachineRegisterInfo *MRI) {
|
||||
PSetIterator PSetI = MRI->getPressureSets(RegUnit);
|
||||
int Weight = IsDec ? -PSetI.getWeight() : PSetI.getWeight();
|
||||
for (; PSetI.isValid(); ++PSetI) {
|
||||
// Find an existing entry in the pressure diff for this PSet.
|
||||
PressureDiff::iterator I = begin(), E = end();
|
||||
for (; I != E && I->isValid(); ++I) {
|
||||
if (I->getPSet() >= *PSetI)
|
||||
break;
|
||||
}
|
||||
// If all pressure sets are more constrained, skip the remaining PSets.
|
||||
if (I == E)
|
||||
break;
|
||||
// Insert this PressureChange.
|
||||
if (!I->isValid() || I->getPSet() != *PSetI) {
|
||||
PressureChange PTmp = PressureChange(*PSetI);
|
||||
for (PressureDiff::iterator J = I; J != E && PTmp.isValid(); ++J)
|
||||
std::swap(*J,PTmp);
|
||||
}
|
||||
// Update the units for this pressure set.
|
||||
I->setUnitInc(I->getUnitInc() + Weight);
|
||||
}
|
||||
}
|
||||
|
||||
/// Record the pressure difference induced by the given operand list.
|
||||
static void collectPDiff(PressureDiff &PDiff, RegisterOperands &RegOpers,
|
||||
const MachineRegisterInfo *MRI) {
|
||||
assert(!PDiff.begin()->isValid() && "stale PDiff");
|
||||
|
||||
for (unsigned i = 0, e = RegOpers.Defs.size(); i != e; ++i) {
|
||||
if (!containsReg(RegOpers.Uses, RegOpers.Defs[i]))
|
||||
PDiff.addPressureChange(RegOpers.Defs[i], true, MRI);
|
||||
}
|
||||
for (unsigned i = 0, e = RegOpers.Uses.size(); i != e; ++i)
|
||||
PDiff.addPressureChange(RegOpers.Uses[i], false, MRI);
|
||||
}
|
||||
|
||||
/// Force liveness of registers.
|
||||
void RegPressureTracker::addLiveRegs(ArrayRef<unsigned> Regs) {
|
||||
for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
|
||||
@ -381,7 +438,8 @@ void RegPressureTracker::discoverLiveOut(unsigned Reg) {
|
||||
}
|
||||
|
||||
/// Recede across the previous instruction.
|
||||
bool RegPressureTracker::recede() {
|
||||
/// Record the pressure difference if it is provided.
|
||||
bool RegPressureTracker::recede(PressureDiff *PDiff) {
|
||||
// Check for the top of the analyzable region.
|
||||
if (CurrPos == MBB->begin()) {
|
||||
closeRegion();
|
||||
@ -414,6 +472,9 @@ bool RegPressureTracker::recede() {
|
||||
RegisterOperands RegOpers(TRI, MRI);
|
||||
collectOperands(CurrPos, RegOpers);
|
||||
|
||||
if (PDiff)
|
||||
collectPDiff(*PDiff, RegOpers, MRI);
|
||||
|
||||
// Boost pressure for all dead defs together.
|
||||
increaseRegPressure(RegOpers.DeadDefs);
|
||||
decreaseRegPressure(RegOpers.DeadDefs);
|
||||
@ -527,8 +588,7 @@ static void computeExcessPressureDelta(ArrayRef<unsigned> OldPressureVec,
|
||||
RegPressureDelta &Delta,
|
||||
const RegisterClassInfo *RCI,
|
||||
ArrayRef<unsigned> LiveThruPressureVec) {
|
||||
int ExcessUnits = 0;
|
||||
unsigned PSetID = ~0U;
|
||||
Delta.Excess = PressureChange();
|
||||
for (unsigned i = 0, e = OldPressureVec.size(); i < e; ++i) {
|
||||
unsigned POld = OldPressureVec[i];
|
||||
unsigned PNew = NewPressureVec[i];
|
||||
@ -550,13 +610,11 @@ static void computeExcessPressureDelta(ArrayRef<unsigned> OldPressureVec,
|
||||
PDiff = Limit - POld; // Just obeyed limit.
|
||||
|
||||
if (PDiff) {
|
||||
ExcessUnits = PDiff;
|
||||
PSetID = i;
|
||||
Delta.Excess = PressureChange(i);
|
||||
Delta.Excess.setUnitInc(PDiff);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Delta.Excess.PSetID = PSetID;
|
||||
Delta.Excess.UnitIncrease = ExcessUnits;
|
||||
}
|
||||
|
||||
/// Find the max change in max pressure that either surpasses a critical PSet
|
||||
@ -567,11 +625,11 @@ static void computeExcessPressureDelta(ArrayRef<unsigned> OldPressureVec,
|
||||
/// RegPressureTracker API change to work with pressure differences.
|
||||
static void computeMaxPressureDelta(ArrayRef<unsigned> OldMaxPressureVec,
|
||||
ArrayRef<unsigned> NewMaxPressureVec,
|
||||
ArrayRef<PressureElement> CriticalPSets,
|
||||
ArrayRef<PressureChange> CriticalPSets,
|
||||
ArrayRef<unsigned> MaxPressureLimit,
|
||||
RegPressureDelta &Delta) {
|
||||
Delta.CriticalMax = PressureElement();
|
||||
Delta.CurrentMax = PressureElement();
|
||||
Delta.CriticalMax = PressureChange();
|
||||
Delta.CurrentMax = PressureChange();
|
||||
|
||||
unsigned CritIdx = 0, CritEnd = CriticalPSets.size();
|
||||
for (unsigned i = 0, e = OldMaxPressureVec.size(); i < e; ++i) {
|
||||
@ -581,27 +639,24 @@ static void computeMaxPressureDelta(ArrayRef<unsigned> OldMaxPressureVec,
|
||||
continue;
|
||||
|
||||
if (!Delta.CriticalMax.isValid()) {
|
||||
while (CritIdx != CritEnd && CriticalPSets[CritIdx].PSetID < i)
|
||||
while (CritIdx != CritEnd && CriticalPSets[CritIdx].getPSet() < i)
|
||||
++CritIdx;
|
||||
|
||||
if (CritIdx != CritEnd && CriticalPSets[CritIdx].PSetID == i) {
|
||||
int PDiff = (int)PNew - (int)CriticalPSets[CritIdx].UnitIncrease;
|
||||
if (CritIdx != CritEnd && CriticalPSets[CritIdx].getPSet() == i) {
|
||||
int PDiff = (int)PNew - (int)CriticalPSets[CritIdx].getUnitInc();
|
||||
if (PDiff > 0) {
|
||||
Delta.CriticalMax.PSetID = i;
|
||||
Delta.CriticalMax.UnitIncrease = PDiff;
|
||||
Delta.CriticalMax = PressureChange(i);
|
||||
Delta.CriticalMax.setUnitInc(PDiff);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Find the first increase above MaxPressureLimit.
|
||||
// (Ignores negative MDiff).
|
||||
if (!Delta.CurrentMax.isValid()) {
|
||||
int MDiff = (int)PNew - (int)MaxPressureLimit[i];
|
||||
if (MDiff > 0) {
|
||||
Delta.CurrentMax.PSetID = i;
|
||||
Delta.CurrentMax.UnitIncrease = MDiff;
|
||||
if (CritIdx == CritEnd || Delta.CriticalMax.isValid())
|
||||
break;
|
||||
}
|
||||
if (!Delta.CurrentMax.isValid() && PNew > MaxPressureLimit[i]) {
|
||||
Delta.CurrentMax = PressureChange(i);
|
||||
Delta.CurrentMax.setUnitInc(PNew - POld);
|
||||
if (CritIdx == CritEnd || Delta.CriticalMax.isValid())
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -616,7 +671,7 @@ void RegPressureTracker::bumpUpwardPressure(const MachineInstr *MI) {
|
||||
assert(!MI->isDebugValue() && "Expect a nondebug instruction.");
|
||||
|
||||
// Account for register pressure similar to RegPressureTracker::recede().
|
||||
RegisterOperands RegOpers(TRI, MRI);
|
||||
RegisterOperands RegOpers(TRI, MRI, /*IgnoreDead=*/true);
|
||||
collectOperands(MI, RegOpers);
|
||||
|
||||
// Boost max pressure for all dead defs together.
|
||||
@ -650,8 +705,9 @@ void RegPressureTracker::bumpUpwardPressure(const MachineInstr *MI) {
|
||||
/// result per-SUnit with enough information to adjust for the current
|
||||
/// scheduling position. But this works as a proof of concept.
|
||||
void RegPressureTracker::
|
||||
getMaxUpwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta,
|
||||
ArrayRef<PressureElement> CriticalPSets,
|
||||
getMaxUpwardPressureDelta(const MachineInstr *MI, PressureDiff *PDiff,
|
||||
RegPressureDelta &Delta,
|
||||
ArrayRef<PressureChange> CriticalPSets,
|
||||
ArrayRef<unsigned> MaxPressureLimit) {
|
||||
// Snapshot Pressure.
|
||||
// FIXME: The snapshot heap space should persist. But I'm planning to
|
||||
@ -665,12 +721,125 @@ getMaxUpwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta,
|
||||
LiveThruPressure);
|
||||
computeMaxPressureDelta(SavedMaxPressure, P.MaxSetPressure, CriticalPSets,
|
||||
MaxPressureLimit, Delta);
|
||||
assert(Delta.CriticalMax.UnitIncrease >= 0 &&
|
||||
Delta.CurrentMax.UnitIncrease >= 0 && "cannot decrease max pressure");
|
||||
assert(Delta.CriticalMax.getUnitInc() >= 0 &&
|
||||
Delta.CurrentMax.getUnitInc() >= 0 && "cannot decrease max pressure");
|
||||
|
||||
// Restore the tracker's state.
|
||||
P.MaxSetPressure.swap(SavedMaxPressure);
|
||||
CurrSetPressure.swap(SavedPressure);
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (!PDiff)
|
||||
return;
|
||||
|
||||
// Check if the alternate algorithm yields the same result.
|
||||
RegPressureDelta Delta2;
|
||||
getUpwardPressureDelta(MI, *PDiff, Delta2, CriticalPSets, MaxPressureLimit);
|
||||
if (Delta != Delta2) {
|
||||
dbgs() << "DELTA: " << *MI;
|
||||
if (Delta.Excess.isValid())
|
||||
dbgs() << "Excess1 " << TRI->getRegPressureSetName(Delta.Excess.getPSet())
|
||||
<< " " << Delta.Excess.getUnitInc() << "\n";
|
||||
if (Delta.CriticalMax.isValid())
|
||||
dbgs() << "Critic1 " << TRI->getRegPressureSetName(Delta.CriticalMax.getPSet())
|
||||
<< " " << Delta.CriticalMax.getUnitInc() << "\n";
|
||||
if (Delta.CurrentMax.isValid())
|
||||
dbgs() << "CurrMx1 " << TRI->getRegPressureSetName(Delta.CurrentMax.getPSet())
|
||||
<< " " << Delta.CurrentMax.getUnitInc() << "\n";
|
||||
if (Delta2.Excess.isValid())
|
||||
dbgs() << "Excess2 " << TRI->getRegPressureSetName(Delta2.Excess.getPSet())
|
||||
<< " " << Delta2.Excess.getUnitInc() << "\n";
|
||||
if (Delta2.CriticalMax.isValid())
|
||||
dbgs() << "Critic2 " << TRI->getRegPressureSetName(Delta2.CriticalMax.getPSet())
|
||||
<< " " << Delta2.CriticalMax.getUnitInc() << "\n";
|
||||
if (Delta2.CurrentMax.isValid())
|
||||
dbgs() << "CurrMx2 " << TRI->getRegPressureSetName(Delta2.CurrentMax.getPSet())
|
||||
<< " " << Delta2.CurrentMax.getUnitInc() << "\n";
|
||||
llvm_unreachable("RegP Delta Mismatch");
|
||||
}
|
||||
#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.
|
||||
///
|
||||
/// @param Delta captures information needed for heuristics.
|
||||
///
|
||||
/// @param CriticalPSets Are the pressure sets that are known to exceed some
|
||||
/// limit within the region, not necessarily at the current position.
|
||||
///
|
||||
/// @param MaxPressureLimit Is the max pressure within the region, not
|
||||
/// necessarily at the current position.
|
||||
void RegPressureTracker::
|
||||
getUpwardPressureDelta(const MachineInstr *MI, /*const*/ PressureDiff &PDiff1,
|
||||
RegPressureDelta &Delta,
|
||||
ArrayRef<PressureChange> CriticalPSets,
|
||||
ArrayRef<unsigned> MaxPressureLimit) const {
|
||||
RegisterOperands RegOpers(TRI, MRI, /*IgnoreDead=*/true);
|
||||
collectOperands(MI, RegOpers);
|
||||
|
||||
// Decrease the pressure change for live uses.
|
||||
PressureDiff PDiff = PDiff1;
|
||||
for (unsigned i = 0, e = RegOpers.Uses.size(); i != e; ++i) {
|
||||
if (LiveRegs.contains(RegOpers.Uses[i]))
|
||||
PDiff.addPressureChange(RegOpers.Uses[i], true, MRI);
|
||||
}
|
||||
|
||||
// Now directly query pressure from PDiff. Everything above this can be
|
||||
// cached and updated independent of the query.
|
||||
unsigned CritIdx = 0, CritEnd = CriticalPSets.size();
|
||||
for (PressureDiff::const_iterator
|
||||
PDiffI = PDiff.begin(), PDiffE = PDiff.end();
|
||||
PDiffI != PDiffE && PDiffI->isValid(); ++PDiffI) {
|
||||
|
||||
unsigned PSetID = PDiffI->getPSet();
|
||||
unsigned Limit = RCI->getRegPressureSetLimit(PSetID);
|
||||
if (!LiveThruPressure.empty())
|
||||
Limit += LiveThruPressure[PSetID];
|
||||
|
||||
unsigned POld = CurrSetPressure[PSetID];
|
||||
unsigned MOld = P.MaxSetPressure[PSetID];
|
||||
unsigned MNew = MOld;
|
||||
// Ignore DeadDefs here because they aren't captured by PressureChange.
|
||||
unsigned PNew = POld + PDiffI->getUnitInc();
|
||||
assert((PDiffI->getUnitInc() >= 0) == (PNew >= POld) && "PSet overflow");
|
||||
if (PNew > MOld)
|
||||
MNew = PNew;
|
||||
// Check if current pressure has exceeded the limit.
|
||||
if (!Delta.Excess.isValid()) {
|
||||
unsigned ExcessInc = 0;
|
||||
if (PNew > Limit)
|
||||
ExcessInc = POld > Limit ? PNew - POld : PNew - Limit;
|
||||
else if (POld > Limit)
|
||||
ExcessInc = Limit - POld;
|
||||
if (ExcessInc) {
|
||||
Delta.Excess = PressureChange(PSetID);
|
||||
Delta.Excess.setUnitInc(ExcessInc);
|
||||
}
|
||||
}
|
||||
// Check if max pressure has exceeded a critical pressure set max.
|
||||
if (MNew == MOld)
|
||||
continue;
|
||||
if (!Delta.CriticalMax.isValid()) {
|
||||
while (CritIdx != CritEnd && CriticalPSets[CritIdx].getPSet() < PSetID)
|
||||
++CritIdx;
|
||||
|
||||
if (CritIdx != CritEnd && CriticalPSets[CritIdx].getPSet() == PSetID) {
|
||||
int CritInc = (int)MNew - (int)CriticalPSets[CritIdx].getUnitInc();
|
||||
if (CritInc > 0 && CritInc <= INT16_MAX) {
|
||||
Delta.CriticalMax = PressureChange(PSetID);
|
||||
Delta.CriticalMax.setUnitInc(CritInc);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check if max pressure has exceeded the current max.
|
||||
if (!Delta.CurrentMax.isValid() && MNew > MaxPressureLimit[PSetID]) {
|
||||
Delta.CurrentMax = PressureChange(PSetID);
|
||||
Delta.CurrentMax.setUnitInc(MNew - MOld);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper to find a vreg use between two indices [PriorUseIdx, NextUseIdx).
|
||||
@ -744,7 +913,7 @@ void RegPressureTracker::bumpDownwardPressure(const MachineInstr *MI) {
|
||||
/// This assumes that the current LiveIn set is sufficient.
|
||||
void RegPressureTracker::
|
||||
getMaxDownwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta,
|
||||
ArrayRef<PressureElement> CriticalPSets,
|
||||
ArrayRef<PressureChange> CriticalPSets,
|
||||
ArrayRef<unsigned> MaxPressureLimit) {
|
||||
// Snapshot Pressure.
|
||||
std::vector<unsigned> SavedPressure = CurrSetPressure;
|
||||
@ -756,8 +925,8 @@ getMaxDownwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta,
|
||||
LiveThruPressure);
|
||||
computeMaxPressureDelta(SavedMaxPressure, P.MaxSetPressure, CriticalPSets,
|
||||
MaxPressureLimit, Delta);
|
||||
assert(Delta.CriticalMax.UnitIncrease >= 0 &&
|
||||
Delta.CurrentMax.UnitIncrease >= 0 && "cannot decrease max pressure");
|
||||
assert(Delta.CriticalMax.getUnitInc() >= 0 &&
|
||||
Delta.CurrentMax.getUnitInc() >= 0 && "cannot decrease max pressure");
|
||||
|
||||
// Restore the tracker's state.
|
||||
P.MaxSetPressure.swap(SavedMaxPressure);
|
||||
|
@ -690,7 +690,8 @@ void ScheduleDAGInstrs::initSUnits() {
|
||||
/// DAG builder is an efficient place to do it because it already visits
|
||||
/// operands.
|
||||
void ScheduleDAGInstrs::buildSchedGraph(AliasAnalysis *AA,
|
||||
RegPressureTracker *RPTracker) {
|
||||
RegPressureTracker *RPTracker,
|
||||
PressureDiffs *PDiffs) {
|
||||
const TargetSubtargetInfo &ST = TM.getSubtarget<TargetSubtargetInfo>();
|
||||
bool UseAA = EnableAASchedMI.getNumOccurrences() > 0 ? EnableAASchedMI
|
||||
: ST.useAA();
|
||||
@ -699,6 +700,9 @@ void ScheduleDAGInstrs::buildSchedGraph(AliasAnalysis *AA,
|
||||
// Create an SUnit for each real instruction.
|
||||
initSUnits();
|
||||
|
||||
if (PDiffs)
|
||||
PDiffs->init(SUnits.size());
|
||||
|
||||
// We build scheduling units by walking a block's instruction list from bottom
|
||||
// to top.
|
||||
|
||||
@ -746,17 +750,18 @@ void ScheduleDAGInstrs::buildSchedGraph(AliasAnalysis *AA,
|
||||
DbgMI = MI;
|
||||
continue;
|
||||
}
|
||||
SUnit *SU = MISUnitMap[MI];
|
||||
assert(SU && "No SUnit mapped to this MI");
|
||||
|
||||
if (RPTracker) {
|
||||
RPTracker->recede();
|
||||
PressureDiff *PDiff = PDiffs ? &(*PDiffs)[SU->NodeNum] : 0;
|
||||
RPTracker->recede(PDiff);
|
||||
assert(RPTracker->getPos() == prior(MII) && "RPTracker can't find MI");
|
||||
}
|
||||
|
||||
assert((CanHandleTerminators || (!MI->isTerminator() && !MI->isLabel())) &&
|
||||
"Cannot schedule terminators or labels!");
|
||||
|
||||
SUnit *SU = MISUnitMap[MI];
|
||||
assert(SU && "No SUnit mapped to this MI");
|
||||
|
||||
// Add register-based dependencies (data, anti, and output).
|
||||
bool HasVRegDef = false;
|
||||
for (unsigned j = 0, n = MI->getNumOperands(); j != n; ++j) {
|
||||
|
@ -407,11 +407,11 @@ SUnit *ConvergingVLIWScheduler::SchedBoundary::pickOnlyChoice() {
|
||||
#ifndef NDEBUG
|
||||
void ConvergingVLIWScheduler::traceCandidate(const char *Label,
|
||||
const ReadyQueue &Q,
|
||||
SUnit *SU, PressureElement P) {
|
||||
SUnit *SU, PressureChange P) {
|
||||
dbgs() << Label << " " << Q.getName() << " ";
|
||||
if (P.isValid())
|
||||
dbgs() << DAG->TRI->getRegPressureSetName(P.PSetID) << ":" << P.UnitIncrease
|
||||
<< " ";
|
||||
dbgs() << DAG->TRI->getRegPressureSetName(P.getPSet()) << ":"
|
||||
<< P.getUnitInc() << " ";
|
||||
else
|
||||
dbgs() << " ";
|
||||
SU->dump(DAG);
|
||||
@ -517,8 +517,8 @@ int ConvergingVLIWScheduler::SchedulingCost(ReadyQueue &Q, SUnit *SU,
|
||||
ResCount += (NumNodesBlocking * ScaleTwo);
|
||||
|
||||
// Factor in reg pressure as a heuristic.
|
||||
ResCount -= (Delta.Excess.UnitIncrease*PriorityThree);
|
||||
ResCount -= (Delta.CriticalMax.UnitIncrease*PriorityThree);
|
||||
ResCount -= (Delta.Excess.getUnitInc()*PriorityThree);
|
||||
ResCount -= (Delta.CriticalMax.getUnitInc()*PriorityThree);
|
||||
|
||||
DEBUG(if (verbose) dbgs() << " Total(" << ResCount << ")");
|
||||
|
||||
|
@ -233,7 +233,7 @@ protected:
|
||||
SchedCandidate &Candidate);
|
||||
#ifndef NDEBUG
|
||||
void traceCandidate(const char *Label, const ReadyQueue &Q, SUnit *SU,
|
||||
PressureElement P = PressureElement());
|
||||
PressureChange P = PressureChange());
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
; RUN: llc < %s -march=x86-64 -mcpu=core2 -pre-RA-sched=source -enable-misched -verify-machineinstrs | FileCheck %s
|
||||
; RUN-disabled: llc < %s -march=x86-64 -mcpu=core2 -pre-RA-sched=source -enable-misched -verify-machineinstrs | FileCheck %s
|
||||
; RUN: true
|
||||
;
|
||||
; Verify that misched resource/latency balancy heuristics are sane.
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
; REQUIRES: asserts
|
||||
; RUN: llc < %s -march=x86-64 -mcpu=core2 -pre-RA-sched=source -enable-misched -stats 2>&1 | FileCheck %s
|
||||
; RUN-disabled: llc < %s -march=x86-64 -mcpu=core2 -pre-RA-sched=source -enable-misched -stats 2>&1 | FileCheck %s
|
||||
; RUN: true
|
||||
;
|
||||
; Verify that register pressure heuristics are working in MachineScheduler.
|
||||
;
|
||||
|
@ -1,6 +1,6 @@
|
||||
; RUN: llc < %s -march=x86-64 -mcpu=core2 -pre-RA-sched=source -enable-misched \
|
||||
; RUN: -misched-topdown -verify-machineinstrs \
|
||||
; RUN: | FileCheck %s -check-prefix=TOPDOWN
|
||||
; RUN: | FileCheck %s -check-prefix=TOPDOWN-disabled
|
||||
; RUN: llc < %s -march=x86-64 -mcpu=core2 -pre-RA-sched=source -enable-misched \
|
||||
; RUN: -misched=ilpmin -verify-machineinstrs \
|
||||
; RUN: | FileCheck %s -check-prefix=ILPMIN
|
||||
@ -15,7 +15,7 @@
|
||||
; been reordered with the stores. This tests the scheduler's cheap
|
||||
; alias analysis ability (that doesn't require any AliasAnalysis pass).
|
||||
;
|
||||
; TOPDOWN: %for.body
|
||||
; TOPDOWN-disabled: %for.body
|
||||
; TOPDOWN: movl %{{.*}}, (
|
||||
; TOPDOWN: imull {{[0-9]*}}(
|
||||
; TOPDOWN: movl %{{.*}}, 4(
|
||||
|
Loading…
Reference in New Issue
Block a user