Index: llvm/lib/CodeGen/RegisterCoalescer.cpp
===================================================================
--- llvm/lib/CodeGen/RegisterCoalescer.cpp
+++ llvm/lib/CodeGen/RegisterCoalescer.cpp
@@ -358,6 +358,12 @@
 INITIALIZE_PASS_END(RegisterCoalescer, "simple-register-coalescing",
                     "Simple Register Coalescing", false, false)
 
+// Forward dec
+static void makeDeadDbgValsUndefForPhysReg(const SlotIndexes &Slots,
+                                           MachineBasicBlock *MBB,
+                                           const LiveInterval &RegLiveness,
+                                           Register VReg);
+
 LLVM_NODISCARD static bool isMoveInstr(const TargetRegisterInfo &tri,
                                        const MachineInstr *MI, unsigned &Src,
                                        unsigned &Dst, unsigned &SrcSub,
@@ -1974,47 +1980,6 @@
   return true;
 }
 
-// See comment for CheckDbgValuesInBlock; this is a specialised copy for
-// when one coalesced register is a physical register.
-static void CheckDbgValuesInBlockForPhysReg(const SlotIndexes &Slots,
-                                            MachineBasicBlock *MBB,
-                                            const LiveInterval &RegLiveness,
-                                            unsigned Reg) {
-  SlotIndex BlockStart = Slots.getMBBStartIdx(MBB);
-  SlotIndex BlockEnd = Slots.getMBBEndIdx(MBB);
-
-  auto RegLivenessIt = RegLiveness.find(BlockStart);
-
-  // If the Reg is live all the way through this block, no non-live DBG_VALUEs
-  // can be merged in. Early exit.
-  if (RegLivenessIt != RegLiveness.end() &&
-      RegLivenessIt->start <= BlockStart && RegLivenessIt->end >= BlockEnd)
-    return;
-
-  MachineInstr *StartMI = Slots.getInstructionFromIndex(BlockStart);
-  auto InstIt = (StartMI) ? StartMI->getIterator() : MBB->begin();
-  MachineInstr *EndMI = Slots.getInstructionFromIndex(BlockEnd);
-  auto InstEndIt = (EndMI) ? EndMI->getIterator() : MBB->end();
-  bool RegIsLive = RegLiveness.liveAt(BlockStart);
-
-  for (; InstIt != InstEndIt; ++InstIt) {
-    MachineInstr &MI = *InstIt;
-    // Is this a DBG_VALUE for Reg, where Reg is dead?
-    if (MI.isDebugValue() && !RegIsLive &&
-        MI.getOperand(0).isReg() && MI.getOperand(0).getReg() == Reg) {
-      // If so, point the DBG_VALUE to $noreg
-      MI.getOperand(0).setReg(0);
-    } else if (!MI.isDebugInstr()) {
-      // If not, update current liveness record.
-      SlotIndex Slot = Slots.getInstructionIndex(MI);
-      Slot = Slot.getRegSlot();
-      RegIsLive = RegLiveness.liveAt(Slot);
-    }
-  }
-
-  return;
-}
-
 bool RegisterCoalescer::joinReservedPhysReg(CoalescerPair &CP) {
   unsigned DstReg = CP.getDstReg();
   unsigned SrcReg = CP.getSrcReg();
@@ -2070,7 +2035,7 @@
   }
 
   for (auto *MBB : SeenBlocks) {
-    CheckDbgValuesInBlockForPhysReg(Slots, MBB, RHS, SrcReg);
+    makeDeadDbgValsUndefForPhysReg(Slots, MBB, RHS, SrcReg);
   }
 
   // Delete the identity copy.
@@ -3352,33 +3317,25 @@
   return true;
 }
 
-// Scan a basic block for unsound DBG_VALUE updates if two live ranges are
-// coalesced. RegLiveness is the LiveInterval for Reg, while OtherLiveness is
-// the other range it will be merged with. If, at a particular DBG_VALUE,
-// Reg is not live, but OtherLiveness is, then merging the two would be
-// unsound (PR40010).
-// Walk through all instructions in the block, storing the liveness properties
-// at a particular location. This is to work around the fact that slot-index
-// queries for DBG_VALUEs is slow.
-static void CheckDbgValuesInBlock(const SlotIndexes &Slots,
-                                  MachineBasicBlock *MBB,
-                                  const LiveInterval &RegLiveness,
-                                  const LiveInterval &OtherLiveness,
-                                  unsigned Reg) {
+/// Scan a basic block for unsound DBG_VALUE updates if two live ranges are
+/// coalesced. RegLiveness is the LiveInterval for Reg, while OtherLiveness is
+/// the other range it will be merged with. If, at a particular DBG_VALUE,
+/// Reg is not live, but OtherLiveness is, then merging the two would be
+/// unsound (PR40010).
+/// Walk through all instructions in the block, storing the liveness properties
+/// at a particular location. This is to work around the fact that slot-index
+/// queries for DBG_VALUEs is slow.
+static void makeDeadDbgValsUndefImpl(
+    const SlotIndexes &Slots, MachineBasicBlock *MBB,
+    const LiveInterval &RegLiveness,
+    std::function<bool(const SlotIndex &)> TestOtherLiveness, Register VReg) {
   SlotIndex BlockStart = Slots.getMBBStartIdx(MBB);
   SlotIndex BlockEnd = Slots.getMBBEndIdx(MBB);
 
   auto RegLivenessIt = RegLiveness.find(BlockStart);
-  auto OtherLivenessIt = OtherLiveness.find(BlockStart);
-
-  // If the Other range is never live, it can never interfere with Reg in this
-  // block. Exit early.
-  if (OtherLivenessIt == OtherLiveness.end() ||
-      OtherLivenessIt->start > BlockEnd)
-    return;
 
   // If the Reg is live all the way through this block, no non-live DBG_VALUEs
-  // can be merged with the live range of Other. Exit early.
+  // can be merged with the live range of the other. Exit early.
   if (RegLivenessIt != RegLiveness.end() &&
       RegLivenessIt->start <= BlockStart && RegLivenessIt->end >= BlockEnd)
     return;
@@ -3388,27 +3345,69 @@
   MachineInstr *EndMI = Slots.getInstructionFromIndex(BlockEnd);
   auto InstEndIt = (EndMI) ? EndMI->getIterator() : MBB->end();
   bool RegIsLive = RegLiveness.liveAt(BlockStart);
-  bool OtherIsLive = OtherLiveness.liveAt(BlockStart);
+  bool OtherIsLive = TestOtherLiveness(BlockStart);
 
   for (; InstIt != InstEndIt; ++InstIt) {
     MachineInstr &MI = *InstIt;
     // Is this a DBG_VALUE for Reg, where Reg is dead and Other is live?
-    if (MI.isDebugValue() && !RegIsLive && OtherIsLive &&
-        MI.getOperand(0).isReg() && MI.getOperand(0).getReg() == Reg) {
-      // If so, point the DBG_VALUE to $noreg
-      MI.getOperand(0).setReg(0);
-    } else if (!MI.isDebugInstr()) {
-      // If not, update current liveness record.
-      SlotIndex Slot = Slots.getInstructionIndex(MI);
-      Slot = Slot.getRegSlot();
-      RegIsLive = RegLiveness.liveAt(Slot);
-      OtherIsLive = OtherLiveness.liveAt(Slot);
+    if (MI.isDebugValue()) {
+      if (!RegIsLive && OtherIsLive && MI.getOperand(0).isReg() &&
+          MI.getOperand(0).getReg() == VReg) {
+        // If so, point the DBG_VALUE to $noreg
+        MI.getOperand(0).setReg(0);
+      }
+      continue;
     }
+
+    if (MI.isDebugInstr())
+      continue;
+
+    // If not, update current liveness record.
+    SlotIndex Slot = Slots.getInstructionIndex(MI);
+    Slot = Slot.getRegSlot();
+    RegIsLive = RegLiveness.liveAt(Slot);
+    OtherIsLive = TestOtherLiveness(Slot);
   }
 
   return;
 }
 
+/// Wrapper around makeDeadDbgValsUndefImpl that takes the liveness ranges
+/// of two vregs, and the source vreg being merged.
+static void makeDeadDbgValsUndef(const SlotIndexes &Slots,
+                                 MachineBasicBlock *MBB,
+                                 const LiveInterval &RegLiveness,
+                                 const LiveInterval &OtherLiveness,
+                                 Register VReg) {
+
+  // If the Other range is never live, it can never interfere with Reg in this
+  // block. Exit early.
+  auto OtherLivenessIt = OtherLiveness.find(Slots.getMBBStartIdx(MBB));
+  if (OtherLivenessIt == OtherLiveness.end() ||
+      OtherLivenessIt->start > Slots.getMBBEndIdx(MBB))
+    return;
+
+  auto OtherLivenessTest = [&OtherLiveness](const SlotIndex &Idx) -> bool {
+    return OtherLiveness.liveAt(Idx);
+  };
+
+  makeDeadDbgValsUndefImpl(Slots, MBB, RegLiveness, OtherLivenessTest, VReg);
+}
+
+/// Wrapper around makeDeadDbgValsUndefImpl that takes a single liveness
+/// range for the source vreg, treating the physical destination reg as
+/// being always-live.
+static void makeDeadDbgValsUndefForPhysReg(const SlotIndexes &Slots,
+                                           MachineBasicBlock *MBB,
+                                           const LiveInterval &RegLiveness,
+                                           Register VReg) {
+
+  // The range of the "other" register is a physreg, so always live.
+  auto OtherLivenessTest = [](const SlotIndex &Idx) -> bool { return true; };
+
+  makeDeadDbgValsUndefImpl(Slots, MBB, RegLiveness, OtherLivenessTest, VReg);
+}
+
 bool RegisterCoalescer::joinVirtRegs(CoalescerPair &CP) {
   SmallVector<VNInfo*, 16> NewVNInfo;
   LiveInterval &RHS = LIS->getInterval(CP.getSrcReg());
@@ -3445,7 +3444,7 @@
   const SlotIndexes &Slots = *LIS->getSlotIndexes();
 
   // Helper delegate to collect blocks of interest, then call
-  // CheckDbgValuesInBlock on each one once.
+  // makeDeadDbgValsUndef on each one once.
   auto DbgValueRegScanner = [&](const LiveInterval &RegLiveness,
                                 const LiveInterval &OtherLiveness,
                                 unsigned Reg) {
@@ -3456,7 +3455,7 @@
     }
 
     for (auto *MBB : SeenBlocks)
-      CheckDbgValuesInBlock(Slots, MBB, RegLiveness, OtherLiveness, Reg);
+      makeDeadDbgValsUndef(Slots, MBB, RegLiveness, OtherLiveness, Reg);
   };
 
   unsigned SrcReg = CP.getSrcReg();