#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/LiveIntervals.h"
#include "llvm/CodeGen/LivePhysRegs.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SlotIndexes.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/ModuleSlotTracker.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include <algorithm>
using namespace llvm;
#define DEBUG_TYPE "codegen"
static cl::opt<bool> PrintSlotIndexes(
    "print-slotindexes",
    cl::desc("When printing machine IR, annotate instructions and blocks with "
             "SlotIndexes when available"),
    cl::init(true), cl::Hidden);
MachineBasicBlock::MachineBasicBlock(MachineFunction &MF, const BasicBlock *B)
    : BB(B), Number(-1), xParent(&MF) {
  Insts.Parent = this;
  if (B)
    IrrLoopHeaderWeight = B->getIrrLoopHeaderWeight();
}
MachineBasicBlock::~MachineBasicBlock() = default;
MCSymbol *MachineBasicBlock::getSymbol() const {
  if (!CachedMCSymbol) {
    const MachineFunction *MF = getParent();
    MCContext &Ctx = MF->getContext();
                if (MF->hasBBSections() && isBeginSection()) {
      SmallString<5> Suffix;
      if (SectionID == MBBSectionID::ColdSectionID) {
        Suffix += ".cold";
      } else if (SectionID == MBBSectionID::ExceptionSectionID) {
        Suffix += ".eh";
      } else {
                                Suffix = (Suffix + Twine(".__part.") + Twine(SectionID.Number)).str();
      }
      CachedMCSymbol = Ctx.getOrCreateSymbol(MF->getName() + Suffix);
    } else {
      const StringRef Prefix = Ctx.getAsmInfo()->getPrivateLabelPrefix();
      CachedMCSymbol = Ctx.getOrCreateSymbol(Twine(Prefix) + "BB" +
                                             Twine(MF->getFunctionNumber()) +
                                             "_" + Twine(getNumber()));
    }
  }
  return CachedMCSymbol;
}
MCSymbol *MachineBasicBlock::getEHCatchretSymbol() const {
  if (!CachedEHCatchretMCSymbol) {
    const MachineFunction *MF = getParent();
    SmallString<128> SymbolName;
    raw_svector_ostream(SymbolName)
        << "$ehgcr_" << MF->getFunctionNumber() << '_' << getNumber();
    CachedEHCatchretMCSymbol = MF->getContext().getOrCreateSymbol(SymbolName);
  }
  return CachedEHCatchretMCSymbol;
}
MCSymbol *MachineBasicBlock::getEndSymbol() const {
  if (!CachedEndMCSymbol) {
    const MachineFunction *MF = getParent();
    MCContext &Ctx = MF->getContext();
    auto Prefix = Ctx.getAsmInfo()->getPrivateLabelPrefix();
    CachedEndMCSymbol = Ctx.getOrCreateSymbol(Twine(Prefix) + "BB_END" +
                                              Twine(MF->getFunctionNumber()) +
                                              "_" + Twine(getNumber()));
  }
  return CachedEndMCSymbol;
}
raw_ostream &llvm::operator<<(raw_ostream &OS, const MachineBasicBlock &MBB) {
  MBB.print(OS);
  return OS;
}
Printable llvm::printMBBReference(const MachineBasicBlock &MBB) {
  return Printable([&MBB](raw_ostream &OS) { return MBB.printAsOperand(OS); });
}
void ilist_callback_traits<MachineBasicBlock>::addNodeToList(
    MachineBasicBlock *N) {
  MachineFunction &MF = *N->getParent();
  N->Number = MF.addToMBBNumbering(N);
    MachineRegisterInfo &RegInfo = MF.getRegInfo();
  for (MachineInstr &MI : N->instrs())
    MI.addRegOperandsToUseLists(RegInfo);
}
void ilist_callback_traits<MachineBasicBlock>::removeNodeFromList(
    MachineBasicBlock *N) {
  N->getParent()->removeFromMBBNumbering(N->Number);
  N->Number = -1;
}
void ilist_traits<MachineInstr>::addNodeToList(MachineInstr *N) {
  assert(!N->getParent() && "machine instruction already in a basic block");
  N->setParent(Parent);
      MachineFunction *MF = Parent->getParent();
  N->addRegOperandsToUseLists(MF->getRegInfo());
  MF->handleInsertion(*N);
}
void ilist_traits<MachineInstr>::removeNodeFromList(MachineInstr *N) {
  assert(N->getParent() && "machine instruction not in a basic block");
    if (MachineFunction *MF = N->getMF()) {
    MF->handleRemoval(*N);
    N->removeRegOperandsFromUseLists(MF->getRegInfo());
  }
  N->setParent(nullptr);
}
void ilist_traits<MachineInstr>::transferNodesFromList(ilist_traits &FromList,
                                                       instr_iterator First,
                                                       instr_iterator Last) {
  assert(Parent->getParent() == FromList.Parent->getParent() &&
         "cannot transfer MachineInstrs between MachineFunctions");
    if (this == &FromList)
    return;
  assert(Parent != FromList.Parent && "Two lists have the same parent?");
      for (; First != Last; ++First)
    First->setParent(Parent);
}
void ilist_traits<MachineInstr>::deleteNode(MachineInstr *MI) {
  assert(!MI->getParent() && "MI is still in a block!");
  Parent->getParent()->deleteMachineInstr(MI);
}
MachineBasicBlock::iterator MachineBasicBlock::getFirstNonPHI() {
  instr_iterator I = instr_begin(), E = instr_end();
  while (I != E && I->isPHI())
    ++I;
  assert((I == E || !I->isInsideBundle()) &&
         "First non-phi MI cannot be inside a bundle!");
  return I;
}
MachineBasicBlock::iterator
MachineBasicBlock::SkipPHIsAndLabels(MachineBasicBlock::iterator I) {
  const TargetInstrInfo *TII = getParent()->getSubtarget().getInstrInfo();
  iterator E = end();
  while (I != E && (I->isPHI() || I->isPosition() ||
                    TII->isBasicBlockPrologue(*I)))
    ++I;
      assert((I == E || !I->isInsideBundle()) &&
         "First non-phi / non-label instruction is inside a bundle!");
  return I;
}
MachineBasicBlock::iterator
MachineBasicBlock::SkipPHIsLabelsAndDebug(MachineBasicBlock::iterator I,
                                          bool SkipPseudoOp) {
  const TargetInstrInfo *TII = getParent()->getSubtarget().getInstrInfo();
  iterator E = end();
  while (I != E && (I->isPHI() || I->isPosition() || I->isDebugInstr() ||
                    (SkipPseudoOp && I->isPseudoProbe()) ||
                    TII->isBasicBlockPrologue(*I)))
    ++I;
      assert((I == E || !I->isInsideBundle()) &&
         "First non-phi / non-label / non-debug "
         "instruction is inside a bundle!");
  return I;
}
MachineBasicBlock::iterator MachineBasicBlock::getFirstTerminator() {
  iterator B = begin(), E = end(), I = E;
  while (I != B && ((--I)->isTerminator() || I->isDebugInstr()))
    ; 
  while (I != E && !I->isTerminator())
    ++I;
  return I;
}
MachineBasicBlock::instr_iterator MachineBasicBlock::getFirstInstrTerminator() {
  instr_iterator B = instr_begin(), E = instr_end(), I = E;
  while (I != B && ((--I)->isTerminator() || I->isDebugInstr()))
    ; 
  while (I != E && !I->isTerminator())
    ++I;
  return I;
}
MachineBasicBlock::iterator
MachineBasicBlock::getFirstNonDebugInstr(bool SkipPseudoOp) {
    return skipDebugInstructionsForward(begin(), end(), SkipPseudoOp);
}
MachineBasicBlock::iterator
MachineBasicBlock::getLastNonDebugInstr(bool SkipPseudoOp) {
    instr_iterator B = instr_begin(), I = instr_end();
  while (I != B) {
    --I;
        if (I->isDebugInstr() || I->isInsideBundle())
      continue;
    if (SkipPseudoOp && I->isPseudoProbe())
      continue;
    return I;
  }
    return end();
}
bool MachineBasicBlock::hasEHPadSuccessor() const {
  for (const MachineBasicBlock *Succ : successors())
    if (Succ->isEHPad())
      return true;
  return false;
}
bool MachineBasicBlock::isEntryBlock() const {
  return getParent()->begin() == getIterator();
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void MachineBasicBlock::dump() const {
  print(dbgs());
}
#endif
bool MachineBasicBlock::mayHaveInlineAsmBr() const {
  for (const MachineBasicBlock *Succ : successors()) {
    if (Succ->isInlineAsmBrIndirectTarget())
      return true;
  }
  return false;
}
bool MachineBasicBlock::isLegalToHoistInto() const {
  if (isReturnBlock() || hasEHPadSuccessor() || mayHaveInlineAsmBr())
    return false;
  return true;
}
StringRef MachineBasicBlock::getName() const {
  if (const BasicBlock *LBB = getBasicBlock())
    return LBB->getName();
  else
    return StringRef("", 0);
}
std::string MachineBasicBlock::getFullName() const {
  std::string Name;
  if (getParent())
    Name = (getParent()->getName() + ":").str();
  if (getBasicBlock())
    Name += getBasicBlock()->getName();
  else
    Name += ("BB" + Twine(getNumber())).str();
  return Name;
}
void MachineBasicBlock::print(raw_ostream &OS, const SlotIndexes *Indexes,
                              bool IsStandalone) const {
  const MachineFunction *MF = getParent();
  if (!MF) {
    OS << "Can't print out MachineBasicBlock because parent MachineFunction"
       << " is null\n";
    return;
  }
  const Function &F = MF->getFunction();
  const Module *M = F.getParent();
  ModuleSlotTracker MST(M);
  MST.incorporateFunction(F);
  print(OS, MST, Indexes, IsStandalone);
}
void MachineBasicBlock::print(raw_ostream &OS, ModuleSlotTracker &MST,
                              const SlotIndexes *Indexes,
                              bool IsStandalone) const {
  const MachineFunction *MF = getParent();
  if (!MF) {
    OS << "Can't print out MachineBasicBlock because parent MachineFunction"
       << " is null\n";
    return;
  }
  if (Indexes && PrintSlotIndexes)
    OS << Indexes->getMBBStartIdx(this) << '\t';
  printName(OS, PrintNameIr | PrintNameAttributes, &MST);
  OS << ":\n";
  const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
  const MachineRegisterInfo &MRI = MF->getRegInfo();
  const TargetInstrInfo &TII = *getParent()->getSubtarget().getInstrInfo();
  bool HasLineAttributes = false;
    if (!pred_empty() && IsStandalone) {
    if (Indexes) OS << '\t';
        OS << "; predecessors: ";
    ListSeparator LS;
    for (auto *Pred : predecessors())
      OS << LS << printMBBReference(*Pred);
    OS << '\n';
    HasLineAttributes = true;
  }
  if (!succ_empty()) {
    if (Indexes) OS << '\t';
        OS.indent(2) << "successors: ";
    ListSeparator LS;
    for (auto I = succ_begin(), E = succ_end(); I != E; ++I) {
      OS << LS << printMBBReference(**I);
      if (!Probs.empty())
        OS << '('
           << format("0x%08" PRIx32, getSuccProbability(I).getNumerator())
           << ')';
    }
    if (!Probs.empty() && IsStandalone) {
            OS << "; ";
      ListSeparator LS;
      for (auto I = succ_begin(), E = succ_end(); I != E; ++I) {
        const BranchProbability &BP = getSuccProbability(I);
        OS << LS << printMBBReference(**I) << '('
           << format("%.2f%%",
                     rint(((double)BP.getNumerator() / BP.getDenominator()) *
                          100.0 * 100.0) /
                         100.0)
           << ')';
      }
    }
    OS << '\n';
    HasLineAttributes = true;
  }
  if (!livein_empty() && MRI.tracksLiveness()) {
    if (Indexes) OS << '\t';
    OS.indent(2) << "liveins: ";
    ListSeparator LS;
    for (const auto &LI : liveins()) {
      OS << LS << printReg(LI.PhysReg, TRI);
      if (!LI.LaneMask.all())
        OS << ":0x" << PrintLaneMask(LI.LaneMask);
    }
    HasLineAttributes = true;
  }
  if (HasLineAttributes)
    OS << '\n';
  bool IsInBundle = false;
  for (const MachineInstr &MI : instrs()) {
    if (Indexes && PrintSlotIndexes) {
      if (Indexes->hasIndex(MI))
        OS << Indexes->getInstructionIndex(MI);
      OS << '\t';
    }
    if (IsInBundle && !MI.isInsideBundle()) {
      OS.indent(2) << "}\n";
      IsInBundle = false;
    }
    OS.indent(IsInBundle ? 4 : 2);
    MI.print(OS, MST, IsStandalone, false, false,
             false, &TII);
    if (!IsInBundle && MI.getFlag(MachineInstr::BundledSucc)) {
      OS << " {";
      IsInBundle = true;
    }
    OS << '\n';
  }
  if (IsInBundle)
    OS.indent(2) << "}\n";
  if (IrrLoopHeaderWeight && IsStandalone) {
    if (Indexes) OS << '\t';
    OS.indent(2) << "; Irreducible loop header weight: "
                 << IrrLoopHeaderWeight.value() << '\n';
  }
}
void MachineBasicBlock::printName(raw_ostream &os, unsigned printNameFlags,
                                  ModuleSlotTracker *moduleSlotTracker) const {
  os << "bb." << getNumber();
  bool hasAttributes = false;
  if (printNameFlags & PrintNameIr) {
    if (const auto *bb = getBasicBlock()) {
      if (bb->hasName()) {
        os << '.' << bb->getName();
      } else {
        hasAttributes = true;
        os << " (";
        int slot = -1;
        if (moduleSlotTracker) {
          slot = moduleSlotTracker->getLocalSlot(bb);
        } else if (bb->getParent()) {
          ModuleSlotTracker tmpTracker(bb->getModule(), false);
          tmpTracker.incorporateFunction(*bb->getParent());
          slot = tmpTracker.getLocalSlot(bb);
        }
        if (slot == -1)
          os << "<ir-block badref>";
        else
          os << (Twine("%ir-block.") + Twine(slot)).str();
      }
    }
  }
  if (printNameFlags & PrintNameAttributes) {
    if (hasAddressTaken()) {
      os << (hasAttributes ? ", " : " (");
      os << "address-taken";
      hasAttributes = true;
    }
    if (isEHPad()) {
      os << (hasAttributes ? ", " : " (");
      os << "landing-pad";
      hasAttributes = true;
    }
    if (isInlineAsmBrIndirectTarget()) {
      os << (hasAttributes ? ", " : " (");
      os << "inlineasm-br-indirect-target";
      hasAttributes = true;
    }
    if (isEHFuncletEntry()) {
      os << (hasAttributes ? ", " : " (");
      os << "ehfunclet-entry";
      hasAttributes = true;
    }
    if (getAlignment() != Align(1)) {
      os << (hasAttributes ? ", " : " (");
      os << "align " << getAlignment().value();
      hasAttributes = true;
    }
    if (getSectionID() != MBBSectionID(0)) {
      os << (hasAttributes ? ", " : " (");
      os << "bbsections ";
      switch (getSectionID().Type) {
      case MBBSectionID::SectionType::Exception:
        os << "Exception";
        break;
      case MBBSectionID::SectionType::Cold:
        os << "Cold";
        break;
      default:
        os << getSectionID().Number;
      }
      hasAttributes = true;
    }
  }
  if (hasAttributes)
    os << ')';
}
void MachineBasicBlock::printAsOperand(raw_ostream &OS,
                                       bool ) const {
  OS << '%';
  printName(OS, 0);
}
void MachineBasicBlock::removeLiveIn(MCPhysReg Reg, LaneBitmask LaneMask) {
  LiveInVector::iterator I = find_if(
      LiveIns, [Reg](const RegisterMaskPair &LI) { return LI.PhysReg == Reg; });
  if (I == LiveIns.end())
    return;
  I->LaneMask &= ~LaneMask;
  if (I->LaneMask.none())
    LiveIns.erase(I);
}
MachineBasicBlock::livein_iterator
MachineBasicBlock::removeLiveIn(MachineBasicBlock::livein_iterator I) {
    LiveInVector::iterator LI = LiveIns.begin() + (I - LiveIns.begin());
  return LiveIns.erase(LI);
}
bool MachineBasicBlock::isLiveIn(MCPhysReg Reg, LaneBitmask LaneMask) const {
  livein_iterator I = find_if(
      LiveIns, [Reg](const RegisterMaskPair &LI) { return LI.PhysReg == Reg; });
  return I != livein_end() && (I->LaneMask & LaneMask).any();
}
void MachineBasicBlock::sortUniqueLiveIns() {
  llvm::sort(LiveIns,
             [](const RegisterMaskPair &LI0, const RegisterMaskPair &LI1) {
               return LI0.PhysReg < LI1.PhysReg;
             });
    LiveInVector::const_iterator I = LiveIns.begin();
  LiveInVector::const_iterator J;
  LiveInVector::iterator Out = LiveIns.begin();
  for (; I != LiveIns.end(); ++Out, I = J) {
    MCRegister PhysReg = I->PhysReg;
    LaneBitmask LaneMask = I->LaneMask;
    for (J = std::next(I); J != LiveIns.end() && J->PhysReg == PhysReg; ++J)
      LaneMask |= J->LaneMask;
    Out->PhysReg = PhysReg;
    Out->LaneMask = LaneMask;
  }
  LiveIns.erase(Out, LiveIns.end());
}
Register
MachineBasicBlock::addLiveIn(MCRegister PhysReg, const TargetRegisterClass *RC) {
  assert(getParent() && "MBB must be inserted in function");
  assert(Register::isPhysicalRegister(PhysReg) && "Expected physreg");
  assert(RC && "Register class is required");
  assert((isEHPad() || this == &getParent()->front()) &&
         "Only the entry block and landing pads can have physreg live ins");
  bool LiveIn = isLiveIn(PhysReg);
  iterator I = SkipPHIsAndLabels(begin()), E = end();
  MachineRegisterInfo &MRI = getParent()->getRegInfo();
  const TargetInstrInfo &TII = *getParent()->getSubtarget().getInstrInfo();
    if (LiveIn)
    for (;I != E && I->isCopy(); ++I)
      if (I->getOperand(1).getReg() == PhysReg) {
        Register VirtReg = I->getOperand(0).getReg();
        if (!MRI.constrainRegClass(VirtReg, RC))
          llvm_unreachable("Incompatible live-in register class.");
        return VirtReg;
      }
    Register VirtReg = MRI.createVirtualRegister(RC);
  BuildMI(*this, I, DebugLoc(), TII.get(TargetOpcode::COPY), VirtReg)
    .addReg(PhysReg, RegState::Kill);
  if (!LiveIn)
    addLiveIn(PhysReg);
  return VirtReg;
}
void MachineBasicBlock::moveBefore(MachineBasicBlock *NewAfter) {
  getParent()->splice(NewAfter->getIterator(), getIterator());
}
void MachineBasicBlock::moveAfter(MachineBasicBlock *NewBefore) {
  getParent()->splice(++NewBefore->getIterator(), getIterator());
}
void MachineBasicBlock::updateTerminator(
    MachineBasicBlock *PreviousLayoutSuccessor) {
  LLVM_DEBUG(dbgs() << "Updating terminators on " << printMBBReference(*this)
                    << "\n");
  const TargetInstrInfo *TII = getParent()->getSubtarget().getInstrInfo();
    if (this->succ_empty())
    return;
  MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
  SmallVector<MachineOperand, 4> Cond;
  DebugLoc DL = findBranchDebugLoc();
  bool B = TII->analyzeBranch(*this, TBB, FBB, Cond);
  (void) B;
  assert(!B && "UpdateTerminators requires analyzable predecessors!");
  if (Cond.empty()) {
    if (TBB) {
                  if (isLayoutSuccessor(TBB))
        TII->removeBranch(*this);
    } else {
            
                              if (!PreviousLayoutSuccessor || !isSuccessor(PreviousLayoutSuccessor) ||
          PreviousLayoutSuccessor->isEHPad())
        return;
                  if (!isLayoutSuccessor(PreviousLayoutSuccessor))
        TII->insertBranch(*this, PreviousLayoutSuccessor, nullptr, Cond, DL);
    }
    return;
  }
  if (FBB) {
                if (isLayoutSuccessor(TBB)) {
      if (TII->reverseBranchCondition(Cond))
        return;
      TII->removeBranch(*this);
      TII->insertBranch(*this, FBB, nullptr, Cond, DL);
    } else if (isLayoutSuccessor(FBB)) {
      TII->removeBranch(*this);
      TII->insertBranch(*this, TBB, nullptr, Cond, DL);
    }
    return;
  }
    assert(PreviousLayoutSuccessor);
  assert(!PreviousLayoutSuccessor->isEHPad());
  assert(isSuccessor(PreviousLayoutSuccessor));
  if (PreviousLayoutSuccessor == TBB) {
                TII->removeBranch(*this);
    if (!isLayoutSuccessor(TBB)) {
      Cond.clear();
      TII->insertBranch(*this, TBB, nullptr, Cond, DL);
    }
    return;
  }
    if (isLayoutSuccessor(TBB)) {
    if (TII->reverseBranchCondition(Cond)) {
            Cond.clear();
      TII->insertBranch(*this, PreviousLayoutSuccessor, nullptr, Cond, DL);
      return;
    }
    TII->removeBranch(*this);
    TII->insertBranch(*this, PreviousLayoutSuccessor, nullptr, Cond, DL);
  } else if (!isLayoutSuccessor(PreviousLayoutSuccessor)) {
    TII->removeBranch(*this);
    TII->insertBranch(*this, TBB, PreviousLayoutSuccessor, Cond, DL);
  }
}
void MachineBasicBlock::validateSuccProbs() const {
#ifndef NDEBUG
  int64_t Sum = 0;
  for (auto Prob : Probs)
    Sum += Prob.getNumerator();
        assert((uint64_t)std::abs(Sum - BranchProbability::getDenominator()) <=
             Probs.size() &&
         "The sum of successors's probabilities exceeds one.");
#endif }
void MachineBasicBlock::addSuccessor(MachineBasicBlock *Succ,
                                     BranchProbability Prob) {
      if (!(Probs.empty() && !Successors.empty()))
    Probs.push_back(Prob);
  Successors.push_back(Succ);
  Succ->addPredecessor(this);
}
void MachineBasicBlock::addSuccessorWithoutProb(MachineBasicBlock *Succ) {
        Probs.clear();
  Successors.push_back(Succ);
  Succ->addPredecessor(this);
}
void MachineBasicBlock::splitSuccessor(MachineBasicBlock *Old,
                                       MachineBasicBlock *New,
                                       bool NormalizeSuccProbs) {
  succ_iterator OldI = llvm::find(successors(), Old);
  assert(OldI != succ_end() && "Old is not a successor of this block!");
  assert(!llvm::is_contained(successors(), New) &&
         "New is already a successor of this block!");
            addSuccessor(New, Probs.empty() ? BranchProbability::getUnknown()
                                  : *getProbabilityIterator(OldI));
  if (NormalizeSuccProbs)
    normalizeSuccProbs();
}
void MachineBasicBlock::removeSuccessor(MachineBasicBlock *Succ,
                                        bool NormalizeSuccProbs) {
  succ_iterator I = find(Successors, Succ);
  removeSuccessor(I, NormalizeSuccProbs);
}
MachineBasicBlock::succ_iterator
MachineBasicBlock::removeSuccessor(succ_iterator I, bool NormalizeSuccProbs) {
  assert(I != Successors.end() && "Not a current successor!");
      if (!Probs.empty()) {
    probability_iterator WI = getProbabilityIterator(I);
    Probs.erase(WI);
    if (NormalizeSuccProbs)
      normalizeSuccProbs();
  }
  (*I)->removePredecessor(this);
  return Successors.erase(I);
}
void MachineBasicBlock::replaceSuccessor(MachineBasicBlock *Old,
                                         MachineBasicBlock *New) {
  if (Old == New)
    return;
  succ_iterator E = succ_end();
  succ_iterator NewI = E;
  succ_iterator OldI = E;
  for (succ_iterator I = succ_begin(); I != E; ++I) {
    if (*I == Old) {
      OldI = I;
      if (NewI != E)
        break;
    }
    if (*I == New) {
      NewI = I;
      if (OldI != E)
        break;
    }
  }
  assert(OldI != E && "Old is not a successor of this block");
    if (NewI == E) {
    Old->removePredecessor(this);
    New->addPredecessor(this);
    *OldI = New;
    return;
  }
      if (!Probs.empty()) {
    auto ProbIter = getProbabilityIterator(NewI);
    if (!ProbIter->isUnknown())
      *ProbIter += *getProbabilityIterator(OldI);
  }
  removeSuccessor(OldI);
}
void MachineBasicBlock::copySuccessor(MachineBasicBlock *Orig,
                                      succ_iterator I) {
  if (!Orig->Probs.empty())
    addSuccessor(*I, Orig->getSuccProbability(I));
  else
    addSuccessorWithoutProb(*I);
}
void MachineBasicBlock::addPredecessor(MachineBasicBlock *Pred) {
  Predecessors.push_back(Pred);
}
void MachineBasicBlock::removePredecessor(MachineBasicBlock *Pred) {
  pred_iterator I = find(Predecessors, Pred);
  assert(I != Predecessors.end() && "Pred is not a predecessor of this block!");
  Predecessors.erase(I);
}
void MachineBasicBlock::transferSuccessors(MachineBasicBlock *FromMBB) {
  if (this == FromMBB)
    return;
  while (!FromMBB->succ_empty()) {
    MachineBasicBlock *Succ = *FromMBB->succ_begin();
            if (!FromMBB->Probs.empty()) {
      auto Prob = *FromMBB->Probs.begin();
      addSuccessor(Succ, Prob);
    } else
      addSuccessorWithoutProb(Succ);
    FromMBB->removeSuccessor(Succ);
  }
}
void
MachineBasicBlock::transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB) {
  if (this == FromMBB)
    return;
  while (!FromMBB->succ_empty()) {
    MachineBasicBlock *Succ = *FromMBB->succ_begin();
    if (!FromMBB->Probs.empty()) {
      auto Prob = *FromMBB->Probs.begin();
      addSuccessor(Succ, Prob);
    } else
      addSuccessorWithoutProb(Succ);
    FromMBB->removeSuccessor(Succ);
        Succ->replacePhiUsesWith(FromMBB, this);
  }
  normalizeSuccProbs();
}
bool MachineBasicBlock::isPredecessor(const MachineBasicBlock *MBB) const {
  return is_contained(predecessors(), MBB);
}
bool MachineBasicBlock::isSuccessor(const MachineBasicBlock *MBB) const {
  return is_contained(successors(), MBB);
}
bool MachineBasicBlock::isLayoutSuccessor(const MachineBasicBlock *MBB) const {
  MachineFunction::const_iterator I(this);
  return std::next(I) == MachineFunction::const_iterator(MBB);
}
const MachineBasicBlock *MachineBasicBlock::getSingleSuccessor() const {
  return Successors.size() == 1 ? Successors[0] : nullptr;
}
MachineBasicBlock *MachineBasicBlock::getFallThrough() {
  MachineFunction::iterator Fallthrough = getIterator();
  ++Fallthrough;
    if (Fallthrough == getParent()->end())
    return nullptr;
    if (!isSuccessor(&*Fallthrough))
    return nullptr;
    MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
  SmallVector<MachineOperand, 4> Cond;
  const TargetInstrInfo *TII = getParent()->getSubtarget().getInstrInfo();
  if (TII->analyzeBranch(*this, TBB, FBB, Cond)) {
                        return (empty() || !back().isBarrier() || TII->isPredicated(back()))
               ? &*Fallthrough
               : nullptr;
  }
    if (!TBB) return &*Fallthrough;
      if (MachineFunction::iterator(TBB) == Fallthrough ||
      MachineFunction::iterator(FBB) == Fallthrough)
    return &*Fallthrough;
      if (Cond.empty()) return nullptr;
      return (FBB == nullptr) ? &*Fallthrough : nullptr;
}
bool MachineBasicBlock::canFallThrough() {
  return getFallThrough() != nullptr;
}
MachineBasicBlock *MachineBasicBlock::splitAt(MachineInstr &MI,
                                              bool UpdateLiveIns,
                                              LiveIntervals *LIS) {
  MachineBasicBlock::iterator SplitPoint(&MI);
  ++SplitPoint;
  if (SplitPoint == end()) {
        return this;
  }
  MachineFunction *MF = getParent();
  LivePhysRegs LiveRegs;
  if (UpdateLiveIns) {
            MachineBasicBlock::iterator Prev(&MI);
    LiveRegs.init(*MF->getSubtarget().getRegisterInfo());
    LiveRegs.addLiveOuts(*this);
    for (auto I = rbegin(), E = Prev.getReverse(); I != E; ++I)
      LiveRegs.stepBackward(*I);
  }
  MachineBasicBlock *SplitBB = MF->CreateMachineBasicBlock(getBasicBlock());
  MF->insert(++MachineFunction::iterator(this), SplitBB);
  SplitBB->splice(SplitBB->begin(), this, SplitPoint, end());
  SplitBB->transferSuccessorsAndUpdatePHIs(this);
  addSuccessor(SplitBB);
  if (UpdateLiveIns)
    addLiveIns(*SplitBB, LiveRegs);
  if (LIS)
    LIS->insertMBBInMaps(SplitBB);
  return SplitBB;
}
MachineBasicBlock *MachineBasicBlock::SplitCriticalEdge(
    MachineBasicBlock *Succ, Pass &P,
    std::vector<SparseBitVector<>> *LiveInSets) {
  if (!canSplitCriticalEdge(Succ))
    return nullptr;
  MachineFunction *MF = getParent();
  MachineBasicBlock *PrevFallthrough = getNextNode();
  DebugLoc DL;  
  MachineBasicBlock *NMBB = MF->CreateMachineBasicBlock();
  MF->insert(std::next(MachineFunction::iterator(this)), NMBB);
  LLVM_DEBUG(dbgs() << "Splitting critical edge: " << printMBBReference(*this)
                    << " -- " << printMBBReference(*NMBB) << " -- "
                    << printMBBReference(*Succ) << '\n');
  LiveIntervals *LIS = P.getAnalysisIfAvailable<LiveIntervals>();
  SlotIndexes *Indexes = P.getAnalysisIfAvailable<SlotIndexes>();
  if (LIS)
    LIS->insertMBBInMaps(NMBB);
  else if (Indexes)
    Indexes->insertMBBInMaps(NMBB);
        LiveVariables *LV = P.getAnalysisIfAvailable<LiveVariables>();
    SmallVector<Register, 4> KilledRegs;
  if (LV)
    for (MachineInstr &MI :
         llvm::make_range(getFirstInstrTerminator(), instr_end())) {
      for (MachineOperand &MO : MI.operands()) {
        if (!MO.isReg() || MO.getReg() == 0 || !MO.isUse() || !MO.isKill() ||
            MO.isUndef())
          continue;
        Register Reg = MO.getReg();
        if (Register::isPhysicalRegister(Reg) ||
            LV->getVarInfo(Reg).removeKill(MI)) {
          KilledRegs.push_back(Reg);
          LLVM_DEBUG(dbgs() << "Removing terminator kill: " << MI);
          MO.setIsKill(false);
        }
      }
    }
  SmallVector<Register, 4> UsedRegs;
  if (LIS) {
    for (MachineInstr &MI :
         llvm::make_range(getFirstInstrTerminator(), instr_end())) {
      for (const MachineOperand &MO : MI.operands()) {
        if (!MO.isReg() || MO.getReg() == 0)
          continue;
        Register Reg = MO.getReg();
        if (!is_contained(UsedRegs, Reg))
          UsedRegs.push_back(Reg);
      }
    }
  }
  ReplaceUsesOfBlockWith(Succ, NMBB);
      SmallVector<MachineInstr*, 4> Terminators;
  if (Indexes) {
    for (MachineInstr &MI :
         llvm::make_range(getFirstInstrTerminator(), instr_end()))
      Terminators.push_back(&MI);
  }
      if (Succ == PrevFallthrough)
    PrevFallthrough = NMBB;
  updateTerminator(PrevFallthrough);
  if (Indexes) {
    SmallVector<MachineInstr*, 4> NewTerminators;
    for (MachineInstr &MI :
         llvm::make_range(getFirstInstrTerminator(), instr_end()))
      NewTerminators.push_back(&MI);
    for (MachineInstr *Terminator : Terminators) {
      if (!is_contained(NewTerminators, Terminator))
        Indexes->removeMachineInstrFromMaps(*Terminator);
    }
  }
    NMBB->addSuccessor(Succ);
  if (!NMBB->isLayoutSuccessor(Succ)) {
    SmallVector<MachineOperand, 4> Cond;
    const TargetInstrInfo *TII = getParent()->getSubtarget().getInstrInfo();
    TII->insertBranch(*NMBB, Succ, nullptr, Cond, DL);
    if (Indexes) {
      for (MachineInstr &MI : NMBB->instrs()) {
                        if (Indexes->hasIndex(MI))
          Indexes->removeMachineInstrFromMaps(MI);
        Indexes->insertMachineInstrInMaps(MI);
      }
    }
  }
    Succ->replacePhiUsesWith(this, NMBB);
    for (const auto &LI : Succ->liveins())
    NMBB->addLiveIn(LI);
    const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
  if (LV) {
        while (!KilledRegs.empty()) {
      Register Reg = KilledRegs.pop_back_val();
      for (instr_iterator I = instr_end(), E = instr_begin(); I != E;) {
        if (!(--I)->addRegisterKilled(Reg, TRI,  false))
          continue;
        if (Register::isVirtualRegister(Reg))
          LV->getVarInfo(Reg).Kills.push_back(&*I);
        LLVM_DEBUG(dbgs() << "Restored terminator kill: " << *I);
        break;
      }
    }
        if (LiveInSets != nullptr)
      LV->addNewBlock(NMBB, this, Succ, *LiveInSets);
    else
      LV->addNewBlock(NMBB, this, Succ);
  }
  if (LIS) {
                        
    bool isLastMBB =
      std::next(MachineFunction::iterator(NMBB)) == getParent()->end();
    SlotIndex StartIndex = Indexes->getMBBEndIdx(this);
    SlotIndex PrevIndex = StartIndex.getPrevSlot();
    SlotIndex EndIndex = Indexes->getMBBEndIdx(NMBB);
        SmallSet<Register, 8> PHISrcRegs;
    for (MachineBasicBlock::instr_iterator
         I = Succ->instr_begin(), E = Succ->instr_end();
         I != E && I->isPHI(); ++I) {
      for (unsigned ni = 1, ne = I->getNumOperands(); ni != ne; ni += 2) {
        if (I->getOperand(ni+1).getMBB() == NMBB) {
          MachineOperand &MO = I->getOperand(ni);
          Register Reg = MO.getReg();
          PHISrcRegs.insert(Reg);
          if (MO.isUndef())
            continue;
          LiveInterval &LI = LIS->getInterval(Reg);
          VNInfo *VNI = LI.getVNInfoAt(PrevIndex);
          assert(VNI &&
                 "PHI sources should be live out of their predecessors.");
          LI.addSegment(LiveInterval::Segment(StartIndex, EndIndex, VNI));
        }
      }
    }
    MachineRegisterInfo *MRI = &getParent()->getRegInfo();
    for (unsigned i = 0, e = MRI->getNumVirtRegs(); i != e; ++i) {
      Register Reg = Register::index2VirtReg(i);
      if (PHISrcRegs.count(Reg) || !LIS->hasInterval(Reg))
        continue;
      LiveInterval &LI = LIS->getInterval(Reg);
      if (!LI.liveAt(PrevIndex))
        continue;
      bool isLiveOut = LI.liveAt(LIS->getMBBStartIdx(Succ));
      if (isLiveOut && isLastMBB) {
        VNInfo *VNI = LI.getVNInfoAt(PrevIndex);
        assert(VNI && "LiveInterval should have VNInfo where it is live.");
        LI.addSegment(LiveInterval::Segment(StartIndex, EndIndex, VNI));
      } else if (!isLiveOut && !isLastMBB) {
        LI.removeSegment(StartIndex, EndIndex);
      }
    }
            LIS->repairIntervalsInRange(this, getFirstTerminator(), end(), UsedRegs);
  }
  if (MachineDominatorTree *MDT =
          P.getAnalysisIfAvailable<MachineDominatorTree>())
    MDT->recordSplitCriticalEdge(this, Succ, NMBB);
  if (MachineLoopInfo *MLI = P.getAnalysisIfAvailable<MachineLoopInfo>())
    if (MachineLoop *TIL = MLI->getLoopFor(this)) {
                  if (MachineLoop *DestLoop = MLI->getLoopFor(Succ)) {
        if (TIL == DestLoop) {
                    DestLoop->addBasicBlockToLoop(NMBB, MLI->getBase());
        } else if (TIL->contains(DestLoop)) {
                    TIL->addBasicBlockToLoop(NMBB, MLI->getBase());
        } else if (DestLoop->contains(TIL)) {
                    DestLoop->addBasicBlockToLoop(NMBB, MLI->getBase());
        } else {
                                                  assert(DestLoop->getHeader() == Succ &&
                 "Should not create irreducible loops!");
          if (MachineLoop *P = DestLoop->getParentLoop())
            P->addBasicBlockToLoop(NMBB, MLI->getBase());
        }
      }
    }
  return NMBB;
}
bool MachineBasicBlock::canSplitCriticalEdge(
    const MachineBasicBlock *Succ) const {
      if (Succ->isEHPad())
    return false;
      if (Succ->isInlineAsmBrIndirectTarget())
    return false;
  const MachineFunction *MF = getParent();
      if (MF->getTarget().requiresStructuredCFG())
    return false;
      const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
  MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
  SmallVector<MachineOperand, 4> Cond;
    if (TII->analyzeBranch(*const_cast<MachineBasicBlock *>(this), TBB, FBB, Cond,
                          false))
    return false;
          if (TBB && TBB == FBB) {
    LLVM_DEBUG(dbgs() << "Won't split critical edge after degenerate "
                      << printMBBReference(*this) << '\n');
    return false;
  }
  return true;
}
static void unbundleSingleMI(MachineInstr *MI) {
    if (MI->isBundledWithSucc() && !MI->isBundledWithPred())
    MI->unbundleFromSucc();
    if (MI->isBundledWithPred() && !MI->isBundledWithSucc())
    MI->unbundleFromPred();
    }
MachineBasicBlock::instr_iterator
MachineBasicBlock::erase(MachineBasicBlock::instr_iterator I) {
  unbundleSingleMI(&*I);
  return Insts.erase(I);
}
MachineInstr *MachineBasicBlock::remove_instr(MachineInstr *MI) {
  unbundleSingleMI(MI);
  MI->clearFlag(MachineInstr::BundledPred);
  MI->clearFlag(MachineInstr::BundledSucc);
  return Insts.remove(MI);
}
MachineBasicBlock::instr_iterator
MachineBasicBlock::insert(instr_iterator I, MachineInstr *MI) {
  assert(!MI->isBundledWithPred() && !MI->isBundledWithSucc() &&
         "Cannot insert instruction with bundle flags");
    if (I != instr_end() && I->isBundledWithPred()) {
    MI->setFlag(MachineInstr::BundledPred);
    MI->setFlag(MachineInstr::BundledSucc);
  }
  return Insts.insert(I, MI);
}
MachineBasicBlock *MachineBasicBlock::removeFromParent() {
  assert(getParent() && "Not embedded in a function!");
  getParent()->remove(this);
  return this;
}
void MachineBasicBlock::eraseFromParent() {
  assert(getParent() && "Not embedded in a function!");
  getParent()->erase(this);
}
void MachineBasicBlock::ReplaceUsesOfBlockWith(MachineBasicBlock *Old,
                                               MachineBasicBlock *New) {
  assert(Old != New && "Cannot replace self with self!");
  MachineBasicBlock::instr_iterator I = instr_end();
  while (I != instr_begin()) {
    --I;
    if (!I->isTerminator()) break;
            for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
      if (I->getOperand(i).isMBB() &&
          I->getOperand(i).getMBB() == Old)
        I->getOperand(i).setMBB(New);
  }
    replaceSuccessor(Old, New);
}
void MachineBasicBlock::replacePhiUsesWith(MachineBasicBlock *Old,
                                           MachineBasicBlock *New) {
  for (MachineInstr &MI : phis())
    for (unsigned i = 2, e = MI.getNumOperands() + 1; i != e; i += 2) {
      MachineOperand &MO = MI.getOperand(i);
      if (MO.getMBB() == Old)
        MO.setMBB(New);
    }
}
DebugLoc
MachineBasicBlock::findDebugLoc(instr_iterator MBBI) {
    MBBI = skipDebugInstructionsForward(MBBI, instr_end());
  if (MBBI != instr_end())
    return MBBI->getDebugLoc();
  return {};
}
DebugLoc MachineBasicBlock::rfindDebugLoc(reverse_instr_iterator MBBI) {
    MBBI = skipDebugInstructionsBackward(MBBI, instr_rbegin());
  if (!MBBI->isDebugInstr())
    return MBBI->getDebugLoc();
  return {};
}
DebugLoc MachineBasicBlock::findPrevDebugLoc(instr_iterator MBBI) {
  if (MBBI == instr_begin()) return {};
    MBBI = prev_nodbg(MBBI, instr_begin());
  if (!MBBI->isDebugInstr()) return MBBI->getDebugLoc();
  return {};
}
DebugLoc MachineBasicBlock::rfindPrevDebugLoc(reverse_instr_iterator MBBI) {
  if (MBBI == instr_rend())
    return {};
    MBBI = next_nodbg(MBBI, instr_rend());
  if (MBBI != instr_rend())
    return MBBI->getDebugLoc();
  return {};
}
DebugLoc
MachineBasicBlock::findBranchDebugLoc() {
  DebugLoc DL;
  auto TI = getFirstTerminator();
  while (TI != end() && !TI->isBranch())
    ++TI;
  if (TI != end()) {
    DL = TI->getDebugLoc();
    for (++TI ; TI != end() ; ++TI)
      if (TI->isBranch())
        DL = DILocation::getMergedLocation(DL, TI->getDebugLoc());
  }
  return DL;
}
BranchProbability
MachineBasicBlock::getSuccProbability(const_succ_iterator Succ) const {
  if (Probs.empty())
    return BranchProbability(1, succ_size());
  const auto &Prob = *getProbabilityIterator(Succ);
  if (Prob.isUnknown()) {
            unsigned KnownProbNum = 0;
    auto Sum = BranchProbability::getZero();
    for (const auto &P : Probs) {
      if (!P.isUnknown()) {
        Sum += P;
        KnownProbNum++;
      }
    }
    return Sum.getCompl() / (Probs.size() - KnownProbNum);
  } else
    return Prob;
}
void MachineBasicBlock::setSuccProbability(succ_iterator I,
                                           BranchProbability Prob) {
  assert(!Prob.isUnknown());
  if (Probs.empty())
    return;
  *getProbabilityIterator(I) = Prob;
}
MachineBasicBlock::const_probability_iterator
MachineBasicBlock::getProbabilityIterator(
    MachineBasicBlock::const_succ_iterator I) const {
  assert(Probs.size() == Successors.size() && "Async probability list!");
  const size_t index = std::distance(Successors.begin(), I);
  assert(index < Probs.size() && "Not a current successor!");
  return Probs.begin() + index;
}
MachineBasicBlock::probability_iterator
MachineBasicBlock::getProbabilityIterator(MachineBasicBlock::succ_iterator I) {
  assert(Probs.size() == Successors.size() && "Async probability list!");
  const size_t index = std::distance(Successors.begin(), I);
  assert(index < Probs.size() && "Not a current successor!");
  return Probs.begin() + index;
}
MachineBasicBlock::LivenessQueryResult
MachineBasicBlock::computeRegisterLiveness(const TargetRegisterInfo *TRI,
                                           MCRegister Reg, const_iterator Before,
                                           unsigned Neighborhood) const {
  unsigned N = Neighborhood;
    const_iterator I(Before);
  for (; I != end() && N > 0; ++I) {
    if (I->isDebugOrPseudoInstr())
      continue;
    --N;
    PhysRegInfo Info = AnalyzePhysRegInBundle(*I, Reg, TRI);
        if (Info.Read)
      return LQR_Live;
        if (Info.FullyDefined || Info.Clobbered)
      return LQR_Dead;
  }
      if (I == end()) {
    for (MachineBasicBlock *S : successors()) {
      for (const MachineBasicBlock::RegisterMaskPair &LI : S->liveins()) {
        if (TRI->regsOverlap(LI.PhysReg, Reg))
          return LQR_Live;
      }
    }
    return LQR_Dead;
  }
  N = Neighborhood;
    I = const_iterator(Before);
    if (I != begin()) {
    do {
      --I;
      if (I->isDebugOrPseudoInstr())
        continue;
      --N;
      PhysRegInfo Info = AnalyzePhysRegInBundle(*I, Reg, TRI);
      
            if (Info.DeadDef)
        return LQR_Dead;
            if (Info.Defined) {
        if (!Info.PartialDeadDef)
          return LQR_Live;
                                        break;
      }
            if (Info.Killed || Info.Clobbered)
        return LQR_Dead;
            if (Info.Read)
        return LQR_Live;
    } while (I != begin() && N > 0);
  }
      while (I != begin() && std::prev(I)->isDebugOrPseudoInstr())
    --I;
    if (I == begin()) {
        for (const MachineBasicBlock::RegisterMaskPair &LI : liveins())
      if (TRI->regsOverlap(LI.PhysReg, Reg))
        return LQR_Live;
    return LQR_Dead;
  }
    return LQR_Unknown;
}
const uint32_t *
MachineBasicBlock::getBeginClobberMask(const TargetRegisterInfo *TRI) const {
    return isEHFuncletEntry() ? TRI->getNoPreservedMask() : nullptr;
}
const uint32_t *
MachineBasicBlock::getEndClobberMask(const TargetRegisterInfo *TRI) const {
        return isReturnBlock() && !succ_empty() ? TRI->getNoPreservedMask() : nullptr;
}
void MachineBasicBlock::clearLiveIns() {
  LiveIns.clear();
}
MachineBasicBlock::livein_iterator MachineBasicBlock::livein_begin() const {
  assert(getParent()->getProperties().hasProperty(
      MachineFunctionProperties::Property::TracksLiveness) &&
      "Liveness information is accurate");
  return LiveIns.begin();
}
MachineBasicBlock::liveout_iterator MachineBasicBlock::liveout_begin() const {
  const MachineFunction &MF = *getParent();
  assert(MF.getProperties().hasProperty(
      MachineFunctionProperties::Property::TracksLiveness) &&
      "Liveness information is accurate");
  const TargetLowering &TLI = *MF.getSubtarget().getTargetLowering();
  MCPhysReg ExceptionPointer = 0, ExceptionSelector = 0;
  if (MF.getFunction().hasPersonalityFn()) {
    auto PersonalityFn = MF.getFunction().getPersonalityFn();
    ExceptionPointer = TLI.getExceptionPointerRegister(PersonalityFn);
    ExceptionSelector = TLI.getExceptionSelectorRegister(PersonalityFn);
  }
  return liveout_iterator(*this, ExceptionPointer, ExceptionSelector, false);
}
bool MachineBasicBlock::sizeWithoutDebugLargerThan(unsigned Limit) const {
  unsigned Cntr = 0;
  auto R = instructionsWithoutDebug(begin(), end());
  for (auto I = R.begin(), E = R.end(); I != E; ++I) {
    if (++Cntr > Limit)
      return true;
  }
  return false;
}
const MBBSectionID MBBSectionID::ColdSectionID(MBBSectionID::SectionType::Cold);
const MBBSectionID
    MBBSectionID::ExceptionSectionID(MBBSectionID::SectionType::Exception);