Index: include/llvm/CodeGen/TargetFrameLowering.h =================================================================== --- include/llvm/CodeGen/TargetFrameLowering.h +++ include/llvm/CodeGen/TargetFrameLowering.h @@ -282,6 +282,12 @@ report_fatal_error("WinEH not implemented for this target"); } + /// Check if the target is updating FrameSetup and FrameDestroy attributes on + /// machine instructions. + virtual bool isFrameSetupAndFrameDestroySupported() const { + return false; + } + /// This method is called during prolog/epilog code insertion to eliminate /// call frame setup and destroy pseudo instructions (but only if the Target /// is using them). It is responsible for eliminating these instructions, Index: lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp +++ lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp @@ -15,6 +15,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineOperand.h" +#include "llvm/CodeGen/TargetFrameLowering.h" #include "llvm/CodeGen/TargetLowering.h" #include "llvm/CodeGen/TargetRegisterInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" @@ -187,11 +188,58 @@ } } +/// \brief Collect registers that are modified in the function (ignoring +/// FrameSetup/FrameDestroy/Return instructions). Debug variables that are +/// mapped to such registers need to be described using debug location ranges +/// (as they aren't valid throughout the function). Compare this to a variable +/// that is an argument to the function, being received in a register that isn't +/// modified. Such a variable can be printed from anywhere inside the function +/// and no range information is needed. +static void collectChangingRegsInBody(const MachineFunction *MF, + const TargetRegisterInfo *TRI, + BitVector &Regs) { + for (const auto &MBB : *MF) { + // A bundle might contain a mix of FrameSetup/FrameDestroy and other + // instructions. So we need to use the instr iterator to analyse the + // individual instructions. + for (const auto &MI : MBB.instrs()) { + // We look inside the bundle, so skip the BUNDLE head. + if (MI.isBundle()) + continue; + // Avoid looking at prologue or epilogue instructions. + if (MI.isReturn() || + MI.getFlag(MachineInstr::FrameSetup) || + MI.getFlag(MachineInstr::FrameDestroy)) + continue; + + // Look for register defs and register masks. Register masks are + // typically on calls and they clobber everything not in the mask. + for (const MachineOperand &MO : MI.operands()) { + // Skip virtual registers since they are handled by the parent. + if (MO.isReg() && MO.isDef() && MO.getReg() && + !TRI->isVirtualRegister(MO.getReg())) { + for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid(); + ++AI) + Regs.set(*AI); + } else if (MO.isRegMask()) { + Regs.setBitsNotInMask(MO.getRegMask()); + } + } + } + } +} + void llvm::calculateDbgValueHistory(const MachineFunction *MF, const TargetRegisterInfo *TRI, DbgValueHistoryMap &Result) { + const TargetFrameLowering *TFI = MF->getSubtarget().getFrameLowering(); + bool LookInsideBundlesAndRelyOnFrameDestroy = + TFI->isFrameSetupAndFrameDestroySupported(); BitVector ChangingRegs(TRI->getNumRegs()); - collectChangingRegs(MF, TRI, ChangingRegs); + if (LookInsideBundlesAndRelyOnFrameDestroy) + collectChangingRegsInBody(MF, TRI, ChangingRegs); + else + collectChangingRegs(MF, TRI, ChangingRegs); const TargetLowering *TLI = MF->getSubtarget().getTargetLowering(); unsigned SP = TLI->getStackPointerRegisterToSaveRestore();