Reapply r128045 and r128051 with fixes.

This will extend the ranges of debug info variables in registers until they are
clobbered.

Fix 1: Don't mistake DBG_VALUE instructions referring to incoming arguments on
the stack with DBG_VALUE instructions referring to variables in the frame
pointer. This fixes the gdb test-suite failure.

Fix 2: Don't trace through copies to physical registers setting up call
arguments. These registers are call clobbered, and the source register is more
likely to be a callee-saved register that can be extended through the call
instruction.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128114 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jakob Stoklund Olesen
2011-03-22 22:33:08 +00:00
parent 27c6baeca2
commit 28cf1156c9
4 changed files with 95 additions and 58 deletions

View File

@ -2382,9 +2382,9 @@ DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction * MF,
/// DBG_VALUE instruction, is in a defined reg. /// DBG_VALUE instruction, is in a defined reg.
static bool isDbgValueInDefinedReg(const MachineInstr *MI) { static bool isDbgValueInDefinedReg(const MachineInstr *MI) {
assert (MI->isDebugValue() && "Invalid DBG_VALUE machine instruction!"); assert (MI->isDebugValue() && "Invalid DBG_VALUE machine instruction!");
if (MI->getOperand(0).isReg() && MI->getOperand(0).getReg()) return MI->getNumOperands() == 3 &&
return true; MI->getOperand(0).isReg() && MI->getOperand(0).getReg() &&
return false; MI->getOperand(1).isImm() && MI->getOperand(1).getImm() == 0;
} }
/// collectVariableInfo - Populate DbgScope entries with variables' info. /// collectVariableInfo - Populate DbgScope entries with variables' info.
@ -2407,7 +2407,7 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF,
DbgValues.push_back(MInsn); 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<const MachineInstr *, 4> MultipleValues; SmallVector<const MachineInstr *, 4> MultipleValues;
for(SmallVector<const MachineInstr *, 8>::iterator I = DbgValues.begin(), for(SmallVector<const MachineInstr *, 8>::iterator I = DbgValues.begin(),
E = DbgValues.end(); I != E; ++I) { E = DbgValues.end(); I != E; ++I) {
@ -2424,8 +2424,7 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF,
ME = DbgValues.end(); MI != ME; ++MI) { ME = DbgValues.end(); MI != ME; ++MI) {
const MDNode *Var = const MDNode *Var =
(*MI)->getOperand((*MI)->getNumOperands()-1).getMetadata(); (*MI)->getOperand((*MI)->getNumOperands()-1).getMetadata();
if (Var == DV && if (Var == DV && !PrevMI->isIdenticalTo(*MI))
!PrevMI->isIdenticalTo(*MI))
MultipleValues.push_back(*MI); MultipleValues.push_back(*MI);
PrevMI = *MI; PrevMI = *MI;
} }
@ -2448,7 +2447,7 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF,
DbgVariableToDbgInstMap[AbsVar] = MInsn; DbgVariableToDbgInstMap[AbsVar] = MInsn;
VarToAbstractVarMap[RegVar] = AbsVar; VarToAbstractVarMap[RegVar] = AbsVar;
} }
if (MultipleValues.size() <= 1) { if (MultipleValues.size() <= 1 && !RegClobberInsn.count(MInsn)) {
DbgVariableToDbgInstMap[RegVar] = MInsn; DbgVariableToDbgInstMap[RegVar] = MInsn;
continue; continue;
} }
@ -2458,16 +2457,11 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF,
RegVar->setDotDebugLocOffset(0); RegVar->setDotDebugLocOffset(0);
else else
RegVar->setDotDebugLocOffset(DotDebugLocEntries.size()); RegVar->setDotDebugLocOffset(DotDebugLocEntries.size());
const MachineInstr *Begin = NULL;
const MachineInstr *End = NULL;
for (SmallVector<const MachineInstr *, 4>::iterator for (SmallVector<const MachineInstr *, 4>::iterator
MVI = MultipleValues.begin(), MVE = MultipleValues.end(); MVI = MultipleValues.begin(), MVE = MultipleValues.end();
MVI != MVE; ++MVI) { MVI != MVE; ++MVI) {
if (!Begin) { const MachineInstr *Begin = *MVI;
Begin = *MVI;
continue;
}
End = *MVI;
MachineLocation MLoc; MachineLocation MLoc;
if (Begin->getNumOperands() == 3) { if (Begin->getNumOperands() == 3) {
if (Begin->getOperand(0).isReg() && Begin->getOperand(1).isImm()) if (Begin->getOperand(0).isReg() && Begin->getOperand(1).isImm())
@ -2475,25 +2469,25 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF,
} else } else
MLoc = Asm->getDebugValueLocation(Begin); MLoc = Asm->getDebugValueLocation(Begin);
const MCSymbol *FLabel = getLabelBeforeInsn(Begin); if (!MLoc.getReg())
const MCSymbol *SLabel = getLabelBeforeInsn(End); continue;
if (MLoc.getReg())
DotDebugLocEntries.push_back(DotDebugLocEntry(FLabel, SLabel, MLoc));
Begin = End; // Compute the range for a register location.
if (MVI + 1 == MVE) { const MCSymbol *FLabel = getLabelBeforeInsn(Begin);
// If End is the last instruction then its value is valid 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. // until the end of the funtion.
MachineLocation EMLoc; SLabel = FunctionEndSym;
if (End->getNumOperands() == 3) { else
if (End->getOperand(0).isReg() && Begin->getOperand(1).isImm()) // The value is valid until the next DBG_VALUE.
EMLoc.set(Begin->getOperand(0).getReg(), Begin->getOperand(1).getImm()); SLabel = getLabelBeforeInsn(MVI[1]);
} else
EMLoc = Asm->getDebugValueLocation(End); DotDebugLocEntries.push_back(DotDebugLocEntry(FLabel, SLabel, MLoc));
if (EMLoc.getReg())
DotDebugLocEntries.
push_back(DotDebugLocEntry(SLabel, FunctionEndSym, EMLoc));
}
} }
DotDebugLocEntries.push_back(DotDebugLocEntry()); DotDebugLocEntries.push_back(DotDebugLocEntry());
} }
@ -2568,7 +2562,7 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
/// endInstruction - Process end of an instruction. /// endInstruction - Process end of an instruction.
void DwarfDebug::endInstruction(const MachineInstr *MI) { 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. // Emit a label if this instruction ends a scope.
MCSymbol *Label = MMI->getContext().CreateTempSymbol(); MCSymbol *Label = MMI->getContext().CreateTempSymbol();
Asm->OutStreamer.EmitLabel(Label); Asm->OutStreamer.EmitLabel(Label);
@ -2833,7 +2827,7 @@ void DwarfDebug::identifyScopeMarkers() {
RE = Ranges.end(); RI != RE; ++RI) { RE = Ranges.end(); RI != RE; ++RI) {
assert(RI->first && "DbgRange does not have first instruction!"); assert(RI->first && "DbgRange does not have first instruction!");
assert(RI->second && "DbgRange does not have second 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. /// ProcessedArgs - Collection of arguments already processed.
SmallPtrSet<const MDNode *, 8> ProcessedArgs; SmallPtrSet<const MDNode *, 8> ProcessedArgs;
/// LastDbgValue - Refer back to the last DBG_VALUE instruction to mention MD.
DenseMap<const MDNode*, const MachineInstr*> LastDbgValue;
const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo();
/// LiveUserVar - Map physreg numbers to the MDNode they contain.
std::vector<const MDNode*> LiveUserVar(TRI->getNumRegs());
DebugLoc PrevLoc; DebugLoc PrevLoc;
for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
I != E; ++I) I != E; ++I)
@ -2923,7 +2925,15 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) {
DebugLoc DL = MI->getDebugLoc(); DebugLoc DL = MI->getDebugLoc();
if (MI->isDebugValue()) { if (MI->isDebugValue()) {
assert (MI->getNumOperands() > 1 && "Invalid machine instruction!"); 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 (!DV.Verify()) continue;
// If DBG_VALUE is for a local variable then it needs a label. // If DBG_VALUE is for a local variable then it needs a label.
if (DV.getTag() != dwarf::DW_TAG_arg_variable) if (DV.getTag() != dwarf::DW_TAG_arg_variable)
@ -2944,6 +2954,32 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) {
} else if (DL != PrevLoc) } else if (DL != PrevLoc)
// Otherwise, instruction needs a location only if it is new location. // Otherwise, instruction needs a location only if it is new location.
InsnNeedsLabel.insert(MI); 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) if (!DL.isUnknown() || UnknownLocations)
@ -3013,7 +3049,8 @@ void DwarfDebug::endFunction(const MachineFunction *MF) {
VarToAbstractVarMap.clear(); VarToAbstractVarMap.clear();
DbgVariableToDbgInstMap.clear(); DbgVariableToDbgInstMap.clear();
DeleteContainerSeconds(DbgScopeMap); DeleteContainerSeconds(DbgScopeMap);
InsnsEndScopeSet.clear(); InsnsNeedsLabelAfter.clear();
RegClobberInsn.clear();
ConcreteScopes.clear(); ConcreteScopes.clear();
DeleteContainerSeconds(AbstractScopes); DeleteContainerSeconds(AbstractScopes);
AbstractScopesList.clear(); AbstractScopesList.clear();

View File

@ -200,8 +200,6 @@ class DwarfDebug {
typedef SmallVector<DbgScope *, 2> ScopeVector; typedef SmallVector<DbgScope *, 2> ScopeVector;
SmallPtrSet<const MachineInstr *, 8> InsnsEndScopeSet;
/// InlineInfo - Keep track of inlined functions and their location. This /// InlineInfo - Keep track of inlined functions and their location. This
/// information is used to populate debug_inlined section. /// information is used to populate debug_inlined section.
typedef std::pair<const MCSymbol *, DIE *> InlineInfoLabels; typedef std::pair<const MCSymbol *, DIE *> InlineInfoLabels;
@ -224,6 +222,16 @@ class DwarfDebug {
/// a debuggging information entity. /// a debuggging information entity.
SmallPtrSet<const MachineInstr *, 8> InsnNeedsLabel; SmallPtrSet<const MachineInstr *, 8> InsnNeedsLabel;
/// InsnsNeedsLabelAfter - Collection of instructions that need a label after
/// the instruction because they end a scope of clobber a register.
SmallPtrSet<const MachineInstr *, 8> 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<const MachineInstr *, const MachineInstr *> RegClobberInsn;
SmallVector<const MCSymbol *, 8> DebugRangeSymbols; SmallVector<const MCSymbol *, 8> DebugRangeSymbols;
/// Previous instruction's location information. This is used to determine /// Previous instruction's location information. This is used to determine

View File

@ -101,10 +101,6 @@ class UserValue {
void insertDebugValue(MachineBasicBlock *MBB, SlotIndex Idx, unsigned LocNo, void insertDebugValue(MachineBasicBlock *MBB, SlotIndex Idx, unsigned LocNo,
LiveIntervals &LIS, const TargetInstrInfo &TII); 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: public:
/// UserValue - Create a new UserValue. /// UserValue - Create a new UserValue.
UserValue(const MDNode *var, unsigned o, DebugLoc L, UserValue(const MDNode *var, unsigned o, DebugLoc L,
@ -515,6 +511,13 @@ UserValue::addDefsFromCopies(LiveInterval *LI, unsigned LocNo,
MachineInstr *MI = &*UI; MachineInstr *MI = &*UI;
unsigned DstReg = MI->getOperand(0).getReg(); 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 // 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. // it, or we are looking at a wrong value of LI.
SlotIndex Idx = LIS.getInstructionIndex(MI); SlotIndex Idx = LIS.getInstructionIndex(MI);
@ -752,13 +755,6 @@ void UserValue::insertDebugValue(MachineBasicBlock *MBB, SlotIndex Idx,
.addOperand(Loc).addImm(offset).addMetadata(variable); .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, void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS,
const TargetInstrInfo &TII) { const TargetInstrInfo &TII) {
MachineFunction::iterator MFEnd = VRM->getMachineFunction().end(); MachineFunction::iterator MFEnd = VRM->getMachineFunction().end();
@ -790,12 +786,6 @@ void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS,
break; break;
++I; ++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);
} }
} }

View File

@ -41,15 +41,17 @@ declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone
!18 = metadata !{i32 7, i32 2, metadata !12, null} !18 = metadata !{i32 7, i32 2, metadata !12, null}
!19 = metadata !{i32 8, 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 ; Check that variable bar:b value range is appropriately trucated in debug info.
; location range. ; The variable is in %rdi which is clobbered by 'movl %ebx, %edi'
; Here Ltmp7 is the end of the location range.
;CHECK:Ltmp6 ;CHECK:Ltmp6
;CHECK-NEXT: DEBUG_VALUE: bar:b <- undef ;CHECK-NEXT: movl
;CHECK-NEXT: Ltmp7
;CHECK:Ldebug_loc0: ;CHECK:Ldebug_loc0:
;CHECK-NEXT: .quad Ltmp ;CHECK-NEXT: .quad Ltmp
;CHECK-NEXT: .quad Ltmp6 ;CHECK-NEXT: .quad Ltmp7
;CHECK-NEXT: .short 1 ;CHECK-NEXT: .short 1
;CHECK-NEXT: .byte 85 ;CHECK-NEXT: .byte 85
;CHECK-NEXT: .quad 0 ;CHECK-NEXT: .quad 0