From adb877d62e5ac88db037d91bcd2e9f7dc2c4cd7a Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Sat, 26 Mar 2011 02:19:36 +0000 Subject: [PATCH] Collect and coalesce DBG_VALUE instructions before emitting the function. Correctly terminate the range of register DBG_VALUEs when the register is clobbered or when the basic block ends. The code is now ready to deal with variables that are sometimes in a register and sometimes on the stack. We just need to teach emitDebugLoc to say 'stack slot'. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128327 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/MachineBasicBlock.h | 4 + lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 253 ++++++++++++++--------- lib/CodeGen/AsmPrinter/DwarfDebug.h | 44 ++-- test/CodeGen/X86/dbg-merge-loc-entry.ll | 2 +- 4 files changed, 192 insertions(+), 111 deletions(-) diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index 19060933888..5a6581c21c0 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -309,6 +309,10 @@ public: /// instruction in the basic block, or end() iterator getLastNonDebugInstr(); + const_iterator getLastNonDebugInstr() const { + return const_cast(this)->getLastNonDebugInstr(); + } + /// SplitCriticalEdge - Split the critical edge from this block to the /// given successor block, and return the newly created block, or null /// if splitting is not possible. diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index b5a266dc6e9..9026aefc494 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -2408,38 +2408,21 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, /// collection info from MMI table. collectVariableInfoFromMMITable(MF, Processed); - SmallVector DbgValues; - // Collect variable information from DBG_VALUE machine instructions; - for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end(); - I != E; ++I) - for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); - II != IE; ++II) { - const MachineInstr *MInsn = II; - if (!MInsn->isDebugValue()) - continue; - DbgValues.push_back(MInsn); - } - - // 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) { - const MachineInstr *MInsn = *I; - MultipleValues.clear(); - if (isDbgValueInDefinedReg(MInsn)) - MultipleValues.push_back(MInsn); - DIVariable DV(MInsn->getOperand(MInsn->getNumOperands() - 1).getMetadata()); - if (Processed.count(DV) != 0) + for (SmallVectorImpl::const_iterator + UVI = UserVariables.begin(), UVE = UserVariables.end(); UVI != UVE; + ++UVI) { + const MDNode *Var = *UVI; + if (Processed.count(Var)) continue; - for (SmallVector::iterator MI = I+1, - ME = DbgValues.end(); MI != ME; ++MI) { - const MDNode *Var = - (*MI)->getOperand((*MI)->getNumOperands()-1).getMetadata(); - if (Var == DV) - MultipleValues.push_back(*MI); - } + // History contains relevant DBG_VALUE instructions for Var and instructions + // clobbering it. + SmallVectorImpl &History = DbgValues[Var]; + if (History.empty()) + continue; + const MachineInstr *MInsn = History.front(); + DIVariable DV(Var); DbgScope *Scope = NULL; if (DV.getTag() == dwarf::DW_TAG_arg_variable && DISubprogram(DV.getContext()).describes(MF->getFunction())) @@ -2451,6 +2434,7 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, continue; Processed.insert(DV); + assert(MInsn->isDebugValue() && "History must begin with debug value"); DbgVariable *RegVar = new DbgVariable(DV); if (!addCurrentFnArgument(MF, RegVar, Scope)) Scope->addVariable(RegVar); @@ -2458,21 +2442,21 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, DbgVariableToDbgInstMap[AbsVar] = MInsn; VarToAbstractVarMap[RegVar] = AbsVar; } - if (MultipleValues.size() <= 1 && !RegClobberInsn.count(MInsn)) { + + // Simple ranges that are fully coalesced. + if (History.size() <= 1 || (History.size() == 2 && + MInsn->isIdenticalTo(History.back()))) { DbgVariableToDbgInstMap[RegVar] = MInsn; continue; } // handle multiple DBG_VALUE instructions describing one variable. - if (DotDebugLocEntries.empty()) - RegVar->setDotDebugLocOffset(0); - else - RegVar->setDotDebugLocOffset(DotDebugLocEntries.size()); + RegVar->setDotDebugLocOffset(DotDebugLocEntries.size()); - for (SmallVector::iterator - MVI = MultipleValues.begin(), MVE = MultipleValues.end(); - MVI != MVE; ++MVI) { - const MachineInstr *Begin = *MVI; + for (SmallVectorImpl::const_iterator + HI = History.begin(), HE = History.end(); HI != HE; ++HI) { + const MachineInstr *Begin = *HI; + assert(Begin->isDebugValue() && "Invalid History entry"); MachineLocation MLoc; if (Begin->getNumOperands() == 3) { if (Begin->getOperand(0).isReg() && Begin->getOperand(1).isImm()) @@ -2480,6 +2464,7 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, } else MLoc = Asm->getDebugValueLocation(Begin); + // FIXME: emitDebugLoc only understands registers. if (!MLoc.getReg()) continue; @@ -2487,17 +2472,23 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, 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 + if (HI + 1 == HE) + // If Begin is the last instruction in History then its value is valid // until the end of the funtion. SLabel = FunctionEndSym; - else - // The value is valid until the next DBG_VALUE. - SLabel = getLabelBeforeInsn(MVI[1]); + else { + const MachineInstr *End = HI[1]; + if (End->isDebugValue()) + SLabel = getLabelBeforeInsn(End); + else { + // End is a normal instruction clobbering the range. + SLabel = getLabelAfterInsn(End); + assert(SLabel && "Forgot label after clobber instruction"); + ++HI; + } + } + // The value is valid until the next DBG_VALUE or clobber. DotDebugLocEntries.push_back(DotDebugLocEntry(FLabel, SLabel, MLoc)); } DotDebugLocEntries.push_back(DotDebugLocEntry()); @@ -2519,21 +2510,14 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, /// getLabelBeforeInsn - Return Label preceding the instruction. const MCSymbol *DwarfDebug::getLabelBeforeInsn(const MachineInstr *MI) { - DenseMap::iterator I = - LabelsBeforeInsn.find(MI); - if (I == LabelsBeforeInsn.end()) - // FunctionBeginSym always preceeds all the instruction in current function. - return FunctionBeginSym; - return I->second; + MCSymbol *Label = LabelsBeforeInsn.lookup(MI); + assert(Label && "Didn't insert label before instruction"); + return Label; } /// getLabelAfterInsn - Return Label immediately following the instruction. const MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) { - DenseMap::iterator I = - LabelsAfterInsn.find(MI); - if (I == LabelsAfterInsn.end()) - return NULL; - return I->second; + return LabelsAfterInsn.lookup(MI); } /// beginInstruction - Process beginning of an instruction. @@ -2552,14 +2536,22 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) { } // Insert labels where requested. - if (!InsnNeedsLabel.count(MI)) + DenseMap::iterator I = + LabelsBeforeInsn.find(MI); + + // No label needed. + if (I == LabelsBeforeInsn.end()) + return; + + // Label already assigned. + if (I->second) return; if (!PrevLabel) { PrevLabel = MMI->getContext().CreateTempSymbol(); Asm->OutStreamer.EmitLabel(PrevLabel); } - LabelsBeforeInsn[MI] = PrevLabel; + I->second = PrevLabel; } /// endInstruction - Process end of an instruction. @@ -2569,7 +2561,15 @@ void DwarfDebug::endInstruction(const MachineInstr *MI) { if (!MI->isDebugValue()) PrevLabel = 0; - if (!InsnsNeedsLabelAfter.count(MI)) + DenseMap::iterator I = + LabelsAfterInsn.find(MI); + + // No label needed. + if (I == LabelsAfterInsn.end()) + return; + + // Label already assigned. + if (I->second) return; // We need a label after this instruction. @@ -2577,7 +2577,7 @@ void DwarfDebug::endInstruction(const MachineInstr *MI) { PrevLabel = MMI->getContext().CreateTempSymbol(); Asm->OutStreamer.EmitLabel(PrevLabel); } - LabelsAfterInsn[MI] = PrevLabel; + I->second = PrevLabel; } /// getOrCreateDbgScope - Create DbgScope for the scope. @@ -2837,8 +2837,8 @@ 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!"); - InsnNeedsLabel.insert(RI->first); - InsnsNeedsLabelAfter.insert(RI->second); + requestLabelBeforeInsn(RI->first); + requestLabelAfterInsn(RI->second); } } } @@ -2916,46 +2916,78 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { recordSourceLine(Line, Col, TheScope); + assert(UserVariables.empty() && DbgValues.empty() && "Maps weren't cleaned"); + /// 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()); for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); - I != E; ++I) + I != E; ++I) { + bool AtBlockEntry = true; for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); II != IE; ++II) { const MachineInstr *MI = II; - DebugLoc DL = MI->getDebugLoc(); + if (MI->isDebugValue()) { assert (MI->getNumOperands() > 1 && "Invalid machine instruction!"); - // Keep track of variables in registers. + // Keep track of user variables. const MDNode *Var = MI->getOperand(MI->getNumOperands() - 1).getMetadata(); - LastDbgValue[Var] = MI; + + // Variable is in a register, we need to check for clobbers. 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) - InsnNeedsLabel.insert(MI); - // DBG_VALUE for inlined functions argument needs a label. - else if (!DISubprogram(getDISubprogram(DV.getContext())). - describes(MF->getFunction())) - InsnNeedsLabel.insert(MI); - // DBG_VALUE indicating argument location change needs a label. - else if (!ProcessedArgs.insert(DV)) - InsnNeedsLabel.insert(MI); + // Check the history of this variable. + SmallVectorImpl &History = DbgValues[Var]; + if (History.empty()) { + UserVariables.push_back(Var); + // The first mention of a function argument gets the FunctionBeginSym + // label, so arguments are visible when breaking at function entry. + DIVariable DV(Var); + if (DV.Verify() && DV.getTag() == dwarf::DW_TAG_arg_variable && + DISubprogram(getDISubprogram(DV.getContext())) + .describes(MF->getFunction())) + LabelsBeforeInsn[MI] = FunctionBeginSym; + } else { + // We have seen this variable before. Try to coalesce DBG_VALUEs. + const MachineInstr *Prev = History.back(); + if (Prev->isDebugValue()) { + // Coalesce identical entries at the end of History. + if (History.size() >= 2 && + Prev->isIdenticalTo(History[History.size() - 2])) + History.pop_back(); + + // Terminate old register assignments that don't reach MI; + MachineFunction::const_iterator PrevMBB = Prev->getParent(); + if (PrevMBB != I && (!AtBlockEntry || llvm::next(PrevMBB) != I) && + isDbgValueInDefinedReg(Prev)) { + // Previous register assignment needs to terminate at the end of + // its basic block. + MachineBasicBlock::const_iterator LastMI = + PrevMBB->getLastNonDebugInstr(); + if (LastMI == PrevMBB->end()) + // Drop DBG_VALUE for empty range. + History.pop_back(); + else { + // Terminate after LastMI. + History.push_back(LastMI); + } + } + } + } + History.push_back(MI); } else { + // Not a DBG_VALUE instruction. + if (!MI->isLabel()) + AtBlockEntry = false; + // 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) { @@ -2970,19 +3002,57 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { 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()) + DbgValueHistoryMap::iterator HistI = DbgValues.find(Var); + if (HistI == DbgValues.end()) + continue; + SmallVectorImpl &History = HistI->second; + if (History.empty()) + continue; + const MachineInstr *Prev = History.back(); + // Sanity-check: Register assignments are terminated at the end of + // their block. + if (!Prev->isDebugValue() || Prev->getParent() != MI->getParent()) continue; - if (!isDbgValueInDefinedReg(Last) || - Last->getOperand(0).getReg() != Reg) + // Is the variable still in Reg? + if (!isDbgValueInDefinedReg(Prev) || + Prev->getOperand(0).getReg() != Reg) continue; - // MD is clobbered. Make sure the next instruction gets a label. - InsnsNeedsLabelAfter.insert(MI); - RegClobberInsn[Last] = MI; + // Var is clobbered. Make sure the next instruction gets a label. + History.push_back(MI); } } } } + } + + for (DbgValueHistoryMap::iterator I = DbgValues.begin(), E = DbgValues.end(); + I != E; ++I) { + SmallVectorImpl &History = I->second; + if (History.empty()) + continue; + + // Make sure the final register assignments are terminated. + const MachineInstr *Prev = History.back(); + if (Prev->isDebugValue() && isDbgValueInDefinedReg(Prev)) { + const MachineBasicBlock *PrevMBB = Prev->getParent(); + MachineBasicBlock::const_iterator LastMI = PrevMBB->getLastNonDebugInstr(); + if (LastMI == PrevMBB->end()) + // Drop DBG_VALUE for empty range. + History.pop_back(); + else { + // Terminate after LastMI. + History.push_back(LastMI); + } + } + // Request labels for the full history. + for (unsigned i = 0, e = History.size(); i != e; ++i) { + const MachineInstr *MI = History[i]; + if (MI->isDebugValue()) + requestLabelBeforeInsn(MI); + else + requestLabelAfterInsn(MI); + } + } PrevInstLoc = DebugLoc(); PrevLabel = FunctionBeginSym; @@ -3043,13 +3113,12 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { // Clear debug info CurrentFnDbgScope = NULL; CurrentFnArguments.clear(); - InsnNeedsLabel.clear(); DbgVariableToFrameIndexMap.clear(); VarToAbstractVarMap.clear(); DbgVariableToDbgInstMap.clear(); DeleteContainerSeconds(DbgScopeMap); - InsnsNeedsLabelAfter.clear(); - RegClobberInsn.clear(); + UserVariables.clear(); + DbgValues.clear(); ConcreteScopes.clear(); DeleteContainerSeconds(AbstractScopes); AbstractScopesList.clear(); diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index a4260fb5ac6..18155271a05 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -218,19 +218,16 @@ class DwarfDebug { /// instruction. DenseMap LabelsAfterInsn; - /// insnNeedsLabel - Collection of instructions that need a label to mark - /// a debuggging information entity. - SmallPtrSet InsnNeedsLabel; + /// UserVariables - Every user variable mentioned by a DBG_VALUE instruction + /// in order of appearance. + SmallVector UserVariables; - /// 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; + /// DbgValues - For each user variable, keep a list of DBG_VALUE + /// instructions in order. The list can also contain normal instructions that + /// clobber the previous DBG_VALUE. + typedef DenseMap > + DbgValueHistoryMap; + DbgValueHistoryMap DbgValues; SmallVector DebugRangeSymbols; @@ -570,6 +567,23 @@ private: /// side table maintained by MMI. void collectVariableInfoFromMMITable(const MachineFunction * MF, SmallPtrSet &P); + + /// requestLabelBeforeInsn - Ensure that a label will be emitted before MI. + void requestLabelBeforeInsn(const MachineInstr *MI) { + LabelsBeforeInsn.insert(std::make_pair(MI, (MCSymbol*)0)); + } + + /// getLabelBeforeInsn - Return Label preceding the instruction. + const MCSymbol *getLabelBeforeInsn(const MachineInstr *MI); + + /// requestLabelAfterInsn - Ensure that a label will be emitted after MI. + void requestLabelAfterInsn(const MachineInstr *MI) { + LabelsAfterInsn.insert(std::make_pair(MI, (MCSymbol*)0)); + } + + /// getLabelAfterInsn - Return Label immediately following the instruction. + const MCSymbol *getLabelAfterInsn(const MachineInstr *MI); + public: //===--------------------------------------------------------------------===// // Main entry points. @@ -593,12 +607,6 @@ public: /// void endFunction(const MachineFunction *MF); - /// getLabelBeforeInsn - Return Label preceding the instruction. - const MCSymbol *getLabelBeforeInsn(const MachineInstr *MI); - - /// getLabelAfterInsn - Return Label immediately following the instruction. - const MCSymbol *getLabelAfterInsn(const MachineInstr *MI); - /// beginInstruction - Process beginning of an instruction. void beginInstruction(const MachineInstr *MI); diff --git a/test/CodeGen/X86/dbg-merge-loc-entry.ll b/test/CodeGen/X86/dbg-merge-loc-entry.ll index 83df1478cf1..9c75c51d11b 100644 --- a/test/CodeGen/X86/dbg-merge-loc-entry.ll +++ b/test/CodeGen/X86/dbg-merge-loc-entry.ll @@ -4,7 +4,7 @@ target triple = "x86_64-apple-darwin8" ;CHECK: Ldebug_loc0: ;CHECK-NEXT: .quad Lfunc_begin0 -;CHECK-NEXT: .quad Lfunc_end0 +;CHECK-NEXT: .quad L ;CHECK-NEXT: .short 1 ## Loc expr size ;CHECK-NEXT: .byte 85 ## DW_OP_reg5 ;CHECK-NEXT: .quad 0 -- 2.34.1