Index: lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h =================================================================== --- lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h +++ lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h @@ -12,6 +12,7 @@ #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" +#include namespace llvm { @@ -28,16 +29,26 @@ // range. If end is not specified, location is valid until the start // instruction of the next instruction range, or until the end of the // function. + // We must avoid generating empty ranges. An empty range conveys no + // information, and even worse, an empty range with start/end addresses + // 0 (the addresses are function relative) will be interpreted as the + // end of location list marker (Making the location list appear as empty). public: typedef std::pair InstrRange; typedef SmallVector InstrRanges; typedef MapVector InstrRangesMap; private: InstrRangesMap VarInstrRanges; - + InstrRangesMap EmptyRanges; public: + DbgValueHistoryMap() {} + void startInstrRange(const MDNode *Var, const MachineInstr &MI); void endInstrRange(const MDNode *Var, const MachineInstr &MI); + void markOpenRangesNonEmpty(); + void dropEmptyRanges(); + void tryToPromoteEmptyRange(const MDNode *Var); + // Returns register currently describing @Var. If @Var is currently // unaccessible or is not described by a register, returns 0. unsigned getRegisterForVar(const MDNode *Var) const; Index: lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp +++ lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp @@ -44,24 +44,57 @@ << "\t" << Ranges.back().first << "\t" << MI << "\n"); return; } - Ranges.push_back(std::make_pair(&MI, nullptr)); + EmptyRanges[Var].push_back(std::make_pair(&MI, nullptr)); } void DbgValueHistoryMap::endInstrRange(const MDNode *Var, const MachineInstr &MI) { + if (!EmptyRanges[Var].empty()) + return EmptyRanges[Var].pop_back(); + auto &Ranges = VarInstrRanges[Var]; // Verify that the current instruction range is not yet closed. assert(!Ranges.empty() && Ranges.back().second == nullptr); // For now, instruction ranges are not allowed to cross basic block // boundaries. assert(Ranges.back().first->getParent() == MI.getParent()); + Ranges.back().second = &MI; } +void DbgValueHistoryMap::markOpenRangesNonEmpty() { + if (EmptyRanges.empty()) + return; + + for (auto &Ranges : make_range(EmptyRanges.begin(), EmptyRanges.end())) + for (auto &Range : Ranges.second) + VarInstrRanges[Ranges.first].push_back(Range); + + EmptyRanges.clear(); +} + +void DbgValueHistoryMap::dropEmptyRanges() { EmptyRanges.clear(); } + +void DbgValueHistoryMap::tryToPromoteEmptyRange(const MDNode *Var) { + if (EmptyRanges.empty()) + return; + + auto I = EmptyRanges.find(Var); + if (I == EmptyRanges.end()) + return; + + VarInstrRanges[Var].push_back(I->second.back()); + I->second.pop_back(); + EmptyRanges.clear(); +} + unsigned DbgValueHistoryMap::getRegisterForVar(const MDNode *Var) const { - const auto &I = VarInstrRanges.find(Var); - if (I == VarInstrRanges.end()) - return 0; + auto I = EmptyRanges.find(Var); + if (I == EmptyRanges.end()) { + I = VarInstrRanges.find(Var); + if (I == VarInstrRanges.end()) + return 0; + } const auto &Ranges = I->second; if (Ranges.empty() || Ranges.back().second != nullptr) return 0; @@ -195,6 +228,9 @@ if (ChangingRegs.test(RegNo)) clobberRegisterUses(RegVars, RegNo, Result, MI); }); + + if (!MI.isTransient()) + Result.markOpenRangesNonEmpty(); continue; } @@ -221,7 +257,15 @@ auto CurElem = I++; // CurElem can be erased below. if (ChangingRegs.test(CurElem->first)) clobberRegisterUses(RegVars, CurElem, Result, MBB.back()); + else + // If a variable uses a register that isn't clobbered + // anywhere in the function, its range will be extended. The + // range needs to survive this pass though. + for (const auto *Var : CurElem->second) + Result.tryToPromoteEmptyRange(Var); } } + + Result.dropEmptyRanges(); } } Index: test/DebugInfo/X86/dbg-value-inlined-parameter.ll =================================================================== --- test/DebugInfo/X86/dbg-value-inlined-parameter.ll +++ test/DebugInfo/X86/dbg-value-inlined-parameter.ll @@ -31,11 +31,9 @@ ;CHECK-NEXT: DW_AT_call_file ;CHECK-NEXT: DW_AT_call_line +;FIXME: We shouldn't drop the sp parameter. ;CHECK: DW_TAG_formal_parameter -;FIXME: Linux shouldn't drop this parameter either... ;CHECK-NOT: DW_TAG -;DARWIN: DW_AT_abstract_origin {{.*}} "sp" -;DARWIN: DW_TAG_formal_parameter ;CHECK: DW_AT_abstract_origin {{.*}} "nums" ;CHECK-NOT: DW_TAG_formal_parameter