//===- LiveDebugVariables.cpp - Tracking debug info variables -------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file implements the LiveDebugVariables analysis.
//
// Remove all DBG_VALUE instructions referencing virtual registers and replace
// them with a data structure tracking where live user variables are kept - in a
// virtual register or in a stack slot.
//
// Allow the data structure to be updated during register allocation when values
// are moved between registers and stack slots. Finally emit new DBG_VALUE
// instructions after register allocation is complete.
//
//===----------------------------------------------------------------------===//

#include "LiveDebugVariables.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntervalMap.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/LexicalScopes.h"
#include "llvm/CodeGen/LiveInterval.h"
#include "llvm/CodeGen/LiveIntervals.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/SlotIndexes.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/CodeGen/VirtRegMap.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Metadata.h"
#include "llvm/InitializePasses.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Pass.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include <algorithm>
#include <cassert>
#include <iterator>
#include <memory>
#include <utility>

using namespace llvm;

#define DEBUG_TYPE "livedebugvars"

static cl::opt<bool>
EnableLDV("live-debug-variables", cl::init(true),
          cl::desc("Enable the live debug variables pass"), cl::Hidden);

STATISTIC(NumInsertedDebugValues, "Number of DBG_VALUEs inserted");
STATISTIC(NumInsertedDebugLabels, "Number of DBG_LABELs inserted");

char LiveDebugVariables::ID = 0;

INITIALIZE_PASS_BEGIN(LiveDebugVariables, DEBUG_TYPE,
                "Debug Variable Analysis", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
INITIALIZE_PASS_END(LiveDebugVariables, DEBUG_TYPE,
                "Debug Variable Analysis", false, false)

void LiveDebugVariables::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.addRequired<MachineDominatorTree>();
  AU.addRequiredTransitive<LiveIntervals>();
  AU.setPreservesAll();
  MachineFunctionPass::getAnalysisUsage(AU);
}

LiveDebugVariables::LiveDebugVariables() : MachineFunctionPass(ID) {
  initializeLiveDebugVariablesPass(*PassRegistry::getPassRegistry());
}

enum : unsigned { UndefLocNo = ~0U };

namespace {
/// Describes a debug variable value by location number and expression along
/// with some flags about the original usage of the location.
class DbgVariableValue {
public:
  DbgVariableValue(ArrayRef<unsigned> NewLocs, bool WasIndirect, bool WasList,
                   const DIExpression &Expr)
      : WasIndirect(WasIndirect), WasList(WasList), Expression(&Expr) {
    assert(!(WasIndirect && WasList) &&
           "DBG_VALUE_LISTs should not be indirect.");
    SmallVector<unsigned> LocNoVec;
    for (unsigned LocNo : NewLocs) {
      auto It = find(LocNoVec, LocNo);
      if (It == LocNoVec.end())
        LocNoVec.push_back(LocNo);
      else {
        // Loc duplicates an element in LocNos; replace references to Op
        // with references to the duplicating element.
        unsigned OpIdx = LocNoVec.size();
        unsigned DuplicatingIdx = std::distance(LocNoVec.begin(), It);
        Expression =
            DIExpression::replaceArg(Expression, OpIdx, DuplicatingIdx);
      }
    }
    // FIXME: Debug values referencing 64+ unique machine locations are rare and
    // currently unsupported for performance reasons. If we can verify that
    // performance is acceptable for such debug values, we can increase the
    // bit-width of LocNoCount to 14 to enable up to 16384 unique machine
    // locations. We will also need to verify that this does not cause issues
    // with LiveDebugVariables' use of IntervalMap.
    if (LocNoVec.size() < 64) {
      LocNoCount = LocNoVec.size();
      if (LocNoCount > 0) {
        LocNos = std::make_unique<unsigned[]>(LocNoCount);
        std::copy(LocNoVec.begin(), LocNoVec.end(), loc_nos_begin());
      }
    } else {
      LLVM_DEBUG(dbgs() << "Found debug value with 64+ unique machine "
                           "locations, dropping...\n");
      LocNoCount = 1;
      // Turn this into an undef debug value list; right now, the simplest form
      // of this is an expression with one arg, and an undef debug operand.
      Expression =
          DIExpression::get(Expr.getContext(), {dwarf::DW_OP_LLVM_arg, 0,
                                                dwarf::DW_OP_stack_value});
      if (auto FragmentInfoOpt = Expr.getFragmentInfo())
        Expression = *DIExpression::createFragmentExpression(
            Expression, FragmentInfoOpt->OffsetInBits,
            FragmentInfoOpt->SizeInBits);
      LocNos = std::make_unique<unsigned[]>(LocNoCount);
      LocNos[0] = UndefLocNo;
    }
  }

  DbgVariableValue() : LocNoCount(0), WasIndirect(false), WasList(false) {}
  DbgVariableValue(const DbgVariableValue &Other)
      : LocNoCount(Other.LocNoCount), WasIndirect(Other.getWasIndirect()),
        WasList(Other.getWasList()), Expression(Other.getExpression()) {
    if (Other.getLocNoCount()) {
      LocNos.reset(new unsigned[Other.getLocNoCount()]);
      std::copy(Other.loc_nos_begin(), Other.loc_nos_end(), loc_nos_begin());
    }
  }

  DbgVariableValue &operator=(const DbgVariableValue &Other) {
    if (this == &Other)
      return *this;
    if (Other.getLocNoCount()) {
      LocNos.reset(new unsigned[Other.getLocNoCount()]);
      std::copy(Other.loc_nos_begin(), Other.loc_nos_end(), loc_nos_begin());
    } else {
      LocNos.release();
    }
    LocNoCount = Other.getLocNoCount();
    WasIndirect = Other.getWasIndirect();
    WasList = Other.getWasList();
    Expression = Other.getExpression();
    return *this;
  }

  const DIExpression *getExpression() const { return Expression; }
  uint8_t getLocNoCount() const { return LocNoCount; }
  bool containsLocNo(unsigned LocNo) const {
    return is_contained(loc_nos(), LocNo);
  }
  bool getWasIndirect() const { return WasIndirect; }
  bool getWasList() const { return WasList; }
  bool isUndef() const { return LocNoCount == 0 || containsLocNo(UndefLocNo); }

  DbgVariableValue decrementLocNosAfterPivot(unsigned Pivot) const {
    SmallVector<unsigned, 4> NewLocNos;
    for (unsigned LocNo : loc_nos())
      NewLocNos.push_back(LocNo != UndefLocNo && LocNo > Pivot ? LocNo - 1
                                                               : LocNo);
    return DbgVariableValue(NewLocNos, WasIndirect, WasList, *Expression);
  }

  DbgVariableValue remapLocNos(ArrayRef<unsigned> LocNoMap) const {
    SmallVector<unsigned> NewLocNos;
    for (unsigned LocNo : loc_nos())
      // Undef values don't exist in locations (and thus not in LocNoMap
      // either) so skip over them. See getLocationNo().
      NewLocNos.push_back(LocNo == UndefLocNo ? UndefLocNo : LocNoMap[LocNo]);
    return DbgVariableValue(NewLocNos, WasIndirect, WasList, *Expression);
  }

  DbgVariableValue changeLocNo(unsigned OldLocNo, unsigned NewLocNo) const {
    SmallVector<unsigned> NewLocNos;
    NewLocNos.assign(loc_nos_begin(), loc_nos_end());
    auto OldLocIt = find(NewLocNos, OldLocNo);
    assert(OldLocIt != NewLocNos.end() && "Old location must be present.");
    *OldLocIt = NewLocNo;
    return DbgVariableValue(NewLocNos, WasIndirect, WasList, *Expression);
  }

  bool hasLocNoGreaterThan(unsigned LocNo) const {
    return any_of(loc_nos(),
                  [LocNo](unsigned ThisLocNo) { return ThisLocNo > LocNo; });
  }

  void printLocNos(llvm::raw_ostream &OS) const {
    for (const unsigned &Loc : loc_nos())
      OS << (&Loc == loc_nos_begin() ? " " : ", ") << Loc;
  }

  friend inline bool operator==(const DbgVariableValue &LHS,
                                const DbgVariableValue &RHS) {
    if (std::tie(LHS.LocNoCount, LHS.WasIndirect, LHS.WasList,
                 LHS.Expression) !=
        std::tie(RHS.LocNoCount, RHS.WasIndirect, RHS.WasList, RHS.Expression))
      return false;
    return std::equal(LHS.loc_nos_begin(), LHS.loc_nos_end(),
                      RHS.loc_nos_begin());
  }

  friend inline bool operator!=(const DbgVariableValue &LHS,
                                const DbgVariableValue &RHS) {
    return !(LHS == RHS);
  }

  unsigned *loc_nos_begin() { return LocNos.get(); }
  const unsigned *loc_nos_begin() const { return LocNos.get(); }
  unsigned *loc_nos_end() { return LocNos.get() + LocNoCount; }
  const unsigned *loc_nos_end() const { return LocNos.get() + LocNoCount; }
  ArrayRef<unsigned> loc_nos() const {
    return ArrayRef<unsigned>(LocNos.get(), LocNoCount);
  }

private:
  // IntervalMap requires the value object to be very small, to the extent
  // that we do not have enough room for an std::vector. Using a C-style array
  // (with a unique_ptr wrapper for convenience) allows us to optimize for this
  // specific case by packing the array size into only 6 bits (it is highly
  // unlikely that any debug value will need 64+ locations).
  std::unique_ptr<unsigned[]> LocNos;
  uint8_t LocNoCount : 6;
  bool WasIndirect : 1;
  bool WasList : 1;
  const DIExpression *Expression = nullptr;
};
} // namespace

/// Map of where a user value is live to that value.
using LocMap = IntervalMap<SlotIndex, DbgVariableValue, 4>;

/// Map of stack slot offsets for spilled locations.
/// Non-spilled locations are not added to the map.
using SpillOffsetMap = DenseMap<unsigned, unsigned>;

/// Cache to save the location where it can be used as the starting
/// position as input for calling MachineBasicBlock::SkipPHIsLabelsAndDebug.
/// This is to prevent MachineBasicBlock::SkipPHIsLabelsAndDebug from
/// repeatedly searching the same set of PHIs/Labels/Debug instructions
/// if it is called many times for the same block.
using BlockSkipInstsMap =
    DenseMap<MachineBasicBlock *, MachineBasicBlock::iterator>;

namespace {

class LDVImpl;

/// A user value is a part of a debug info user variable.
///
/// A DBG_VALUE instruction notes that (a sub-register of) a virtual register
/// holds part of a user variable. The part is identified by a byte offset.
///
/// UserValues are grouped into equivalence classes for easier searching. Two
/// user values are related if they are held by the same virtual register. The
/// equivalence class is the transitive closure of that relation.
class UserValue {
  const DILocalVariable *Variable; ///< The debug info variable we are part of.
  /// The part of the variable we describe.
  const Optional<DIExpression::FragmentInfo> Fragment;
  DebugLoc dl;            ///< The debug location for the variable. This is
                          ///< used by dwarf writer to find lexical scope.
  UserValue *leader;      ///< Equivalence class leader.
  UserValue *next = nullptr; ///< Next value in equivalence class, or null.

  /// Numbered locations referenced by locmap.
  SmallVector<MachineOperand, 4> locations;

  /// Map of slot indices where this value is live.
  LocMap locInts;

  /// Set of interval start indexes that have been trimmed to the
  /// lexical scope.
  SmallSet<SlotIndex, 2> trimmedDefs;

  /// Insert a DBG_VALUE into MBB at Idx for DbgValue.
  void insertDebugValue(MachineBasicBlock *MBB, SlotIndex StartIdx,
                        SlotIndex StopIdx, DbgVariableValue DbgValue,
                        ArrayRef<bool> LocSpills,
                        ArrayRef<unsigned> SpillOffsets, LiveIntervals &LIS,
                        const TargetInstrInfo &TII,
                        const TargetRegisterInfo &TRI,
                        BlockSkipInstsMap &BBSkipInstsMap);

  /// Replace OldLocNo ranges with NewRegs ranges where NewRegs
  /// is live. Returns true if any changes were made.
  bool splitLocation(unsigned OldLocNo, ArrayRef<Register> NewRegs,
                     LiveIntervals &LIS);

public:
  /// Create a new UserValue.
  UserValue(const DILocalVariable *var,
            Optional<DIExpression::FragmentInfo> Fragment, DebugLoc L,
            LocMap::Allocator &alloc)
      : Variable(var), Fragment(Fragment), dl(std::move(L)), leader(this),
        locInts(alloc) {}

  /// Get the leader of this value's equivalence class.
  UserValue *getLeader() {
    UserValue *l = leader;
    while (l != l->leader)
      l = l->leader;
    return leader = l;
  }

  /// Return the next UserValue in the equivalence class.
  UserValue *getNext() const { return next; }

  /// Merge equivalence classes.
  static UserValue *merge(UserValue *L1, UserValue *L2) {
    L2 = L2->getLeader();
    if (!L1)
      return L2;
    L1 = L1->getLeader();
    if (L1 == L2)
      return L1;
    // Splice L2 before L1's members.
    UserValue *End = L2;
    while (End->next) {
      End->leader = L1;
      End = End->next;
    }
    End->leader = L1;
    End->next = L1->next;
    L1->next = L2;
    return L1;
  }

  /// Return the location number that matches Loc.
  ///
  /// For undef values we always return location number UndefLocNo without
  /// inserting anything in locations. Since locations is a vector and the
  /// location number is the position in the vector and UndefLocNo is ~0,
  /// we would need a very big vector to put the value at the right position.
  unsigned getLocationNo(const MachineOperand &LocMO) {
    if (LocMO.isReg()) {
      if (LocMO.getReg() == 0)
        return UndefLocNo;
      // For register locations we dont care about use/def and other flags.
      for (unsigned i = 0, e = locations.size(); i != e; ++i)
        if (locations[i].isReg() &&
            locations[i].getReg() == LocMO.getReg() &&
            locations[i].getSubReg() == LocMO.getSubReg())
          return i;
    } else
      for (unsigned i = 0, e = locations.size(); i != e; ++i)
        if (LocMO.isIdenticalTo(locations[i]))
          return i;
    locations.push_back(LocMO);
    // We are storing a MachineOperand outside a MachineInstr.
    locations.back().clearParent();
    // Don't store def operands.
    if (locations.back().isReg()) {
      if (locations.back().isDef())
        locations.back().setIsDead(false);
      locations.back().setIsUse();
    }
    return locations.size() - 1;
  }

  /// Remove (recycle) a location number. If \p LocNo still is used by the
  /// locInts nothing is done.
  void removeLocationIfUnused(unsigned LocNo) {
    // Bail out if LocNo still is used.
    for (LocMap::const_iterator I = locInts.begin(); I.valid(); ++I) {
      const DbgVariableValue &DbgValue = I.value();
      if (DbgValue.containsLocNo(LocNo))
        return;
    }
    // Remove the entry in the locations vector, and adjust all references to
    // location numbers above the removed entry.
    locations.erase(locations.begin() + LocNo);
    for (LocMap::iterator I = locInts.begin(); I.valid(); ++I) {
      const DbgVariableValue &DbgValue = I.value();
      if (DbgValue.hasLocNoGreaterThan(LocNo))
        I.setValueUnchecked(DbgValue.decrementLocNosAfterPivot(LocNo));
    }
  }

  /// Ensure that all virtual register locations are mapped.
  void mapVirtRegs(LDVImpl *LDV);

  /// Add a definition point to this user value.
  void addDef(SlotIndex Idx, ArrayRef<MachineOperand> LocMOs, bool IsIndirect,
              bool IsList, const DIExpression &Expr) {
    SmallVector<unsigned> Locs;
    for (const MachineOperand &Op : LocMOs)
      Locs.push_back(getLocationNo(Op));
    DbgVariableValue DbgValue(Locs, IsIndirect, IsList, Expr);
    // Add a singular (Idx,Idx) -> value mapping.
    LocMap::iterator I = locInts.find(Idx);
    if (!I.valid() || I.start() != Idx)
      I.insert(Idx, Idx.getNextSlot(), std::move(DbgValue));
    else
      // A later DBG_VALUE at the same SlotIndex overrides the old location.
      I.setValue(std::move(DbgValue));
  }

  /// Extend the current definition as far as possible down.
  ///
  /// Stop when meeting an existing def or when leaving the live
  /// range of VNI. End points where VNI is no longer live are added to Kills.
  ///
  /// We only propagate DBG_VALUES locally here. LiveDebugValues performs a
  /// data-flow analysis to propagate them beyond basic block boundaries.
  ///
  /// \param Idx Starting point for the definition.
  /// \param DbgValue value to propagate.
  /// \param LiveIntervalInfo For each location number key in this map,
  /// restricts liveness to where the LiveRange has the value equal to the\
  /// VNInfo.
  /// \param [out] Kills Append end points of VNI's live range to Kills.
  /// \param LIS Live intervals analysis.
  void extendDef(SlotIndex Idx, DbgVariableValue DbgValue,
                 SmallDenseMap<unsigned, std::pair<LiveRange *, const VNInfo *>>
                     &LiveIntervalInfo,
                 Optional<std::pair<SlotIndex, SmallVector<unsigned>>> &Kills,
                 LiveIntervals &LIS);

  /// The value in LI may be copies to other registers. Determine if
  /// any of the copies are available at the kill points, and add defs if
  /// possible.
  ///
  /// \param DbgValue Location number of LI->reg, and DIExpression.
  /// \param LocIntervals Scan for copies of the value for each location in the
  /// corresponding LiveInterval->reg.
  /// \param KilledAt The point where the range of DbgValue could be extended.
  /// \param [in,out] NewDefs Append (Idx, DbgValue) of inserted defs here.
  void addDefsFromCopies(
      DbgVariableValue DbgValue,
      SmallVectorImpl<std::pair<unsigned, LiveInterval *>> &LocIntervals,
      SlotIndex KilledAt,
      SmallVectorImpl<std::pair<SlotIndex, DbgVariableValue>> &NewDefs,
      MachineRegisterInfo &MRI, LiveIntervals &LIS);

  /// Compute the live intervals of all locations after collecting all their
  /// def points.
  void computeIntervals(MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
                        LiveIntervals &LIS, LexicalScopes &LS);

  /// Replace OldReg ranges with NewRegs ranges where NewRegs is
  /// live. Returns true if any changes were made.
  bool splitRegister(Register OldReg, ArrayRef<Register> NewRegs,
                     LiveIntervals &LIS);

  /// Rewrite virtual register locations according to the provided virtual
  /// register map. Record the stack slot offsets for the locations that
  /// were spilled.
  void rewriteLocations(VirtRegMap &VRM, const MachineFunction &MF,
                        const TargetInstrInfo &TII,
                        const TargetRegisterInfo &TRI,
                        SpillOffsetMap &SpillOffsets);

  /// Recreate DBG_VALUE instruction from data structures.
  void emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS,
                       const TargetInstrInfo &TII,
                       const TargetRegisterInfo &TRI,
                       const SpillOffsetMap &SpillOffsets,
                       BlockSkipInstsMap &BBSkipInstsMap);

  /// Return DebugLoc of this UserValue.
  const DebugLoc &getDebugLoc() { return dl; }

  void print(raw_ostream &, const TargetRegisterInfo *);
};

/// A user label is a part of a debug info user label.
class UserLabel {
  const DILabel *Label; ///< The debug info label we are part of.
  DebugLoc dl;          ///< The debug location for the label. This is
                        ///< used by dwarf writer to find lexical scope.
  SlotIndex loc;        ///< Slot used by the debug label.

  /// Insert a DBG_LABEL into MBB at Idx.
  void insertDebugLabel(MachineBasicBlock *MBB, SlotIndex Idx,
                        LiveIntervals &LIS, const TargetInstrInfo &TII,
                        BlockSkipInstsMap &BBSkipInstsMap);

public:
  /// Create a new UserLabel.
  UserLabel(const DILabel *label, DebugLoc L, SlotIndex Idx)
      : Label(label), dl(std::move(L)), loc(Idx) {}

  /// Does this UserLabel match the parameters?
  bool matches(const DILabel *L, const DILocation *IA,
             const SlotIndex Index) const {
    return Label == L && dl->getInlinedAt() == IA && loc == Index;
  }

  /// Recreate DBG_LABEL instruction from data structures.
  void emitDebugLabel(LiveIntervals &LIS, const TargetInstrInfo &TII,
                      BlockSkipInstsMap &BBSkipInstsMap);

  /// Return DebugLoc of this UserLabel.
  const DebugLoc &getDebugLoc() { return dl; }

  void print(raw_ostream &, const TargetRegisterInfo *);
};

/// Implementation of the LiveDebugVariables pass.
class LDVImpl {
  LiveDebugVariables &pass;
  LocMap::Allocator allocator;
  MachineFunction *MF = nullptr;
  LiveIntervals *LIS;
  const TargetRegisterInfo *TRI;

  /// Position and VReg of a PHI instruction during register allocation.
  struct PHIValPos {
    SlotIndex SI;    /// Slot where this PHI occurs.
    Register Reg;    /// VReg this PHI occurs in.
    unsigned SubReg; /// Qualifiying subregister for Reg.
  };

  /// Map from debug instruction number to PHI position during allocation.
  std::map<unsigned, PHIValPos> PHIValToPos;
  /// Index of, for each VReg, which debug instruction numbers and corresponding
  /// PHIs are sensitive to splitting. Each VReg may have multiple PHI defs,
  /// at different positions.
  DenseMap<Register, std::vector<unsigned>> RegToPHIIdx;

  /// Record for any debug instructions unlinked from their blocks during
  /// regalloc. Stores the instr and it's location, so that they can be
  /// re-inserted after regalloc is over.
  struct InstrPos {
    MachineInstr *MI;       ///< Debug instruction, unlinked from it's block.
    SlotIndex Idx;          ///< Slot position where MI should be re-inserted.
    MachineBasicBlock *MBB; ///< Block that MI was in.
  };

  /// Collection of stored debug instructions, preserved until after regalloc.
  SmallVector<InstrPos, 32> StashedDebugInstrs;

  /// Whether emitDebugValues is called.
  bool EmitDone = false;

  /// Whether the machine function is modified during the pass.
  bool ModifiedMF = false;

  /// All allocated UserValue instances.
  SmallVector<std::unique_ptr<UserValue>, 8> userValues;

  /// All allocated UserLabel instances.
  SmallVector<std::unique_ptr<UserLabel>, 2> userLabels;

  /// Map virtual register to eq class leader.
  using VRMap = DenseMap<unsigned, UserValue *>;
  VRMap virtRegToEqClass;

  /// Map to find existing UserValue instances.
  using UVMap = DenseMap<DebugVariable, UserValue *>;
  UVMap userVarMap;

  /// Find or create a UserValue.
  UserValue *getUserValue(const DILocalVariable *Var,
                          Optional<DIExpression::FragmentInfo> Fragment,
                          const DebugLoc &DL);

  /// Find the EC leader for VirtReg or null.
  UserValue *lookupVirtReg(Register VirtReg);

  /// Add DBG_VALUE instruction to our maps.
  ///
  /// \param MI DBG_VALUE instruction
  /// \param Idx Last valid SLotIndex before instruction.
  ///
  /// \returns True if the DBG_VALUE instruction should be deleted.
  bool handleDebugValue(MachineInstr &MI, SlotIndex Idx);

  /// Track variable location debug instructions while using the instruction
  /// referencing implementation. Such debug instructions do not need to be
  /// updated during regalloc because they identify instructions rather than
  /// register locations. However, they needs to be removed from the
  /// MachineFunction during regalloc, then re-inserted later, to avoid
  /// disrupting the allocator.
  ///
  /// \param MI Any DBG_VALUE / DBG_INSTR_REF / DBG_PHI instruction
  /// \param Idx Last valid SlotIndex before instruction
  ///
  /// \returns Iterator to continue processing from after unlinking.
  MachineBasicBlock::iterator handleDebugInstr(MachineInstr &MI, SlotIndex Idx);

  /// Add DBG_LABEL instruction to UserLabel.
  ///
  /// \param MI DBG_LABEL instruction
  /// \param Idx Last valid SlotIndex before instruction.
  ///
  /// \returns True if the DBG_LABEL instruction should be deleted.
  bool handleDebugLabel(MachineInstr &MI, SlotIndex Idx);

  /// Collect and erase all DBG_VALUE instructions, adding a UserValue def
  /// for each instruction.
  ///
  /// \param mf MachineFunction to be scanned.
  /// \param InstrRef Whether to operate in instruction referencing mode. If
  ///        true, most of LiveDebugVariables doesn't run.
  ///
  /// \returns True if any debug values were found.
  bool collectDebugValues(MachineFunction &mf, bool InstrRef);

  /// Compute the live intervals of all user values after collecting all
  /// their def points.
  void computeIntervals();

public:
  LDVImpl(LiveDebugVariables *ps) : pass(*ps) {}

  bool runOnMachineFunction(MachineFunction &mf, bool InstrRef);

  /// Release all memory.
  void clear() {
    MF = nullptr;
    PHIValToPos.clear();
    RegToPHIIdx.clear();
    StashedDebugInstrs.clear();
    userValues.clear();
    userLabels.clear();
    virtRegToEqClass.clear();
    userVarMap.clear();
    // Make sure we call emitDebugValues if the machine function was modified.
    assert((!ModifiedMF || EmitDone) &&
           "Dbg values are not emitted in LDV");
    EmitDone = false;
    ModifiedMF = false;
  }

  /// Map virtual register to an equivalence class.
  void mapVirtReg(Register VirtReg, UserValue *EC);

  /// Replace any PHI referring to OldReg with its corresponding NewReg, if
  /// present.
  void splitPHIRegister(Register OldReg, ArrayRef<Register> NewRegs);

  /// Replace all references to OldReg with NewRegs.
  void splitRegister(Register OldReg, ArrayRef<Register> NewRegs);

  /// Recreate DBG_VALUE instruction from data structures.
  void emitDebugValues(VirtRegMap *VRM);

  void print(raw_ostream&);
};

} // end anonymous namespace

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
static void printDebugLoc(const DebugLoc &DL, raw_ostream &CommentOS,
                          const LLVMContext &Ctx) {
  if (!DL)
    return;

  auto *Scope = cast<DIScope>(DL.getScope());
  // Omit the directory, because it's likely to be long and uninteresting.
  CommentOS << Scope->getFilename();
  CommentOS << ':' << DL.getLine();
  if (DL.getCol() != 0)
    CommentOS << ':' << DL.getCol();

  DebugLoc InlinedAtDL = DL.getInlinedAt();
  if (!InlinedAtDL)
    return;

  CommentOS << " @[ ";
  printDebugLoc(InlinedAtDL, CommentOS, Ctx);
  CommentOS << " ]";
}

static void printExtendedName(raw_ostream &OS, const DINode *Node,
                              const DILocation *DL) {
  const LLVMContext &Ctx = Node->getContext();
  StringRef Res;
  unsigned Line = 0;
  if (const auto *V = dyn_cast<const DILocalVariable>(Node)) {
    Res = V->getName();
    Line = V->getLine();
  } else if (const auto *L = dyn_cast<const DILabel>(Node)) {
    Res = L->getName();
    Line = L->getLine();
  }

  if (!Res.empty())
    OS << Res << "," << Line;
  auto *InlinedAt = DL ? DL->getInlinedAt() : nullptr;
  if (InlinedAt) {
    if (DebugLoc InlinedAtDL = InlinedAt) {
      OS << " @[";
      printDebugLoc(InlinedAtDL, OS, Ctx);
      OS << "]";
    }
  }
}

void UserValue::print(raw_ostream &OS, const TargetRegisterInfo *TRI) {
  OS << "!\"";
  printExtendedName(OS, Variable, dl);

  OS << "\"\t";
  for (LocMap::const_iterator I = locInts.begin(); I.valid(); ++I) {
    OS << " [" << I.start() << ';' << I.stop() << "):";
    if (I.value().isUndef())
      OS << " undef";
    else {
      I.value().printLocNos(OS);
      if (I.value().getWasIndirect())
        OS << " ind";
      else if (I.value().getWasList())
        OS << " list";
    }
  }
  for (unsigned i = 0, e = locations.size(); i != e; ++i) {
    OS << " Loc" << i << '=';
    locations[i].print(OS, TRI);
  }
  OS << '\n';
}

void UserLabel::print(raw_ostream &OS, const TargetRegisterInfo *TRI) {
  OS << "!\"";
  printExtendedName(OS, Label, dl);

  OS << "\"\t";
  OS << loc;
  OS << '\n';
}

void LDVImpl::print(raw_ostream &OS) {
  OS << "********** DEBUG VARIABLES **********\n";
  for (auto &userValue : userValues)
    userValue->print(OS, TRI);
  OS << "********** DEBUG LABELS **********\n";
  for (auto &userLabel : userLabels)
    userLabel->print(OS, TRI);
}
#endif

void UserValue::mapVirtRegs(LDVImpl *LDV) {
  for (unsigned i = 0, e = locations.size(); i != e; ++i)
    if (locations[i].isReg() &&
        Register::isVirtualRegister(locations[i].getReg()))
      LDV->mapVirtReg(locations[i].getReg(), this);
}

UserValue *LDVImpl::getUserValue(const DILocalVariable *Var,
                                 Optional<DIExpression::FragmentInfo> Fragment,
                                 const DebugLoc &DL) {
  // FIXME: Handle partially overlapping fragments. See
  // https://reviews.llvm.org/D70121#1849741.
  DebugVariable ID(Var, Fragment, DL->getInlinedAt());
  UserValue *&UV = userVarMap[ID];
  if (!UV) {
    userValues.push_back(
        std::make_unique<UserValue>(Var, Fragment, DL, allocator));
    UV = userValues.back().get();
  }
  return UV;
}

void LDVImpl::mapVirtReg(Register VirtReg, UserValue *EC) {
  assert(Register::isVirtualRegister(VirtReg) && "Only map VirtRegs");
  UserValue *&Leader = virtRegToEqClass[VirtReg];
  Leader = UserValue::merge(Leader, EC);
}

UserValue *LDVImpl::lookupVirtReg(Register VirtReg) {
  if (UserValue *UV = virtRegToEqClass.lookup(VirtReg))
    return UV->getLeader();
  return nullptr;
}

bool LDVImpl::handleDebugValue(MachineInstr &MI, SlotIndex Idx) {
  // DBG_VALUE loc, offset, variable, expr
  // DBG_VALUE_LIST variable, expr, locs...
  if (!MI.isDebugValue()) {
    LLVM_DEBUG(dbgs() << "Can't handle non-DBG_VALUE*: " << MI);
    return false;
  }
  if (!MI.getDebugVariableOp().isMetadata()) {
    LLVM_DEBUG(dbgs() << "Can't handle DBG_VALUE* with invalid variable: "
                      << MI);
    return false;
  }
  if (MI.isNonListDebugValue() &&
      (MI.getNumOperands() != 4 ||
       !(MI.getDebugOffset().isImm() || MI.getDebugOffset().isReg()))) {
    LLVM_DEBUG(dbgs() << "Can't handle malformed DBG_VALUE: " << MI);
    return false;
  }

  // Detect invalid DBG_VALUE instructions, with a debug-use of a virtual
  // register that hasn't been defined yet. If we do not remove those here, then
  // the re-insertion of the DBG_VALUE instruction after register allocation
  // will be incorrect.
  bool Discard = false;
  for (const MachineOperand &Op : MI.debug_operands()) {
    if (Op.isReg() && Register::isVirtualRegister(Op.getReg())) {
      const Register Reg = Op.getReg();
      if (!LIS->hasInterval(Reg)) {
        // The DBG_VALUE is described by a virtual register that does not have a
        // live interval. Discard the DBG_VALUE.
        Discard = true;
        LLVM_DEBUG(dbgs() << "Discarding debug info (no LIS interval): " << Idx
                          << " " << MI);
      } else {
        // The DBG_VALUE is only valid if either Reg is live out from Idx, or
        // Reg is defined dead at Idx (where Idx is the slot index for the
        // instruction preceding the DBG_VALUE).
        const LiveInterval &LI = LIS->getInterval(Reg);
        LiveQueryResult LRQ = LI.Query(Idx);
        if (!LRQ.valueOutOrDead()) {
          // We have found a DBG_VALUE with the value in a virtual register that
          // is not live. Discard the DBG_VALUE.
          Discard = true;
          LLVM_DEBUG(dbgs() << "Discarding debug info (reg not live): " << Idx
                            << " " << MI);
        }
      }
    }
  }

  // Get or create the UserValue for (variable,offset) here.
  bool IsIndirect = MI.isDebugOffsetImm();
  if (IsIndirect)
    assert(MI.getDebugOffset().getImm() == 0 &&
           "DBG_VALUE with nonzero offset");
  bool IsList = MI.isDebugValueList();
  const DILocalVariable *Var = MI.getDebugVariable();
  const DIExpression *Expr = MI.getDebugExpression();
  UserValue *UV = getUserValue(Var, Expr->getFragmentInfo(), MI.getDebugLoc());
  if (!Discard)
    UV->addDef(Idx,
               ArrayRef<MachineOperand>(MI.debug_operands().begin(),
                                        MI.debug_operands().end()),
               IsIndirect, IsList, *Expr);
  else {
    MachineOperand MO = MachineOperand::CreateReg(0U, false);
    MO.setIsDebug();
    // We should still pass a list the same size as MI.debug_operands() even if
    // all MOs are undef, so that DbgVariableValue can correctly adjust the
    // expression while removing the duplicated undefs.
    SmallVector<MachineOperand, 4> UndefMOs(MI.getNumDebugOperands(), MO);
    UV->addDef(Idx, UndefMOs, false, IsList, *Expr);
  }
  return true;
}

MachineBasicBlock::iterator LDVImpl::handleDebugInstr(MachineInstr &MI,
                                                      SlotIndex Idx) {
  assert(MI.isDebugValue() || MI.isDebugRef() || MI.isDebugPHI());

  // In instruction referencing mode, there should be no DBG_VALUE instructions
  // that refer to virtual registers. They might still refer to constants.
  if (MI.isDebugValue())
    assert(!MI.getOperand(0).isReg() || !MI.getOperand(0).getReg().isVirtual());

  // Unlink the instruction, store it in the debug instructions collection.
  auto NextInst = std::next(MI.getIterator());
  auto *MBB = MI.getParent();
  MI.removeFromParent();
  StashedDebugInstrs.push_back({&MI, Idx, MBB});
  return NextInst;
}

bool LDVImpl::handleDebugLabel(MachineInstr &MI, SlotIndex Idx) {
  // DBG_LABEL label
  if (MI.getNumOperands() != 1 || !MI.getOperand(0).isMetadata()) {
    LLVM_DEBUG(dbgs() << "Can't handle " << MI);
    return false;
  }

  // Get or create the UserLabel for label here.
  const DILabel *Label = MI.getDebugLabel();
  const DebugLoc &DL = MI.getDebugLoc();
  bool Found = false;
  for (auto const &L : userLabels) {
    if (L->matches(Label, DL->getInlinedAt(), Idx)) {
      Found = true;
      break;
    }
  }
  if (!Found)
    userLabels.push_back(std::make_unique<UserLabel>(Label, DL, Idx));

  return true;
}

bool LDVImpl::collectDebugValues(MachineFunction &mf, bool InstrRef) {
  bool Changed = false;
  for (MachineBasicBlock &MBB : mf) {
    for (MachineBasicBlock::iterator MBBI = MBB.begin(), MBBE = MBB.end();
         MBBI != MBBE;) {
      // Use the first debug instruction in the sequence to get a SlotIndex
      // for following consecutive debug instructions.
      if (!MBBI->isDebugOrPseudoInstr()) {
        ++MBBI;
        continue;
      }
      // Debug instructions has no slot index. Use the previous
      // non-debug instruction's SlotIndex as its SlotIndex.
      SlotIndex Idx =
          MBBI == MBB.begin()
              ? LIS->getMBBStartIdx(&MBB)
              : LIS->getInstructionIndex(*std::prev(MBBI)).getRegSlot();
      // Handle consecutive debug instructions with the same slot index.
      do {
        // In instruction referencing mode, pass each instr to handleDebugInstr
        // to be unlinked. Ignore DBG_VALUE_LISTs -- they refer to vregs, and
        // need to go through the normal live interval splitting process.
        if (InstrRef && (MBBI->isNonListDebugValue() || MBBI->isDebugPHI() ||
                         MBBI->isDebugRef())) {
          MBBI = handleDebugInstr(*MBBI, Idx);
          Changed = true;
        // In normal debug mode, use the dedicated DBG_VALUE / DBG_LABEL handler
        // to track things through register allocation, and erase the instr.
        } else if ((MBBI->isDebugValue() && handleDebugValue(*MBBI, Idx)) ||
                   (MBBI->isDebugLabel() && handleDebugLabel(*MBBI, Idx))) {
          MBBI = MBB.erase(MBBI);
          Changed = true;
        } else
          ++MBBI;
      } while (MBBI != MBBE && MBBI->isDebugOrPseudoInstr());
    }
  }
  return Changed;
}

void UserValue::extendDef(
    SlotIndex Idx, DbgVariableValue DbgValue,
    SmallDenseMap<unsigned, std::pair<LiveRange *, const VNInfo *>>
        &LiveIntervalInfo,
    Optional<std::pair<SlotIndex, SmallVector<unsigned>>> &Kills,
    LiveIntervals &LIS) {
  SlotIndex Start = Idx;
  MachineBasicBlock *MBB = LIS.getMBBFromIndex(Start);
  SlotIndex Stop = LIS.getMBBEndIdx(MBB);
  LocMap::iterator I = locInts.find(Start);

  // Limit to the intersection of the VNIs' live ranges.
  for (auto &LII : LiveIntervalInfo) {
    LiveRange *LR = LII.second.first;
    assert(LR && LII.second.second && "Missing range info for Idx.");
    LiveInterval::Segment *Segment = LR->getSegmentContaining(Start);
    assert(Segment && Segment->valno == LII.second.second &&
           "Invalid VNInfo for Idx given?");
    if (Segment->end < Stop) {
      Stop = Segment->end;
      Kills = {Stop, {LII.first}};
    } else if (Segment->end == Stop && Kills.hasValue()) {
      // If multiple locations end at the same place, track all of them in
      // Kills.
      Kills->second.push_back(LII.first);
    }
  }

  // There could already be a short def at Start.
  if (I.valid() && I.start() <= Start) {
    // Stop when meeting a different location or an already extended interval.
    Start = Start.getNextSlot();
    if (I.value() != DbgValue || I.stop() != Start) {
      // Clear `Kills`, as we have a new def available.
      Kills = None;
      return;
    }
    // This is a one-slot placeholder. Just skip it.
    ++I;
  }

  // Limited by the next def.
  if (I.valid() && I.start() < Stop) {
    Stop = I.start();
    // Clear `Kills`, as we have a new def available.
    Kills = None;
  }

  if (Start < Stop) {
    DbgVariableValue ExtDbgValue(DbgValue);
    I.insert(Start, Stop, std::move(ExtDbgValue));
  }
}

void UserValue::addDefsFromCopies(
    DbgVariableValue DbgValue,
    SmallVectorImpl<std::pair<unsigned, LiveInterval *>> &LocIntervals,
    SlotIndex KilledAt,
    SmallVectorImpl<std::pair<SlotIndex, DbgVariableValue>> &NewDefs,
    MachineRegisterInfo &MRI, LiveIntervals &LIS) {
  // Don't track copies from physregs, there are too many uses.
  if (any_of(LocIntervals, [](auto LocI) {
        return !Register::isVirtualRegister(LocI.second->reg());
      }))
    return;

  // Collect all the (vreg, valno) pairs that are copies of LI.
  SmallDenseMap<unsigned,
                SmallVector<std::pair<LiveInterval *, const VNInfo *>, 4>>
      CopyValues;
  for (auto &LocInterval : LocIntervals) {
    unsigned LocNo = LocInterval.first;
    LiveInterval *LI = LocInterval.second;
    for (MachineOperand &MO : MRI.use_nodbg_operands(LI->reg())) {
      MachineInstr *MI = MO.getParent();
      // Copies of the full value.
      if (MO.getSubReg() || !MI->isCopy())
        continue;
      Register DstReg = MI->getOperand(0).getReg();

      // Don't follow copies to physregs. These are usually setting up call
      // arguments, and the argument registers are always call clobbered. We are
      // better off in the source register which could be a callee-saved
      // register, or it could be spilled.
      if (!Register::isVirtualRegister(DstReg))
        continue;

      // Is the value extended to reach this copy? If not, another def may be
      // blocking it, or we are looking at a wrong value of LI.
      SlotIndex Idx = LIS.getInstructionIndex(*MI);
      LocMap::iterator I = locInts.find(Idx.getRegSlot(true));
      if (!I.valid() || I.value() != DbgValue)
        continue;

      if (!LIS.hasInterval(DstReg))
        continue;
      LiveInterval *DstLI = &LIS.getInterval(DstReg);
      const VNInfo *DstVNI = DstLI->getVNInfoAt(Idx.getRegSlot());
      assert(DstVNI && DstVNI->def == Idx.getRegSlot() && "Bad copy value");
      CopyValues[LocNo].push_back(std::make_pair(DstLI, DstVNI));
    }
  }

  if (CopyValues.empty())
    return;

#if !defined(NDEBUG)
  for (auto &LocInterval : LocIntervals)
    LLVM_DEBUG(dbgs() << "Got " << CopyValues[LocInterval.first].size()
                      << " copies of " << *LocInterval.second << '\n');
#endif

  // Try to add defs of the copied values for the kill point. Check that there
  // isn't already a def at Idx.
  LocMap::iterator I = locInts.find(KilledAt);
  if (I.valid() && I.start() <= KilledAt)
    return;
  DbgVariableValue NewValue(DbgValue);
  for (auto &LocInterval : LocIntervals) {
    unsigned LocNo = LocInterval.first;
    bool FoundCopy = false;
    for (auto &LIAndVNI : CopyValues[LocNo]) {
      LiveInterval *DstLI = LIAndVNI.first;
      const VNInfo *DstVNI = LIAndVNI.second;
      if (DstLI->getVNInfoAt(KilledAt) != DstVNI)
        continue;
      LLVM_DEBUG(dbgs() << "Kill at " << KilledAt << " covered by valno #"
                        << DstVNI->id << " in " << *DstLI << '\n');
      MachineInstr *CopyMI = LIS.getInstructionFromIndex(DstVNI->def);
      assert(CopyMI && CopyMI->isCopy() && "Bad copy value");
      unsigned NewLocNo = getLocationNo(CopyMI->getOperand(0));
      NewValue = NewValue.changeLocNo(LocNo, NewLocNo);
      FoundCopy = true;
      break;
    }
    // If there are any killed locations we can't find a copy for, we can't
    // extend the variable value.
    if (!FoundCopy)
      return;
  }
  I.insert(KilledAt, KilledAt.getNextSlot(), NewValue);
  NewDefs.push_back(std::make_pair(KilledAt, NewValue));
}

void UserValue::computeIntervals(MachineRegisterInfo &MRI,
                                 const TargetRegisterInfo &TRI,
                                 LiveIntervals &LIS, LexicalScopes &LS) {
  SmallVector<std::pair<SlotIndex, DbgVariableValue>, 16> Defs;

  // Collect all defs to be extended (Skipping undefs).
  for (LocMap::const_iterator I = locInts.begin(); I.valid(); ++I)
    if (!I.value().isUndef())
      Defs.push_back(std::make_pair(I.start(), I.value()));

  // Extend all defs, and possibly add new ones along the way.
  for (unsigned i = 0; i != Defs.size(); ++i) {
    SlotIndex Idx = Defs[i].first;
    DbgVariableValue DbgValue = Defs[i].second;
    SmallDenseMap<unsigned, std::pair<LiveRange *, const VNInfo *>> LIs;
    SmallVector<const VNInfo *, 4> VNIs;
    bool ShouldExtendDef = false;
    for (unsigned LocNo : DbgValue.loc_nos()) {
      const MachineOperand &LocMO = locations[LocNo];
      if (!LocMO.isReg() || !Register::isVirtualRegister(LocMO.getReg())) {
        ShouldExtendDef |= !LocMO.isReg();
        continue;
      }
      ShouldExtendDef = true;
      LiveInterval *LI = nullptr;
      const VNInfo *VNI = nullptr;
      if (LIS.hasInterval(LocMO.getReg())) {
        LI = &LIS.getInterval(LocMO.getReg());
        VNI = LI->getVNInfoAt(Idx);
      }
      if (LI && VNI)
        LIs[LocNo] = {LI, VNI};
    }
    if (ShouldExtendDef) {
      Optional<std::pair<SlotIndex, SmallVector<unsigned>>> Kills;
      extendDef(Idx, DbgValue, LIs, Kills, LIS);

      if (Kills) {
        SmallVector<std::pair<unsigned, LiveInterval *>, 2> KilledLocIntervals;
        bool AnySubreg = false;
        for (unsigned LocNo : Kills->second) {
          const MachineOperand &LocMO = this->locations[LocNo];
          if (LocMO.getSubReg()) {
            AnySubreg = true;
            break;
          }
          LiveInterval *LI = &LIS.getInterval(LocMO.getReg());
          KilledLocIntervals.push_back({LocNo, LI});
        }

        // FIXME: Handle sub-registers in addDefsFromCopies. The problem is that
        // if the original location for example is %vreg0:sub_hi, and we find a
        // full register copy in addDefsFromCopies (at the moment it only
        // handles full register copies), then we must add the sub1 sub-register
        // index to the new location. However, that is only possible if the new
        // virtual register is of the same regclass (or if there is an
        // equivalent sub-register in that regclass). For now, simply skip
        // handling copies if a sub-register is involved.
        if (!AnySubreg)
          addDefsFromCopies(DbgValue, KilledLocIntervals, Kills->first, Defs,
                            MRI, LIS);
      }
    }

    // For physregs, we only mark the start slot idx. DwarfDebug will see it
    // as if the DBG_VALUE is valid up until the end of the basic block, or
    // the next def of the physical register. So we do not need to extend the
    // range. It might actually happen that the DBG_VALUE is the last use of
    // the physical register (e.g. if this is an unused input argument to a
    // function).
  }

  // The computed intervals may extend beyond the range of the debug
  // location's lexical scope. In this case, splitting of an interval
  // can result in an interval outside of the scope being created,
  // causing extra unnecessary DBG_VALUEs to be emitted. To prevent
  // this, trim the intervals to the lexical scope in the case of inlined
  // variables, since heavy inlining may cause production of dramatically big
  // number of DBG_VALUEs to be generated.
  if (!dl.getInlinedAt())
    return;

  LexicalScope *Scope = LS.findLexicalScope(dl);
  if (!Scope)
    return;

  SlotIndex PrevEnd;
  LocMap::iterator I = locInts.begin();

  // Iterate over the lexical scope ranges. Each time round the loop
  // we check the intervals for overlap with the end of the previous
  // range and the start of the next. The first range is handled as
  // a special case where there is no PrevEnd.
  for (const InsnRange &Range : Scope->getRanges()) {
    SlotIndex RStart = LIS.getInstructionIndex(*Range.first);
    SlotIndex REnd = LIS.getInstructionIndex(*Range.second);

    // Variable locations at the first instruction of a block should be
    // based on the block's SlotIndex, not the first instruction's index.
    if (Range.first == Range.first->getParent()->begin())
      RStart = LIS.getSlotIndexes()->getIndexBefore(*Range.first);

    // At the start of each iteration I has been advanced so that
    // I.stop() >= PrevEnd. Check for overlap.
    if (PrevEnd && I.start() < PrevEnd) {
      SlotIndex IStop = I.stop();
      DbgVariableValue DbgValue = I.value();

      // Stop overlaps previous end - trim the end of the interval to
      // the scope range.
      I.setStopUnchecked(PrevEnd);
      ++I;

      // If the interval also overlaps the start of the "next" (i.e.
      // current) range create a new interval for the remainder (which
      // may be further trimmed).
      if (RStart < IStop)
        I.insert(RStart, IStop, DbgValue);
    }

    // Advance I so that I.stop() >= RStart, and check for overlap.
    I.advanceTo(RStart);
    if (!I.valid())
      return;

    if (I.start() < RStart) {
      // Interval start overlaps range - trim to the scope range.
      I.setStartUnchecked(RStart);
      // Remember that this interval was trimmed.
      trimmedDefs.insert(RStart);
    }

    // The end of a lexical scope range is the last instruction in the
    // range. To convert to an interval we need the index of the
    // instruction after it.
    REnd = REnd.getNextIndex();

    // Advance I to first interval outside current range.
    I.advanceTo(REnd);
    if (!I.valid())
      return;

    PrevEnd = REnd;
  }

  // Check for overlap with end of final range.
  if (PrevEnd && I.start() < PrevEnd)
    I.setStopUnchecked(PrevEnd);
}

void LDVImpl::computeIntervals() {
  LexicalScopes LS;
  LS.initialize(*MF);

  for (unsigned i = 0, e = userValues.size(); i != e; ++i) {
    userValues[i]->computeIntervals(MF->getRegInfo(), *TRI, *LIS, LS);
    userValues[i]->mapVirtRegs(this);
  }
}

bool LDVImpl::runOnMachineFunction(MachineFunction &mf, bool InstrRef) {
  clear();
  MF = &mf;
  LIS = &pass.getAnalysis<LiveIntervals>();
  TRI = mf.getSubtarget().getRegisterInfo();
  LLVM_DEBUG(dbgs() << "********** COMPUTING LIVE DEBUG VARIABLES: "
                    << mf.getName() << " **********\n");

  bool Changed = collectDebugValues(mf, InstrRef);
  computeIntervals();
  LLVM_DEBUG(print(dbgs()));

  // Collect the set of VReg / SlotIndexs where PHIs occur; index the sensitive
  // VRegs too, for when we're notified of a range split.
  SlotIndexes *Slots = LIS->getSlotIndexes();
  for (const auto &PHIIt : MF->DebugPHIPositions) {
    const MachineFunction::DebugPHIRegallocPos &Position = PHIIt.second;
    MachineBasicBlock *MBB = Position.MBB;
    Register Reg = Position.Reg;
    unsigned SubReg = Position.SubReg;
    SlotIndex SI = Slots->getMBBStartIdx(MBB);
    PHIValPos VP = {SI, Reg, SubReg};
    PHIValToPos.insert(std::make_pair(PHIIt.first, VP));
    RegToPHIIdx[Reg].push_back(PHIIt.first);
  }

  ModifiedMF = Changed;
  return Changed;
}

static void removeDebugInstrs(MachineFunction &mf) {
  for (MachineBasicBlock &MBB : mf) {
    for (MachineInstr &MI : llvm::make_early_inc_range(MBB))
      if (MI.isDebugInstr())
        MBB.erase(&MI);
  }
}

bool LiveDebugVariables::runOnMachineFunction(MachineFunction &mf) {
  if (!EnableLDV)
    return false;
  if (!mf.getFunction().getSubprogram()) {
    removeDebugInstrs(mf);
    return false;
  }

  // Have we been asked to track variable locations using instruction
  // referencing?
  bool InstrRef = mf.useDebugInstrRef();

  if (!pImpl)
    pImpl = new LDVImpl(this);
  return static_cast<LDVImpl *>(pImpl)->runOnMachineFunction(mf, InstrRef);
}

void LiveDebugVariables::releaseMemory() {
  if (pImpl)
    static_cast<LDVImpl*>(pImpl)->clear();
}

LiveDebugVariables::~LiveDebugVariables() {
  if (pImpl)
    delete static_cast<LDVImpl*>(pImpl);
}

//===----------------------------------------------------------------------===//
//                           Live Range Splitting
//===----------------------------------------------------------------------===//

bool
UserValue::splitLocation(unsigned OldLocNo, ArrayRef<Register> NewRegs,
                         LiveIntervals& LIS) {
  LLVM_DEBUG({
    dbgs() << "Splitting Loc" << OldLocNo << '\t';
    print(dbgs(), nullptr);
  });
  bool DidChange = false;
  LocMap::iterator LocMapI;
  LocMapI.setMap(locInts);
  for (Register NewReg : NewRegs) {
    LiveInterval *LI = &LIS.getInterval(NewReg);
    if (LI->empty())
      continue;

    // Don't allocate the new LocNo until it is needed.
    unsigned NewLocNo = UndefLocNo;

    // Iterate over the overlaps between locInts and LI.
    LocMapI.find(LI->beginIndex());
    if (!LocMapI.valid())
      continue;
    LiveInterval::iterator LII = LI->advanceTo(LI->begin(), LocMapI.start());
    LiveInterval::iterator LIE = LI->end();
    while (LocMapI.valid() && LII != LIE) {
      // At this point, we know that LocMapI.stop() > LII->start.
      LII = LI->advanceTo(LII, LocMapI.start());
      if (LII == LIE)
        break;

      // Now LII->end > LocMapI.start(). Do we have an overlap?
      if (LocMapI.value().containsLocNo(OldLocNo) &&
          LII->start < LocMapI.stop()) {
        // Overlapping correct location. Allocate NewLocNo now.
        if (NewLocNo == UndefLocNo) {
          MachineOperand MO = MachineOperand::CreateReg(LI->reg(), false);
          MO.setSubReg(locations[OldLocNo].getSubReg());
          NewLocNo = getLocationNo(MO);
          DidChange = true;
        }

        SlotIndex LStart = LocMapI.start();
        SlotIndex LStop = LocMapI.stop();
        DbgVariableValue OldDbgValue = LocMapI.value();

        // Trim LocMapI down to the LII overlap.
        if (LStart < LII->start)
          LocMapI.setStartUnchecked(LII->start);
        if (LStop > LII->end)
          LocMapI.setStopUnchecked(LII->end);

        // Change the value in the overlap. This may trigger coalescing.
        LocMapI.setValue(OldDbgValue.changeLocNo(OldLocNo, NewLocNo));

        // Re-insert any removed OldDbgValue ranges.
        if (LStart < LocMapI.start()) {
          LocMapI.insert(LStart, LocMapI.start(), OldDbgValue);
          ++LocMapI;
          assert(LocMapI.valid() && "Unexpected coalescing");
        }
        if (LStop > LocMapI.stop()) {
          ++LocMapI;
          LocMapI.insert(LII->end, LStop, OldDbgValue);
          --LocMapI;
        }
      }

      // Advance to the next overlap.
      if (LII->end < LocMapI.stop()) {
        if (++LII == LIE)
          break;
        LocMapI.advanceTo(LII->start);
      } else {
        ++LocMapI;
        if (!LocMapI.valid())
          break;
        LII = LI->advanceTo(LII, LocMapI.start());
      }
    }
  }

  // Finally, remove OldLocNo unless it is still used by some interval in the
  // locInts map. One case when OldLocNo still is in use is when the register
  // has been spilled. In such situations the spilled register is kept as a
  // location until rewriteLocations is called (VirtRegMap is mapping the old
  // register to the spill slot). So for a while we can have locations that map
  // to virtual registers that have been removed from both the MachineFunction
  // and from LiveIntervals.
  //
  // We may also just be using the location for a value with a different
  // expression.
  removeLocationIfUnused(OldLocNo);

  LLVM_DEBUG({
    dbgs() << "Split result: \t";
    print(dbgs(), nullptr);
  });
  return DidChange;
}

bool
UserValue::splitRegister(Register OldReg, ArrayRef<Register> NewRegs,
                         LiveIntervals &LIS) {
  bool DidChange = false;
  // Split locations referring to OldReg. Iterate backwards so splitLocation can
  // safely erase unused locations.
  for (unsigned i = locations.size(); i ; --i) {
    unsigned LocNo = i-1;
    const MachineOperand *Loc = &locations[LocNo];
    if (!Loc->isReg() || Loc->getReg() != OldReg)
      continue;
    DidChange |= splitLocation(LocNo, NewRegs, LIS);
  }
  return DidChange;
}

void LDVImpl::splitPHIRegister(Register OldReg, ArrayRef<Register> NewRegs) {
  auto RegIt = RegToPHIIdx.find(OldReg);
  if (RegIt == RegToPHIIdx.end())
    return;

  std::vector<std::pair<Register, unsigned>> NewRegIdxes;
  // Iterate over all the debug instruction numbers affected by this split.
  for (unsigned InstrID : RegIt->second) {
    auto PHIIt = PHIValToPos.find(InstrID);
    assert(PHIIt != PHIValToPos.end());
    const SlotIndex &Slot = PHIIt->second.SI;
    assert(OldReg == PHIIt->second.Reg);

    // Find the new register that covers this position.
    for (auto NewReg : NewRegs) {
      const LiveInterval &LI = LIS->getInterval(NewReg);
      auto LII = LI.find(Slot);
      if (LII != LI.end() && LII->start <= Slot) {
        // This new register covers this PHI position, record this for indexing.
        NewRegIdxes.push_back(std::make_pair(NewReg, InstrID));
        // Record that this value lives in a different VReg now.
        PHIIt->second.Reg = NewReg;
        break;
      }
    }

    // If we do not find a new register covering this PHI, then register
    // allocation has dropped its location, for example because it's not live.
    // The old VReg will not be mapped to a physreg, and the instruction
    // number will have been optimized out.
  }

  // Re-create register index using the new register numbers.
  RegToPHIIdx.erase(RegIt);
  for (auto &RegAndInstr : NewRegIdxes)
    RegToPHIIdx[RegAndInstr.first].push_back(RegAndInstr.second);
}

void LDVImpl::splitRegister(Register OldReg, ArrayRef<Register> NewRegs) {
  // Consider whether this split range affects any PHI locations.
  splitPHIRegister(OldReg, NewRegs);

  // Check whether any intervals mapped by a DBG_VALUE were split and need
  // updating.
  bool DidChange = false;
  for (UserValue *UV = lookupVirtReg(OldReg); UV; UV = UV->getNext())
    DidChange |= UV->splitRegister(OldReg, NewRegs, *LIS);

  if (!DidChange)
    return;

  // Map all of the new virtual registers.
  UserValue *UV = lookupVirtReg(OldReg);
  for (Register NewReg : NewRegs)
    mapVirtReg(NewReg, UV);
}

void LiveDebugVariables::
splitRegister(Register OldReg, ArrayRef<Register> NewRegs, LiveIntervals &LIS) {
  if (pImpl)
    static_cast<LDVImpl*>(pImpl)->splitRegister(OldReg, NewRegs);
}

void UserValue::rewriteLocations(VirtRegMap &VRM, const MachineFunction &MF,
                                 const TargetInstrInfo &TII,
                                 const TargetRegisterInfo &TRI,
                                 SpillOffsetMap &SpillOffsets) {
  // Build a set of new locations with new numbers so we can coalesce our
  // IntervalMap if two vreg intervals collapse to the same physical location.
  // Use MapVector instead of SetVector because MapVector::insert returns the
  // position of the previously or newly inserted element. The boolean value
  // tracks if the location was produced by a spill.
  // FIXME: This will be problematic if we ever support direct and indirect
  // frame index locations, i.e. expressing both variables in memory and
  // 'int x, *px = &x'. The "spilled" bit must become part of the location.
  MapVector<MachineOperand, std::pair<bool, unsigned>> NewLocations;
  SmallVector<unsigned, 4> LocNoMap(locations.size());
  for (unsigned I = 0, E = locations.size(); I != E; ++I) {
    bool Spilled = false;
    unsigned SpillOffset = 0;
    MachineOperand Loc = locations[I];
    // Only virtual registers are rewritten.
    if (Loc.isReg() && Loc.getReg() &&
        Register::isVirtualRegister(Loc.getReg())) {
      Register VirtReg = Loc.getReg();
      if (VRM.isAssignedReg(VirtReg) &&
          Register::isPhysicalRegister(VRM.getPhys(VirtReg))) {
        // This can create a %noreg operand in rare cases when the sub-register
        // index is no longer available. That means the user value is in a
        // non-existent sub-register, and %noreg is exactly what we want.
        Loc.substPhysReg(VRM.getPhys(VirtReg), TRI);
      } else if (VRM.getStackSlot(VirtReg) != VirtRegMap::NO_STACK_SLOT) {
        // Retrieve the stack slot offset.
        unsigned SpillSize;
        const MachineRegisterInfo &MRI = MF.getRegInfo();
        const TargetRegisterClass *TRC = MRI.getRegClass(VirtReg);
        bool Success = TII.getStackSlotRange(TRC, Loc.getSubReg(), SpillSize,
                                             SpillOffset, MF);

        // FIXME: Invalidate the location if the offset couldn't be calculated.
        (void)Success;

        Loc = MachineOperand::CreateFI(VRM.getStackSlot(VirtReg));
        Spilled = true;
      } else {
        Loc.setReg(0);
        Loc.setSubReg(0);
      }
    }

    // Insert this location if it doesn't already exist and record a mapping
    // from the old number to the new number.
    auto InsertResult = NewLocations.insert({Loc, {Spilled, SpillOffset}});
    unsigned NewLocNo = std::distance(NewLocations.begin(), InsertResult.first);
    LocNoMap[I] = NewLocNo;
  }

  // Rewrite the locations and record the stack slot offsets for spills.
  locations.clear();
  SpillOffsets.clear();
  for (auto &Pair : NewLocations) {
    bool Spilled;
    unsigned SpillOffset;
    std::tie(Spilled, SpillOffset) = Pair.second;
    locations.push_back(Pair.first);
    if (Spilled) {
      unsigned NewLocNo = std::distance(&*NewLocations.begin(), &Pair);
      SpillOffsets[NewLocNo] = SpillOffset;
    }
  }

  // Update the interval map, but only coalesce left, since intervals to the
  // right use the old location numbers. This should merge two contiguous
  // DBG_VALUE intervals with different vregs that were allocated to the same
  // physical register.
  for (LocMap::iterator I = locInts.begin(); I.valid(); ++I) {
    I.setValueUnchecked(I.value().remapLocNos(LocNoMap));
    I.setStart(I.start());
  }
}

/// Find an iterator for inserting a DBG_VALUE instruction.
static MachineBasicBlock::iterator
findInsertLocation(MachineBasicBlock *MBB, SlotIndex Idx, LiveIntervals &LIS,
                   BlockSkipInstsMap &BBSkipInstsMap) {
  SlotIndex Start = LIS.getMBBStartIdx(MBB);
  Idx = Idx.getBaseIndex();

  // Try to find an insert location by going backwards from Idx.
  MachineInstr *MI;
  while (!(MI = LIS.getInstructionFromIndex(Idx))) {
    // We've reached the beginning of MBB.
    if (Idx == Start) {
      // Retrieve the last PHI/Label/Debug location found when calling
      // SkipPHIsLabelsAndDebug last time. Start searching from there.
      //
      // Note the iterator kept in BBSkipInstsMap is one step back based
      // on the iterator returned by SkipPHIsLabelsAndDebug last time.
      // One exception is when SkipPHIsLabelsAndDebug returns MBB->begin(),
      // BBSkipInstsMap won't save it. This is to consider the case that
      // new instructions may be inserted at the beginning of MBB after
      // last call of SkipPHIsLabelsAndDebug. If we save MBB->begin() in
      // BBSkipInstsMap, after new non-phi/non-label/non-debug instructions
      // are inserted at the beginning of the MBB, the iterator in
      // BBSkipInstsMap won't point to the beginning of the MBB anymore.
      // Therefore The next search in SkipPHIsLabelsAndDebug will skip those
      // newly added instructions and that is unwanted.
      MachineBasicBlock::iterator BeginIt;
      auto MapIt = BBSkipInstsMap.find(MBB);
      if (MapIt == BBSkipInstsMap.end())
        BeginIt = MBB->begin();
      else
        BeginIt = std::next(MapIt->second);
      auto I = MBB->SkipPHIsLabelsAndDebug(BeginIt);
      if (I != BeginIt)
        BBSkipInstsMap[MBB] = std::prev(I);
      return I;
    }
    Idx = Idx.getPrevIndex();
  }

  // Don't insert anything after the first terminator, though.
  return MI->isTerminator() ? MBB->getFirstTerminator() :
                              std::next(MachineBasicBlock::iterator(MI));
}

/// Find an iterator for inserting the next DBG_VALUE instruction
/// (or end if no more insert locations found).
static MachineBasicBlock::iterator
findNextInsertLocation(MachineBasicBlock *MBB, MachineBasicBlock::iterator I,
                       SlotIndex StopIdx, ArrayRef<MachineOperand> LocMOs,
                       LiveIntervals &LIS, const TargetRegisterInfo &TRI) {
  SmallVector<Register, 4> Regs;
  for (const MachineOperand &LocMO : LocMOs)
    if (LocMO.isReg())
      Regs.push_back(LocMO.getReg());
  if (Regs.empty())
    return MBB->instr_end();

  // Find the next instruction in the MBB that define the register Reg.
  while (I != MBB->end() && !I->isTerminator()) {
    if (!LIS.isNotInMIMap(*I) &&
        SlotIndex::isEarlierEqualInstr(StopIdx, LIS.getInstructionIndex(*I)))
      break;
    if (any_of(Regs, [&I, &TRI](Register &Reg) {
          return I->definesRegister(Reg, &TRI);
        }))
      // The insert location is directly after the instruction/bundle.
      return std::next(I);
    ++I;
  }
  return MBB->end();
}

void UserValue::insertDebugValue(MachineBasicBlock *MBB, SlotIndex StartIdx,
                                 SlotIndex StopIdx, DbgVariableValue DbgValue,
                                 ArrayRef<bool> LocSpills,
                                 ArrayRef<unsigned> SpillOffsets,
                                 LiveIntervals &LIS, const TargetInstrInfo &TII,
                                 const TargetRegisterInfo &TRI,
                                 BlockSkipInstsMap &BBSkipInstsMap) {
  SlotIndex MBBEndIdx = LIS.getMBBEndIdx(&*MBB);
  // Only search within the current MBB.
  StopIdx = (MBBEndIdx < StopIdx) ? MBBEndIdx : StopIdx;
  MachineBasicBlock::iterator I =
      findInsertLocation(MBB, StartIdx, LIS, BBSkipInstsMap);
  // Undef values don't exist in locations so create new "noreg" register MOs
  // for them. See getLocationNo().
  SmallVector<MachineOperand, 8> MOs;
  if (DbgValue.isUndef()) {
    MOs.assign(DbgValue.loc_nos().size(),
               MachineOperand::CreateReg(
                   /* Reg */ 0, /* isDef */ false, /* isImp */ false,
                   /* isKill */ false, /* isDead */ false,
                   /* isUndef */ false, /* isEarlyClobber */ false,
                   /* SubReg */ 0, /* isDebug */ true));
  } else {
    for (unsigned LocNo : DbgValue.loc_nos())
      MOs.push_back(locations[LocNo]);
  }

  ++NumInsertedDebugValues;

  assert(cast<DILocalVariable>(Variable)
             ->isValidLocationForIntrinsic(getDebugLoc()) &&
         "Expected inlined-at fields to agree");

  // If the location was spilled, the new DBG_VALUE will be indirect. If the
  // original DBG_VALUE was indirect, we need to add DW_OP_deref to indicate
  // that the original virtual register was a pointer. Also, add the stack slot
  // offset for the spilled register to the expression.
  const DIExpression *Expr = DbgValue.getExpression();
  bool IsIndirect = DbgValue.getWasIndirect();
  bool IsList = DbgValue.getWasList();
  for (unsigned I = 0, E = LocSpills.size(); I != E; ++I) {
    if (LocSpills[I]) {
      if (!IsList) {
        uint8_t DIExprFlags = DIExpression::ApplyOffset;
        if (IsIndirect)
          DIExprFlags |= DIExpression::DerefAfter;
        Expr = DIExpression::prepend(Expr, DIExprFlags, SpillOffsets[I]);
        IsIndirect = true;
      } else {
        SmallVector<uint64_t, 4> Ops;
        DIExpression::appendOffset(Ops, SpillOffsets[I]);
        Ops.push_back(dwarf::DW_OP_deref);
        Expr = DIExpression::appendOpsToArg(Expr, Ops, I);
      }
    }

    assert((!LocSpills[I] || MOs[I].isFI()) &&
           "a spilled location must be a frame index");
  }

  unsigned DbgValueOpcode =
      IsList ? TargetOpcode::DBG_VALUE_LIST : TargetOpcode::DBG_VALUE;
  do {
    BuildMI(*MBB, I, getDebugLoc(), TII.get(DbgValueOpcode), IsIndirect, MOs,
            Variable, Expr);

    // Continue and insert DBG_VALUES after every redefinition of a register
    // associated with the debug value within the range
    I = findNextInsertLocation(MBB, I, StopIdx, MOs, LIS, TRI);
  } while (I != MBB->end());
}

void UserLabel::insertDebugLabel(MachineBasicBlock *MBB, SlotIndex Idx,
                                 LiveIntervals &LIS, const TargetInstrInfo &TII,
                                 BlockSkipInstsMap &BBSkipInstsMap) {
  MachineBasicBlock::iterator I =
      findInsertLocation(MBB, Idx, LIS, BBSkipInstsMap);
  ++NumInsertedDebugLabels;
  BuildMI(*MBB, I, getDebugLoc(), TII.get(TargetOpcode::DBG_LABEL))
      .addMetadata(Label);
}

void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS,
                                const TargetInstrInfo &TII,
                                const TargetRegisterInfo &TRI,
                                const SpillOffsetMap &SpillOffsets,
                                BlockSkipInstsMap &BBSkipInstsMap) {
  MachineFunction::iterator MFEnd = VRM->getMachineFunction().end();

  for (LocMap::const_iterator I = locInts.begin(); I.valid();) {
    SlotIndex Start = I.start();
    SlotIndex Stop = I.stop();
    DbgVariableValue DbgValue = I.value();

    SmallVector<bool> SpilledLocs;
    SmallVector<unsigned> LocSpillOffsets;
    for (unsigned LocNo : DbgValue.loc_nos()) {
      auto SpillIt =
          !DbgValue.isUndef() ? SpillOffsets.find(LocNo) : SpillOffsets.end();
      bool Spilled = SpillIt != SpillOffsets.end();
      SpilledLocs.push_back(Spilled);
      LocSpillOffsets.push_back(Spilled ? SpillIt->second : 0);
    }

    // If the interval start was trimmed to the lexical scope insert the
    // DBG_VALUE at the previous index (otherwise it appears after the
    // first instruction in the range).
    if (trimmedDefs.count(Start))
      Start = Start.getPrevIndex();

    LLVM_DEBUG(auto &dbg = dbgs(); dbg << "\t[" << Start << ';' << Stop << "):";
               DbgValue.printLocNos(dbg));
    MachineFunction::iterator MBB = LIS.getMBBFromIndex(Start)->getIterator();
    SlotIndex MBBEnd = LIS.getMBBEndIdx(&*MBB);

    LLVM_DEBUG(dbgs() << ' ' << printMBBReference(*MBB) << '-' << MBBEnd);
    insertDebugValue(&*MBB, Start, Stop, DbgValue, SpilledLocs, LocSpillOffsets,
                     LIS, TII, TRI, BBSkipInstsMap);
    // This interval may span multiple basic blocks.
    // Insert a DBG_VALUE into each one.
    while (Stop > MBBEnd) {
      // Move to the next block.
      Start = MBBEnd;
      if (++MBB == MFEnd)
        break;
      MBBEnd = LIS.getMBBEndIdx(&*MBB);
      LLVM_DEBUG(dbgs() << ' ' << printMBBReference(*MBB) << '-' << MBBEnd);
      insertDebugValue(&*MBB, Start, Stop, DbgValue, SpilledLocs,
                       LocSpillOffsets, LIS, TII, TRI, BBSkipInstsMap);
    }
    LLVM_DEBUG(dbgs() << '\n');
    if (MBB == MFEnd)
      break;

    ++I;
  }
}

void UserLabel::emitDebugLabel(LiveIntervals &LIS, const TargetInstrInfo &TII,
                               BlockSkipInstsMap &BBSkipInstsMap) {
  LLVM_DEBUG(dbgs() << "\t" << loc);
  MachineFunction::iterator MBB = LIS.getMBBFromIndex(loc)->getIterator();

  LLVM_DEBUG(dbgs() << ' ' << printMBBReference(*MBB));
  insertDebugLabel(&*MBB, loc, LIS, TII, BBSkipInstsMap);

  LLVM_DEBUG(dbgs() << '\n');
}

void LDVImpl::emitDebugValues(VirtRegMap *VRM) {
  LLVM_DEBUG(dbgs() << "********** EMITTING LIVE DEBUG VARIABLES **********\n");
  if (!MF)
    return;

  BlockSkipInstsMap BBSkipInstsMap;
  const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
  SpillOffsetMap SpillOffsets;
  for (auto &userValue : userValues) {
    LLVM_DEBUG(userValue->print(dbgs(), TRI));
    userValue->rewriteLocations(*VRM, *MF, *TII, *TRI, SpillOffsets);
    userValue->emitDebugValues(VRM, *LIS, *TII, *TRI, SpillOffsets,
                               BBSkipInstsMap);
  }
  LLVM_DEBUG(dbgs() << "********** EMITTING LIVE DEBUG LABELS **********\n");
  for (auto &userLabel : userLabels) {
    LLVM_DEBUG(userLabel->print(dbgs(), TRI));
    userLabel->emitDebugLabel(*LIS, *TII, BBSkipInstsMap);
  }

  LLVM_DEBUG(dbgs() << "********** EMITTING DEBUG PHIS **********\n");

  auto Slots = LIS->getSlotIndexes();
  for (auto &It : PHIValToPos) {
    // For each ex-PHI, identify its physreg location or stack slot, and emit
    // a DBG_PHI for it.
    unsigned InstNum = It.first;
    auto Slot = It.second.SI;
    Register Reg = It.second.Reg;
    unsigned SubReg = It.second.SubReg;

    MachineBasicBlock *OrigMBB = Slots->getMBBFromIndex(Slot);
    if (VRM->isAssignedReg(Reg) &&
        Register::isPhysicalRegister(VRM->getPhys(Reg))) {
      unsigned PhysReg = VRM->getPhys(Reg);
      if (SubReg != 0)
        PhysReg = TRI->getSubReg(PhysReg, SubReg);

      auto Builder = BuildMI(*OrigMBB, OrigMBB->begin(), DebugLoc(),
                             TII->get(TargetOpcode::DBG_PHI));
      Builder.addReg(PhysReg);
      Builder.addImm(InstNum);
    } else if (VRM->getStackSlot(Reg) != VirtRegMap::NO_STACK_SLOT) {
      const MachineRegisterInfo &MRI = MF->getRegInfo();
      const TargetRegisterClass *TRC = MRI.getRegClass(Reg);
      unsigned SpillSize, SpillOffset;

      // Test whether this location is legal with the given subreg.
      bool Success =
          TII->getStackSlotRange(TRC, SubReg, SpillSize, SpillOffset, *MF);

      if (Success) {
        auto Builder = BuildMI(*OrigMBB, OrigMBB->begin(), DebugLoc(),
                               TII->get(TargetOpcode::DBG_PHI));
        Builder.addFrameIndex(VRM->getStackSlot(Reg));
        Builder.addImm(InstNum);
      }
    }
    // If there was no mapping for a value ID, it's optimized out. Create no
    // DBG_PHI, and any variables using this value will become optimized out.
  }
  MF->DebugPHIPositions.clear();

  LLVM_DEBUG(dbgs() << "********** EMITTING INSTR REFERENCES **********\n");

  // Re-insert any debug instrs back in the position they were. We must
  // re-insert in the same order to ensure that debug instructions don't swap,
  // which could re-order assignments. Do so in a batch -- once we find the
  // insert position, insert all instructions at the same SlotIdx. They are
  // guaranteed to appear in-sequence in StashedDebugInstrs because we insert
  // them in order.
  for (auto StashIt = StashedDebugInstrs.begin();
       StashIt != StashedDebugInstrs.end(); ++StashIt) {
    SlotIndex Idx = StashIt->Idx;
    MachineBasicBlock *MBB = StashIt->MBB;
    MachineInstr *MI = StashIt->MI;

    auto EmitInstsHere = [this, &StashIt, MBB, Idx,
                          MI](MachineBasicBlock::iterator InsertPos) {
      // Insert this debug instruction.
      MBB->insert(InsertPos, MI);

      // Look at subsequent stashed debug instructions: if they're at the same
      // index, insert those too.
      auto NextItem = std::next(StashIt);
      while (NextItem != StashedDebugInstrs.end() && NextItem->Idx == Idx) {
        assert(NextItem->MBB == MBB && "Instrs with same slot index should be"
               "in the same block");
        MBB->insert(InsertPos, NextItem->MI);
        StashIt = NextItem;
        NextItem = std::next(StashIt);
      };
    };

    // Start block index: find the first non-debug instr in the block, and
    // insert before it.
    if (Idx == Slots->getMBBStartIdx(MBB)) {
      MachineBasicBlock::iterator InsertPos =
          findInsertLocation(MBB, Idx, *LIS, BBSkipInstsMap);
      EmitInstsHere(InsertPos);
      continue;
    }

    if (MachineInstr *Pos = Slots->getInstructionFromIndex(Idx)) {
      // Insert at the end of any debug instructions.
      auto PostDebug = std::next(Pos->getIterator());
      PostDebug = skipDebugInstructionsForward(PostDebug, MBB->instr_end());
      EmitInstsHere(PostDebug);
    } else {
      // Insert position disappeared; walk forwards through slots until we
      // find a new one.
      SlotIndex End = Slots->getMBBEndIdx(MBB);
      for (; Idx < End; Idx = Slots->getNextNonNullIndex(Idx)) {
        Pos = Slots->getInstructionFromIndex(Idx);
        if (Pos) {
          EmitInstsHere(Pos->getIterator());
          break;
        }
      }

      // We have reached the end of the block and didn't find anywhere to
      // insert! It's not safe to discard any debug instructions; place them
      // in front of the first terminator, or in front of end().
      if (Idx >= End) {
        auto TermIt = MBB->getFirstTerminator();
        EmitInstsHere(TermIt);
      }
    }
  }

  EmitDone = true;
  BBSkipInstsMap.clear();
}

void LiveDebugVariables::emitDebugValues(VirtRegMap *VRM) {
  if (pImpl)
    static_cast<LDVImpl*>(pImpl)->emitDebugValues(VRM);
}

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void LiveDebugVariables::dump() const {
  if (pImpl)
    static_cast<LDVImpl*>(pImpl)->print(dbgs());
}
#endif
