//===- 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 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();
}

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

  for (unsigned I = NumOperands, E = getNumOperands(); I != E; ++I) {
    const MachineOperand &MO = getOperand(I);
    // 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 (unsigned I = NumDefs, E = getNumOperands(); I != E; ++I) {
    const MachineOperand &MO = getOperand(I);
    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 (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.begin(), HashComponents.end());
}

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;
  for (const MachineOperand &Op : MI.getDebugOperandsForReg(SpillReg))
    SpillOperands.push_back(&Op);
  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) {
  uint64_t Size = 0;
  for (const auto *A : Accesses) {
    if (MFI.isSpillSlotObjectIndex(
            cast<FixedStackPseudoSourceValue>(A->getPseudoValue())
                ->getFrameIndex())) {
      LocationSize S = A->getSize();
      if (!S.hasValue())
        return LocationSize::beforeOrAfterPointer();
      Size += S.getValue();
    }
  }
  return 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;
}
