//===- MachineFunction.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
//
//===----------------------------------------------------------------------===//
//
// Collect native machine code information for a function.  This allows
// target-specific information about the generated code to be stored with each
// function.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/CodeGen/PseudoSourceValueManager.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/CodeGen/WasmEHFuncInfo.h"
#include "llvm/CodeGen/WinEHFuncInfo.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/EHPersonalities.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ModuleSlotTracker.h"
#include "llvm/IR/Value.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/SectionKind.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DOTGraphTraits.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <iterator>
#include <string>
#include <utility>
#include <vector>

#include "LiveDebugValues/LiveDebugValues.h"

using namespace llvm;

#define DEBUG_TYPE "codegen"

static cl::opt<unsigned> AlignAllFunctions(
    "align-all-functions",
    cl::desc("Force the alignment of all functions in log2 format (e.g. 4 "
             "means align on 16B boundaries)."),
    cl::init(0), cl::Hidden);

static const char *getPropertyName(MachineFunctionProperties::Property Prop) {
  using P = MachineFunctionProperties::Property;

  // clang-format off
  switch(Prop) {
  case P::FailedISel: return "FailedISel";
  case P::IsSSA: return "IsSSA";
  case P::Legalized: return "Legalized";
  case P::NoPHIs: return "NoPHIs";
  case P::NoVRegs: return "NoVRegs";
  case P::RegBankSelected: return "RegBankSelected";
  case P::Selected: return "Selected";
  case P::TracksLiveness: return "TracksLiveness";
  case P::TiedOpsRewritten: return "TiedOpsRewritten";
  case P::FailsVerification: return "FailsVerification";
  case P::FailedRegAlloc: return "FailedRegAlloc";
  case P::TracksDebugUserValues: return "TracksDebugUserValues";
  }
  // clang-format on
  llvm_unreachable("Invalid machine function property");
}

void setUnsafeStackSize(const Function &F, MachineFrameInfo &FrameInfo) {
  if (!F.hasFnAttribute(Attribute::SafeStack))
    return;

  auto *Existing =
      dyn_cast_or_null<MDTuple>(F.getMetadata(LLVMContext::MD_annotation));

  if (!Existing || Existing->getNumOperands() != 2)
    return;

  auto *MetadataName = "unsafe-stack-size";
  if (auto &N = Existing->getOperand(0)) {
    if (N.equalsStr(MetadataName)) {
      if (auto &Op = Existing->getOperand(1)) {
        auto Val = mdconst::extract<ConstantInt>(Op)->getZExtValue();
        FrameInfo.setUnsafeStackSize(Val);
      }
    }
  }
}

// Pin the vtable to this file.
void MachineFunction::Delegate::anchor() {}

void MachineFunctionProperties::print(raw_ostream &OS) const {
  const char *Separator = "";
  for (BitVector::size_type I = 0; I < Properties.size(); ++I) {
    if (!Properties[I])
      continue;
    OS << Separator << getPropertyName(static_cast<Property>(I));
    Separator = ", ";
  }
}

//===----------------------------------------------------------------------===//
// MachineFunction implementation
//===----------------------------------------------------------------------===//

// Out-of-line virtual method.
MachineFunctionInfo::~MachineFunctionInfo() = default;

void ilist_alloc_traits<MachineBasicBlock>::deleteNode(MachineBasicBlock *MBB) {
  MBB->getParent()->deleteMachineBasicBlock(MBB);
}

static inline Align getFnStackAlignment(const TargetSubtargetInfo *STI,
                                           const Function &F) {
  if (auto MA = F.getFnStackAlign())
    return *MA;
  return STI->getFrameLowering()->getStackAlign();
}

MachineFunction::MachineFunction(Function &F, const TargetMachine &Target,
                                 const TargetSubtargetInfo &STI, MCContext &Ctx,
                                 unsigned FunctionNum)
    : F(F), Target(Target), STI(&STI), Ctx(Ctx) {
  FunctionNumber = FunctionNum;
  init();
}

void MachineFunction::handleInsertion(MachineInstr &MI) {
  if (TheDelegate)
    TheDelegate->MF_HandleInsertion(MI);
}

void MachineFunction::handleRemoval(MachineInstr &MI) {
  if (TheDelegate)
    TheDelegate->MF_HandleRemoval(MI);
}

void MachineFunction::handleChangeDesc(MachineInstr &MI,
                                       const MCInstrDesc &TID) {
  if (TheDelegate)
    TheDelegate->MF_HandleChangeDesc(MI, TID);
}

void MachineFunction::init() {
  // Assume the function starts in SSA form with correct liveness.
  Properties.set(MachineFunctionProperties::Property::IsSSA);
  Properties.set(MachineFunctionProperties::Property::TracksLiveness);
  if (STI->getRegisterInfo())
    RegInfo = new (Allocator) MachineRegisterInfo(this);
  else
    RegInfo = nullptr;

  MFInfo = nullptr;

  // We can realign the stack if the target supports it and the user hasn't
  // explicitly asked us not to.
  bool CanRealignSP = STI->getFrameLowering()->isStackRealignable() &&
                      !F.hasFnAttribute("no-realign-stack");
  bool ForceRealignSP = F.hasFnAttribute(Attribute::StackAlignment) ||
                        F.hasFnAttribute("stackrealign");
  FrameInfo = new (Allocator) MachineFrameInfo(
      getFnStackAlignment(STI, F), /*StackRealignable=*/CanRealignSP,
      /*ForcedRealign=*/ForceRealignSP && CanRealignSP);

  setUnsafeStackSize(F, *FrameInfo);

  if (F.hasFnAttribute(Attribute::StackAlignment))
    FrameInfo->ensureMaxAlignment(*F.getFnStackAlign());

  ConstantPool = new (Allocator) MachineConstantPool(getDataLayout());
  Alignment = STI->getTargetLowering()->getMinFunctionAlignment();

  // FIXME: Shouldn't use pref alignment if explicit alignment is set on F.
  // FIXME: Use Function::hasOptSize().
  if (!F.hasFnAttribute(Attribute::OptimizeForSize))
    Alignment = std::max(Alignment,
                         STI->getTargetLowering()->getPrefFunctionAlignment());

  // -fsanitize=function and -fsanitize=kcfi instrument indirect function calls
  // to load a type hash before the function label. Ensure functions are aligned
  // by a least 4 to avoid unaligned access, which is especially important for
  // -mno-unaligned-access.
  if (F.hasMetadata(LLVMContext::MD_func_sanitize) ||
      F.getMetadata(LLVMContext::MD_kcfi_type))
    Alignment = std::max(Alignment, Align(4));

  if (AlignAllFunctions)
    Alignment = Align(1ULL << AlignAllFunctions);

  JumpTableInfo = nullptr;

  if (isFuncletEHPersonality(classifyEHPersonality(
          F.hasPersonalityFn() ? F.getPersonalityFn() : nullptr))) {
    WinEHInfo = new (Allocator) WinEHFuncInfo();
  }

  if (isScopedEHPersonality(classifyEHPersonality(
          F.hasPersonalityFn() ? F.getPersonalityFn() : nullptr))) {
    WasmEHInfo = new (Allocator) WasmEHFuncInfo();
  }

  assert(Target.isCompatibleDataLayout(getDataLayout()) &&
         "Can't create a MachineFunction using a Module with a "
         "Target-incompatible DataLayout attached\n");

  PSVManager = std::make_unique<PseudoSourceValueManager>(getTarget());
}

void MachineFunction::initTargetMachineFunctionInfo(
    const TargetSubtargetInfo &STI) {
  assert(!MFInfo && "MachineFunctionInfo already set");
  MFInfo = Target.createMachineFunctionInfo(Allocator, F, &STI);
}

MachineFunction::~MachineFunction() {
  clear();
}

void MachineFunction::clear() {
  Properties.reset();
  // Don't call destructors on MachineInstr and MachineOperand. All of their
  // memory comes from the BumpPtrAllocator which is about to be purged.
  //
  // Do call MachineBasicBlock destructors, it contains std::vectors.
  for (iterator I = begin(), E = end(); I != E; I = BasicBlocks.erase(I))
    I->Insts.clearAndLeakNodesUnsafely();
  MBBNumbering.clear();

  InstructionRecycler.clear(Allocator);
  OperandRecycler.clear(Allocator);
  BasicBlockRecycler.clear(Allocator);
  CodeViewAnnotations.clear();
  VariableDbgInfos.clear();
  if (RegInfo) {
    RegInfo->~MachineRegisterInfo();
    Allocator.Deallocate(RegInfo);
  }
  if (MFInfo) {
    MFInfo->~MachineFunctionInfo();
    Allocator.Deallocate(MFInfo);
  }

  FrameInfo->~MachineFrameInfo();
  Allocator.Deallocate(FrameInfo);

  ConstantPool->~MachineConstantPool();
  Allocator.Deallocate(ConstantPool);

  if (JumpTableInfo) {
    JumpTableInfo->~MachineJumpTableInfo();
    Allocator.Deallocate(JumpTableInfo);
  }

  if (WinEHInfo) {
    WinEHInfo->~WinEHFuncInfo();
    Allocator.Deallocate(WinEHInfo);
  }

  if (WasmEHInfo) {
    WasmEHInfo->~WasmEHFuncInfo();
    Allocator.Deallocate(WasmEHInfo);
  }
}

const DataLayout &MachineFunction::getDataLayout() const {
  return F.getDataLayout();
}

/// Get the JumpTableInfo for this function.
/// If it does not already exist, allocate one.
MachineJumpTableInfo *MachineFunction::
getOrCreateJumpTableInfo(unsigned EntryKind) {
  if (JumpTableInfo) return JumpTableInfo;

  JumpTableInfo = new (Allocator)
    MachineJumpTableInfo((MachineJumpTableInfo::JTEntryKind)EntryKind);
  return JumpTableInfo;
}

DenormalMode MachineFunction::getDenormalMode(const fltSemantics &FPType) const {
  return F.getDenormalMode(FPType);
}

/// Should we be emitting segmented stack stuff for the function
bool MachineFunction::shouldSplitStack() const {
  return getFunction().hasFnAttribute("split-stack");
}

[[nodiscard]] unsigned
MachineFunction::addFrameInst(const MCCFIInstruction &Inst) {
  FrameInstructions.push_back(Inst);
  return FrameInstructions.size() - 1;
}

/// This discards all of the MachineBasicBlock numbers and recomputes them.
/// This guarantees that the MBB numbers are sequential, dense, and match the
/// ordering of the blocks within the function.  If a specific MachineBasicBlock
/// is specified, only that block and those after it are renumbered.
void MachineFunction::RenumberBlocks(MachineBasicBlock *MBB) {
  if (empty()) { MBBNumbering.clear(); return; }
  MachineFunction::iterator MBBI, E = end();
  if (MBB == nullptr)
    MBBI = begin();
  else
    MBBI = MBB->getIterator();

  // Figure out the block number this should have.
  unsigned BlockNo = 0;
  if (MBBI != begin())
    BlockNo = std::prev(MBBI)->getNumber() + 1;

  for (; MBBI != E; ++MBBI, ++BlockNo) {
    if (MBBI->getNumber() != (int)BlockNo) {
      // Remove use of the old number.
      if (MBBI->getNumber() != -1) {
        assert(MBBNumbering[MBBI->getNumber()] == &*MBBI &&
               "MBB number mismatch!");
        MBBNumbering[MBBI->getNumber()] = nullptr;
      }

      // If BlockNo is already taken, set that block's number to -1.
      if (MBBNumbering[BlockNo])
        MBBNumbering[BlockNo]->setNumber(-1);

      MBBNumbering[BlockNo] = &*MBBI;
      MBBI->setNumber(BlockNo);
    }
  }

  // Okay, all the blocks are renumbered.  If we have compactified the block
  // numbering, shrink MBBNumbering now.
  assert(BlockNo <= MBBNumbering.size() && "Mismatch!");
  MBBNumbering.resize(BlockNo);
  MBBNumberingEpoch++;
}

int64_t MachineFunction::estimateFunctionSizeInBytes() {
  const TargetInstrInfo &TII = *getSubtarget().getInstrInfo();
  const Align FunctionAlignment = getAlignment();
  MachineFunction::iterator MBBI = begin(), E = end();
  /// Offset - Distance from the beginning of the function to the end
  /// of the basic block.
  int64_t Offset = 0;

  for (; MBBI != E; ++MBBI) {
    const Align Alignment = MBBI->getAlignment();
    int64_t BlockSize = 0;

    for (auto &MI : *MBBI) {
      BlockSize += TII.getInstSizeInBytes(MI);
    }

    int64_t OffsetBB;
    if (Alignment <= FunctionAlignment) {
      OffsetBB = alignTo(Offset, Alignment);
    } else {
      // The alignment of this MBB is larger than the function's alignment, so
      // we can't tell whether or not it will insert nops. Assume that it will.
      OffsetBB = alignTo(Offset, Alignment) + Alignment.value() -
                 FunctionAlignment.value();
    }
    Offset = OffsetBB + BlockSize;
  }

  return Offset;
}

/// This method iterates over the basic blocks and assigns their IsBeginSection
/// and IsEndSection fields. This must be called after MBB layout is finalized
/// and the SectionID's are assigned to MBBs.
void MachineFunction::assignBeginEndSections() {
  front().setIsBeginSection();
  auto CurrentSectionID = front().getSectionID();
  for (auto MBBI = std::next(begin()), E = end(); MBBI != E; ++MBBI) {
    if (MBBI->getSectionID() == CurrentSectionID)
      continue;
    MBBI->setIsBeginSection();
    std::prev(MBBI)->setIsEndSection();
    CurrentSectionID = MBBI->getSectionID();
  }
  back().setIsEndSection();
}

/// Allocate a new MachineInstr. Use this instead of `new MachineInstr'.
MachineInstr *MachineFunction::CreateMachineInstr(const MCInstrDesc &MCID,
                                                  DebugLoc DL,
                                                  bool NoImplicit) {
  return new (InstructionRecycler.Allocate<MachineInstr>(Allocator))
      MachineInstr(*this, MCID, std::move(DL), NoImplicit);
}

/// Create a new MachineInstr which is a copy of the 'Orig' instruction,
/// identical in all ways except the instruction has no parent, prev, or next.
MachineInstr *
MachineFunction::CloneMachineInstr(const MachineInstr *Orig) {
  return new (InstructionRecycler.Allocate<MachineInstr>(Allocator))
             MachineInstr(*this, *Orig);
}

MachineInstr &MachineFunction::cloneMachineInstrBundle(
    MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertBefore,
    const MachineInstr &Orig) {
  MachineInstr *FirstClone = nullptr;
  MachineBasicBlock::const_instr_iterator I = Orig.getIterator();
  while (true) {
    MachineInstr *Cloned = CloneMachineInstr(&*I);
    MBB.insert(InsertBefore, Cloned);
    if (FirstClone == nullptr) {
      FirstClone = Cloned;
    } else {
      Cloned->bundleWithPred();
    }

    if (!I->isBundledWithSucc())
      break;
    ++I;
  }
  // Copy over call info to the cloned instruction if needed. If Orig is in
  // a bundle, copyAdditionalCallInfo takes care of finding the call instruction
  // in the bundle.
  if (Orig.shouldUpdateAdditionalCallInfo())
    copyAdditionalCallInfo(&Orig, FirstClone);
  return *FirstClone;
}

/// Delete the given MachineInstr.
///
/// This function also serves as the MachineInstr destructor - the real
/// ~MachineInstr() destructor must be empty.
void MachineFunction::deleteMachineInstr(MachineInstr *MI) {
  // Verify that a call site info is at valid state. This assertion should
  // be triggered during the implementation of support for the
  // call site info of a new architecture. If the assertion is triggered,
  // back trace will tell where to insert a call to updateCallSiteInfo().
  assert((!MI->isCandidateForAdditionalCallInfo() ||
          !CallSitesInfo.contains(MI)) &&
         "Call site info was not updated!");
  // Verify that the "called globals" info is in a valid state.
  assert((!MI->isCandidateForAdditionalCallInfo() ||
          !CalledGlobalsInfo.contains(MI)) &&
         "Called globals info was not updated!");
  // Strip it for parts. The operand array and the MI object itself are
  // independently recyclable.
  if (MI->Operands)
    deallocateOperandArray(MI->CapOperands, MI->Operands);
  // Don't call ~MachineInstr() which must be trivial anyway because
  // ~MachineFunction drops whole lists of MachineInstrs wihout calling their
  // destructors.
  InstructionRecycler.Deallocate(Allocator, MI);
}

/// Allocate a new MachineBasicBlock. Use this instead of
/// `new MachineBasicBlock'.
MachineBasicBlock *
MachineFunction::CreateMachineBasicBlock(const BasicBlock *BB,
                                         std::optional<UniqueBBID> BBID) {
  MachineBasicBlock *MBB =
      new (BasicBlockRecycler.Allocate<MachineBasicBlock>(Allocator))
          MachineBasicBlock(*this, BB);
  // Set BBID for `-basic-block-sections=list` and `-basic-block-address-map` to
  // allow robust mapping of profiles to basic blocks.
  if (Target.Options.BBAddrMap ||
      Target.getBBSectionsType() == BasicBlockSection::List)
    MBB->setBBID(BBID.has_value() ? *BBID : UniqueBBID{NextBBID++, 0});
  return MBB;
}

/// Delete the given MachineBasicBlock.
void MachineFunction::deleteMachineBasicBlock(MachineBasicBlock *MBB) {
  assert(MBB->getParent() == this && "MBB parent mismatch!");
  // Clean up any references to MBB in jump tables before deleting it.
  if (JumpTableInfo)
    JumpTableInfo->RemoveMBBFromJumpTables(MBB);
  MBB->~MachineBasicBlock();
  BasicBlockRecycler.Deallocate(Allocator, MBB);
}

MachineMemOperand *MachineFunction::getMachineMemOperand(
    MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LocationSize Size,
    Align BaseAlignment, const AAMDNodes &AAInfo, const MDNode *Ranges,
    SyncScope::ID SSID, AtomicOrdering Ordering,
    AtomicOrdering FailureOrdering) {
  assert((!Size.hasValue() ||
          Size.getValue().getKnownMinValue() != ~UINT64_C(0)) &&
         "Unexpected an unknown size to be represented using "
         "LocationSize::beforeOrAfter()");
  return new (Allocator)
      MachineMemOperand(PtrInfo, F, Size, BaseAlignment, AAInfo, Ranges, SSID,
                        Ordering, FailureOrdering);
}

MachineMemOperand *MachineFunction::getMachineMemOperand(
    MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy,
    Align base_alignment, const AAMDNodes &AAInfo, const MDNode *Ranges,
    SyncScope::ID SSID, AtomicOrdering Ordering,
    AtomicOrdering FailureOrdering) {
  return new (Allocator)
      MachineMemOperand(PtrInfo, f, MemTy, base_alignment, AAInfo, Ranges, SSID,
                        Ordering, FailureOrdering);
}

MachineMemOperand *
MachineFunction::getMachineMemOperand(const MachineMemOperand *MMO,
                                      const MachinePointerInfo &PtrInfo,
                                      LocationSize Size) {
  assert((!Size.hasValue() ||
          Size.getValue().getKnownMinValue() != ~UINT64_C(0)) &&
         "Unexpected an unknown size to be represented using "
         "LocationSize::beforeOrAfter()");
  return new (Allocator)
      MachineMemOperand(PtrInfo, MMO->getFlags(), Size, MMO->getBaseAlign(),
                        AAMDNodes(), nullptr, MMO->getSyncScopeID(),
                        MMO->getSuccessOrdering(), MMO->getFailureOrdering());
}

MachineMemOperand *MachineFunction::getMachineMemOperand(
    const MachineMemOperand *MMO, const MachinePointerInfo &PtrInfo, LLT Ty) {
  return new (Allocator)
      MachineMemOperand(PtrInfo, MMO->getFlags(), Ty, MMO->getBaseAlign(),
                        AAMDNodes(), nullptr, MMO->getSyncScopeID(),
                        MMO->getSuccessOrdering(), MMO->getFailureOrdering());
}

MachineMemOperand *
MachineFunction::getMachineMemOperand(const MachineMemOperand *MMO,
                                      int64_t Offset, LLT Ty) {
  const MachinePointerInfo &PtrInfo = MMO->getPointerInfo();

  // If there is no pointer value, the offset isn't tracked so we need to adjust
  // the base alignment.
  Align Alignment = PtrInfo.V.isNull()
                        ? commonAlignment(MMO->getBaseAlign(), Offset)
                        : MMO->getBaseAlign();

  // Do not preserve ranges, since we don't necessarily know what the high bits
  // are anymore.
  return new (Allocator) MachineMemOperand(
      PtrInfo.getWithOffset(Offset), MMO->getFlags(), Ty, Alignment,
      MMO->getAAInfo(), nullptr, MMO->getSyncScopeID(),
      MMO->getSuccessOrdering(), MMO->getFailureOrdering());
}

MachineMemOperand *
MachineFunction::getMachineMemOperand(const MachineMemOperand *MMO,
                                      const AAMDNodes &AAInfo) {
  MachinePointerInfo MPI = MMO->getValue() ?
             MachinePointerInfo(MMO->getValue(), MMO->getOffset()) :
             MachinePointerInfo(MMO->getPseudoValue(), MMO->getOffset());

  return new (Allocator) MachineMemOperand(
      MPI, MMO->getFlags(), MMO->getSize(), MMO->getBaseAlign(), AAInfo,
      MMO->getRanges(), MMO->getSyncScopeID(), MMO->getSuccessOrdering(),
      MMO->getFailureOrdering());
}

MachineMemOperand *
MachineFunction::getMachineMemOperand(const MachineMemOperand *MMO,
                                      MachineMemOperand::Flags Flags) {
  return new (Allocator) MachineMemOperand(
      MMO->getPointerInfo(), Flags, MMO->getSize(), MMO->getBaseAlign(),
      MMO->getAAInfo(), MMO->getRanges(), MMO->getSyncScopeID(),
      MMO->getSuccessOrdering(), MMO->getFailureOrdering());
}

MachineInstr::ExtraInfo *MachineFunction::createMIExtraInfo(
    ArrayRef<MachineMemOperand *> MMOs, MCSymbol *PreInstrSymbol,
    MCSymbol *PostInstrSymbol, MDNode *HeapAllocMarker, MDNode *PCSections,
    uint32_t CFIType, MDNode *MMRAs) {
  return MachineInstr::ExtraInfo::create(Allocator, MMOs, PreInstrSymbol,
                                         PostInstrSymbol, HeapAllocMarker,
                                         PCSections, CFIType, MMRAs);
}

const char *MachineFunction::createExternalSymbolName(StringRef Name) {
  char *Dest = Allocator.Allocate<char>(Name.size() + 1);
  llvm::copy(Name, Dest);
  Dest[Name.size()] = 0;
  return Dest;
}

uint32_t *MachineFunction::allocateRegMask() {
  unsigned NumRegs = getSubtarget().getRegisterInfo()->getNumRegs();
  unsigned Size = MachineOperand::getRegMaskSize(NumRegs);
  uint32_t *Mask = Allocator.Allocate<uint32_t>(Size);
  memset(Mask, 0, Size * sizeof(Mask[0]));
  return Mask;
}

ArrayRef<int> MachineFunction::allocateShuffleMask(ArrayRef<int> Mask) {
  int* AllocMask = Allocator.Allocate<int>(Mask.size());
  copy(Mask, AllocMask);
  return {AllocMask, Mask.size()};
}

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void MachineFunction::dump() const {
  print(dbgs());
}
#endif

StringRef MachineFunction::getName() const {
  return getFunction().getName();
}

void MachineFunction::print(raw_ostream &OS, const SlotIndexes *Indexes) const {
  OS << "# Machine code for function " << getName() << ": ";
  getProperties().print(OS);
  OS << '\n';

  // Print Frame Information
  FrameInfo->print(*this, OS);

  // Print JumpTable Information
  if (JumpTableInfo)
    JumpTableInfo->print(OS);

  // Print Constant Pool
  ConstantPool->print(OS);

  const TargetRegisterInfo *TRI = getSubtarget().getRegisterInfo();

  if (RegInfo && !RegInfo->livein_empty()) {
    OS << "Function Live Ins: ";
    for (MachineRegisterInfo::livein_iterator
         I = RegInfo->livein_begin(), E = RegInfo->livein_end(); I != E; ++I) {
      OS << printReg(I->first, TRI);
      if (I->second)
        OS << " in " << printReg(I->second, TRI);
      if (std::next(I) != E)
        OS << ", ";
    }
    OS << '\n';
  }

  ModuleSlotTracker MST(getFunction().getParent());
  MST.incorporateFunction(getFunction());
  for (const auto &BB : *this) {
    OS << '\n';
    // If we print the whole function, print it at its most verbose level.
    BB.print(OS, MST, Indexes, /*IsStandalone=*/true);
  }

  OS << "\n# End machine code for function " << getName() << ".\n\n";
}

/// True if this function needs frame moves for debug or exceptions.
bool MachineFunction::needsFrameMoves() const {
  // TODO: Ideally, what we'd like is to have a switch that allows emitting
  // synchronous (precise at call-sites only) CFA into .eh_frame. However, even
  // under this switch, we'd like .debug_frame to be precise when using -g. At
  // this moment, there's no way to specify that some CFI directives go into
  // .eh_frame only, while others go into .debug_frame only.
  return getTarget().Options.ForceDwarfFrameSection ||
         F.needsUnwindTableEntry() ||
         !F.getParent()->debug_compile_units().empty();
}

namespace llvm {

  template<>
  struct DOTGraphTraits<const MachineFunction*> : public DefaultDOTGraphTraits {
    DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}

    static std::string getGraphName(const MachineFunction *F) {
      return ("CFG for '" + F->getName() + "' function").str();
    }

    std::string getNodeLabel(const MachineBasicBlock *Node,
                             const MachineFunction *Graph) {
      std::string OutStr;
      {
        raw_string_ostream OSS(OutStr);

        if (isSimple()) {
          OSS << printMBBReference(*Node);
          if (const BasicBlock *BB = Node->getBasicBlock())
            OSS << ": " << BB->getName();
        } else
          Node->print(OSS);
      }

      if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());

      // Process string output to make it nicer...
      for (unsigned i = 0; i != OutStr.length(); ++i)
        if (OutStr[i] == '\n') {                            // Left justify
          OutStr[i] = '\\';
          OutStr.insert(OutStr.begin()+i+1, 'l');
        }
      return OutStr;
    }
  };

} // end namespace llvm

void MachineFunction::viewCFG() const
{
#ifndef NDEBUG
  ViewGraph(this, "mf" + getName());
#else
  errs() << "MachineFunction::viewCFG is only available in debug builds on "
         << "systems with Graphviz or gv!\n";
#endif // NDEBUG
}

void MachineFunction::viewCFGOnly() const
{
#ifndef NDEBUG
  ViewGraph(this, "mf" + getName(), true);
#else
  errs() << "MachineFunction::viewCFGOnly is only available in debug builds on "
         << "systems with Graphviz or gv!\n";
#endif // NDEBUG
}

/// Add the specified physical register as a live-in value and
/// create a corresponding virtual register for it.
Register MachineFunction::addLiveIn(MCRegister PReg,
                                    const TargetRegisterClass *RC) {
  MachineRegisterInfo &MRI = getRegInfo();
  Register VReg = MRI.getLiveInVirtReg(PReg);
  if (VReg) {
    const TargetRegisterClass *VRegRC = MRI.getRegClass(VReg);
    (void)VRegRC;
    // A physical register can be added several times.
    // Between two calls, the register class of the related virtual register
    // may have been constrained to match some operation constraints.
    // In that case, check that the current register class includes the
    // physical register and is a sub class of the specified RC.
    assert((VRegRC == RC || (VRegRC->contains(PReg) &&
                             RC->hasSubClassEq(VRegRC))) &&
            "Register class mismatch!");
    return VReg;
  }
  VReg = MRI.createVirtualRegister(RC);
  MRI.addLiveIn(PReg, VReg);
  return VReg;
}

/// Return the MCSymbol for the specified non-empty jump table.
/// If isLinkerPrivate is specified, an 'l' label is returned, otherwise a
/// normal 'L' label is returned.
MCSymbol *MachineFunction::getJTISymbol(unsigned JTI, MCContext &Ctx,
                                        bool isLinkerPrivate) const {
  const DataLayout &DL = getDataLayout();
  assert(JumpTableInfo && "No jump tables");
  assert(JTI < JumpTableInfo->getJumpTables().size() && "Invalid JTI!");

  StringRef Prefix = isLinkerPrivate ? DL.getLinkerPrivateGlobalPrefix()
                                     : DL.getPrivateGlobalPrefix();
  SmallString<60> Name;
  raw_svector_ostream(Name)
    << Prefix << "JTI" << getFunctionNumber() << '_' << JTI;
  return Ctx.getOrCreateSymbol(Name);
}

/// Return a function-local symbol to represent the PIC base.
MCSymbol *MachineFunction::getPICBaseSymbol() const {
  const DataLayout &DL = getDataLayout();
  return Ctx.getOrCreateSymbol(Twine(DL.getPrivateGlobalPrefix()) +
                               Twine(getFunctionNumber()) + "$pb");
}

/// \name Exception Handling
/// \{

LandingPadInfo &
MachineFunction::getOrCreateLandingPadInfo(MachineBasicBlock *LandingPad) {
  unsigned N = LandingPads.size();
  for (unsigned i = 0; i < N; ++i) {
    LandingPadInfo &LP = LandingPads[i];
    if (LP.LandingPadBlock == LandingPad)
      return LP;
  }

  LandingPads.push_back(LandingPadInfo(LandingPad));
  return LandingPads[N];
}

void MachineFunction::addInvoke(MachineBasicBlock *LandingPad,
                                MCSymbol *BeginLabel, MCSymbol *EndLabel) {
  LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
  LP.BeginLabels.push_back(BeginLabel);
  LP.EndLabels.push_back(EndLabel);
}

MCSymbol *MachineFunction::addLandingPad(MachineBasicBlock *LandingPad) {
  MCSymbol *LandingPadLabel = Ctx.createTempSymbol();
  LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad);
  LP.LandingPadLabel = LandingPadLabel;

  BasicBlock::const_iterator FirstI =
      LandingPad->getBasicBlock()->getFirstNonPHIIt();
  if (const auto *LPI = dyn_cast<LandingPadInst>(FirstI)) {
    // If there's no typeid list specified, then "cleanup" is implicit.
    // Otherwise, id 0 is reserved for the cleanup action.
    if (LPI->isCleanup() && LPI->getNumClauses() != 0)
      LP.TypeIds.push_back(0);

    // FIXME: New EH - Add the clauses in reverse order. This isn't 100%
    //        correct, but we need to do it this way because of how the DWARF EH
    //        emitter processes the clauses.
    for (unsigned I = LPI->getNumClauses(); I != 0; --I) {
      Value *Val = LPI->getClause(I - 1);
      if (LPI->isCatch(I - 1)) {
        LP.TypeIds.push_back(
            getTypeIDFor(dyn_cast<GlobalValue>(Val->stripPointerCasts())));
      } else {
        // Add filters in a list.
        auto *CVal = cast<Constant>(Val);
        SmallVector<unsigned, 4> FilterList;
        for (const Use &U : CVal->operands())
          FilterList.push_back(
              getTypeIDFor(cast<GlobalValue>(U->stripPointerCasts())));

        LP.TypeIds.push_back(getFilterIDFor(FilterList));
      }
    }

  } else if (const auto *CPI = dyn_cast<CatchPadInst>(FirstI)) {
    for (unsigned I = CPI->arg_size(); I != 0; --I) {
      auto *TypeInfo =
          dyn_cast<GlobalValue>(CPI->getArgOperand(I - 1)->stripPointerCasts());
      LP.TypeIds.push_back(getTypeIDFor(TypeInfo));
    }

  } else {
    assert(isa<CleanupPadInst>(FirstI) && "Invalid landingpad!");
  }

  return LandingPadLabel;
}

void MachineFunction::setCallSiteLandingPad(MCSymbol *Sym,
                                            ArrayRef<unsigned> Sites) {
  LPadToCallSiteMap[Sym].append(Sites.begin(), Sites.end());
}

unsigned MachineFunction::getTypeIDFor(const GlobalValue *TI) {
  for (unsigned i = 0, N = TypeInfos.size(); i != N; ++i)
    if (TypeInfos[i] == TI) return i + 1;

  TypeInfos.push_back(TI);
  return TypeInfos.size();
}

int MachineFunction::getFilterIDFor(ArrayRef<unsigned> TyIds) {
  // If the new filter coincides with the tail of an existing filter, then
  // re-use the existing filter.  Folding filters more than this requires
  // re-ordering filters and/or their elements - probably not worth it.
  for (unsigned i : FilterEnds) {
    unsigned j = TyIds.size();

    while (i && j)
      if (FilterIds[--i] != TyIds[--j])
        goto try_next;

    if (!j)
      // The new filter coincides with range [i, end) of the existing filter.
      return -(1 + i);

try_next:;
  }

  // Add the new filter.
  int FilterID = -(1 + FilterIds.size());
  FilterIds.reserve(FilterIds.size() + TyIds.size() + 1);
  llvm::append_range(FilterIds, TyIds);
  FilterEnds.push_back(FilterIds.size());
  FilterIds.push_back(0); // terminator
  return FilterID;
}

MachineFunction::CallSiteInfoMap::iterator
MachineFunction::getCallSiteInfo(const MachineInstr *MI) {
  assert(MI->isCandidateForAdditionalCallInfo() &&
         "Call site info refers only to call (MI) candidates");

  if (!Target.Options.EmitCallSiteInfo)
    return CallSitesInfo.end();
  return CallSitesInfo.find(MI);
}

/// Return the call machine instruction or find a call within bundle.
static const MachineInstr *getCallInstr(const MachineInstr *MI) {
  if (!MI->isBundle())
    return MI;

  for (const auto &BMI : make_range(getBundleStart(MI->getIterator()),
                                    getBundleEnd(MI->getIterator())))
    if (BMI.isCandidateForAdditionalCallInfo())
      return &BMI;

  llvm_unreachable("Unexpected bundle without a call site candidate");
}

void MachineFunction::eraseAdditionalCallInfo(const MachineInstr *MI) {
  assert(MI->shouldUpdateAdditionalCallInfo() &&
         "Call info refers only to call (MI) candidates or "
         "candidates inside bundles");

  const MachineInstr *CallMI = getCallInstr(MI);

  CallSiteInfoMap::iterator CSIt = getCallSiteInfo(CallMI);
  if (CSIt != CallSitesInfo.end())
    CallSitesInfo.erase(CSIt);

  CalledGlobalsMap::iterator CGIt = CalledGlobalsInfo.find(CallMI);
  if (CGIt != CalledGlobalsInfo.end())
    CalledGlobalsInfo.erase(CGIt);
}

void MachineFunction::copyAdditionalCallInfo(const MachineInstr *Old,
                                             const MachineInstr *New) {
  assert(Old->shouldUpdateAdditionalCallInfo() &&
         "Call info refers only to call (MI) candidates or "
         "candidates inside bundles");

  if (!New->isCandidateForAdditionalCallInfo())
    return eraseAdditionalCallInfo(Old);

  const MachineInstr *OldCallMI = getCallInstr(Old);
  CallSiteInfoMap::iterator CSIt = getCallSiteInfo(OldCallMI);
  if (CSIt != CallSitesInfo.end()) {
    CallSiteInfo CSInfo = CSIt->second;
    CallSitesInfo[New] = CSInfo;
  }

  CalledGlobalsMap::iterator CGIt = CalledGlobalsInfo.find(OldCallMI);
  if (CGIt != CalledGlobalsInfo.end()) {
    CalledGlobalInfo CGInfo = CGIt->second;
    CalledGlobalsInfo[New] = CGInfo;
  }
}

void MachineFunction::moveAdditionalCallInfo(const MachineInstr *Old,
                                             const MachineInstr *New) {
  assert(Old->shouldUpdateAdditionalCallInfo() &&
         "Call info refers only to call (MI) candidates or "
         "candidates inside bundles");

  if (!New->isCandidateForAdditionalCallInfo())
    return eraseAdditionalCallInfo(Old);

  const MachineInstr *OldCallMI = getCallInstr(Old);
  CallSiteInfoMap::iterator CSIt = getCallSiteInfo(OldCallMI);
  if (CSIt != CallSitesInfo.end()) {
    CallSiteInfo CSInfo = std::move(CSIt->second);
    CallSitesInfo.erase(CSIt);
    CallSitesInfo[New] = CSInfo;
  }

  CalledGlobalsMap::iterator CGIt = CalledGlobalsInfo.find(OldCallMI);
  if (CGIt != CalledGlobalsInfo.end()) {
    CalledGlobalInfo CGInfo = std::move(CGIt->second);
    CalledGlobalsInfo.erase(CGIt);
    CalledGlobalsInfo[New] = CGInfo;
  }
}

void MachineFunction::setDebugInstrNumberingCount(unsigned Num) {
  DebugInstrNumberingCount = Num;
}

void MachineFunction::makeDebugValueSubstitution(DebugInstrOperandPair A,
                                                 DebugInstrOperandPair B,
                                                 unsigned Subreg) {
  // Catch any accidental self-loops.
  assert(A.first != B.first);
  // Don't allow any substitutions _from_ the memory operand number.
  assert(A.second != DebugOperandMemNumber);

  DebugValueSubstitutions.push_back({A, B, Subreg});
}

void MachineFunction::substituteDebugValuesForInst(const MachineInstr &Old,
                                                   MachineInstr &New,
                                                   unsigned MaxOperand) {
  // If the Old instruction wasn't tracked at all, there is no work to do.
  unsigned OldInstrNum = Old.peekDebugInstrNum();
  if (!OldInstrNum)
    return;

  // Iterate over all operands looking for defs to create substitutions for.
  // Avoid creating new instr numbers unless we create a new substitution.
  // While this has no functional effect, it risks confusing someone reading
  // MIR output.
  // Examine all the operands, or the first N specified by the caller.
  MaxOperand = std::min(MaxOperand, Old.getNumOperands());
  for (unsigned int I = 0; I < MaxOperand; ++I) {
    const auto &OldMO = Old.getOperand(I);
    auto &NewMO = New.getOperand(I);
    (void)NewMO;

    if (!OldMO.isReg() || !OldMO.isDef())
      continue;
    assert(NewMO.isDef());

    unsigned NewInstrNum = New.getDebugInstrNum();
    makeDebugValueSubstitution(std::make_pair(OldInstrNum, I),
                               std::make_pair(NewInstrNum, I));
  }
}

auto MachineFunction::salvageCopySSA(
    MachineInstr &MI, DenseMap<Register, DebugInstrOperandPair> &DbgPHICache)
    -> DebugInstrOperandPair {
  const TargetInstrInfo &TII = *getSubtarget().getInstrInfo();

  // Check whether this copy-like instruction has already been salvaged into
  // an operand pair.
  Register Dest;
  if (auto CopyDstSrc = TII.isCopyLikeInstr(MI)) {
    Dest = CopyDstSrc->Destination->getReg();
  } else {
    assert(MI.isSubregToReg());
    Dest = MI.getOperand(0).getReg();
  }

  auto CacheIt = DbgPHICache.find(Dest);
  if (CacheIt != DbgPHICache.end())
    return CacheIt->second;

  // Calculate the instruction number to use, or install a DBG_PHI.
  auto OperandPair = salvageCopySSAImpl(MI);
  DbgPHICache.insert({Dest, OperandPair});
  return OperandPair;
}

auto MachineFunction::salvageCopySSAImpl(MachineInstr &MI)
    -> DebugInstrOperandPair {
  MachineRegisterInfo &MRI = getRegInfo();
  const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
  const TargetInstrInfo &TII = *getSubtarget().getInstrInfo();

  // Chase the value read by a copy-like instruction back to the instruction
  // that ultimately _defines_ that value. This may pass:
  //  * Through multiple intermediate copies, including subregister moves /
  //    copies,
  //  * Copies from physical registers that must then be traced back to the
  //    defining instruction,
  //  * Or, physical registers may be live-in to (only) the entry block, which
  //    requires a DBG_PHI to be created.
  // We can pursue this problem in that order: trace back through copies,
  // optionally through a physical register, to a defining instruction. We
  // should never move from physreg to vreg. As we're still in SSA form, no need
  // to worry about partial definitions of registers.

  // Helper lambda to interpret a copy-like instruction. Takes instruction,
  // returns the register read and any subregister identifying which part is
  // read.
  auto GetRegAndSubreg =
      [&](const MachineInstr &Cpy) -> std::pair<Register, unsigned> {
    Register NewReg, OldReg;
    unsigned SubReg;
    if (Cpy.isCopy()) {
      OldReg = Cpy.getOperand(0).getReg();
      NewReg = Cpy.getOperand(1).getReg();
      SubReg = Cpy.getOperand(1).getSubReg();
    } else if (Cpy.isSubregToReg()) {
      OldReg = Cpy.getOperand(0).getReg();
      NewReg = Cpy.getOperand(2).getReg();
      SubReg = Cpy.getOperand(3).getImm();
    } else {
      auto CopyDetails = *TII.isCopyInstr(Cpy);
      const MachineOperand &Src = *CopyDetails.Source;
      const MachineOperand &Dest = *CopyDetails.Destination;
      OldReg = Dest.getReg();
      NewReg = Src.getReg();
      SubReg = Src.getSubReg();
    }

    return {NewReg, SubReg};
  };

  // First seek either the defining instruction, or a copy from a physreg.
  // During search, the current state is the current copy instruction, and which
  // register we've read. Accumulate qualifying subregisters into SubregsSeen;
  // deal with those later.
  auto State = GetRegAndSubreg(MI);
  auto CurInst = MI.getIterator();
  SmallVector<unsigned, 4> SubregsSeen;
  while (true) {
    // If we've found a copy from a physreg, first portion of search is over.
    if (!State.first.isVirtual())
      break;

    // Record any subregister qualifier.
    if (State.second)
      SubregsSeen.push_back(State.second);

    assert(MRI.hasOneDef(State.first));
    MachineInstr &Inst = *MRI.def_begin(State.first)->getParent();
    CurInst = Inst.getIterator();

    // Any non-copy instruction is the defining instruction we're seeking.
    if (!Inst.isCopyLike() && !TII.isCopyLikeInstr(Inst))
      break;
    State = GetRegAndSubreg(Inst);
  };

  // Helper lambda to apply additional subregister substitutions to a known
  // instruction/operand pair. Adds new (fake) substitutions so that we can
  // record the subregister. FIXME: this isn't very space efficient if multiple
  // values are tracked back through the same copies; cache something later.
  auto ApplySubregisters =
      [&](DebugInstrOperandPair P) -> DebugInstrOperandPair {
    for (unsigned Subreg : reverse(SubregsSeen)) {
      // Fetch a new instruction number, not attached to an actual instruction.
      unsigned NewInstrNumber = getNewDebugInstrNum();
      // Add a substitution from the "new" number to the known one, with a
      // qualifying subreg.
      makeDebugValueSubstitution({NewInstrNumber, 0}, P, Subreg);
      // Return the new number; to find the underlying value, consumers need to
      // deal with the qualifying subreg.
      P = {NewInstrNumber, 0};
    }
    return P;
  };

  // If we managed to find the defining instruction after COPYs, return an
  // instruction / operand pair after adding subregister qualifiers.
  if (State.first.isVirtual()) {
    // Virtual register def -- we can just look up where this happens.
    MachineInstr *Inst = MRI.def_begin(State.first)->getParent();
    for (auto &MO : Inst->all_defs()) {
      if (MO.getReg() != State.first)
        continue;
      return ApplySubregisters({Inst->getDebugInstrNum(), MO.getOperandNo()});
    }

    llvm_unreachable("Vreg def with no corresponding operand?");
  }

  // Our search ended in a copy from a physreg: walk back up the function
  // looking for whatever defines the physreg.
  assert(CurInst->isCopyLike() || TII.isCopyInstr(*CurInst));
  State = GetRegAndSubreg(*CurInst);
  Register RegToSeek = State.first;

  auto RMII = CurInst->getReverseIterator();
  auto PrevInstrs = make_range(RMII, CurInst->getParent()->instr_rend());
  for (auto &ToExamine : PrevInstrs) {
    for (auto &MO : ToExamine.all_defs()) {
      // Test for operand that defines something aliasing RegToSeek.
      if (!TRI.regsOverlap(RegToSeek, MO.getReg()))
        continue;

      return ApplySubregisters(
          {ToExamine.getDebugInstrNum(), MO.getOperandNo()});
    }
  }

  MachineBasicBlock &InsertBB = *CurInst->getParent();

  // We reached the start of the block before finding a defining instruction.
  // There are numerous scenarios where this can happen:
  // * Constant physical registers,
  // * Several intrinsics that allow LLVM-IR to read arbitary registers,
  // * Arguments in the entry block,
  // * Exception handling landing pads.
  // Validating all of them is too difficult, so just insert a DBG_PHI reading
  // the variable value at this position, rather than checking it makes sense.

  // Create DBG_PHI for specified physreg.
  auto Builder = BuildMI(InsertBB, InsertBB.getFirstNonPHI(), DebugLoc(),
                         TII.get(TargetOpcode::DBG_PHI));
  Builder.addReg(State.first);
  unsigned NewNum = getNewDebugInstrNum();
  Builder.addImm(NewNum);
  return ApplySubregisters({NewNum, 0u});
}

void MachineFunction::finalizeDebugInstrRefs() {
  auto *TII = getSubtarget().getInstrInfo();

  auto MakeUndefDbgValue = [&](MachineInstr &MI) {
    const MCInstrDesc &RefII = TII->get(TargetOpcode::DBG_VALUE_LIST);
    MI.setDesc(RefII);
    MI.setDebugValueUndef();
  };

  DenseMap<Register, DebugInstrOperandPair> ArgDbgPHIs;
  for (auto &MBB : *this) {
    for (auto &MI : MBB) {
      if (!MI.isDebugRef())
        continue;

      bool IsValidRef = true;

      for (MachineOperand &MO : MI.debug_operands()) {
        if (!MO.isReg())
          continue;

        Register Reg = MO.getReg();

        // Some vregs can be deleted as redundant in the meantime. Mark those
        // as DBG_VALUE $noreg. Additionally, some normal instructions are
        // quickly deleted, leaving dangling references to vregs with no def.
        if (Reg == 0 || !RegInfo->hasOneDef(Reg)) {
          IsValidRef = false;
          break;
        }

        assert(Reg.isVirtual());
        MachineInstr &DefMI = *RegInfo->def_instr_begin(Reg);

        // If we've found a copy-like instruction, follow it back to the
        // instruction that defines the source value, see salvageCopySSA docs
        // for why this is important.
        if (DefMI.isCopyLike() || TII->isCopyInstr(DefMI)) {
          auto Result = salvageCopySSA(DefMI, ArgDbgPHIs);
          MO.ChangeToDbgInstrRef(Result.first, Result.second);
        } else {
          // Otherwise, identify the operand number that the VReg refers to.
          unsigned OperandIdx = 0;
          for (const auto &DefMO : DefMI.operands()) {
            if (DefMO.isReg() && DefMO.isDef() && DefMO.getReg() == Reg)
              break;
            ++OperandIdx;
          }
          assert(OperandIdx < DefMI.getNumOperands());

          // Morph this instr ref to point at the given instruction and operand.
          unsigned ID = DefMI.getDebugInstrNum();
          MO.ChangeToDbgInstrRef(ID, OperandIdx);
        }
      }

      if (!IsValidRef)
        MakeUndefDbgValue(MI);
    }
  }
}

bool MachineFunction::shouldUseDebugInstrRef() const {
  // Disable instr-ref at -O0: it's very slow (in compile time). We can still
  // have optimized code inlined into this unoptimized code, however with
  // fewer and less aggressive optimizations happening, coverage and accuracy
  // should not suffer.
  if (getTarget().getOptLevel() == CodeGenOptLevel::None)
    return false;

  // Don't use instr-ref if this function is marked optnone.
  if (F.hasFnAttribute(Attribute::OptimizeNone))
    return false;

  if (llvm::debuginfoShouldUseDebugInstrRef(getTarget().getTargetTriple()))
    return true;

  return false;
}

bool MachineFunction::useDebugInstrRef() const {
  return UseDebugInstrRef;
}

void MachineFunction::setUseDebugInstrRef(bool Use) {
  UseDebugInstrRef = Use;
}

// Use one million as a high / reserved number.
const unsigned MachineFunction::DebugOperandMemNumber = 1000000;

/// \}

//===----------------------------------------------------------------------===//
//  MachineJumpTableInfo implementation
//===----------------------------------------------------------------------===//

MachineJumpTableEntry::MachineJumpTableEntry(
    const std::vector<MachineBasicBlock *> &MBBs)
    : MBBs(MBBs), Hotness(MachineFunctionDataHotness::Unknown) {}

/// Return the size of each entry in the jump table.
unsigned MachineJumpTableInfo::getEntrySize(const DataLayout &TD) const {
  // The size of a jump table entry is 4 bytes unless the entry is just the
  // address of a block, in which case it is the pointer size.
  switch (getEntryKind()) {
  case MachineJumpTableInfo::EK_BlockAddress:
    return TD.getPointerSize();
  case MachineJumpTableInfo::EK_GPRel64BlockAddress:
  case MachineJumpTableInfo::EK_LabelDifference64:
    return 8;
  case MachineJumpTableInfo::EK_GPRel32BlockAddress:
  case MachineJumpTableInfo::EK_LabelDifference32:
  case MachineJumpTableInfo::EK_Custom32:
    return 4;
  case MachineJumpTableInfo::EK_Inline:
    return 0;
  }
  llvm_unreachable("Unknown jump table encoding!");
}

/// Return the alignment of each entry in the jump table.
unsigned MachineJumpTableInfo::getEntryAlignment(const DataLayout &TD) const {
  // The alignment of a jump table entry is the alignment of int32 unless the
  // entry is just the address of a block, in which case it is the pointer
  // alignment.
  switch (getEntryKind()) {
  case MachineJumpTableInfo::EK_BlockAddress:
    return TD.getPointerABIAlignment(0).value();
  case MachineJumpTableInfo::EK_GPRel64BlockAddress:
  case MachineJumpTableInfo::EK_LabelDifference64:
    return TD.getABIIntegerTypeAlignment(64).value();
  case MachineJumpTableInfo::EK_GPRel32BlockAddress:
  case MachineJumpTableInfo::EK_LabelDifference32:
  case MachineJumpTableInfo::EK_Custom32:
    return TD.getABIIntegerTypeAlignment(32).value();
  case MachineJumpTableInfo::EK_Inline:
    return 1;
  }
  llvm_unreachable("Unknown jump table encoding!");
}

/// Create a new jump table entry in the jump table info.
unsigned MachineJumpTableInfo::createJumpTableIndex(
                               const std::vector<MachineBasicBlock*> &DestBBs) {
  assert(!DestBBs.empty() && "Cannot create an empty jump table!");
  JumpTables.push_back(MachineJumpTableEntry(DestBBs));
  return JumpTables.size()-1;
}

bool MachineJumpTableInfo::updateJumpTableEntryHotness(
    size_t JTI, MachineFunctionDataHotness Hotness) {
  assert(JTI < JumpTables.size() && "Invalid JTI!");
  // Record the largest hotness value.
  if (Hotness <= JumpTables[JTI].Hotness)
    return false;

  JumpTables[JTI].Hotness = Hotness;
  return true;
}

/// If Old is the target of any jump tables, update the jump tables to branch
/// to New instead.
bool MachineJumpTableInfo::ReplaceMBBInJumpTables(MachineBasicBlock *Old,
                                                  MachineBasicBlock *New) {
  assert(Old != New && "Not making a change?");
  bool MadeChange = false;
  for (size_t i = 0, e = JumpTables.size(); i != e; ++i)
    ReplaceMBBInJumpTable(i, Old, New);
  return MadeChange;
}

/// If MBB is present in any jump tables, remove it.
bool MachineJumpTableInfo::RemoveMBBFromJumpTables(MachineBasicBlock *MBB) {
  bool MadeChange = false;
  for (MachineJumpTableEntry &JTE : JumpTables) {
    auto removeBeginItr = std::remove(JTE.MBBs.begin(), JTE.MBBs.end(), MBB);
    MadeChange |= (removeBeginItr != JTE.MBBs.end());
    JTE.MBBs.erase(removeBeginItr, JTE.MBBs.end());
  }
  return MadeChange;
}

/// If Old is a target of the jump tables, update the jump table to branch to
/// New instead.
bool MachineJumpTableInfo::ReplaceMBBInJumpTable(unsigned Idx,
                                                 MachineBasicBlock *Old,
                                                 MachineBasicBlock *New) {
  assert(Old != New && "Not making a change?");
  bool MadeChange = false;
  MachineJumpTableEntry &JTE = JumpTables[Idx];
  for (MachineBasicBlock *&MBB : JTE.MBBs)
    if (MBB == Old) {
      MBB = New;
      MadeChange = true;
    }
  return MadeChange;
}

void MachineJumpTableInfo::print(raw_ostream &OS) const {
  if (JumpTables.empty()) return;

  OS << "Jump Tables:\n";

  for (unsigned i = 0, e = JumpTables.size(); i != e; ++i) {
    OS << printJumpTableEntryReference(i) << ':';
    for (const MachineBasicBlock *MBB : JumpTables[i].MBBs)
      OS << ' ' << printMBBReference(*MBB);
    if (i != e)
      OS << '\n';
  }

  OS << '\n';
}

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void MachineJumpTableInfo::dump() const { print(dbgs()); }
#endif

Printable llvm::printJumpTableEntryReference(unsigned Idx) {
  return Printable([Idx](raw_ostream &OS) { OS << "%jump-table." << Idx; });
}

//===----------------------------------------------------------------------===//
//  MachineConstantPool implementation
//===----------------------------------------------------------------------===//

void MachineConstantPoolValue::anchor() {}

unsigned MachineConstantPoolValue::getSizeInBytes(const DataLayout &DL) const {
  return DL.getTypeAllocSize(Ty);
}

unsigned MachineConstantPoolEntry::getSizeInBytes(const DataLayout &DL) const {
  if (isMachineConstantPoolEntry())
    return Val.MachineCPVal->getSizeInBytes(DL);
  return DL.getTypeAllocSize(Val.ConstVal->getType());
}

bool MachineConstantPoolEntry::needsRelocation() const {
  if (isMachineConstantPoolEntry())
    return true;
  return Val.ConstVal->needsDynamicRelocation();
}

SectionKind
MachineConstantPoolEntry::getSectionKind(const DataLayout *DL) const {
  if (needsRelocation())
    return SectionKind::getReadOnlyWithRel();
  switch (getSizeInBytes(*DL)) {
  case 4:
    return SectionKind::getMergeableConst4();
  case 8:
    return SectionKind::getMergeableConst8();
  case 16:
    return SectionKind::getMergeableConst16();
  case 32:
    return SectionKind::getMergeableConst32();
  default:
    return SectionKind::getReadOnly();
  }
}

MachineConstantPool::~MachineConstantPool() {
  // A constant may be a member of both Constants and MachineCPVsSharingEntries,
  // so keep track of which we've deleted to avoid double deletions.
  DenseSet<MachineConstantPoolValue*> Deleted;
  for (const MachineConstantPoolEntry &C : Constants)
    if (C.isMachineConstantPoolEntry()) {
      Deleted.insert(C.Val.MachineCPVal);
      delete C.Val.MachineCPVal;
    }
  for (MachineConstantPoolValue *CPV : MachineCPVsSharingEntries) {
    if (Deleted.count(CPV) == 0)
      delete CPV;
  }
}

/// Test whether the given two constants can be allocated the same constant pool
/// entry referenced by \param A.
static bool CanShareConstantPoolEntry(const Constant *A, const Constant *B,
                                      const DataLayout &DL) {
  // Handle the trivial case quickly.
  if (A == B) return true;

  // If they have the same type but weren't the same constant, quickly
  // reject them.
  if (A->getType() == B->getType()) return false;

  // We can't handle structs or arrays.
  if (isa<StructType>(A->getType()) || isa<ArrayType>(A->getType()) ||
      isa<StructType>(B->getType()) || isa<ArrayType>(B->getType()))
    return false;

  // For now, only support constants with the same size.
  uint64_t StoreSize = DL.getTypeStoreSize(A->getType());
  if (StoreSize != DL.getTypeStoreSize(B->getType()) || StoreSize > 128)
    return false;

  bool ContainsUndefOrPoisonA = A->containsUndefOrPoisonElement();

  Type *IntTy = IntegerType::get(A->getContext(), StoreSize*8);

  // Try constant folding a bitcast of both instructions to an integer.  If we
  // get two identical ConstantInt's, then we are good to share them.  We use
  // the constant folding APIs to do this so that we get the benefit of
  // DataLayout.
  if (isa<PointerType>(A->getType()))
    A = ConstantFoldCastOperand(Instruction::PtrToInt,
                                const_cast<Constant *>(A), IntTy, DL);
  else if (A->getType() != IntTy)
    A = ConstantFoldCastOperand(Instruction::BitCast, const_cast<Constant *>(A),
                                IntTy, DL);
  if (isa<PointerType>(B->getType()))
    B = ConstantFoldCastOperand(Instruction::PtrToInt,
                                const_cast<Constant *>(B), IntTy, DL);
  else if (B->getType() != IntTy)
    B = ConstantFoldCastOperand(Instruction::BitCast, const_cast<Constant *>(B),
                                IntTy, DL);

  if (A != B)
    return false;

  // Constants only safely match if A doesn't contain undef/poison.
  // As we'll be reusing A, it doesn't matter if B contain undef/poison.
  // TODO: Handle cases where A and B have the same undef/poison elements.
  // TODO: Merge A and B with mismatching undef/poison elements.
  return !ContainsUndefOrPoisonA;
}

/// Create a new entry in the constant pool or return an existing one.
/// User must specify the log2 of the minimum required alignment for the object.
unsigned MachineConstantPool::getConstantPoolIndex(const Constant *C,
                                                   Align Alignment) {
  if (Alignment > PoolAlignment) PoolAlignment = Alignment;

  // Check to see if we already have this constant.
  //
  // FIXME, this could be made much more efficient for large constant pools.
  for (unsigned i = 0, e = Constants.size(); i != e; ++i)
    if (!Constants[i].isMachineConstantPoolEntry() &&
        CanShareConstantPoolEntry(Constants[i].Val.ConstVal, C, DL)) {
      if (Constants[i].getAlign() < Alignment)
        Constants[i].Alignment = Alignment;
      return i;
    }

  Constants.push_back(MachineConstantPoolEntry(C, Alignment));
  return Constants.size()-1;
}

unsigned MachineConstantPool::getConstantPoolIndex(MachineConstantPoolValue *V,
                                                   Align Alignment) {
  if (Alignment > PoolAlignment) PoolAlignment = Alignment;

  // Check to see if we already have this constant.
  //
  // FIXME, this could be made much more efficient for large constant pools.
  int Idx = V->getExistingMachineCPValue(this, Alignment);
  if (Idx != -1) {
    MachineCPVsSharingEntries.insert(V);
    return (unsigned)Idx;
  }

  Constants.push_back(MachineConstantPoolEntry(V, Alignment));
  return Constants.size()-1;
}

void MachineConstantPool::print(raw_ostream &OS) const {
  if (Constants.empty()) return;

  OS << "Constant Pool:\n";
  for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
    OS << "  cp#" << i << ": ";
    if (Constants[i].isMachineConstantPoolEntry())
      Constants[i].Val.MachineCPVal->print(OS);
    else
      Constants[i].Val.ConstVal->printAsOperand(OS, /*PrintType=*/false);
    OS << ", align=" << Constants[i].getAlign().value();
    OS << "\n";
  }
}

//===----------------------------------------------------------------------===//
// Template specialization for MachineFunction implementation of
// ProfileSummaryInfo::getEntryCount().
//===----------------------------------------------------------------------===//
template <>
std::optional<Function::ProfileCount>
ProfileSummaryInfo::getEntryCount<llvm::MachineFunction>(
    const llvm::MachineFunction *F) const {
  return F->getFunction().getEntryCount();
}

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void MachineConstantPool::dump() const { print(dbgs()); }
#endif
