//=====-- Rematerializer.cpp - MIR rematerialization support ----*- C++ -*-===//
//
// 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
//
//==-----------------------------------------------------------------------===//
//
/// \file
/// Implements helpers for target-independent rematerialization at the MIR
/// level.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/Rematerializer.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/CodeGen/LiveIntervals.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Register.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include <optional>

#define DEBUG_TYPE "rematerializer"

using namespace llvm;
using RegisterIdx = Rematerializer::RegisterIdx;

// Pin the vtable to this file.
void Rematerializer::Listener::anchor() {}

/// Checks whether the value in \p LI at \p UseIdx is identical to \p OVNI (this
/// implies it is also live there). When \p LI has sub-ranges, checks that
/// all sub-ranges intersecting with \p Mask are also live at \p UseIdx.
static bool isIdenticalAtUse(const VNInfo &OVNI, LaneBitmask Mask,
                             SlotIndex UseIdx, const LiveInterval &LI) {
  if (&OVNI != LI.getVNInfoAt(UseIdx))
    return false;

  if (LI.hasSubRanges()) {
    // Check that intersecting subranges are live at user.
    for (const LiveInterval::SubRange &SR : LI.subranges()) {
      if ((SR.LaneMask & Mask).none())
        continue;
      if (!SR.liveAt(UseIdx))
        return false;

      // Early exit if all used lanes are checked. No need to continue.
      Mask &= ~SR.LaneMask;
      if (Mask.none())
        break;
    }
  }
  return true;
}

/// If \p MO is a virtual read register, returns it. Otherwise returns the
/// sentinel register.
static Register getRegDependency(const MachineOperand &MO) {
  if (!MO.isReg() || !MO.readsReg())
    return Register();
  Register Reg = MO.getReg();
  if (Reg.isPhysical()) {
    // By the requirements on trivially rematerializable instructions, a
    // physical register use is either constant or ignorable.
    return Register();
  }
  return Reg;
}

RegisterIdx Rematerializer::rematerializeToRegion(RegisterIdx RootIdx,
                                                  unsigned UseRegion,
                                                  DependencyReuseInfo &DRI) {
  MachineInstr *FirstMI =
      getReg(RootIdx).getRegionUseBounds(UseRegion, LIS).first;
  // If there are no users in the region, rematerialize the register at the very
  // end of the region.
  MachineBasicBlock::iterator InsertPos =
      FirstMI ? FirstMI : Regions[UseRegion].second;
  RegisterIdx NewRegIdx =
      rematerializeToPos(RootIdx, UseRegion, InsertPos, DRI);
  transferRegionUsers(RootIdx, NewRegIdx, UseRegion);
  return NewRegIdx;
}

RegisterIdx
Rematerializer::rematerializeToPos(RegisterIdx RootIdx, unsigned UseRegion,
                                   MachineBasicBlock::iterator InsertPos,
                                   DependencyReuseInfo &DRI) {
  assert(!DRI.DependencyMap.contains(RootIdx));
  LLVM_DEBUG(dbgs() << "Rematerializing " << printID(RootIdx) << '\n');

  SmallVector<RegisterIdx, 2> NewDeps;
  // Copy all dependencies because recursive rematerialization of dependencies
  // may invalidate references to the backing vector of registers.
  SmallVector<RegisterIdx, 2> OldDeps(getReg(RootIdx).Dependencies);
  for (RegisterIdx DepRegIdx : OldDeps) {
    // Recursively rematerialize required dependencies at the same position as
    // the root. Registers form a DAG so the recursion is guaranteed to
    // terminate.
    auto RematIdx = DRI.DependencyMap.find(DepRegIdx);
    RegisterIdx NewDepRegIdx;
    if (RematIdx == DRI.DependencyMap.end())
      NewDepRegIdx = rematerializeToPos(DepRegIdx, UseRegion, InsertPos, DRI);
    else
      NewDepRegIdx = RematIdx->second;
    NewDeps.push_back(NewDepRegIdx);
  }
  RegisterIdx NewIdx =
      rematerializeReg(RootIdx, UseRegion, InsertPos, std::move(NewDeps));
  DRI.DependencyMap.insert({RootIdx, NewIdx});
  return NewIdx;
}

void Rematerializer::transferUser(RegisterIdx FromRegIdx, RegisterIdx ToRegIdx,
                                  unsigned UserRegion, MachineInstr &UserMI) {
  transferUserImpl(FromRegIdx, ToRegIdx, UserMI);

  Regs[ToRegIdx].addUser(&UserMI, UserRegion);
  extendToNewUsers(ToRegIdx, &UserMI);

  Regs[FromRegIdx].eraseUser(&UserMI, UserRegion);
  shrinkToUses(FromRegIdx);
}

void Rematerializer::transferRegionUsers(RegisterIdx FromRegIdx,
                                         RegisterIdx ToRegIdx,
                                         unsigned UseRegion) {
  Reg &FromReg = Regs[FromRegIdx];
  auto UsesIt = FromReg.Uses.find(UseRegion);
  if (UsesIt == FromReg.Uses.end())
    return;

  const SmallDenseSet<MachineInstr *, 4> &RegionUsers = UsesIt->getSecond();
  SmallVector<MachineInstr *, 4> NewUsers;
  for (MachineInstr *UserMI : RegionUsers) {
    transferUserImpl(FromRegIdx, ToRegIdx, *UserMI);
    NewUsers.push_back(UserMI);
  }

  extendToNewUsers(ToRegIdx, NewUsers);
  Regs[ToRegIdx].addUsers(RegionUsers, UseRegion);

  FromReg.Uses.erase(UseRegion);
  shrinkToUses(FromRegIdx);
}

void Rematerializer::transferAllUsers(RegisterIdx FromRegIdx,
                                      RegisterIdx ToRegIdx) {
  Reg &FromReg = Regs[FromRegIdx];
  SmallVector<MachineInstr *, 4> NewUsers;
  for (const auto &[UseRegion, RegionUsers] : FromReg.Uses) {
    for (MachineInstr *UserMI : RegionUsers) {
      transferUserImpl(FromRegIdx, ToRegIdx, *UserMI);
      NewUsers.push_back(UserMI);
    }
    Regs[ToRegIdx].addUsers(RegionUsers, UseRegion);
  }
  extendToNewUsers(ToRegIdx, NewUsers);

  FromReg.Uses.clear();
  deleteReg(FromRegIdx);
}

void Rematerializer::transferUserImpl(RegisterIdx FromRegIdx,
                                      RegisterIdx ToRegIdx,
                                      MachineInstr &UserMI) {
  assert(FromRegIdx != ToRegIdx && "identical registers");
  assert(getOriginOrSelf(FromRegIdx) == getOriginOrSelf(ToRegIdx) &&
         "unrelated registers");

  LLVM_DEBUG(dbgs() << "User transfer from " << printID(FromRegIdx) << " to "
                    << printID(ToRegIdx) << ": " << printUser(&UserMI) << '\n');

  UserMI.substituteRegister(getReg(FromRegIdx).getDefReg(),
                            getReg(ToRegIdx).getDefReg(), 0, TRI);

  // If the user is rematerializable, we must change its dependency to the
  // new register.
  if (RegisterIdx UserRegIdx = getDefRegIdx(UserMI); UserRegIdx != NoReg) {
    // Look for the user's dependency that matches the register.
    for (RegisterIdx &DepRegIdx : Regs[UserRegIdx].Dependencies) {
      if (DepRegIdx == FromRegIdx) {
        DepRegIdx = ToRegIdx;
        return;
      }
    }
    llvm_unreachable("broken dependency");
  }
}

bool Rematerializer::isMOIdenticalAtUses(MachineOperand &MO,
                                         ArrayRef<SlotIndex> Uses) const {
  unsigned SubIdx = MO.getSubReg();
  LaneBitmask Mask = SubIdx ? TRI.getSubRegIndexLaneMask(SubIdx)
                            : MRI.getMaxLaneMaskForVReg(MO.getReg());
  return isRegIdenticalAtUses(
      MO.getReg(), Mask,
      LIS.getInstructionIndex(*MO.getParent()).getRegSlot(true), Uses);
}

bool Rematerializer::isRegIdenticalAtUses(Register Reg, LaneBitmask Mask,
                                          SlotIndex RefSlot,
                                          ArrayRef<SlotIndex> Uses) const {
  if (Uses.empty())
    return true;
  const LiveInterval &LI = LIS.getInterval(Reg);
  const VNInfo *DefVN = LI.getVNInfoAt(RefSlot);
  for (SlotIndex Use : Uses) {
    if (!isIdenticalAtUse(*DefVN, Mask, Use, LI))
      return false;
  }
  return true;
}

RegisterIdx Rematerializer::findRematInRegion(RegisterIdx RegIdx,
                                              unsigned Region,
                                              SlotIndex Before) const {
  auto It = Rematerializations.find(getOriginOrSelf(RegIdx));
  if (It == Rematerializations.end())
    return NoReg;
  const RematsOf &Remats = It->getSecond();

  SlotIndex BestSlot;
  RegisterIdx BestRegIdx = NoReg;
  for (RegisterIdx RematRegIdx : Remats) {
    const Reg &RematReg = getReg(RematRegIdx);
    if (RematReg.DefRegion != Region || RematReg.Uses.empty())
      continue;
    SlotIndex RematRegSlot =
        LIS.getInstructionIndex(*RematReg.DefMI).getRegSlot();
    if (RematRegSlot < Before &&
        (BestRegIdx == NoReg || RematRegSlot > BestSlot)) {
      BestSlot = RematRegSlot;
      BestRegIdx = RematRegIdx;
    }
  }
  return BestRegIdx;
}

void Rematerializer::deleteReg(RegisterIdx RootIdx) {
  assert(getReg(RootIdx).Uses.empty() && "register still has uses");

  // Traverse the root's dependency DAG depth-first to find the set of registers
  // we can delete and a legal order to delete them in.
  SmallVector<RegisterIdx, 4> DepDAG{RootIdx};
  SmallVector<RegisterIdx, 8> DeleteOrder{RootIdx};
  do {
    // A deleted register's dependencies may be deletable too.
    const Reg &DeleteReg = getReg(DepDAG.pop_back_val());
    for (RegisterIdx DepRegIdx : DeleteReg.Dependencies) {
      // All dependencies lose a user (the deleted register).
      Reg &DepReg = Regs[DepRegIdx];
      DepReg.eraseUser(DeleteReg.DefMI, DeleteReg.DefRegion);
      if (DepReg.Uses.empty()) {
        DeleteOrder.push_back(DepRegIdx);
        DepDAG.push_back(DepRegIdx);
      }
    }
  } while (!DepDAG.empty());

  for (RegisterIdx RegIdx : DeleteOrder) {
    preDeletion(RegIdx);
    Reg &DeleteReg = Regs[RegIdx];
    Register DefReg = DeleteReg.getDefReg();
    LIS.RemoveMachineInstrFromMaps(*DeleteReg.DefMI);
    DeleteReg.DefMI->eraseFromParent();
    DeleteReg.DefMI = nullptr;
    LIS.removeInterval(DefReg);
  }

  SmallSet<RegisterIdx, 8> ShrinkRematRegs;
  SmallSet<Register, 8> ShrinkUnrematRegs;

  // All dependencies lose a user; their live interval could be shrunk.
  for (RegisterIdx DeletedRegIdx : DeleteOrder) {
    for (RegisterIdx DepRegIdx : getReg(DeletedRegIdx).Dependencies) {
      const Reg &DepReg = getReg(DepRegIdx);
      if (DepReg.isAlive() && ShrinkRematRegs.insert(DepRegIdx).second) {
        assert(!DepReg.Uses.empty() && "dep should have uses");
        shrinkToUses(DepRegIdx);
      }
    }
    for (const auto [Reg, Mask] : getUnrematableDeps(DeletedRegIdx)) {
      if (ShrinkUnrematRegs.insert(Reg).second)
        shrinkToUsesUnremat(Reg);
    }
  }
}

void Rematerializer::DeadDefDelegate::LRE_WillEraseInstruction(
    MachineInstr *MI) {
  RegisterIdx RegIdx = Remater.getDefRegIdx(*MI);
  if (RegIdx == Rematerializer::NoReg) {
    // This is an unrematerializable register.
    Remater.noteMIWillBeDeleted(*MI);
    LLVM_DEBUG(dbgs() << "** About to delete dead definition: " << *MI);

    // Do a linear scan through regions to figure out which one the about to be
    // deleted unrematerializable MI is a part of. This is expensive but should
    // happen extremely rarely.
    //
    // FIXME: the rematerializer should stop tracking regions and operate on a
    // machine basic block-basis. This would simplify this and a lot of the
    // tracking elsewhere.
    MachineBasicBlock::iterator It = MI->getIterator();
    const LiveIntervals &LIS = Remater.LIS;
    SlotIndex MISlot = LIS.getInstructionIndex(*MI);
    unsigned MIRegion = ~0U;
    for (auto [RegionIdx, Bounds] : enumerate(Remater.Regions)) {
      auto &[RegionBegin, RegionEnd] = Bounds;
      MachineBasicBlock::iterator FirstMI =
          skipDebugInstructionsForward(RegionBegin, RegionEnd);
      if (FirstMI == RegionEnd) {
        // The MI cannot be in an empty region.
        continue;
      }

      if (LIS.getInstructionIndex(*FirstMI) <= MISlot) {
        // FistMI exists inside the region so this is guaranteed to point to a
        // non-debug MI.
        MachineBasicBlock::iterator LastMI =
            skipDebugInstructionsBackward(std::prev(RegionEnd), RegionBegin);
        if (LIS.getInstructionIndex(*LastMI) < MISlot)
          continue;

        // We have found the region the MI is a part of.
        MIRegion = RegionIdx;
        if (RegionBegin == It)
          ++RegionBegin;
        break;
      }
    }

    // All rematerializable registers that this MI uses must be notified.
    SmallDenseSet<Register, 2> UsedRegs;
    for (const MachineOperand &MO : MI->all_uses()) {
      Register Reg = MO.getReg();
      if (Reg.isVirtual() && !UsedRegs.insert(Reg).second)
        continue;
      auto RematRegUse = Remater.RegToIdx.find(Reg);
      if (RematRegUse == Remater.RegToIdx.end())
        continue;
      assert(MIRegion != ~0U && "remat user cannot be outside regions");
      Remater.Regs[RematRegUse->second].eraseUser(MI, MIRegion);
    }
    return;
  }
  // This is a rematerializable register.

  // All rematerializable dependencies must be notified.
  Reg &DeleteReg = Remater.Regs[RegIdx];
  for (RegisterIdx DepRegIdx : DeleteReg.Dependencies)
    Remater.Regs[DepRegIdx].eraseUser(MI, DeleteReg.DefRegion);

  assert(DeleteReg.isAlive() && "register must be alive");
  assert(DeleteReg.Uses.empty() && "register should no longer have uses");

  // The live-range editor will delete the defining instruction from the MIR
  // as well as the register's live-range, so we just need to nullify the def
  // internally.
  Remater.preDeletion(RegIdx);
  DeleteReg.DefMI = nullptr;
}

void Rematerializer::preDeletion(RegisterIdx DeleteRegIdx) {
  Reg &DeleteReg = Regs[DeleteRegIdx];
  assert(DeleteReg.isAlive() && "register must still be alive");
  noteRegWillBeDeleted(DeleteRegIdx);
  LLVM_DEBUG(dbgs() << "** About to delete " << printID(DeleteRegIdx) << "\n");

  // Update region boundary if necessary. It is not possible for the deleted
  // instruction to be the upper region boundary since we don't ever consider
  // them rematerializable.
  MachineBasicBlock::iterator &RegionBegin = Regions[DeleteReg.DefRegion].first;
  if (RegionBegin == DeleteReg.DefMI)
    ++RegionBegin;

  if (isOriginalRegister(DeleteRegIdx))
    return;

  // Delete rematerialized register from its origin's rematerializations.
  const RegisterIdx OriginIdx = getOriginOf(DeleteRegIdx);
  RematsOf &OriginRemats = Rematerializations.at(OriginIdx);
  assert(OriginRemats.contains(DeleteRegIdx) && "broken remat<->origin link");
  OriginRemats.erase(DeleteRegIdx);
  if (OriginRemats.empty())
    Rematerializations.erase(OriginIdx);
}

Rematerializer::Rematerializer(MachineFunction &MF,
                               SmallVectorImpl<RegionBoundaries> &Regions,
                               LiveIntervals &LIS)
    : Regions(Regions), MRI(MF.getRegInfo()), LIS(LIS),
      TII(*MF.getSubtarget().getInstrInfo()), TRI(TII.getRegisterInfo()) {
#ifdef EXPENSIVE_CHECKS
  // Check that regions are valid.
  DenseSet<MachineInstr *> SeenMIs;
  for (const auto &[RegionBegin, RegionEnd] : Regions) {
    assert(RegionBegin != RegionEnd && "empty region");
    for (auto MI = RegionBegin; MI != RegionEnd; ++MI) {
      bool IsNewMI = SeenMIs.insert(&*MI).second;
      assert(IsNewMI && "overlapping regions");
      assert(!MI->isTerminator() && "terminator in region");
    }
    if (RegionEnd != RegionBegin->getParent()->end()) {
      bool IsNewMI = SeenMIs.insert(&*RegionEnd).second;
      assert(IsNewMI && "overlapping regions (upper bound)");
    }
  }
#endif
}

bool Rematerializer::analyze() {
  Regs.clear();
  UnrematableDeps.clear();
  Origins.clear();
  Rematerializations.clear();
  RegionMBB.clear();
  RegToIdx.clear();
  if (Regions.empty())
    return false;

  /// Maps all MIs to their parent region. Region terminators are considered
  /// part of the region they terminate.
  DenseMap<MachineInstr *, unsigned> MIRegion;

  // Initialize MI to containing region mapping.
  RegionMBB.reserve(Regions.size());
  for (unsigned I = 0, E = Regions.size(); I < E; ++I) {
    RegionBoundaries Region = Regions[I];
    assert(Region.first != Region.second && "empty cannot be region");
    for (auto MI = Region.first; MI != Region.second; ++MI) {
      assert(!MIRegion.contains(&*MI) && "regions should not intersect");
      MIRegion.insert({&*MI, I});
    }
    MachineBasicBlock &MBB = *Region.first->getParent();
    RegionMBB.push_back(&MBB);

    // A terminator instruction is considered part of the region it terminates.
    if (Region.second != MBB.end()) {
      MachineInstr *RegionTerm = &*Region.second;
      assert(!MIRegion.contains(RegionTerm) && "regions should not intersect");
      MIRegion.insert({RegionTerm, I});
    }
  }

  const unsigned NumVirtRegs = MRI.getNumVirtRegs();
  BitVector SeenRegs(NumVirtRegs);
  for (unsigned I = 0, E = NumVirtRegs; I != E; ++I) {
    if (!SeenRegs[I])
      addRegIfRematerializable(I, MIRegion, SeenRegs);
  }
  assert(Regs.size() == UnrematableDeps.size());

  LLVM_DEBUG({
    for (RegisterIdx I = 0, E = getNumRegs(); I < E; ++I)
      dbgs() << printDependencyDAG(I) << '\n';
  });
  return !Regs.empty();
}

void Rematerializer::addRegIfRematerializable(
    unsigned VirtRegIdx, const DenseMap<MachineInstr *, unsigned> &MIRegion,
    BitVector &SeenRegs) {
  assert(!SeenRegs[VirtRegIdx] && "register already seen");
  Register DefReg = Register::index2VirtReg(VirtRegIdx);
  SeenRegs.set(VirtRegIdx);

  MachineOperand *MO = MRI.getOneDef(DefReg);
  if (!MO)
    return;
  MachineInstr &DefMI = *MO->getParent();
  if (!isMIRematerializable(DefMI))
    return;
  auto DefRegion = MIRegion.find(&DefMI);
  if (DefRegion == MIRegion.end())
    return;

  Reg RematReg;
  RematReg.DefMI = &DefMI;
  RematReg.DefRegion = DefRegion->second;
  unsigned SubIdx = DefMI.getOperand(0).getSubReg();
  RematReg.Mask = SubIdx ? TRI.getSubRegIndexLaneMask(SubIdx)
                         : MRI.getMaxLaneMaskForVReg(DefReg);

  // Collect the candidate's direct users, both rematerializable and
  // unrematerializable. MIs outside provided regions cannot be tracked so the
  // registers they use are not safely rematerializable.
  for (MachineInstr &UseMI : MRI.use_nodbg_instructions(DefReg)) {
    if (auto UseRegion = MIRegion.find(&UseMI); UseRegion != MIRegion.end())
      RematReg.addUser(&UseMI, UseRegion->second);
    else
      return;
  }
  if (RematReg.Uses.empty())
    return;

  // Collect the candidate's dependencies, rematerializable or not. If the same
  // rematerializable register is used multiple times we just need to consider
  // it once.
  SmallSetVector<RegisterIdx, 2> RematDeps;
  SmallMapVector<Register, LaneBitmask, 2> UnrematDeps;
  for (const MachineOperand &MO : DefMI.all_uses()) {
    Register DepReg = getRegDependency(MO);
    if (!DepReg)
      continue;
    unsigned DepRegIdx = DepReg.virtRegIndex();
    if (!SeenRegs[DepRegIdx])
      addRegIfRematerializable(DepRegIdx, MIRegion, SeenRegs);
    if (auto DepIt = RegToIdx.find(DepReg); DepIt != RegToIdx.end()) {
      RematDeps.insert(DepIt->second);
    } else {
      LaneBitmask &CurrentMask =
          UnrematDeps.try_emplace(DepReg, LaneBitmask::getNone()).first->second;
      LaneBitmask Mask = MO.getSubReg()
                             ? TRI.getSubRegIndexLaneMask(MO.getSubReg())
                             : MRI.getMaxLaneMaskForVReg(DepReg);
      CurrentMask |= Mask;
    }
  }

  // The register is rematerializable.
  RematReg.Dependencies = RematDeps.takeVector();
  RegToIdx.insert({DefReg, Regs.size()});
  Regs.push_back(RematReg);
  UnrematableDeps.push_back(UnrematDeps.takeVector());
}

bool Rematerializer::isMIRematerializable(const MachineInstr &MI) const {
  if (!TII.isReMaterializable(MI))
    return false;

  assert(MI.getOperand(0).getReg().isVirtual() && "should be virtual");
  assert(MRI.hasOneDef(MI.getOperand(0).getReg()) && "should have single def");

  for (const MachineOperand &MO : MI.all_uses()) {
    // We can't remat physreg uses, unless it is a constant or an ignorable
    // use (e.g. implicit exec use on VALU instructions)
    if (MO.getReg().isPhysical()) {
      if (MRI.isConstantPhysReg(MO.getReg()) || TII.isIgnorableUse(MO))
        continue;
      return false;
    }
  }

  return true;
}

RegisterIdx Rematerializer::getDefRegIdx(const MachineInstr &MI) const {
  if (!MI.getNumOperands() || !MI.getOperand(0).isReg() ||
      MI.getOperand(0).readsReg())
    return NoReg;
  Register Reg = MI.getOperand(0).getReg();
  auto UserRegIt = RegToIdx.find(Reg);
  if (UserRegIt == RegToIdx.end())
    return NoReg;
  return UserRegIt->second;
}

RegisterIdx
Rematerializer::rematerializeReg(RegisterIdx RegIdx, unsigned UseRegion,
                                 MachineBasicBlock::iterator InsertPos,
                                 SmallVectorImpl<RegisterIdx> &&Dependencies) {
  RegisterIdx NewRegIdx = Regs.size();

  Reg &NewReg = Regs.emplace_back();
  Reg &FromReg = Regs[RegIdx];
  NewReg.Mask = FromReg.Mask;
  NewReg.DefRegion = UseRegion;
  NewReg.Dependencies = std::move(Dependencies);

  // Track rematerialization link between registers. Origins are always
  // registers that existed originally, and rematerializations are always
  // attached to them.
  const RegisterIdx OriginIdx = getOriginOrSelf(RegIdx);
  Origins.push_back(OriginIdx);
  Rematerializations[OriginIdx].insert(NewRegIdx);

  // Use the TII to rematerialize the defining instruction with a new defined
  // register.
  Register NewDefReg = MRI.cloneVirtualRegister(FromReg.getDefReg());
  TII.reMaterialize(*RegionMBB[UseRegion], InsertPos, NewDefReg, 0,
                    *FromReg.DefMI);
  NewReg.DefMI = &*std::prev(InsertPos);
  RegToIdx.insert({NewDefReg, NewRegIdx});
  postRematerialization(RegIdx, NewRegIdx);

  noteRegCreated(NewRegIdx);
  LLVM_DEBUG(dbgs() << "** Rematerialized " << printID(RegIdx) << " as "
                    << printRematReg(NewRegIdx) << '\n');
  return NewRegIdx;
}

void Rematerializer::recreateReg(RegisterIdx RegIdx,
                                 MachineBasicBlock::iterator InsertPos,
                                 Register DefReg) {
  assert(RegToIdx.contains(DefReg) && "unknown defined register");
  assert(RegToIdx.at(DefReg) == RegIdx && "incorrect defined register");
  assert(!getReg(RegIdx).isAlive() && "register is still alive");

  Reg &OriginReg = Regs[RegIdx];

  // Re-establish the link between origin and rematerialization if necessary.
  const bool RecreateOriginalReg = isOriginalRegister(RegIdx);
  if (!RecreateOriginalReg)
    Rematerializations[getOriginOf(RegIdx)].insert(RegIdx);

  // Rematerialize from one of the existing rematerializations or from the
  // origin. We expect at least one to exist, otherwise it would mean the value
  // held by the original register is no longer available anywhere in the MF.
  RegisterIdx ModelRegIdx;
  if (RecreateOriginalReg) {
    assert(Rematerializations.contains(RegIdx) && "expected remats");
    ModelRegIdx = *Rematerializations.at(RegIdx).begin();
  } else {
    assert(getReg(getOriginOf(RegIdx)).isAlive() && "expected alive origin");
    ModelRegIdx = getOriginOf(RegIdx);
  }
  const MachineInstr &ModelDefMI = *getReg(ModelRegIdx).DefMI;

  TII.reMaterialize(*RegionMBB[OriginReg.DefRegion], InsertPos, DefReg, 0,
                    ModelDefMI);
  OriginReg.DefMI = &*std::prev(InsertPos);
  postRematerialization(ModelRegIdx, RegIdx);
  LLVM_DEBUG(dbgs() << "** Recreated " << printID(RegIdx) << " as "
                    << printRematReg(RegIdx) << '\n');
}

void Rematerializer::postRematerialization(RegisterIdx ModelRegIdx,
                                           RegisterIdx RematRegIdx) {
  Reg &ModelReg = Regs[ModelRegIdx], &RematReg = Regs[RematRegIdx];

  // The rematerialization has no user at this point so its interval will
  // initially be empty.
  SlotIndex UseIdx = LIS.InsertMachineInstrInMaps(*RematReg.DefMI).getRegSlot();
  LIS.createAndComputeVirtRegInterval(RematReg.getDefReg());

  // The start of the new register's region may have changed.
  MachineBasicBlock::iterator &RegionBegin = Regions[RematReg.DefRegion].first;
  if (RegionBegin == std::next(MachineBasicBlock::iterator(RematReg.DefMI)))
    RegionBegin = RematReg.DefMI;

  // Replace dependencies as needed in the rematerialized MI. All dependencies
  // of the latter gain a new user.
  auto ZipedDeps = zip_equal(ModelReg.Dependencies, RematReg.Dependencies);
  for (const auto &[OldDepRegIdx, NewDepRegIdx] : ZipedDeps) {
    LLVM_DEBUG(dbgs() << "  Dependency: " << printID(OldDepRegIdx) << " -> "
                      << printID(NewDepRegIdx) << '\n');

    Reg &NewDepReg = Regs[NewDepRegIdx];
    if (OldDepRegIdx != NewDepRegIdx) {
      Reg &OldDepReg = Regs[OldDepRegIdx];
      RematReg.DefMI->substituteRegister(OldDepReg.getDefReg(),
                                         NewDepReg.getDefReg(), 0, TRI);
    }
    NewDepReg.addUser(RematReg.DefMI, RematReg.DefRegion);
    extendToNewUsers(NewDepRegIdx, RematReg.DefMI);
  }

  // Unrematerializable dependencies always gain a new user after a
  // rematerialization; their live range may need to be extended.
  for (const auto &[Reg, Mask] : getUnrematableDeps(ModelRegIdx))
    extendInterval(LIS.getInterval(Reg), Mask, UseIdx);
}

void Rematerializer::extendToNewUsers(RegisterIdx RegIdx,
                                      ArrayRef<MachineInstr *> NewUsers) const {
  if (NewUsers.empty())
    return;
  const Reg &ExtendReg = getReg(RegIdx);
  assert(ExtendReg.isAlive() && "register must be alive");

  Register DefReg = ExtendReg.getDefReg();
  LiveInterval &LI = LIS.getInterval(DefReg);
  const LaneBitmask FullLaneMask = MRI.getMaxLaneMaskForVReg(DefReg);
  const bool ShouldTrackSubReg = MRI.shouldTrackSubRegLiveness(DefReg);

  // Seed subranges from the main range when subreg liveness is tracked but no
  // subrange exists yet. VirtRegRewriter later requires subranges even when a
  // new user reads the full mask, because other users may read subregs.
  if (!LI.hasSubRanges() && ShouldTrackSubReg)
    LI.createSubRangeFrom(LIS.getVNInfoAllocator(), FullLaneMask, LI);

  // Extend all ranges in the register's live interval so that they reach the
  // new users.
  for (MachineInstr *UserMI : NewUsers) {
    SlotIndex UseIdx = LIS.getInstructionIndex(*UserMI).getRegSlot();

    // Derive register lanes read by that user.
    LaneBitmask RegMask;
    for (MachineOperand &MO : UserMI->all_uses()) {
      if (MO.getReg() == DefReg) {
        unsigned SubIdx = MO.getSubReg();
        if (SubIdx == 0) {
          RegMask = FullLaneMask;
          break;
        }
        RegMask |= TRI.getSubRegIndexLaneMask(SubIdx);
      }
    }

    if (RegMask != FullLaneMask) {
      // Refine sub-ranges to be able to track the mask for that user.
      LI.refineSubRanges(
          LIS.getVNInfoAllocator(), RegMask, [](LiveInterval::SubRange &SR) {},
          *LIS.getSlotIndexes(), TRI);
    }
    extendInterval(LI, RegMask, UseIdx);
  }

  LLVM_DEBUG({
    if (ExtendReg.DefMI->getOperand(0).isDead())
      dbgs() << "Clearing dead flag for "
             << printRematReg(RegIdx, /*SkipRegions=*/false) << '\n';
  });
  ExtendReg.DefMI->getOperand(0).setIsDead(false);
}

void Rematerializer::extendInterval(LiveInterval &LI, LaneBitmask Mask,
                                    SlotIndex UseIdx) const {
  if (!LI.hasSubRanges()) {
    if (!LI.liveAt(UseIdx))
      LLVM_DEBUG(dbgs() << "Extending interval of register "
                        << printReg(LI.reg(), &TRI, 0, &MRI) << " to " << UseIdx
                        << '\n');
    LIS.extendToIndices(LI, UseIdx);
    return;
  }

  bool SubRangeExtended = false;
  for (LiveInterval::SubRange &SR : LI.subranges()) {
    if ((SR.LaneMask & Mask).any() && !SR.liveAt(UseIdx)) {
      SubRangeExtended = true;
      LLVM_DEBUG(dbgs() << "Extending subrange " << SR << " of register "
                        << printReg(LI.reg(), &TRI, 0, &MRI) << " to " << UseIdx
                        << '\n');
      LIS.extendToIndices(SR, UseIdx);
    }
  }
  if (!SubRangeExtended)
    return;

  // FIXME: this fully reconstructs the main live range from scratch, but
  // there may be a more targeted way to make the update.
  LI.clear();
  LIS.constructMainRangeFromSubranges(LI);
}

void Rematerializer::shrinkToUses(RegisterIdx RegIdx) {
  Reg &ShrinkReg = Regs[RegIdx];
  assert(ShrinkReg.isAlive() && "register must be alive");
  if (ShrinkReg.Uses.empty()) {
    deleteReg(RegIdx);
    return;
  }

  // By construction, registers should never end up with multiple disconnected
  // components or dead definitions.
  LiveInterval &LI = LIS.getInterval(ShrinkReg.getDefReg());
  LLVM_DEBUG(dbgs() << "Shrinking interval of " << printID(RegIdx) << ": " << LI
                    << '\n');
  LIS.shrinkToUses(&LI);
}

void Rematerializer::shrinkToUsesUnremat(Register Reg) {
  LiveInterval &LI = LIS.getInterval(Reg);
  LLVM_DEBUG(dbgs() << "Shrinking interval of unrematerializable register "
                    << LI << '\n');

  SmallVector<MachineInstr *, 2> DeadDefs;
  if (!LIS.shrinkToUses(&LI, &DeadDefs)) {
    assert(DeadDefs.empty() && "expected no dead def");
    return;
  }

  // This should be a very rare occurence, but shrinking an unrematerializable
  // register could create dead defs.
  if (DeadDefs.empty())
    return;

  // The live-range editor delegate will take care of reflecting the
  // elimination of all dead definitions in the rematerializer.
  SmallVector<Register, 4> NewRegs;
  DeadDefDelegate DeadDefDeleg(*this);
  MachineFunction &MF = *DeadDefs.front()->getParent()->getParent();
  LiveRangeEdit(nullptr, NewRegs, MF, LIS, nullptr, &DeadDefDeleg)
      .eliminateDeadDefs(DeadDefs);
}

std::pair<MachineInstr *, MachineInstr *>
Rematerializer::Reg::getRegionUseBounds(unsigned UseRegion,
                                        const LiveIntervals &LIS) const {
  auto It = Uses.find(UseRegion);
  if (It == Uses.end())
    return {nullptr, nullptr};
  const RegionUsers &RegionUsers = It->getSecond();
  assert(!RegionUsers.empty() && "empty userset in region");

  auto User = RegionUsers.begin(), UserEnd = RegionUsers.end();
  MachineInstr *FirstMI = *User, *LastMI = FirstMI;
  SlotIndex FirstIndex = LIS.getInstructionIndex(*FirstMI),
            LastIndex = FirstIndex;

  while (++User != UserEnd) {
    SlotIndex UserIndex = LIS.getInstructionIndex(**User);
    if (UserIndex < FirstIndex) {
      FirstIndex = UserIndex;
      FirstMI = *User;
    } else if (UserIndex > LastIndex) {
      LastIndex = UserIndex;
      LastMI = *User;
    }
  }

  return {FirstMI, LastMI};
}

void Rematerializer::Reg::addUser(MachineInstr *MI, unsigned Region) {
  Uses[Region].insert(MI);
}

void Rematerializer::Reg::addUsers(const RegionUsers &NewUsers,
                                   unsigned Region) {
  Uses[Region].insert_range(NewUsers);
}

void Rematerializer::Reg::eraseUser(MachineInstr *MI, unsigned Region) {
  RegionUsers &RUsers = Uses.at(Region);
  assert(RUsers.contains(MI) && "user not in region");
  if (RUsers.size() == 1)
    Uses.erase(Region);
  else
    RUsers.erase(MI);
}

Printable Rematerializer::printDependencyDAG(RegisterIdx RootIdx) const {
  return Printable([&, RootIdx](raw_ostream &OS) {
    DenseMap<RegisterIdx, unsigned> RegDepths;
    std::function<void(RegisterIdx, unsigned)> WalkTree =
        [&](RegisterIdx RegIdx, unsigned Depth) -> void {
      unsigned MaxDepth = std::max(RegDepths.lookup_or(RegIdx, Depth), Depth);
      RegDepths.emplace_or_assign(RegIdx, MaxDepth);
      for (RegisterIdx DepRegIdx : getReg(RegIdx).Dependencies)
        WalkTree(DepRegIdx, Depth + 1);
    };
    WalkTree(RootIdx, 0);

    // Sort in decreasing depth order to print root at the bottom.
    SmallVector<std::pair<RegisterIdx, unsigned>> Regs(RegDepths.begin(),
                                                       RegDepths.end());
    sort(Regs, [](const auto &LHS, const auto &RHS) {
      return LHS.second > RHS.second;
    });

    OS << printID(RootIdx) << " has " << Regs.size() - 1 << " dependencies\n";
    for (const auto &[RegIdx, Depth] : Regs) {
      OS << indent(Depth, 2) << (Depth ? '|' : '*') << ' '
         << printRematReg(RegIdx, /*SkipRegions=*/Depth) << '\n';
    }
    OS << printRegUsers(RootIdx);
  });
}

Printable Rematerializer::printID(RegisterIdx RegIdx) const {
  return Printable([&, RegIdx](raw_ostream &OS) {
    const Reg &PrintReg = getReg(RegIdx);
    OS << '(' << RegIdx << '/';
    if (!PrintReg.isAlive()) {
      OS << "<dead>";
    } else {
      OS << printReg(PrintReg.getDefReg(), &TRI,
                     PrintReg.DefMI->getOperand(0).getSubReg(), &MRI);
    }
    OS << ")[" << PrintReg.DefRegion << "]";
  });
}

Printable Rematerializer::printRematReg(RegisterIdx RegIdx,
                                        bool SkipRegions) const {
  return Printable([&, RegIdx, SkipRegions](raw_ostream &OS) {
    const Reg &PrintReg = getReg(RegIdx);
    OS << printID(RegIdx);
    if (!SkipRegions) {
      OS << " [" << PrintReg.DefRegion;
      if (!PrintReg.Uses.empty()) {
        assert(PrintReg.isAlive() && "dead register cannot have uses");
        const LiveInterval &LI = LIS.getInterval(PrintReg.getDefReg());
        // First display all regions in which the register is live-through and
        // not used.
        bool First = true;
        for (const auto &[I, Bounds] : enumerate(Regions)) {
          if (PrintReg.Uses.contains(I))
            continue;
          // The register must be live at the live-ins and live-outs of the
          // region.
          MachineBasicBlock::iterator LiveIn =
              skipDebugInstructionsForward(Bounds.first, Bounds.second);
          if (LiveIn == Bounds.second) {
            // The region has no non-debug instructions, it's hard to assess
            // whether the register is live across it without an index.
            continue;
          }
          // LiveIn is inside the range and a non-debug instruction so we know
          // this will also point to a non-debug instruction within the region.
          MachineBasicBlock::iterator LiveOut = skipDebugInstructionsBackward(
              std::prev(Bounds.second), Bounds.first);
          if (LI.liveAt(LIS.getInstructionIndex(*LiveIn)) &&
              LI.liveAt(LIS.getInstructionIndex(*LiveOut).getDeadSlot())) {
            OS << (First ? " - " : ",") << I;
            First = false;
          }
        }
        OS << (First ? " --> " : " -> ");

        // Then display regions in which the register is used.
        auto It = PrintReg.Uses.begin();
        OS << It->first;
        while (++It != PrintReg.Uses.end())
          OS << "," << It->first;
      }
      OS << "] ";
    }
    if (PrintReg.isAlive()) {
      PrintReg.DefMI->print(OS, /*IsStandalone=*/true, /*SkipOpers=*/false,
                            /*SkipDebugLoc=*/false, /*AddNewLine=*/false);
      OS << " @ ";
      LIS.getInstructionIndex(*PrintReg.DefMI).print(OS);
    }
  });
}

Printable Rematerializer::printRegUsers(RegisterIdx RegIdx) const {
  return Printable([&, RegIdx](raw_ostream &OS) {
    for (const auto &[UseRegion, Users] : getReg(RegIdx).Uses) {
      for (MachineInstr *MI : Users)
        OS << "  User " << printUser(MI, UseRegion) << '\n';
    }
  });
}

Printable Rematerializer::printUser(const MachineInstr *MI,
                                    std::optional<unsigned> UseRegion) const {
  return Printable([&, MI, UseRegion](raw_ostream &OS) {
    RegisterIdx RegIdx = getDefRegIdx(*MI);
    if (RegIdx != NoReg) {
      OS << printID(RegIdx);
    } else {
      OS << "(-/-)[";
      if (UseRegion)
        OS << *UseRegion;
      else
        OS << '?';
      OS << ']';
    }
    OS << ' ';
    MI->print(OS, /*IsStandalone=*/true, /*SkipOpers=*/false,
              /*SkipDebugLoc=*/false, /*AddNewLine=*/false);
    OS << " @ ";
    LIS.getInstructionIndex(*MI).print(OS);
  });
}

void Rollbacker::rematerializerNoteRegCreated(const Rematerializer &Remater,
                                              RegisterIdx RegIdx) {
  if (RollingBack)
    return;
  assert(Remater.isRematerializedRegister(RegIdx) && "only remats are created");
  Rematerializations[Remater.getOriginOf(RegIdx)].insert(RegIdx);
}

void Rollbacker::rematerializerNoteRegWillBeDeleted(
    const Rematerializer &Remater, RegisterIdx RegIdx) {
  if (RollingBack)
    return;

  // Find a valid re-creation position after the register's definition.
  MachineInstr *DefMI = Remater.getReg(RegIdx).DefMI;
  MachineBasicBlock *ParentMBB = DefMI->getParent();
  MachineBasicBlock::iterator ValidPos = std::next(DefMI->getIterator());
  while (ValidPos != ParentMBB->end() && isRollbackableMI(*ValidPos, Remater))
    ValidPos = std::next(ValidPos);

  if (Remater.isRematerializedRegister(RegIdx)) {
    // Rematerializations will not be re-created. Previously deleted registers
    // that reference this register's defining instruction as their re-creation
    // position should instead be re-created at a valid position after the
    // deleted MI.
    invalidatePosition(DefMI, ValidPos);
    return;
  }

  // Original registers can be re-created. Add a re-creation position for the
  // definition of the rematerializable register.
  DeadRegs.push_back(DeadReg(RegIdx, Remater));
  const InsertBeforePos InsertPos = makePos(ValidPos, ParentMBB);
  PosToIdx[InsertPos].insert(Positions.size());
  Positions.push_back(InsertPos);
}

void Rollbacker::rematerializerNoteMIWillBeDeleted(
    const Rematerializer &Remater, MachineInstr &MI) {
  if (RollingBack)
    return;

  // Previously deleted registers that reference this MI as their re-creation
  // position should instead be re-created at a valid position after it.
  MachineBasicBlock *ParentMBB = MI.getParent();
  MachineBasicBlock::iterator ValidPos = std::next(MI.getIterator());
  while (ValidPos != ParentMBB->end() && isRollbackableMI(*ValidPos, Remater))
    ValidPos = std::next(ValidPos);
  invalidatePosition(&MI, ValidPos);
}

void Rollbacker::rollback(Rematerializer &Remater) {
  RollingBack = true;

  // As we re-create registers, map deleted definitions to re-created ones. This
  // allows to replace invalid re-creation positions that reference deleted
  // definitions to valid new positions while restoring original MI order.
  DenseMap<MachineInstr *, MachineInstr *> Replacements;
  unsigned PositionIndex = Positions.size();

  // Re-create deleted registers in reverse order of deletion. Related registers
  // are deleted in reverse def-use order so this ensures we re-create registers
  // in def-use order. This also ensures that re-creation positions that became
  // invalid due to later MI deletions can be corrected as we go.
  for (const DeadReg &Reg : reverse(DeadRegs)) {
    if (Remater.isPermanentlyDead(Reg.Idx)) {
      // It is possible the register was permanently deleted as a consequence of
      // dead-def elimination.
      Rematerializations.erase(Reg.Idx);
      --PositionIndex;
      continue;
    }

    assert(!Remater.getReg(Reg.Idx).isAlive() && "register should be dead");

    // Determine re-creation position for the register's definition.
    MachineBasicBlock::iterator InsertPosition;
    InsertBeforePos Pos = Positions[--PositionIndex];
    if (auto *MBB = dyn_cast<MachineBasicBlock *>(Pos)) {
      InsertPosition = MBB->end();
    } else {
      auto *MI = cast<MachineInstr *>(Pos);
      InsertPosition = Replacements.lookup_or(MI, MI)->getIterator();
    }

    Remater.recreateReg(Reg.Idx, InsertPosition, Reg.DefReg);

    const Rematerializer::Reg &RecreateReg = Remater.getReg(Reg.Idx);
    if (!Replacements.insert({Reg.DefMI, RecreateReg.DefMI}).second)
      llvm_unreachable("duplicate deleted MI");
  }

  // Rollback rematerializations.
  for (const auto &[RegIdx, RematsOf] : Rematerializations) {
    for (RegisterIdx RematRegIdx : RematsOf) {
      // It is possible that rematerializations were deleted. Their users would
      // have been transfered to some other rematerialization so we can safely
      // ignore them. Original registers that were deleted were just re-created
      // so we do not need to check for that.
      if (Remater.getReg(RematRegIdx).isAlive())
        Remater.transferAllUsers(RematRegIdx, RegIdx);
    }
  }

  DeadRegs.clear();
  Positions.clear();
  PosToIdx.clear();
  Rematerializations.clear();
  RollingBack = false;
}

bool Rollbacker::isRollbackableMI(const MachineInstr &MI,
                                  const Rematerializer &Remater) const {
  RegisterIdx RegIdx = Remater.getDefRegIdx(MI);
  if (RegIdx == Rematerializer::NoReg ||
      !Remater.isRematerializedRegister(RegIdx))
    return false;
  // It is possible that the MI defines a rematerializable register that was not
  // recorded if the rollbacker was attached to the rematerializer after the
  // rematerialization happened. In such cases the MI won't be rolled back.
  auto RematsOf = Rematerializations.find(Remater.getOriginOf(RegIdx));
  if (RematsOf == Rematerializations.end())
    return false;
  return RematsOf->getSecond().contains(RegIdx);
}

void Rollbacker::invalidatePosition(MachineInstr *MI,
                                    MachineBasicBlock::iterator It) {
  const InsertBeforePos MIPos = InsertBeforePos(MI),
                        NewPos = makePos(It, MI->getParent());
  auto MIIndices = PosToIdx.find(MIPos);
  if (MIIndices == PosToIdx.end())
    return;
  const SmallDenseSet<unsigned, 1> &InvalIndices = MIIndices->getSecond();
  assert(!InvalIndices.empty() && "no index hold position");
  for (unsigned I : InvalIndices)
    Positions[I] = NewPos;
  PosToIdx.try_emplace(NewPos).first->getSecond().insert_range(InvalIndices);
  PosToIdx.erase(MIPos);
}
