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