//===- 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.setIsSSA();
  Properties.setTracksLiveness();
  RegInfo = new (Allocator) MachineRegisterInfo(this);

  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();

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

  // Clear JumpTableInfo first. Otherwise, every MBB we delete would do a
  // linear search over the jump table entries to find and erase itself.
  if (JumpTableInfo) {
    JumpTableInfo->~MachineJumpTableInfo();
    Allocator.Deallocate(JumpTableInfo);
    JumpTableInfo = nullptr;
  }

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

Align MachineFunction::getPreferredAlignment() const {
  Align PrefAlignment;

  if (MaybeAlign A = F.getPreferredAlignment())
    PrefAlignment = *A;
  else if (!F.hasOptSize())
    PrefAlignment = STI.getTargetLowering()->getPrefFunctionAlignment();
  else
    PrefAlignment = Align(1);

  return std::max(PrefAlignment, getAlignment());
}

[[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, Value *DS) {
  return MachineInstr::ExtraInfo::create(Allocator, MMOs, PreInstrSymbol,
                                         PostInstrSymbol, HeapAllocMarker,
                                         PCSections, CFIType, MMRAs, DS);
}

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

MachineFunction::CallSiteInfo::CallSiteInfo(const CallBase &CB) {
  if (MDNode *Node = CB.getMetadata(llvm::LLVMContext::MD_call_target))
    CallTarget = Node;

  // Numeric callee_type ids are only for indirect calls.
  if (!CB.isIndirectCall())
    return;

  MDNode *CalleeTypeList = CB.getMetadata(LLVMContext::MD_callee_type);
  if (!CalleeTypeList)
    return;

  for (const MDOperand &Op : CalleeTypeList->operands()) {
    MDNode *TypeMD = cast<MDNode>(Op);
    MDString *TypeIdStr = cast<MDString>(TypeMD->getOperand(1));
    // Compute numeric type id from generalized type id string
    uint64_t TypeIdVal = MD5Hash(TypeIdStr->getString());
    IntegerType *Int64Ty = Type::getInt64Ty(CB.getContext());
    CalleeTypeIds.push_back(
        ConstantInt::get(Int64Ty, TypeIdVal, /*IsSigned=*/false));
  }
}

template <>
struct llvm::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;
  }
};

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 && !Target.Options.EmitCallGraphSection)
    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);

  CalledGlobalsInfo.erase(CallMI);
}

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] = std::move(CSInfo);
  }

  CalledGlobalsMap::iterator CGIt = CalledGlobalsInfo.find(OldCallMI);
  if (CGIt != CalledGlobalsInfo.end()) {
    CalledGlobalInfo CGInfo = CGIt->second;
    CalledGlobalsInfo[New] = std::move(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] = std::move(CSInfo);
  }

  CalledGlobalsMap::iterator CGIt = CalledGlobalsInfo.find(OldCallMI);
  if (CGIt != CalledGlobalsInfo.end()) {
    CalledGlobalInfo CGInfo = std::move(CGIt->second);
    CalledGlobalsInfo.erase(CGIt);
    CalledGlobalsInfo[New] = std::move(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(1).getReg();
      SubReg = Cpy.getOperand(2).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);
    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
