//===- CodeGenRegisters.cpp - Register and RegisterClass Info -------------===//
//
// 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 defines structures to encapsulate information gleaned from the
// target register and register class definitions.
//
//===----------------------------------------------------------------------===//

#include "CodeGenRegisters.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntEqClasses.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TGTimer.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <iterator>
#include <map>
#include <queue>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

using namespace llvm;

#define DEBUG_TYPE "regalloc-emitter"

//===----------------------------------------------------------------------===//
//                             CodeGenSubRegIndex
//===----------------------------------------------------------------------===//

CodeGenSubRegIndex::CodeGenSubRegIndex(const Record *R, unsigned Enum,
                                       const CodeGenHwModes &CGH)
    : TheDef(R), Name(R->getName().str()), EnumValue(Enum),
      AllSuperRegsCovered(true), Artificial(true) {
  if (R->getValue("Namespace"))
    Namespace = R->getValueAsString("Namespace").str();

  if (const Record *RV = R->getValueAsOptionalDef("SubRegRanges"))
    Range = SubRegRangeByHwMode(RV, CGH);
  if (!Range.hasDefault())
    Range.insertSubRegRangeForMode(DefaultMode, SubRegRange(R));
}

CodeGenSubRegIndex::CodeGenSubRegIndex(StringRef N, StringRef Nspace,
                                       unsigned Enum)
    : TheDef(nullptr), Name(N.str()), Namespace(Nspace.str()),
      Range(SubRegRange(-1, -1)), EnumValue(Enum), AllSuperRegsCovered(true),
      Artificial(true) {}

std::string CodeGenSubRegIndex::getQualifiedName() const {
  std::string N = getNamespace();
  if (!N.empty())
    N += "::";
  N += getName();
  return N;
}

void CodeGenSubRegIndex::updateComponents(CodeGenRegBank &RegBank) {
  if (!TheDef)
    return;

  std::vector<const Record *> Comps =
      TheDef->getValueAsListOfDefs("ComposedOf");
  if (!Comps.empty()) {
    if (Comps.size() != 2)
      PrintFatalError(TheDef->getLoc(),
                      "ComposedOf must have exactly two entries");
    CodeGenSubRegIndex *A = RegBank.getSubRegIdx(Comps[0]);
    CodeGenSubRegIndex *B = RegBank.getSubRegIdx(Comps[1]);
    CodeGenSubRegIndex *X = A->addComposite(B, this, RegBank.getHwModes());
    if (X)
      PrintFatalError(TheDef->getLoc(), "Ambiguous ComposedOf entries");
  }

  std::vector<const Record *> Parts =
      TheDef->getValueAsListOfDefs("CoveringSubRegIndices");
  if (!Parts.empty()) {
    if (Parts.size() < 2)
      PrintFatalError(TheDef->getLoc(),
                      "CoveringSubRegIndices must have two or more entries");
    SmallVector<CodeGenSubRegIndex *, 8> IdxParts;
    for (const Record *Part : Parts)
      IdxParts.push_back(RegBank.getSubRegIdx(Part));
    setConcatenationOf(IdxParts);
  }
}

LaneBitmask CodeGenSubRegIndex::computeLaneMask() const {
  // Already computed?
  if (LaneMask.any())
    return LaneMask;

  // Recursion guard, shouldn't be required.
  LaneMask = LaneBitmask::getAll();

  // The lane mask is simply the union of all sub-indices.
  LaneBitmask M;
  for (const auto &C : Composed)
    M |= C.second->computeLaneMask();
  assert(M.any() && "Missing lane mask, sub-register cycle?");
  LaneMask = M;
  return LaneMask;
}

void CodeGenSubRegIndex::setConcatenationOf(
    ArrayRef<CodeGenSubRegIndex *> Parts) {
  if (ConcatenationOf.empty()) {
    ConcatenationOf.assign(Parts.begin(), Parts.end());
    return;
  }
  assert(llvm::equal(Parts, ConcatenationOf) && "parts consistent");
}

void CodeGenSubRegIndex::computeConcatTransitiveClosure() {
  for (SmallVectorImpl<CodeGenSubRegIndex *>::iterator I =
           ConcatenationOf.begin();
       I != ConcatenationOf.end();
       /*empty*/) {
    CodeGenSubRegIndex *SubIdx = *I;
    SubIdx->computeConcatTransitiveClosure();
#ifndef NDEBUG
    for (CodeGenSubRegIndex *SRI : SubIdx->ConcatenationOf)
      assert(SRI->ConcatenationOf.empty() && "No transitive closure?");
#endif

    if (SubIdx->ConcatenationOf.empty()) {
      ++I;
    } else {
      I = ConcatenationOf.erase(I);
      I = ConcatenationOf.insert(I, SubIdx->ConcatenationOf.begin(),
                                 SubIdx->ConcatenationOf.end());
      I += SubIdx->ConcatenationOf.size();
    }
  }
}

//===----------------------------------------------------------------------===//
//                              CodeGenRegister
//===----------------------------------------------------------------------===//

CodeGenRegister::CodeGenRegister(const Record *R, unsigned Enum)
    : TheDef(R), EnumValue(Enum),
      CostPerUse(R->getValueAsListOfInts("CostPerUse")),
      CoveredBySubRegs(R->getValueAsBit("CoveredBySubRegs")),
      Constant(R->getValueAsBit("isConstant")), SubRegsComplete(false),
      SuperRegsComplete(false), TopoSig(~0u) {
  Artificial = R->getValueAsBit("isArtificial");
}

void CodeGenRegister::buildObjectGraph(CodeGenRegBank &RegBank) {
  std::vector<const Record *> SRIs =
      TheDef->getValueAsListOfDefs("SubRegIndices");
  std::vector<const Record *> SRs = TheDef->getValueAsListOfDefs("SubRegs");

  for (const auto &[SRI, SR] : zip_equal(SRIs, SRs)) {
    ExplicitSubRegIndices.push_back(RegBank.getSubRegIdx(SRI));
    ExplicitSubRegs.push_back(RegBank.getReg(SR));
  }

  // Also compute leading super-registers. Each register has a list of
  // covered-by-subregs super-registers where it appears as the first explicit
  // sub-register.
  //
  // This is used by computeSecondarySubRegs() to find candidates.
  if (CoveredBySubRegs && !ExplicitSubRegs.empty())
    ExplicitSubRegs.front()->LeadingSuperRegs.push_back(this);

  // Add ad hoc alias links. This is a symmetric relationship between two
  // registers, so build a symmetric graph by adding links in both ends.
  for (const Record *Alias : TheDef->getValueAsListOfDefs("Aliases")) {
    CodeGenRegister *Reg = RegBank.getReg(Alias);
    ExplicitAliases.push_back(Reg);
    Reg->ExplicitAliases.push_back(this);
  }
}

// Inherit register units from subregisters.
// Return true if the RegUnits changed.
bool CodeGenRegister::inheritRegUnits(CodeGenRegBank &RegBank) {
  bool changed = false;
  for (const auto &[_, SR] : getSubRegs()) {
    // Merge the subregister's units into this register's RegUnits.
    changed |= (RegUnits |= SR->RegUnits);
  }

  return changed;
}

const CodeGenRegister::SubRegMap &
CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
  // Only compute this map once.
  if (SubRegsComplete)
    return SubRegs;
  SubRegsComplete = true;

  HasDisjunctSubRegs = ExplicitSubRegs.size() > 1;

  // First insert the explicit subregs and make sure they are fully indexed.
  for (auto [SR, Idx] : zip_equal(ExplicitSubRegs, ExplicitSubRegIndices)) {
    if (!SR->Artificial)
      Idx->Artificial = false;
    if (!SubRegs.try_emplace(Idx, SR).second)
      PrintFatalError(TheDef->getLoc(), "SubRegIndex " + Idx->getName() +
                                            " appears twice in Register " +
                                            getName());
    // Map explicit sub-registers first, so the names take precedence.
    // The inherited sub-registers are mapped below.
    SubReg2Idx.try_emplace(SR, Idx);
  }

  // Keep track of inherited subregs and how they can be reached.
  SmallPtrSet<CodeGenRegister *, 8> Orphans;

  // Clone inherited subregs and place duplicate entries in Orphans.
  // Here the order is important - earlier subregs take precedence.
  for (CodeGenRegister *ESR : ExplicitSubRegs) {
    const SubRegMap &Map = ESR->computeSubRegs(RegBank);
    HasDisjunctSubRegs |= ESR->HasDisjunctSubRegs;

    for (const auto &SR : Map) {
      if (!SubRegs.insert(SR).second)
        Orphans.insert(SR.second);
    }
  }

  // Expand any composed subreg indices.
  // If dsub_2 has ComposedOf = [qsub_1, dsub_0], and this register has a
  // qsub_1 subreg, add a dsub_2 subreg.  Keep growing Indices and process
  // expanded subreg indices recursively.
  SmallVector<CodeGenSubRegIndex *, 8> Indices = ExplicitSubRegIndices;
  for (unsigned i = 0; i != Indices.size(); ++i) {
    CodeGenSubRegIndex *Idx = Indices[i];
    const CodeGenSubRegIndex::CompMap &Comps = Idx->getComposites();
    CodeGenRegister *SR = SubRegs[Idx];
    const SubRegMap &Map = SR->computeSubRegs(RegBank);

    // Look at the possible compositions of Idx.
    // They may not all be supported by SR.
    for (auto [Key, Val] : Comps) {
      SubRegMap::const_iterator SRI = Map.find(Key);
      if (SRI == Map.end())
        continue; // Idx + I->first doesn't exist in SR.
      // Add `Val` as a name for the subreg SRI->second, assuming it is
      // orphaned, and the name isn't already used for something else.
      if (SubRegs.count(Val) || !Orphans.erase(SRI->second))
        continue;
      // We found a new name for the orphaned sub-register.
      SubRegs.try_emplace(Val, SRI->second);
      Indices.push_back(Val);
    }
  }

  // Now Orphans contains the inherited subregisters without a direct index.
  // Create inferred indexes for all missing entries.
  // Work backwards in the Indices vector in order to compose subregs bottom-up.
  // Consider this subreg sequence:
  //
  //   qsub_1 -> dsub_0 -> ssub_0
  //
  // The qsub_1 -> dsub_0 composition becomes dsub_2, so the ssub_0 register
  // can be reached in two different ways:
  //
  //   qsub_1 -> ssub_0
  //   dsub_2 -> ssub_0
  //
  // We pick the latter composition because another register may have [dsub_0,
  // dsub_1, dsub_2] subregs without necessarily having a qsub_1 subreg.  The
  // dsub_2 -> ssub_0 composition can be shared.
  while (!Indices.empty() && !Orphans.empty()) {
    CodeGenSubRegIndex *Idx = Indices.pop_back_val();
    CodeGenRegister *SR = SubRegs[Idx];
    const SubRegMap &Map = SR->computeSubRegs(RegBank);
    for (const auto &[SRI, SubReg] : Map)
      if (Orphans.erase(SubReg))
        SubRegs[RegBank.getCompositeSubRegIndex(Idx, SRI)] = SubReg;
  }

  // Compute the inverse SubReg -> Idx map.
  for (auto &[SRI, SubReg] : SubRegs) {
    if (SubReg == this) {
      ArrayRef<SMLoc> Loc;
      if (TheDef)
        Loc = TheDef->getLoc();
      PrintFatalError(Loc, "Register " + getName() +
                               " has itself as a sub-register");
    }

    // Compute AllSuperRegsCovered.
    if (!CoveredBySubRegs)
      SRI->AllSuperRegsCovered = false;

    // Ensure that every sub-register has a unique name.
    DenseMap<const CodeGenRegister *, CodeGenSubRegIndex *>::iterator Ins =
        SubReg2Idx.try_emplace(SubReg, SRI).first;
    if (Ins->second == SRI)
      continue;
    // Trouble: Two different names for SubReg.second.
    ArrayRef<SMLoc> Loc;
    if (TheDef)
      Loc = TheDef->getLoc();
    PrintFatalError(Loc, "Sub-register can't have two names: " +
                             SubReg->getName() + " available as " +
                             SRI->getName() + " and " + Ins->second->getName());
  }

  // Derive possible names for sub-register concatenations from any explicit
  // sub-registers. By doing this before computeSecondarySubRegs(), we ensure
  // that getConcatSubRegIndex() won't invent any concatenated indices that the
  // user already specified.
  for (auto [Idx, SR] : enumerate(ExplicitSubRegs)) {
    if (!SR->CoveredBySubRegs || SR->Artificial)
      continue;

    // SR is composed of multiple sub-regs. Find their names in this register.
    bool AnyArtificial = false;
    SmallVector<CodeGenSubRegIndex *, 8> Parts;
    for (unsigned j = 0, e = SR->ExplicitSubRegs.size(); j != e; ++j) {
      CodeGenSubRegIndex &I = *SR->ExplicitSubRegIndices[j];
      if (I.Artificial) {
        AnyArtificial = true;
        break;
      }
      Parts.push_back(getSubRegIndex(SR->ExplicitSubRegs[j]));
    }

    if (AnyArtificial)
      continue;

    // Offer this as an existing spelling for the concatenation of Parts.
    ExplicitSubRegIndices[Idx]->setConcatenationOf(Parts);
  }

  // Initialize RegUnitList. Because getSubRegs is called recursively, this
  // processes the register hierarchy in postorder.
  if (ExplicitSubRegs.empty()) {
    // Create one register unit per leaf register. These units correspond to the
    // maximal cliques in the register overlap graph which is optimal.
    RegUnits.set(RegBank.newRegUnit(this));
  } else {
    // Inherit all sub-register units. It is good enough to look at the explicit
    // sub-registers, the other registers won't contribute any more units.
    for (const CodeGenRegister *SR : ExplicitSubRegs)
      RegUnits |= SR->RegUnits;
  }

  // When there is ad hoc aliasing, we simply create one unit per edge in the
  // undirected ad hoc aliasing graph. Technically, we could do better by
  // identifying maximal cliques in the ad hoc graph, but cliques larger than 2
  // are extremely rare anyway (I've never seen one), so we don't bother with
  // the added complexity.
  for (CodeGenRegister *AR : ExplicitAliases) {
    // Only visit each edge once.
    if (AR->SubRegsComplete)
      continue;
    // Create a RegUnit representing this alias edge, and add it to both
    // registers.
    unsigned Unit = RegBank.newRegUnit(this, AR);
    RegUnits.set(Unit);
    AR->RegUnits.set(Unit);
  }

  // We have now computed the native register units. More may be adopted later
  // for balancing purposes.
  NativeRegUnits = RegUnits;

  return SubRegs;
}

// Verify that a register's explicit sub-registers fit within it. A SubRegIndex
// whose offset+size runs past the register's own size gives that sub-register
// an oversized lane mask, which silently corrupts sub-register liveness and
// spilling and is not otherwise diagnosed. (This was found via a real
// wrong-code bug in a downstream target, where a 64-bit exponent sub-register
// index was mistakenly declared with size 576.) The check is limited to
// registers whose explicit sub-registers tile a contiguous bit range:
// strided/spaced register tuples (e.g. ARM's Tuples3DSpc,
// [dsub_0, dsub_2, dsub_4]) deliberately place sub-registers at non-adjacent
// offsets that extend past the nominal size, and are not bugs.
void CodeGenRegister::checkSubRegIndexSizes(CodeGenRegBank &RegBank) const {
  // Only registers that are covered by their sub-registers promise to be fully
  // tiled by them; for those an explicit SubRegIndex extending past the
  // register is a genuine bug. A register that is not covered by its
  // sub-registers makes no such promise, so don't second-guess its layout.
  if (!CoveredBySubRegs)
    return;

  // This register's own bit size is the largest register class containing it.
  unsigned ParentSize = 0;
  for (const auto &RC : RegBank.getRegClasses()) {
    if (!RC.contains(this) || !RC.RSI.hasDefault())
      continue;
    // Only trust a register-class size that is backed by a real value type.
    // An 'untyped' class carries a placeholder size, not the register's bit
    // width, so its size cannot be compared against sub-register extents.
    // getValueTypes() is indexed by HwMode; DefaultMode is the first entry.
    ArrayRef<ValueTypeByHwMode> VTs = RC.getValueTypes();
    if (VTs.empty())
      continue;
    const ValueTypeByHwMode &VT = VTs[DefaultMode];
    if (!VT.isSimple() || VT.getSimple() == MVT::Untyped)
      continue;
    ParentSize = std::max(ParentSize, RC.RSI.get(DefaultMode).RegSize);
  }
  if (!ParentSize)
    return;

  // Collect the explicit sub-register (offset, size) ranges. Bail on any
  // register with incomplete or non-contiguous range info.
  SmallVector<std::pair<unsigned, unsigned>> Ranges;
  for (const CodeGenSubRegIndex *Idx : ExplicitSubRegIndices) {
    if (!Idx->Range.hasDefault())
      return;
    const SubRegRange &R = Idx->Range.get(DefaultMode);
    if (R.Size == static_cast<uint32_t>(-1) ||
        R.Offset == static_cast<uint32_t>(-1))
      return; // tuple sub-index with no contiguous bit range (e.g. X86 KPAIRS,
              // ARM strided NEON tuples)
    Ranges.emplace_back(R.Offset, R.Size);
  }
  if (Ranges.empty())
    return;

  // ExplicitSubRegIndices is in .td declaration order, not offset order, so
  // sort by offset before scanning. Only a contiguous tiling is a dense bit
  // container; anything left with a gap or overlap is a strided/spaced tuple
  // (also covered-by-subregs), which is allowed to exceed the nominal size.
  llvm::sort(Ranges);
  unsigned Pos = 0;
  for (auto [Off, Sz] : Ranges) {
    if (Off != Pos)
      return; // gap or overlap -> strided/sparse, skip
    Pos += Sz;
  }

  if (Pos > ParentSize)
    PrintFatalError(TheDef,
                    formatv("register '{}' has size {} but its explicit "
                            "sub-registers cover {} bits",
                            getName(), ParentSize, Pos));
}

// In a register that is covered by its sub-registers, try to find redundant
// sub-registers. For example:
//
//   QQ0 = {Q0, Q1}
//   Q0 = {D0, D1}
//   Q1 = {D2, D3}
//
// We can infer that D1_D2 is also a sub-register, even if it wasn't named in
// the register definition.
//
// The explicitly specified registers form a tree. This function discovers
// sub-register relationships that would force a DAG.
//
void CodeGenRegister::computeSecondarySubRegs(CodeGenRegBank &RegBank) {
  SmallVector<SubRegMap::value_type, 8> NewSubRegs;

  std::queue<std::pair<CodeGenSubRegIndex *, CodeGenRegister *>> SubRegQueue;
  for (auto [SRI, SubReg] : SubRegs)
    SubRegQueue.emplace(SRI, SubReg);

  // Look at the leading super-registers of each sub-register. Those are the
  // candidates for new sub-registers, assuming they are fully contained in
  // this register.
  while (!SubRegQueue.empty()) {
    auto [SubRegIdx, SubReg] = SubRegQueue.front();
    SubRegQueue.pop();

    const CodeGenRegister::SuperRegList &Leads = SubReg->LeadingSuperRegs;
    for (const CodeGenRegister *Cand : Leads) {
      // Already got this sub-register?
      if (Cand == this || getSubRegIndex(Cand))
        continue;
      // Check if each component of Cand is already a sub-register.
      assert(!Cand->ExplicitSubRegs.empty() &&
             "Super-register has no sub-registers");
      if (Cand->ExplicitSubRegs.size() == 1)
        continue;
      SmallVector<CodeGenSubRegIndex *, 8> Parts;
      // We know that the first component is (SubRegIdx,SubReg). However we
      // may still need to split it into smaller subregister parts.
      assert(Cand->ExplicitSubRegs[0] == SubReg && "LeadingSuperRegs correct");
      assert(getSubRegIndex(SubReg) == SubRegIdx && "LeadingSuperRegs correct");
      for (CodeGenRegister *SubReg : Cand->ExplicitSubRegs) {
        if (CodeGenSubRegIndex *SubRegIdx = getSubRegIndex(SubReg)) {
          if (SubRegIdx->ConcatenationOf.empty())
            Parts.push_back(SubRegIdx);
          else
            append_range(Parts, SubRegIdx->ConcatenationOf);
        } else {
          // Sub-register doesn't exist.
          Parts.clear();
          break;
        }
      }
      // There is nothing to do if some Cand sub-register is not part of this
      // register.
      if (Parts.empty())
        continue;

      // Each part of Cand is a sub-register of this. Make the full Cand also
      // a sub-register with a concatenated sub-register index.
      CodeGenSubRegIndex *Concat =
          RegBank.getConcatSubRegIndex(Parts, RegBank.getHwModes());
      std::pair<CodeGenSubRegIndex *, CodeGenRegister *> NewSubReg = {
          Concat, const_cast<CodeGenRegister *>(Cand)};

      if (!SubRegs.insert(NewSubReg).second)
        continue;

      // We inserted a new subregister.
      NewSubRegs.push_back(NewSubReg);
      SubRegQueue.push(NewSubReg);
      SubReg2Idx.try_emplace(Cand, Concat);
    }
  }

  // Create sub-register index composition maps for the synthesized indices.
  for (auto [NewIdx, NewSubReg] : NewSubRegs) {
    for (auto [SRI, SubReg] : NewSubReg->SubRegs) {
      CodeGenSubRegIndex *SubIdx = getSubRegIndex(SubReg);
      if (!SubIdx)
        PrintFatalError(TheDef->getLoc(), "No SubRegIndex for " +
                                              SubReg->getName() + " in " +
                                              getName());
      NewIdx->addComposite(SRI, SubIdx, RegBank.getHwModes());
    }
  }
}

CodeGenRegister *CodeGenRegister::getSubReg(const CodeGenSubRegIndex *Idx,
                                            unsigned &Hint) const {
  assert(SuperRegsComplete && "Must precompute super-registers");
  if (Hint < FinalSubRegs.size() && FinalSubRegs[Hint].first == Idx)
    return FinalSubRegs[Hint].second;

  auto It = llvm::lower_bound(FinalSubRegs, Idx->EnumValue,
                              [](const auto &Entry, unsigned EnumValue) {
                                return Entry.first->EnumValue < EnumValue;
                              });
  if (It == FinalSubRegs.end() || It->first != Idx)
    return nullptr;
  Hint = It - FinalSubRegs.begin();
  return It->second;
}

void CodeGenRegister::computeSuperRegs(CodeGenRegBank &RegBank) {
  // Only visit each register once.
  if (SuperRegsComplete)
    return;
  SuperRegsComplete = true;

  // Make sure all sub-registers have been visited first, so the super-reg
  // lists will be topologically ordered.
  for (auto SubReg : SubRegs)
    SubReg.second->computeSuperRegs(RegBank);

  // Now add this as a super-register on all sub-registers.
  // Also compute the TopoSigId in post-order.
  TopoSigId Id;
  FinalSubRegs.reserve(SubRegs.size());
  for (auto SubReg : SubRegs) {
    FinalSubRegs.push_back(SubReg);

    // Topological signature computed from SubIdx, TopoId(SubReg).
    // Loops and idempotent indices have TopoSig = ~0u.
    Id.push_back(SubReg.first->EnumValue);
    Id.push_back(SubReg.second->TopoSig);

    // Don't add duplicate entries.
    if (!SubReg.second->SuperRegs.empty() &&
        SubReg.second->SuperRegs.back() == this)
      continue;
    SubReg.second->SuperRegs.push_back(this);
  }

  TopoSig = RegBank.getTopoSig(Id);
  SubRegs = SubRegMap();
}

void CodeGenRegister::addSubRegsPreOrder(
    SetVector<const CodeGenRegister *> &OSet, CodeGenRegBank &RegBank) const {
  assert(SuperRegsComplete && "Must precompute super-registers");
  for (CodeGenRegister *SR : ExplicitSubRegs) {
    if (OSet.insert(SR))
      SR->addSubRegsPreOrder(OSet, RegBank);
  }
  // Add any secondary sub-registers that weren't part of the explicit tree.
  OSet.insert_range(llvm::make_second_range(FinalSubRegs));
}

// Get the sum of this register's unit weights.
unsigned CodeGenRegister::getWeight(const CodeGenRegBank &RegBank) const {
  unsigned Weight = 0;
  for (unsigned RegUnit : RegUnits)
    Weight += RegBank.getRegUnit(RegUnit).Weight;
  return Weight;
}

//===----------------------------------------------------------------------===//
//                               RegisterTuples
//===----------------------------------------------------------------------===//

// A RegisterTuples def is used to generate pseudo-registers from lists of
// sub-registers. We provide a SetTheory expander class that returns the new
// registers.
namespace {

struct TupleExpander : SetTheory::Expander {
  // Reference to SynthDefs in the containing CodeGenRegBank, to keep track of
  // the synthesized definitions for their lifetime.
  std::vector<std::unique_ptr<Record>> &SynthDefs;

  // Track all synthesized tuple names in order to detect duplicate definitions.
  llvm::StringSet<> TupleNames;

  TupleExpander(std::vector<std::unique_ptr<Record>> &SynthDefs)
      : SynthDefs(SynthDefs) {}

  void expand(SetTheory &ST, const Record *Def,
              SetTheory::RecSet &Elts) override {
    std::vector<const Record *> Indices =
        Def->getValueAsListOfDefs("SubRegIndices");
    unsigned Dim = Indices.size();
    const ListInit *SubRegs = Def->getValueAsListInit("SubRegs");

    // Evaluate the sub-register lists to be zipped.
    unsigned Length = ~0u;
    SmallVector<SetTheory::RecSet, 4> Lists(Dim);
    for (unsigned i = 0; i != Dim; ++i) {
      ST.evaluate(SubRegs->getElement(i), Lists[i], Def->getLoc());
      Length = std::min(Length, unsigned(Lists[i].size()));
    }

    if (Length == 0)
      return;

    // Precompute some types.
    const Record *RegisterCl = Def->getRecords().getClass("Register");
    const RecTy *RegisterRecTy = RecordRecTy::get(RegisterCl);
    std::vector<StringRef> RegNames =
        Def->getValueAsListOfStrings("RegAsmNames");

    // Zip them up.
    RecordKeeper &RK = Def->getRecords();
    for (unsigned n = 0; n != Length; ++n) {
      std::string Name;
      const Record *Proto = Lists[0][n];
      std::vector<Init *> Tuple;
      for (unsigned i = 0; i != Dim; ++i) {
        const Record *Reg = Lists[i][n];
        if (i)
          Name += '_';
        Name += Reg->getName();
        Tuple.push_back(Reg->getDefInit());
      }

      // Take the cost list of the first register in the tuple.
      const ListInit *CostList = Proto->getValueAsListInit("CostPerUse");
      SmallVector<const Init *, 2> CostPerUse(CostList->getElements());

      const StringInit *AsmName = StringInit::get(RK, "");
      if (!RegNames.empty()) {
        if (RegNames.size() <= n)
          PrintFatalError(Def->getLoc(),
                          "Register tuple definition missing name for '" +
                              Name + "'.");
        AsmName = StringInit::get(RK, RegNames[n]);
      }

      // Create a new Record representing the synthesized register. This record
      // is only for consumption by CodeGenRegister, it is not added to the
      // RecordKeeper.
      SynthDefs.emplace_back(
          std::make_unique<Record>(Name, Def->getLoc(), Def->getRecords()));
      Record *NewReg = SynthDefs.back().get();
      Elts.insert(NewReg);

      // Detect duplicates among synthesized registers.
      const auto Res = TupleNames.insert(NewReg->getName());
      if (!Res.second)
        PrintFatalError(Def->getLoc(),
                        "Register tuple redefines register '" + Name + "'.");

      // Copy Proto super-classes.
      for (const auto &[Super, Loc] : Proto->getDirectSuperClasses())
        NewReg->addDirectSuperClass(Super, Loc);

      // Copy Proto fields.
      for (RecordVal RV : Proto->getValues()) {
        // Skip existing fields, like NAME.
        if (NewReg->getValue(RV.getNameInit()))
          continue;

        StringRef Field = RV.getName();

        // Replace the sub-register list with Tuple.
        if (Field == "SubRegs")
          RV.setValue(ListInit::get(Tuple, RegisterRecTy));

        if (Field == "AsmName")
          RV.setValue(AsmName);

        // CostPerUse is aggregated from all Tuple members.
        if (Field == "CostPerUse")
          RV.setValue(ListInit::get(CostPerUse, CostList->getElementType()));

        // Composite registers are always covered by sub-registers.
        if (Field == "CoveredBySubRegs")
          RV.setValue(BitInit::get(RK, true));

        // Copy fields from the RegisterTuples def.
        if (Field == "SubRegIndices") {
          NewReg->addValue(*Def->getValue(Field));
          continue;
        }

        // Some fields get their default uninitialized value.
        if (Field == "DwarfNumbers" || Field == "DwarfAlias" ||
            Field == "Aliases") {
          if (const RecordVal *DefRV = RegisterCl->getValue(Field))
            NewReg->addValue(*DefRV);
          continue;
        }

        // Everything else is copied from Proto.
        NewReg->addValue(RV);
      }
    }
  }
};

} // end anonymous namespace

//===----------------------------------------------------------------------===//
//                            CodeGenRegisterClass
//===----------------------------------------------------------------------===//

static void sortAndUniqueRegisters(CodeGenRegister::Vec &M) {
  llvm::sort(M, deref<std::less<>>());
  M.erase(llvm::unique(M, deref<std::equal_to<>>()), M.end());
}

CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank,
                                           const Record *R)
    : TheDef(R), Name(R->getName().str()),
      RegsWithSuperRegsTopoSigs(RegBank.getNumTopoSigs()), EnumValue(-1),
      TSFlags(0) {
  GeneratePressureSet = R->getValueAsBit("GeneratePressureSet");
  for (const Record *Type : R->getValueAsListOfDefs("RegTypes"))
    VTs.push_back(getValueTypeByHwMode(Type, RegBank.getHwModes()));

  // Allocation order 0 is the full set. AltOrders provides others.
  const SetTheory::RecVec *Elements = RegBank.getSets().expand(R);
  const ListInit *AltOrders = R->getValueAsListInit("AltOrders");
  Orders.resize(1 + AltOrders->size());

  // Default allocation order always contains all registers.
  MemberBV.resize(RegBank.getRegisters().size());
  Artificial = true;
  for (const Record *Element : *Elements) {
    Orders[0].push_back(Element);
    const CodeGenRegister *Reg = RegBank.getReg(Element);
    Members.push_back(Reg);
    MemberBV.set(CodeGenRegBank::getRegIndex(Reg));
    Artificial &= Reg->Artificial;
    if (!Reg->getSuperRegs().empty())
      RegsWithSuperRegsTopoSigs.set(Reg->getTopoSig());
  }
  sortAndUniqueRegisters(Members);

  // Alternative allocation orders may be subsets.
  SetTheory::RecSet Order;
  for (auto [Idx, AltOrderElem] : enumerate(AltOrders->getElements())) {
    RegBank.getSets().evaluate(AltOrderElem, Order, R->getLoc());
    Orders[1 + Idx].append(Order.begin(), Order.end());
    // Verify that all altorder members are regclass members.
    while (!Order.empty()) {
      CodeGenRegister *Reg = RegBank.getReg(Order.back());
      Order.pop_back();
      if (!contains(Reg))
        PrintFatalError(R->getLoc(), " AltOrder register " + Reg->getName() +
                                         " is not a class member");
    }
  }

  Namespace = R->getValueAsString("Namespace");

  if (const Record *RV = R->getValueAsOptionalDef("RegInfos"))
    RSI = RegSizeInfoByHwMode(RV, RegBank.getHwModes());
  unsigned Size = R->getValueAsInt("Size");
  if (!RSI.hasDefault() && Size == 0 && !VTs[0].isSimple())
    PrintFatalError(R->getLoc(), "Impossible to determine register size");
  if (!RSI.hasDefault()) {
    RegSizeInfo RI;
    RI.RegSize = RI.SpillSize =
        Size ? Size : VTs[0].getSimple().getSizeInBits();
    RI.SpillAlignment = R->getValueAsInt("Alignment");
    RSI.insertRegSizeForMode(DefaultMode, RI);
  }

  int CopyCostParsed = R->getValueAsInt("CopyCost");
  Allocatable = R->getValueAsBit("isAllocatable");
  AltOrderSelect = R->getValueAsString("AltOrderSelect");
  int SpillStackIDParsed = R->getValueAsInt("SpillStackID");
  if (!isUInt<8>(SpillStackIDParsed))
    PrintFatalError(R->getLoc(), "SpillStackID out of range [0,255]");
  SpillStackID = SpillStackIDParsed;
  int AllocationPriority = R->getValueAsInt("AllocationPriority");
  if (!isUInt<5>(AllocationPriority))
    PrintFatalError(R->getLoc(), "AllocationPriority out of range [0,31]");
  this->AllocationPriority = AllocationPriority;

  GlobalPriority = R->getValueAsBit("GlobalPriority");

  const BitsInit *TSF = R->getValueAsBitsInit("TSFlags");
  TSFlags = uint8_t(*TSF->convertInitializerToInt());

  // Saturate negative costs to the maximum
  if (CopyCostParsed < 0)
    CopyCost = std::numeric_limits<uint8_t>::max();
  else if (!isUInt<8>(CopyCostParsed))
    PrintFatalError(R->getLoc(), "'CopyCost' must be an 8-bit value");

  CopyCost = CopyCostParsed;
}

// Create an inferred register class that was missing from the .td files.
// Most properties will be inherited from the closest super-class after the
// class structure has been computed.
CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank,
                                           StringRef Name, Key Props)
    : Members(*Props.Members), TheDef(nullptr), Name(Name.str()),
      RegsWithSuperRegsTopoSigs(RegBank.getNumTopoSigs()), EnumValue(-1),
      RSI(Props.RSI), CopyCost(0), Allocatable(true), AllocationPriority(0),
      GlobalPriority(false), TSFlags(0), SpillStackID(0) {
  MemberBV.resize(RegBank.getRegisters().size());
  Artificial = true;
  GeneratePressureSet = false;
  for (const auto R : Members) {
    MemberBV.set(CodeGenRegBank::getRegIndex(R));
    if (!R->getSuperRegs().empty())
      RegsWithSuperRegsTopoSigs.set(R->getTopoSig());
    Artificial &= R->Artificial;
  }
}

// Compute inherited properties for a synthesized register class.
void CodeGenRegisterClass::inheritProperties(CodeGenRegBank &RegBank) {
  assert(!getDef() && "Only synthesized classes can inherit properties");
  assert(!SuperClasses.empty() && "Synthesized class without super class");

  // The last super-class is the smallest one in topological order. Check for
  // allocatable super-classes and inherit from the nearest allocatable one if
  // any.
  auto NearestAllocSCRIt =
      find_if(reverse(SuperClasses),
              [&](const CodeGenRegisterClass *S) { return S->Allocatable; });
  CodeGenRegisterClass &Super = NearestAllocSCRIt == SuperClasses.rend()
                                    ? *SuperClasses.back()
                                    : **NearestAllocSCRIt;

  // Most properties are copied directly.
  // Exceptions are members, size, and alignment
  Namespace = Super.Namespace;
  VTs = Super.VTs;
  CopyCost = Super.CopyCost;
  Allocatable = Super.Allocatable;
  AltOrderSelect = Super.AltOrderSelect;
  AllocationPriority = Super.AllocationPriority;
  GlobalPriority = Super.GlobalPriority;
  TSFlags = Super.TSFlags;
  SpillStackID = Super.SpillStackID;
  GeneratePressureSet |= Super.GeneratePressureSet;

  // Copy all allocation orders, filter out foreign registers from the larger
  // super-class.
  Orders.resize(Super.Orders.size());
  for (auto [Idx, Outer] : enumerate(Super.Orders))
    for (const Record *Reg : Outer)
      if (contains(RegBank.getReg(Reg)))
        Orders[Idx].push_back(Reg);
}

bool CodeGenRegisterClass::hasType(const ValueTypeByHwMode &VT) const {
  if (llvm::is_contained(VTs, VT))
    return true;

  // If VT is not identical to any of this class's types, but is a simple
  // type, check if any of the types for this class contain it under some
  // mode.
  // The motivating example came from RISC-V, where (likely because of being
  // guarded by "64-bit" predicate), the type of X5 was {*:[i64]}, but the
  // type in GRC was {*:[i32], m1:[i64]}.
  if (VT.isSimple()) {
    MVT T = VT.getSimple();
    for (const ValueTypeByHwMode &OurVT : VTs) {
      if (llvm::is_contained(llvm::make_second_range(OurVT), T))
        return true;
    }
  }
  return false;
}

bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const {
  return MemberBV.test(CodeGenRegBank::getRegIndex(Reg));
}

unsigned CodeGenRegisterClass::getWeight(const CodeGenRegBank &RegBank) const {
  if (TheDef && !TheDef->isValueUnset("Weight"))
    return TheDef->getValueAsInt("Weight");

  if (Artificial)
    return 0;

  for (const CodeGenRegister *Reg : Members) {
    if (!Reg->Artificial)
      return Reg->getWeight(RegBank);
  }

  return 0;
}

// This is a simple lexicographical order that can be used to search for sets.
// It is not the same as the topological order provided by TopoOrderRC.
bool CodeGenRegisterClass::Key::operator<(
    const CodeGenRegisterClass::Key &B) const {
  assert(Members && B.Members);

  // Lexicographical comparison. Ignores artificial registers when asked.
  auto IA = Members->begin(), EA = Members->end();
  auto IB = B.Members->begin(), EB = B.Members->end();
  for (;;) {
    while (IgnoreArtificialMembers && IA != EA && (*IA)->Artificial)
      ++IA;
    while (IgnoreArtificialMembers && IB != EB && (*IB)->Artificial)
      ++IB;
    if (IA == EA && IB == EB)
      break;
    if (IA == EA || IB == EB)
      return IA == EA;
    if (**IA != **IB)
      return **IA < **IB;
    ++IA;
    ++IB;
  }
  return RSI < B.RSI;
}

// Returns true if RC is a strict subclass.
// RC is a sub-class of this class if it is a valid replacement for any
// instruction operand where a register of this classis required. It must
// satisfy these conditions:
//
// 1. All RC registers are also in this.
// 2. The RC spill size must not be smaller than our spill size.
// 3. RC spill alignment must be compatible with ours.
//
static bool testSubClass(const CodeGenRegisterClass *A,
                         const CodeGenRegisterClass *B) {
  return A->RSI.isSubClassOf(B->RSI) &&
         llvm::includes(A->getMembers(), B->getMembers(), deref<std::less<>>());
}

/// Sorting predicate for register classes.  This provides a topological
/// ordering that arranges all register classes before their sub-classes.
///
/// Register classes with the same registers, spill size, and alignment form a
/// clique. They will be ordered alphabetically.
///
static bool TopoOrderRC(const CodeGenRegisterClass &A,
                        const CodeGenRegisterClass &B) {
  if (&A == &B)
    return false;

  constexpr size_t SIZET_MAX = std::numeric_limits<size_t>::max();

  // Sort in the following order:
  // (a) first by register size in ascending order.
  // (b) then by set size in descending order.
  // (c) finally, by name as a tie breaker.
  //
  // For set size, note that the classes' allocation order may not have been
  // computed yet, but the members set is always valid. Also, since we use
  // std::tie() < operator for ordering, we can achieve the descending set size
  // ordering by using (SIZET_MAX - set_size) in the std::tie.
  return std::tuple(A.RSI, SIZET_MAX - A.getMembers().size(),
                    StringRef(A.getName())) <
         std::tuple(B.RSI, SIZET_MAX - B.getMembers().size(),
                    StringRef(B.getName()));
}

std::string CodeGenRegisterClass::getNamespaceQualification() const {
  return Namespace.empty() ? "" : (Namespace + "::").str();
}

std::string CodeGenRegisterClass::getQualifiedName() const {
  return getNamespaceQualification() + getName();
}

std::string CodeGenRegisterClass::getIdName() const {
  return getName() + "RegClassID";
}

std::string CodeGenRegisterClass::getQualifiedIdName() const {
  return getNamespaceQualification() + getIdName();
}

// Compute sub-classes of all register classes.
// Assume the classes are ordered topologically.
void CodeGenRegisterClass::computeSubClasses(CodeGenRegBank &RegBank) {
  std::list<CodeGenRegisterClass> &RegClasses = RegBank.getRegClasses();

  const size_t NumRegClasses = RegClasses.size();
  // Visit backwards so sub-classes are seen first.
  for (auto I = RegClasses.rbegin(), E = RegClasses.rend(); I != E; ++I) {
    CodeGenRegisterClass &RC = *I;
    RC.SubClasses.resize(NumRegClasses);
    RC.SubClasses.set(RC.EnumValue);
    if (RC.Artificial)
      continue;

    // Normally, all subclasses have IDs >= rci, unless RC is part of a clique.
    for (auto I2 = I.base(), E2 = RegClasses.end(); I2 != E2; ++I2) {
      CodeGenRegisterClass &SubRC = *I2;
      if (RC.SubClasses.test(SubRC.EnumValue))
        continue;
      if (!testSubClass(&RC, &SubRC))
        continue;
      // SubRC is a sub-class. Grap all its sub-classes so we won't have to
      // check them again.
      RC.SubClasses |= SubRC.SubClasses;
    }

    // Sweep up missed clique members.  They will be immediately preceding RC.
    for (auto I2 = std::next(I); I2 != E && testSubClass(&RC, &*I2); ++I2)
      RC.SubClasses.set(I2->EnumValue);
  }

  // Compute the SuperClasses lists from the SubClasses vectors.
  for (auto &RC : RegClasses) {
    const BitVector &SC = RC.getSubClasses();
    auto I = RegClasses.begin();
    for (int s = 0, next_s = SC.find_first(); next_s != -1;
         next_s = SC.find_next(s)) {
      std::advance(I, next_s - s);
      s = next_s;
      if (&*I == &RC)
        continue;
      I->SuperClasses.push_back(&RC);
    }
  }

  // With the class hierarchy in place, let synthesized register classes inherit
  // properties from their closest super-class. The iteration order here can
  // propagate properties down multiple levels.
  for (CodeGenRegisterClass &RC : RegClasses)
    if (!RC.getDef())
      RC.inheritProperties(RegBank);
}

std::optional<std::pair<CodeGenRegisterClass *, CodeGenRegisterClass *>>
CodeGenRegisterClass::getMatchingSubClassWithSubRegs(
    CodeGenRegBank &RegBank, const CodeGenSubRegIndex *SubIdx) const {
  auto WeakSizeOrder = [this](const CodeGenRegisterClass *A,
                              const CodeGenRegisterClass *B) {
    // If there are multiple, identical register classes, prefer the original
    // register class.
    if (A == B)
      return false;
    if (A->getMembers().size() == B->getMembers().size()) {
      if (A->getBaseClassOrder() != B->getBaseClassOrder())
        return A->getBaseClassOrder() > B->getBaseClassOrder();
      return A == this;
    }
    return A->getMembers().size() > B->getMembers().size();
  };

  std::list<CodeGenRegisterClass> &RegClasses = RegBank.getRegClasses();

  // Find all the subclasses of this one that fully support the sub-register
  // index and order them by size. BiggestSuperRC should always be first.
  CodeGenRegisterClass *BiggestSuperRegRC = getSubClassWithSubReg(SubIdx);
  if (!BiggestSuperRegRC)
    return std::nullopt;
  BitVector SuperRegRCsBV = BiggestSuperRegRC->getSubClasses();
  std::vector<CodeGenRegisterClass *> SuperRegRCs;
  for (auto &RC : RegClasses)
    if (SuperRegRCsBV[RC.EnumValue])
      SuperRegRCs.emplace_back(&RC);
  llvm::stable_sort(SuperRegRCs, WeakSizeOrder);

  assert((SuperRegRCs.front() == BiggestSuperRegRC ||
          SuperRegRCs.front()->getBaseClassOrder() >
              BiggestSuperRegRC->getBaseClassOrder()) &&
         "Biggest class wasn't first");

  // Find all the subreg classes and order them by size too.
  std::vector<CodeGenRegisterClass *> SuperRegClasses;
  for (auto &RC : RegClasses) {
    if (RC.hasAnySuperRegClasses(SubIdx))
      SuperRegClasses.push_back(&RC);
  }
  llvm::stable_sort(SuperRegClasses, WeakSizeOrder);

  // Find the biggest subclass and subreg class such that R:subidx is in the
  // subreg class for all R in subclass.
  //
  // For example:
  // All registers in X86's GR64 have a sub_32bit subregister but no class
  // exists that contains all the 32-bit subregisters because GR64 contains RIP
  // but GR32 does not contain EIP. Instead, we constrain SuperRegRC to
  // GR32_with_sub_8bit (which is identical to GR32_with_sub_32bit) and then,
  // having excluded RIP, we are able to find a SubRegRC (GR32).
  CodeGenRegisterClass *ChosenSuperRegClass = nullptr;
  CodeGenRegisterClass *SubRegRC = nullptr;
  for (CodeGenRegisterClass *SuperRegRC : SuperRegRCs) {
    for (CodeGenRegisterClass *SuperRegClass : SuperRegClasses) {
      if (SuperRegClass->hasSuperRegClass(SubIdx, SuperRegRC)) {
        SubRegRC = SuperRegClass;
        ChosenSuperRegClass = SuperRegRC;

        // If SubRegRC is bigger than SuperRegRC then there are members of
        // SubRegRC that don't have super registers via SubIdx. Keep looking to
        // find a better fit and fall back on this one if there isn't one.
        //
        // This is intended to prevent X86 from making odd choices such as
        // picking LOW32_ADDR_ACCESS_RBP instead of GR32 in the example above.
        // LOW32_ADDR_ACCESS_RBP is a valid choice but contains registers that
        // aren't subregisters of SuperRegRC whereas GR32 has a direct 1:1
        // mapping.
        if (SuperRegRC->getMembers().size() >= SubRegRC->getMembers().size())
          return std::pair(ChosenSuperRegClass, SubRegRC);
      }
    }

    // If we found a fit but it wasn't quite ideal because SubRegRC had excess
    // registers, then we're done.
    if (ChosenSuperRegClass)
      return std::pair(ChosenSuperRegClass, SubRegRC);
  }

  return std::nullopt;
}

bool CodeGenRegisterClass::hasAnySuperRegClasses(
    const CodeGenSubRegIndex *SubIdx) const {
  return SuperRegClasses.contains(SubIdx);
}

bool CodeGenRegisterClass::hasSuperRegClass(
    const CodeGenSubRegIndex *SubIdx, const CodeGenRegisterClass *RC) const {
  auto FindI = SuperRegClasses.find(SubIdx);

  return FindI != SuperRegClasses.end() && FindI->second.contains(RC);
}

bool CodeGenRegisterClass::hasSuperRegClass(
    const CodeGenRegisterClass *RC) const {
  return any_of(SuperRegClasses,
                [RC](const auto &Entry) { return Entry.second.contains(RC); });
}

void CodeGenRegisterClass::getSuperRegClasses(const CodeGenSubRegIndex *SubIdx,
                                              BitVector &Out) const {
  auto FindI = SuperRegClasses.find(SubIdx);
  if (FindI == SuperRegClasses.end())
    return;
  for (CodeGenRegisterClass *RC : FindI->second)
    Out.set(RC->EnumValue);
}

// Populate a unique sorted list of units from a register set.
void CodeGenRegisterClass::buildRegUnitSet(
    const CodeGenRegBank &RegBank, std::vector<unsigned> &RegUnits) const {
  std::vector<unsigned> TmpUnits;
  for (const CodeGenRegister *Reg : Members) {
    for (unsigned UnitI : Reg->getRegUnits()) {
      const RegUnit &RU = RegBank.getRegUnit(UnitI);
      if (!RU.Artificial)
        TmpUnits.push_back(UnitI);
    }
  }
  llvm::sort(TmpUnits);
  std::unique_copy(TmpUnits.begin(), TmpUnits.end(),
                   std::back_inserter(RegUnits));
}

// Combine our super classes of the given sub-register index with all of their
// super classes in turn.
void CodeGenRegisterClass::extendSuperRegClasses(CodeGenSubRegIndex *SubIdx) {
  auto It = SuperRegClasses.find(SubIdx);
  if (It == SuperRegClasses.end())
    return;

  SmallVector<CodeGenRegisterClass *> MidRCs;
  llvm::append_range(MidRCs, It->second);

  for (CodeGenRegisterClass *MidRC : MidRCs) {
    for (auto &Pair : MidRC->SuperRegClasses) {
      CodeGenSubRegIndex *ComposedSubIdx = Pair.first->compose(SubIdx);
      if (!ComposedSubIdx)
        continue;

      SuperRegClasses[ComposedSubIdx].insert_range(Pair.second);
    }
  }
}

//===----------------------------------------------------------------------===//
//                           CodeGenRegisterCategory
//===----------------------------------------------------------------------===//

CodeGenRegisterCategory::CodeGenRegisterCategory(CodeGenRegBank &RegBank,
                                                 const Record *R)
    : TheDef(R), Name(R->getName().str()) {
  for (const Record *RegClass : R->getValueAsListOfDefs("Classes"))
    Classes.push_back(RegBank.getRegClass(RegClass));
}

//===----------------------------------------------------------------------===//
//                               CodeGenRegBank
//===----------------------------------------------------------------------===//

CodeGenRegBank::CodeGenRegBank(const RecordKeeper &Records,
                               const CodeGenHwModes &Modes,
                               const bool RegistersAreIntervals)
    : Records(Records), CGH(Modes),
      RegistersAreIntervals(RegistersAreIntervals) {
  // Configure register Sets to understand register classes and tuples.
  Sets.addFieldExpander("RegisterClass", "MemberList");
  Sets.addFieldExpander("CalleeSavedRegs", "SaveList");
  Sets.addExpander("RegisterTuples",
                   std::make_unique<TupleExpander>(SynthDefs));

  // Read in the user-defined (named) sub-register indices.
  // More indices will be synthesized later.
  for (const Record *SRI : Records.getAllDerivedDefinitions("SubRegIndex"))
    getSubRegIdx(SRI);
  // Build composite maps from ComposedOf fields.
  for (auto &Idx : SubRegIndices)
    Idx.updateComponents(*this);

  // Read in the register and register tuple definitions.
  const RecordKeeper &RC = Records;
  std::vector<const Record *> Regs = RC.getAllDerivedDefinitions("Register");
  if (!Regs.empty() && Regs[0]->isSubClassOf("X86Reg")) {
    // For X86, we need to sort Registers and RegisterTuples together to list
    // new registers and register tuples at a later position. So that we can
    // reduce unnecessary iterations on unsupported registers in LiveVariables.
    // TODO: Remove this logic when migrate from LiveVariables to LiveIntervals
    // completely.
    for (const Record *R : Records.getAllDerivedDefinitions("RegisterTuples")) {
      // Expand tuples and merge the vectors
      std::vector<const Record *> TupRegs = *Sets.expand(R);
      llvm::append_range(Regs, TupRegs);
    }

    llvm::sort(Regs, LessRecordRegister());
    // Assign the enumeration values.
    for (const Record *Reg : Regs)
      getReg(Reg);
  } else {
    llvm::sort(Regs, LessRecordRegister());
    // Assign the enumeration values.
    for (const Record *Reg : Regs)
      getReg(Reg);

    // Expand tuples and number the new registers.
    for (const Record *R : Records.getAllDerivedDefinitions("RegisterTuples")) {
      std::vector<const Record *> TupRegs = *Sets.expand(R);
      llvm::sort(TupRegs, LessRecordRegister());
      for (const Record *RC : TupRegs)
        getReg(RC);
    }
  }

  // Now all the registers are known. Build the object graph of explicit
  // register-register references.
  for (CodeGenRegister &Reg : Registers)
    Reg.buildObjectGraph(*this);

  // Compute register name map.
  for (CodeGenRegister &Reg : Registers)
    // FIXME: This could just be RegistersByName[name] = register, except that
    // causes some failures in MIPS - perhaps they have duplicate register name
    // entries? (or maybe there's a reason for it - I don't know much about this
    // code, just drive-by refactoring)
    RegistersByName.try_emplace(Reg.TheDef->getValueAsString("AsmName"), &Reg);

  // Precompute all sub-register maps.
  // This will create Composite entries for all inferred sub-register indices.
  for (CodeGenRegister &Reg : Registers)
    Reg.computeSubRegs(*this);

  // Compute transitive closure of subregister index ConcatenationOf vectors
  // and initialize ConcatIdx map.
  for (CodeGenSubRegIndex &SRI : SubRegIndices) {
    SRI.computeConcatTransitiveClosure();
    if (!SRI.ConcatenationOf.empty())
      ConcatIdx.try_emplace(
          SmallVector<CodeGenSubRegIndex *, 8>(SRI.ConcatenationOf.begin(),
                                               SRI.ConcatenationOf.end()),
          &SRI);
  }

  // Infer even more sub-registers by combining leading super-registers.
  for (CodeGenRegister &Reg : Registers)
    if (Reg.CoveredBySubRegs)
      Reg.computeSecondarySubRegs(*this);

  // After the sub-register graph is complete, compute the topologically
  // ordered SuperRegs list.
  for (CodeGenRegister &Reg : Registers)
    Reg.computeSuperRegs(*this);

  // For each pair of Reg:SR, if both are non-artificial, mark the
  // corresponding sub-register index as non-artificial.
  for (CodeGenRegister &Reg : Registers) {
    if (Reg.Artificial)
      continue;
    for (auto [SRI, SR] : Reg.getSubRegs()) {
      if (!SR->Artificial)
        SRI->Artificial = false;
    }
  }

  computeSubRegIndicesRPOT();

  // Native register units are associated with a leaf register. They've all been
  // discovered now.
  NumNativeRegUnits = RegUnits.size();

  // Read in register class definitions.
  ArrayRef<const Record *> RCs =
      Records.getAllDerivedDefinitions("RegisterClass");
  if (RCs.empty())
    PrintFatalError("No 'RegisterClass' subclasses defined!");

  // Allocate user-defined register classes.
  for (const Record *R : RCs) {
    RegClasses.emplace_back(*this, R);
    CodeGenRegisterClass &RC = RegClasses.back();
    RegClassNames.insert(RC.getName());
    if (!RC.Artificial)
      addToMaps(&RC);
  }

  // Infer missing classes to create a full algebra.
  computeInferredRegisterClasses();

  // Order register classes topologically and assign enum values.
  RegClasses.sort(TopoOrderRC);
  for (auto [Idx, RC] : enumerate(RegClasses))
    RC.EnumValue = Idx;
  CodeGenRegisterClass::computeSubClasses(*this);

  // Read in the register category definitions.
  for (const Record *R : Records.getAllDerivedDefinitions("RegisterCategory"))
    RegCategories.emplace_back(*this, R);

  // Now that register classes (and their sizes) are built, check that no
  // explicit SubRegIndex makes a sub-register overflow its register.
  for (const auto &Reg : Registers)
    Reg.checkSubRegIndexSizes(*this);
}

// Create a synthetic CodeGenSubRegIndex without a corresponding Record.
CodeGenSubRegIndex *CodeGenRegBank::createSubRegIndex(StringRef Name,
                                                      StringRef Namespace) {
  SubRegIndices.emplace_back(Name, Namespace, SubRegIndices.size() + 1);
  return &SubRegIndices.back();
}

CodeGenSubRegIndex *CodeGenRegBank::getSubRegIdx(const Record *Def) {
  CodeGenSubRegIndex *&Idx = Def2SubRegIdx[Def];
  if (Idx)
    return Idx;
  SubRegIndices.emplace_back(Def, SubRegIndices.size() + 1, getHwModes());
  Idx = &SubRegIndices.back();
  return Idx;
}

const CodeGenSubRegIndex *
CodeGenRegBank::findSubRegIdx(const Record *Def) const {
  return Def2SubRegIdx.at(Def);
}

CodeGenRegister *CodeGenRegBank::getReg(const Record *Def) {
  CodeGenRegister *&Reg = Def2Reg[Def];
  if (Reg)
    return Reg;
  Registers.emplace_back(Def, Registers.size() + 1);
  Reg = &Registers.back();
  return Reg;
}

void CodeGenRegBank::addToMaps(CodeGenRegisterClass *RC) {
  if (const Record *Def = RC->getDef())
    Def2RC.try_emplace(Def, RC);

  // Duplicate classes are rejected by insert().
  // That's OK, we only care about the properties handled by CGRC::Key.
  CodeGenRegisterClass::Key K(*RC, /*IgnoreArtificialMembers=*/true);
  Key2RC.try_emplace(K, RC);
}

// Create a synthetic sub-class if it is missing.
std::pair<CodeGenRegisterClass *, bool>
CodeGenRegBank::getOrCreateSubClass(const CodeGenRegisterClass *RC,
                                    const CodeGenRegister::Vec *Members,
                                    StringRef Name) {
  // Synthetic sub-class has the same size and alignment as RC.
  CodeGenRegisterClass::Key K(Members, RC->RSI,
                              /*IgnoreArtificialMembers=*/true);
  RCKeyMap::const_iterator FoundI = Key2RC.find(K);
  if (FoundI != Key2RC.end())
    return {FoundI->second, false};

  // Sub-class doesn't exist, create a new one.
  RegClasses.emplace_back(*this, Name, K);
  RegClassNames.insert(Name);
  addToMaps(&RegClasses.back());
  return {&RegClasses.back(), true};
}

CodeGenRegisterClass *CodeGenRegBank::getRegClass(const Record *Def,
                                                  ArrayRef<SMLoc> Loc) const {
  assert(Def->isSubClassOf("RegisterClassLike"));
  if (CodeGenRegisterClass *RC = Def2RC.lookup(Def))
    return RC;

  ArrayRef<SMLoc> DiagLoc = Loc.empty() ? Def->getLoc() : Loc;
  // TODO: Ideally we should update the API to allow resolving HwMode.
  if (Def->isSubClassOf("RegClassByHwMode"))
    PrintError(DiagLoc, "cannot resolve HwMode for " + Def->getName());
  else
    PrintError(DiagLoc, Def->getName() + " is not a known RegisterClass!");
  PrintFatalNote(Def->getLoc(), Def->getName() + " defined here");
}

CodeGenSubRegIndex *
CodeGenRegBank::getCompositeSubRegIndex(CodeGenSubRegIndex *A,
                                        CodeGenSubRegIndex *B) {
  // Look for an existing entry.
  CodeGenSubRegIndex *Comp = A->compose(B);
  if (Comp)
    return Comp;

  // None exists, synthesize one.
  std::string Name = A->getName() + "_then_" + B->getName();
  Comp = createSubRegIndex(Name, A->getNamespace());
  A->addComposite(B, Comp, getHwModes());
  return Comp;
}

CodeGenSubRegIndex *CodeGenRegBank::getConcatSubRegIndex(
    const SmallVector<CodeGenSubRegIndex *, 8> &Parts,
    const CodeGenHwModes &CGH) {
  assert(Parts.size() > 1 && "Need two parts to concatenate");
#ifndef NDEBUG
  for (CodeGenSubRegIndex *Idx : Parts) {
    assert(Idx->ConcatenationOf.empty() && "No transitive closure?");
  }
#endif

  // Look for an existing entry.
  CodeGenSubRegIndex *&Idx = ConcatIdx[Parts];
  if (Idx)
    return Idx;

  // None exists, synthesize one.
  std::string Name = Parts.front()->getName();
  const unsigned UnknownSize = (uint32_t)-1;

  for (const CodeGenSubRegIndex *Part : ArrayRef(Parts).drop_front()) {
    Name += '_';
    Name += Part->getName();
  }

  Idx = createSubRegIndex(Name, Parts.front()->getNamespace());
  Idx->ConcatenationOf.assign(Parts.begin(), Parts.end());

  unsigned NumModes = CGH.getNumModeIds();
  for (unsigned M = 0; M < NumModes; ++M) {
    const CodeGenSubRegIndex *FirstPart = Parts.front();

    // Determine whether all parts are contiguous.
    bool IsContinuous = true;
    const SubRegRange &FirstPartRange = FirstPart->Range.get(M);
    unsigned Size = FirstPartRange.Size;
    unsigned LastOffset = FirstPartRange.Offset;
    unsigned LastSize = FirstPartRange.Size;

    for (const CodeGenSubRegIndex *Part : ArrayRef(Parts).drop_front()) {
      const SubRegRange &PartRange = Part->Range.get(M);
      if (Size == UnknownSize || PartRange.Size == UnknownSize)
        Size = UnknownSize;
      else
        Size += PartRange.Size;
      if (LastSize == UnknownSize ||
          PartRange.Offset != (LastOffset + LastSize))
        IsContinuous = false;
      LastOffset = PartRange.Offset;
      LastSize = PartRange.Size;
    }
    unsigned Offset = IsContinuous ? FirstPartRange.Offset : -1;
    Idx->Range.get(M) = SubRegRange(Size, Offset);
  }

  return Idx;
}

void CodeGenRegBank::computeComposites() {
  using RegMap = std::map<const CodeGenRegister *, const CodeGenRegister *>;

  // Subreg -> { Reg->Reg }, where the right-hand side is the mapping from
  // register to (sub)register associated with the action of the left-hand
  // side subregister.
  std::map<const CodeGenSubRegIndex *, RegMap> SubRegAction;
  for (const CodeGenRegister &R : Registers) {
    CodeGenRegister::SubRegArrayRef SM = R.getSubRegs();
    for (auto [SRI, SubReg] : SM)
      SubRegAction[SRI].try_emplace(&R, SubReg);
  }

  // Calculate the composition of two subregisters as compositions of their
  // associated actions.
  auto compose = [&SubRegAction](const CodeGenSubRegIndex *Sub1,
                                 const CodeGenSubRegIndex *Sub2) {
    RegMap C;
    const RegMap &Img1 = SubRegAction.at(Sub1);
    const RegMap &Img2 = SubRegAction.at(Sub2);
    for (auto [R, SubReg] : Img1) {
      auto F = Img2.find(SubReg);
      if (F != Img2.end())
        C.try_emplace(R, F->second);
    }
    return C;
  };

  // Check if the two maps agree on the intersection of their domains.
  auto agree = [](const RegMap &Map1, const RegMap &Map2) {
    // Technically speaking, an empty map agrees with any other map, but
    // this could flag false positives. We're interested in non-vacuous
    // agreements.
    if (Map1.empty() || Map2.empty())
      return false;
    for (auto [K, V] : Map1) {
      auto F = Map2.find(K);
      if (F == Map2.end() || V != F->second)
        return false;
    }
    return true;
  };

  using CompositePair =
      std::pair<const CodeGenSubRegIndex *, const CodeGenSubRegIndex *>;
  SmallSet<CompositePair, 4> UserDefined;
  for (const CodeGenSubRegIndex &Idx : SubRegIndices)
    for (auto P : Idx.getComposites())
      UserDefined.insert({&Idx, P.first});

  // Keep track of TopoSigs visited. We only need to visit each TopoSig once,
  // and many registers will share TopoSigs on regular architectures.
  BitVector TopoSigs(getNumTopoSigs());

  for (const CodeGenRegister &Reg1 : Registers) {
    // Skip identical subreg structures already processed.
    if (TopoSigs.test(Reg1.getTopoSig()))
      continue;
    TopoSigs.set(Reg1.getTopoSig());

    CodeGenRegister::SubRegArrayRef SRM1 = Reg1.getSubRegs();
    for (auto [Idx1, Reg2] : SRM1) {
      // Ignore identity compositions.
      if (&Reg1 == Reg2)
        continue;
      CodeGenRegister::SubRegArrayRef SRM2 = Reg2->getSubRegs();
      // Try composing Idx1 with another SubRegIndex.
      for (auto I2 : SRM2) {
        CodeGenSubRegIndex *Idx2 = I2.first;
        CodeGenRegister *Reg3 = I2.second;
        // Ignore identity compositions.
        if (Reg2 == Reg3)
          continue;
        // OK Reg1:IdxPair == Reg3. Find the index with Reg:Idx == Reg3.
        CodeGenSubRegIndex *Idx3 = Reg1.getSubRegIndex(Reg3);
        assert(Idx3 && "Sub-register doesn't have an index");

        // Conflicting composition? Emit a warning but allow it.
        if (CodeGenSubRegIndex *Prev =
                Idx1->addComposite(Idx2, Idx3, getHwModes())) {
          // If the composition was not user-defined, always emit a warning.
          if (!UserDefined.contains({Idx1, Idx2}) ||
              agree(compose(Idx1, Idx2), SubRegAction.at(Idx3)))
            PrintWarning(Twine("SubRegIndex ") + Idx1->getQualifiedName() +
                         " and " + Idx2->getQualifiedName() +
                         " compose ambiguously as " + Prev->getQualifiedName() +
                         " or " + Idx3->getQualifiedName());
        }
      }
    }
  }
}

// Compute lane masks. This is similar to register units, but at the
// sub-register index level. Each bit in the lane mask is like a register unit
// class, and two lane masks will have a bit in common if two sub-register
// indices overlap in some register.
//
// Conservatively share a lane mask bit if two sub-register indices overlap in
// some registers, but not in others. That shouldn't happen a lot.
void CodeGenRegBank::computeSubRegLaneMasks() {
  // First assign individual bits to all the leaf indices.
  unsigned Bit = 0;
  // Determine mask of lanes that cover their registers.
  CoveringLanes = LaneBitmask::getAll();
  for (CodeGenSubRegIndex &Idx : SubRegIndices) {
    if (Idx.getComposites().empty()) {
      if (Bit >= LaneBitmask::BitWidth) {
        PrintFatalError(
            Twine("Ran out of lanemask bits to represent subregister ") +
            Idx.getName());
      }
      Idx.LaneMask = LaneBitmask::getLane(Bit);
      ++Bit;
    } else {
      Idx.LaneMask = LaneBitmask::getNone();
    }
  }

  // Compute transformation sequences for composeSubRegIndexLaneMask. The idea
  // here is that for each possible target subregister we look at the leafs
  // in the subregister graph that compose for this target and create
  // transformation sequences for the lanemasks. Each step in the sequence
  // consists of a bitmask and a bitrotate operation. As the rotation amounts
  // are usually the same for many subregisters we can easily combine the steps
  // by combining the masks.
  for (const CodeGenSubRegIndex &Idx : SubRegIndices) {
    const CodeGenSubRegIndex::CompMap &Composites = Idx.getComposites();
    auto &LaneTransforms = Idx.CompositionLaneMaskTransform;

    if (Composites.empty()) {
      // Moving from a class with no subregisters we just had a single lane:
      // The subregister must be a leaf subregister and only occupies 1 bit.
      // Move the bit from the class without subregisters into that position.
      unsigned DstBit = Idx.LaneMask.getHighestLane();
      assert(Idx.LaneMask == LaneBitmask::getLane(DstBit) &&
             "Must be a leaf subregister");
      MaskRolPair MaskRol = {LaneBitmask::getLane(0), (uint8_t)DstBit};
      LaneTransforms.push_back(MaskRol);
    } else {
      // Go through all leaf subregisters and find the ones that compose with
      // Idx. These make out all possible valid bits in the lane mask we want to
      // transform. Looking only at the leafs ensure that only a single bit in
      // the mask is set.
      for (CodeGenSubRegIndex &Idx2 : SubRegIndices) {
        // Skip non-leaf subregisters.
        if (!Idx2.getComposites().empty())
          continue;
        LaneBitmask SrcMask = Idx2.LaneMask;

        // Get the composed subregister if there is any.
        auto C = Composites.find(&Idx2);
        if (C == Composites.end())
          continue;
        const CodeGenSubRegIndex *Composite = C->second;
        // The Composed subreg should be a leaf subreg too
        assert(Composite->getComposites().empty());

        // Create Mask+Rotate operation and merge with existing ops if possible.
        unsigned SrcBit = SrcMask.getHighestLane();
        unsigned DstBit = Composite->LaneMask.getHighestLane();
        int Shift = DstBit - SrcBit;
        uint8_t RotateLeft =
            Shift >= 0 ? (uint8_t)Shift : LaneBitmask::BitWidth + Shift;
        for (MaskRolPair &I : LaneTransforms) {
          if (I.RotateLeft == RotateLeft) {
            I.Mask |= SrcMask;
            SrcMask = LaneBitmask::getNone();
          }
        }
        if (SrcMask.any()) {
          MaskRolPair MaskRol = {SrcMask, RotateLeft};
          LaneTransforms.push_back(MaskRol);
        }
      }
    }

    // Optimize if the transformation consists of one step only: Set mask to
    // 0xffffffff (including some irrelevant invalid bits) so that it should
    // merge with more entries later while compressing the table.
    if (LaneTransforms.size() == 1)
      LaneTransforms[0].Mask = LaneBitmask::getAll();

    // Further compression optimization: For invalid compositions resulting
    // in a sequence with 0 entries we can just pick any other. Choose
    // Mask 0xffffffff with Rotation 0.
    if (LaneTransforms.size() == 0) {
      MaskRolPair P = {LaneBitmask::getAll(), 0};
      LaneTransforms.push_back(P);
    }
  }

  // FIXME: What if ad-hoc aliasing introduces overlaps that aren't represented
  // by the sub-register graph? This doesn't occur in any known targets.

  // Inherit lanes from composites.
  for (const CodeGenSubRegIndex &Idx : SubRegIndices) {
    LaneBitmask Mask = Idx.computeLaneMask();
    // If some super-registers without CoveredBySubRegs use this index, we can
    // no longer assume that the lanes are covering their registers.
    if (!Idx.AllSuperRegsCovered)
      CoveringLanes &= ~Mask;
  }

  // Compute lane mask combinations for register classes.
  for (auto &RegClass : RegClasses) {
    LaneBitmask LaneMask;
    for (const CodeGenSubRegIndex &SubRegIndex : SubRegIndices) {
      if (RegClass.getSubClassWithSubReg(&SubRegIndex) == nullptr)
        continue;
      LaneMask |= SubRegIndex.LaneMask;
    }

    // For classes without any subregisters set LaneMask to 1 instead of 0.
    // This makes it easier for client code to handle classes uniformly.
    if (LaneMask.none())
      LaneMask = LaneBitmask::getLane(0);

    RegClass.LaneMask = LaneMask;
  }
}

namespace {

// A directed graph on sub-register indices with a virtual source node that
// has an arc to all other nodes, and an arc from A to B if sub-register index
// B can be obtained by composing A with some other sub-register index.
struct SubRegIndexCompositionGraph {
  std::deque<CodeGenSubRegIndex> &SubRegIndices;
  CodeGenSubRegIndex::CompMap EntryNode;

  SubRegIndexCompositionGraph(std::deque<CodeGenSubRegIndex> &SubRegIndices)
      : SubRegIndices(SubRegIndices) {
    for (CodeGenSubRegIndex &Idx : SubRegIndices) {
      EntryNode.try_emplace(&Idx, &Idx);
    }
  }
};

} // namespace

template <> struct llvm::GraphTraits<SubRegIndexCompositionGraph> {
  using NodeRef =
      PointerUnion<CodeGenSubRegIndex *, const CodeGenSubRegIndex::CompMap *>;

  // Using a reverse iterator causes sub-register indices to appear in their
  // more natural order in RPOT.
  using CompMapIt = CodeGenSubRegIndex::CompMap::const_reverse_iterator;
  struct ChildIteratorType
      : public iterator_adaptor_base<
            ChildIteratorType, CompMapIt,
            std::iterator_traits<CompMapIt>::iterator_category, NodeRef> {
    ChildIteratorType(CompMapIt I)
        : ChildIteratorType::iterator_adaptor_base(I) {}

    NodeRef operator*() const { return wrapped()->second; }
  };

  static NodeRef getEntryNode(const SubRegIndexCompositionGraph &G) {
    return &G.EntryNode;
  }

  static const CodeGenSubRegIndex::CompMap *children(NodeRef N) {
    if (auto *Idx = dyn_cast<CodeGenSubRegIndex *>(N))
      return &Idx->getComposites();
    return cast<const CodeGenSubRegIndex::CompMap *>(N);
  }

  static ChildIteratorType child_begin(NodeRef N) {
    return ChildIteratorType(children(N)->rbegin());
  }
  static ChildIteratorType child_end(NodeRef N) {
    return ChildIteratorType(children(N)->rend());
  }

  static auto nodes_begin(SubRegIndexCompositionGraph *G) {
    return G->SubRegIndices.begin();
  }
  static auto nodes_end(SubRegIndexCompositionGraph *G) {
    return G->SubRegIndices.end();
  }

  static unsigned size(SubRegIndexCompositionGraph *G) {
    return G->SubRegIndices.size();
  }
};

void CodeGenRegBank::computeSubRegIndicesRPOT() {
  SubRegIndexCompositionGraph G(SubRegIndices);
  ReversePostOrderTraversal<SubRegIndexCompositionGraph> RPOT(G);
  for (const auto N : RPOT) {
    if (auto *Idx = dyn_cast<CodeGenSubRegIndex *>(N))
      SubRegIndicesRPOT.push_back(Idx);
  }
}

namespace {

// UberRegSet is a helper class for computeRegUnitWeights. Each UberRegSet is
// the transitive closure of the union of overlapping register
// classes. Together, the UberRegSets form a partition of the registers. If we
// consider overlapping register classes to be connected, then each UberRegSet
// is a set of connected components.
//
// An UberRegSet will likely be a horizontal slice of register names of
// the same width. Nontrivial subregisters should then be in a separate
// UberRegSet. But this property isn't required for valid computation of
// register unit weights.
//
// A Weight field caches the max per-register unit weight in each UberRegSet.
//
// A set of SingularDeterminants flags single units of some register in this set
// for which the unit weight equals the set weight. These units should not have
// their weight increased.
struct UberRegSet {
  CodeGenRegister::Vec Regs;
  unsigned Weight = 0;
  CodeGenRegister::RegUnitList SingularDeterminants;

  UberRegSet() = default;
};

} // end anonymous namespace

// Partition registers into UberRegSets, where each set is the transitive
// closure of the union of overlapping register classes.
//
// UberRegSets[0] is a special non-allocatable set.
static void computeUberSets(std::vector<UberRegSet> &UberSets,
                            std::vector<UberRegSet *> &RegSets,
                            CodeGenRegBank &RegBank) {
  const auto &Registers = RegBank.getRegisters();

  // The Register EnumValue is one greater than its index into Registers.
  assert(Registers.size() == Registers.back().EnumValue &&
         "register enum value mismatch");

  // For simplicitly make the SetID the same as EnumValue.
  IntEqClasses UberSetIDs(Registers.size() + 1);
  BitVector AllocatableRegs(Registers.size() + 1);
  for (CodeGenRegisterClass &RegClass : RegBank.getRegClasses()) {
    if (!RegClass.Allocatable)
      continue;

    // Ignore artificial registers. They may be members of register
    // classes that together include registers and their subregisters,
    // in which case it is impossible to normalize the weights of
    // their register units.
    CodeGenRegister::Vec Regs;
    for (const CodeGenRegister *Reg : RegClass.getMembers()) {
      if (!Reg->Artificial)
        Regs.push_back(Reg);
    }

    if (Regs.empty())
      continue;

    unsigned USetID = UberSetIDs.findLeader((*Regs.begin())->EnumValue);
    assert(USetID && "register number 0 is invalid");

    AllocatableRegs.set((*Regs.begin())->EnumValue);
    for (const CodeGenRegister *CGR : llvm::drop_begin(Regs)) {
      AllocatableRegs.set(CGR->EnumValue);
      UberSetIDs.join(USetID, CGR->EnumValue);
    }
  }
  // Combine non-allocatable regs.
  for (const CodeGenRegister &Reg : Registers) {
    unsigned RegNum = Reg.EnumValue;
    if (AllocatableRegs.test(RegNum))
      continue;

    UberSetIDs.join(0, RegNum);
  }
  UberSetIDs.compress();

  // Make the first UberSet a special unallocatable set.
  unsigned ZeroID = UberSetIDs[0];

  // Insert Registers into the UberSets formed by union-find.
  // Do not resize after this.
  UberSets.resize(UberSetIDs.getNumClasses());
  for (auto [Idx, Reg] : enumerate(Registers)) {
    unsigned USetID = UberSetIDs[Reg.EnumValue];
    if (!USetID)
      USetID = ZeroID;
    else if (USetID == ZeroID)
      USetID = 0;

    UberRegSet *USet = &UberSets[USetID];
    USet->Regs.push_back(&Reg);
    RegSets[Idx] = USet;
  }
}

// Recompute a single UberSet's weight after a change to register-unit weights.
static void computeUberWeight(UberRegSet &S, CodeGenRegBank &RegBank) {
  // Initialize all unit weights in this set, and remember the max units/reg.
  unsigned MaxWeight = 0;
  for (const CodeGenRegister *R : S.Regs) {
    unsigned Weight = 0;
    for (unsigned U : R->getRegUnits()) {
      if (!RegBank.getRegUnit(U).Artificial) {
        unsigned UWeight = RegBank.getRegUnit(U).Weight;
        if (!UWeight) {
          UWeight = 1;
          RegBank.increaseRegUnitWeight(U, UWeight);
        }
        Weight += UWeight;
      }
    }
    MaxWeight = std::max(MaxWeight, Weight);
  }
  if (S.Weight != MaxWeight) {
    LLVM_DEBUG({
      dbgs() << "UberSet Weight " << MaxWeight;
      for (const CodeGenRegister *R : S.Regs)
        dbgs() << " " << R->getName();
      dbgs() << '\n';
    });
    // Update the set weight.
    S.Weight = MaxWeight;
  }

  // Find singular determinants.
  for (const CodeGenRegister *R : S.Regs)
    if (R->getRegUnits().count() == 1 && R->getWeight(RegBank) == S.Weight)
      S.SingularDeterminants |= R->getRegUnits();
}

// Recompute each UberSet weight after changing unit weights.
static void computeUberWeights(MutableArrayRef<UberRegSet> UberSets,
                               CodeGenRegBank &RegBank) {
  // Skip the first unallocatable set.
  for (UberRegSet &S : UberSets.drop_front())
    computeUberWeight(S, RegBank);
}

// normalizeWeight is a computeRegUnitWeights helper that adjusts the weight of
// a register and its subregisters so that they have the same weight as their
// UberSet. Self-recursion processes the subregister tree in postorder so
// subregisters are normalized first.
//
// Side effects:
// - creates new adopted register units
// - causes superregisters to inherit adopted units
// - increases the weight of "singular" units
// - induces recomputation of UberWeights.
static bool normalizeWeight(CodeGenRegister *Reg,
                            std::vector<UberRegSet> &UberSets,
                            std::vector<UberRegSet *> &RegSets,
                            BitVector &NormalRegs,
                            CodeGenRegister::RegUnitList &NormalUnits,
                            CodeGenRegBank &RegBank) {
  NormalRegs.resize(std::max(Reg->EnumValue + 1, NormalRegs.size()));
  if (NormalRegs.test(Reg->EnumValue))
    return false;
  NormalRegs.set(Reg->EnumValue);

  bool Changed = false;
  CodeGenRegister::SubRegArrayRef SRM = Reg->getSubRegs();
  for (auto SRI : SRM) {
    if (SRI.second == Reg)
      continue; // self-cycles happen

    Changed |= normalizeWeight(SRI.second, UberSets, RegSets, NormalRegs,
                               NormalUnits, RegBank);
  }
  // Postorder register normalization.

  // Inherit register units newly adopted by subregisters. Inheriting units
  // only changes this register's weight, so just its own UberSet can change;
  // recompute only that set rather than rescanning every UberSet.
  if (Reg->inheritRegUnits(RegBank))
    computeUberWeight(*RegSets[RegBank.getRegIndex(Reg)], RegBank);

  // Check if this register is too skinny for its UberRegSet.
  UberRegSet *UberSet = RegSets[RegBank.getRegIndex(Reg)];

  unsigned RegWeight = Reg->getWeight(RegBank);
  if (UberSet->Weight > RegWeight) {
    // A register unit's weight can be adjusted only if it is the singular unit
    // for this register, has not been used to normalize a subregister's set,
    // and has not already been used to singularly determine this UberRegSet.
    unsigned AdjustUnit = *Reg->getRegUnits().begin();
    if (Reg->getRegUnits().count() != 1 || NormalUnits.test(AdjustUnit) ||
        UberSet->SingularDeterminants.test(AdjustUnit)) {
      // We don't have an adjustable unit, so adopt a new one.
      AdjustUnit = RegBank.newRegUnit(UberSet->Weight - RegWeight);
      Reg->adoptRegUnit(AdjustUnit);
      // Adopting a unit does not immediately require recomputing set weights.
    } else {
      // Adjust the existing single unit.
      if (!RegBank.getRegUnit(AdjustUnit).Artificial)
        RegBank.increaseRegUnitWeight(AdjustUnit, UberSet->Weight - RegWeight);
      // The unit may be shared among sets and registers within this set.
      computeUberWeights(UberSets, RegBank);
    }
    Changed = true;
  }

  // Mark these units normalized so superregisters can't change their weights.
  NormalUnits |= Reg->getRegUnits();

  return Changed;
}

// Compute a weight for each register unit created during getSubRegs.
//
// The goal is that two registers in the same class will have the same weight,
// where each register's weight is defined as sum of its units' weights.
void CodeGenRegBank::computeRegUnitWeights() {
  std::vector<UberRegSet> UberSets;
  std::vector<UberRegSet *> RegSets(Registers.size());
  computeUberSets(UberSets, RegSets, *this);
  // UberSets and RegSets are now immutable.

  computeUberWeights(UberSets, *this);

  // Iterate over each Register, normalizing the unit weights until reaching
  // a fix point.
  unsigned NumIters = 0;
  for (bool Changed = true; Changed; ++NumIters) {
    assert(NumIters <= NumNativeRegUnits && "Runaway register unit weights");
    (void)NumIters;
    Changed = false;
    for (CodeGenRegister &Reg : Registers) {
      CodeGenRegister::RegUnitList NormalUnits;
      BitVector NormalRegs;
      Changed |= normalizeWeight(&Reg, UberSets, RegSets, NormalRegs,
                                 NormalUnits, *this);
    }
  }
}

// isContiguous is a enforceRegUnitIntervals helper that returns true if all
// units in Units form a contiguous interval.
static bool isContiguous(const CodeGenRegister::RegUnitList &Units) {
  unsigned LastUnit = Units.find_first();
  for (auto ThisUnit : llvm::make_range(++Units.begin(), Units.end())) {
    if (ThisUnit != LastUnit + 1)
      return false;
    LastUnit = ThisUnit;
  }
  return true;
}

// Enforce that all registers are intervals of regunits if the target
// requests this property. This will renumber regunits to ensure the
// interval property holds, or error out if it cannot be satisfied.
void CodeGenRegBank::enforceRegUnitIntervals() {
  if (!RegistersAreIntervals)
    return;

  LLVM_DEBUG(dbgs() << "Enforcing regunit intervals for target\n");
  std::vector<unsigned> RegUnitRenumbering(RegUnits.size(), ~0u);

  // RegUnits that have been renumbered from X -> Y. Y is what is marked so that
  // it doesn't create a chain of swaps.
  SparseBitVector<> DontRenumberUnits;

  auto GetRenumberedUnit = [&](unsigned RegUnit) -> unsigned {
    if (unsigned RenumberedUnit = RegUnitRenumbering[RegUnit];
        RenumberedUnit != ~0u)
      return RenumberedUnit;
    return RegUnit;
  };

  // Process registers in definition order
  for (CodeGenRegister &Reg : Registers) {
    LLVM_DEBUG(dbgs() << "Processing register " << Reg.getName() << "\n");
    const auto &Units = Reg.getNativeRegUnits();
    if (Units.empty())
      continue;
    SparseBitVector<> RenumberedUnits;
    // First renumber all the units for this register according to previous
    // renumbering.
    LLVM_DEBUG(dbgs() << "  Original (Renumbered) units:");
    for (unsigned U : Units) {
      LLVM_DEBUG(dbgs() << " " << U << "(" << GetRenumberedUnit(U) << "), ");
      RenumberedUnits.set(GetRenumberedUnit(U));
    }
    LLVM_DEBUG(dbgs() << "\n");

    unsigned LastUnit = RenumberedUnits.find_first();
    for (auto ThisUnit :
         llvm::make_range(++RenumberedUnits.begin(), RenumberedUnits.end())) {
      if (ThisUnit != LastUnit + 1) {
        if (DontRenumberUnits.test(LastUnit + 1)) {
          PrintFatalError(
              "cannot enforce regunit intervals for register " + Reg.getName() +
              ": unit " + Twine(LastUnit + 1) +
              " (root: " + RegUnits[LastUnit + 1].Roots[0]->getName() +
              ") has already been renumbered and cannot be swapped");
        }
        LLVM_DEBUG(dbgs() << "  Renumbering unit " << ThisUnit << " to "
                          << (LastUnit + 1) << "\n");
        RegUnitRenumbering[LastUnit + 1] = ThisUnit;
        RegUnitRenumbering[ThisUnit] = LastUnit + 1;
        DontRenumberUnits.set(LastUnit + 1);
        ThisUnit = LastUnit + 1;
      }
      LastUnit = ThisUnit;
    }
  }

  // Apply the renumbering to all registers
  for (CodeGenRegister &Reg : Registers) {
    CodeGenRegister::RegUnitList NewRegUnits;
    for (unsigned OldUnit : Reg.getRegUnits())
      NewRegUnits.set(GetRenumberedUnit(OldUnit));
    Reg.setNewRegUnits(NewRegUnits);

    CodeGenRegister::RegUnitList NewNativeUnits;
    for (unsigned OldUnit : Reg.getNativeRegUnits())
      NewNativeUnits.set(GetRenumberedUnit(OldUnit));
    if (!isContiguous(NewNativeUnits)) {
      PrintFatalError("cannot enforce regunit intervals, final "
                      "renumbering did not produce contiguous units "
                      "for register " +
                      Reg.getName() + "\n");
    }
    Reg.NativeRegUnits = NewNativeUnits;
  }
}

// Find a set in UniqueSets with the same elements as Set.
// Return an iterator into UniqueSets.
static std::vector<RegUnitSet>::const_iterator
findRegUnitSet(const std::vector<RegUnitSet> &UniqueSets,
               const RegUnitSet &Set) {
  return llvm::find_if(
      UniqueSets, [&Set](const RegUnitSet &I) { return I.Units == Set.Units; });
}

// Return true if the RUSubSet is a subset of RUSuperSet.
static bool isRegUnitSubSet(const std::vector<unsigned> &RUSubSet,
                            const std::vector<unsigned> &RUSuperSet) {
  return llvm::includes(RUSuperSet, RUSubSet);
}

/// Iteratively prune unit sets. Prune subsets that are close to the superset,
/// but with one or two registers removed. We occasionally have registers like
/// APSR and PC thrown in with the general registers. We also see many
/// special-purpose register subsets, such as tail-call and Thumb
/// encodings. Generating all possible overlapping sets is combinatorial and
/// overkill for modeling pressure. Ideally we could fix this statically in
/// tablegen by (1) having the target define register classes that only include
/// the allocatable registers and marking other classes as non-allocatable and
/// (2) having a way to mark special purpose classes as "don't-care" classes for
/// the purpose of pressure.  However, we make an attempt to handle targets that
/// are not nicely defined by merging nearly identical register unit sets
/// statically. This generates smaller tables. Then, dynamically, we adjust the
/// set limit by filtering the reserved registers.
///
/// Merge sets only if the units have the same weight. For example, on ARM,
/// Q-tuples with ssub index 0 include all S regs but also include D16+. We
/// should not expand the S set to include D regs.
void CodeGenRegBank::pruneUnitSets() {
  assert(RegClassUnitSets.empty() && "this invalidates RegClassUnitSets");

  // Form an equivalence class of UnitSets with no significant difference.
  std::vector<unsigned> SuperSetIDs;
  unsigned EndIdx = RegUnitSets.size();
  for (auto [SubIdx, SubSet] : enumerate(RegUnitSets)) {
    unsigned SuperIdx = 0;
    for (; SuperIdx != EndIdx; ++SuperIdx) {
      if (SuperIdx == SubIdx)
        continue;

      unsigned UnitWeight = RegUnits[SubSet.Units[0]].Weight;
      const RegUnitSet &SuperSet = RegUnitSets[SuperIdx];
      if (isRegUnitSubSet(SubSet.Units, SuperSet.Units) &&
          (SubSet.Units.size() + 3 > SuperSet.Units.size()) &&
          UnitWeight == RegUnits[SuperSet.Units[0]].Weight &&
          UnitWeight == RegUnits[SuperSet.Units.back()].Weight) {
        LLVM_DEBUG({
          dbgs() << "UnitSet " << SubIdx << " subsumed by " << SuperIdx << '\n';
        });
        // We can pick any of the set names for the merged set. Go for the
        // shortest one to avoid picking the name of one of the classes that are
        // artificially created by tablegen. So "FPR128_lo" instead of
        // "QQQQ_with_qsub3_in_FPR128_lo".
        if (RegUnitSets[SubIdx].Name.size() < RegUnitSets[SuperIdx].Name.size())
          RegUnitSets[SuperIdx].Name = RegUnitSets[SubIdx].Name;
        break;
      }
    }
    if (SuperIdx == EndIdx)
      SuperSetIDs.push_back(SubIdx);
  }
  // Populate PrunedUnitSets with each equivalence class's superset.
  std::vector<RegUnitSet> PrunedUnitSets;
  PrunedUnitSets.reserve(SuperSetIDs.size());
  for (unsigned SuperIdx : SuperSetIDs) {
    PrunedUnitSets.emplace_back(RegUnitSets[SuperIdx].Name);
    PrunedUnitSets.back().Units = std::move(RegUnitSets[SuperIdx].Units);
  }
  RegUnitSets = std::move(PrunedUnitSets);
}

// Create a RegUnitSet for each RegClass that contains all units in the class
// including adopted units that are necessary to model register pressure. Then
// iteratively compute RegUnitSets such that the union of any two overlapping
// RegUnitSets is represented.
//
// RegisterInfoEmitter will map each RegClass to its RegUnitClass and any
// RegUnitSet that is a superset of that RegUnitClass.
void CodeGenRegBank::computeRegUnitSets() {
  assert(RegUnitSets.empty() && "dirty RegUnitSets");

#ifndef NDEBUG
  // Helper to print register unit sets.
  auto PrintRegUnitSets = [this]() {
    for (auto [USIdx, US] : enumerate(RegUnitSets)) {
      dbgs() << "UnitSet " << USIdx << " " << US.Name << ":";
      printRegUnitNames(US.Units);
    }
  };
#endif // NDEBUG

  // Compute a unique RegUnitSet for each RegClass.
  auto &RegClasses = getRegClasses();
  for (CodeGenRegisterClass &RC : RegClasses) {
    if (!RC.Allocatable || RC.Artificial || !RC.GeneratePressureSet)
      continue;

    // Compute a sorted list of units in this class.
    RegUnitSet RUSet(RC.getName());
    RC.buildRegUnitSet(*this, RUSet.Units);

    // Find an existing RegUnitSet.
    if (findRegUnitSet(RegUnitSets, RUSet) == RegUnitSets.end())
      RegUnitSets.push_back(std::move(RUSet));
  }

  if (RegUnitSets.empty())
    PrintFatalError("RegUnitSets cannot be empty!");

  LLVM_DEBUG({
    dbgs() << "\nBefore pruning:\n";
    PrintRegUnitSets();
  });

  // Iteratively prune unit sets.
  pruneUnitSets();

  LLVM_DEBUG({
    dbgs() << "\nBefore union:\n";
    PrintRegUnitSets();
    dbgs() << "\nUnion sets:\n";
  });

  // Iterate over all unit sets, including new ones added by this loop.
  // FIXME: Since `EndIdx` is computed just once during loop initialization,
  // does this really iterate over new unit sets added by this loop?
  unsigned NumRegUnitSubSets = RegUnitSets.size();
  for (unsigned Idx = 0, EndIdx = RegUnitSets.size(); Idx != EndIdx; ++Idx) {
    // In theory, this is combinatorial. In practice, it needs to be bounded
    // by a small number of sets for regpressure to be efficient.
    // If the assert is hit, we need to implement pruning.
    assert(Idx < (2 * NumRegUnitSubSets) && "runaway unit set inference");

    // Compare new sets with all original classes.
    for (unsigned SearchIdx = (Idx >= NumRegUnitSubSets) ? 0 : Idx + 1;
         SearchIdx != EndIdx; ++SearchIdx) {
      std::vector<unsigned> Intersection;
      std::set_intersection(
          RegUnitSets[Idx].Units.begin(), RegUnitSets[Idx].Units.end(),
          RegUnitSets[SearchIdx].Units.begin(),
          RegUnitSets[SearchIdx].Units.end(), std::back_inserter(Intersection));
      if (Intersection.empty())
        continue;

      RegUnitSet RUSet(RegUnitSets[Idx].Name + "_with_" +
                       RegUnitSets[SearchIdx].Name);
      std::set_union(RegUnitSets[Idx].Units.begin(),
                     RegUnitSets[Idx].Units.end(),
                     RegUnitSets[SearchIdx].Units.begin(),
                     RegUnitSets[SearchIdx].Units.end(),
                     std::inserter(RUSet.Units, RUSet.Units.begin()));

      // Find an existing RegUnitSet, or add the union to the unique sets.
      if (findRegUnitSet(RegUnitSets, RUSet) == RegUnitSets.end()) {
        LLVM_DEBUG({
          dbgs() << "UnitSet " << RegUnitSets.size() << " " << RUSet.Name
                 << ":";
          printRegUnitNames(RUSet.Units);
        });
        RegUnitSets.push_back(std::move(RUSet));
      }
    }
  }

  // Iteratively prune unit sets after inferring supersets.
  pruneUnitSets();

  LLVM_DEBUG({
    dbgs() << '\n';
    PrintRegUnitSets();
  });

  // For each register class, list the UnitSets that are supersets.
  RegClassUnitSets.resize(RegClasses.size());
  for (CodeGenRegisterClass &RC : RegClasses) {
    if (!RC.Allocatable)
      continue;

    // Recompute the sorted list of units in this class.
    std::vector<unsigned> RCRegUnits;
    RC.buildRegUnitSet(*this, RCRegUnits);

    // Don't increase pressure for unallocatable regclasses.
    if (RCRegUnits.empty())
      continue;

    LLVM_DEBUG({
      dbgs() << "RC " << RC.getName() << " Units:\n";
      printRegUnitNames(RCRegUnits);
      dbgs() << "UnitSetIDs:";
    });

    // Find all supersets.
    for (const auto &[USIdx, Set] : enumerate(RegUnitSets)) {
      if (isRegUnitSubSet(RCRegUnits, Set.Units)) {
        LLVM_DEBUG(dbgs() << " " << USIdx);
        RegClassUnitSets[RC.EnumValue].push_back(USIdx);
      }
    }
    LLVM_DEBUG(dbgs() << '\n');
    assert(
        (!RegClassUnitSets[RC.EnumValue].empty() || !RC.GeneratePressureSet) &&
        "missing unit set for regclass");
  }

  // For each register unit, ensure that we have the list of UnitSets that
  // contain the unit. Normally, this matches an existing list of UnitSets for a
  // register class. If not, we create a new entry in RegClassUnitSets as a
  // "fake" register class.
  for (unsigned UnitIdx = 0, UnitEnd = NumNativeRegUnits; UnitIdx < UnitEnd;
       ++UnitIdx) {
    std::vector<unsigned> RUSets;
    for (auto [Idx, S] : enumerate(RegUnitSets))
      if (is_contained(S.Units, UnitIdx))
        RUSets.push_back(Idx);

    unsigned RCUnitSetsIdx = 0;
    for (unsigned e = RegClassUnitSets.size(); RCUnitSetsIdx != e;
         ++RCUnitSetsIdx) {
      if (RegClassUnitSets[RCUnitSetsIdx] == RUSets) {
        break;
      }
    }
    RegUnits[UnitIdx].RegClassUnitSetsIdx = RCUnitSetsIdx;
    if (RCUnitSetsIdx == RegClassUnitSets.size()) {
      // Create a new list of UnitSets as a "fake" register class.
      RegClassUnitSets.push_back(std::move(RUSets));
    }
  }
}

void CodeGenRegBank::computeRegUnitLaneMasks() {
  for (CodeGenRegister &Register : Registers) {
    // Create an initial lane mask for all register units.
    const auto &RegUnits = Register.getRegUnits();
    CodeGenRegister::RegUnitLaneMaskList RegUnitLaneMasks(
        RegUnits.count(), LaneBitmask::getAll());
    // Iterate through SubRegisters.
    using SubRegArrayRef = CodeGenRegister::SubRegArrayRef;
    SubRegArrayRef SubRegs = Register.getSubRegs();

    auto UnitMaskIdx = [&](unsigned SUI) {
      unsigned U = 0;
      for (unsigned RU : RegUnits) {
        if (SUI == RU)
          return U;
        ++U;
      }
      llvm_unreachable("unit is not part of the register");
    };

    for (auto [SubRegIndex, SubReg] : SubRegs) {
      // Ignore non-leaf subregisters, their lane masks are fully covered by
      // the leaf subregisters, unless the subregister is not CoveredBySubRegs -
      // this is dealt with by the loop below.
      if (!SubReg->getSubRegs().empty())
        continue;
      LaneBitmask LaneMask = SubRegIndex->LaneMask;
      // Distribute LaneMask to Register Units touched.
      for (unsigned SUI : SubReg->getRegUnits())
        RegUnitLaneMasks[UnitMaskIdx(SUI)] &= LaneMask;
    }

    // A sub-register that is not CoveredBySubRegs may be missing lanes that
    // none of its leaves account for. If left unclaimed, those lanes would
    // not appear in any register unit's mask, making them invisible to
    // interference and liveness queries. Backfill the missing lanes onto the
    // sub-register's own native units.
    for (auto [SubRegIndex, SubReg] : SubRegs) {
      if (SubReg->CoveredBySubRegs || SubReg->getSubRegs().empty())
        continue;
      LaneBitmask Unclaimed = SubRegIndex->LaneMask;
      for (unsigned SUI : SubReg->getNativeRegUnits())
        Unclaimed &= ~RegUnitLaneMasks[UnitMaskIdx(SUI)];
      for (unsigned SUI : SubReg->getNativeRegUnits())
        RegUnitLaneMasks[UnitMaskIdx(SUI)] |= Unclaimed;
    }

    Register.setRegUnitLaneMasks(RegUnitLaneMasks);
  }
}

void CodeGenRegBank::computeDerivedInfo() {
  computeComposites();
  computeSubRegLaneMasks();

  // Compute a weight for each register unit created during getSubRegs.
  // This may create adopted register units (with unit # >= NumNativeRegUnits).
  Records.getTimer().startTimer("Compute reg unit weights");
  computeRegUnitWeights();
  Records.getTimer().stopTimer();

  // Enforce regunit intervals if requested by the target.
  Records.getTimer().startTimer("Enforce regunit intervals");
  enforceRegUnitIntervals();
  Records.getTimer().stopTimer();

  // Compute a unique set of RegUnitSets. One for each RegClass and inferred
  // supersets for the union of overlapping sets.
  computeRegUnitSets();

  computeRegUnitLaneMasks();

  // Compute register class HasDisjunctSubRegs/CoveredBySubRegs flag.
  for (CodeGenRegisterClass &RC : RegClasses) {
    RC.HasDisjunctSubRegs = false;
    RC.CoveredBySubRegs = true;
    for (const CodeGenRegister *Reg : RC.getMembers()) {
      RC.HasDisjunctSubRegs |= Reg->HasDisjunctSubRegs;
      RC.CoveredBySubRegs &= Reg->CoveredBySubRegs;
    }
  }

  // Get the weight of each set.
  for (auto [Idx, US] : enumerate(RegUnitSets))
    RegUnitSets[Idx].Weight = getRegUnitSetWeight(US.Units);

  // Find the order of each set.
  RegUnitSetOrder.reserve(RegUnitSets.size());
  for (unsigned Idx : seq<unsigned>(RegUnitSets.size()))
    RegUnitSetOrder.push_back(Idx);

  llvm::stable_sort(RegUnitSetOrder, [this](unsigned ID1, unsigned ID2) {
    return getRegPressureSet(ID1).Units.size() <
           getRegPressureSet(ID2).Units.size();
  });
  for (unsigned Idx = 0, EndIdx = RegUnitSets.size(); Idx != EndIdx; ++Idx)
    RegUnitSets[RegUnitSetOrder[Idx]].Order = Idx;
}

//
// Synthesize missing register class intersections.
//
// Make sure that sub-classes of RC exists such that getCommonSubClass(RC, X)
// returns a maximal register class for all X.
//
void CodeGenRegBank::inferCommonSubClass(CodeGenRegisterClass *RC) {
  assert(!RegClasses.empty());
  // Stash the iterator to the last element so that this loop doesn't visit
  // elements added by the getOrCreateSubClass call within it.
  for (auto I = RegClasses.begin(), E = std::prev(RegClasses.end());
       I != std::next(E); ++I) {
    CodeGenRegisterClass *RC1 = RC;
    CodeGenRegisterClass *RC2 = &*I;
    if (RC1 == RC2)
      continue;

    // Compute the set intersection of RC1 and RC2.
    const CodeGenRegister::Vec &Memb1 = RC1->getMembers();
    const CodeGenRegister::Vec &Memb2 = RC2->getMembers();
    CodeGenRegister::Vec Intersection;
    std::set_intersection(Memb1.begin(), Memb1.end(), Memb2.begin(),
                          Memb2.end(),
                          std::inserter(Intersection, Intersection.begin()),
                          deref<std::less<>>());

    // Skip disjoint class pairs.
    if (Intersection.empty())
      continue;

    // Skip casses where the intersection is composed of artificial
    // registers.
    if (llvm::all_of(Intersection, [](const CodeGenRegister *Reg) {
          return Reg->Artificial;
        }))
      continue;

    // If RC1 and RC2 have different spill sizes or alignments, use the
    // stricter one for sub-classing.  If they are equal, prefer RC1.
    if (RC2->RSI.hasStricterSpillThan(RC1->RSI))
      std::swap(RC1, RC2);

    getOrCreateSubClass(RC1, &Intersection,
                        RC1->getName() + "_and_" + RC2->getName());
  }
}

//
// Synthesize missing sub-classes for getSubClassWithSubReg().
//
// Make sure that the set of registers in RC with a given SubIdx sub-register
// form a register class.  Update RC->SubClassWithSubReg.
//
void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) {
  // Map SubRegIndex to set of registers in RC supporting that SubRegIndex.
  using SubReg2SetMap = std::map<const CodeGenSubRegIndex *,
                                 CodeGenRegister::Vec, deref<std::less<>>>;

  // Compute the set of registers supporting each SubRegIndex.
  SubReg2SetMap SRSets;
  for (const CodeGenRegister *R : RC->getMembers()) {
    if (R->Artificial)
      continue;
    CodeGenRegister::SubRegArrayRef SRM = R->getSubRegs();
    for (auto [I, _] : SRM)
      SRSets[I].push_back(R);
  }

  // Find matching classes for all SRSets entries.  Iterate in SubRegIndex
  // numerical order to visit synthetic indices last.
  for (const CodeGenSubRegIndex &SubIdx : SubRegIndices) {
    SubReg2SetMap::const_iterator I = SRSets.find(&SubIdx);
    // Unsupported SubRegIndex. Skip it.
    if (I == SRSets.end())
      continue;
    // In most cases, all RC registers support the SubRegIndex.
    auto IsNotArtificial = [](const CodeGenRegister *R) {
      return !R->Artificial;
    };
    if (I->second.size() ==
        (size_t)count_if(RC->getMembers(), IsNotArtificial)) {
      RC->setSubClassWithSubReg(&SubIdx, RC);
      continue;
    }
    if (SubIdx.Artificial)
      continue;
    // This is a real subset.  See if we have a matching class.
    CodeGenRegisterClass *SubRC =
        getOrCreateSubClass(RC, &I->second,
                            RC->getName() + "_with_" + I->first->getName())
            .first;
    RC->setSubClassWithSubReg(&SubIdx, SubRC);
  }
}

//
// Synthesize missing sub-classes of RC for getMatchingSuperRegClass().
//
// Create sub-classes of RC such that getMatchingSuperRegClass(RC, SubIdx, X)
// has a maximal result for any SubIdx and any X >= FirstSubRegRC.
//

void CodeGenRegBank::inferMatchingSuperRegClass(
    CodeGenRegisterClass *RC,
    std::list<CodeGenRegisterClass>::iterator FirstSubRegRC) {
  DenseSet<const CodeGenSubRegIndex *> ImpliedSubRegIndices;
  std::vector<const CodeGenRegister *> SubRegs;
  BitVector TopoSigs(getNumTopoSigs());

  // Iterate subregister indices in topological order to visit larger indices
  // first. This allows us to skip the smaller indices in many cases because
  // their inferred super-register classes are implied.
  for (CodeGenSubRegIndex *SubIdx : SubRegIndicesRPOT) {
    // Skip indexes that aren't fully supported by RC's registers. This was
    // computed by inferSubClassWithSubReg() above which should have been
    // called first.
    if (RC->getSubClassWithSubReg(SubIdx) != RC)
      continue;

    if (ImpliedSubRegIndices.contains(SubIdx))
      continue;

    // Build list of (Sub, Super) pairs for this SubIdx, sorted by Sub. Note
    // that the list may contain entries with the same Sub but different Supers.
    SubRegs.clear();
    TopoSigs.reset();
    unsigned Hint = 0;
    for (const CodeGenRegister *Super : RC->getMembers()) {
      if (Super->Artificial)
        continue;
      const CodeGenRegister *Sub = Super->getSubReg(SubIdx, Hint);
      assert(Sub && "Missing sub-register");
      SubRegs.push_back(Sub);
      TopoSigs.set(Sub->getTopoSig());
    }

    // Iterate over sub-register class candidates.  Ignore classes created by
    // this loop. They will never be useful.
    // Store an iterator to the last element (not end) so that this loop doesn't
    // visit newly inserted elements.
    assert(!RegClasses.empty());
    for (auto I = FirstSubRegRC, E = std::prev(RegClasses.end());
         I != std::next(E); ++I) {
      CodeGenRegisterClass &SubRC = *I;
      if (SubRC.Artificial)
        continue;
      // Topological shortcut: SubRC members have the wrong shape.
      if (!TopoSigs.anyCommon(SubRC.getRegsWithSuperRegsTopoSigs()))
        continue;
      // Compute the subset of RC that maps into SubRC.
      CodeGenRegister::Vec SubSetVec;
      auto IsNotArtificial = [](const CodeGenRegister *R) {
        return !R->Artificial;
      };
      auto NonArtificialMembers =
          make_filter_range(RC->getMembers(), IsNotArtificial);
      for (const auto &[Sub, Super] :
           zip_equal(SubRegs, NonArtificialMembers)) {
        if (SubRC.contains(Sub))
          SubSetVec.push_back(Super);
      }

      if (SubSetVec.empty())
        continue;

      // RC injects completely into SubRC.
      if (SubSetVec.size() ==
          (size_t)count_if(RC->getMembers(), IsNotArtificial)) {
        SubRC.addSuperRegClass(SubIdx, RC);

        // We can skip checking subregister indices that can be composed from
        // the current SubIdx.
        //
        // Proof sketch: Let SubRC' be another register class and SubSubIdx
        // a subregister index that can be composed from SubIdx.
        //
        // Calling this function with SubRC in place of RC ensures the existence
        // of a subclass X of SubRC with the registers that have subregisters in
        // SubRC'.
        //
        // The set of registers in RC with SubSubIdx in SubRC' is equal to the
        // set of registers in RC with SubIdx in X (because every register in
        // RC has a corresponding subregister in SubRC), and so checking the
        // pair (SubSubIdx, SubRC') is redundant with checking (SubIdx, X).
        for (const auto &SubSubIdx : SubIdx->getComposites())
          ImpliedSubRegIndices.insert(SubSubIdx.second);

        continue;
      }

      // Only a subset of RC maps into SubRC. Make sure it is represented by a
      // class.
      //
      // The name of the inferred register class follows the template
      // "<RC>_with_<SubIdx>_in_<SubRC>".
      //
      // When SubRC is already an inferred class, prefer a name of the form
      // "<RC>_with_<CompositeSubIdx>_in_<SubSubRC>" over a chain of the form
      // "<RC>_with_<SubIdx>_in_<OtherRc>_with_<SubSubIdx>_in_<SubSubRC>".
      // If that preferred name is already used, fall back to the uncomposed
      // form so that different inferred classes do not alias through the same
      // composed name.
      CodeGenSubRegIndex *CompositeSubIdx = SubIdx;
      CodeGenRegisterClass *CompositeSubRC = &SubRC;
      if (CodeGenSubRegIndex *SubSubIdx = SubRC.getInferredFromSubRegIdx()) {
        auto It = SubIdx->getComposites().find(SubSubIdx);
        if (It != SubIdx->getComposites().end()) {
          CompositeSubIdx = It->second;
          CompositeSubRC = SubRC.getInferredFromRC();
        }
      }

      std::string Name = RC->getName() + "_with_" + CompositeSubIdx->getName() +
                         "_in_" + CompositeSubRC->getName();

      if (RegClassNames.contains(Name))
        Name = RC->getName() + "_with_" + SubIdx->getName() + "_in_" +
               SubRC.getName();

      auto [SubSetRC, Inserted] = getOrCreateSubClass(RC, &SubSetVec, Name);

      if (Inserted)
        SubSetRC->setInferredFrom(CompositeSubIdx, CompositeSubRC);
    }
  }
}

//
// Infer missing register classes.
//
void CodeGenRegBank::computeInferredRegisterClasses() {
  assert(!RegClasses.empty());
  // When this function is called, the register classes have not been sorted
  // and assigned EnumValues yet.  That means getSubClasses(),
  // getSuperClasses(), and hasSubClass() functions are defunct.

  Records.getTimer().startTimer("Compute inferred register classes");

  // Use one-before-the-end so it doesn't move forward when new elements are
  // added.
  auto FirstNewRC = std::prev(RegClasses.end());

  // Visit all register classes, including the ones being added by the loop.
  // Watch out for iterator invalidation here.
  for (auto I = RegClasses.begin(), E = RegClasses.end(); I != E; ++I) {
    CodeGenRegisterClass *RC = &*I;
    if (RC->Artificial)
      continue;

    // Synthesize answers for getSubClassWithSubReg().
    inferSubClassWithSubReg(RC);

    // Synthesize answers for getCommonSubClass().
    inferCommonSubClass(RC);

    // Synthesize answers for getMatchingSuperRegClass().
    inferMatchingSuperRegClass(RC);

    // New register classes are created while this loop is running, and we need
    // to visit all of them.  In particular, inferMatchingSuperRegClass needs
    // to match old super-register classes with sub-register classes created
    // after inferMatchingSuperRegClass was called.  At this point,
    // inferMatchingSuperRegClass has checked SuperRC = [0..rci] with SubRC =
    // [0..FirstNewRC).  We need to cover SubRC = [FirstNewRC..rci].
    if (I == FirstNewRC) {
      auto NextNewRC = std::prev(RegClasses.end());
      for (auto I2 = RegClasses.begin(), E2 = std::next(FirstNewRC); I2 != E2;
           ++I2)
        inferMatchingSuperRegClass(&*I2, E2);
      FirstNewRC = NextNewRC;
    }
  }

  Records.getTimer().startTimer("Extend super-register classes");

  // Compute the transitive closure for super-register classes.
  //
  // By iterating over sub-register indices in topological order, we only ever
  // add super-register classes for sub-register indices that have not already
  // been visited. That allows computing the transitive closure in a single
  // pass.
  for (CodeGenSubRegIndex *SubIdx : SubRegIndicesRPOT) {
    for (CodeGenRegisterClass &SubRC : RegClasses)
      SubRC.extendSuperRegClasses(SubIdx);
  }

  Records.getTimer().stopTimer();
}

/// getRegisterClassForRegister - Find the register class that contains the
/// specified physical register.  If the register is not in a register class,
/// return null. If the register is in multiple classes, and the classes have a
/// superset-subset relationship and the same set of types, return the
/// superclass.  Otherwise return null.
const CodeGenRegisterClass *
CodeGenRegBank::getRegClassForRegister(const Record *R) {
  const CodeGenRegister *Reg = getReg(R);
  const CodeGenRegisterClass *FoundRC = nullptr;
  for (const CodeGenRegisterClass &RC : getRegClasses()) {
    if (!RC.contains(Reg))
      continue;

    // If this is the first class that contains the register,
    // make a note of it and go on to the next class.
    if (!FoundRC) {
      FoundRC = &RC;
      continue;
    }

    // If a register's classes have different types, return null.
    if (RC.getValueTypes() != FoundRC->getValueTypes())
      return nullptr;

    // Check to see if the previously found class that contains
    // the register is a subclass of the current class. If so,
    // prefer the superclass.
    if (RC.hasSubClass(FoundRC)) {
      FoundRC = &RC;
      continue;
    }

    // Check to see if the previously found class that contains
    // the register is a superclass of the current class. If so,
    // prefer the superclass.
    if (FoundRC->hasSubClass(&RC))
      continue;

    // Multiple classes, and neither is a superclass of the other.
    // Return null.
    return nullptr;
  }
  return FoundRC;
}

bool CodeGenRegBank::regClassContainsReg(const Record *RegClassDef,
                                         const Record *RegDef,
                                         ArrayRef<SMLoc> Loc) {
  // Check all four combinations of Register[ByHwMode] X RegClass[ByHwMode],
  // starting with the two RegClassByHwMode cases.
  unsigned NumModes = CGH.getNumModeIds();
  std::optional<RegisterByHwMode> RegByMode;
  CodeGenRegister *Reg = nullptr;
  if (RegDef->isSubClassOf("RegisterByHwMode"))
    RegByMode = RegisterByHwMode(RegDef, *this);
  else
    Reg = getReg(RegDef);
  if (RegClassDef->isSubClassOf("RegClassByHwMode")) {
    RegClassByHwMode RC(RegClassDef, *this);
    for (unsigned M = 0; M < NumModes; ++M) {
      if (RC.hasMode(M) && !RC.get(M)->contains(Reg ? Reg : RegByMode->get(M)))
        return false;
    }
    return true;
  }
  // Otherwise we have a plain register class, check Register[ByHwMode]
  CodeGenRegisterClass *RC = getRegClass(RegClassDef, Loc);
  if (Reg)
    return RC->contains(Reg);
  for (unsigned M = 0; M < NumModes; ++M) {
    if (RegByMode->hasMode(M) && !RC->contains(RegByMode->get(M)))
      return false;
  }
  return true; // RegByMode contained for all possible modes.
}

const CodeGenRegisterClass *
CodeGenRegBank::getMinimalPhysRegClass(const Record *RegRecord,
                                       ValueTypeByHwMode *VT) {
  const CodeGenRegister *Reg = getReg(RegRecord);
  const CodeGenRegisterClass *BestRC = nullptr;
  for (const CodeGenRegisterClass &RC : getRegClasses()) {
    if ((!VT || RC.hasType(*VT)) && RC.contains(Reg) &&
        (!BestRC || BestRC->hasSubClass(&RC)))
      BestRC = &RC;
  }

  assert(BestRC && "Couldn't find the register class");
  return BestRC;
}

const CodeGenRegisterClass *
CodeGenRegBank::getSuperRegForSubReg(const ValueTypeByHwMode &ValueTy,
                                     const CodeGenSubRegIndex *SubIdx,
                                     bool MustBeAllocatable) const {
  std::vector<const CodeGenRegisterClass *> Candidates;
  auto &RegClasses = getRegClasses();

  // Try to find a register class which supports ValueTy, and also contains
  // SubIdx.
  for (const CodeGenRegisterClass &RC : RegClasses) {
    // Is there a subclass of this class which contains this subregister index?
    const CodeGenRegisterClass *SubClassWithSubReg =
        RC.getSubClassWithSubReg(SubIdx);
    if (!SubClassWithSubReg)
      continue;

    // We have a class. Check if it supports this value type.
    if (!llvm::is_contained(SubClassWithSubReg->VTs, ValueTy))
      continue;

    // If necessary, check that it is allocatable.
    if (MustBeAllocatable && !SubClassWithSubReg->Allocatable)
      continue;

    // We have a register class which supports both the value type and
    // subregister index. Remember it.
    Candidates.push_back(SubClassWithSubReg);
  }

  // If we didn't find anything, we're done.
  if (Candidates.empty())
    return nullptr;

  // Find and return the largest of our candidate classes.
  llvm::stable_sort(Candidates, [&](const CodeGenRegisterClass *A,
                                    const CodeGenRegisterClass *B) {
    if (A->getMembers().size() > B->getMembers().size())
      return true;

    if (A->getMembers().size() < B->getMembers().size())
      return false;

    // Order by name as a tie-breaker.
    return StringRef(A->getName()) < B->getName();
  });

  return Candidates[0];
}

BitVector
CodeGenRegBank::computeCoveredRegisters(ArrayRef<const Record *> Regs) {
  SetVector<const CodeGenRegister *> Set;

  // First add Regs with all sub-registers.
  for (const Record *RegDef : Regs) {
    CodeGenRegister *Reg = getReg(RegDef);
    if (Set.insert(Reg))
      // Reg is new, add all sub-registers.
      // The pre-ordering is not important here.
      Reg->addSubRegsPreOrder(Set, *this);
  }

  // Second, find all super-registers that are completely covered by the set.
  for (unsigned i = 0; i != Set.size(); ++i) {
    for (const CodeGenRegister *Super : Set[i]->getSuperRegs()) {
      if (!Super->CoveredBySubRegs || Set.contains(Super))
        continue;
      // This new super-register is covered by its sub-registers.
      bool AllSubsInSet = true;
      CodeGenRegister::SubRegArrayRef SRM = Super->getSubRegs();
      for (auto [_, SR] : SRM)
        if (!Set.contains(SR)) {
          AllSubsInSet = false;
          break;
        }
      // All sub-registers in Set, add Super as well.
      // We will visit Super later to recheck its super-registers.
      if (AllSubsInSet)
        Set.insert(Super);
    }
  }

  // Convert to BitVector.
  BitVector BV(Registers.size() + 1);
  for (const CodeGenRegister *Reg : Set)
    BV.set(Reg->EnumValue);
  return BV;
}

void CodeGenRegBank::printRegUnitNames(ArrayRef<unsigned> Units) const {
  for (unsigned Unit : Units) {
    if (Unit < NumNativeRegUnits)
      dbgs() << ' ' << RegUnits[Unit].Roots[0]->getName();
    else
      dbgs() << " #" << Unit;
  }
  dbgs() << '\n';
}
