diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 15330c28d2c..7c50b1e4607 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -2382,9 +2382,9 @@ DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction * MF, /// DBG_VALUE instruction, is in a defined reg. static bool isDbgValueInDefinedReg(const MachineInstr *MI) { assert (MI->isDebugValue() && "Invalid DBG_VALUE machine instruction!"); - if (MI->getOperand(0).isReg() && MI->getOperand(0).getReg()) - return true; - return false; + return MI->getNumOperands() == 3 && + MI->getOperand(0).isReg() && MI->getOperand(0).getReg() && + MI->getOperand(1).isImm() && MI->getOperand(1).getImm() == 0; } /// collectVariableInfo - Populate DbgScope entries with variables' info. @@ -2407,7 +2407,7 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, DbgValues.push_back(MInsn); } - // This is a collection of DBV_VALUE instructions describing same variable. + // This is a collection of DBG_VALUE instructions describing same variable. SmallVector MultipleValues; for(SmallVector::iterator I = DbgValues.begin(), E = DbgValues.end(); I != E; ++I) { @@ -2424,8 +2424,7 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, ME = DbgValues.end(); MI != ME; ++MI) { const MDNode *Var = (*MI)->getOperand((*MI)->getNumOperands()-1).getMetadata(); - if (Var == DV && - !PrevMI->isIdenticalTo(*MI)) + if (Var == DV && !PrevMI->isIdenticalTo(*MI)) MultipleValues.push_back(*MI); PrevMI = *MI; } @@ -2448,7 +2447,7 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, DbgVariableToDbgInstMap[AbsVar] = MInsn; VarToAbstractVarMap[RegVar] = AbsVar; } - if (MultipleValues.size() <= 1) { + if (MultipleValues.size() <= 1 && !RegClobberInsn.count(MInsn)) { DbgVariableToDbgInstMap[RegVar] = MInsn; continue; } @@ -2458,16 +2457,11 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, RegVar->setDotDebugLocOffset(0); else RegVar->setDotDebugLocOffset(DotDebugLocEntries.size()); - const MachineInstr *Begin = NULL; - const MachineInstr *End = NULL; + for (SmallVector::iterator MVI = MultipleValues.begin(), MVE = MultipleValues.end(); MVI != MVE; ++MVI) { - if (!Begin) { - Begin = *MVI; - continue; - } - End = *MVI; + const MachineInstr *Begin = *MVI; MachineLocation MLoc; if (Begin->getNumOperands() == 3) { if (Begin->getOperand(0).isReg() && Begin->getOperand(1).isImm()) @@ -2475,25 +2469,25 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, } else MLoc = Asm->getDebugValueLocation(Begin); - const MCSymbol *FLabel = getLabelBeforeInsn(Begin); - const MCSymbol *SLabel = getLabelBeforeInsn(End); - if (MLoc.getReg()) - DotDebugLocEntries.push_back(DotDebugLocEntry(FLabel, SLabel, MLoc)); + if (!MLoc.getReg()) + continue; - Begin = End; - if (MVI + 1 == MVE) { - // If End is the last instruction then its value is valid + // Compute the range for a register location. + const MCSymbol *FLabel = getLabelBeforeInsn(Begin); + const MCSymbol *SLabel = 0; + + if (const MachineInstr *ClobberMI = RegClobberInsn.lookup(Begin)) + // The register range starting at Begin may be clobbered. + SLabel = getLabelAfterInsn(ClobberMI); + else if (MVI + 1 == MVE) + // If Begin is the last instruction then its value is valid // until the end of the funtion. - MachineLocation EMLoc; - if (End->getNumOperands() == 3) { - if (End->getOperand(0).isReg() && Begin->getOperand(1).isImm()) - EMLoc.set(Begin->getOperand(0).getReg(), Begin->getOperand(1).getImm()); - } else - EMLoc = Asm->getDebugValueLocation(End); - if (EMLoc.getReg()) - DotDebugLocEntries. - push_back(DotDebugLocEntry(SLabel, FunctionEndSym, EMLoc)); - } + SLabel = FunctionEndSym; + else + // The value is valid until the next DBG_VALUE. + SLabel = getLabelBeforeInsn(MVI[1]); + + DotDebugLocEntries.push_back(DotDebugLocEntry(FLabel, SLabel, MLoc)); } DotDebugLocEntries.push_back(DotDebugLocEntry()); } @@ -2568,7 +2562,7 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) { /// endInstruction - Process end of an instruction. void DwarfDebug::endInstruction(const MachineInstr *MI) { - if (InsnsEndScopeSet.count(MI) != 0) { + if (InsnsNeedsLabelAfter.count(MI) != 0) { // Emit a label if this instruction ends a scope. MCSymbol *Label = MMI->getContext().CreateTempSymbol(); Asm->OutStreamer.EmitLabel(Label); @@ -2833,7 +2827,7 @@ void DwarfDebug::identifyScopeMarkers() { RE = Ranges.end(); RI != RE; ++RI) { assert(RI->first && "DbgRange does not have first instruction!"); assert(RI->second && "DbgRange does not have second instruction!"); - InsnsEndScopeSet.insert(RI->second); + InsnsNeedsLabelAfter.insert(RI->second); } } } @@ -2914,6 +2908,14 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { /// ProcessedArgs - Collection of arguments already processed. SmallPtrSet ProcessedArgs; + /// LastDbgValue - Refer back to the last DBG_VALUE instruction to mention MD. + DenseMap LastDbgValue; + + const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo(); + + /// LiveUserVar - Map physreg numbers to the MDNode they contain. + std::vector LiveUserVar(TRI->getNumRegs()); + DebugLoc PrevLoc; for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); I != E; ++I) @@ -2923,7 +2925,15 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { DebugLoc DL = MI->getDebugLoc(); if (MI->isDebugValue()) { assert (MI->getNumOperands() > 1 && "Invalid machine instruction!"); - DIVariable DV(MI->getOperand(MI->getNumOperands() - 1).getMetadata()); + + // Keep track of variables in registers. + const MDNode *Var = + MI->getOperand(MI->getNumOperands() - 1).getMetadata(); + LastDbgValue[Var] = MI; + if (isDbgValueInDefinedReg(MI)) + LiveUserVar[MI->getOperand(0).getReg()] = Var; + + DIVariable DV(Var); if (!DV.Verify()) continue; // If DBG_VALUE is for a local variable then it needs a label. if (DV.getTag() != dwarf::DW_TAG_arg_variable) @@ -2944,6 +2954,32 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { } else if (DL != PrevLoc) // Otherwise, instruction needs a location only if it is new location. InsnNeedsLabel.insert(MI); + + // Check if the instruction clobbers any registers with debug vars. + for (MachineInstr::const_mop_iterator MOI = MI->operands_begin(), + MOE = MI->operands_end(); MOI != MOE; ++MOI) { + if (!MOI->isReg() || !MOI->isDef() || !MOI->getReg()) + continue; + for (const unsigned *AI = TRI->getOverlaps(MOI->getReg()); + unsigned Reg = *AI; ++AI) { + const MDNode *Var = LiveUserVar[Reg]; + if (!Var) + continue; + // Reg is now clobbered. + LiveUserVar[Reg] = 0; + + // Was MD last defined by a DBG_VALUE referring to Reg? + const MachineInstr *Last = LastDbgValue.lookup(Var); + if (!Last || Last->getParent() != MI->getParent()) + continue; + if (!isDbgValueInDefinedReg(Last) || + Last->getOperand(0).getReg() != Reg) + continue; + // MD is clobbered. Make sure the next instruction gets a label. + InsnsNeedsLabelAfter.insert(MI); + RegClobberInsn[Last] = MI; + } + } } if (!DL.isUnknown() || UnknownLocations) @@ -3013,7 +3049,8 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { VarToAbstractVarMap.clear(); DbgVariableToDbgInstMap.clear(); DeleteContainerSeconds(DbgScopeMap); - InsnsEndScopeSet.clear(); + InsnsNeedsLabelAfter.clear(); + RegClobberInsn.clear(); ConcreteScopes.clear(); DeleteContainerSeconds(AbstractScopes); AbstractScopesList.clear(); diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index 2863ea38060..e59ab5bd821 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -200,8 +200,6 @@ class DwarfDebug { typedef SmallVector ScopeVector; - SmallPtrSet InsnsEndScopeSet; - /// InlineInfo - Keep track of inlined functions and their location. This /// information is used to populate debug_inlined section. typedef std::pair InlineInfoLabels; @@ -224,6 +222,16 @@ class DwarfDebug { /// a debuggging information entity. SmallPtrSet InsnNeedsLabel; + /// InsnsNeedsLabelAfter - Collection of instructions that need a label after + /// the instruction because they end a scope of clobber a register. + SmallPtrSet InsnsNeedsLabelAfter; + + /// RegClobberInsn - For each DBG_VALUE instruction referring to a register + /// that is clobbered before the variable gets a new DBG_VALUE, map the + /// instruction that clobbered the register. This instruction will also be in + /// InsnsNeedsLabelAfter. + DenseMap RegClobberInsn; + SmallVector DebugRangeSymbols; /// Previous instruction's location information. This is used to determine diff --git a/lib/CodeGen/LiveDebugVariables.cpp b/lib/CodeGen/LiveDebugVariables.cpp index 20e997ae377..333d15fbe2c 100644 --- a/lib/CodeGen/LiveDebugVariables.cpp +++ b/lib/CodeGen/LiveDebugVariables.cpp @@ -101,10 +101,6 @@ class UserValue { void insertDebugValue(MachineBasicBlock *MBB, SlotIndex Idx, unsigned LocNo, LiveIntervals &LIS, const TargetInstrInfo &TII); - /// insertDebugKill - Insert an undef DBG_VALUE into MBB at Idx. - void insertDebugKill(MachineBasicBlock *MBB, SlotIndex Idx, - LiveIntervals &LIS, const TargetInstrInfo &TII); - public: /// UserValue - Create a new UserValue. UserValue(const MDNode *var, unsigned o, DebugLoc L, @@ -515,6 +511,13 @@ UserValue::addDefsFromCopies(LiveInterval *LI, unsigned LocNo, MachineInstr *MI = &*UI; unsigned 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 (!TargetRegisterInfo::isVirtualRegister(DstReg)) + continue; + // Is LocNo 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); @@ -752,13 +755,6 @@ void UserValue::insertDebugValue(MachineBasicBlock *MBB, SlotIndex Idx, .addOperand(Loc).addImm(offset).addMetadata(variable); } -void UserValue::insertDebugKill(MachineBasicBlock *MBB, SlotIndex Idx, - LiveIntervals &LIS, const TargetInstrInfo &TII) { - MachineBasicBlock::iterator I = findInsertLocation(MBB, Idx, LIS); - BuildMI(*MBB, I, findDebugLoc(), TII.get(TargetOpcode::DBG_VALUE)).addReg(0) - .addImm(offset).addMetadata(variable); -} - void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS, const TargetInstrInfo &TII) { MachineFunction::iterator MFEnd = VRM->getMachineFunction().end(); @@ -790,12 +786,6 @@ void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS, break; ++I; - if (Stop == MBBEnd) - continue; - // The current interval ends before MBB. - // Insert a kill if there is a gap. - if (!I.valid() || I.start() > Stop) - insertDebugKill(MBB, Stop, LIS, TII); } } diff --git a/test/CodeGen/X86/dbg-value-range.ll b/test/CodeGen/X86/dbg-value-range.ll index 2985224d9db..665cedcb0b3 100644 --- a/test/CodeGen/X86/dbg-value-range.ll +++ b/test/CodeGen/X86/dbg-value-range.ll @@ -41,15 +41,17 @@ declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone !18 = metadata !{i32 7, i32 2, metadata !12, null} !19 = metadata !{i32 8, i32 2, metadata !12, null} -; check that variable bar:b value range is appropriately trucated in debug info. Here Ltmp5 is end of -; location range. +; Check that variable bar:b value range is appropriately trucated in debug info. +; The variable is in %rdi which is clobbered by 'movl %ebx, %edi' +; Here Ltmp7 is the end of the location range. ;CHECK:Ltmp6 -;CHECK-NEXT: DEBUG_VALUE: bar:b <- undef +;CHECK-NEXT: movl +;CHECK-NEXT: Ltmp7 ;CHECK:Ldebug_loc0: ;CHECK-NEXT: .quad Ltmp -;CHECK-NEXT: .quad Ltmp6 +;CHECK-NEXT: .quad Ltmp7 ;CHECK-NEXT: .short 1 ;CHECK-NEXT: .byte 85 ;CHECK-NEXT: .quad 0