//===- lib/CodeGen/MachineInstr.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
//
//===----------------------------------------------------------------------===//
//
// Methods common to all machine instructions.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/CodeGen/LiveRegUnits.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineInstrBundle.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/CodeGen/Register.h"
#include "llvm/CodeGen/StackMaps.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/CodeGenTypes/LowLevelType.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSlotTracker.h"
#include "llvm/IR/Operator.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstring>
#include <utility>

using namespace llvm;

static cl::opt<bool>
    PrintMIAddrs("print-mi-addrs", cl::Hidden,
                 cl::desc("Print addresses of MachineInstrs when dumping"));

static const MachineFunction *getMFIfAvailable(const MachineInstr &MI) {
  if (const MachineBasicBlock *MBB = MI.getParent())
    if (const MachineFunction *MF = MBB->getParent())
      return MF;
  return nullptr;
}

// Try to crawl up to the machine function and get TRI/MRI/TII from it.
static void tryToGetTargetInfo(const MachineInstr &MI,
                               const TargetRegisterInfo *&TRI,
                               const MachineRegisterInfo *&MRI,
                               const TargetInstrInfo *&TII) {

  if (const MachineFunction *MF = getMFIfAvailable(MI)) {
    TRI = MF->getSubtarget().getRegisterInfo();
    MRI = &MF->getRegInfo();
    TII = MF->getSubtarget().getInstrInfo();
  }
}

void MachineInstr::addImplicitDefUseOperands(MachineFunction &MF) {
  for (MCPhysReg ImpDef : MCID->implicit_defs())
    addOperand(MF, MachineOperand::CreateReg(ImpDef, true, true));
  for (MCPhysReg ImpUse : MCID->implicit_uses())
    addOperand(MF, MachineOperand::CreateReg(ImpUse, false, true));
}

/// MachineInstr ctor - This constructor creates a MachineInstr and adds the
/// implicit operands. It reserves space for the number of operands specified by
/// the MCInstrDesc.
MachineInstr::MachineInstr(MachineFunction &MF, const MCInstrDesc &TID,
                           DebugLoc DL, bool NoImp)
    : MCID(&TID), NumOperands(0), Flags(0), AsmPrinterFlags(0),
      DbgLoc(std::move(DL)), DebugInstrNum(0), Opcode(TID.Opcode) {
  assert(DbgLoc.hasTrivialDestructor() && "Expected trivial destructor");

  // Reserve space for the expected number of operands.
  if (unsigned NumOps = MCID->getNumOperands() + MCID->implicit_defs().size() +
                        MCID->implicit_uses().size()) {
    CapOperands = OperandCapacity::get(NumOps);
    Operands = MF.allocateOperandArray(CapOperands);
  }

  if (!NoImp)
    addImplicitDefUseOperands(MF);
}

/// MachineInstr ctor - Copies MachineInstr arg exactly.
/// Does not copy the number from debug instruction numbering, to preserve
/// uniqueness.
MachineInstr::MachineInstr(MachineFunction &MF, const MachineInstr &MI)
    : MCID(&MI.getDesc()), NumOperands(0), Flags(0), AsmPrinterFlags(0),
      Info(MI.Info), DbgLoc(MI.getDebugLoc()), DebugInstrNum(0),
      Opcode(MI.getOpcode()) {
  assert(DbgLoc.hasTrivialDestructor() && "Expected trivial destructor");

  CapOperands = OperandCapacity::get(MI.getNumOperands());
  Operands = MF.allocateOperandArray(CapOperands);

  // Copy operands.
  for (const MachineOperand &MO : MI.operands())
    addOperand(MF, MO);

  // Replicate ties between the operands, which addOperand was not
  // able to do reliably.
  for (unsigned i = 0, e = getNumOperands(); i < e; ++i) {
    MachineOperand &NewMO = getOperand(i);
    const MachineOperand &OrigMO = MI.getOperand(i);
    NewMO.TiedTo = OrigMO.TiedTo;
  }

  // Copy all the sensible flags.
  setFlags(MI.Flags);
}

void MachineInstr::setDesc(const MCInstrDesc &TID) {
  if (getParent())
    getMF()->handleChangeDesc(*this, TID);
  MCID = &TID;
  Opcode = TID.Opcode;
}

void MachineInstr::moveBefore(MachineInstr *MovePos) {
  MovePos->getParent()->splice(MovePos, getParent(), getIterator());
}

/// getRegInfo - If this instruction is embedded into a MachineFunction,
/// return the MachineRegisterInfo object for the current function, otherwise
/// return null.
MachineRegisterInfo *MachineInstr::getRegInfo() {
  if (MachineBasicBlock *MBB = getParent())
    return &MBB->getParent()->getRegInfo();
  return nullptr;
}

const MachineRegisterInfo *MachineInstr::getRegInfo() const {
  if (const MachineBasicBlock *MBB = getParent())
    return &MBB->getParent()->getRegInfo();
  return nullptr;
}

void MachineInstr::removeRegOperandsFromUseLists(MachineRegisterInfo &MRI) {
  for (MachineOperand &MO : operands())
    if (MO.isReg())
      MRI.removeRegOperandFromUseList(&MO);
}

void MachineInstr::addRegOperandsToUseLists(MachineRegisterInfo &MRI) {
  for (MachineOperand &MO : operands())
    if (MO.isReg())
      MRI.addRegOperandToUseList(&MO);
}

void MachineInstr::addOperand(const MachineOperand &Op) {
  MachineBasicBlock *MBB = getParent();
  assert(MBB && "Use MachineInstrBuilder to add operands to dangling instrs");
  MachineFunction *MF = MBB->getParent();
  assert(MF && "Use MachineInstrBuilder to add operands to dangling instrs");
  addOperand(*MF, Op);
}

/// Move NumOps MachineOperands from Src to Dst, with support for overlapping
/// ranges. If MRI is non-null also update use-def chains.
static void moveOperands(MachineOperand *Dst, MachineOperand *Src,
                         unsigned NumOps, MachineRegisterInfo *MRI) {
  if (MRI)
    return MRI->moveOperands(Dst, Src, NumOps);
  // MachineOperand is a trivially copyable type so we can just use memmove.
  assert(Dst && Src && "Unknown operands");
  std::memmove(Dst, Src, NumOps * sizeof(MachineOperand));
}

/// addOperand - Add the specified operand to the instruction.  If it is an
/// implicit operand, it is added to the end of the operand list.  If it is
/// an explicit operand it is added at the end of the explicit operand list
/// (before the first implicit operand).
void MachineInstr::addOperand(MachineFunction &MF, const MachineOperand &Op) {
  assert(isUInt<LLVM_MI_NUMOPERANDS_BITS>(NumOperands + 1) &&
         "Cannot add more operands.");
  assert(MCID && "Cannot add operands before providing an instr descriptor");

  // Check if we're adding one of our existing operands.
  if (&Op >= Operands && &Op < Operands + NumOperands) {
    // This is unusual: MI->addOperand(MI->getOperand(i)).
    // If adding Op requires reallocating or moving existing operands around,
    // the Op reference could go stale. Support it by copying Op.
    MachineOperand CopyOp(Op);
    return addOperand(MF, CopyOp);
  }

  // Find the insert location for the new operand.  Implicit registers go at
  // the end, everything else goes before the implicit regs.
  //
  // FIXME: Allow mixed explicit and implicit operands on inline asm.
  // InstrEmitter::EmitSpecialNode() is marking inline asm clobbers as
  // implicit-defs, but they must not be moved around.  See the FIXME in
  // InstrEmitter.cpp.
  unsigned OpNo = getNumOperands();
  bool isImpReg = Op.isReg() && Op.isImplicit();
  if (!isImpReg && !isInlineAsm()) {
    while (OpNo && Operands[OpNo-1].isReg() && Operands[OpNo-1].isImplicit()) {
      --OpNo;
      assert(!Operands[OpNo].isTied() && "Cannot move tied operands");
    }
  }

  // OpNo now points as the desired insertion point.  Unless this is a variadic
  // instruction, only implicit regs are allowed beyond MCID->getNumOperands().
  // RegMask operands go between the explicit and implicit operands.
  MachineRegisterInfo *MRI = getRegInfo();

  // Determine if the Operands array needs to be reallocated.
  // Save the old capacity and operand array.
  OperandCapacity OldCap = CapOperands;
  MachineOperand *OldOperands = Operands;
  if (!OldOperands || OldCap.getSize() == getNumOperands()) {
    CapOperands = OldOperands ? OldCap.getNext() : OldCap.get(1);
    Operands = MF.allocateOperandArray(CapOperands);
    // Move the operands before the insertion point.
    if (OpNo)
      moveOperands(Operands, OldOperands, OpNo, MRI);
  }

  // Move the operands following the insertion point.
  if (OpNo != NumOperands)
    moveOperands(Operands + OpNo + 1, OldOperands + OpNo, NumOperands - OpNo,
                 MRI);
  ++NumOperands;

  // Deallocate the old operand array.
  if (OldOperands != Operands && OldOperands)
    MF.deallocateOperandArray(OldCap, OldOperands);

  // Copy Op into place. It still needs to be inserted into the MRI use lists.
  MachineOperand *NewMO = new (Operands + OpNo) MachineOperand(Op);
  NewMO->ParentMI = this;

  // When adding a register operand, tell MRI about it.
  if (NewMO->isReg()) {
    // Ensure isOnRegUseList() returns false, regardless of Op's status.
    NewMO->Contents.Reg.Prev = nullptr;
    // Ignore existing ties. This is not a property that can be copied.
    NewMO->TiedTo = 0;
    // Add the new operand to MRI, but only for instructions in an MBB.
    if (MRI)
      MRI->addRegOperandToUseList(NewMO);
    // The MCID operand information isn't accurate until we start adding
    // explicit operands. The implicit operands are added first, then the
    // explicits are inserted before them.
    if (!isImpReg) {
      // Tie uses to defs as indicated in MCInstrDesc.
      if (NewMO->isUse()) {
        int DefIdx = MCID->getOperandConstraint(OpNo, MCOI::TIED_TO);
        if (DefIdx != -1)
          tieOperands(DefIdx, OpNo);
      }
      // If the register operand is flagged as early, mark the operand as such.
      if (MCID->getOperandConstraint(OpNo, MCOI::EARLY_CLOBBER) != -1)
        NewMO->setIsEarlyClobber(true);
    }
    // Ensure debug instructions set debug flag on register uses.
    if (NewMO->isUse() && isDebugInstr())
      NewMO->setIsDebug();
  }
}

void MachineInstr::removeOperand(unsigned OpNo) {
  assert(OpNo < getNumOperands() && "Invalid operand number");
  untieRegOperand(OpNo);

#ifndef NDEBUG
  // Moving tied operands would break the ties.
  for (unsigned i = OpNo + 1, e = getNumOperands(); i != e; ++i)
    if (Operands[i].isReg())
      assert(!Operands[i].isTied() && "Cannot move tied operands");
#endif

  MachineRegisterInfo *MRI = getRegInfo();
  if (MRI && Operands[OpNo].isReg())
    MRI->removeRegOperandFromUseList(Operands + OpNo);

  // Don't call the MachineOperand destructor. A lot of this code depends on
  // MachineOperand having a trivial destructor anyway, and adding a call here
  // wouldn't make it 'destructor-correct'.

  if (unsigned N = NumOperands - 1 - OpNo)
    moveOperands(Operands + OpNo, Operands + OpNo + 1, N, MRI);
  --NumOperands;
}

void MachineInstr::setExtraInfo(MachineFunction &MF,
                                ArrayRef<MachineMemOperand *> MMOs,
                                MCSymbol *PreInstrSymbol,
                                MCSymbol *PostInstrSymbol,
                                MDNode *HeapAllocMarker, MDNode *PCSections,
                                uint32_t CFIType, MDNode *MMRAs) {
  bool HasPreInstrSymbol = PreInstrSymbol != nullptr;
  bool HasPostInstrSymbol = PostInstrSymbol != nullptr;
  bool HasHeapAllocMarker = HeapAllocMarker != nullptr;
  bool HasPCSections = PCSections != nullptr;
  bool HasCFIType = CFIType != 0;
  bool HasMMRAs = MMRAs != nullptr;
  int NumPointers = MMOs.size() + HasPreInstrSymbol + HasPostInstrSymbol +
                    HasHeapAllocMarker + HasPCSections + HasCFIType + HasMMRAs;

  // Drop all extra info if there is none.
  if (NumPointers <= 0) {
    Info.clear();
    return;
  }

  // If more than one pointer, then store out of line. Store heap alloc markers
  // out of line because PointerSumType cannot hold more than 4 tag types with
  // 32-bit pointers.
  // FIXME: Maybe we should make the symbols in the extra info mutable?
  else if (NumPointers > 1 || HasMMRAs || HasHeapAllocMarker || HasPCSections ||
           HasCFIType) {
    Info.set<EIIK_OutOfLine>(
        MF.createMIExtraInfo(MMOs, PreInstrSymbol, PostInstrSymbol,
                             HeapAllocMarker, PCSections, CFIType, MMRAs));
    return;
  }

  // Otherwise store the single pointer inline.
  if (HasPreInstrSymbol)
    Info.set<EIIK_PreInstrSymbol>(PreInstrSymbol);
  else if (HasPostInstrSymbol)
    Info.set<EIIK_PostInstrSymbol>(PostInstrSymbol);
  else
    Info.set<EIIK_MMO>(MMOs[0]);
}

void MachineInstr::dropMemRefs(MachineFunction &MF) {
  if (memoperands_empty())
    return;

  setExtraInfo(MF, {}, getPreInstrSymbol(), getPostInstrSymbol(),
               getHeapAllocMarker(), getPCSections(), getCFIType(),
               getMMRAMetadata());
}

void MachineInstr::setMemRefs(MachineFunction &MF,
                              ArrayRef<MachineMemOperand *> MMOs) {
  if (MMOs.empty()) {
    dropMemRefs(MF);
    return;
  }

  setExtraInfo(MF, MMOs, getPreInstrSymbol(), getPostInstrSymbol(),
               getHeapAllocMarker(), getPCSections(), getCFIType(),
               getMMRAMetadata());
}

void MachineInstr::addMemOperand(MachineFunction &MF,
                                 MachineMemOperand *MO) {
  SmallVector<MachineMemOperand *, 2> MMOs;
  MMOs.append(memoperands_begin(), memoperands_end());
  MMOs.push_back(MO);
  setMemRefs(MF, MMOs);
}

void MachineInstr::cloneMemRefs(MachineFunction &MF, const MachineInstr &MI) {
  if (this == &MI)
    // Nothing to do for a self-clone!
    return;

  assert(&MF == MI.getMF() &&
         "Invalid machine functions when cloning memory refrences!");
  // See if we can just steal the extra info already allocated for the
  // instruction. We can do this whenever the pre- and post-instruction symbols
  // are the same (including null).
  if (getPreInstrSymbol() == MI.getPreInstrSymbol() &&
      getPostInstrSymbol() == MI.getPostInstrSymbol() &&
      getHeapAllocMarker() == MI.getHeapAllocMarker() &&
      getPCSections() == MI.getPCSections() && getMMRAMetadata() &&
      MI.getMMRAMetadata()) {
    Info = MI.Info;
    return;
  }

  // Otherwise, fall back on a copy-based clone.
  setMemRefs(MF, MI.memoperands());
}

/// Check to see if the MMOs pointed to by the two MemRefs arrays are
/// identical.
static bool hasIdenticalMMOs(ArrayRef<MachineMemOperand *> LHS,
                             ArrayRef<MachineMemOperand *> RHS) {
  if (LHS.size() != RHS.size())
    return false;

  auto LHSPointees = make_pointee_range(LHS);
  auto RHSPointees = make_pointee_range(RHS);
  return std::equal(LHSPointees.begin(), LHSPointees.end(),
                    RHSPointees.begin());
}

void MachineInstr::cloneMergedMemRefs(MachineFunction &MF,
                                      ArrayRef<const MachineInstr *> MIs) {
  // Try handling easy numbers of MIs with simpler mechanisms.
  if (MIs.empty()) {
    dropMemRefs(MF);
    return;
  }
  if (MIs.size() == 1) {
    cloneMemRefs(MF, *MIs[0]);
    return;
  }
  // Because an empty memoperands list provides *no* information and must be
  // handled conservatively (assuming the instruction can do anything), the only
  // way to merge with it is to drop all other memoperands.
  if (MIs[0]->memoperands_empty()) {
    dropMemRefs(MF);
    return;
  }

  // Handle the general case.
  SmallVector<MachineMemOperand *, 2> MergedMMOs;
  // Start with the first instruction.
  assert(&MF == MIs[0]->getMF() &&
         "Invalid machine functions when cloning memory references!");
  MergedMMOs.append(MIs[0]->memoperands_begin(), MIs[0]->memoperands_end());
  // Now walk all the other instructions and accumulate any different MMOs.
  for (const MachineInstr &MI : make_pointee_range(MIs.slice(1))) {
    assert(&MF == MI.getMF() &&
           "Invalid machine functions when cloning memory references!");

    // Skip MIs with identical operands to the first. This is a somewhat
    // arbitrary hack but will catch common cases without being quadratic.
    // TODO: We could fully implement merge semantics here if needed.
    if (hasIdenticalMMOs(MIs[0]->memoperands(), MI.memoperands()))
      continue;

    // Because an empty memoperands list provides *no* information and must be
    // handled conservatively (assuming the instruction can do anything), the
    // only way to merge with it is to drop all other memoperands.
    if (MI.memoperands_empty()) {
      dropMemRefs(MF);
      return;
    }

    // Otherwise accumulate these into our temporary buffer of the merged state.
    MergedMMOs.append(MI.memoperands_begin(), MI.memoperands_end());
  }

  setMemRefs(MF, MergedMMOs);
}

void MachineInstr::setPreInstrSymbol(MachineFunction &MF, MCSymbol *Symbol) {
  // Do nothing if old and new symbols are the same.
  if (Symbol == getPreInstrSymbol())
    return;

  // If there was only one symbol and we're removing it, just clear info.
  if (!Symbol && Info.is<EIIK_PreInstrSymbol>()) {
    Info.clear();
    return;
  }

  setExtraInfo(MF, memoperands(), Symbol, getPostInstrSymbol(),
               getHeapAllocMarker(), getPCSections(), getCFIType(),
               getMMRAMetadata());
}

void MachineInstr::setPostInstrSymbol(MachineFunction &MF, MCSymbol *Symbol) {
  // Do nothing if old and new symbols are the same.
  if (Symbol == getPostInstrSymbol())
    return;

  // If there was only one symbol and we're removing it, just clear info.
  if (!Symbol && Info.is<EIIK_PostInstrSymbol>()) {
    Info.clear();
    return;
  }

  setExtraInfo(MF, memoperands(), getPreInstrSymbol(), Symbol,
               getHeapAllocMarker(), getPCSections(), getCFIType(),
               getMMRAMetadata());
}

void MachineInstr::setHeapAllocMarker(MachineFunction &MF, MDNode *Marker) {
  // Do nothing if old and new symbols are the same.
  if (Marker == getHeapAllocMarker())
    return;

  setExtraInfo(MF, memoperands(), getPreInstrSymbol(), getPostInstrSymbol(),
               Marker, getPCSections(), getCFIType(), getMMRAMetadata());
}

void MachineInstr::setPCSections(MachineFunction &MF, MDNode *PCSections) {
  // Do nothing if old and new symbols are the same.
  if (PCSections == getPCSections())
    return;

  setExtraInfo(MF, memoperands(), getPreInstrSymbol(), getPostInstrSymbol(),
               getHeapAllocMarker(), PCSections, getCFIType(),
               getMMRAMetadata());
}

void MachineInstr::setCFIType(MachineFunction &MF, uint32_t Type) {
  // Do nothing if old and new types are the same.
  if (Type == getCFIType())
    return;

  setExtraInfo(MF, memoperands(), getPreInstrSymbol(), getPostInstrSymbol(),
               getHeapAllocMarker(), getPCSections(), Type, getMMRAMetadata());
}

void MachineInstr::setMMRAMetadata(MachineFunction &MF, MDNode *MMRAs) {
  // Do nothing if old and new symbols are the same.
  if (MMRAs == getMMRAMetadata())
    return;

  setExtraInfo(MF, memoperands(), getPreInstrSymbol(), getPostInstrSymbol(),
               getHeapAllocMarker(), getPCSections(), getCFIType(), MMRAs);
}

void MachineInstr::cloneInstrSymbols(MachineFunction &MF,
                                     const MachineInstr &MI) {
  if (this == &MI)
    // Nothing to do for a self-clone!
    return;

  assert(&MF == MI.getMF() &&
         "Invalid machine functions when cloning instruction symbols!");

  setPreInstrSymbol(MF, MI.getPreInstrSymbol());
  setPostInstrSymbol(MF, MI.getPostInstrSymbol());
  setHeapAllocMarker(MF, MI.getHeapAllocMarker());
  setPCSections(MF, MI.getPCSections());
  setMMRAMetadata(MF, MI.getMMRAMetadata());
}

uint32_t MachineInstr::mergeFlagsWith(const MachineInstr &Other) const {
  // For now, the just return the union of the flags. If the flags get more
  // complicated over time, we might need more logic here.
  return getFlags() | Other.getFlags();
}

uint32_t MachineInstr::copyFlagsFromInstruction(const Instruction &I) {
  uint32_t MIFlags = 0;
  // Copy the wrapping flags.
  if (const OverflowingBinaryOperator *OB =
          dyn_cast<OverflowingBinaryOperator>(&I)) {
    if (OB->hasNoSignedWrap())
      MIFlags |= MachineInstr::MIFlag::NoSWrap;
    if (OB->hasNoUnsignedWrap())
      MIFlags |= MachineInstr::MIFlag::NoUWrap;
  } else if (const TruncInst *TI = dyn_cast<TruncInst>(&I)) {
    if (TI->hasNoSignedWrap())
      MIFlags |= MachineInstr::MIFlag::NoSWrap;
    if (TI->hasNoUnsignedWrap())
      MIFlags |= MachineInstr::MIFlag::NoUWrap;
  } else if (const GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(&I)) {
    if (GEP->hasNoUnsignedSignedWrap())
      MIFlags |= MachineInstr::MIFlag::NoUSWrap;
    if (GEP->hasNoUnsignedWrap())
      MIFlags |= MachineInstr::MIFlag::NoUWrap;
  }

  // Copy the nonneg flag.
  if (const PossiblyNonNegInst *PNI = dyn_cast<PossiblyNonNegInst>(&I)) {
    if (PNI->hasNonNeg())
      MIFlags |= MachineInstr::MIFlag::NonNeg;
    // Copy the disjoint flag.
  } else if (const PossiblyDisjointInst *PD =
                 dyn_cast<PossiblyDisjointInst>(&I)) {
    if (PD->isDisjoint())
      MIFlags |= MachineInstr::MIFlag::Disjoint;
  }

  // Copy the samesign flag.
  if (const ICmpInst *ICmp = dyn_cast<ICmpInst>(&I))
    if (ICmp->hasSameSign())
      MIFlags |= MachineInstr::MIFlag::SameSign;

  // Copy the exact flag.
  if (const PossiblyExactOperator *PE = dyn_cast<PossiblyExactOperator>(&I))
    if (PE->isExact())
      MIFlags |= MachineInstr::MIFlag::IsExact;

  // Copy the fast-math flags.
  if (const FPMathOperator *FP = dyn_cast<FPMathOperator>(&I)) {
    const FastMathFlags Flags = FP->getFastMathFlags();
    if (Flags.noNaNs())
      MIFlags |= MachineInstr::MIFlag::FmNoNans;
    if (Flags.noInfs())
      MIFlags |= MachineInstr::MIFlag::FmNoInfs;
    if (Flags.noSignedZeros())
      MIFlags |= MachineInstr::MIFlag::FmNsz;
    if (Flags.allowReciprocal())
      MIFlags |= MachineInstr::MIFlag::FmArcp;
    if (Flags.allowContract())
      MIFlags |= MachineInstr::MIFlag::FmContract;
    if (Flags.approxFunc())
      MIFlags |= MachineInstr::MIFlag::FmAfn;
    if (Flags.allowReassoc())
      MIFlags |= MachineInstr::MIFlag::FmReassoc;
  }

  if (I.getMetadata(LLVMContext::MD_unpredictable))
    MIFlags |= MachineInstr::MIFlag::Unpredictable;

  return MIFlags;
}

void MachineInstr::copyIRFlags(const Instruction &I) {
  Flags = copyFlagsFromInstruction(I);
}

bool MachineInstr::hasPropertyInBundle(uint64_t Mask, QueryType Type) const {
  assert(!isBundledWithPred() && "Must be called on bundle header");
  for (MachineBasicBlock::const_instr_iterator MII = getIterator();; ++MII) {
    if (MII->getDesc().getFlags() & Mask) {
      if (Type == AnyInBundle)
        return true;
    } else {
      if (Type == AllInBundle && !MII->isBundle())
        return false;
    }
    // This was the last instruction in the bundle.
    if (!MII->isBundledWithSucc())
      return Type == AllInBundle;
  }
}

bool MachineInstr::isIdenticalTo(const MachineInstr &Other,
                                 MICheckType Check) const {
  // If opcodes or number of operands are not the same then the two
  // instructions are obviously not identical.
  if (Other.getOpcode() != getOpcode() ||
      Other.getNumOperands() != getNumOperands())
    return false;

  if (isBundle()) {
    // We have passed the test above that both instructions have the same
    // opcode, so we know that both instructions are bundles here. Let's compare
    // MIs inside the bundle.
    assert(Other.isBundle() && "Expected that both instructions are bundles.");
    MachineBasicBlock::const_instr_iterator I1 = getIterator();
    MachineBasicBlock::const_instr_iterator I2 = Other.getIterator();
    // Loop until we analysed the last intruction inside at least one of the
    // bundles.
    while (I1->isBundledWithSucc() && I2->isBundledWithSucc()) {
      ++I1;
      ++I2;
      if (!I1->isIdenticalTo(*I2, Check))
        return false;
    }
    // If we've reached the end of just one of the two bundles, but not both,
    // the instructions are not identical.
    if (I1->isBundledWithSucc() || I2->isBundledWithSucc())
      return false;
  }

  // Check operands to make sure they match.
  for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = getOperand(i);
    const MachineOperand &OMO = Other.getOperand(i);
    if (!MO.isReg()) {
      if (!MO.isIdenticalTo(OMO))
        return false;
      continue;
    }

    // Clients may or may not want to ignore defs when testing for equality.
    // For example, machine CSE pass only cares about finding common
    // subexpressions, so it's safe to ignore virtual register defs.
    if (MO.isDef()) {
      if (Check == IgnoreDefs)
        continue;
      else if (Check == IgnoreVRegDefs) {
        if (!MO.getReg().isVirtual() || !OMO.getReg().isVirtual())
          if (!MO.isIdenticalTo(OMO))
            return false;
      } else {
        if (!MO.isIdenticalTo(OMO))
          return false;
        if (Check == CheckKillDead && MO.isDead() != OMO.isDead())
          return false;
      }
    } else {
      if (!MO.isIdenticalTo(OMO))
        return false;
      if (Check == CheckKillDead && MO.isKill() != OMO.isKill())
        return false;
    }
  }
  // If DebugLoc does not match then two debug instructions are not identical.
  if (isDebugInstr())
    if (getDebugLoc() && Other.getDebugLoc() &&
        getDebugLoc() != Other.getDebugLoc())
      return false;
  // If pre- or post-instruction symbols do not match then the two instructions
  // are not identical.
  if (getPreInstrSymbol() != Other.getPreInstrSymbol() ||
      getPostInstrSymbol() != Other.getPostInstrSymbol())
    return false;
  // Call instructions with different CFI types are not identical.
  if (isCall() && getCFIType() != Other.getCFIType())
    return false;

  return true;
}

bool MachineInstr::isEquivalentDbgInstr(const MachineInstr &Other) const {
  if (!isDebugValueLike() || !Other.isDebugValueLike())
    return false;
  if (getDebugLoc() != Other.getDebugLoc())
    return false;
  if (getDebugVariable() != Other.getDebugVariable())
    return false;
  if (getNumDebugOperands() != Other.getNumDebugOperands())
    return false;
  for (unsigned OpIdx = 0; OpIdx < getNumDebugOperands(); ++OpIdx)
    if (!getDebugOperand(OpIdx).isIdenticalTo(Other.getDebugOperand(OpIdx)))
      return false;
  if (!DIExpression::isEqualExpression(
          getDebugExpression(), isIndirectDebugValue(),
          Other.getDebugExpression(), Other.isIndirectDebugValue()))
    return false;
  return true;
}

const MachineFunction *MachineInstr::getMF() const {
  return getParent()->getParent();
}

MachineInstr *MachineInstr::removeFromParent() {
  assert(getParent() && "Not embedded in a basic block!");
  return getParent()->remove(this);
}

MachineInstr *MachineInstr::removeFromBundle() {
  assert(getParent() && "Not embedded in a basic block!");
  return getParent()->remove_instr(this);
}

void MachineInstr::eraseFromParent() {
  assert(getParent() && "Not embedded in a basic block!");
  getParent()->erase(this);
}

void MachineInstr::eraseFromBundle() {
  assert(getParent() && "Not embedded in a basic block!");
  getParent()->erase_instr(this);
}

bool MachineInstr::isCandidateForAdditionalCallInfo(QueryType Type) const {
  if (!isCall(Type))
    return false;
  switch (getOpcode()) {
  case TargetOpcode::PATCHPOINT:
  case TargetOpcode::STACKMAP:
  case TargetOpcode::STATEPOINT:
  case TargetOpcode::FENTRY_CALL:
    return false;
  }
  return true;
}

bool MachineInstr::shouldUpdateAdditionalCallInfo() const {
  if (isBundle())
    return isCandidateForAdditionalCallInfo(MachineInstr::AnyInBundle);
  return isCandidateForAdditionalCallInfo();
}

template <typename Operand, typename Instruction>
static iterator_range<
    filter_iterator<Operand *, std::function<bool(Operand &Op)>>>
getDebugOperandsForRegHelper(Instruction *MI, Register Reg) {
  std::function<bool(Operand & Op)> OpUsesReg(
      [Reg](Operand &Op) { return Op.isReg() && Op.getReg() == Reg; });
  return make_filter_range(MI->debug_operands(), OpUsesReg);
}

iterator_range<filter_iterator<const MachineOperand *,
                               std::function<bool(const MachineOperand &Op)>>>
MachineInstr::getDebugOperandsForReg(Register Reg) const {
  return getDebugOperandsForRegHelper<const MachineOperand, const MachineInstr>(
      this, Reg);
}

iterator_range<
    filter_iterator<MachineOperand *, std::function<bool(MachineOperand &Op)>>>
MachineInstr::getDebugOperandsForReg(Register Reg) {
  return getDebugOperandsForRegHelper<MachineOperand, MachineInstr>(this, Reg);
}

unsigned MachineInstr::getNumExplicitOperands() const {
  unsigned NumOperands = MCID->getNumOperands();
  if (!MCID->isVariadic())
    return NumOperands;

  for (const MachineOperand &MO : operands_impl().drop_front(NumOperands)) {
    // The operands must always be in the following order:
    // - explicit reg defs,
    // - other explicit operands (reg uses, immediates, etc.),
    // - implicit reg defs
    // - implicit reg uses
    if (MO.isReg() && MO.isImplicit())
      break;
    ++NumOperands;
  }
  return NumOperands;
}

unsigned MachineInstr::getNumExplicitDefs() const {
  unsigned NumDefs = MCID->getNumDefs();
  if (!MCID->isVariadic())
    return NumDefs;

  for (const MachineOperand &MO : operands_impl().drop_front(NumDefs)) {
    if (!MO.isReg() || !MO.isDef() || MO.isImplicit())
      break;
    ++NumDefs;
  }
  return NumDefs;
}

void MachineInstr::bundleWithPred() {
  assert(!isBundledWithPred() && "MI is already bundled with its predecessor");
  setFlag(BundledPred);
  MachineBasicBlock::instr_iterator Pred = getIterator();
  --Pred;
  assert(!Pred->isBundledWithSucc() && "Inconsistent bundle flags");
  Pred->setFlag(BundledSucc);
}

void MachineInstr::bundleWithSucc() {
  assert(!isBundledWithSucc() && "MI is already bundled with its successor");
  setFlag(BundledSucc);
  MachineBasicBlock::instr_iterator Succ = getIterator();
  ++Succ;
  assert(!Succ->isBundledWithPred() && "Inconsistent bundle flags");
  Succ->setFlag(BundledPred);
}

void MachineInstr::unbundleFromPred() {
  assert(isBundledWithPred() && "MI isn't bundled with its predecessor");
  clearFlag(BundledPred);
  MachineBasicBlock::instr_iterator Pred = getIterator();
  --Pred;
  assert(Pred->isBundledWithSucc() && "Inconsistent bundle flags");
  Pred->clearFlag(BundledSucc);
}

void MachineInstr::unbundleFromSucc() {
  assert(isBundledWithSucc() && "MI isn't bundled with its successor");
  clearFlag(BundledSucc);
  MachineBasicBlock::instr_iterator Succ = getIterator();
  ++Succ;
  assert(Succ->isBundledWithPred() && "Inconsistent bundle flags");
  Succ->clearFlag(BundledPred);
}

bool MachineInstr::isStackAligningInlineAsm() const {
  if (isInlineAsm()) {
    unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
    if (ExtraInfo & InlineAsm::Extra_IsAlignStack)
      return true;
  }
  return false;
}

InlineAsm::AsmDialect MachineInstr::getInlineAsmDialect() const {
  assert(isInlineAsm() && "getInlineAsmDialect() only works for inline asms!");
  unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
  return InlineAsm::AsmDialect((ExtraInfo & InlineAsm::Extra_AsmDialect) != 0);
}

int MachineInstr::findInlineAsmFlagIdx(unsigned OpIdx,
                                       unsigned *GroupNo) const {
  assert(isInlineAsm() && "Expected an inline asm instruction");
  assert(OpIdx < getNumOperands() && "OpIdx out of range");

  // Ignore queries about the initial operands.
  if (OpIdx < InlineAsm::MIOp_FirstOperand)
    return -1;

  unsigned Group = 0;
  unsigned NumOps;
  for (unsigned i = InlineAsm::MIOp_FirstOperand, e = getNumOperands(); i < e;
       i += NumOps) {
    const MachineOperand &FlagMO = getOperand(i);
    // If we reach the implicit register operands, stop looking.
    if (!FlagMO.isImm())
      return -1;
    const InlineAsm::Flag F(FlagMO.getImm());
    NumOps = 1 + F.getNumOperandRegisters();
    if (i + NumOps > OpIdx) {
      if (GroupNo)
        *GroupNo = Group;
      return i;
    }
    ++Group;
  }
  return -1;
}

const DILabel *MachineInstr::getDebugLabel() const {
  assert(isDebugLabel() && "not a DBG_LABEL");
  return cast<DILabel>(getOperand(0).getMetadata());
}

const MachineOperand &MachineInstr::getDebugVariableOp() const {
  assert((isDebugValueLike()) && "not a DBG_VALUE*");
  unsigned VariableOp = isNonListDebugValue() ? 2 : 0;
  return getOperand(VariableOp);
}

MachineOperand &MachineInstr::getDebugVariableOp() {
  assert((isDebugValueLike()) && "not a DBG_VALUE*");
  unsigned VariableOp = isNonListDebugValue() ? 2 : 0;
  return getOperand(VariableOp);
}

const DILocalVariable *MachineInstr::getDebugVariable() const {
  return cast<DILocalVariable>(getDebugVariableOp().getMetadata());
}

const MachineOperand &MachineInstr::getDebugExpressionOp() const {
  assert((isDebugValueLike()) && "not a DBG_VALUE*");
  unsigned ExpressionOp = isNonListDebugValue() ? 3 : 1;
  return getOperand(ExpressionOp);
}

MachineOperand &MachineInstr::getDebugExpressionOp() {
  assert((isDebugValueLike()) && "not a DBG_VALUE*");
  unsigned ExpressionOp = isNonListDebugValue() ? 3 : 1;
  return getOperand(ExpressionOp);
}

const DIExpression *MachineInstr::getDebugExpression() const {
  return cast<DIExpression>(getDebugExpressionOp().getMetadata());
}

bool MachineInstr::isDebugEntryValue() const {
  return isDebugValue() && getDebugExpression()->isEntryValue();
}

const TargetRegisterClass*
MachineInstr::getRegClassConstraint(unsigned OpIdx,
                                    const TargetInstrInfo *TII,
                                    const TargetRegisterInfo *TRI) const {
  assert(getParent() && "Can't have an MBB reference here!");
  assert(getMF() && "Can't have an MF reference here!");
  const MachineFunction &MF = *getMF();

  // Most opcodes have fixed constraints in their MCInstrDesc.
  if (!isInlineAsm())
    return TII->getRegClass(getDesc(), OpIdx, TRI, MF);

  if (!getOperand(OpIdx).isReg())
    return nullptr;

  // For tied uses on inline asm, get the constraint from the def.
  unsigned DefIdx;
  if (getOperand(OpIdx).isUse() && isRegTiedToDefOperand(OpIdx, &DefIdx))
    OpIdx = DefIdx;

  // Inline asm stores register class constraints in the flag word.
  int FlagIdx = findInlineAsmFlagIdx(OpIdx);
  if (FlagIdx < 0)
    return nullptr;

  const InlineAsm::Flag F(getOperand(FlagIdx).getImm());
  unsigned RCID;
  if ((F.isRegUseKind() || F.isRegDefKind() || F.isRegDefEarlyClobberKind()) &&
      F.hasRegClassConstraint(RCID))
    return TRI->getRegClass(RCID);

  // Assume that all registers in a memory operand are pointers.
  if (F.isMemKind())
    return TRI->getPointerRegClass(MF);

  return nullptr;
}

const TargetRegisterClass *MachineInstr::getRegClassConstraintEffectForVReg(
    Register Reg, const TargetRegisterClass *CurRC, const TargetInstrInfo *TII,
    const TargetRegisterInfo *TRI, bool ExploreBundle) const {
  // Check every operands inside the bundle if we have
  // been asked to.
  if (ExploreBundle)
    for (ConstMIBundleOperands OpndIt(*this); OpndIt.isValid() && CurRC;
         ++OpndIt)
      CurRC = OpndIt->getParent()->getRegClassConstraintEffectForVRegImpl(
          OpndIt.getOperandNo(), Reg, CurRC, TII, TRI);
  else
    // Otherwise, just check the current operands.
    for (unsigned i = 0, e = NumOperands; i < e && CurRC; ++i)
      CurRC = getRegClassConstraintEffectForVRegImpl(i, Reg, CurRC, TII, TRI);
  return CurRC;
}

const TargetRegisterClass *MachineInstr::getRegClassConstraintEffectForVRegImpl(
    unsigned OpIdx, Register Reg, const TargetRegisterClass *CurRC,
    const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) const {
  assert(CurRC && "Invalid initial register class");
  // Check if Reg is constrained by some of its use/def from MI.
  const MachineOperand &MO = getOperand(OpIdx);
  if (!MO.isReg() || MO.getReg() != Reg)
    return CurRC;
  // If yes, accumulate the constraints through the operand.
  return getRegClassConstraintEffect(OpIdx, CurRC, TII, TRI);
}

const TargetRegisterClass *MachineInstr::getRegClassConstraintEffect(
    unsigned OpIdx, const TargetRegisterClass *CurRC,
    const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) const {
  const TargetRegisterClass *OpRC = getRegClassConstraint(OpIdx, TII, TRI);
  const MachineOperand &MO = getOperand(OpIdx);
  assert(MO.isReg() &&
         "Cannot get register constraints for non-register operand");
  assert(CurRC && "Invalid initial register class");
  if (unsigned SubIdx = MO.getSubReg()) {
    if (OpRC)
      CurRC = TRI->getMatchingSuperRegClass(CurRC, OpRC, SubIdx);
    else
      CurRC = TRI->getSubClassWithSubReg(CurRC, SubIdx);
  } else if (OpRC)
    CurRC = TRI->getCommonSubClass(CurRC, OpRC);
  return CurRC;
}

/// Return the number of instructions inside the MI bundle, not counting the
/// header instruction.
unsigned MachineInstr::getBundleSize() const {
  MachineBasicBlock::const_instr_iterator I = getIterator();
  unsigned Size = 0;
  while (I->isBundledWithSucc()) {
    ++Size;
    ++I;
  }
  return Size;
}

/// Returns true if the MachineInstr has an implicit-use operand of exactly
/// the given register (not considering sub/super-registers).
bool MachineInstr::hasRegisterImplicitUseOperand(Register Reg) const {
  for (const MachineOperand &MO : implicit_operands()) {
    if (MO.isReg() && MO.isUse() && MO.getReg() == Reg)
      return true;
  }
  return false;
}

/// findRegisterUseOperandIdx() - Returns the MachineOperand that is a use of
/// the specific register or -1 if it is not found. It further tightens
/// the search criteria to a use that kills the register if isKill is true.
int MachineInstr::findRegisterUseOperandIdx(Register Reg,
                                            const TargetRegisterInfo *TRI,
                                            bool isKill) const {
  for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = getOperand(i);
    if (!MO.isReg() || !MO.isUse())
      continue;
    Register MOReg = MO.getReg();
    if (!MOReg)
      continue;
    if (MOReg == Reg || (TRI && Reg && MOReg && TRI->regsOverlap(MOReg, Reg)))
      if (!isKill || MO.isKill())
        return i;
  }
  return -1;
}

/// readsWritesVirtualRegister - Return a pair of bools (reads, writes)
/// indicating if this instruction reads or writes Reg. This also considers
/// partial defines.
std::pair<bool,bool>
MachineInstr::readsWritesVirtualRegister(Register Reg,
                                         SmallVectorImpl<unsigned> *Ops) const {
  bool PartDef = false; // Partial redefine.
  bool FullDef = false; // Full define.
  bool Use = false;

  for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = getOperand(i);
    if (!MO.isReg() || MO.getReg() != Reg)
      continue;
    if (Ops)
      Ops->push_back(i);
    if (MO.isUse())
      Use |= !MO.isUndef();
    else if (MO.getSubReg() && !MO.isUndef())
      // A partial def undef doesn't count as reading the register.
      PartDef = true;
    else
      FullDef = true;
  }
  // A partial redefine uses Reg unless there is also a full define.
  return std::make_pair(Use || (PartDef && !FullDef), PartDef || FullDef);
}

/// findRegisterDefOperandIdx() - Returns the operand index that is a def of
/// the specified register or -1 if it is not found. If isDead is true, defs
/// that are not dead are skipped. If TargetRegisterInfo is non-null, then it
/// also checks if there is a def of a super-register.
int MachineInstr::findRegisterDefOperandIdx(Register Reg,
                                            const TargetRegisterInfo *TRI,
                                            bool isDead, bool Overlap) const {
  bool isPhys = Reg.isPhysical();
  for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = getOperand(i);
    // Accept regmask operands when Overlap is set.
    // Ignore them when looking for a specific def operand (Overlap == false).
    if (isPhys && Overlap && MO.isRegMask() && MO.clobbersPhysReg(Reg))
      return i;
    if (!MO.isReg() || !MO.isDef())
      continue;
    Register MOReg = MO.getReg();
    bool Found = (MOReg == Reg);
    if (!Found && TRI && isPhys && MOReg.isPhysical()) {
      if (Overlap)
        Found = TRI->regsOverlap(MOReg, Reg);
      else
        Found = TRI->isSubRegister(MOReg, Reg);
    }
    if (Found && (!isDead || MO.isDead()))
      return i;
  }
  return -1;
}

/// findFirstPredOperandIdx() - Find the index of the first operand in the
/// operand list that is used to represent the predicate. It returns -1 if
/// none is found.
int MachineInstr::findFirstPredOperandIdx() const {
  // Don't call MCID.findFirstPredOperandIdx() because this variant
  // is sometimes called on an instruction that's not yet complete, and
  // so the number of operands is less than the MCID indicates. In
  // particular, the PTX target does this.
  const MCInstrDesc &MCID = getDesc();
  if (MCID.isPredicable()) {
    for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
      if (MCID.operands()[i].isPredicate())
        return i;
  }

  return -1;
}

// MachineOperand::TiedTo is 4 bits wide.
const unsigned TiedMax = 15;

/// tieOperands - Mark operands at DefIdx and UseIdx as tied to each other.
///
/// Use and def operands can be tied together, indicated by a non-zero TiedTo
/// field. TiedTo can have these values:
///
/// 0:              Operand is not tied to anything.
/// 1 to TiedMax-1: Tied to getOperand(TiedTo-1).
/// TiedMax:        Tied to an operand >= TiedMax-1.
///
/// The tied def must be one of the first TiedMax operands on a normal
/// instruction. INLINEASM instructions allow more tied defs.
///
void MachineInstr::tieOperands(unsigned DefIdx, unsigned UseIdx) {
  MachineOperand &DefMO = getOperand(DefIdx);
  MachineOperand &UseMO = getOperand(UseIdx);
  assert(DefMO.isDef() && "DefIdx must be a def operand");
  assert(UseMO.isUse() && "UseIdx must be a use operand");
  assert(!DefMO.isTied() && "Def is already tied to another use");
  assert(!UseMO.isTied() && "Use is already tied to another def");

  if (DefIdx < TiedMax) {
    UseMO.TiedTo = DefIdx + 1;
  } else {
    // Inline asm can use the group descriptors to find tied operands,
    // statepoint tied operands are trivial to match (1-1 reg def with reg use),
    // but on normal instruction, the tied def must be within the first TiedMax
    // operands.
    assert((isInlineAsm() || getOpcode() == TargetOpcode::STATEPOINT) &&
           "DefIdx out of range");
    UseMO.TiedTo = TiedMax;
  }

  // UseIdx can be out of range, we'll search for it in findTiedOperandIdx().
  DefMO.TiedTo = std::min(UseIdx + 1, TiedMax);
}

/// Given the index of a tied register operand, find the operand it is tied to.
/// Defs are tied to uses and vice versa. Returns the index of the tied operand
/// which must exist.
unsigned MachineInstr::findTiedOperandIdx(unsigned OpIdx) const {
  const MachineOperand &MO = getOperand(OpIdx);
  assert(MO.isTied() && "Operand isn't tied");

  // Normally TiedTo is in range.
  if (MO.TiedTo < TiedMax)
    return MO.TiedTo - 1;

  // Uses on normal instructions can be out of range.
  if (!isInlineAsm() && getOpcode() != TargetOpcode::STATEPOINT) {
    // Normal tied defs must be in the 0..TiedMax-1 range.
    if (MO.isUse())
      return TiedMax - 1;
    // MO is a def. Search for the tied use.
    for (unsigned i = TiedMax - 1, e = getNumOperands(); i != e; ++i) {
      const MachineOperand &UseMO = getOperand(i);
      if (UseMO.isReg() && UseMO.isUse() && UseMO.TiedTo == OpIdx + 1)
        return i;
    }
    llvm_unreachable("Can't find tied use");
  }

  if (getOpcode() == TargetOpcode::STATEPOINT) {
    // In STATEPOINT defs correspond 1-1 to GC pointer operands passed
    // on registers.
    StatepointOpers SO(this);
    unsigned CurUseIdx = SO.getFirstGCPtrIdx();
    assert(CurUseIdx != -1U && "only gc pointer statepoint operands can be tied");
    unsigned NumDefs = getNumDefs();
    for (unsigned CurDefIdx = 0; CurDefIdx < NumDefs; ++CurDefIdx) {
      while (!getOperand(CurUseIdx).isReg())
        CurUseIdx = StackMaps::getNextMetaArgIdx(this, CurUseIdx);
      if (OpIdx == CurDefIdx)
        return CurUseIdx;
      if (OpIdx == CurUseIdx)
        return CurDefIdx;
      CurUseIdx = StackMaps::getNextMetaArgIdx(this, CurUseIdx);
    }
    llvm_unreachable("Can't find tied use");
  }

  // Now deal with inline asm by parsing the operand group descriptor flags.
  // Find the beginning of each operand group.
  SmallVector<unsigned, 8> GroupIdx;
  unsigned OpIdxGroup = ~0u;
  unsigned NumOps;
  for (unsigned i = InlineAsm::MIOp_FirstOperand, e = getNumOperands(); i < e;
       i += NumOps) {
    const MachineOperand &FlagMO = getOperand(i);
    assert(FlagMO.isImm() && "Invalid tied operand on inline asm");
    unsigned CurGroup = GroupIdx.size();
    GroupIdx.push_back(i);
    const InlineAsm::Flag F(FlagMO.getImm());
    NumOps = 1 + F.getNumOperandRegisters();
    // OpIdx belongs to this operand group.
    if (OpIdx > i && OpIdx < i + NumOps)
      OpIdxGroup = CurGroup;
    unsigned TiedGroup;
    if (!F.isUseOperandTiedToDef(TiedGroup))
      continue;
    // Operands in this group are tied to operands in TiedGroup which must be
    // earlier. Find the number of operands between the two groups.
    unsigned Delta = i - GroupIdx[TiedGroup];

    // OpIdx is a use tied to TiedGroup.
    if (OpIdxGroup == CurGroup)
      return OpIdx - Delta;

    // OpIdx is a def tied to this use group.
    if (OpIdxGroup == TiedGroup)
      return OpIdx + Delta;
  }
  llvm_unreachable("Invalid tied operand on inline asm");
}

/// clearKillInfo - Clears kill flags on all operands.
///
void MachineInstr::clearKillInfo() {
  for (MachineOperand &MO : operands()) {
    if (MO.isReg() && MO.isUse())
      MO.setIsKill(false);
  }
}

void MachineInstr::substituteRegister(Register FromReg, Register ToReg,
                                      unsigned SubIdx,
                                      const TargetRegisterInfo &RegInfo) {
  if (ToReg.isPhysical()) {
    if (SubIdx)
      ToReg = RegInfo.getSubReg(ToReg, SubIdx);
    for (MachineOperand &MO : operands()) {
      if (!MO.isReg() || MO.getReg() != FromReg)
        continue;
      MO.substPhysReg(ToReg, RegInfo);
    }
  } else {
    for (MachineOperand &MO : operands()) {
      if (!MO.isReg() || MO.getReg() != FromReg)
        continue;
      MO.substVirtReg(ToReg, SubIdx, RegInfo);
    }
  }
}

/// isSafeToMove - Return true if it is safe to move this instruction. If
/// SawStore is set to true, it means that there is a store (or call) between
/// the instruction's location and its intended destination.
bool MachineInstr::isSafeToMove(bool &SawStore) const {
  // Ignore stuff that we obviously can't move.
  //
  // Treat volatile loads as stores. This is not strictly necessary for
  // volatiles, but it is required for atomic loads. It is not allowed to move
  // a load across an atomic load with Ordering > Monotonic.
  if (mayStore() || isCall() || isPHI() ||
      (mayLoad() && hasOrderedMemoryRef())) {
    SawStore = true;
    return false;
  }

  // Don't touch instructions that have non-trivial invariants.  For example,
  // terminators have to be at the end of a basic block.
  if (isPosition() || isDebugInstr() || isTerminator() ||
      isJumpTableDebugInfo())
    return false;

  // Don't touch instructions which can have non-load/store effects.
  //
  // Inline asm has a "sideeffect" marker to indicate whether the asm has
  // intentional side-effects. Even if an inline asm is not "sideeffect",
  // though, it still can't be speculatively executed: the operation might
  // not be valid on the current target, or for some combinations of operands.
  // (Some transforms that move an instruction don't speculatively execute it;
  // we currently don't try to handle that distinction here.)
  //
  // Other instructions handled here include those that can raise FP
  // exceptions, x86 "DIV" instructions which trap on divide by zero, and
  // stack adjustments.
  if (mayRaiseFPException() || hasProperty(MCID::UnmodeledSideEffects) ||
      isInlineAsm())
    return false;

  // See if this instruction does a load.  If so, we have to guarantee that the
  // loaded value doesn't change between the load and the its intended
  // destination. The check for isInvariantLoad gives the target the chance to
  // classify the load as always returning a constant, e.g. a constant pool
  // load.
  if (mayLoad() && !isDereferenceableInvariantLoad())
    // Otherwise, this is a real load.  If there is a store between the load and
    // end of block, we can't move it.
    return !SawStore;

  return true;
}

bool MachineInstr::wouldBeTriviallyDead() const {
  // Don't delete frame allocation labels.
  // FIXME: Why is LOCAL_ESCAPE not considered in MachineInstr::isLabel?
  if (getOpcode() == TargetOpcode::LOCAL_ESCAPE)
    return false;

  // Don't delete FAKE_USE.
  // FIXME: Why is FAKE_USE not considered in MachineInstr::isPosition?
  if (isFakeUse())
    return false;

  // LIFETIME markers should be preserved.
  // FIXME: Why are LIFETIME markers not considered in MachineInstr::isPosition?
  if (isLifetimeMarker())
    return false;

  // If we can move an instruction, we can remove it.  Otherwise, it has
  // a side-effect of some sort.
  bool SawStore = false;
  return isPHI() || isSafeToMove(SawStore);
}

bool MachineInstr::isDead(const MachineRegisterInfo &MRI,
                          LiveRegUnits *LivePhysRegs) const {
  // Instructions without side-effects are dead iff they only define dead regs.
  // This function is hot and this loop returns early in the common case,
  // so only perform additional checks before this if absolutely necessary.
  for (const MachineOperand &MO : all_defs()) {
    Register Reg = MO.getReg();
    if (Reg.isPhysical()) {
      // Don't delete live physreg defs, or any reserved register defs.
      if (!LivePhysRegs || !LivePhysRegs->available(Reg) || MRI.isReserved(Reg))
        return false;
    } else {
      if (MO.isDead())
        continue;
      for (const MachineInstr &Use : MRI.use_nodbg_instructions(Reg)) {
        if (&Use != this)
          // This def has a non-debug use. Don't delete the instruction!
          return false;
      }
    }
  }

  // Technically speaking inline asm without side effects and no defs can still
  // be deleted. But there is so much bad inline asm code out there, we should
  // let them be.
  if (isInlineAsm())
    return false;

  // FIXME: See issue #105950 for why LIFETIME markers are considered dead here.
  if (isLifetimeMarker())
    return true;

  // If there are no defs with uses, then we call the instruction dead so long
  // as we do not suspect it may have sideeffects.
  return wouldBeTriviallyDead();
}

static bool MemOperandsHaveAlias(const MachineFrameInfo &MFI,
                                 BatchAAResults *AA, bool UseTBAA,
                                 const MachineMemOperand *MMOa,
                                 const MachineMemOperand *MMOb) {
  // The following interface to AA is fashioned after DAGCombiner::isAlias and
  // operates with MachineMemOperand offset with some important assumptions:
  //   - LLVM fundamentally assumes flat address spaces.
  //   - MachineOperand offset can *only* result from legalization and cannot
  //     affect queries other than the trivial case of overlap checking.
  //   - These offsets never wrap and never step outside of allocated objects.
  //   - There should never be any negative offsets here.
  //
  // FIXME: Modify API to hide this math from "user"
  // Even before we go to AA we can reason locally about some memory objects. It
  // can save compile time, and possibly catch some corner cases not currently
  // covered.

  int64_t OffsetA = MMOa->getOffset();
  int64_t OffsetB = MMOb->getOffset();
  int64_t MinOffset = std::min(OffsetA, OffsetB);

  LocationSize WidthA = MMOa->getSize();
  LocationSize WidthB = MMOb->getSize();
  bool KnownWidthA = WidthA.hasValue();
  bool KnownWidthB = WidthB.hasValue();
  bool BothMMONonScalable = !WidthA.isScalable() && !WidthB.isScalable();

  const Value *ValA = MMOa->getValue();
  const Value *ValB = MMOb->getValue();
  bool SameVal = (ValA && ValB && (ValA == ValB));
  if (!SameVal) {
    const PseudoSourceValue *PSVa = MMOa->getPseudoValue();
    const PseudoSourceValue *PSVb = MMOb->getPseudoValue();
    if (PSVa && ValB && !PSVa->mayAlias(&MFI))
      return false;
    if (PSVb && ValA && !PSVb->mayAlias(&MFI))
      return false;
    if (PSVa && PSVb && (PSVa == PSVb))
      SameVal = true;
  }

  if (SameVal && BothMMONonScalable) {
    if (!KnownWidthA || !KnownWidthB)
      return true;
    int64_t MaxOffset = std::max(OffsetA, OffsetB);
    int64_t LowWidth = (MinOffset == OffsetA)
                           ? WidthA.getValue().getKnownMinValue()
                           : WidthB.getValue().getKnownMinValue();
    return (MinOffset + LowWidth > MaxOffset);
  }

  if (!AA)
    return true;

  if (!ValA || !ValB)
    return true;

  assert((OffsetA >= 0) && "Negative MachineMemOperand offset");
  assert((OffsetB >= 0) && "Negative MachineMemOperand offset");

  // If Scalable Location Size has non-zero offset, Width + Offset does not work
  // at the moment
  if ((WidthA.isScalable() && OffsetA > 0) ||
      (WidthB.isScalable() && OffsetB > 0))
    return true;

  int64_t OverlapA =
      KnownWidthA ? WidthA.getValue().getKnownMinValue() + OffsetA - MinOffset
                  : MemoryLocation::UnknownSize;
  int64_t OverlapB =
      KnownWidthB ? WidthB.getValue().getKnownMinValue() + OffsetB - MinOffset
                  : MemoryLocation::UnknownSize;

  LocationSize LocA = (WidthA.isScalable() || !KnownWidthA)
                          ? WidthA
                          : LocationSize::precise(OverlapA);
  LocationSize LocB = (WidthB.isScalable() || !KnownWidthB)
                          ? WidthB
                          : LocationSize::precise(OverlapB);

  return !AA->isNoAlias(
      MemoryLocation(ValA, LocA, UseTBAA ? MMOa->getAAInfo() : AAMDNodes()),
      MemoryLocation(ValB, LocB, UseTBAA ? MMOb->getAAInfo() : AAMDNodes()));
}

bool MachineInstr::mayAlias(BatchAAResults *AA, const MachineInstr &Other,
                            bool UseTBAA) const {
  const MachineFunction *MF = getMF();
  const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
  const MachineFrameInfo &MFI = MF->getFrameInfo();

  // Exclude call instruction which may alter the memory but can not be handled
  // by this function.
  if (isCall() || Other.isCall())
    return true;

  // If neither instruction stores to memory, they can't alias in any
  // meaningful way, even if they read from the same address.
  if (!mayStore() && !Other.mayStore())
    return false;

  // Both instructions must be memory operations to be able to alias.
  if (!mayLoadOrStore() || !Other.mayLoadOrStore())
    return false;

  // Let the target decide if memory accesses cannot possibly overlap.
  if (TII->areMemAccessesTriviallyDisjoint(*this, Other))
    return false;

  // Memory operations without memory operands may access anything. Be
  // conservative and assume `MayAlias`.
  if (memoperands_empty() || Other.memoperands_empty())
    return true;

  // Skip if there are too many memory operands.
  auto NumChecks = getNumMemOperands() * Other.getNumMemOperands();
  if (NumChecks > TII->getMemOperandAACheckLimit())
    return true;

  // Check each pair of memory operands from both instructions, which can't
  // alias only if all pairs won't alias.
  for (auto *MMOa : memoperands())
    for (auto *MMOb : Other.memoperands())
      if (MemOperandsHaveAlias(MFI, AA, UseTBAA, MMOa, MMOb))
        return true;

  return false;
}

bool MachineInstr::mayAlias(AAResults *AA, const MachineInstr &Other,
                            bool UseTBAA) const {
  if (AA) {
    BatchAAResults BAA(*AA);
    return mayAlias(&BAA, Other, UseTBAA);
  }
  return mayAlias(static_cast<BatchAAResults *>(nullptr), Other, UseTBAA);
}

/// hasOrderedMemoryRef - Return true if this instruction may have an ordered
/// or volatile memory reference, or if the information describing the memory
/// reference is not available. Return false if it is known to have no ordered
/// memory references.
bool MachineInstr::hasOrderedMemoryRef() const {
  // An instruction known never to access memory won't have a volatile access.
  if (!mayStore() &&
      !mayLoad() &&
      !isCall() &&
      !hasUnmodeledSideEffects())
    return false;

  // Otherwise, if the instruction has no memory reference information,
  // conservatively assume it wasn't preserved.
  if (memoperands_empty())
    return true;

  // Check if any of our memory operands are ordered.
  return llvm::any_of(memoperands(), [](const MachineMemOperand *MMO) {
    return !MMO->isUnordered();
  });
}

/// isDereferenceableInvariantLoad - Return true if this instruction will never
/// trap and is loading from a location whose value is invariant across a run of
/// this function.
bool MachineInstr::isDereferenceableInvariantLoad() const {
  // If the instruction doesn't load at all, it isn't an invariant load.
  if (!mayLoad())
    return false;

  // If the instruction has lost its memoperands, conservatively assume that
  // it may not be an invariant load.
  if (memoperands_empty())
    return false;

  const MachineFrameInfo &MFI = getParent()->getParent()->getFrameInfo();

  for (MachineMemOperand *MMO : memoperands()) {
    if (!MMO->isUnordered())
      // If the memory operand has ordering side effects, we can't move the
      // instruction.  Such an instruction is technically an invariant load,
      // but the caller code would need updated to expect that.
      return false;
    if (MMO->isStore()) return false;
    if (MMO->isInvariant() && MMO->isDereferenceable())
      continue;

    // A load from a constant PseudoSourceValue is invariant.
    if (const PseudoSourceValue *PSV = MMO->getPseudoValue()) {
      if (PSV->isConstant(&MFI))
        continue;
    }

    // Otherwise assume conservatively.
    return false;
  }

  // Everything checks out.
  return true;
}

Register MachineInstr::isConstantValuePHI() const {
  if (!isPHI())
    return {};
  assert(getNumOperands() >= 3 &&
         "It's illegal to have a PHI without source operands");

  Register Reg = getOperand(1).getReg();
  for (unsigned i = 3, e = getNumOperands(); i < e; i += 2)
    if (getOperand(i).getReg() != Reg)
      return {};
  return Reg;
}

bool MachineInstr::hasUnmodeledSideEffects() const {
  if (hasProperty(MCID::UnmodeledSideEffects))
    return true;
  if (isInlineAsm()) {
    unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
    if (ExtraInfo & InlineAsm::Extra_HasSideEffects)
      return true;
  }

  return false;
}

bool MachineInstr::isLoadFoldBarrier() const {
  return mayStore() || isCall() ||
         (hasUnmodeledSideEffects() && !isPseudoProbe());
}

/// allDefsAreDead - Return true if all the defs of this instruction are dead.
///
bool MachineInstr::allDefsAreDead() const {
  for (const MachineOperand &MO : operands()) {
    if (!MO.isReg() || MO.isUse())
      continue;
    if (!MO.isDead())
      return false;
  }
  return true;
}

bool MachineInstr::allImplicitDefsAreDead() const {
  for (const MachineOperand &MO : implicit_operands()) {
    if (!MO.isReg() || MO.isUse())
      continue;
    if (!MO.isDead())
      return false;
  }
  return true;
}

/// copyImplicitOps - Copy implicit register operands from specified
/// instruction to this instruction.
void MachineInstr::copyImplicitOps(MachineFunction &MF,
                                   const MachineInstr &MI) {
  for (const MachineOperand &MO :
       llvm::drop_begin(MI.operands(), MI.getDesc().getNumOperands()))
    if ((MO.isReg() && MO.isImplicit()) || MO.isRegMask())
      addOperand(MF, MO);
}

bool MachineInstr::hasComplexRegisterTies() const {
  const MCInstrDesc &MCID = getDesc();
  if (MCID.Opcode == TargetOpcode::STATEPOINT)
    return true;
  for (unsigned I = 0, E = getNumOperands(); I < E; ++I) {
    const auto &Operand = getOperand(I);
    if (!Operand.isReg() || Operand.isDef())
      // Ignore the defined registers as MCID marks only the uses as tied.
      continue;
    int ExpectedTiedIdx = MCID.getOperandConstraint(I, MCOI::TIED_TO);
    int TiedIdx = Operand.isTied() ? int(findTiedOperandIdx(I)) : -1;
    if (ExpectedTiedIdx != TiedIdx)
      return true;
  }
  return false;
}

LLT MachineInstr::getTypeToPrint(unsigned OpIdx, SmallBitVector &PrintedTypes,
                                 const MachineRegisterInfo &MRI) const {
  const MachineOperand &Op = getOperand(OpIdx);
  if (!Op.isReg())
    return LLT{};

  if (isVariadic() || OpIdx >= getNumExplicitOperands())
    return MRI.getType(Op.getReg());

  auto &OpInfo = getDesc().operands()[OpIdx];
  if (!OpInfo.isGenericType())
    return MRI.getType(Op.getReg());

  if (PrintedTypes[OpInfo.getGenericTypeIndex()])
    return LLT{};

  LLT TypeToPrint = MRI.getType(Op.getReg());
  // Don't mark the type index printed if it wasn't actually printed: maybe
  // another operand with the same type index has an actual type attached:
  if (TypeToPrint.isValid())
    PrintedTypes.set(OpInfo.getGenericTypeIndex());
  return TypeToPrint;
}

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void MachineInstr::dump() const {
  dbgs() << "  ";
  print(dbgs());
}

LLVM_DUMP_METHOD void MachineInstr::dumprImpl(
    const MachineRegisterInfo &MRI, unsigned Depth, unsigned MaxDepth,
    SmallPtrSetImpl<const MachineInstr *> &AlreadySeenInstrs) const {
  if (Depth >= MaxDepth)
    return;
  if (!AlreadySeenInstrs.insert(this).second)
    return;
  // PadToColumn always inserts at least one space.
  // Don't mess up the alignment if we don't want any space.
  if (Depth)
    fdbgs().PadToColumn(Depth * 2);
  print(fdbgs());
  for (const MachineOperand &MO : operands()) {
    if (!MO.isReg() || MO.isDef())
      continue;
    Register Reg = MO.getReg();
    if (Reg.isPhysical())
      continue;
    const MachineInstr *NewMI = MRI.getUniqueVRegDef(Reg);
    if (NewMI == nullptr)
      continue;
    NewMI->dumprImpl(MRI, Depth + 1, MaxDepth, AlreadySeenInstrs);
  }
}

LLVM_DUMP_METHOD void MachineInstr::dumpr(const MachineRegisterInfo &MRI,
                                          unsigned MaxDepth) const {
  SmallPtrSet<const MachineInstr *, 16> AlreadySeenInstrs;
  dumprImpl(MRI, 0, MaxDepth, AlreadySeenInstrs);
}
#endif

void MachineInstr::print(raw_ostream &OS, bool IsStandalone, bool SkipOpers,
                         bool SkipDebugLoc, bool AddNewLine,
                         const TargetInstrInfo *TII) const {
  const Module *M = nullptr;
  const Function *F = nullptr;
  if (const MachineFunction *MF = getMFIfAvailable(*this)) {
    F = &MF->getFunction();
    M = F->getParent();
    if (!TII)
      TII = MF->getSubtarget().getInstrInfo();
  }

  ModuleSlotTracker MST(M);
  if (F)
    MST.incorporateFunction(*F);
  print(OS, MST, IsStandalone, SkipOpers, SkipDebugLoc, AddNewLine, TII);
}

void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
                         bool IsStandalone, bool SkipOpers, bool SkipDebugLoc,
                         bool AddNewLine, const TargetInstrInfo *TII) const {
  // We can be a bit tidier if we know the MachineFunction.
  const TargetRegisterInfo *TRI = nullptr;
  const MachineRegisterInfo *MRI = nullptr;
  tryToGetTargetInfo(*this, TRI, MRI, TII);

  if (isCFIInstruction())
    assert(getNumOperands() == 1 && "Expected 1 operand in CFI instruction");

  SmallBitVector PrintedTypes(8);
  bool ShouldPrintRegisterTies = IsStandalone || hasComplexRegisterTies();
  auto getTiedOperandIdx = [&](unsigned OpIdx) {
    if (!ShouldPrintRegisterTies)
      return 0U;
    const MachineOperand &MO = getOperand(OpIdx);
    if (MO.isReg() && MO.isTied() && !MO.isDef())
      return findTiedOperandIdx(OpIdx);
    return 0U;
  };
  unsigned StartOp = 0;
  unsigned e = getNumOperands();

  // Print explicitly defined operands on the left of an assignment syntax.
  while (StartOp < e) {
    const MachineOperand &MO = getOperand(StartOp);
    if (!MO.isReg() || !MO.isDef() || MO.isImplicit())
      break;

    if (StartOp != 0)
      OS << ", ";

    LLT TypeToPrint = MRI ? getTypeToPrint(StartOp, PrintedTypes, *MRI) : LLT{};
    unsigned TiedOperandIdx = getTiedOperandIdx(StartOp);
    MO.print(OS, MST, TypeToPrint, StartOp, /*PrintDef=*/false, IsStandalone,
             ShouldPrintRegisterTies, TiedOperandIdx, TRI);
    ++StartOp;
  }

  if (StartOp != 0)
    OS << " = ";

  if (getFlag(MachineInstr::FrameSetup))
    OS << "frame-setup ";
  if (getFlag(MachineInstr::FrameDestroy))
    OS << "frame-destroy ";
  if (getFlag(MachineInstr::FmNoNans))
    OS << "nnan ";
  if (getFlag(MachineInstr::FmNoInfs))
    OS << "ninf ";
  if (getFlag(MachineInstr::FmNsz))
    OS << "nsz ";
  if (getFlag(MachineInstr::FmArcp))
    OS << "arcp ";
  if (getFlag(MachineInstr::FmContract))
    OS << "contract ";
  if (getFlag(MachineInstr::FmAfn))
    OS << "afn ";
  if (getFlag(MachineInstr::FmReassoc))
    OS << "reassoc ";
  if (getFlag(MachineInstr::NoUWrap))
    OS << "nuw ";
  if (getFlag(MachineInstr::NoSWrap))
    OS << "nsw ";
  if (getFlag(MachineInstr::IsExact))
    OS << "exact ";
  if (getFlag(MachineInstr::NoFPExcept))
    OS << "nofpexcept ";
  if (getFlag(MachineInstr::NoMerge))
    OS << "nomerge ";
  if (getFlag(MachineInstr::NonNeg))
    OS << "nneg ";
  if (getFlag(MachineInstr::Disjoint))
    OS << "disjoint ";
  if (getFlag(MachineInstr::SameSign))
    OS << "samesign ";

  // Print the opcode name.
  if (TII)
    OS << TII->getName(getOpcode());
  else
    OS << "UNKNOWN";

  if (SkipOpers)
    return;

  // Print the rest of the operands.
  bool FirstOp = true;
  unsigned AsmDescOp = ~0u;
  unsigned AsmOpCount = 0;

  if (isInlineAsm() && e >= InlineAsm::MIOp_FirstOperand) {
    // Print asm string.
    OS << " ";
    const unsigned OpIdx = InlineAsm::MIOp_AsmString;
    LLT TypeToPrint = MRI ? getTypeToPrint(OpIdx, PrintedTypes, *MRI) : LLT{};
    unsigned TiedOperandIdx = getTiedOperandIdx(OpIdx);
    getOperand(OpIdx).print(OS, MST, TypeToPrint, OpIdx, /*PrintDef=*/true,
                            IsStandalone, ShouldPrintRegisterTies,
                            TiedOperandIdx, TRI);

    // Print HasSideEffects, MayLoad, MayStore, IsAlignStack
    unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
    if (ExtraInfo & InlineAsm::Extra_HasSideEffects)
      OS << " [sideeffect]";
    if (ExtraInfo & InlineAsm::Extra_MayLoad)
      OS << " [mayload]";
    if (ExtraInfo & InlineAsm::Extra_MayStore)
      OS << " [maystore]";
    if (ExtraInfo & InlineAsm::Extra_IsConvergent)
      OS << " [isconvergent]";
    if (ExtraInfo & InlineAsm::Extra_IsAlignStack)
      OS << " [alignstack]";
    if (getInlineAsmDialect() == InlineAsm::AD_ATT)
      OS << " [attdialect]";
    if (getInlineAsmDialect() == InlineAsm::AD_Intel)
      OS << " [inteldialect]";

    StartOp = AsmDescOp = InlineAsm::MIOp_FirstOperand;
    FirstOp = false;
  }

  for (unsigned i = StartOp, e = getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = getOperand(i);

    if (FirstOp) FirstOp = false; else OS << ",";
    OS << " ";

    if (isDebugValueLike() && MO.isMetadata()) {
      // Pretty print DBG_VALUE* instructions.
      auto *DIV = dyn_cast<DILocalVariable>(MO.getMetadata());
      if (DIV && !DIV->getName().empty())
        OS << "!\"" << DIV->getName() << '\"';
      else {
        LLT TypeToPrint = MRI ? getTypeToPrint(i, PrintedTypes, *MRI) : LLT{};
        unsigned TiedOperandIdx = getTiedOperandIdx(i);
        MO.print(OS, MST, TypeToPrint, i, /*PrintDef=*/true, IsStandalone,
                 ShouldPrintRegisterTies, TiedOperandIdx, TRI);
      }
    } else if (isDebugLabel() && MO.isMetadata()) {
      // Pretty print DBG_LABEL instructions.
      auto *DIL = dyn_cast<DILabel>(MO.getMetadata());
      if (DIL && !DIL->getName().empty())
        OS << "\"" << DIL->getName() << '\"';
      else {
        LLT TypeToPrint = MRI ? getTypeToPrint(i, PrintedTypes, *MRI) : LLT{};
        unsigned TiedOperandIdx = getTiedOperandIdx(i);
        MO.print(OS, MST, TypeToPrint, i, /*PrintDef=*/true, IsStandalone,
                 ShouldPrintRegisterTies, TiedOperandIdx, TRI);
      }
    } else if (i == AsmDescOp && MO.isImm()) {
      // Pretty print the inline asm operand descriptor.
      OS << '$' << AsmOpCount++;
      unsigned Flag = MO.getImm();
      const InlineAsm::Flag F(Flag);
      OS << ":[";
      OS << F.getKindName();

      unsigned RCID;
      if (!F.isImmKind() && !F.isMemKind() && F.hasRegClassConstraint(RCID)) {
        if (TRI) {
          OS << ':' << TRI->getRegClassName(TRI->getRegClass(RCID));
        } else
          OS << ":RC" << RCID;
      }

      if (F.isMemKind()) {
        const InlineAsm::ConstraintCode MCID = F.getMemoryConstraintID();
        OS << ":" << InlineAsm::getMemConstraintName(MCID);
      }

      unsigned TiedTo;
      if (F.isUseOperandTiedToDef(TiedTo))
        OS << " tiedto:$" << TiedTo;

      if ((F.isRegDefKind() || F.isRegDefEarlyClobberKind() ||
           F.isRegUseKind()) &&
          F.getRegMayBeFolded()) {
        OS << " foldable";
      }

      OS << ']';

      // Compute the index of the next operand descriptor.
      AsmDescOp += 1 + F.getNumOperandRegisters();
    } else {
      LLT TypeToPrint = MRI ? getTypeToPrint(i, PrintedTypes, *MRI) : LLT{};
      unsigned TiedOperandIdx = getTiedOperandIdx(i);
      if (MO.isImm() && isOperandSubregIdx(i))
        MachineOperand::printSubRegIdx(OS, MO.getImm(), TRI);
      else
        MO.print(OS, MST, TypeToPrint, i, /*PrintDef=*/true, IsStandalone,
                 ShouldPrintRegisterTies, TiedOperandIdx, TRI);
    }
  }

  // Print any optional symbols attached to this instruction as-if they were
  // operands.
  if (MCSymbol *PreInstrSymbol = getPreInstrSymbol()) {
    if (!FirstOp) {
      FirstOp = false;
      OS << ',';
    }
    OS << " pre-instr-symbol ";
    MachineOperand::printSymbol(OS, *PreInstrSymbol);
  }
  if (MCSymbol *PostInstrSymbol = getPostInstrSymbol()) {
    if (!FirstOp) {
      FirstOp = false;
      OS << ',';
    }
    OS << " post-instr-symbol ";
    MachineOperand::printSymbol(OS, *PostInstrSymbol);
  }
  if (MDNode *HeapAllocMarker = getHeapAllocMarker()) {
    if (!FirstOp) {
      FirstOp = false;
      OS << ',';
    }
    OS << " heap-alloc-marker ";
    HeapAllocMarker->printAsOperand(OS, MST);
  }
  if (MDNode *PCSections = getPCSections()) {
    if (!FirstOp) {
      FirstOp = false;
      OS << ',';
    }
    OS << " pcsections ";
    PCSections->printAsOperand(OS, MST);
  }
  if (MDNode *MMRA = getMMRAMetadata()) {
    if (!FirstOp) {
      FirstOp = false;
      OS << ',';
    }
    OS << " mmra ";
    MMRA->printAsOperand(OS, MST);
  }
  if (uint32_t CFIType = getCFIType()) {
    if (!FirstOp)
      OS << ',';
    OS << " cfi-type " << CFIType;
  }

  if (DebugInstrNum) {
    if (!FirstOp)
      OS << ",";
    OS << " debug-instr-number " << DebugInstrNum;
  }

  if (!SkipDebugLoc) {
    if (const DebugLoc &DL = getDebugLoc()) {
      if (!FirstOp)
        OS << ',';
      OS << " debug-location ";
      DL->printAsOperand(OS, MST);
    }
  }

  if (!memoperands_empty()) {
    SmallVector<StringRef, 0> SSNs;
    const LLVMContext *Context = nullptr;
    std::unique_ptr<LLVMContext> CtxPtr;
    const MachineFrameInfo *MFI = nullptr;
    if (const MachineFunction *MF = getMFIfAvailable(*this)) {
      MFI = &MF->getFrameInfo();
      Context = &MF->getFunction().getContext();
    } else {
      CtxPtr = std::make_unique<LLVMContext>();
      Context = CtxPtr.get();
    }

    OS << " :: ";
    bool NeedComma = false;
    for (const MachineMemOperand *Op : memoperands()) {
      if (NeedComma)
        OS << ", ";
      Op->print(OS, MST, SSNs, *Context, MFI, TII);
      NeedComma = true;
    }
  }

  if (SkipDebugLoc)
    return;

  bool HaveSemi = false;

  // Print debug location information.
  if (const DebugLoc &DL = getDebugLoc()) {
    if (!HaveSemi) {
      OS << ';';
      HaveSemi = true;
    }
    OS << ' ';
    DL.print(OS);
  }

  // Print extra comments for DEBUG_VALUE and friends if they are well-formed.
  if ((isNonListDebugValue() && getNumOperands() >= 4) ||
      (isDebugValueList() && getNumOperands() >= 2) ||
      (isDebugRef() && getNumOperands() >= 3)) {
    if (getDebugVariableOp().isMetadata()) {
      if (!HaveSemi) {
        OS << ";";
        HaveSemi = true;
      }
      auto *DV = getDebugVariable();
      OS << " line no:" << DV->getLine();
      if (isIndirectDebugValue())
        OS << " indirect";
    }
  }
  // TODO: DBG_LABEL

  if (PrintMIAddrs)
    OS << " ; " << this;

  if (AddNewLine)
    OS << '\n';
}

bool MachineInstr::addRegisterKilled(Register IncomingReg,
                                     const TargetRegisterInfo *RegInfo,
                                     bool AddIfNotFound) {
  bool isPhysReg = IncomingReg.isPhysical();
  bool hasAliases = isPhysReg &&
    MCRegAliasIterator(IncomingReg, RegInfo, false).isValid();
  bool Found = false;
  SmallVector<unsigned,4> DeadOps;
  for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
    MachineOperand &MO = getOperand(i);
    if (!MO.isReg() || !MO.isUse() || MO.isUndef())
      continue;

    // DEBUG_VALUE nodes do not contribute to code generation and should
    // always be ignored. Failure to do so may result in trying to modify
    // KILL flags on DEBUG_VALUE nodes.
    if (MO.isDebug())
      continue;

    Register Reg = MO.getReg();
    if (!Reg)
      continue;

    if (Reg == IncomingReg) {
      if (!Found) {
        if (MO.isKill())
          // The register is already marked kill.
          return true;
        if (isPhysReg && isRegTiedToDefOperand(i))
          // Two-address uses of physregs must not be marked kill.
          return true;
        MO.setIsKill();
        Found = true;
      }
    } else if (hasAliases && MO.isKill() && Reg.isPhysical()) {
      // A super-register kill already exists.
      if (RegInfo->isSuperRegister(IncomingReg, Reg))
        return true;
      if (RegInfo->isSubRegister(IncomingReg, Reg))
        DeadOps.push_back(i);
    }
  }

  // Trim unneeded kill operands.
  while (!DeadOps.empty()) {
    unsigned OpIdx = DeadOps.back();
    if (getOperand(OpIdx).isImplicit() &&
        (!isInlineAsm() || findInlineAsmFlagIdx(OpIdx) < 0))
      removeOperand(OpIdx);
    else
      getOperand(OpIdx).setIsKill(false);
    DeadOps.pop_back();
  }

  // If not found, this means an alias of one of the operands is killed. Add a
  // new implicit operand if required.
  if (!Found && AddIfNotFound) {
    addOperand(MachineOperand::CreateReg(IncomingReg,
                                         false /*IsDef*/,
                                         true  /*IsImp*/,
                                         true  /*IsKill*/));
    return true;
  }
  return Found;
}

void MachineInstr::clearRegisterKills(Register Reg,
                                      const TargetRegisterInfo *RegInfo) {
  if (!Reg.isPhysical())
    RegInfo = nullptr;
  for (MachineOperand &MO : operands()) {
    if (!MO.isReg() || !MO.isUse() || !MO.isKill())
      continue;
    Register OpReg = MO.getReg();
    if ((RegInfo && RegInfo->regsOverlap(Reg, OpReg)) || Reg == OpReg)
      MO.setIsKill(false);
  }
}

bool MachineInstr::addRegisterDead(Register Reg,
                                   const TargetRegisterInfo *RegInfo,
                                   bool AddIfNotFound) {
  bool isPhysReg = Reg.isPhysical();
  bool hasAliases = isPhysReg &&
    MCRegAliasIterator(Reg, RegInfo, false).isValid();
  bool Found = false;
  SmallVector<unsigned,4> DeadOps;
  for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
    MachineOperand &MO = getOperand(i);
    if (!MO.isReg() || !MO.isDef())
      continue;
    Register MOReg = MO.getReg();
    if (!MOReg)
      continue;

    if (MOReg == Reg) {
      MO.setIsDead();
      Found = true;
    } else if (hasAliases && MO.isDead() && MOReg.isPhysical()) {
      // There exists a super-register that's marked dead.
      if (RegInfo->isSuperRegister(Reg, MOReg))
        return true;
      if (RegInfo->isSubRegister(Reg, MOReg))
        DeadOps.push_back(i);
    }
  }

  // Trim unneeded dead operands.
  while (!DeadOps.empty()) {
    unsigned OpIdx = DeadOps.back();
    if (getOperand(OpIdx).isImplicit() &&
        (!isInlineAsm() || findInlineAsmFlagIdx(OpIdx) < 0))
      removeOperand(OpIdx);
    else
      getOperand(OpIdx).setIsDead(false);
    DeadOps.pop_back();
  }

  // If not found, this means an alias of one of the operands is dead. Add a
  // new implicit operand if required.
  if (Found || !AddIfNotFound)
    return Found;

  addOperand(MachineOperand::CreateReg(Reg,
                                       true  /*IsDef*/,
                                       true  /*IsImp*/,
                                       false /*IsKill*/,
                                       true  /*IsDead*/));
  return true;
}

void MachineInstr::clearRegisterDeads(Register Reg) {
  for (MachineOperand &MO : all_defs())
    if (MO.getReg() == Reg)
      MO.setIsDead(false);
}

void MachineInstr::setRegisterDefReadUndef(Register Reg, bool IsUndef) {
  for (MachineOperand &MO : all_defs())
    if (MO.getReg() == Reg && MO.getSubReg() != 0)
      MO.setIsUndef(IsUndef);
}

void MachineInstr::addRegisterDefined(Register Reg,
                                      const TargetRegisterInfo *RegInfo) {
  if (Reg.isPhysical()) {
    MachineOperand *MO = findRegisterDefOperand(Reg, RegInfo, false, false);
    if (MO)
      return;
  } else {
    for (const MachineOperand &MO : all_defs()) {
      if (MO.getReg() == Reg && MO.getSubReg() == 0)
        return;
    }
  }
  addOperand(MachineOperand::CreateReg(Reg,
                                       true  /*IsDef*/,
                                       true  /*IsImp*/));
}

void MachineInstr::setPhysRegsDeadExcept(ArrayRef<Register> UsedRegs,
                                         const TargetRegisterInfo &TRI) {
  bool HasRegMask = false;
  for (MachineOperand &MO : operands()) {
    if (MO.isRegMask()) {
      HasRegMask = true;
      continue;
    }
    if (!MO.isReg() || !MO.isDef()) continue;
    Register Reg = MO.getReg();
    if (!Reg.isPhysical())
      continue;
    // If there are no uses, including partial uses, the def is dead.
    if (llvm::none_of(UsedRegs,
                      [&](MCRegister Use) { return TRI.regsOverlap(Use, Reg); }))
      MO.setIsDead();
  }

  // This is a call with a register mask operand.
  // Mask clobbers are always dead, so add defs for the non-dead defines.
  if (HasRegMask)
    for (const Register &UsedReg : UsedRegs)
      addRegisterDefined(UsedReg, &TRI);
}

unsigned
MachineInstrExpressionTrait::getHashValue(const MachineInstr* const &MI) {
  // Build up a buffer of hash code components.
  SmallVector<size_t, 16> HashComponents;
  HashComponents.reserve(MI->getNumOperands() + 1);
  HashComponents.push_back(MI->getOpcode());
  for (const MachineOperand &MO : MI->operands()) {
    if (MO.isReg() && MO.isDef() && MO.getReg().isVirtual())
      continue;  // Skip virtual register defs.

    HashComponents.push_back(hash_value(MO));
  }
  return hash_combine_range(HashComponents);
}

const MDNode *MachineInstr::getLocCookieMD() const {
  // Find the source location cookie.
  const MDNode *LocMD = nullptr;
  for (unsigned i = getNumOperands(); i != 0; --i) {
    if (getOperand(i-1).isMetadata() &&
        (LocMD = getOperand(i-1).getMetadata()) &&
        LocMD->getNumOperands() != 0) {
      if (mdconst::hasa<ConstantInt>(LocMD->getOperand(0)))
        return LocMD;
    }
  }

  return nullptr;
}

void MachineInstr::emitInlineAsmError(const Twine &Msg) const {
  assert(isInlineAsm());
  const MDNode *LocMD = getLocCookieMD();
  uint64_t LocCookie =
      LocMD
          ? mdconst::extract<ConstantInt>(LocMD->getOperand(0))->getZExtValue()
          : 0;
  LLVMContext &Ctx = getMF()->getFunction().getContext();
  Ctx.diagnose(DiagnosticInfoInlineAsm(LocCookie, Msg));
}

void MachineInstr::emitGenericError(const Twine &Msg) const {
  const Function &Fn = getMF()->getFunction();
  Fn.getContext().diagnose(
      DiagnosticInfoGenericWithLoc(Msg, Fn, getDebugLoc()));
}

MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL,
                                  const MCInstrDesc &MCID, bool IsIndirect,
                                  Register Reg, const MDNode *Variable,
                                  const MDNode *Expr) {
  assert(isa<DILocalVariable>(Variable) && "not a variable");
  assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
  assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) &&
         "Expected inlined-at fields to agree");
  auto MIB = BuildMI(MF, DL, MCID).addReg(Reg);
  if (IsIndirect)
    MIB.addImm(0U);
  else
    MIB.addReg(0U);
  return MIB.addMetadata(Variable).addMetadata(Expr);
}

MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL,
                                  const MCInstrDesc &MCID, bool IsIndirect,
                                  ArrayRef<MachineOperand> DebugOps,
                                  const MDNode *Variable, const MDNode *Expr) {
  assert(isa<DILocalVariable>(Variable) && "not a variable");
  assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
  assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) &&
         "Expected inlined-at fields to agree");
  if (MCID.Opcode == TargetOpcode::DBG_VALUE) {
    assert(DebugOps.size() == 1 &&
           "DBG_VALUE must contain exactly one debug operand");
    MachineOperand DebugOp = DebugOps[0];
    if (DebugOp.isReg())
      return BuildMI(MF, DL, MCID, IsIndirect, DebugOp.getReg(), Variable,
                     Expr);

    auto MIB = BuildMI(MF, DL, MCID).add(DebugOp);
    if (IsIndirect)
      MIB.addImm(0U);
    else
      MIB.addReg(0U);
    return MIB.addMetadata(Variable).addMetadata(Expr);
  }

  auto MIB = BuildMI(MF, DL, MCID);
  MIB.addMetadata(Variable).addMetadata(Expr);
  for (const MachineOperand &DebugOp : DebugOps)
    if (DebugOp.isReg())
      MIB.addReg(DebugOp.getReg());
    else
      MIB.add(DebugOp);
  return MIB;
}

MachineInstrBuilder llvm::BuildMI(MachineBasicBlock &BB,
                                  MachineBasicBlock::iterator I,
                                  const DebugLoc &DL, const MCInstrDesc &MCID,
                                  bool IsIndirect, Register Reg,
                                  const MDNode *Variable, const MDNode *Expr) {
  MachineFunction &MF = *BB.getParent();
  MachineInstr *MI = BuildMI(MF, DL, MCID, IsIndirect, Reg, Variable, Expr);
  BB.insert(I, MI);
  return MachineInstrBuilder(MF, MI);
}

MachineInstrBuilder llvm::BuildMI(MachineBasicBlock &BB,
                                  MachineBasicBlock::iterator I,
                                  const DebugLoc &DL, const MCInstrDesc &MCID,
                                  bool IsIndirect,
                                  ArrayRef<MachineOperand> DebugOps,
                                  const MDNode *Variable, const MDNode *Expr) {
  MachineFunction &MF = *BB.getParent();
  MachineInstr *MI =
      BuildMI(MF, DL, MCID, IsIndirect, DebugOps, Variable, Expr);
  BB.insert(I, MI);
  return MachineInstrBuilder(MF, *MI);
}

/// Compute the new DIExpression to use with a DBG_VALUE for a spill slot.
/// This prepends DW_OP_deref when spilling an indirect DBG_VALUE.
static const DIExpression *computeExprForSpill(
    const MachineInstr &MI,
    const SmallVectorImpl<const MachineOperand *> &SpilledOperands) {
  assert(MI.getDebugVariable()->isValidLocationForIntrinsic(MI.getDebugLoc()) &&
         "Expected inlined-at fields to agree");

  const DIExpression *Expr = MI.getDebugExpression();
  if (MI.isIndirectDebugValue()) {
    assert(MI.getDebugOffset().getImm() == 0 &&
           "DBG_VALUE with nonzero offset");
    Expr = DIExpression::prepend(Expr, DIExpression::DerefBefore);
  } else if (MI.isDebugValueList()) {
    // We will replace the spilled register with a frame index, so
    // immediately deref all references to the spilled register.
    std::array<uint64_t, 1> Ops{{dwarf::DW_OP_deref}};
    for (const MachineOperand *Op : SpilledOperands) {
      unsigned OpIdx = MI.getDebugOperandIndex(Op);
      Expr = DIExpression::appendOpsToArg(Expr, Ops, OpIdx);
    }
  }
  return Expr;
}
static const DIExpression *computeExprForSpill(const MachineInstr &MI,
                                               Register SpillReg) {
  assert(MI.hasDebugOperandForReg(SpillReg) && "Spill Reg is not used in MI.");
  SmallVector<const MachineOperand *> SpillOperands(
      llvm::make_pointer_range(MI.getDebugOperandsForReg(SpillReg)));
  return computeExprForSpill(MI, SpillOperands);
}

MachineInstr *llvm::buildDbgValueForSpill(MachineBasicBlock &BB,
                                          MachineBasicBlock::iterator I,
                                          const MachineInstr &Orig,
                                          int FrameIndex, Register SpillReg) {
  assert(!Orig.isDebugRef() &&
         "DBG_INSTR_REF should not reference a virtual register.");
  const DIExpression *Expr = computeExprForSpill(Orig, SpillReg);
  MachineInstrBuilder NewMI =
      BuildMI(BB, I, Orig.getDebugLoc(), Orig.getDesc());
  // Non-Variadic Operands: Location, Offset, Variable, Expression
  // Variadic Operands:     Variable, Expression, Locations...
  if (Orig.isNonListDebugValue())
    NewMI.addFrameIndex(FrameIndex).addImm(0U);
  NewMI.addMetadata(Orig.getDebugVariable()).addMetadata(Expr);
  if (Orig.isDebugValueList()) {
    for (const MachineOperand &Op : Orig.debug_operands())
      if (Op.isReg() && Op.getReg() == SpillReg)
        NewMI.addFrameIndex(FrameIndex);
      else
        NewMI.add(MachineOperand(Op));
  }
  return NewMI;
}
MachineInstr *llvm::buildDbgValueForSpill(
    MachineBasicBlock &BB, MachineBasicBlock::iterator I,
    const MachineInstr &Orig, int FrameIndex,
    const SmallVectorImpl<const MachineOperand *> &SpilledOperands) {
  const DIExpression *Expr = computeExprForSpill(Orig, SpilledOperands);
  MachineInstrBuilder NewMI =
      BuildMI(BB, I, Orig.getDebugLoc(), Orig.getDesc());
  // Non-Variadic Operands: Location, Offset, Variable, Expression
  // Variadic Operands:     Variable, Expression, Locations...
  if (Orig.isNonListDebugValue())
    NewMI.addFrameIndex(FrameIndex).addImm(0U);
  NewMI.addMetadata(Orig.getDebugVariable()).addMetadata(Expr);
  if (Orig.isDebugValueList()) {
    for (const MachineOperand &Op : Orig.debug_operands())
      if (is_contained(SpilledOperands, &Op))
        NewMI.addFrameIndex(FrameIndex);
      else
        NewMI.add(MachineOperand(Op));
  }
  return NewMI;
}

void llvm::updateDbgValueForSpill(MachineInstr &Orig, int FrameIndex,
                                  Register Reg) {
  const DIExpression *Expr = computeExprForSpill(Orig, Reg);
  if (Orig.isNonListDebugValue())
    Orig.getDebugOffset().ChangeToImmediate(0U);
  for (MachineOperand &Op : Orig.getDebugOperandsForReg(Reg))
    Op.ChangeToFrameIndex(FrameIndex);
  Orig.getDebugExpressionOp().setMetadata(Expr);
}

void MachineInstr::collectDebugValues(
                                SmallVectorImpl<MachineInstr *> &DbgValues) {
  MachineInstr &MI = *this;
  if (!MI.getOperand(0).isReg())
    return;

  MachineBasicBlock::iterator DI = MI; ++DI;
  for (MachineBasicBlock::iterator DE = MI.getParent()->end();
       DI != DE; ++DI) {
    if (!DI->isDebugValue())
      return;
    if (DI->hasDebugOperandForReg(MI.getOperand(0).getReg()))
      DbgValues.push_back(&*DI);
  }
}

void MachineInstr::changeDebugValuesDefReg(Register Reg) {
  // Collect matching debug values.
  SmallVector<MachineInstr *, 2> DbgValues;

  if (!getOperand(0).isReg())
    return;

  Register DefReg = getOperand(0).getReg();
  auto *MRI = getRegInfo();
  for (auto &MO : MRI->use_operands(DefReg)) {
    auto *DI = MO.getParent();
    if (!DI->isDebugValue())
      continue;
    if (DI->hasDebugOperandForReg(DefReg)) {
      DbgValues.push_back(DI);
    }
  }

  // Propagate Reg to debug value instructions.
  for (auto *DBI : DbgValues)
    for (MachineOperand &Op : DBI->getDebugOperandsForReg(DefReg))
      Op.setReg(Reg);
}

using MMOList = SmallVector<const MachineMemOperand *, 2>;

static LocationSize getSpillSlotSize(const MMOList &Accesses,
                                     const MachineFrameInfo &MFI) {
  std::optional<TypeSize> Size;
  for (const auto *A : Accesses) {
    if (MFI.isSpillSlotObjectIndex(
            cast<FixedStackPseudoSourceValue>(A->getPseudoValue())
                ->getFrameIndex())) {
      LocationSize S = A->getSize();
      if (!S.hasValue())
        return LocationSize::beforeOrAfterPointer();
      if (!Size)
        Size = S.getValue();
      else
        Size = *Size + S.getValue();
    }
  }
  if (!Size)
    return LocationSize::precise(0);
  return LocationSize::precise(*Size);
}

std::optional<LocationSize>
MachineInstr::getSpillSize(const TargetInstrInfo *TII) const {
  int FI;
  if (TII->isStoreToStackSlotPostFE(*this, FI)) {
    const MachineFrameInfo &MFI = getMF()->getFrameInfo();
    if (MFI.isSpillSlotObjectIndex(FI))
      return (*memoperands_begin())->getSize();
  }
  return std::nullopt;
}

std::optional<LocationSize>
MachineInstr::getFoldedSpillSize(const TargetInstrInfo *TII) const {
  MMOList Accesses;
  if (TII->hasStoreToStackSlot(*this, Accesses))
    return getSpillSlotSize(Accesses, getMF()->getFrameInfo());
  return std::nullopt;
}

std::optional<LocationSize>
MachineInstr::getRestoreSize(const TargetInstrInfo *TII) const {
  int FI;
  if (TII->isLoadFromStackSlotPostFE(*this, FI)) {
    const MachineFrameInfo &MFI = getMF()->getFrameInfo();
    if (MFI.isSpillSlotObjectIndex(FI))
      return (*memoperands_begin())->getSize();
  }
  return std::nullopt;
}

std::optional<LocationSize>
MachineInstr::getFoldedRestoreSize(const TargetInstrInfo *TII) const {
  MMOList Accesses;
  if (TII->hasLoadFromStackSlot(*this, Accesses))
    return getSpillSlotSize(Accesses, getMF()->getFrameInfo());
  return std::nullopt;
}

unsigned MachineInstr::getDebugInstrNum() {
  if (DebugInstrNum == 0)
    DebugInstrNum = getParent()->getParent()->getNewDebugInstrNum();
  return DebugInstrNum;
}

unsigned MachineInstr::getDebugInstrNum(MachineFunction &MF) {
  if (DebugInstrNum == 0)
    DebugInstrNum = MF.getNewDebugInstrNum();
  return DebugInstrNum;
}

std::tuple<LLT, LLT> MachineInstr::getFirst2LLTs() const {
  return std::tuple(getRegInfo()->getType(getOperand(0).getReg()),
                    getRegInfo()->getType(getOperand(1).getReg()));
}

std::tuple<LLT, LLT, LLT> MachineInstr::getFirst3LLTs() const {
  return std::tuple(getRegInfo()->getType(getOperand(0).getReg()),
                    getRegInfo()->getType(getOperand(1).getReg()),
                    getRegInfo()->getType(getOperand(2).getReg()));
}

std::tuple<LLT, LLT, LLT, LLT> MachineInstr::getFirst4LLTs() const {
  return std::tuple(getRegInfo()->getType(getOperand(0).getReg()),
                    getRegInfo()->getType(getOperand(1).getReg()),
                    getRegInfo()->getType(getOperand(2).getReg()),
                    getRegInfo()->getType(getOperand(3).getReg()));
}

std::tuple<LLT, LLT, LLT, LLT, LLT> MachineInstr::getFirst5LLTs() const {
  return std::tuple(getRegInfo()->getType(getOperand(0).getReg()),
                    getRegInfo()->getType(getOperand(1).getReg()),
                    getRegInfo()->getType(getOperand(2).getReg()),
                    getRegInfo()->getType(getOperand(3).getReg()),
                    getRegInfo()->getType(getOperand(4).getReg()));
}

std::tuple<Register, LLT, Register, LLT>
MachineInstr::getFirst2RegLLTs() const {
  Register Reg0 = getOperand(0).getReg();
  Register Reg1 = getOperand(1).getReg();
  return std::tuple(Reg0, getRegInfo()->getType(Reg0), Reg1,
                    getRegInfo()->getType(Reg1));
}

std::tuple<Register, LLT, Register, LLT, Register, LLT>
MachineInstr::getFirst3RegLLTs() const {
  Register Reg0 = getOperand(0).getReg();
  Register Reg1 = getOperand(1).getReg();
  Register Reg2 = getOperand(2).getReg();
  return std::tuple(Reg0, getRegInfo()->getType(Reg0), Reg1,
                    getRegInfo()->getType(Reg1), Reg2,
                    getRegInfo()->getType(Reg2));
}

std::tuple<Register, LLT, Register, LLT, Register, LLT, Register, LLT>
MachineInstr::getFirst4RegLLTs() const {
  Register Reg0 = getOperand(0).getReg();
  Register Reg1 = getOperand(1).getReg();
  Register Reg2 = getOperand(2).getReg();
  Register Reg3 = getOperand(3).getReg();
  return std::tuple(
      Reg0, getRegInfo()->getType(Reg0), Reg1, getRegInfo()->getType(Reg1),
      Reg2, getRegInfo()->getType(Reg2), Reg3, getRegInfo()->getType(Reg3));
}

std::tuple<Register, LLT, Register, LLT, Register, LLT, Register, LLT, Register,
           LLT>
MachineInstr::getFirst5RegLLTs() const {
  Register Reg0 = getOperand(0).getReg();
  Register Reg1 = getOperand(1).getReg();
  Register Reg2 = getOperand(2).getReg();
  Register Reg3 = getOperand(3).getReg();
  Register Reg4 = getOperand(4).getReg();
  return std::tuple(
      Reg0, getRegInfo()->getType(Reg0), Reg1, getRegInfo()->getType(Reg1),
      Reg2, getRegInfo()->getType(Reg2), Reg3, getRegInfo()->getType(Reg3),
      Reg4, getRegInfo()->getType(Reg4));
}

void MachineInstr::insert(mop_iterator InsertBefore,
                          ArrayRef<MachineOperand> Ops) {
  assert(InsertBefore != nullptr && "invalid iterator");
  assert(InsertBefore->getParent() == this &&
         "iterator points to operand of other inst");
  if (Ops.empty())
    return;

  // Do one pass to untie operands.
  SmallDenseMap<unsigned, unsigned> TiedOpIndices;
  for (const MachineOperand &MO : operands()) {
    if (MO.isReg() && MO.isTied()) {
      unsigned OpNo = getOperandNo(&MO);
      unsigned TiedTo = findTiedOperandIdx(OpNo);
      TiedOpIndices[OpNo] = TiedTo;
      untieRegOperand(OpNo);
    }
  }

  unsigned OpIdx = getOperandNo(InsertBefore);
  unsigned NumOperands = getNumOperands();
  unsigned OpsToMove = NumOperands - OpIdx;

  SmallVector<MachineOperand> MovingOps;
  MovingOps.reserve(OpsToMove);

  for (unsigned I = 0; I < OpsToMove; ++I) {
    MovingOps.emplace_back(getOperand(OpIdx));
    removeOperand(OpIdx);
  }
  for (const MachineOperand &MO : Ops)
    addOperand(MO);
  for (const MachineOperand &OpMoved : MovingOps)
    addOperand(OpMoved);

  // Re-tie operands.
  for (auto [Tie1, Tie2] : TiedOpIndices) {
    if (Tie1 >= OpIdx)
      Tie1 += Ops.size();
    if (Tie2 >= OpIdx)
      Tie2 += Ops.size();
    tieOperands(Tie1, Tie2);
  }
}

bool MachineInstr::mayFoldInlineAsmRegOp(unsigned OpId) const {
  assert(OpId && "expected non-zero operand id");
  assert(isInlineAsm() && "should only be used on inline asm");

  if (!getOperand(OpId).isReg())
    return false;

  const MachineOperand &MD = getOperand(OpId - 1);
  if (!MD.isImm())
    return false;

  InlineAsm::Flag F(MD.getImm());
  if (F.isRegUseKind() || F.isRegDefKind() || F.isRegDefEarlyClobberKind())
    return F.getRegMayBeFolded();
  return false;
}
