diff --git a/lib/CodeGen/MachineScheduler.cpp b/lib/CodeGen/MachineScheduler.cpp index 1d810fdf16d..57f3506d8e8 100644 --- a/lib/CodeGen/MachineScheduler.cpp +++ b/lib/CodeGen/MachineScheduler.cpp @@ -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 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 &getRegionCriticalPSets() const { + return RegionCriticalPSets; + } + protected: void initRegPressure(); + void updateScheduledPressure(std::vector 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 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 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(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"); diff --git a/lib/CodeGen/RegisterPressure.cpp b/lib/CodeGen/RegisterPressure.cpp index 912ed0dd7b1..b30f76d05da 100644 --- a/lib/CodeGen/RegisterPressure.cpp +++ b/lib/CodeGen/RegisterPressure.cpp @@ -562,12 +562,13 @@ bool RegPressureTracker::advance() { return true; } -// Find the max change in excess pressure across all sets. -static int computeMaxPressureDelta(ArrayRef OldPressureVec, - ArrayRef NewPressureVec, - unsigned &PSetID, - const TargetRegisterInfo *TRI) { +/// Find the max change in excess pressure across all sets. +static void computeExcessPressureDelta(ArrayRef OldPressureVec, + ArrayRef 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 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 OldMaxPressureVec, + ArrayRef NewMaxPressureVec, + ArrayRef CriticalPSets, + ArrayRef 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 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 CriticalPSets, + ArrayRef 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 SavedPressure = CurrSetPressure; std::vector 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 CriticalPSets, + ArrayRef 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); diff --git a/lib/CodeGen/RegisterPressure.h b/lib/CodeGen/RegisterPressure.h index b1d13784018..b4244800900 100644 --- a/lib/CodeGen/RegisterPressure.h +++ b/lib/CodeGen/RegisterPressure.h @@ -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 CriticalPSets, + ArrayRef 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 CriticalPSets, + ArrayRef 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 CriticalPSets, + ArrayRef 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: