summaryrefslogtreecommitdiff
path: root/lib/CodeGen/RegisterPressure.cpp
diff options
context:
space:
mode:
authorAndrew Trick <atrick@apple.com>2013-08-30 03:49:48 +0000
committerAndrew Trick <atrick@apple.com>2013-08-30 03:49:48 +0000
commit4c60b8a78d811a5b16ae45f6957933fb479bab58 (patch)
tree35355754c69394e12072b41a8d9c9978f0bc241e /lib/CodeGen/RegisterPressure.cpp
parente206efd39bcc00600d816b67b041820b35d023fe (diff)
downloadllvm-4c60b8a78d811a5b16ae45f6957933fb479bab58.tar.gz
llvm-4c60b8a78d811a5b16ae45f6957933fb479bab58.tar.bz2
llvm-4c60b8a78d811a5b16ae45f6957933fb479bab58.tar.xz
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@189640 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/RegisterPressure.cpp')
-rw-r--r--lib/CodeGen/RegisterPressure.cpp237
1 files changed, 203 insertions, 34 deletions
diff --git a/lib/CodeGen/RegisterPressure.cpp b/lib/CodeGen/RegisterPressure.cpp
index d3b4f60a77..188750dbc0 100644
--- a/lib/CodeGen/RegisterPressure.cpp
+++ b/lib/CodeGen/RegisterPressure.cpp
@@ -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);