//===- RegisterPressure.cpp - Dynamic Register Pressure -------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements the RegisterPressure class which can be used to track
// MachineInstr level register pressure.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/RegisterPressure.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/LiveInterval.h"
#include "llvm/CodeGen/LiveIntervals.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBundle.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterClassInfo.h"
#include "llvm/CodeGen/SlotIndexes.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/MC/LaneBitmask.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <iterator>
#include <limits>
#include <utility>
#include <vector>

using namespace llvm;

/// Increase pressure for each pressure set provided by TargetRegisterInfo.
static void increaseSetPressure(std::vector<unsigned> &CurrSetPressure,
                                const MachineRegisterInfo &MRI,
                                VirtRegOrUnit VRegOrUnit, LaneBitmask PrevMask,
                                LaneBitmask NewMask) {
  assert((PrevMask & ~NewMask).none() && "Must not remove bits");
  if (PrevMask.any() || NewMask.none())
    return;

  PSetIterator PSetI = MRI.getPressureSets(VRegOrUnit);
  unsigned Weight = PSetI.getWeight();
  for (; PSetI.isValid(); ++PSetI)
    CurrSetPressure[*PSetI] += Weight;
}

/// Decrease pressure for each pressure set provided by TargetRegisterInfo.
static void decreaseSetPressure(std::vector<unsigned> &CurrSetPressure,
                                const MachineRegisterInfo &MRI,
                                VirtRegOrUnit VRegOrUnit, LaneBitmask PrevMask,
                                LaneBitmask NewMask) {
  assert((NewMask & ~PrevMask).none() && "Must not add bits");
  if (NewMask.any() || PrevMask.none())
    return;

  PSetIterator PSetI = MRI.getPressureSets(VRegOrUnit);
  unsigned Weight = PSetI.getWeight();
  for (; PSetI.isValid(); ++PSetI) {
    assert(CurrSetPressure[*PSetI] >= Weight && "register pressure underflow");
    CurrSetPressure[*PSetI] -= Weight;
  }
}

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD
void llvm::dumpRegSetPressure(ArrayRef<unsigned> SetPressure,
                              const TargetRegisterInfo *TRI) {
  for (unsigned i = 0, e = SetPressure.size(); i < e; ++i) {
    if (SetPressure[i] != 0) {
      dbgs() << TRI->getRegPressureSetName(i) << "=" << SetPressure[i] << ' ';
    }
  }
  dbgs() << "\n";
}

LLVM_DUMP_METHOD
void RegisterPressure::dump(const TargetRegisterInfo *TRI) const {
  dbgs() << "Max Pressure: ";
  dumpRegSetPressure(MaxSetPressure, TRI);
  dbgs() << "Live In: ";
  for (const VRegMaskOrUnit &P : LiveInRegs) {
    dbgs() << printVRegOrUnit(P.VRegOrUnit, TRI);
    if (!P.LaneMask.all())
      dbgs() << ':' << PrintLaneMask(P.LaneMask);
    dbgs() << ' ';
  }
  dbgs() << '\n';
  dbgs() << "Live Out: ";
  for (const VRegMaskOrUnit &P : LiveOutRegs) {
    dbgs() << printVRegOrUnit(P.VRegOrUnit, TRI);
    if (!P.LaneMask.all())
      dbgs() << ':' << PrintLaneMask(P.LaneMask);
    dbgs() << ' ';
  }
  dbgs() << '\n';
}

LLVM_DUMP_METHOD
void RegPressureTracker::dump() const {
  if (!isTopClosed() || !isBottomClosed()) {
    dbgs() << "Curr Pressure: ";
    dumpRegSetPressure(CurrSetPressure, TRI);
  }
  P.dump(TRI);
}

LLVM_DUMP_METHOD
void PressureDiff::dump(const TargetRegisterInfo &TRI) const {
  const char *sep = "";
  for (const PressureChange &Change : *this) {
    if (!Change.isValid())
      break;
    dbgs() << sep << TRI.getRegPressureSetName(Change.getPSet())
           << " " << Change.getUnitInc();
    sep = "    ";
  }
  dbgs() << '\n';
}

LLVM_DUMP_METHOD
void PressureChange::dump() const {
  dbgs() << "[" << getPSetOrMax() << ", " << getUnitInc() << "]\n";
}

void RegPressureDelta::dump() const {
  dbgs() << "[Excess=";
  Excess.dump();
  dbgs() << ", CriticalMax=";
  CriticalMax.dump();
  dbgs() << ", CurrentMax=";
  CurrentMax.dump();
  dbgs() << "]\n";
}

#endif

void RegPressureTracker::increaseRegPressure(VirtRegOrUnit VRegOrUnit,
                                             LaneBitmask PreviousMask,
                                             LaneBitmask NewMask) {
  if (PreviousMask.any() || NewMask.none())
    return;

  PSetIterator PSetI = MRI->getPressureSets(VRegOrUnit);
  unsigned Weight = PSetI.getWeight();
  for (; PSetI.isValid(); ++PSetI) {
    CurrSetPressure[*PSetI] += Weight;
    P.MaxSetPressure[*PSetI] =
        std::max(P.MaxSetPressure[*PSetI], CurrSetPressure[*PSetI]);
  }
}

void RegPressureTracker::decreaseRegPressure(VirtRegOrUnit VRegOrUnit,
                                             LaneBitmask PreviousMask,
                                             LaneBitmask NewMask) {
  decreaseSetPressure(CurrSetPressure, *MRI, VRegOrUnit, PreviousMask, NewMask);
}

/// Clear the result so it can be used for another round of pressure tracking.
void IntervalPressure::reset() {
  TopIdx = BottomIdx = SlotIndex();
  MaxSetPressure.clear();
  LiveInRegs.clear();
  LiveOutRegs.clear();
}

/// Clear the result so it can be used for another round of pressure tracking.
void RegionPressure::reset() {
  TopPos = BottomPos = MachineBasicBlock::const_iterator();
  MaxSetPressure.clear();
  LiveInRegs.clear();
  LiveOutRegs.clear();
}

/// If the current top is not less than or equal to the next index, open it.
/// We happen to need the SlotIndex for the next top for pressure update.
void IntervalPressure::openTop(SlotIndex NextTop) {
  if (TopIdx <= NextTop)
    return;
  TopIdx = SlotIndex();
  LiveInRegs.clear();
}

/// If the current top is the previous instruction (before receding), open it.
void RegionPressure::openTop(MachineBasicBlock::const_iterator PrevTop) {
  if (TopPos != PrevTop)
    return;
  TopPos = MachineBasicBlock::const_iterator();
  LiveInRegs.clear();
}

/// If the current bottom is not greater than the previous index, open it.
void IntervalPressure::openBottom(SlotIndex PrevBottom) {
  if (BottomIdx > PrevBottom)
    return;
  BottomIdx = SlotIndex();
  LiveInRegs.clear();
}

/// If the current bottom is the previous instr (before advancing), open it.
void RegionPressure::openBottom(MachineBasicBlock::const_iterator PrevBottom) {
  if (BottomPos != PrevBottom)
    return;
  BottomPos = MachineBasicBlock::const_iterator();
  LiveInRegs.clear();
}

void LiveRegSet::init(const MachineRegisterInfo &MRI) {
  const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
  unsigned NumRegUnits = TRI.getNumRegs();
  unsigned NumVirtRegs = MRI.getNumVirtRegs();
  Regs.setUniverse(NumRegUnits + NumVirtRegs);
  this->NumRegUnits = NumRegUnits;
}

void LiveRegSet::clear() {
  Regs.clear();
}

void RegPressureTracker::reset() {
  MBB = nullptr;
  LIS = nullptr;

  CurrSetPressure.clear();
  LiveThruPressure.clear();
  P.MaxSetPressure.clear();

  if (RequireIntervals)
    static_cast<IntervalPressure&>(P).reset();
  else
    static_cast<RegionPressure&>(P).reset();

  LiveRegs.clear();
  UntiedDefs.clear();
}

/// Setup the RegPressureTracker.
///
/// TODO: Add support for pressure without LiveIntervals.
void RegPressureTracker::init(const MachineFunction *mf,
                              const RegisterClassInfo *rci,
                              const LiveIntervals *lis,
                              const MachineBasicBlock *mbb,
                              MachineBasicBlock::const_iterator pos,
                              bool TrackLaneMasks, bool TrackUntiedDefs) {
  reset();

  MF = mf;
  TRI = MF->getSubtarget().getRegisterInfo();
  RCI = rci;
  MRI = &MF->getRegInfo();
  MBB = mbb;
  this->TrackUntiedDefs = TrackUntiedDefs;
  this->TrackLaneMasks = TrackLaneMasks;

  if (RequireIntervals) {
    assert(lis && "IntervalPressure requires LiveIntervals");
    LIS = lis;
  }

  CurrPos = pos;
  CurrSetPressure.assign(TRI->getNumRegPressureSets(), 0);

  P.MaxSetPressure = CurrSetPressure;

  LiveRegs.init(*MRI);
  if (TrackUntiedDefs)
    UntiedDefs.setUniverse(MRI->getNumVirtRegs());
}

/// Does this pressure result have a valid top position and live ins.
bool RegPressureTracker::isTopClosed() const {
  if (RequireIntervals)
    return static_cast<IntervalPressure&>(P).TopIdx.isValid();
  return (static_cast<RegionPressure&>(P).TopPos ==
          MachineBasicBlock::const_iterator());
}

/// Does this pressure result have a valid bottom position and live outs.
bool RegPressureTracker::isBottomClosed() const {
  if (RequireIntervals)
    return static_cast<IntervalPressure&>(P).BottomIdx.isValid();
  return (static_cast<RegionPressure&>(P).BottomPos ==
          MachineBasicBlock::const_iterator());
}

SlotIndex RegPressureTracker::getCurrSlot() const {
  MachineBasicBlock::const_iterator IdxPos =
    skipDebugInstructionsForward(CurrPos, MBB->end());
  if (IdxPos == MBB->end())
    return LIS->getMBBEndIdx(MBB);
  return LIS->getInstructionIndex(*IdxPos).getRegSlot();
}

/// Set the boundary for the top of the region and summarize live ins.
void RegPressureTracker::closeTop() {
  if (RequireIntervals)
    static_cast<IntervalPressure&>(P).TopIdx = getCurrSlot();
  else
    static_cast<RegionPressure&>(P).TopPos = CurrPos;

  assert(P.LiveInRegs.empty() && "inconsistent max pressure result");
  P.LiveInRegs.reserve(LiveRegs.size());
  LiveRegs.appendTo(P.LiveInRegs);
}

/// Set the boundary for the bottom of the region and summarize live outs.
void RegPressureTracker::closeBottom() {
  if (RequireIntervals)
    static_cast<IntervalPressure&>(P).BottomIdx = getCurrSlot();
  else
    static_cast<RegionPressure&>(P).BottomPos = CurrPos;

  assert(P.LiveOutRegs.empty() && "inconsistent max pressure result");
  P.LiveOutRegs.reserve(LiveRegs.size());
  LiveRegs.appendTo(P.LiveOutRegs);
}

/// Finalize the region boundaries and record live ins and live outs.
void RegPressureTracker::closeRegion() {
  if (!isTopClosed() && !isBottomClosed()) {
    assert(LiveRegs.size() == 0 && "no region boundary");
    return;
  }
  if (!isBottomClosed())
    closeBottom();
  else if (!isTopClosed())
    closeTop();
  // If both top and bottom are closed, do nothing.
}

/// The register tracker is unaware of global liveness so ignores normal
/// live-thru ranges. However, two-address or coalesced chains can also lead
/// to live ranges with no holes. Count these to inform heuristics that we
/// can never drop below this pressure.
void RegPressureTracker::initLiveThru(const RegPressureTracker &RPTracker) {
  LiveThruPressure.assign(TRI->getNumRegPressureSets(), 0);
  assert(isBottomClosed() && "need bottom-up tracking to initialize.");
  for (const VRegMaskOrUnit &Pair : P.LiveOutRegs) {
    VirtRegOrUnit VRegOrUnit = Pair.VRegOrUnit;
    if (VRegOrUnit.isVirtualReg() &&
        !RPTracker.hasUntiedDef(VRegOrUnit.asVirtualReg()))
      increaseSetPressure(LiveThruPressure, *MRI, VRegOrUnit,
                          LaneBitmask::getNone(), Pair.LaneMask);
  }
}

static LaneBitmask getRegLanes(ArrayRef<VRegMaskOrUnit> RegUnits,
                               VirtRegOrUnit VRegOrUnit) {
  auto I = llvm::find_if(RegUnits, [VRegOrUnit](const VRegMaskOrUnit Other) {
    return Other.VRegOrUnit == VRegOrUnit;
  });
  if (I == RegUnits.end())
    return LaneBitmask::getNone();
  return I->LaneMask;
}

static void addRegLanes(SmallVectorImpl<VRegMaskOrUnit> &RegUnits,
                        VRegMaskOrUnit Pair) {
  VirtRegOrUnit VRegOrUnit = Pair.VRegOrUnit;
  assert(Pair.LaneMask.any());
  auto I = llvm::find_if(RegUnits, [VRegOrUnit](const VRegMaskOrUnit Other) {
    return Other.VRegOrUnit == VRegOrUnit;
  });
  if (I == RegUnits.end()) {
    RegUnits.push_back(Pair);
  } else {
    I->LaneMask |= Pair.LaneMask;
  }
}

static void setRegZero(SmallVectorImpl<VRegMaskOrUnit> &RegUnits,
                       VirtRegOrUnit VRegOrUnit) {
  auto I = llvm::find_if(RegUnits, [VRegOrUnit](const VRegMaskOrUnit Other) {
    return Other.VRegOrUnit == VRegOrUnit;
  });
  if (I == RegUnits.end()) {
    RegUnits.emplace_back(VRegOrUnit, LaneBitmask::getNone());
  } else {
    I->LaneMask = LaneBitmask::getNone();
  }
}

static void removeRegLanes(SmallVectorImpl<VRegMaskOrUnit> &RegUnits,
                           VRegMaskOrUnit Pair) {
  VirtRegOrUnit VRegOrUnit = Pair.VRegOrUnit;
  assert(Pair.LaneMask.any());
  auto I = llvm::find_if(RegUnits, [VRegOrUnit](const VRegMaskOrUnit Other) {
    return Other.VRegOrUnit == VRegOrUnit;
  });
  if (I != RegUnits.end()) {
    I->LaneMask &= ~Pair.LaneMask;
    if (I->LaneMask.none())
      RegUnits.erase(I);
  }
}

static LaneBitmask
getLanesWithProperty(const LiveIntervals &LIS, const MachineRegisterInfo &MRI,
                     bool TrackLaneMasks, VirtRegOrUnit VRegOrUnit,
                     SlotIndex Pos, LaneBitmask SafeDefault,
                     bool (*Property)(const LiveRange &LR, SlotIndex Pos)) {
  if (VRegOrUnit.isVirtualReg()) {
    const LiveInterval &LI = LIS.getInterval(VRegOrUnit.asVirtualReg());
    LaneBitmask Result;
    if (TrackLaneMasks && LI.hasSubRanges()) {
        for (const LiveInterval::SubRange &SR : LI.subranges()) {
          if (Property(SR, Pos))
            Result |= SR.LaneMask;
        }
    } else if (Property(LI, Pos)) {
      Result = TrackLaneMasks
                   ? MRI.getMaxLaneMaskForVReg(VRegOrUnit.asVirtualReg())
                   : LaneBitmask::getAll();
    }

    return Result;
  } else {
    const LiveRange *LR = LIS.getCachedRegUnit(VRegOrUnit.asMCRegUnit());
    // Be prepared for missing liveranges: We usually do not compute liveranges
    // for physical registers on targets with many registers (GPUs).
    if (LR == nullptr)
      return SafeDefault;
    return Property(*LR, Pos) ? LaneBitmask::getAll() : LaneBitmask::getNone();
  }
}

static LaneBitmask getLiveLanesAt(const LiveIntervals &LIS,
                                  const MachineRegisterInfo &MRI,
                                  bool TrackLaneMasks, VirtRegOrUnit VRegOrUnit,
                                  SlotIndex Pos) {
  return getLanesWithProperty(
      LIS, MRI, TrackLaneMasks, VRegOrUnit, Pos, LaneBitmask::getAll(),
      [](const LiveRange &LR, SlotIndex Pos) { return LR.liveAt(Pos); });
}

namespace {

/// Collect this instruction's unique uses and defs into SmallVectors for
/// processing defs and uses in order.
///
/// FIXME: always ignore tied opers
class RegisterOperandsCollector {
  friend class llvm::RegisterOperands;

  RegisterOperands &RegOpers;
  const TargetRegisterInfo &TRI;
  const MachineRegisterInfo &MRI;
  bool IgnoreDead;

  RegisterOperandsCollector(RegisterOperands &RegOpers,
                            const TargetRegisterInfo &TRI,
                            const MachineRegisterInfo &MRI, bool IgnoreDead)
    : RegOpers(RegOpers), TRI(TRI), MRI(MRI), IgnoreDead(IgnoreDead) {}

  void collectInstr(const MachineInstr &MI) const {
    for (ConstMIBundleOperands OperI(MI); OperI.isValid(); ++OperI)
      collectOperand(*OperI);

    // An instruction can have overlapping defs where only some carry the dead
    // flag, for example a dead super-register def alongside a live sub-register
    // def. A register unit is dead if any def covering it is dead, so subtract
    // the dead defs from the live defs.
    for (const VRegMaskOrUnit &P : RegOpers.DeadDefs)
      removeRegLanes(RegOpers.Defs, P);
  }

  void collectInstrLanes(const MachineInstr &MI) const {
    for (ConstMIBundleOperands OperI(MI); OperI.isValid(); ++OperI)
      collectOperandLanes(*OperI);

    // A register unit is dead if any def covering it is dead; subtract the
    // dead defs from the live defs so overlapping defs do not leave a unit
    // counted as live. See collectInstr.
    for (const VRegMaskOrUnit &P : RegOpers.DeadDefs)
      removeRegLanes(RegOpers.Defs, P);
  }

  /// Push this operand's register onto the correct vectors.
  void collectOperand(const MachineOperand &MO) const {
    if (!MO.isReg() || !MO.getReg())
      return;
    Register Reg = MO.getReg();
    if (MO.isUse()) {
      if (!MO.isUndef() && !MO.isInternalRead())
        pushReg(Reg, RegOpers.Uses);
    } else {
      assert(MO.isDef());
      // Subregister definitions may imply a register read.
      if (MO.readsReg())
        pushReg(Reg, RegOpers.Uses);

      if (MO.isDead()) {
        if (!IgnoreDead)
          pushReg(Reg, RegOpers.DeadDefs);
      } else
        pushReg(Reg, RegOpers.Defs);
    }
  }

  void pushReg(Register Reg, SmallVectorImpl<VRegMaskOrUnit> &RegUnits) const {
    if (Reg.isVirtual()) {
      addRegLanes(RegUnits,
                  VRegMaskOrUnit(VirtRegOrUnit(Reg), LaneBitmask::getAll()));
    } else if (MRI.isAllocatable(Reg)) {
      for (MCRegUnit Unit : TRI.regunits(Reg.asMCReg()))
        addRegLanes(RegUnits,
                    VRegMaskOrUnit(VirtRegOrUnit(Unit), LaneBitmask::getAll()));
    }
  }

  void collectOperandLanes(const MachineOperand &MO) const {
    if (!MO.isReg() || !MO.getReg())
      return;
    Register Reg = MO.getReg();
    unsigned SubRegIdx = MO.getSubReg();
    if (MO.isUse()) {
      if (!MO.isUndef() && !MO.isInternalRead())
        pushRegLanes(Reg, SubRegIdx, RegOpers.Uses);
    } else {
      assert(MO.isDef());
      // Treat read-undef subreg defs as definitions of the whole register.
      if (MO.isUndef())
        SubRegIdx = 0;

      if (MO.isDead()) {
        if (!IgnoreDead)
          pushRegLanes(Reg, SubRegIdx, RegOpers.DeadDefs);
      } else
        pushRegLanes(Reg, SubRegIdx, RegOpers.Defs);
    }
  }

  void pushRegLanes(Register Reg, unsigned SubRegIdx,
                    SmallVectorImpl<VRegMaskOrUnit> &RegUnits) const {
    if (Reg.isVirtual()) {
      LaneBitmask LaneMask = SubRegIdx != 0
                             ? TRI.getSubRegIndexLaneMask(SubRegIdx)
                             : MRI.getMaxLaneMaskForVReg(Reg);
      addRegLanes(RegUnits, VRegMaskOrUnit(VirtRegOrUnit(Reg), LaneMask));
    } else if (MRI.isAllocatable(Reg)) {
      for (MCRegUnit Unit : TRI.regunits(Reg.asMCReg()))
        addRegLanes(RegUnits,
                    VRegMaskOrUnit(VirtRegOrUnit(Unit), LaneBitmask::getAll()));
    }
  }
};

} // end anonymous namespace

void RegisterOperands::collect(const MachineInstr &MI,
                               const TargetRegisterInfo &TRI,
                               const MachineRegisterInfo &MRI,
                               bool TrackLaneMasks, bool IgnoreDead) {
  RegisterOperandsCollector Collector(*this, TRI, MRI, IgnoreDead);
  if (TrackLaneMasks)
    Collector.collectInstrLanes(MI);
  else
    Collector.collectInstr(MI);
}

void RegisterOperands::detectDeadDefs(const MachineInstr &MI,
                                      const LiveIntervals &LIS,
                                      const MachineRegisterInfo &MRI) {
  SlotIndex DeadSlotIdx = LIS.getInstructionIndex(MI).getDeadSlot();
  for (auto *I = Defs.begin(); I != Defs.end(); /*empty*/) {
    LaneBitmask LiveAfter = getLiveLanesAt(LIS, MRI, /*TrackLaneMasks=*/false,
                                           I->VRegOrUnit, DeadSlotIdx);
    I = adjustDef(*I, LiveAfter);
  }
}

void RegisterOperands::adjustLaneLiveness(const LiveIntervals &LIS,
                                          const MachineRegisterInfo &MRI,
                                          SlotIndex Pos) {
  for (auto *I = Defs.begin(); I != Defs.end(); /*empty*/) {
    LaneBitmask LiveAfter = getLiveLanesAt(LIS, MRI, /*TrackLaneMasks=*/true,
                                           I->VRegOrUnit, Pos.getDeadSlot());
    I = adjustDef(*I, LiveAfter);
  }
  adjustUses(LIS, MRI, Pos.getBaseIndex());
}

void RegisterOperands::adjustLaneLiveness(const LiveIntervals &LIS,
                                          const MachineRegisterInfo &MRI,
                                          MachineInstr &MI) {
  SlotIndex Pos = LIS.getInstructionIndex(MI);
  for (auto *I = Defs.begin(); I != Defs.end(); /*empty*/) {
    LaneBitmask LiveAfter = getLiveLanesAt(LIS, MRI, /*TrackLaneMasks=*/true,
                                           I->VRegOrUnit, Pos.getDeadSlot());
    // If the def is all that is live after the instruction, then in case
    // of a subregister def we need a read-undef flag.
    VirtRegOrUnit VRegOrUnit = I->VRegOrUnit;
    if (VRegOrUnit.isVirtualReg() && (LiveAfter & ~I->LaneMask).none())
      MI.setRegisterDefReadUndef(VRegOrUnit.asVirtualReg());
    I = adjustDef(*I, LiveAfter);
  }

  adjustUses(LIS, MRI, Pos);

  const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
  for (const VRegMaskOrUnit &P : DeadDefs) {
    VirtRegOrUnit VRegOrUnit = P.VRegOrUnit;
    if (!VRegOrUnit.isVirtualReg())
      continue;
    Register VReg = VRegOrUnit.asVirtualReg();
    LaneBitmask LiveAfter = getLiveLanesAt(LIS, MRI, /*TrackLaneMasks=*/true,
                                           VRegOrUnit, Pos.getDeadSlot());
    if (!LiveAfter.none())
      continue;
    // The register's read value doesn't matter if none of its lanes are live
    // after the def.
    MI.setRegisterDefReadUndef(VReg);

    // The register's last definition should be marked dead.
    const LiveInterval &LI = LIS.getInterval(VReg);
    if (LI.segments.back().end == Pos.getDeadSlot())
      MI.addRegisterDead(VReg, TRI, /*AddIfNotFound=*/false);
  }
}

VRegMaskOrUnit *RegisterOperands::adjustDef(VRegMaskOrUnit &Def,
                                            LaneBitmask LiveAfterDef) {
  LaneBitmask ActualDef = Def.LaneMask & LiveAfterDef;
  if (ActualDef.none()) {
    DeadDefs.push_back(Def);
    return Defs.erase(&Def);
  }

  Def.LaneMask = ActualDef;
  return &Def + 1;
}

void RegisterOperands::adjustUses(const LiveIntervals &LIS,
                                  const MachineRegisterInfo &MRI,
                                  SlotIndex Pos) {
  for (auto &[VRegOrUnit, LaneMask] : Uses) {
    LaneMask =
        getLiveLanesAt(LIS, MRI, /*TrackLaneMasks=*/true, VRegOrUnit, Pos);
  }
}

/// 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 = static_cast<PressureDiff*>(safe_calloc(N, sizeof(PressureDiff)));
}

void PressureDiffs::addInstruction(unsigned Idx,
                                   const RegisterOperands &RegOpers,
                                   const MachineRegisterInfo &MRI) {
  PressureDiff &PDiff = (*this)[Idx];
  assert(!PDiff.begin()->isValid() && "stale PDiff");
  for (const VRegMaskOrUnit &P : RegOpers.Defs)
    PDiff.addPressureChange(P.VRegOrUnit, true, &MRI);

  for (const VRegMaskOrUnit &P : RegOpers.Uses)
    PDiff.addPressureChange(P.VRegOrUnit, false, &MRI);
}

/// Add a change in pressure to the pressure diff of a given instruction.
void PressureDiff::addPressureChange(VirtRegOrUnit VRegOrUnit, bool IsDec,
                                     const MachineRegisterInfo *MRI) {
  PSetIterator PSetI = MRI->getPressureSets(VRegOrUnit);
  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 = nonconst_begin(), E = nonconst_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.
    unsigned NewUnitInc = I->getUnitInc() + Weight;
    if (NewUnitInc != 0) {
      I->setUnitInc(NewUnitInc);
    } else {
      // Remove entry
      PressureDiff::iterator J;
      for (J = std::next(I); J != E && J->isValid(); ++J, ++I)
        *I = *J;
      *I = PressureChange();
    }
  }
}

/// Force liveness of registers.
void RegPressureTracker::addLiveRegs(ArrayRef<VRegMaskOrUnit> Regs) {
  for (const VRegMaskOrUnit &P : Regs) {
    LaneBitmask PrevMask = LiveRegs.insert(P);
    LaneBitmask NewMask = PrevMask | P.LaneMask;
    increaseRegPressure(P.VRegOrUnit, PrevMask, NewMask);
  }
}

void RegPressureTracker::discoverLiveInOrOut(
    VRegMaskOrUnit Pair, SmallVectorImpl<VRegMaskOrUnit> &LiveInOrOut) {
  assert(Pair.LaneMask.any());

  VirtRegOrUnit VRegOrUnit = Pair.VRegOrUnit;
  auto I = find_if(LiveInOrOut, [VRegOrUnit](const VRegMaskOrUnit &Other) {
    return Other.VRegOrUnit == VRegOrUnit;
  });
  LaneBitmask PrevMask;
  LaneBitmask NewMask;
  if (I == LiveInOrOut.end()) {
    PrevMask = LaneBitmask::getNone();
    NewMask = Pair.LaneMask;
    LiveInOrOut.push_back(Pair);
  } else {
    PrevMask = I->LaneMask;
    NewMask = PrevMask | Pair.LaneMask;
    I->LaneMask = NewMask;
  }
  increaseSetPressure(P.MaxSetPressure, *MRI, VRegOrUnit, PrevMask, NewMask);
}

void RegPressureTracker::discoverLiveIn(VRegMaskOrUnit Pair) {
  discoverLiveInOrOut(Pair, P.LiveInRegs);
}

void RegPressureTracker::discoverLiveOut(VRegMaskOrUnit Pair) {
  discoverLiveInOrOut(Pair, P.LiveOutRegs);
}

void RegPressureTracker::bumpDeadDefs(ArrayRef<VRegMaskOrUnit> DeadDefs) {
  for (const VRegMaskOrUnit &P : DeadDefs) {
    LaneBitmask LiveMask = LiveRegs.contains(P.VRegOrUnit);
    LaneBitmask BumpedMask = LiveMask | P.LaneMask;
    increaseRegPressure(P.VRegOrUnit, LiveMask, BumpedMask);
  }
  for (const VRegMaskOrUnit &P : DeadDefs) {
    LaneBitmask LiveMask = LiveRegs.contains(P.VRegOrUnit);
    LaneBitmask BumpedMask = LiveMask | P.LaneMask;
    decreaseRegPressure(P.VRegOrUnit, BumpedMask, LiveMask);
  }
}

/// Recede across the previous instruction. If LiveUses is provided, record any
/// RegUnits that are made live by the current instruction's uses. This includes
/// registers that are both defined and used by the instruction.  If a pressure
/// difference pointer is provided record the changes is pressure caused by this
/// instruction independent of liveness.
void RegPressureTracker::recede(const RegisterOperands &RegOpers,
                                SmallVectorImpl<VRegMaskOrUnit> *LiveUses) {
  assert(!CurrPos->isDebugOrPseudoInstr());

  // Boost pressure for all dead defs together.
  bumpDeadDefs(RegOpers.DeadDefs);

  // Kill liveness at live defs.
  // TODO: consider earlyclobbers?
  for (const VRegMaskOrUnit &Def : RegOpers.Defs) {
    VirtRegOrUnit VRegOrUnit = Def.VRegOrUnit;

    LaneBitmask PreviousMask = LiveRegs.erase(Def);
    LaneBitmask NewMask = PreviousMask & ~Def.LaneMask;

    LaneBitmask LiveOut = Def.LaneMask & ~PreviousMask;
    if (LiveOut.any()) {
      discoverLiveOut(VRegMaskOrUnit(VRegOrUnit, LiveOut));
      // Retroactively model effects on pressure of the live out lanes.
      increaseSetPressure(CurrSetPressure, *MRI, VRegOrUnit,
                          LaneBitmask::getNone(), LiveOut);
      PreviousMask = LiveOut;
    }

    if (NewMask.none()) {
      // Add a 0 entry to LiveUses as a marker that the complete vreg has become
      // dead.
      if (TrackLaneMasks && LiveUses != nullptr)
        setRegZero(*LiveUses, VRegOrUnit);
    }

    decreaseRegPressure(VRegOrUnit, PreviousMask, NewMask);
  }

  SlotIndex SlotIdx;
  if (RequireIntervals)
    SlotIdx = LIS->getInstructionIndex(*CurrPos).getRegSlot();

  // Generate liveness for uses.
  for (const VRegMaskOrUnit &Use : RegOpers.Uses) {
    VirtRegOrUnit VRegOrUnit = Use.VRegOrUnit;
    assert(Use.LaneMask.any());
    LaneBitmask PreviousMask = LiveRegs.insert(Use);
    LaneBitmask NewMask = PreviousMask | Use.LaneMask;
    if (NewMask == PreviousMask)
      continue;

    // Did the register just become live?
    if (PreviousMask.none()) {
      if (LiveUses != nullptr) {
        if (!TrackLaneMasks) {
          addRegLanes(*LiveUses, VRegMaskOrUnit(VRegOrUnit, NewMask));
        } else {
          auto I = find_if(*LiveUses, [VRegOrUnit](const VRegMaskOrUnit Other) {
            return Other.VRegOrUnit == VRegOrUnit;
          });
          bool IsRedef = I != LiveUses->end();
          if (IsRedef) {
            // ignore re-defs here...
            assert(I->LaneMask.none());
            removeRegLanes(*LiveUses, VRegMaskOrUnit(VRegOrUnit, NewMask));
          } else {
            addRegLanes(*LiveUses, VRegMaskOrUnit(VRegOrUnit, NewMask));
          }
        }
      }

      // Discover live outs if this may be the first occurance of this register.
      if (RequireIntervals) {
        LaneBitmask LiveOut = getLiveThroughAt(VRegOrUnit, SlotIdx);
        if (LiveOut.any())
          discoverLiveOut(VRegMaskOrUnit(VRegOrUnit, LiveOut));
      }
    }

    increaseRegPressure(VRegOrUnit, PreviousMask, NewMask);
  }
  if (TrackUntiedDefs) {
    for (const VRegMaskOrUnit &Def : RegOpers.Defs) {
      VirtRegOrUnit VRegOrUnit = Def.VRegOrUnit;
      if (VRegOrUnit.isVirtualReg() &&
          (LiveRegs.contains(VRegOrUnit) & Def.LaneMask).none())
        UntiedDefs.insert(VRegOrUnit.asVirtualReg());
    }
  }
}

void RegPressureTracker::recedeSkipDebugValues() {
  assert(CurrPos != MBB->begin());
  if (!isBottomClosed())
    closeBottom();

  // Open the top of the region using block iterators.
  if (!RequireIntervals && isTopClosed())
    static_cast<RegionPressure&>(P).openTop(CurrPos);

  // Find the previous instruction.
  CurrPos = prev_nodbg(CurrPos, MBB->begin());

  SlotIndex SlotIdx;
  if (RequireIntervals && !CurrPos->isDebugOrPseudoInstr())
    SlotIdx = LIS->getInstructionIndex(*CurrPos).getRegSlot();

  // Open the top of the region using slot indexes.
  if (RequireIntervals && isTopClosed())
    static_cast<IntervalPressure&>(P).openTop(SlotIdx);
}

void RegPressureTracker::recede(SmallVectorImpl<VRegMaskOrUnit> *LiveUses) {
  recedeSkipDebugValues();
  if (CurrPos->isDebugOrPseudoInstr()) {
    // It's possible to only have debug_value and pseudo probe instructions and
    // hit the start of the block.
    assert(CurrPos == MBB->begin());
    return;
  }

  const MachineInstr &MI = *CurrPos;
  RegisterOperands RegOpers;
  RegOpers.collect(MI, *TRI, *MRI, TrackLaneMasks, /*IgnoreDead=*/false);
  if (TrackLaneMasks) {
    SlotIndex SlotIdx = LIS->getInstructionIndex(*CurrPos).getRegSlot();
    RegOpers.adjustLaneLiveness(*LIS, *MRI, SlotIdx);
  } else if (RequireIntervals) {
    RegOpers.detectDeadDefs(MI, *LIS, *MRI);
  }

  recede(RegOpers, LiveUses);
}

/// Advance across the current instruction.
void RegPressureTracker::advance(const RegisterOperands &RegOpers) {
  assert(!TrackUntiedDefs && "unsupported mode");
  assert(CurrPos != MBB->end());
  if (!isTopClosed())
    closeTop();

  SlotIndex SlotIdx;
  if (RequireIntervals)
    SlotIdx = getCurrSlot();

  // Open the bottom of the region using slot indexes.
  if (isBottomClosed()) {
    if (RequireIntervals)
      static_cast<IntervalPressure&>(P).openBottom(SlotIdx);
    else
      static_cast<RegionPressure&>(P).openBottom(CurrPos);
  }

  for (const VRegMaskOrUnit &Use : RegOpers.Uses) {
    VirtRegOrUnit VRegOrUnit = Use.VRegOrUnit;
    LaneBitmask LiveMask = LiveRegs.contains(VRegOrUnit);
    LaneBitmask LiveIn = Use.LaneMask & ~LiveMask;
    if (LiveIn.any()) {
      discoverLiveIn(VRegMaskOrUnit(VRegOrUnit, LiveIn));
      increaseRegPressure(VRegOrUnit, LiveMask, LiveMask | LiveIn);
      LiveRegs.insert(VRegMaskOrUnit(VRegOrUnit, LiveIn));
    }
    // Kill liveness at last uses.
    if (RequireIntervals) {
      LaneBitmask LastUseMask = getLastUsedLanes(VRegOrUnit, SlotIdx);
      if (LastUseMask.any()) {
        LiveRegs.erase(VRegMaskOrUnit(VRegOrUnit, LastUseMask));
        decreaseRegPressure(VRegOrUnit, LiveMask, LiveMask & ~LastUseMask);
      }
    }
  }

  // Generate liveness for defs.
  for (const VRegMaskOrUnit &Def : RegOpers.Defs) {
    LaneBitmask PreviousMask = LiveRegs.insert(Def);
    LaneBitmask NewMask = PreviousMask | Def.LaneMask;
    increaseRegPressure(Def.VRegOrUnit, PreviousMask, NewMask);
  }

  // Boost pressure for all dead defs together.
  bumpDeadDefs(RegOpers.DeadDefs);

  // Find the next instruction.
  CurrPos = next_nodbg(CurrPos, MBB->end());
}

void RegPressureTracker::advance() {
  const MachineInstr &MI = *CurrPos;
  RegisterOperands RegOpers;
  RegOpers.collect(MI, *TRI, *MRI, TrackLaneMasks, false);
  if (TrackLaneMasks) {
    SlotIndex SlotIdx = getCurrSlot();
    RegOpers.adjustLaneLiveness(*LIS, *MRI, SlotIdx);
  }
  advance(RegOpers);
}

/// Find the max change in excess pressure across all sets.
static void computeExcessPressureDelta(ArrayRef<unsigned> OldPressureVec,
                                       ArrayRef<unsigned> NewPressureVec,
                                       RegPressureDelta &Delta,
                                       const RegisterClassInfo *RCI,
                                       ArrayRef<unsigned> LiveThruPressureVec) {
  Delta.Excess = PressureChange();
  for (unsigned i = 0, e = OldPressureVec.size(); i < e; ++i) {
    unsigned POld = OldPressureVec[i];
    unsigned PNew = NewPressureVec[i];
    int PDiff = (int)PNew - (int)POld;
    if (!PDiff) // No change in this set in the common case.
      continue;
    // Only consider change beyond the limit.
    unsigned Limit = RCI->getRegPressureSetLimit(i);
    if (!LiveThruPressureVec.empty())
      Limit += LiveThruPressureVec[i];

    if (Limit > POld) {
      if (Limit > PNew)
        PDiff = 0;            // Under the limit
      else
        PDiff = PNew - Limit; // Just exceeded limit.
    } else if (Limit > PNew)
      PDiff = Limit - POld;   // Just obeyed limit.

    if (PDiff) {
      Delta.Excess = PressureChange(i);
      Delta.Excess.setUnitInc(PDiff);
      break;
    }
  }
}

/// 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<PressureChange> CriticalPSets,
                                    ArrayRef<unsigned> MaxPressureLimit,
                                    RegPressureDelta &Delta) {
  Delta.CriticalMax = PressureChange();
  Delta.CurrentMax = PressureChange();

  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;

    if (!Delta.CriticalMax.isValid()) {
      while (CritIdx != CritEnd && CriticalPSets[CritIdx].getPSet() < i)
        ++CritIdx;

      if (CritIdx != CritEnd && CriticalPSets[CritIdx].getPSet() == i) {
        int PDiff = (int)PNew - CriticalPSets[CritIdx].getUnitInc();
        if (PDiff > 0) {
          Delta.CriticalMax = PressureChange(i);
          Delta.CriticalMax.setUnitInc(PDiff);
        }
      }
    }
    // Find the first increase above MaxPressureLimit.
    // (Ignores negative MDiff).
    if (!Delta.CurrentMax.isValid() && PNew > MaxPressureLimit[i]) {
      Delta.CurrentMax = PressureChange(i);
      Delta.CurrentMax.setUnitInc(PNew - POld);
      if (CritIdx == CritEnd || Delta.CriticalMax.isValid())
        break;
    }
  }
}

/// Record the upward impact of a single instruction on current register
/// pressure. Unlike the advance/recede pressure tracking interface, this does
/// not discover live in/outs.
///
/// This is intended for speculative queries. It leaves pressure inconsistent
/// with the current position, so must be restored by the caller.
void RegPressureTracker::bumpUpwardPressure(const MachineInstr *MI) {
  assert(!MI->isDebugOrPseudoInstr() && "Expect a nondebug instruction.");

  SlotIndex SlotIdx;
  if (RequireIntervals)
    SlotIdx = LIS->getInstructionIndex(*MI).getRegSlot();

  // Account for register pressure similar to RegPressureTracker::recede().
  RegisterOperands RegOpers;
  RegOpers.collect(*MI, *TRI, *MRI, TrackLaneMasks, /*IgnoreDead=*/true);
  assert(RegOpers.DeadDefs.empty());
  if (TrackLaneMasks)
    RegOpers.adjustLaneLiveness(*LIS, *MRI, SlotIdx);
  else if (RequireIntervals)
    RegOpers.detectDeadDefs(*MI, *LIS, *MRI);

  // Boost max pressure for all dead defs together.
  // Since CurrSetPressure and MaxSetPressure
  bumpDeadDefs(RegOpers.DeadDefs);

  // Kill liveness at live defs.
  for (const VRegMaskOrUnit &P : RegOpers.Defs) {
    LaneBitmask LiveAfter = LiveRegs.contains(P.VRegOrUnit);
    LaneBitmask UseLanes = getRegLanes(RegOpers.Uses, P.VRegOrUnit);
    LaneBitmask DefLanes = P.LaneMask;
    LaneBitmask LiveBefore = (LiveAfter & ~DefLanes) | UseLanes;

    // There may be parts of the register that were dead before the
    // instruction, but became live afterwards.
    decreaseRegPressure(P.VRegOrUnit, LiveAfter, LiveAfter & LiveBefore);
  }
  // Generate liveness for uses. Also handle any uses which overlap with defs.
  for (const VRegMaskOrUnit &P : RegOpers.Uses) {
    LaneBitmask LiveAfter = LiveRegs.contains(P.VRegOrUnit);
    LaneBitmask LiveBefore = LiveAfter | P.LaneMask;
    increaseRegPressure(P.VRegOrUnit, LiveAfter, LiveBefore);
  }
}

/// Consider the pressure increase caused by traversing this instruction
/// bottom-up. Find the pressure set with the most change beyond its pressure
/// limit based on the tracker's current pressure, and return the change in
/// number of register units of that pressure set introduced by this
/// instruction.
///
/// This assumes that the current LiveOut set is sufficient.
///
/// This is expensive for an on-the-fly query because it calls
/// bumpUpwardPressure to recompute the pressure sets based on current
/// liveness. This mainly exists to verify correctness, e.g. with
/// -verify-misched. getUpwardPressureDelta is the fast version of this query
/// that uses the per-SUnit cache of the PressureDiff.
void RegPressureTracker::
getMaxUpwardPressureDelta(const MachineInstr *MI, PressureDiff *PDiff,
                          RegPressureDelta &Delta,
                          ArrayRef<PressureChange> CriticalPSets,
                          ArrayRef<unsigned> MaxPressureLimit) {
  // 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;

  bumpUpwardPressure(MI);

  computeExcessPressureDelta(SavedPressure, CurrSetPressure, Delta, RCI,
                             LiveThruPressure);
  computeMaxPressureDelta(SavedMaxPressure, P.MaxSetPressure, CriticalPSets,
                          MaxPressureLimit, Delta);
  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() << "PDiff: ";
    PDiff->dump(*TRI);
    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 the fast version of querying register pressure that does not
/// directly depend on current liveness.
///
/// @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 &PDiff,
                       RegPressureDelta &Delta,
                       ArrayRef<PressureChange> CriticalPSets,
                       ArrayRef<unsigned> MaxPressureLimit) const {
  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/underflow");
    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 - CriticalPSets[CritIdx].getUnitInc();
        if (CritInc > 0 && CritInc <= std::numeric_limits<int16_t>::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).
/// The query starts with a lane bitmask which gets lanes/bits removed for every
/// use we find.
static LaneBitmask findUseBetween(VirtRegOrUnit VRegOrUnit,
                                  LaneBitmask LastUseMask,
                                  SlotIndex PriorUseIdx, SlotIndex NextUseIdx,
                                  const MachineRegisterInfo &MRI,
                                  const LiveIntervals *LIS) {
  const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
  // FIXME: The static_cast is a bug.
  Register Reg =
      VRegOrUnit.isVirtualReg()
          ? VRegOrUnit.asVirtualReg()
          : Register(static_cast<unsigned>(VRegOrUnit.asMCRegUnit()));
  for (const MachineOperand &MO : MRI.use_nodbg_operands(Reg)) {
    if (MO.isUndef())
      continue;
    const MachineInstr *MI = MO.getParent();
    SlotIndex InstSlot = LIS->getInstructionIndex(*MI).getRegSlot();
    if (InstSlot >= PriorUseIdx && InstSlot < NextUseIdx) {
      unsigned SubRegIdx = MO.getSubReg();
      LaneBitmask UseMask = TRI.getSubRegIndexLaneMask(SubRegIdx);
      LastUseMask &= ~UseMask;
      if (LastUseMask.none())
        return LaneBitmask::getNone();
    }
  }
  return LastUseMask;
}

LaneBitmask RegPressureTracker::getLiveLanesAt(VirtRegOrUnit VRegOrUnit,
                                               SlotIndex Pos) const {
  assert(RequireIntervals);
  return getLanesWithProperty(
      *LIS, *MRI, TrackLaneMasks, VRegOrUnit, Pos, LaneBitmask::getAll(),
      [](const LiveRange &LR, SlotIndex Pos) { return LR.liveAt(Pos); });
}

LaneBitmask RegPressureTracker::getLastUsedLanes(VirtRegOrUnit VRegOrUnit,
                                                 SlotIndex Pos) const {
  assert(RequireIntervals);
  return getLanesWithProperty(
      *LIS, *MRI, TrackLaneMasks, VRegOrUnit, Pos.getBaseIndex(),
      LaneBitmask::getNone(), [](const LiveRange &LR, SlotIndex Pos) {
        const LiveRange::Segment *S = LR.getSegmentContaining(Pos);
        return S != nullptr && S->end == Pos.getRegSlot();
      });
}

LaneBitmask RegPressureTracker::getLiveThroughAt(VirtRegOrUnit VRegOrUnit,
                                                 SlotIndex Pos) const {
  assert(RequireIntervals);
  return getLanesWithProperty(
      *LIS, *MRI, TrackLaneMasks, VRegOrUnit, Pos, LaneBitmask::getNone(),
      [](const LiveRange &LR, SlotIndex Pos) {
        const LiveRange::Segment *S = LR.getSegmentContaining(Pos);
        return S != nullptr && S->start < Pos.getRegSlot(true) &&
               S->end != Pos.getDeadSlot();
      });
}

/// Record the downward impact of a single instruction on current register
/// pressure. Unlike the advance/recede pressure tracking interface, this does
/// not discover live in/outs.
///
/// This is intended for speculative queries. It leaves pressure inconsistent
/// with the current position, so must be restored by the caller.
void RegPressureTracker::bumpDownwardPressure(const MachineInstr *MI) {
  assert(!MI->isDebugOrPseudoInstr() && "Expect a nondebug instruction.");

  SlotIndex SlotIdx;
  if (RequireIntervals)
    SlotIdx = LIS->getInstructionIndex(*MI).getRegSlot();

  // Account for register pressure similar to RegPressureTracker::advance().
  RegisterOperands RegOpers;
  RegOpers.collect(*MI, *TRI, *MRI, TrackLaneMasks, /*IgnoreDead=*/false);
  if (TrackLaneMasks)
    RegOpers.adjustLaneLiveness(*LIS, *MRI, SlotIdx);

  if (RequireIntervals) {
    for (const VRegMaskOrUnit &Use : RegOpers.Uses) {
      VirtRegOrUnit VRegOrUnit = Use.VRegOrUnit;
      LaneBitmask LastUseMask = getLastUsedLanes(VRegOrUnit, SlotIdx);
      if (LastUseMask.none())
        continue;
      // The LastUseMask is queried from the liveness information of instruction
      // which may be further down the schedule. Some lanes may actually not be
      // last uses for the current position.
      // FIXME: allow the caller to pass in the list of vreg uses that remain
      // to be bottom-scheduled to avoid searching uses at each query.
      SlotIndex CurrIdx = getCurrSlot();
      LastUseMask =
          findUseBetween(VRegOrUnit, LastUseMask, CurrIdx, SlotIdx, *MRI, LIS);
      if (LastUseMask.none())
        continue;

      LaneBitmask LiveMask = LiveRegs.contains(VRegOrUnit);
      LaneBitmask NewMask = LiveMask & ~LastUseMask;
      decreaseRegPressure(VRegOrUnit, LiveMask, NewMask);
    }
  }

  // Generate liveness for defs.
  for (const VRegMaskOrUnit &Def : RegOpers.Defs) {
    LaneBitmask LiveMask = LiveRegs.contains(Def.VRegOrUnit);
    LaneBitmask NewMask = LiveMask | Def.LaneMask;
    increaseRegPressure(Def.VRegOrUnit, LiveMask, NewMask);
  }

  // Boost pressure for all dead defs together.
  bumpDeadDefs(RegOpers.DeadDefs);
}

/// Consider the pressure increase caused by traversing this instruction
/// top-down. Find the register class with the most change in its pressure limit
/// based on the tracker's current pressure, and return the number of excess
/// register units of that pressure set introduced by this instruction.
///
/// This assumes that the current LiveIn set is sufficient.
///
/// This is expensive for an on-the-fly query because it calls
/// bumpDownwardPressure to recompute the pressure sets based on current
/// liveness. We don't yet have a fast version of downward pressure tracking
/// analogous to getUpwardPressureDelta.
void RegPressureTracker::
getMaxDownwardPressureDelta(const MachineInstr *MI, RegPressureDelta &Delta,
                            ArrayRef<PressureChange> CriticalPSets,
                            ArrayRef<unsigned> MaxPressureLimit) {
  // Snapshot Pressure.
  std::vector<unsigned> SavedPressure = CurrSetPressure;
  std::vector<unsigned> SavedMaxPressure = P.MaxSetPressure;

  bumpDownwardPressure(MI);

  computeExcessPressureDelta(SavedPressure, CurrSetPressure, Delta, RCI,
                             LiveThruPressure);
  computeMaxPressureDelta(SavedMaxPressure, P.MaxSetPressure, CriticalPSets,
                          MaxPressureLimit, Delta);
  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);
}

/// Get the pressure of each PSet after traversing this instruction bottom-up.
void RegPressureTracker::
getUpwardPressure(const MachineInstr *MI,
                  std::vector<unsigned> &PressureResult,
                  std::vector<unsigned> &MaxPressureResult) {
  // Snapshot pressure.
  PressureResult = CurrSetPressure;
  MaxPressureResult = P.MaxSetPressure;

  bumpUpwardPressure(MI);

  // Current pressure becomes the result. Restore current pressure.
  P.MaxSetPressure.swap(MaxPressureResult);
  CurrSetPressure.swap(PressureResult);
}

/// Get the pressure of each PSet after traversing this instruction top-down.
void RegPressureTracker::
getDownwardPressure(const MachineInstr *MI,
                    std::vector<unsigned> &PressureResult,
                    std::vector<unsigned> &MaxPressureResult) {
  // Snapshot pressure.
  PressureResult = CurrSetPressure;
  MaxPressureResult = P.MaxSetPressure;

  bumpDownwardPressure(MI);

  // Current pressure becomes the result. Restore current pressure.
  P.MaxSetPressure.swap(MaxPressureResult);
  CurrSetPressure.swap(PressureResult);
}
