Index: lib/CodeGen/MachineCopyPropagation.cpp =================================================================== --- lib/CodeGen/MachineCopyPropagation.cpp +++ lib/CodeGen/MachineCopyPropagation.cpp @@ -207,7 +207,8 @@ private: void ClobberRegister(unsigned Reg); - void ReadRegister(unsigned Reg); + void ReadRegister(unsigned Reg, MachineInstr &Reader, + bool IsDebug = false); void CopyPropagateBlock(MachineBasicBlock &MBB); bool eraseIfRedundant(MachineInstr &Copy, unsigned Src, unsigned Def); void forwardUses(MachineInstr &MI); @@ -218,6 +219,9 @@ /// Candidates for deletion. SmallSetVector MaybeDeadCopies; + /// Copy -> DbgUsers multimap. + DenseMap> CopyDbgUsers; + CopyTracker Tracker; bool Changed; @@ -232,13 +236,19 @@ INITIALIZE_PASS(MachineCopyPropagation, DEBUG_TYPE, "Machine Copy Propagation Pass", false, false) -void MachineCopyPropagation::ReadRegister(unsigned Reg) { +void MachineCopyPropagation::ReadRegister(unsigned Reg, MachineInstr &Reader, + bool IsDebug) { // If 'Reg' is defined by a copy, the copy is no longer a candidate - // for elimination. + // for elimination. If a copy is "read" by a debug user, record the user + // for propagation. for (MCRegUnitIterator RUI(Reg, TRI); RUI.isValid(); ++RUI) { if (MachineInstr *Copy = Tracker.findCopyForUnit(*RUI, *TRI)) { - LLVM_DEBUG(dbgs() << "MCP: Copy is used - not dead: "; Copy->dump()); - MaybeDeadCopies.remove(Copy); + if (!IsDebug) { + LLVM_DEBUG(dbgs() << "MCP: Copy is used - not dead: "; Copy->dump()); + MaybeDeadCopies.remove(Copy); + } else { + CopyDbgUsers[Copy].push_back(&Reader); + } } } } @@ -489,14 +499,14 @@ // If Src is defined by a previous copy, the previous copy cannot be // eliminated. - ReadRegister(Src); + ReadRegister(Src, *MI); for (const MachineOperand &MO : MI->implicit_operands()) { if (!MO.isReg() || !MO.readsReg()) continue; unsigned Reg = MO.getReg(); if (!Reg) continue; - ReadRegister(Reg); + ReadRegister(Reg, *MI); } LLVM_DEBUG(dbgs() << "MCP: Copy is a deletion candidate: "; MI->dump()); @@ -535,7 +545,7 @@ // instruction, so we need to make sure we don't remove it as dead // later. if (MO.isTied()) - ReadRegister(Reg); + ReadRegister(Reg, *MI); Tracker.clobberRegister(Reg, *TRI); } @@ -559,8 +569,8 @@ if (MO.isDef() && !MO.isEarlyClobber()) { Defs.push_back(Reg); continue; - } else if (!MO.isDebug() && MO.readsReg()) - ReadRegister(Reg); + } else if (MO.readsReg()) + ReadRegister(Reg, *MI, MO.isDebug()); } // The instruction has a register mask operand which means that it clobbers @@ -610,9 +620,13 @@ MaybeDead->dump()); assert(!MRI->isReserved(MaybeDead->getOperand(0).getReg())); - // Update matching debug values. + // Update matching debug values, if any. assert(MaybeDead->isCopy()); - MaybeDead->changeDebugValuesDefReg(MaybeDead->getOperand(1).getReg()); + unsigned SrcReg = MaybeDead->getOperand(1).getReg(); + for (auto DbgUser : CopyDbgUsers[MaybeDead]) { + assert(DbgUser->getOperand(0).isReg()); + DbgUser->getOperand(0).setReg(SrcReg); + } MaybeDead->eraseFromParent(); Changed = true; @@ -621,6 +635,7 @@ } MaybeDeadCopies.clear(); + CopyDbgUsers.clear(); Tracker.clear(); } Index: test/CodeGen/MIR/X86/pr38773.mir =================================================================== --- test/CodeGen/MIR/X86/pr38773.mir +++ test/CodeGen/MIR/X86/pr38773.mir @@ -99,6 +99,13 @@ ; CHECK: IDIV32r killed renamable $ecx ; CHECK-NEXT: DBG_VALUE $eax, $noreg, !12, !DIExpression(), debug-location !13 DBG_VALUE $ecx, $noreg, !12, !DIExpression(), debug-location !13 + ; The following mov and DBG_VALUE have been inserted after the PR was + ; resolved to check that MCP will update debug users that are not + ; immediately after the dead copy. + ; CHECK-NEXT: $edx = MOV32r0 + $edx = MOV32r0 implicit-def dead $eflags + ; CHECK-NEXT: DBG_VALUE $eax, $noreg, !12, !DIExpression(), debug-location !13 + DBG_VALUE $ecx, $noreg, !12, !DIExpression(), debug-location !13 $eax = COPY killed renamable $ecx RET 0, $eax