diff options
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 28 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp | 140 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp | 28 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 130 |
4 files changed, 220 insertions, 106 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index 75a63df083a..89cd7a8e3bd 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -1160,7 +1160,9 @@ void CodeViewDebug::calculateRanges( // Calculate the definition ranges. for (auto I = Entries.begin(), E = Entries.end(); I != E; ++I) { const auto &Entry = *I; - const MachineInstr *DVInst = Entry.getBegin(); + if (!Entry.isDbgValue()) + continue; + const MachineInstr *DVInst = Entry.getInstr(); assert(DVInst->isDebugValue() && "Invalid History entry"); // FIXME: Find a way to represent constant variables, since they are // relatively common. @@ -1215,21 +1217,15 @@ void CodeViewDebug::calculateRanges( } // Compute the label range. - const MCSymbol *Begin = getLabelBeforeInsn(Entry.getBegin()); - const MCSymbol *End = getLabelAfterInsn(Entry.getEnd()); - if (!End) { - // This range is valid until the next overlapping bitpiece. In the - // common case, ranges will not be bitpieces, so they will overlap. - auto J = std::next(I); - const DIExpression *DIExpr = DVInst->getDebugExpression(); - while (J != E && - !DIExpr->fragmentsOverlap(J->getBegin()->getDebugExpression())) - ++J; - if (J != E) - End = getLabelBeforeInsn(J->getBegin()); - else - End = Asm->getFunctionEnd(); - } + const MCSymbol *Begin = getLabelBeforeInsn(Entry.getInstr()); + const MCSymbol *End; + if (Entry.getEndIndex() != DbgValueHistoryMap::NoEntry) { + auto &EndingEntry = Entries[Entry.getEndIndex()]; + End = EndingEntry.isDbgValue() + ? getLabelBeforeInsn(EndingEntry.getInstr()) + : getLabelAfterInsn(EndingEntry.getInstr()); + } else + End = Asm->getFunctionEnd(); // If the last range end is our begin, just extend the last range. // Otherwise make a new range. diff --git a/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp b/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp index 618fee9544d..5dec591c722 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp @@ -9,6 +9,7 @@ #include "llvm/CodeGen/DbgEntityHistoryCalculator.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" @@ -30,6 +31,10 @@ using namespace llvm; #define DEBUG_TYPE "dwarfdebug" +namespace { +using EntryIndex = DbgValueHistoryMap::EntryIndex; +} + // If @MI is a DBG_VALUE with debug value described by a // defined register, returns the number of this register. // In the other case, returns 0. @@ -41,33 +46,39 @@ static unsigned isDescribedByReg(const MachineInstr &MI) { return MI.getOperand(0).isReg() ? MI.getOperand(0).getReg() : 0; } -void DbgValueHistoryMap::startEntry(InlinedEntity Var, const MachineInstr &MI) { +bool DbgValueHistoryMap::startDbgValue(InlinedEntity Var, + const MachineInstr &MI, + EntryIndex &NewIndex) { // Instruction range should start with a DBG_VALUE instruction for the // variable. assert(MI.isDebugValue() && "not a DBG_VALUE"); auto &Entries = VarEntries[Var]; - if (!Entries.empty() && !Entries.back().isClosed() && - Entries.back().getBegin()->isIdenticalTo(MI)) { + if (!Entries.empty() && Entries.back().isDbgValue() && + !Entries.back().isClosed() && + Entries.back().getInstr()->isIdenticalTo(MI)) { LLVM_DEBUG(dbgs() << "Coalescing identical DBG_VALUE entries:\n" - << "\t" << Entries.back().getBegin() << "\t" << MI + << "\t" << Entries.back().getInstr() << "\t" << MI << "\n"); - return; + return false; } - Entries.emplace_back(&MI); + Entries.emplace_back(&MI, Entry::DbgValue); + NewIndex = Entries.size() - 1; + return true; } -void DbgValueHistoryMap::endEntry(InlinedEntity Var, const MachineInstr &MI) { +EntryIndex DbgValueHistoryMap::startClobber(InlinedEntity Var, + const MachineInstr &MI) { auto &Entries = VarEntries[Var]; - assert(!Entries.empty() && "No range exists for variable!"); - Entries.back().endEntry(MI); + Entries.emplace_back(&MI, Entry::Clobber); + return Entries.size() - 1; } -void DbgValueHistoryMap::Entry::endEntry(const MachineInstr &MI) { +void DbgValueHistoryMap::Entry::endEntry(EntryIndex Index) { // For now, instruction ranges are not allowed to cross basic block // boundaries. - assert(Begin->getParent() == MI.getParent()); - assert(!isClosed() && "Range is already closed!"); - End = &MI; + assert(isDbgValue() && "Setting end index for non-debug value"); + assert(!isClosed() && "End index has already been set"); + EndIndex = Index; } unsigned DbgValueHistoryMap::getRegisterForVar(InlinedEntity Var) const { @@ -77,7 +88,9 @@ unsigned DbgValueHistoryMap::getRegisterForVar(InlinedEntity Var) const { const auto &Entries = I->second; if (Entries.empty() || Entries.back().isClosed()) return 0; - return isDescribedByReg(*Entries.back().getBegin()); + if (Entries.back().isClobber()) + return 0; + return isDescribedByReg(*Entries.back().getInstr()); } void DbgLabelInstrMap::addInstr(InlinedEntity Label, const MachineInstr &MI) { @@ -91,6 +104,12 @@ namespace { using InlinedEntity = DbgValueHistoryMap::InlinedEntity; using RegDescribedVarsMap = std::map<unsigned, SmallVector<InlinedEntity, 1>>; +// Keeps track of the debug value entries that are currently live for each +// inlined entity. As the history map entries are stored in a SmallVector, they +// may be moved at insertion of new entries, so store indices rather than +// pointers. +using DbgValueEntriesMap = std::map<InlinedEntity, SmallSet<EntryIndex, 1>>; + } // end anonymous namespace // Claim that @Var is not described by @RegNo anymore. @@ -116,16 +135,67 @@ static void addRegDescribedVar(RegDescribedVarsMap &RegVars, unsigned RegNo, VarSet.push_back(Var); } +static void clobberRegEntries(InlinedEntity Var, unsigned RegNo, + const MachineInstr &ClobberingInstr, + DbgValueEntriesMap &LiveEntries, + DbgValueHistoryMap &HistMap) { + EntryIndex ClobberIndex = HistMap.startClobber(Var, ClobberingInstr); + + // TODO: Close all preceding live entries that are clobbered by this + // instruction. + EntryIndex ValueIndex = ClobberIndex - 1; + auto &ValueEntry = HistMap.getEntry(Var, ValueIndex); + ValueEntry.endEntry(ClobberIndex); + LiveEntries[Var].erase(ValueIndex); +} + +/// Add a new debug value for \p Var. Closes all overlapping debug values. +static void handleNewDebugValue(InlinedEntity Var, const MachineInstr &DV, + RegDescribedVarsMap &RegVars, + DbgValueEntriesMap &LiveEntries, + DbgValueHistoryMap &HistMap) { + // TODO: We should track all registers which this variable is currently + // described by. + + if (unsigned PrevReg = HistMap.getRegisterForVar(Var)) + dropRegDescribedVar(RegVars, PrevReg, Var); + + EntryIndex NewIndex; + if (HistMap.startDbgValue(Var, DV, NewIndex)) { + // If we have created a new debug value entry, close all preceding + // live entries that overlap. + SmallVector<EntryIndex, 4> IndicesToErase; + const DIExpression *DIExpr = DV.getDebugExpression(); + for (auto Index : LiveEntries[Var]) { + auto &Entry = HistMap.getEntry(Var, Index); + assert(Entry.isDbgValue() && "Not a DBG_VALUE in LiveEntries"); + const MachineInstr &DV = *Entry.getInstr(); + if (DIExpr->fragmentsOverlap(DV.getDebugExpression())) { + IndicesToErase.push_back(Index); + Entry.endEntry(NewIndex); + } + } + // Drop all entries that have ended, and mark the new entry as live. + for (auto Index : IndicesToErase) + LiveEntries[Var].erase(Index); + LiveEntries[Var].insert(NewIndex); + } + + if (unsigned NewReg = isDescribedByReg(DV)) + addRegDescribedVar(RegVars, NewReg, Var); +} + // Terminate the location range for variables described by register at // @I by inserting @ClobberingInstr to their history. static void clobberRegisterUses(RegDescribedVarsMap &RegVars, RegDescribedVarsMap::iterator I, DbgValueHistoryMap &HistMap, + DbgValueEntriesMap &LiveEntries, const MachineInstr &ClobberingInstr) { // Iterate over all variables described by this register and add this // instruction to their history, clobbering it. for (const auto &Var : I->second) - HistMap.endEntry(Var, ClobberingInstr); + clobberRegEntries(Var, I->first, ClobberingInstr, LiveEntries, HistMap); RegVars.erase(I); } @@ -133,11 +203,12 @@ static void clobberRegisterUses(RegDescribedVarsMap &RegVars, // @RegNo by inserting @ClobberingInstr to their history. static void clobberRegisterUses(RegDescribedVarsMap &RegVars, unsigned RegNo, DbgValueHistoryMap &HistMap, + DbgValueEntriesMap &LiveEntries, const MachineInstr &ClobberingInstr) { const auto &I = RegVars.find(RegNo); if (I == RegVars.end()) return; - clobberRegisterUses(RegVars, I, HistMap, ClobberingInstr); + clobberRegisterUses(RegVars, I, HistMap, LiveEntries, ClobberingInstr); } // Returns the first instruction in @MBB which corresponds to @@ -204,6 +275,7 @@ void llvm::calculateDbgEntityHistory(const MachineFunction *MF, const TargetLowering *TLI = MF->getSubtarget().getTargetLowering(); unsigned SP = TLI->getStackPointerRegisterToSaveRestore(); RegDescribedVarsMap RegVars; + DbgValueEntriesMap LiveEntries; for (const auto &MBB : *MF) { for (const auto &MI : MBB) { if (!MI.isDebugInstr()) { @@ -218,14 +290,15 @@ void llvm::calculateDbgEntityHistory(const MachineFunction *MF, // If this is a virtual register, only clobber it since it doesn't // have aliases. if (TRI->isVirtualRegister(MO.getReg())) - clobberRegisterUses(RegVars, MO.getReg(), DbgValues, MI); + clobberRegisterUses(RegVars, MO.getReg(), DbgValues, LiveEntries, + MI); // If this is a register def operand, it may end a debug value // range. else { for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid(); ++AI) if (ChangingRegs.test(*AI)) - clobberRegisterUses(RegVars, *AI, DbgValues, MI); + clobberRegisterUses(RegVars, *AI, DbgValues, LiveEntries, MI); } } else if (MO.isRegMask()) { // If this is a register mask operand, clobber all debug values in @@ -234,7 +307,7 @@ void llvm::calculateDbgEntityHistory(const MachineFunction *MF, // Don't consider SP to be clobbered by register masks. if (unsigned(I) != SP && TRI->isPhysicalRegister(I) && MO.clobbersPhysReg(I)) { - clobberRegisterUses(RegVars, I, DbgValues, MI); + clobberRegisterUses(RegVars, I, DbgValues, LiveEntries, MI); } } } @@ -252,13 +325,7 @@ void llvm::calculateDbgEntityHistory(const MachineFunction *MF, "Expected inlined-at fields to agree"); InlinedEntity Var(RawVar, MI.getDebugLoc()->getInlinedAt()); - if (unsigned PrevReg = DbgValues.getRegisterForVar(Var)) - dropRegDescribedVar(RegVars, PrevReg, Var); - - DbgValues.startEntry(Var, MI); - - if (unsigned NewReg = isDescribedByReg(MI)) - addRegDescribedVar(RegVars, NewReg, Var); + handleNewDebugValue(Var, MI, RegVars, LiveEntries, DbgValues); } else if (MI.isDebugLabel()) { assert(MI.getNumOperands() == 1 && "Invalid DBG_LABEL instruction!"); const DILabel *RawLabel = MI.getDebugLabel(); @@ -280,7 +347,8 @@ void llvm::calculateDbgEntityHistory(const MachineFunction *MF, auto CurElem = I++; // CurElem can be erased below. if (TRI->isVirtualRegister(CurElem->first) || ChangingRegs.test(CurElem->first)) - clobberRegisterUses(RegVars, CurElem, DbgValues, MBB.back()); + clobberRegisterUses(RegVars, CurElem, DbgValues, LiveEntries, + MBB.back()); } } } @@ -306,10 +374,20 @@ LLVM_DUMP_METHOD void DbgValueHistoryMap::dump() const { dbgs() << " --\n"; - for (const auto &Entry : Entries) { - dbgs() << " Begin: " << *Entry.getBegin(); - if (Entry.getEnd()) - dbgs() << " End : " << *Entry.getEnd(); + for (const auto &E : enumerate(Entries)) { + const auto &Entry = E.value(); + dbgs() << " Entry[" << E.index() << "]: "; + if (Entry.isDbgValue()) + dbgs() << "Debug value\n"; + else + dbgs() << "Clobber\n"; + dbgs() << " Instr: " << *Entry.getInstr(); + if (Entry.isDbgValue()) { + if (Entry.getEndIndex() == NoEntry) + dbgs() << " - Valid until end of function\n"; + else + dbgs() << " - Closed by Entry[" << Entry.getEndIndex() << "]\n"; + } dbgs() << "\n"; } } diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp index 00e4cea3135..f24dbf148e7 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp @@ -229,31 +229,35 @@ void DebugHandlerBase::beginFunction(const MachineFunction *MF) { // However, we currently do not emit debug values for constant arguments // directly at the start of the function, so this code is still useful. const DILocalVariable *DIVar = - Entries.front().getBegin()->getDebugVariable(); + Entries.front().getInstr()->getDebugVariable(); if (DIVar->isParameter() && getDISubprogram(DIVar->getScope())->describes(&MF->getFunction())) { - if (!IsDescribedByReg(Entries.front().getBegin())) - LabelsBeforeInsn[Entries.front().getBegin()] = Asm->getFunctionBegin(); - if (Entries.front().getBegin()->getDebugExpression()->isFragment()) { + if (!IsDescribedByReg(Entries.front().getInstr())) + LabelsBeforeInsn[Entries.front().getInstr()] = Asm->getFunctionBegin(); + if (Entries.front().getInstr()->getDebugExpression()->isFragment()) { // Mark all non-overlapping initial fragments. for (auto I = Entries.begin(); I != Entries.end(); ++I) { - const DIExpression *Fragment = I->getBegin()->getDebugExpression(); + if (!I->isDbgValue()) + continue; + const DIExpression *Fragment = I->getInstr()->getDebugExpression(); if (std::any_of(Entries.begin(), I, [&](DbgValueHistoryMap::Entry Pred) { - return Fragment->fragmentsOverlap( - Pred.getBegin()->getDebugExpression()); + return Pred.isDbgValue() && + Fragment->fragmentsOverlap( + Pred.getInstr()->getDebugExpression()); })) break; - if (!IsDescribedByReg(I->getBegin())) - LabelsBeforeInsn[I->getBegin()] = Asm->getFunctionBegin(); + if (!IsDescribedByReg(I->getInstr())) + LabelsBeforeInsn[I->getInstr()] = Asm->getFunctionBegin(); } } } for (const auto &Entry : Entries) { - requestLabelBeforeInsn(Entry.getBegin()); - if (Entry.getEnd()) - requestLabelAfterInsn(Entry.getEnd()); + if (Entry.isDbgValue()) + requestLabelBeforeInsn(Entry.getInstr()); + else + requestLabelAfterInsn(Entry.getInstr()); } } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 07232b5082a..c0b0d0c9273 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -1095,67 +1095,92 @@ static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) { } /// Build the location list for all DBG_VALUEs in the function that -/// describe the same variable. If the ranges of several independent -/// fragments of the same variable overlap partially, split them up and -/// combine the ranges. The resulting DebugLocEntries are will have +/// describe the same variable. The resulting DebugLocEntries will have /// strict monotonically increasing begin addresses and will never /// overlap. // +// See the definition of DbgValueHistoryMap::Entry for an explanation of the +// different kinds of history map entries. One thing to be aware of is that if +// a debug value is ended by another entry (rather than being valid until the +// end of the function), that entry's instruction may or may not be included in +// the range, depending on if the entry is a clobbering entry (it has an +// instruction that clobbers one or more preceding locations), or if it is an +// (overlapping) debug value entry. This distinction can be seen in the example +// below. The first debug value is ended by the clobbering entry 2, and the +// second and third debug values are ended by the overlapping debug value entry +// 4. +// // Input: // -// Ranges History [var, loc, fragment ofs size] -// 0 | [x, (reg0, fragment 0, 32)] -// 1 | | [x, (reg1, fragment 32, 32)] <- IsFragmentOfPrevEntry -// 2 | | ... -// 3 | [clobber reg0] -// 4 [x, (mem, fragment 0, 64)] <- overlapping with both previous fragments of -// x. +// History map entries [type, end index, mi] +// +// 0 | [DbgValue, 2, DBG_VALUE $reg0, [...] (fragment 0, 32)] +// 1 | | [DbgValue, 4, DBG_VALUE $reg1, [...] (fragment 32, 32)] +// 2 | | [Clobber, $reg0 = [...], -, -] +// 3 | | [DbgValue, 4, DBG_VALUE 123, [...] (fragment 64, 32)] +// 4 [DbgValue, ~0, DBG_VALUE @g, [...] (fragment 0, 96)] // -// Output: +// Output [start, end) [Value...]: // -// [0-1] [x, (reg0, fragment 0, 32)] -// [1-3] [x, (reg0, fragment 0, 32), (reg1, fragment 32, 32)] -// [3-4] [x, (reg1, fragment 32, 32)] -// [4- ] [x, (mem, fragment 0, 64)] +// [0-1) [(reg0, fragment 0, 32)] +// [1-3) [(reg0, fragment 0, 32), (reg1, fragment 32, 32)] +// [3-4) [(reg1, fragment 32, 32), (123, fragment 64, 32)] +// [4-) [(@g, fragment 0, 96)] void DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc, const DbgValueHistoryMap::Entries &Entries) { - SmallVector<DebugLocEntry::Value, 4> OpenRanges; - - for (auto EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) { - const MachineInstr *Begin = EI->getBegin(); - const MachineInstr *End = EI->getEnd(); - assert(Begin->isDebugValue() && "Invalid History entry"); - - // Check if a variable is inaccessible in this range. - if (Begin->getNumOperands() > 1 && - Begin->getOperand(0).isReg() && !Begin->getOperand(0).getReg()) { - OpenRanges.clear(); - continue; + using OpenRange = + std::pair<DbgValueHistoryMap::EntryIndex, DebugLocEntry::Value>; + SmallVector<OpenRange, 4> OpenRanges; + + for (auto EB = Entries.begin(), EI = EB, EE = Entries.end(); EI != EE; ++EI) { + const MachineInstr *Instr = EI->getInstr(); + + if (EI->isDbgValue()) { + // Check if a variable is inaccessible in this range. + // TODO: This should only truncate open ranges that are overlapping. + if (Instr->getNumOperands() > 1 && + Instr->getOperand(0).isReg() && !Instr->getOperand(0).getReg()) { + OpenRanges.clear(); + continue; + } } - // If this debug value overlaps with any open ranges, truncate them. - const DIExpression *DIExpr = Begin->getDebugExpression(); - auto Last = remove_if(OpenRanges, [&](DebugLocEntry::Value R) { - return DIExpr->fragmentsOverlap(R.getExpression()); - }); + // Remove all values that are no longer live. + size_t Index = std::distance(EB, EI); + auto Last = + remove_if(OpenRanges, [&](OpenRange &R) { return R.first <= Index; }); OpenRanges.erase(Last, OpenRanges.end()); - const MCSymbol *StartLabel = getLabelBeforeInsn(Begin); - assert(StartLabel && "Forgot label before DBG_VALUE starting a range!"); + // If we are dealing with a clobbering entry, this iteration will result in + // a location list entry starting after the clobbering instruction. + const MCSymbol *StartLabel = + EI->isClobber() ? getLabelAfterInsn(Instr) : getLabelBeforeInsn(Instr); + assert(StartLabel && + "Forgot label before/after instruction starting a range!"); const MCSymbol *EndLabel; - if (End != nullptr) - EndLabel = getLabelAfterInsn(End); - else if (std::next(EI) == Entries.end()) + if (std::next(EI) == Entries.end()) EndLabel = Asm->getFunctionEnd(); + else if (std::next(EI)->isClobber()) + EndLabel = getLabelAfterInsn(std::next(EI)->getInstr()); else - EndLabel = getLabelBeforeInsn(std::next(EI)->getBegin()); + EndLabel = getLabelBeforeInsn(std::next(EI)->getInstr()); assert(EndLabel && "Forgot label after instruction ending a range!"); - LLVM_DEBUG(dbgs() << "DotDebugLoc: " << *Begin << "\n"); + if (EI->isDbgValue()) + LLVM_DEBUG(dbgs() << "DotDebugLoc: " << *Instr << "\n"); - auto Value = getDebugLocValue(Begin); - OpenRanges.push_back(Value); + // If this history map entry has a debug value, add that to the list of + // open ranges. + if (EI->isDbgValue()) { + auto Value = getDebugLocValue(Instr); + OpenRanges.emplace_back(EI->getEndIndex(), Value); + } + + // Location list entries with empty location descriptions are redundant + // information in DWARF, so do not emit those. + if (OpenRanges.empty()) + continue; // Omit entries with empty ranges as they do not have any effect in DWARF. if (StartLabel == EndLabel) { @@ -1163,7 +1188,10 @@ void DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc, continue; } - DebugLoc.emplace_back(StartLabel, EndLabel, OpenRanges); + SmallVector<DebugLocEntry::Value, 4> Values; + for (auto &R : OpenRanges) + Values.push_back(R.second); + DebugLoc.emplace_back(StartLabel, EndLabel, Values); // Attempt to coalesce the ranges of two otherwise identical // DebugLocEntries. @@ -1292,15 +1320,23 @@ void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU, DbgVariable *RegVar = cast<DbgVariable>(createConcreteEntity(TheCU, *Scope, LocalVar, IV.second)); - const MachineInstr *MInsn = HistoryMapEntries.front().getBegin(); + const MachineInstr *MInsn = HistoryMapEntries.front().getInstr(); assert(MInsn->isDebugValue() && "History must begin with debug value"); // Check if there is a single DBG_VALUE, valid throughout the var's scope. - if (HistoryMapEntries.size() == 1 && - validThroughout(LScopes, MInsn, HistoryMapEntries.front().getEnd())) { - RegVar->initializeDbgValue(MInsn); - continue; + // If the history map contains a single debug value, there may be an + // additional entry which clobbers the debug value. + bool SingleValueWithClobber = + HistoryMapEntries.size() == 2 && HistoryMapEntries[1].isClobber(); + if (HistoryMapEntries.size() == 1 || SingleValueWithClobber) { + const auto *End = + SingleValueWithClobber ? HistoryMapEntries[1].getInstr() : nullptr; + if (validThroughout(LScopes, MInsn, End)) { + RegVar->initializeDbgValue(MInsn); + continue; + } } + // Do not emit location lists if .debug_loc secton is disabled. if (!useLocSection()) continue; |