//===- RDFGraph.cpp -------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Target-independent, SSA-based data flow graph for register data flow (RDF).
//
#include "llvm/CodeGen/RDFGraph.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineDominanceFrontier.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RDFRegisters.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/MC/LaneBitmask.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include <cassert>
#include <cstdint>
#include <cstring>
#include <iterator>
#include <set>
#include <utility>
#include <vector>

// Printing functions. Have them here first, so that the rest of the code
// can use them.
namespace llvm::rdf {

raw_ostream &operator<<(raw_ostream &OS, const Print<RegisterRef> &P) {
  P.G.getPRI().print(OS, P.Obj);
  return OS;
}

raw_ostream &operator<<(raw_ostream &OS, const Print<NodeId> &P) {
  if (P.Obj == 0)
    return OS << "null";
  auto NA = P.G.addr<NodeBase *>(P.Obj);
  uint16_t Attrs = NA.Addr->getAttrs();
  uint16_t Kind = NodeAttrs::kind(Attrs);
  uint16_t Flags = NodeAttrs::flags(Attrs);
  switch (NodeAttrs::type(Attrs)) {
  case NodeAttrs::Code:
    switch (Kind) {
    case NodeAttrs::Func:
      OS << 'f';
      break;
    case NodeAttrs::Block:
      OS << 'b';
      break;
    case NodeAttrs::Stmt:
      OS << 's';
      break;
    case NodeAttrs::Phi:
      OS << 'p';
      break;
    default:
      OS << "c?";
      break;
    }
    break;
  case NodeAttrs::Ref:
    if (Flags & NodeAttrs::Undef)
      OS << '/';
    if (Flags & NodeAttrs::Dead)
      OS << '\\';
    if (Flags & NodeAttrs::Preserving)
      OS << '+';
    if (Flags & NodeAttrs::Clobbering)
      OS << '~';
    switch (Kind) {
    case NodeAttrs::Use:
      OS << 'u';
      break;
    case NodeAttrs::Def:
      OS << 'd';
      break;
    case NodeAttrs::Block:
      OS << 'b';
      break;
    default:
      OS << "r?";
      break;
    }
    break;
  default:
    OS << '?';
    break;
  }
  OS << P.Obj;
  if (Flags & NodeAttrs::Shadow)
    OS << '"';
  return OS;
}

static void printRefHeader(raw_ostream &OS, const Ref RA,
                           const DataFlowGraph &G) {
  OS << Print(RA.Id, G) << '<' << Print(RA.Addr->getRegRef(G), G) << '>';
  if (RA.Addr->getFlags() & NodeAttrs::Fixed)
    OS << '!';
}

raw_ostream &operator<<(raw_ostream &OS, const Print<Def> &P) {
  printRefHeader(OS, P.Obj, P.G);
  OS << '(';
  if (NodeId N = P.Obj.Addr->getReachingDef())
    OS << Print(N, P.G);
  OS << ',';
  if (NodeId N = P.Obj.Addr->getReachedDef())
    OS << Print(N, P.G);
  OS << ',';
  if (NodeId N = P.Obj.Addr->getReachedUse())
    OS << Print(N, P.G);
  OS << "):";
  if (NodeId N = P.Obj.Addr->getSibling())
    OS << Print(N, P.G);
  return OS;
}

raw_ostream &operator<<(raw_ostream &OS, const Print<Use> &P) {
  printRefHeader(OS, P.Obj, P.G);
  OS << '(';
  if (NodeId N = P.Obj.Addr->getReachingDef())
    OS << Print(N, P.G);
  OS << "):";
  if (NodeId N = P.Obj.Addr->getSibling())
    OS << Print(N, P.G);
  return OS;
}

raw_ostream &operator<<(raw_ostream &OS, const Print<PhiUse> &P) {
  printRefHeader(OS, P.Obj, P.G);
  OS << '(';
  if (NodeId N = P.Obj.Addr->getReachingDef())
    OS << Print(N, P.G);
  OS << ',';
  if (NodeId N = P.Obj.Addr->getPredecessor())
    OS << Print(N, P.G);
  OS << "):";
  if (NodeId N = P.Obj.Addr->getSibling())
    OS << Print(N, P.G);
  return OS;
}

raw_ostream &operator<<(raw_ostream &OS, const Print<Ref> &P) {
  switch (P.Obj.Addr->getKind()) {
  case NodeAttrs::Def:
    OS << PrintNode<DefNode *>(P.Obj, P.G);
    break;
  case NodeAttrs::Use:
    if (P.Obj.Addr->getFlags() & NodeAttrs::PhiRef)
      OS << PrintNode<PhiUseNode *>(P.Obj, P.G);
    else
      OS << PrintNode<UseNode *>(P.Obj, P.G);
    break;
  }
  return OS;
}

raw_ostream &operator<<(raw_ostream &OS, const Print<NodeList> &P) {
  unsigned N = P.Obj.size();
  for (auto I : P.Obj) {
    OS << Print(I.Id, P.G);
    if (--N)
      OS << ' ';
  }
  return OS;
}

raw_ostream &operator<<(raw_ostream &OS, const Print<NodeSet> &P) {
  unsigned N = P.Obj.size();
  for (auto I : P.Obj) {
    OS << Print(I, P.G);
    if (--N)
      OS << ' ';
  }
  return OS;
}

namespace {

template <typename T> struct PrintListV {
  PrintListV(const NodeList &L, const DataFlowGraph &G) : List(L), G(G) {}

  using Type = T;
  const NodeList &List;
  const DataFlowGraph &G;
};

template <typename T>
raw_ostream &operator<<(raw_ostream &OS, const PrintListV<T> &P) {
  unsigned N = P.List.size();
  for (NodeAddr<T> A : P.List) {
    OS << PrintNode<T>(A, P.G);
    if (--N)
      OS << ", ";
  }
  return OS;
}

} // end anonymous namespace

raw_ostream &operator<<(raw_ostream &OS, const Print<Phi> &P) {
  OS << Print(P.Obj.Id, P.G) << ": phi ["
     << PrintListV<RefNode *>(P.Obj.Addr->members(P.G), P.G) << ']';
  return OS;
}

raw_ostream &operator<<(raw_ostream &OS, const Print<Stmt> &P) {
  const MachineInstr &MI = *P.Obj.Addr->getCode();
  unsigned Opc = MI.getOpcode();
  OS << Print(P.Obj.Id, P.G) << ": " << P.G.getTII().getName(Opc);
  // Print the target for calls and branches (for readability).
  if (MI.isCall() || MI.isBranch()) {
    MachineInstr::const_mop_iterator T =
        llvm::find_if(MI.operands(), [](const MachineOperand &Op) -> bool {
          return Op.isMBB() || Op.isGlobal() || Op.isSymbol();
        });
    if (T != MI.operands_end()) {
      OS << ' ';
      if (T->isMBB())
        OS << printMBBReference(*T->getMBB());
      else if (T->isGlobal())
        OS << T->getGlobal()->getName();
      else if (T->isSymbol())
        OS << T->getSymbolName();
    }
  }
  OS << " [" << PrintListV<RefNode *>(P.Obj.Addr->members(P.G), P.G) << ']';
  return OS;
}

raw_ostream &operator<<(raw_ostream &OS, const Print<Instr> &P) {
  switch (P.Obj.Addr->getKind()) {
  case NodeAttrs::Phi:
    OS << PrintNode<PhiNode *>(P.Obj, P.G);
    break;
  case NodeAttrs::Stmt:
    OS << PrintNode<StmtNode *>(P.Obj, P.G);
    break;
  default:
    OS << "instr? " << Print(P.Obj.Id, P.G);
    break;
  }
  return OS;
}

raw_ostream &operator<<(raw_ostream &OS, const Print<Block> &P) {
  MachineBasicBlock *BB = P.Obj.Addr->getCode();
  unsigned NP = BB->pred_size();
  std::vector<int> Ns;
  auto PrintBBs = [&OS](const std::vector<int> &Ns) -> void {
    unsigned N = Ns.size();
    for (int I : Ns) {
      OS << "%bb." << I;
      if (--N)
        OS << ", ";
    }
  };

  OS << Print(P.Obj.Id, P.G) << ": --- " << printMBBReference(*BB)
     << " --- preds(" << NP << "): ";
  for (MachineBasicBlock *B : BB->predecessors())
    Ns.push_back(B->getNumber());
  PrintBBs(Ns);

  unsigned NS = BB->succ_size();
  OS << "  succs(" << NS << "): ";
  Ns.clear();
  for (MachineBasicBlock *B : BB->successors())
    Ns.push_back(B->getNumber());
  PrintBBs(Ns);
  OS << '\n';

  for (auto I : P.Obj.Addr->members(P.G))
    OS << PrintNode<InstrNode *>(I, P.G) << '\n';
  return OS;
}

raw_ostream &operator<<(raw_ostream &OS, const Print<Func> &P) {
  OS << "DFG dump:[\n"
     << Print(P.Obj.Id, P.G)
     << ": Function: " << P.Obj.Addr->getCode()->getName() << '\n';
  for (auto I : P.Obj.Addr->members(P.G))
    OS << PrintNode<BlockNode *>(I, P.G) << '\n';
  OS << "]\n";
  return OS;
}

raw_ostream &operator<<(raw_ostream &OS, const Print<RegisterSet> &P) {
  OS << '{';
  for (auto I : P.Obj)
    OS << ' ' << Print(I, P.G);
  OS << " }";
  return OS;
}

raw_ostream &operator<<(raw_ostream &OS, const Print<RegisterAggr> &P) {
  OS << P.Obj;
  return OS;
}

raw_ostream &operator<<(raw_ostream &OS,
                        const Print<DataFlowGraph::DefStack> &P) {
  for (auto I = P.Obj.top(), E = P.Obj.bottom(); I != E;) {
    OS << Print(I->Id, P.G) << '<' << Print(I->Addr->getRegRef(P.G), P.G)
       << '>';
    I.down();
    if (I != E)
      OS << ' ';
  }
  return OS;
}

// Node allocation functions.
//
// Node allocator is like a slab memory allocator: it allocates blocks of
// memory in sizes that are multiples of the size of a node. Each block has
// the same size. Nodes are allocated from the currently active block, and
// when it becomes full, a new one is created.
// There is a mapping scheme between node id and its location in a block,
// and within that block is described in the header file.
//
void NodeAllocator::startNewBlock() {
  void *T = MemPool.Allocate(NodesPerBlock * NodeMemSize, NodeMemSize);
  char *P = static_cast<char *>(T);
  Blocks.push_back(P);
  // Check if the block index is still within the allowed range, i.e. less
  // than 2^N, where N is the number of bits in NodeId for the block index.
  // BitsPerIndex is the number of bits per node index.
  assert((Blocks.size() < ((size_t)1 << (8 * sizeof(NodeId) - BitsPerIndex))) &&
         "Out of bits for block index");
  ActiveEnd = P;
}

bool NodeAllocator::needNewBlock() {
  if (Blocks.empty())
    return true;

  char *ActiveBegin = Blocks.back();
  uint32_t Index = (ActiveEnd - ActiveBegin) / NodeMemSize;
  return Index >= NodesPerBlock;
}

Node NodeAllocator::New() {
  if (needNewBlock())
    startNewBlock();

  uint32_t ActiveB = Blocks.size() - 1;
  uint32_t Index = (ActiveEnd - Blocks[ActiveB]) / NodeMemSize;
  Node NA = {reinterpret_cast<NodeBase *>(ActiveEnd), makeId(ActiveB, Index)};
  ActiveEnd += NodeMemSize;
  return NA;
}

NodeId NodeAllocator::id(const NodeBase *P) const {
  uintptr_t A = reinterpret_cast<uintptr_t>(P);
  for (unsigned i = 0, n = Blocks.size(); i != n; ++i) {
    uintptr_t B = reinterpret_cast<uintptr_t>(Blocks[i]);
    if (A < B || A >= B + NodesPerBlock * NodeMemSize)
      continue;
    uint32_t Idx = (A - B) / NodeMemSize;
    return makeId(i, Idx);
  }
  llvm_unreachable("Invalid node address");
}

void NodeAllocator::clear() {
  MemPool.Reset();
  Blocks.clear();
  ActiveEnd = nullptr;
}

// Insert node NA after "this" in the circular chain.
void NodeBase::append(Node NA) {
  NodeId Nx = Next;
  // If NA is already "next", do nothing.
  if (Next != NA.Id) {
    Next = NA.Id;
    NA.Addr->Next = Nx;
  }
}

// Fundamental node manipulator functions.

// Obtain the register reference from a reference node.
RegisterRef RefNode::getRegRef(const DataFlowGraph &G) const {
  assert(NodeAttrs::type(Attrs) == NodeAttrs::Ref);
  if (NodeAttrs::flags(Attrs) & NodeAttrs::PhiRef)
    return G.unpack(RefData.PR);
  assert(RefData.Op != nullptr);
  return G.makeRegRef(*RefData.Op);
}

// Set the register reference in the reference node directly (for references
// in phi nodes).
void RefNode::setRegRef(RegisterRef RR, DataFlowGraph &G) {
  assert(NodeAttrs::type(Attrs) == NodeAttrs::Ref);
  assert(NodeAttrs::flags(Attrs) & NodeAttrs::PhiRef);
  RefData.PR = G.pack(RR);
}

// Set the register reference in the reference node based on a machine
// operand (for references in statement nodes).
void RefNode::setRegRef(MachineOperand *Op, DataFlowGraph &G) {
  assert(NodeAttrs::type(Attrs) == NodeAttrs::Ref);
  assert(!(NodeAttrs::flags(Attrs) & NodeAttrs::PhiRef));
  (void)G;
  RefData.Op = Op;
}

// Get the owner of a given reference node.
Node RefNode::getOwner(const DataFlowGraph &G) {
  Node NA = G.addr<NodeBase *>(getNext());

  while (NA.Addr != this) {
    if (NA.Addr->getType() == NodeAttrs::Code)
      return NA;
    NA = G.addr<NodeBase *>(NA.Addr->getNext());
  }
  llvm_unreachable("No owner in circular list");
}

// Connect the def node to the reaching def node.
void DefNode::linkToDef(NodeId Self, Def DA) {
  RefData.RD = DA.Id;
  RefData.Sib = DA.Addr->getReachedDef();
  DA.Addr->setReachedDef(Self);
}

// Connect the use node to the reaching def node.
void UseNode::linkToDef(NodeId Self, Def DA) {
  RefData.RD = DA.Id;
  RefData.Sib = DA.Addr->getReachedUse();
  DA.Addr->setReachedUse(Self);
}

// Get the first member of the code node.
Node CodeNode::getFirstMember(const DataFlowGraph &G) const {
  if (CodeData.FirstM == 0)
    return Node();
  return G.addr<NodeBase *>(CodeData.FirstM);
}

// Get the last member of the code node.
Node CodeNode::getLastMember(const DataFlowGraph &G) const {
  if (CodeData.LastM == 0)
    return Node();
  return G.addr<NodeBase *>(CodeData.LastM);
}

// Add node NA at the end of the member list of the given code node.
void CodeNode::addMember(Node NA, const DataFlowGraph &G) {
  Node ML = getLastMember(G);
  if (ML.Id != 0) {
    ML.Addr->append(NA);
  } else {
    CodeData.FirstM = NA.Id;
    NodeId Self = G.id(this);
    NA.Addr->setNext(Self);
  }
  CodeData.LastM = NA.Id;
}

// Add node NA after member node MA in the given code node.
void CodeNode::addMemberAfter(Node MA, Node NA, const DataFlowGraph &G) {
  MA.Addr->append(NA);
  if (CodeData.LastM == MA.Id)
    CodeData.LastM = NA.Id;
}

// Remove member node NA from the given code node.
void CodeNode::removeMember(Node NA, const DataFlowGraph &G) {
  Node MA = getFirstMember(G);
  assert(MA.Id != 0);

  // Special handling if the member to remove is the first member.
  if (MA.Id == NA.Id) {
    if (CodeData.LastM == MA.Id) {
      // If it is the only member, set both first and last to 0.
      CodeData.FirstM = CodeData.LastM = 0;
    } else {
      // Otherwise, advance the first member.
      CodeData.FirstM = MA.Addr->getNext();
    }
    return;
  }

  while (MA.Addr != this) {
    NodeId MX = MA.Addr->getNext();
    if (MX == NA.Id) {
      MA.Addr->setNext(NA.Addr->getNext());
      // If the member to remove happens to be the last one, update the
      // LastM indicator.
      if (CodeData.LastM == NA.Id)
        CodeData.LastM = MA.Id;
      return;
    }
    MA = G.addr<NodeBase *>(MX);
  }
  llvm_unreachable("No such member");
}

// Return the list of all members of the code node.
NodeList CodeNode::members(const DataFlowGraph &G) const {
  static auto True = [](Node) -> bool { return true; };
  return members_if(True, G);
}

// Return the owner of the given instr node.
Node InstrNode::getOwner(const DataFlowGraph &G) {
  Node NA = G.addr<NodeBase *>(getNext());

  while (NA.Addr != this) {
    assert(NA.Addr->getType() == NodeAttrs::Code);
    if (NA.Addr->getKind() == NodeAttrs::Block)
      return NA;
    NA = G.addr<NodeBase *>(NA.Addr->getNext());
  }
  llvm_unreachable("No owner in circular list");
}

// Add the phi node PA to the given block node.
void BlockNode::addPhi(Phi PA, const DataFlowGraph &G) {
  Node M = getFirstMember(G);
  if (M.Id == 0) {
    addMember(PA, G);
    return;
  }

  assert(M.Addr->getType() == NodeAttrs::Code);
  if (M.Addr->getKind() == NodeAttrs::Stmt) {
    // If the first member of the block is a statement, insert the phi as
    // the first member.
    CodeData.FirstM = PA.Id;
    PA.Addr->setNext(M.Id);
  } else {
    // If the first member is a phi, find the last phi, and append PA to it.
    assert(M.Addr->getKind() == NodeAttrs::Phi);
    Node MN = M;
    do {
      M = MN;
      MN = G.addr<NodeBase *>(M.Addr->getNext());
      assert(MN.Addr->getType() == NodeAttrs::Code);
    } while (MN.Addr->getKind() == NodeAttrs::Phi);

    // M is the last phi.
    addMemberAfter(M, PA, G);
  }
}

// Find the block node corresponding to the machine basic block BB in the
// given func node.
Block FuncNode::findBlock(const MachineBasicBlock *BB,
                          const DataFlowGraph &G) const {
  auto EqBB = [BB](Node NA) -> bool { return Block(NA).Addr->getCode() == BB; };
  NodeList Ms = members_if(EqBB, G);
  if (!Ms.empty())
    return Ms[0];
  return Block();
}

// Get the block node for the entry block in the given function.
Block FuncNode::getEntryBlock(const DataFlowGraph &G) {
  MachineBasicBlock *EntryB = &getCode()->front();
  return findBlock(EntryB, G);
}

// Target operand information.
//

// For a given instruction, check if there are any bits of RR that can remain
// unchanged across this def.
bool TargetOperandInfo::isPreserving(const MachineInstr &In,
                                     unsigned OpNum) const {
  return TII.isPredicated(In);
}

// Check if the definition of RR produces an unspecified value.
bool TargetOperandInfo::isClobbering(const MachineInstr &In,
                                     unsigned OpNum) const {
  const MachineOperand &Op = In.getOperand(OpNum);
  if (Op.isRegMask())
    return true;
  assert(Op.isReg());
  if (In.isCall())
    if (Op.isDef() && Op.isDead())
      return true;
  return false;
}

// Check if the given instruction specifically requires
bool TargetOperandInfo::isFixedReg(const MachineInstr &In,
                                   unsigned OpNum) const {
  if (In.isCall() || In.isReturn() || In.isInlineAsm())
    return true;
  // Check for a tail call.
  if (In.isBranch())
    for (const MachineOperand &O : In.operands())
      if (O.isGlobal() || O.isSymbol())
        return true;

  const MCInstrDesc &D = In.getDesc();
  if (D.implicit_defs().empty() && D.implicit_uses().empty())
    return false;
  const MachineOperand &Op = In.getOperand(OpNum);
  // If there is a sub-register, treat the operand as non-fixed. Currently,
  // fixed registers are those that are listed in the descriptor as implicit
  // uses or defs, and those lists do not allow sub-registers.
  if (Op.getSubReg() != 0)
    return false;
  Register Reg = Op.getReg();
  ArrayRef<MCPhysReg> ImpOps =
      Op.isDef() ? D.implicit_defs() : D.implicit_uses();
  return is_contained(ImpOps, Reg);
}

//
// The data flow graph construction.
//

DataFlowGraph::DataFlowGraph(MachineFunction &mf, const TargetInstrInfo &tii,
                             const TargetRegisterInfo &tri,
                             const MachineDominatorTree &mdt,
                             const MachineDominanceFrontier &mdf)
    : DefaultTOI(std::make_unique<TargetOperandInfo>(tii)), MF(mf), TII(tii),
      TRI(tri), PRI(tri, mf), MDT(mdt), MDF(mdf), TOI(*DefaultTOI),
      LiveIns(PRI) {}

DataFlowGraph::DataFlowGraph(MachineFunction &mf, const TargetInstrInfo &tii,
                             const TargetRegisterInfo &tri,
                             const MachineDominatorTree &mdt,
                             const MachineDominanceFrontier &mdf,
                             const TargetOperandInfo &toi)
    : MF(mf), TII(tii), TRI(tri), PRI(tri, mf), MDT(mdt), MDF(mdf), TOI(toi),
      LiveIns(PRI) {}

// The implementation of the definition stack.
// Each register reference has its own definition stack. In particular,
// for a register references "Reg" and "Reg:subreg" will each have their
// own definition stacks.

// Construct a stack iterator.
DataFlowGraph::DefStack::Iterator::Iterator(const DataFlowGraph::DefStack &S,
                                            bool Top)
    : DS(S) {
  if (!Top) {
    // Initialize to bottom.
    Pos = 0;
    return;
  }
  // Initialize to the top, i.e. top-most non-delimiter (or 0, if empty).
  Pos = DS.Stack.size();
  while (Pos > 0 && DS.isDelimiter(DS.Stack[Pos - 1]))
    Pos--;
}

// Return the size of the stack, including block delimiters.
unsigned DataFlowGraph::DefStack::size() const {
  unsigned S = 0;
  for (auto I = top(), E = bottom(); I != E; I.down())
    S++;
  return S;
}

// Remove the top entry from the stack. Remove all intervening delimiters
// so that after this, the stack is either empty, or the top of the stack
// is a non-delimiter.
void DataFlowGraph::DefStack::pop() {
  assert(!empty());
  unsigned P = nextDown(Stack.size());
  Stack.resize(P);
}

// Push a delimiter for block node N on the stack.
void DataFlowGraph::DefStack::start_block(NodeId N) {
  assert(N != 0);
  Stack.push_back(Def(nullptr, N));
}

// Remove all nodes from the top of the stack, until the delimited for
// block node N is encountered. Remove the delimiter as well. In effect,
// this will remove from the stack all definitions from block N.
void DataFlowGraph::DefStack::clear_block(NodeId N) {
  assert(N != 0);
  unsigned P = Stack.size();
  while (P > 0) {
    bool Found = isDelimiter(Stack[P - 1], N);
    P--;
    if (Found)
      break;
  }
  // This will also remove the delimiter, if found.
  Stack.resize(P);
}

// Move the stack iterator up by one.
unsigned DataFlowGraph::DefStack::nextUp(unsigned P) const {
  // Get the next valid position after P (skipping all delimiters).
  // The input position P does not have to point to a non-delimiter.
  unsigned SS = Stack.size();
  bool IsDelim;
  assert(P < SS);
  do {
    P++;
    IsDelim = isDelimiter(Stack[P - 1]);
  } while (P < SS && IsDelim);
  assert(!IsDelim);
  return P;
}

// Move the stack iterator down by one.
unsigned DataFlowGraph::DefStack::nextDown(unsigned P) const {
  // Get the preceding valid position before P (skipping all delimiters).
  // The input position P does not have to point to a non-delimiter.
  assert(P > 0 && P <= Stack.size());
  bool IsDelim = isDelimiter(Stack[P - 1]);
  do {
    if (--P == 0)
      break;
    IsDelim = isDelimiter(Stack[P - 1]);
  } while (P > 0 && IsDelim);
  assert(!IsDelim);
  return P;
}

// Register information.

RegisterAggr DataFlowGraph::getLandingPadLiveIns() const {
  RegisterAggr LR(getPRI());
  const Function &F = MF.getFunction();
  const Constant *PF = F.hasPersonalityFn() ? F.getPersonalityFn() : nullptr;
  const TargetLowering &TLI = *MF.getSubtarget().getTargetLowering();
  if (RegisterId R = TLI.getExceptionPointerRegister(
          TLI.getTargetMachine().getExceptionModel(), PF))
    LR.insert(RegisterRef(R));
  if (!isFuncletEHPersonality(classifyEHPersonality(PF))) {
    if (RegisterId R = TLI.getExceptionSelectorRegister(
            TLI.getTargetMachine().getExceptionModel(), PF))
      LR.insert(RegisterRef(R));
  }
  return LR;
}

// Node management functions.

// Get the pointer to the node with the id N.
NodeBase *DataFlowGraph::ptr(NodeId N) const {
  if (N == 0)
    return nullptr;
  return Memory.ptr(N);
}

// Get the id of the node at the address P.
NodeId DataFlowGraph::id(const NodeBase *P) const {
  if (P == nullptr)
    return 0;
  return Memory.id(P);
}

// Allocate a new node and set the attributes to Attrs.
Node DataFlowGraph::newNode(uint16_t Attrs) {
  Node P = Memory.New();
  P.Addr->init();
  P.Addr->setAttrs(Attrs);
  return P;
}

// Make a copy of the given node B, except for the data-flow links, which
// are set to 0.
Node DataFlowGraph::cloneNode(const Node B) {
  Node NA = newNode(0);
  memcpy(NA.Addr, B.Addr, sizeof(NodeBase));
  // Ref nodes need to have the data-flow links reset.
  if (NA.Addr->getType() == NodeAttrs::Ref) {
    Ref RA = NA;
    RA.Addr->setReachingDef(0);
    RA.Addr->setSibling(0);
    if (NA.Addr->getKind() == NodeAttrs::Def) {
      Def DA = NA;
      DA.Addr->setReachedDef(0);
      DA.Addr->setReachedUse(0);
    }
  }
  return NA;
}

// Allocation routines for specific node types/kinds.

Use DataFlowGraph::newUse(Instr Owner, MachineOperand &Op, uint16_t Flags) {
  Use UA = newNode(NodeAttrs::Ref | NodeAttrs::Use | Flags);
  UA.Addr->setRegRef(&Op, *this);
  return UA;
}

PhiUse DataFlowGraph::newPhiUse(Phi Owner, RegisterRef RR, Block PredB,
                                uint16_t Flags) {
  PhiUse PUA = newNode(NodeAttrs::Ref | NodeAttrs::Use | Flags);
  assert(Flags & NodeAttrs::PhiRef);
  PUA.Addr->setRegRef(RR, *this);
  PUA.Addr->setPredecessor(PredB.Id);
  return PUA;
}

Def DataFlowGraph::newDef(Instr Owner, MachineOperand &Op, uint16_t Flags) {
  Def DA = newNode(NodeAttrs::Ref | NodeAttrs::Def | Flags);
  DA.Addr->setRegRef(&Op, *this);
  return DA;
}

Def DataFlowGraph::newDef(Instr Owner, RegisterRef RR, uint16_t Flags) {
  Def DA = newNode(NodeAttrs::Ref | NodeAttrs::Def | Flags);
  assert(Flags & NodeAttrs::PhiRef);
  DA.Addr->setRegRef(RR, *this);
  return DA;
}

Phi DataFlowGraph::newPhi(Block Owner) {
  Phi PA = newNode(NodeAttrs::Code | NodeAttrs::Phi);
  Owner.Addr->addPhi(PA, *this);
  return PA;
}

Stmt DataFlowGraph::newStmt(Block Owner, MachineInstr *MI) {
  Stmt SA = newNode(NodeAttrs::Code | NodeAttrs::Stmt);
  SA.Addr->setCode(MI);
  Owner.Addr->addMember(SA, *this);
  return SA;
}

Block DataFlowGraph::newBlock(Func Owner, MachineBasicBlock *BB) {
  Block BA = newNode(NodeAttrs::Code | NodeAttrs::Block);
  BA.Addr->setCode(BB);
  Owner.Addr->addMember(BA, *this);
  return BA;
}

Func DataFlowGraph::newFunc(MachineFunction *MF) {
  Func FA = newNode(NodeAttrs::Code | NodeAttrs::Func);
  FA.Addr->setCode(MF);
  return FA;
}

// Build the data flow graph.
void DataFlowGraph::build(const Config &config) {
  reset();
  BuildCfg = config;
  MachineRegisterInfo &MRI = MF.getRegInfo();
  ReservedRegs = MRI.getReservedRegs();
  bool SkipReserved = BuildCfg.Options & BuildOptions::OmitReserved;

  auto Insert = [](auto &Set, auto &&Range) {
    Set.insert(Range.begin(), Range.end());
  };

  if (BuildCfg.TrackRegs.empty()) {
    std::set<RegisterId> BaseSet;
    if (BuildCfg.Classes.empty()) {
      // Insert every register.
      for (unsigned R = 1, E = getPRI().getTRI().getNumRegs(); R != E; ++R)
        BaseSet.insert(R);
    } else {
      for (const TargetRegisterClass *RC : BuildCfg.Classes) {
        for (MCPhysReg R : *RC)
          BaseSet.insert(R);
      }
    }
    for (RegisterId R : BaseSet) {
      if (SkipReserved && ReservedRegs[R])
        continue;
      Insert(TrackedUnits, getPRI().getUnits(RegisterRef(R)));
    }
  } else {
    // Track set in Config overrides everything.
    for (unsigned R : BuildCfg.TrackRegs) {
      if (SkipReserved && ReservedRegs[R])
        continue;
      Insert(TrackedUnits, getPRI().getUnits(RegisterRef(R)));
    }
  }

  TheFunc = newFunc(&MF);

  if (MF.empty())
    return;

  for (MachineBasicBlock &B : MF) {
    Block BA = newBlock(TheFunc, &B);
    BlockNodes.insert(std::make_pair(&B, BA));
    for (MachineInstr &I : B) {
      if (I.isDebugInstr())
        continue;
      buildStmt(BA, I);
    }
  }

  Block EA = TheFunc.Addr->getEntryBlock(*this);
  NodeList Blocks = TheFunc.Addr->members(*this);

  // Collect function live-ins and entry block live-ins.
  MachineBasicBlock &EntryB = *EA.Addr->getCode();
  assert(EntryB.pred_empty() && "Function entry block has predecessors");
  for (std::pair<MCRegister, Register> P : MRI.liveins())
    LiveIns.insert(RegisterRef(P.first));
  if (MRI.tracksLiveness()) {
    for (auto I : EntryB.liveins())
      LiveIns.insert(RegisterRef(I.PhysReg, I.LaneMask));
  }

  // Add function-entry phi nodes for the live-in registers.
  for (RegisterRef RR : LiveIns.refs()) {
    if (RR.isReg() && !isTracked(RR)) // isReg is likely guaranteed
      continue;
    Phi PA = newPhi(EA);
    uint16_t PhiFlags = NodeAttrs::PhiRef | NodeAttrs::Preserving;
    Def DA = newDef(PA, RR, PhiFlags);
    PA.Addr->addMember(DA, *this);
  }

  // Add phis for landing pads.
  // Landing pads, unlike usual backs blocks, are not entered through
  // branches in the program, or fall-throughs from other blocks. They
  // are entered from the exception handling runtime and target's ABI
  // may define certain registers as defined on entry to such a block.
  RegisterAggr EHRegs = getLandingPadLiveIns();
  if (!EHRegs.empty()) {
    for (Block BA : Blocks) {
      const MachineBasicBlock &B = *BA.Addr->getCode();
      if (!B.isEHPad())
        continue;

      // Prepare a list of NodeIds of the block's predecessors.
      NodeList Preds;
      for (MachineBasicBlock *PB : B.predecessors())
        Preds.push_back(findBlock(PB));

      // Build phi nodes for each live-in.
      for (RegisterRef RR : EHRegs.refs()) {
        if (RR.isReg() && !isTracked(RR))
          continue;
        Phi PA = newPhi(BA);
        uint16_t PhiFlags = NodeAttrs::PhiRef | NodeAttrs::Preserving;
        // Add def:
        Def DA = newDef(PA, RR, PhiFlags);
        PA.Addr->addMember(DA, *this);
        // Add uses (no reaching defs for phi uses):
        for (Block PBA : Preds) {
          PhiUse PUA = newPhiUse(PA, RR, PBA);
          PA.Addr->addMember(PUA, *this);
        }
      }
    }
  }

  // Build a map "PhiM" which will contain, for each block, the set
  // of references that will require phi definitions in that block.
  // "PhiClobberM" map contains references that require phis for clobbering defs
  BlockRefsMap PhiM(getPRI());
  BlockRefsMap PhiClobberM(getPRI());
  for (Block BA : Blocks)
    recordDefsForDF(PhiM, PhiClobberM, BA);
  for (Block BA : Blocks)
    buildPhis(PhiM, BA);

  // Link all the refs. This will recursively traverse the dominator tree.
  // Phis for clobbering defs are added here.
  DefStackMap DM;
  linkBlockRefs(DM, PhiClobberM, EA);

  // Finally, remove all unused phi nodes.
  if (!(BuildCfg.Options & BuildOptions::KeepDeadPhis))
    removeUnusedPhis();
}

RegisterRef DataFlowGraph::makeRegRef(unsigned Reg, unsigned Sub) const {
  assert(RegisterRef::isRegId(Reg) || RegisterRef::isMaskId(Reg));
  assert(Reg != 0);
  if (Sub != 0)
    Reg = TRI.getSubReg(Reg, Sub);
  return RegisterRef(Reg);
}

RegisterRef DataFlowGraph::makeRegRef(const MachineOperand &Op) const {
  assert(Op.isReg() || Op.isRegMask());
  if (Op.isReg())
    return makeRegRef(Op.getReg(), Op.getSubReg());
  return RegisterRef(getPRI().getRegMaskId(Op.getRegMask()),
                     LaneBitmask::getAll());
}

// For each stack in the map DefM, push the delimiter for block B on it.
void DataFlowGraph::markBlock(NodeId B, DefStackMap &DefM) {
  // Push block delimiters.
  for (auto &P : DefM)
    P.second.start_block(B);
}

// Remove all definitions coming from block B from each stack in DefM.
void DataFlowGraph::releaseBlock(NodeId B, DefStackMap &DefM) {
  // Pop all defs from this block from the definition stack. Defs that were
  // added to the map during the traversal of instructions will not have a
  // delimiter, but for those, the whole stack will be emptied.
  for (auto &P : DefM)
    P.second.clear_block(B);

  // Finally, remove empty stacks from the map.
  DefM.remove_if([](const auto &P) { return P.second.empty(); });
}

// Push all definitions from the instruction node IA to an appropriate
// stack in DefM.
void DataFlowGraph::pushAllDefs(Instr IA, DefStackMap &DefM) {
  pushClobbers(IA, DefM);
  pushDefs(IA, DefM);
}

// Push all definitions from the instruction node IA to an appropriate
// stack in DefM.
void DataFlowGraph::pushClobbers(Instr IA, DefStackMap &DefM) {
  NodeSet Visited;
  std::set<RegisterId> Defined;

  // The important objectives of this function are:
  // - to be able to handle instructions both while the graph is being
  //   constructed, and after the graph has been constructed, and
  // - maintain proper ordering of definitions on the stack for each
  //   register reference:
  //   - if there are two or more related defs in IA (i.e. coming from
  //     the same machine operand), then only push one def on the stack,
  //   - if there are multiple unrelated defs of non-overlapping
  //     subregisters of S, then the stack for S will have both (in an
  //     unspecified order), but the order does not matter from the data-
  //     -flow perspective.

  for (Def DA : IA.Addr->members_if(IsDef, *this)) {
    if (Visited.count(DA.Id))
      continue;
    if (!(DA.Addr->getFlags() & NodeAttrs::Clobbering))
      continue;

    NodeList Rel = getRelatedRefs(IA, DA);
    Def PDA = Rel.front();
    RegisterRef RR = PDA.Addr->getRegRef(*this);

    // Push the definition on the stack for the register and all aliases.
    // The def stack traversal in linkNodeUp will check the exact aliasing.
    DefM[RR.Id].push(DA);
    Defined.insert(RR.Id);
    for (RegisterId A : getPRI().getAliasSet(RR)) {
      if (RegisterRef::isRegId(A) && !isTracked(RegisterRef(A)))
        continue;
      // Check that we don't push the same def twice.
      assert(A != RR.Id);
      if (!Defined.count(A))
        DefM[A].push(DA);
    }
    // Mark all the related defs as visited.
    for (Node T : Rel)
      Visited.insert(T.Id);
  }
}

// Push all definitions from the instruction node IA to an appropriate
// stack in DefM.
void DataFlowGraph::pushDefs(Instr IA, DefStackMap &DefM) {
  NodeSet Visited;
#ifndef NDEBUG
  std::set<RegisterId> Defined;
#endif

  // The important objectives of this function are:
  // - to be able to handle instructions both while the graph is being
  //   constructed, and after the graph has been constructed, and
  // - maintain proper ordering of definitions on the stack for each
  //   register reference:
  //   - if there are two or more related defs in IA (i.e. coming from
  //     the same machine operand), then only push one def on the stack,
  //   - if there are multiple unrelated defs of non-overlapping
  //     subregisters of S, then the stack for S will have both (in an
  //     unspecified order), but the order does not matter from the data-
  //     -flow perspective.

  for (Def DA : IA.Addr->members_if(IsDef, *this)) {
    if (Visited.count(DA.Id))
      continue;
    if (DA.Addr->getFlags() & NodeAttrs::Clobbering)
      continue;

    NodeList Rel = getRelatedRefs(IA, DA);
    Def PDA = Rel.front();
    RegisterRef RR = PDA.Addr->getRegRef(*this);
#ifndef NDEBUG
    // Assert if the register is defined in two or more unrelated defs.
    // This could happen if there are two or more def operands defining it.
    if (!Defined.insert(RR.Id).second) {
      MachineInstr *MI = Stmt(IA).Addr->getCode();
      dbgs() << "Multiple definitions of register: " << Print(RR, *this)
             << " in\n  " << *MI << "in " << printMBBReference(*MI->getParent())
             << '\n';
      llvm_unreachable(nullptr);
    }
#endif
    // Push the definition on the stack for the register and all aliases.
    // The def stack traversal in linkNodeUp will check the exact aliasing.
    DefM[RR.Id].push(DA);
    for (RegisterId A : getPRI().getAliasSet(RR)) {
      if (RegisterRef::isRegId(A) && !isTracked(RegisterRef(A)))
        continue;
      // Check that we don't push the same def twice.
      assert(A != RR.Id);
      DefM[A].push(DA);
    }
    // Mark all the related defs as visited.
    for (Node T : Rel)
      Visited.insert(T.Id);
  }
}

// Return the list of all reference nodes related to RA, including RA itself.
// See "getNextRelated" for the meaning of a "related reference".
NodeList DataFlowGraph::getRelatedRefs(Instr IA, Ref RA) const {
  assert(IA.Id != 0 && RA.Id != 0);

  NodeList Refs;
  NodeId Start = RA.Id;
  do {
    Refs.push_back(RA);
    RA = getNextRelated(IA, RA);
  } while (RA.Id != 0 && RA.Id != Start);
  return Refs;
}

// Clear all information in the graph.
void DataFlowGraph::reset() {
  Memory.clear();
  BlockNodes.clear();
  TrackedUnits.clear();
  ReservedRegs.clear();
  TheFunc = Func();
}

// Return the next reference node in the instruction node IA that is related
// to RA. Conceptually, two reference nodes are related if they refer to the
// same instance of a register access, but differ in flags or other minor
// characteristics. Specific examples of related nodes are shadow reference
// nodes.
// Return the equivalent of nullptr if there are no more related references.
Ref DataFlowGraph::getNextRelated(Instr IA, Ref RA) const {
  assert(IA.Id != 0 && RA.Id != 0);

  auto IsRelated = [this, RA](Ref TA) -> bool {
    if (TA.Addr->getKind() != RA.Addr->getKind())
      return false;
    if (!getPRI().equal_to(TA.Addr->getRegRef(*this),
                           RA.Addr->getRegRef(*this))) {
      return false;
    }
    return true;
  };

  RegisterRef RR = RA.Addr->getRegRef(*this);
  if (IA.Addr->getKind() == NodeAttrs::Stmt) {
    auto Cond = [&IsRelated, RA](Ref TA) -> bool {
      return IsRelated(TA) && &RA.Addr->getOp() == &TA.Addr->getOp();
    };
    return RA.Addr->getNextRef(RR, Cond, true, *this);
  }

  assert(IA.Addr->getKind() == NodeAttrs::Phi);
  auto Cond = [&IsRelated, RA](Ref TA) -> bool {
    if (!IsRelated(TA))
      return false;
    if (TA.Addr->getKind() != NodeAttrs::Use)
      return true;
    // For phi uses, compare predecessor blocks.
    return PhiUse(TA).Addr->getPredecessor() ==
           PhiUse(RA).Addr->getPredecessor();
  };
  return RA.Addr->getNextRef(RR, Cond, true, *this);
}

// Find the next node related to RA in IA that satisfies condition P.
// If such a node was found, return a pair where the second element is the
// located node. If such a node does not exist, return a pair where the
// first element is the element after which such a node should be inserted,
// and the second element is a null-address.
template <typename Predicate>
std::pair<Ref, Ref> DataFlowGraph::locateNextRef(Instr IA, Ref RA,
                                                 Predicate P) const {
  assert(IA.Id != 0 && RA.Id != 0);

  Ref NA;
  NodeId Start = RA.Id;
  while (true) {
    NA = getNextRelated(IA, RA);
    if (NA.Id == 0 || NA.Id == Start)
      break;
    if (P(NA))
      break;
    RA = NA;
  }

  if (NA.Id != 0 && NA.Id != Start)
    return std::make_pair(RA, NA);
  return std::make_pair(RA, Ref());
}

// Get the next shadow node in IA corresponding to RA, and optionally create
// such a node if it does not exist.
Ref DataFlowGraph::getNextShadow(Instr IA, Ref RA, bool Create) {
  assert(IA.Id != 0 && RA.Id != 0);

  uint16_t Flags = RA.Addr->getFlags() | NodeAttrs::Shadow;
  auto IsShadow = [Flags](Ref TA) -> bool {
    return TA.Addr->getFlags() == Flags;
  };
  auto Loc = locateNextRef(IA, RA, IsShadow);
  if (Loc.second.Id != 0 || !Create)
    return Loc.second;

  // Create a copy of RA and mark is as shadow.
  Ref NA = cloneNode(RA);
  NA.Addr->setFlags(Flags | NodeAttrs::Shadow);
  IA.Addr->addMemberAfter(Loc.first, NA, *this);
  return NA;
}

// Create a new statement node in the block node BA that corresponds to
// the machine instruction MI.
void DataFlowGraph::buildStmt(Block BA, MachineInstr &In) {
  Stmt SA = newStmt(BA, &In);

  auto isCall = [](const MachineInstr &In) -> bool {
    if (In.isCall())
      return true;
    // Is tail call?
    if (In.isBranch()) {
      for (const MachineOperand &Op : In.operands())
        if (Op.isGlobal() || Op.isSymbol())
          return true;
      // Assume indirect branches are calls. This is for the purpose of
      // keeping implicit operands, and so it won't hurt on intra-function
      // indirect branches.
      if (In.isIndirectBranch())
        return true;
    }
    return false;
  };

  auto isDefUndef = [this](const MachineInstr &In, RegisterRef DR) -> bool {
    // This instruction defines DR. Check if there is a use operand that
    // would make DR live on entry to the instruction.
    for (const MachineOperand &Op : In.all_uses()) {
      if (Op.getReg() == 0 || Op.isUndef())
        continue;
      RegisterRef UR = makeRegRef(Op);
      if (getPRI().alias(DR, UR))
        return false;
    }
    return true;
  };

  bool IsCall = isCall(In);
  unsigned NumOps = In.getNumOperands();

  // Avoid duplicate implicit defs. This will not detect cases of implicit
  // defs that define registers that overlap, but it is not clear how to
  // interpret that in the absence of explicit defs. Overlapping explicit
  // defs are likely illegal already.
  BitVector DoneDefs(TRI.getNumRegs());
  // Process explicit defs first.
  for (unsigned OpN = 0; OpN < NumOps; ++OpN) {
    MachineOperand &Op = In.getOperand(OpN);
    if (!Op.isReg() || !Op.isDef() || Op.isImplicit())
      continue;
    Register R = Op.getReg();
    if (!R || !R.isPhysical() || !isTracked(RegisterRef(R)))
      continue;
    uint16_t Flags = NodeAttrs::None;
    if (TOI.isPreserving(In, OpN)) {
      Flags |= NodeAttrs::Preserving;
      // If the def is preserving, check if it is also undefined.
      if (isDefUndef(In, makeRegRef(Op)))
        Flags |= NodeAttrs::Undef;
    }
    if (TOI.isClobbering(In, OpN))
      Flags |= NodeAttrs::Clobbering;
    if (TOI.isFixedReg(In, OpN))
      Flags |= NodeAttrs::Fixed;
    if (IsCall && Op.isDead())
      Flags |= NodeAttrs::Dead;
    Def DA = newDef(SA, Op, Flags);
    SA.Addr->addMember(DA, *this);
    assert(!DoneDefs.test(R));
    DoneDefs.set(R);
  }

  // Process reg-masks (as clobbers).
  BitVector DoneClobbers(TRI.getNumRegs());
  for (unsigned OpN = 0; OpN < NumOps; ++OpN) {
    MachineOperand &Op = In.getOperand(OpN);
    if (!Op.isRegMask())
      continue;
    uint16_t Flags = NodeAttrs::Clobbering | NodeAttrs::Fixed | NodeAttrs::Dead;
    Def DA = newDef(SA, Op, Flags);
    SA.Addr->addMember(DA, *this);
    // Record all clobbered registers in DoneDefs.
    const uint32_t *RM = Op.getRegMask();
    for (unsigned i = 1, e = TRI.getNumRegs(); i != e; ++i) {
      if (!isTracked(RegisterRef(i)))
        continue;
      if (!(RM[i / 32] & (1u << (i % 32))))
        DoneClobbers.set(i);
    }
  }

  // Process implicit defs, skipping those that have already been added
  // as explicit.
  for (unsigned OpN = 0; OpN < NumOps; ++OpN) {
    MachineOperand &Op = In.getOperand(OpN);
    if (!Op.isReg() || !Op.isDef() || !Op.isImplicit())
      continue;
    Register R = Op.getReg();
    if (!R || !R.isPhysical() || !isTracked(RegisterRef(R)) || DoneDefs.test(R))
      continue;
    RegisterRef RR = makeRegRef(Op);
    uint16_t Flags = NodeAttrs::None;
    if (TOI.isPreserving(In, OpN)) {
      Flags |= NodeAttrs::Preserving;
      // If the def is preserving, check if it is also undefined.
      if (isDefUndef(In, RR))
        Flags |= NodeAttrs::Undef;
    }
    if (TOI.isClobbering(In, OpN))
      Flags |= NodeAttrs::Clobbering;
    if (TOI.isFixedReg(In, OpN))
      Flags |= NodeAttrs::Fixed;
    if (IsCall && Op.isDead()) {
      if (DoneClobbers.test(R))
        continue;
      Flags |= NodeAttrs::Dead;
    }
    Def DA = newDef(SA, Op, Flags);
    SA.Addr->addMember(DA, *this);
    DoneDefs.set(R);
  }

  for (unsigned OpN = 0; OpN < NumOps; ++OpN) {
    MachineOperand &Op = In.getOperand(OpN);
    if (!Op.isReg() || !Op.isUse())
      continue;
    Register R = Op.getReg();
    if (!R || !R.isPhysical() || !isTracked(RegisterRef(R)))
      continue;
    uint16_t Flags = NodeAttrs::None;
    if (Op.isUndef())
      Flags |= NodeAttrs::Undef;
    if (TOI.isFixedReg(In, OpN))
      Flags |= NodeAttrs::Fixed;
    Use UA = newUse(SA, Op, Flags);
    SA.Addr->addMember(UA, *this);
  }
}

// Scan all defs in the block node BA and record in PhiM the locations of
// phi nodes corresponding to these defs.
// Clobbering defs in BA are recorded in PhiClobberM
void DataFlowGraph::recordDefsForDF(BlockRefsMap &PhiM,
                                    BlockRefsMap &PhiClobberM, Block BA) {
  // Check all defs from block BA and record them in each block in BA's
  // iterated dominance frontier. This information will later be used to
  // create phi nodes.
  MachineBasicBlock *BB = BA.Addr->getCode();
  assert(BB);
  auto DFLoc = MDF.find(BB);
  if (DFLoc == MDF.end() || DFLoc->second.empty())
    return;

  // Traverse all instructions in the block and collect the set of all
  // defined references. For each reference there will be a phi created
  // in the block's iterated dominance frontier.
  // This is done to make sure that each defined reference gets only one
  // phi node, even if it is defined multiple times.
  RegisterAggr Defs(getPRI());
  RegisterAggr ClobberDefs(getPRI());
  for (Instr IA : BA.Addr->members(*this)) {
    for (Ref RA : IA.Addr->members_if(IsDef, *this)) {
      RegisterRef RR = RA.Addr->getRegRef(*this);
      if (!isTracked(RR))
        continue;
      if (RR.isReg())
        Defs.insert(RR);
      // Clobbering def
      else if (RR.isMask())
        ClobberDefs.insert(RR);
    }
  }

  // Calculate the iterated dominance frontier of BB.
  const MachineDominanceFrontier::DomSetType &DF = DFLoc->second;
  SetVector<MachineBasicBlock *> IDF(llvm::from_range, DF);
  for (unsigned i = 0; i < IDF.size(); ++i) {
    auto F = MDF.find(IDF[i]);
    if (F != MDF.end())
      IDF.insert_range(F->second);
  }

  // Finally, add the set of defs to each block in the iterated dominance
  // frontier.
  for (auto *DB : IDF) {
    Block DBA = findBlock(DB);
    PhiM[DBA.Id].insert(Defs);
    PhiClobberM[DBA.Id].insert(ClobberDefs);
  }
}

// Given the locations of phi nodes in the map PhiM, create the phi nodes
// that are located in the block node BA.
void DataFlowGraph::buildPhis(BlockRefsMap &PhiM, Block BA,
                              const DefStackMap &DefM) {
  // Check if this blocks has any DF defs, i.e. if there are any defs
  // that this block is in the iterated dominance frontier of.
  auto HasDF = PhiM.find(BA.Id);
  if (HasDF == PhiM.end() || HasDF->second.empty())
    return;

  // Prepare a list of NodeIds of the block's predecessors.
  NodeList Preds;
  const MachineBasicBlock *MBB = BA.Addr->getCode();
  for (MachineBasicBlock *PB : MBB->predecessors())
    Preds.push_back(findBlock(PB));

  RegisterAggr PhiDefs(getPRI());
  // DefM will be non empty when we are building phis
  // for clobbering defs
  if (!DefM.empty()) {
    for (Instr IA : BA.Addr->members_if(IsPhi, *this)) {
      for (Def DA : IA.Addr->members_if(IsDef, *this)) {
        auto DR = DA.Addr->getRegRef(*this);
        PhiDefs.insert(DR);
      }
    }
  }

  MachineRegisterInfo &MRI = MF.getRegInfo();
  const RegisterAggr &Defs = PhiM[BA.Id];
  uint16_t PhiFlags = NodeAttrs::PhiRef | NodeAttrs::Preserving;

  for (RegisterRef RR : Defs.refs()) {
    if (!DefM.empty()) {
      auto F = DefM.find(RR.Id);
      // Do not create a phi for unallocatable registers, or for registers
      // that are never livein to BA.
      // If a phi exists for RR, do not create another.
      if (!MRI.isAllocatable(RR.asMCReg()) || PhiDefs.hasCoverOf(RR) ||
          F == DefM.end() || F->second.empty())
        continue;
      // Do not create a phi, if all reaching defs are clobbering
      auto RDef = F->second.top();
      if (RDef->Addr->getFlags() & NodeAttrs::Clobbering)
        continue;
      PhiDefs.insert(RR);
    }
    Phi PA = newPhi(BA);
    PA.Addr->addMember(newDef(PA, RR, PhiFlags), *this);

    // Add phi uses.
    for (Block PBA : Preds) {
      PA.Addr->addMember(newPhiUse(PA, RR, PBA), *this);
    }
  }
}

// Remove any unneeded phi nodes that were created during the build process.
void DataFlowGraph::removeUnusedPhis() {
  // This will remove unused phis, i.e. phis where each def does not reach
  // any uses or other defs. This will not detect or remove circular phi
  // chains that are otherwise dead. Unused/dead phis are created during
  // the build process and this function is intended to remove these cases
  // that are easily determinable to be unnecessary.

  SetVector<NodeId> PhiQ;
  for (Block BA : TheFunc.Addr->members(*this)) {
    for (auto P : BA.Addr->members_if(IsPhi, *this))
      PhiQ.insert(P.Id);
  }

  static auto HasUsedDef = [](NodeList &Ms) -> bool {
    for (Node M : Ms) {
      if (M.Addr->getKind() != NodeAttrs::Def)
        continue;
      Def DA = M;
      if (DA.Addr->getReachedDef() != 0 || DA.Addr->getReachedUse() != 0)
        return true;
    }
    return false;
  };

  // Any phi, if it is removed, may affect other phis (make them dead).
  // For each removed phi, collect the potentially affected phis and add
  // them back to the queue.
  while (!PhiQ.empty()) {
    auto PA = addr<PhiNode *>(PhiQ[0]);
    PhiQ.remove(PA.Id);
    NodeList Refs = PA.Addr->members(*this);
    if (HasUsedDef(Refs))
      continue;
    for (Ref RA : Refs) {
      if (NodeId RD = RA.Addr->getReachingDef()) {
        auto RDA = addr<DefNode *>(RD);
        Instr OA = RDA.Addr->getOwner(*this);
        if (IsPhi(OA))
          PhiQ.insert(OA.Id);
      }
      if (RA.Addr->isDef())
        unlinkDef(RA, true);
      else
        unlinkUse(RA, true);
    }
    Block BA = PA.Addr->getOwner(*this);
    BA.Addr->removeMember(PA, *this);
  }
}

// For a given reference node TA in an instruction node IA, connect the
// reaching def of TA to the appropriate def node. Create any shadow nodes
// as appropriate.
template <typename T>
void DataFlowGraph::linkRefUp(Instr IA, NodeAddr<T> TA, DefStack &DS) {
  if (DS.empty())
    return;
  RegisterRef RR = TA.Addr->getRegRef(*this);
  NodeAddr<T> TAP;

  // References from the def stack that have been examined so far.
  RegisterAggr Defs(getPRI());

  for (auto I = DS.top(), E = DS.bottom(); I != E; I.down()) {
    RegisterRef QR = I->Addr->getRegRef(*this);

    // Skip all defs that we have already seen.
    // If this completes a cover of RR, stop the stack traversal.
    bool Seen = Defs.hasCoverOf(QR);
    if (Seen)
      continue;

    bool Cover = Defs.insert(QR).hasCoverOf(RR);

    // The reaching def.
    Def RDA = *I;

    // Pick the reached node.
    if (TAP.Id == 0) {
      TAP = TA;
    } else {
      // Mark the existing ref as "shadow" and create a new shadow.
      TAP.Addr->setFlags(TAP.Addr->getFlags() | NodeAttrs::Shadow);
      TAP = getNextShadow(IA, TAP, true);
    }

    // Create the link.
    TAP.Addr->linkToDef(TAP.Id, RDA);

    if (Cover)
      break;
  }
}

// Create data-flow links for all reference nodes in the statement node SA.
template <typename Predicate>
void DataFlowGraph::linkStmtRefs(DefStackMap &DefM, Stmt SA, Predicate P) {
#ifndef NDEBUG
  RegisterSet Defs(getPRI());
#endif

  // Link all nodes (upwards in the data-flow) with their reaching defs.
  for (Ref RA : SA.Addr->members_if(P, *this)) {
    uint16_t Kind = RA.Addr->getKind();
    assert(Kind == NodeAttrs::Def || Kind == NodeAttrs::Use);
    RegisterRef RR = RA.Addr->getRegRef(*this);
#ifndef NDEBUG
    // Do not expect multiple defs of the same reference.
    assert(Kind != NodeAttrs::Def || !Defs.count(RR));
    Defs.insert(RR);
#endif

    auto F = DefM.find(RR.Id);
    if (F == DefM.end())
      continue;
    DefStack &DS = F->second;
    if (Kind == NodeAttrs::Use)
      linkRefUp<UseNode *>(SA, RA, DS);
    else if (Kind == NodeAttrs::Def)
      linkRefUp<DefNode *>(SA, RA, DS);
    else
      llvm_unreachable("Unexpected node in instruction");
  }
}

// Create data-flow links for all instructions in the block node BA. This
// will include updating any phi nodes in BA.
void DataFlowGraph::linkBlockRefs(DefStackMap &DefM, BlockRefsMap &PhiClobberM,
                                  Block BA) {
  // Create phi nodes for clobbering defs.
  // Since a huge number of registers can get clobbered, it would result in many
  // phi nodes being created in the graph. Only create phi nodes that have a non
  // clobbering reaching def. Use DefM to get not clobbering defs reaching a
  // block.
  buildPhis(PhiClobberM, BA, DefM);

  // Push block delimiters.
  markBlock(BA.Id, DefM);

  auto IsClobber = [](Ref RA) -> bool {
    return IsDef(RA) && (RA.Addr->getFlags() & NodeAttrs::Clobbering);
  };
  auto IsNoClobber = [](Ref RA) -> bool {
    return IsDef(RA) && !(RA.Addr->getFlags() & NodeAttrs::Clobbering);
  };

  assert(BA.Addr && "block node address is needed to create a data-flow link");
  // For each non-phi instruction in the block, link all the defs and uses
  // to their reaching defs. For any member of the block (including phis),
  // push the defs on the corresponding stacks.
  for (Instr IA : BA.Addr->members(*this)) {
    // Ignore phi nodes here. They will be linked part by part from the
    // predecessors.
    if (IA.Addr->getKind() == NodeAttrs::Stmt) {
      linkStmtRefs(DefM, IA, IsUse);
      linkStmtRefs(DefM, IA, IsClobber);
    }

    // Push the definitions on the stack.
    pushClobbers(IA, DefM);

    if (IA.Addr->getKind() == NodeAttrs::Stmt)
      linkStmtRefs(DefM, IA, IsNoClobber);

    pushDefs(IA, DefM);
  }

  // Recursively process all children in the dominator tree.
  MachineDomTreeNode *N = MDT.getNode(BA.Addr->getCode());
  for (auto *I : *N) {
    MachineBasicBlock *SB = I->getBlock();
    Block SBA = findBlock(SB);
    linkBlockRefs(DefM, PhiClobberM, SBA);
  }

  // Link the phi uses from the successor blocks.
  auto IsUseForBA = [BA](Node NA) -> bool {
    if (NA.Addr->getKind() != NodeAttrs::Use)
      return false;
    assert(NA.Addr->getFlags() & NodeAttrs::PhiRef);
    return PhiUse(NA).Addr->getPredecessor() == BA.Id;
  };

  RegisterAggr EHLiveIns = getLandingPadLiveIns();
  MachineBasicBlock *MBB = BA.Addr->getCode();

  for (MachineBasicBlock *SB : MBB->successors()) {
    bool IsEHPad = SB->isEHPad();
    Block SBA = findBlock(SB);
    for (Instr IA : SBA.Addr->members_if(IsPhi, *this)) {
      // Do not link phi uses for landing pad live-ins.
      if (IsEHPad) {
        // Find what register this phi is for.
        Ref RA = IA.Addr->getFirstMember(*this);
        assert(RA.Id != 0);
        if (EHLiveIns.hasCoverOf(RA.Addr->getRegRef(*this)))
          continue;
      }
      // Go over each phi use associated with MBB, and link it.
      for (auto U : IA.Addr->members_if(IsUseForBA, *this)) {
        PhiUse PUA = U;
        RegisterRef RR = PUA.Addr->getRegRef(*this);
        linkRefUp<UseNode *>(IA, PUA, DefM[RR.Id]);
      }
    }
  }

  // Pop all defs from this block from the definition stacks.
  releaseBlock(BA.Id, DefM);
}

// Remove the use node UA from any data-flow and structural links.
void DataFlowGraph::unlinkUseDF(Use UA) {
  NodeId RD = UA.Addr->getReachingDef();
  NodeId Sib = UA.Addr->getSibling();

  if (RD == 0) {
    assert(Sib == 0);
    return;
  }

  auto RDA = addr<DefNode *>(RD);
  auto TA = addr<UseNode *>(RDA.Addr->getReachedUse());
  if (TA.Id == UA.Id) {
    RDA.Addr->setReachedUse(Sib);
    return;
  }

  while (TA.Id != 0) {
    NodeId S = TA.Addr->getSibling();
    if (S == UA.Id) {
      TA.Addr->setSibling(UA.Addr->getSibling());
      return;
    }
    TA = addr<UseNode *>(S);
  }
}

// Remove the def node DA from any data-flow and structural links.
void DataFlowGraph::unlinkDefDF(Def DA) {
  //
  //         RD
  //         | reached
  //         | def
  //         :
  //         .
  //        +----+
  // ... -- | DA | -- ... -- 0  : sibling chain of DA
  //        +----+
  //         |  | reached
  //         |  : def
  //         |  .
  //         | ...  : Siblings (defs)
  //         |
  //         : reached
  //         . use
  //        ... : sibling chain of reached uses

  NodeId RD = DA.Addr->getReachingDef();

  // Visit all siblings of the reached def and reset their reaching defs.
  // Also, defs reached by DA are now "promoted" to being reached by RD,
  // so all of them will need to be spliced into the sibling chain where
  // DA belongs.
  auto getAllNodes = [this](NodeId N) -> NodeList {
    NodeList Res;
    while (N) {
      auto RA = addr<RefNode *>(N);
      // Keep the nodes in the exact sibling order.
      Res.push_back(RA);
      N = RA.Addr->getSibling();
    }
    return Res;
  };
  NodeList ReachedDefs = getAllNodes(DA.Addr->getReachedDef());
  NodeList ReachedUses = getAllNodes(DA.Addr->getReachedUse());

  if (RD == 0) {
    for (Ref I : ReachedDefs)
      I.Addr->setSibling(0);
    for (Ref I : ReachedUses)
      I.Addr->setSibling(0);
  }
  for (Def I : ReachedDefs)
    I.Addr->setReachingDef(RD);
  for (Use I : ReachedUses)
    I.Addr->setReachingDef(RD);

  NodeId Sib = DA.Addr->getSibling();
  if (RD == 0) {
    assert(Sib == 0);
    return;
  }

  // Update the reaching def node and remove DA from the sibling list.
  auto RDA = addr<DefNode *>(RD);
  auto TA = addr<DefNode *>(RDA.Addr->getReachedDef());
  if (TA.Id == DA.Id) {
    // If DA is the first reached def, just update the RD's reached def
    // to the DA's sibling.
    RDA.Addr->setReachedDef(Sib);
  } else {
    // Otherwise, traverse the sibling list of the reached defs and remove
    // DA from it.
    while (TA.Id != 0) {
      NodeId S = TA.Addr->getSibling();
      if (S == DA.Id) {
        TA.Addr->setSibling(Sib);
        break;
      }
      TA = addr<DefNode *>(S);
    }
  }

  // Splice the DA's reached defs into the RDA's reached def chain.
  if (!ReachedDefs.empty()) {
    auto Last = Def(ReachedDefs.back());
    Last.Addr->setSibling(RDA.Addr->getReachedDef());
    RDA.Addr->setReachedDef(ReachedDefs.front().Id);
  }
  // Splice the DA's reached uses into the RDA's reached use chain.
  if (!ReachedUses.empty()) {
    auto Last = Use(ReachedUses.back());
    Last.Addr->setSibling(RDA.Addr->getReachedUse());
    RDA.Addr->setReachedUse(ReachedUses.front().Id);
  }
}

bool DataFlowGraph::isTracked(RegisterRef RR) const {
  return !disjoint(getPRI().getUnits(RR), TrackedUnits);
}

bool DataFlowGraph::hasUntrackedRef(Stmt S, bool IgnoreReserved) const {
  SmallVector<MachineOperand *> Ops;

  for (Ref R : S.Addr->members(*this)) {
    Ops.push_back(&R.Addr->getOp());
    RegisterRef RR = R.Addr->getRegRef(*this);
    if (IgnoreReserved && RR.isReg() && ReservedRegs[RR.asMCReg().id()])
      continue;
    if (!isTracked(RR))
      return true;
  }
  for (const MachineOperand &Op : S.Addr->getCode()->operands()) {
    if (!Op.isReg() && !Op.isRegMask())
      continue;
    if (!llvm::is_contained(Ops, &Op))
      return true;
  }
  return false;
}

} // end namespace llvm::rdf
