misched: Added 3-level regpressure back-off.
authorAndrew Trick <atrick@apple.com>
Thu, 17 May 2012 18:35:10 +0000 (18:35 +0000)
committerAndrew Trick <atrick@apple.com>
Thu, 17 May 2012 18:35:10 +0000 (18:35 +0000)
Introduce the basic strategy for register pressure scheduling.

1) Respect target limits at all times.

2) Indentify critical register classes (pressure sets).
   Track pressure within the scheduled region.
   Avoid increasing scheduled pressure for critical registers.

3) Avoid exceeding the max pressure of the region prior to scheduling.

Added logic for picking between the top and bottom ready Q's based on
regpressure heuristics.

Status: functional but needs to be asjusted to achieve good results.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@157006 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/MachineScheduler.cpp
lib/CodeGen/RegisterPressure.cpp
lib/CodeGen/RegisterPressure.h

index 1d810fdf16d220caa3bc839c188ebf183481d753..57f3506d8e8e883e360b65be78f0e8e275e65253 100644 (file)
@@ -1,4 +1,4 @@
-//===- MachineScheduler.cpp - Machine Instruction Scheduler ---------------===//
+//===- MachineScheduler.cpp - Machine Instruction Scheduler ---------------===//excess
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -326,10 +326,15 @@ class ScheduleDAGMI : public ScheduleDAGInstrs {
 
   MachineBasicBlock::iterator LiveRegionEnd;
 
-  // Register pressure in this region computed by buildSchedGraph.
+  /// Register pressure in this region computed by buildSchedGraph.
   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;
+
   /// The top of the unscheduled zone.
   MachineBasicBlock::iterator CurrentTop;
   IntervalPressure TopPressure;
@@ -380,8 +385,13 @@ public:
   /// Get register pressure for the entire scheduling region before scheduling.
   const IntervalPressure &getRegPressure() const { return RegPressure; }
 
+  const std::vector<PressureElement> &getRegionCriticalPSets() const {
+    return RegionCriticalPSets;
+  }
+
 protected:
   void initRegPressure();
+  void updateScheduledPressure(std::vector<unsigned> NewMaxPressure);
 
   void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos);
   bool checkSchedLimit();
@@ -515,6 +525,33 @@ void ScheduleDAGMI::initRegPressure() {
     BotRPTracker.recede();
 
   assert(BotRPTracker.getPos() == RegionEnd && "Can't find the region bottom");
+
+  // Cache the list of excess pressure sets in this region. This will also track
+  // the max pressure in the scheduled code for these sets.
+  RegionCriticalPSets.clear();
+  std::vector<unsigned> RegionPressure = RPTracker.getPressure().MaxSetPressure;
+  for (unsigned i = 0, e = RegionPressure.size(); i < e; ++i) {
+    unsigned Limit = TRI->getRegPressureSetLimit(i);
+    if (RegionPressure[i] > Limit)
+      RegionCriticalPSets.push_back(PressureElement(i, 0));
+  }
+  DEBUG(dbgs() << "Excess PSets: ";
+        for (unsigned i = 0, e = RegionCriticalPSets.size(); i != e; ++i)
+          dbgs() << TRI->getRegPressureSetName(
+            RegionCriticalPSets[i].PSetID) << " ";
+        dbgs() << "\n");
+}
+
+// FIXME: When the pressure tracker deals in pressure differences then we won't
+// iterate over all RegionCriticalPSets[i].
+void ScheduleDAGMI::
+updateScheduledPressure(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];
+  }
 }
 
 /// schedule - Called back from MachineScheduler::runOnMachineFunction
@@ -581,6 +618,7 @@ void ScheduleDAGMI::schedule() {
       // Update top scheduled pressure.
       TopRPTracker.advance();
       assert(TopRPTracker.getPos() == CurrentTop && "out of sync");
+      updateScheduledPressure(TopRPTracker.getPressure().MaxSetPressure);
 
       // Release dependent instructions for scheduling.
       releaseSuccessors(SU);
@@ -602,6 +640,7 @@ void ScheduleDAGMI::schedule() {
       // Update bottom scheduled pressure.
       BotRPTracker.recede();
       assert(BotRPTracker.getPos() == CurrentBottom && "out of sync");
+      updateScheduledPressure(BotRPTracker.getPressure().MaxSetPressure);
 
       // Release dependent instructions for scheduling.
       releasePredecessors(SU);
@@ -654,6 +693,8 @@ struct ReadyQ {
 
   bool empty() const { return Queue.empty(); }
 
+  unsigned size() const { return Queue.size(); }
+
   iterator begin() { return Queue.begin(); }
 
   iterator end() { return Queue.end(); }
@@ -689,6 +730,9 @@ class ConvergingScheduler : public MachineSchedStrategy {
 
     SchedCandidate(): SU(NULL) {}
   };
+  /// Represent the type of SchedCandidate found within a single queue.
+  enum CandResult {
+    NoCand, NodeOrder, SingleExcess, SingleCritical, SingleMax, MultiPressure };
 
   ScheduleDAGMI *DAG;
   const TargetRegisterInfo *TRI;
@@ -732,88 +776,197 @@ public:
       BotQueue.push(SU);
   }
 protected:
+  SUnit *pickNodeBidrectional(bool &IsTopNode);
+
+  CandResult pickNodeFromQueue(ReadyQ &Q, const RegPressureTracker &RPTracker,
+                               SchedCandidate &Candidate);
 #ifndef NDEBUG
   void traceCandidate(const char *Label, unsigned QID, SUnit *SU,
-                      int RPDiff, unsigned PSetID);
+                      PressureElement P = PressureElement());
 #endif
-  bool pickNodeFromQueue(ReadyQ &Q, const RegPressureTracker &RPTracker,
-                         SchedCandidate &Candidate);
 };
 } // namespace
 
 #ifndef NDEBUG
 void ConvergingScheduler::
 traceCandidate(const char *Label, unsigned QID, SUnit *SU,
-               int RPDiff, unsigned PSetID) {
+               PressureElement P) {
   dbgs() << Label << getQName(QID) << " ";
-  if (RPDiff)
-    dbgs() << TRI->getRegPressureSetName(PSetID) << ":" << RPDiff << " ";
+  if (P.isValid())
+    dbgs() << TRI->getRegPressureSetName(P.PSetID) << ":" << P.UnitIncrease
+           << " ";
   else
     dbgs() << "     ";
   SU->dump(DAG);
 }
 #endif
 
+/// Return true if the LHS reg pressure effect is better than RHS.
+static bool compareRPDelta(const RegPressureDelta &LHS,
+                           const RegPressureDelta &RHS) {
+  // Compare each component of pressure in decreasing order of importance
+  // without checking if any are valid. Invalid PressureElements are assumed to
+  // have UnitIncrease==0, so are neutral.
+  if (LHS.Excess.UnitIncrease != RHS.Excess.UnitIncrease)
+    return LHS.Excess.UnitIncrease < RHS.Excess.UnitIncrease;
+
+  if (LHS.CriticalMax.UnitIncrease != RHS.CriticalMax.UnitIncrease)
+    return LHS.CriticalMax.UnitIncrease < RHS.CriticalMax.UnitIncrease;
+
+  if (LHS.CurrentMax.UnitIncrease != RHS.CurrentMax.UnitIncrease)
+    return LHS.CurrentMax.UnitIncrease < RHS.CurrentMax.UnitIncrease;
+
+  return false;
+}
+
+
 /// Pick the best candidate from the top queue.
 ///
 /// TODO: getMaxPressureDelta results can be mostly cached for each SUnit during
 /// DAG building. To adjust for the current scheduling location we need to
 /// maintain the number of vreg uses remaining to be top-scheduled.
-bool ConvergingScheduler::pickNodeFromQueue(ReadyQ &Q,
-                                            const RegPressureTracker &RPTracker,
-                                            SchedCandidate &Candidate) {
+ConvergingScheduler::CandResult ConvergingScheduler::
+pickNodeFromQueue(ReadyQ &Q, const RegPressureTracker &RPTracker,
+                  SchedCandidate &Candidate) {
+
   // getMaxPressureDelta temporarily modifies the tracker.
   RegPressureTracker &TempTracker = const_cast<RegPressureTracker&>(RPTracker);
 
   // BestSU remains NULL if no top candidates beat the best existing candidate.
-  bool FoundCandidate = false;
+  CandResult FoundCandidate = NoCand;
   for (ReadyQ::iterator I = Q.begin(), E = Q.end(); I != E; ++I) {
 
     RegPressureDelta RPDelta;
-    TempTracker.getMaxPressureDelta((*I)->getInstr(), RPDelta);
+    TempTracker.getMaxPressureDelta((*I)->getInstr(), RPDelta,
+                                    DAG->getRegionCriticalPSets(),
+                                    DAG->getRegPressure().MaxSetPressure);
 
+    // Initialize the candidate if needed.
+    if (!Candidate.SU) {
+      Candidate.SU = *I;
+      Candidate.RPDelta = RPDelta;
+      FoundCandidate = NodeOrder;
+      continue;
+    }
     // Avoid exceeding the target's limit.
-    if (!Candidate.SU || RPDelta.ExcessUnits < Candidate.RPDelta.ExcessUnits) {
-      DEBUG(traceCandidate(Candidate.SU ? "PCAND" : "ACAND", Q.ID, *I,
-                           RPDelta.ExcessUnits, RPDelta.ExcessSetID));
+    if (RPDelta.Excess.UnitIncrease < Candidate.RPDelta.Excess.UnitIncrease) {
+      DEBUG(traceCandidate("ECAND", Q.ID, *I, RPDelta.Excess));
       Candidate.SU = *I;
       Candidate.RPDelta = RPDelta;
-      FoundCandidate = true;
+      FoundCandidate = SingleExcess;
       continue;
     }
-    if (RPDelta.ExcessUnits > Candidate.RPDelta.ExcessUnits)
+    if (RPDelta.Excess.UnitIncrease > Candidate.RPDelta.Excess.UnitIncrease)
       continue;
+    if (FoundCandidate == SingleExcess)
+      FoundCandidate = MultiPressure;
 
-    // Avoid increasing the max pressure.
-    if (RPDelta.MaxUnitIncrease < Candidate.RPDelta.MaxUnitIncrease) {
-      DEBUG(traceCandidate("MCAND", Q.ID, *I,
-                           RPDelta.ExcessUnits, RPDelta.ExcessSetID));
+    // Avoid increasing the max critical pressure in the scheduled region.
+    if (RPDelta.CriticalMax.UnitIncrease
+        < Candidate.RPDelta.CriticalMax.UnitIncrease) {
+      DEBUG(traceCandidate("PCAND", Q.ID, *I, RPDelta.CriticalMax));
       Candidate.SU = *I;
       Candidate.RPDelta = RPDelta;
-      FoundCandidate = true;
+      FoundCandidate = SingleCritical;
       continue;
     }
-    if (RPDelta.MaxUnitIncrease > Candidate.RPDelta.MaxUnitIncrease)
+    if (RPDelta.CriticalMax.UnitIncrease
+        > Candidate.RPDelta.CriticalMax.UnitIncrease)
       continue;
+    if (FoundCandidate == SingleCritical)
+      FoundCandidate = MultiPressure;
+
+    // Avoid increasing the max pressure of the entire region.
+    if (RPDelta.CurrentMax.UnitIncrease
+        < Candidate.RPDelta.CurrentMax.UnitIncrease) {
+      DEBUG(traceCandidate("MCAND", Q.ID, *I, RPDelta.CurrentMax));
+      Candidate.SU = *I;
+      Candidate.RPDelta = RPDelta;
+      FoundCandidate = SingleMax;
+      continue;
+    }
+    if (RPDelta.CurrentMax.UnitIncrease
+        > Candidate.RPDelta.CurrentMax.UnitIncrease)
+      continue;
+    if (FoundCandidate == SingleMax)
+      FoundCandidate = MultiPressure;
 
     // Fall through to original instruction order.
-    // Only consider node order if BestSU was chosen from this Q.
-    if (!FoundCandidate)
+    // Only consider node order if Candidate was chosen from this Q.
+    if (FoundCandidate == NoCand)
       continue;
 
     if ((Q.ID == TopQID && (*I)->NodeNum < Candidate.SU->NodeNum)
         || (Q.ID == BotQID && (*I)->NodeNum > Candidate.SU->NodeNum)) {
-      DEBUG(traceCandidate("NCAND", Q.ID, *I, 0, 0));
+      DEBUG(traceCandidate("NCAND", Q.ID, *I));
       Candidate.SU = *I;
       Candidate.RPDelta = RPDelta;
-      FoundCandidate = true;
+      FoundCandidate = NodeOrder;
     }
   }
   return FoundCandidate;
 }
 
-/// Pick the best node from either the top or bottom queue to balance the
-/// schedule.
+/// Pick the best candidate node from either the top or bottom queue.
+SUnit *ConvergingScheduler::pickNodeBidrectional(bool &IsTopNode) {
+  // Schedule as far as possible in the direction of no choice. This is most
+  // efficient, but also provides the best heuristics for CriticalPSets.
+  if (BotQueue.size() == 1) {
+    IsTopNode = false;
+    return *BotQueue.begin();
+  }
+  if (TopQueue.size() == 1) {
+    IsTopNode = true;
+    return *TopQueue.begin();
+  }
+  SchedCandidate BotCandidate;
+  // Prefer bottom scheduling when heuristics are silent.
+  CandResult BotResult =
+    pickNodeFromQueue(BotQueue, DAG->getBotRPTracker(), BotCandidate);
+  assert(BotResult != NoCand && "failed to find the first candidate");
+
+  // If either Q has a single candidate that provides the least increase in
+  // Excess pressure, we can immediately schedule from that Q.
+  //
+  // RegionCriticalPSets summarizes the pressure within the scheduled region and
+  // affects picking from either Q. If scheduling in one direction must
+  // increase pressure for one of the excess PSets, then schedule in that
+  // direction first to provide more freedom in the other direction.
+  if (BotResult == SingleExcess || BotResult == SingleCritical) {
+    IsTopNode = false;
+    return BotCandidate.SU;
+  }
+  // Check if the top Q has a better candidate.
+  SchedCandidate TopCandidate;
+  CandResult TopResult =
+    pickNodeFromQueue(TopQueue, DAG->getTopRPTracker(), TopCandidate);
+  assert(TopResult != NoCand && "failed to find the first candidate");
+
+  if (TopResult == SingleExcess || TopResult == SingleCritical) {
+    IsTopNode = true;
+    return TopCandidate.SU;
+  }
+  // If either Q has a single candidate that minimizes pressure above the
+  // original region's pressure pick it.
+  if (BotResult == SingleMax) {
+    IsTopNode = false;
+    return BotCandidate.SU;
+  }
+  if (TopResult == SingleMax) {
+    IsTopNode = true;
+    return TopCandidate.SU;
+  }
+  // Check for a salient pressure difference and pick the best from either side.
+  if (compareRPDelta(TopCandidate.RPDelta, BotCandidate.RPDelta)) {
+    IsTopNode = true;
+    return TopCandidate.SU;
+  }
+  // Otherwise prefer the bottom candidate in node order.
+  IsTopNode = false;
+  return BotCandidate.SU;
+}
+
+/// Pick the best node to balance the schedule. Implements MachineSchedStrategy.
 SUnit *ConvergingScheduler::pickNode(bool &IsTopNode) {
   if (DAG->top() == DAG->bottom()) {
     assert(TopQueue.empty() && BotQueue.empty() && "ReadyQ garbage");
@@ -829,12 +982,7 @@ SUnit *ConvergingScheduler::pickNode(bool &IsTopNode) {
     IsTopNode = false;
   }
   else {
-    SchedCandidate Candidate;
-    // Prefer picking from the bottom.
-    pickNodeFromQueue(BotQueue, DAG->getBotRPTracker(), Candidate);
-    IsTopNode =
-      pickNodeFromQueue(TopQueue, DAG->getTopRPTracker(), Candidate);
-    SU = Candidate.SU;
+    SU = pickNodeBidrectional(IsTopNode);
   }
   if (SU->isTopReady()) {
     assert(!TopQueue.empty() && "bad ready count");
index 912ed0dd7b149a5bb42c6366d24e674cafef49bb..b30f76d05da645d26e28844e24084b638fd5a18c 100644 (file)
@@ -562,12 +562,13 @@ bool RegPressureTracker::advance() {
   return true;
 }
 
-// Find the max change in excess pressure across all sets.
-static int computeMaxPressureDelta(ArrayRef<unsigned> OldPressureVec,
-                                   ArrayRef<unsigned> NewPressureVec,
-                                   unsigned &PSetID,
-                                   const TargetRegisterInfo *TRI) {
+/// Find the max change in excess pressure across all sets.
+static void computeExcessPressureDelta(ArrayRef<unsigned> OldPressureVec,
+                                       ArrayRef<unsigned> NewPressureVec,
+                                       RegPressureDelta &Delta,
+                                       const TargetRegisterInfo *TRI) {
   int ExcessUnits = 0;
+  unsigned PSetID = ~0U;
   for (unsigned i = 0, e = OldPressureVec.size(); i < e; ++i) {
     unsigned POld = OldPressureVec[i];
     unsigned PNew = NewPressureVec[i];
@@ -590,7 +591,50 @@ static int computeMaxPressureDelta(ArrayRef<unsigned> OldPressureVec,
       PSetID = i;
     }
   }
-  return ExcessUnits;
+  Delta.Excess.PSetID = PSetID;
+  Delta.Excess.UnitIncrease = ExcessUnits;
+}
+
+/// Find the max change in max pressure that either surpasses a critical PSet
+/// limit or exceeds the current MaxPressureLimit.
+///
+/// FIXME: comparing each element of the old and new MaxPressure vectors here is
+/// silly. It's done now to demonstrate the concept but will go away with a
+/// RegPressureTracker API change to work with pressure differences.
+static void computeMaxPressureDelta(ArrayRef<unsigned> OldMaxPressureVec,
+                                    ArrayRef<unsigned> NewMaxPressureVec,
+                                    ArrayRef<PressureElement> CriticalPSets,
+                                    ArrayRef<unsigned> MaxPressureLimit,
+                                    RegPressureDelta &Delta) {
+  Delta.CriticalMax = PressureElement();
+  Delta.CurrentMax = PressureElement();
+
+  unsigned CritIdx = 0, CritEnd = CriticalPSets.size();
+  for (unsigned i = 0, e = OldMaxPressureVec.size(); i < e; ++i) {
+    unsigned POld = OldMaxPressureVec[i];
+    unsigned PNew = NewMaxPressureVec[i];
+    if (PNew == POld) // No change in this set in the common case.
+      continue;
+
+    while (CritIdx != CritEnd && CriticalPSets[CritIdx].PSetID < i)
+      ++CritIdx;
+
+    if (CritIdx != CritEnd && CriticalPSets[CritIdx].PSetID == i) {
+      int PDiff = (int)PNew - (int)CriticalPSets[CritIdx].UnitIncrease;
+      if (PDiff > Delta.CriticalMax.UnitIncrease) {
+        Delta.CriticalMax.PSetID = i;
+        Delta.CriticalMax.UnitIncrease = PDiff;
+      }
+    }
+
+    // Find the greatest increase above MaxPressureLimit.
+    // (Ignores negative MDiff).
+    int MDiff = (int)PNew - (int)MaxPressureLimit[i];
+    if (MDiff > Delta.CurrentMax.UnitIncrease) {
+      Delta.CurrentMax.PSetID = i;
+      Delta.CurrentMax.UnitIncrease = PNew;
+    }
+  }
 }
 
 /// Consider the pressure increase caused by traversing this instruction
@@ -605,13 +649,17 @@ static int computeMaxPressureDelta(ArrayRef<unsigned> OldPressureVec,
 /// 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) {
+getMaxUpwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta,
+                          ArrayRef<PressureElement> CriticalPSets,
+                          ArrayRef<unsigned> MaxPressureLimit) {
   // Account for register pressure similar to RegPressureTracker::recede().
   PhysRegOperands PhysRegOpers;
   VirtRegOperands VirtRegOpers;
   collectOperands(MI, PhysRegOpers, VirtRegOpers, TRI, RCI);
 
   // Snapshot Pressure.
+  // FIXME: The snapshot heap space should persist. But I'm planning to
+  // summarize the pressure effect so we don't need to snapshot at all.
   std::vector<unsigned> SavedPressure = CurrSetPressure;
   std::vector<unsigned> SavedMaxPressure = P.MaxSetPressure;
 
@@ -643,13 +691,11 @@ getMaxUpwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta) {
       increaseVirtRegPressure(Reg);
     }
   }
-  Delta.ExcessUnits =
-    computeMaxPressureDelta(SavedPressure, CurrSetPressure,
-                            Delta.ExcessSetID, TRI);
-  Delta.MaxUnitIncrease =
-    computeMaxPressureDelta(SavedMaxPressure, P.MaxSetPressure,
-                            Delta.MaxSetID, TRI);
-  assert(Delta.MaxUnitIncrease >= 0 && "cannot increase max pressure");
+  computeExcessPressureDelta(SavedPressure, CurrSetPressure, Delta, TRI);
+  computeMaxPressureDelta(SavedMaxPressure, P.MaxSetPressure, CriticalPSets,
+                          MaxPressureLimit, Delta);
+  assert(Delta.CriticalMax.UnitIncrease >= 0 &&
+         Delta.CurrentMax.UnitIncrease >= 0 && "cannot decrease max pressure");
 
   // Restore the tracker's state.
   P.MaxSetPressure.swap(SavedMaxPressure);
@@ -679,7 +725,9 @@ static bool findUseBetween(unsigned Reg,
 ///
 /// This assumes that the current LiveIn set is sufficient.
 void RegPressureTracker::
-getMaxDownwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta) {
+getMaxDownwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta,
+                            ArrayRef<PressureElement> CriticalPSets,
+                            ArrayRef<unsigned> MaxPressureLimit) {
   // Account for register pressure similar to RegPressureTracker::recede().
   PhysRegOperands PhysRegOpers;
   VirtRegOperands VirtRegOpers;
@@ -717,12 +765,11 @@ getMaxDownwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta) {
   decreasePhysRegPressure(PhysRegOpers.DeadDefs);
   decreaseVirtRegPressure(VirtRegOpers.DeadDefs);
 
-  Delta.ExcessUnits =
-    computeMaxPressureDelta(SavedPressure, CurrSetPressure,
-                            Delta.ExcessSetID, TRI);
-  Delta.MaxUnitIncrease =
-    computeMaxPressureDelta(SavedMaxPressure, P.MaxSetPressure,
-                            Delta.MaxSetID, TRI);
+  computeExcessPressureDelta(SavedPressure, CurrSetPressure, Delta, TRI);
+  computeMaxPressureDelta(SavedMaxPressure, P.MaxSetPressure, CriticalPSets,
+                          MaxPressureLimit, Delta);
+  assert(Delta.CriticalMax.UnitIncrease >= 0 &&
+         Delta.CurrentMax.UnitIncrease >= 0 && "cannot decrease max pressure");
 
   // Restore the tracker's state.
   P.MaxSetPressure.swap(SavedMaxPressure);
index b1d13784018495ba2324b8d553d67f7562f78ddc..b4244800900f828d072afecf4811ee3c8f911961 100644 (file)
@@ -80,28 +80,38 @@ struct RegionPressure : RegisterPressure {
   void openBottom(MachineBasicBlock::const_iterator PrevBottom);
 };
 
-/// Store the results of a change in pressure.
+/// 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;
+
+  PressureElement(): PSetID(~0U), UnitIncrease(0) {}
+  PressureElement(unsigned id, int inc): PSetID(id), UnitIncrease(inc) {}
+
+  bool isValid() const { return PSetID != ~0U; }
+};
+
+/// Store the effects of a change in pressure on things that MI scheduler cares
+/// about.
 ///
-/// ExcessUnits is the value of the largest difference in register units beyond
+/// Excess records the value of the largest difference in register units beyond
 /// the target's pressure limits across the affected pressure sets, where
 /// largest is defined as the absolute value of the difference. Negative
 /// ExcessUnits indicates a reduction in pressure that had already exceeded the
 /// target's limits.
 ///
-/// MaxUnitIncrease is the largest increase in register units required across
-/// the scheduled region across the affected pressure sets, regardless of the
-/// target's pressure limits.
+/// CriticalMax records the largest increase in the tracker's max pressure that
+/// exceeds the critical limit for some pressure set determined by the client.
 ///
-/// If ExcessUnits == 0, then ExcessSetID is invalid.
-/// If MaxUnitIncrease == 0, then MaxSetID is invalid.
+/// 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 {
-  int ExcessUnits;
-  unsigned ExcessSetID;
-  int MaxUnitIncrease;
-  unsigned MaxSetID;
+  PressureElement Excess;
+  PressureElement CriticalMax;
+  PressureElement CurrentMax;
 
-  RegPressureDelta():
-    ExcessUnits(0), ExcessSetID(~0U), MaxUnitIncrease(0), MaxSetID(~0U) {}
+  RegPressureDelta() {}
 };
 
 /// Track the current register pressure at some position in the instruction
@@ -203,24 +213,32 @@ 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,
-                                 RegPressureDelta &Delta);
+                                 RegPressureDelta &Delta,
+                                 ArrayRef<PressureElement> CriticalPSets,
+                                 ArrayRef<unsigned> MaxPressureLimit);
 
   /// 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);
+                                   RegPressureDelta &Delta,
+                                   ArrayRef<PressureElement> 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) {
+  void getMaxPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta,
+                           ArrayRef<PressureElement> CriticalPSets,
+                           ArrayRef<unsigned> MaxPressureLimit) {
     if (isTopClosed())
-      return getMaxDownwardPressureDelta(MI, Delta);
+      return getMaxDownwardPressureDelta(MI, Delta, CriticalPSets,
+                                         MaxPressureLimit);
 
     assert(isBottomClosed() && "Uninitialized pressure tracker");
-    return getMaxUpwardPressureDelta(MI, Delta);
+    return getMaxUpwardPressureDelta(MI, Delta, CriticalPSets,
+                                     MaxPressureLimit);
   }
 
 protected: