Author: Stephen Tozer Date: 2026-07-06T11:59:49+01:00 New Revision: 7f7c7cd7764b13af6858679c3dbcf0df4f0979b4
URL: https://github.com/llvm/llvm-project/commit/7f7c7cd7764b13af6858679c3dbcf0df4f0979b4 DIFF: https://github.com/llvm/llvm-project/commit/7f7c7cd7764b13af6858679c3dbcf0df4f0979b4.diff LOG: Revert "[llvm-dwarfdump][LineCov 3/3] Add IR analysis for variable coverage (…" This reverts commit 5f4940efe9c121fb84ada13be9001f24cbef4a4c. Added: Modified: llvm/docs/CommandGuide/llvm-dwarfdump.rst llvm/test/tools/llvm-dwarfdump/X86/coverage.test llvm/tools/llvm-dwarfdump/Coverage.cpp llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp llvm/tools/llvm-dwarfdump/llvm-dwarfdump.h Removed: ################################################################################ diff --git a/llvm/docs/CommandGuide/llvm-dwarfdump.rst b/llvm/docs/CommandGuide/llvm-dwarfdump.rst index 22f2edfc30f57..03d3623259610 100644 --- a/llvm/docs/CommandGuide/llvm-dwarfdump.rst +++ b/llvm/docs/CommandGuide/llvm-dwarfdump.rst @@ -203,12 +203,6 @@ OPTIONS File to use as the baseline for variable coverage statistics (implies :option:`--show-variable-coverage`) -.. option:: --variable-coverage-bitcode-file - - File containing LLVM IR (bitcode or textual) used for calculating - variable definedness in coverage statistics (implies - :option:`--show-variable-coverage`) - .. option:: --combine-inline-variable-instances Use with :option:`--show-variable-coverage` to average variable diff --git a/llvm/test/tools/llvm-dwarfdump/X86/coverage.test b/llvm/test/tools/llvm-dwarfdump/X86/coverage.test index 5539ef93c9999..647f277ae64e5 100644 --- a/llvm/test/tools/llvm-dwarfdump/X86/coverage.test +++ b/llvm/test/tools/llvm-dwarfdump/X86/coverage.test @@ -36,27 +36,3 @@ BASELINE-NEXT: fn1 u test.c:4 1 14 0.0714 7 0.5 BASELINE-NEXT: fn1 v test.c:13 0 14 0 7 0.5 BASELINE-NEXT: fn1 x test.c:3 7 14 0.5 7 0.5 BASELINE-NEXT: fn1 y test.c:3 7 14 0.5 7 0.5 - -RUN: llvm-dwarfdump --show-variable-coverage --variable-coverage-bitcode-file=%S/Inputs/coverage.ll %t.o | FileCheck %s --check-prefix=BITCODE - -BITCODE: Variable coverage statistics: -BITCODE-NEXT: Function InlChain Variable Decl LinesCovered -BITCODE-NEXT: f k test.c:20 2 -BITCODE-NEXT: f l test.c:20 3 -BITCODE-NEXT: fn1 a test.c:11 6 -BITCODE-NEXT: fn1 u test.c:4 12 -BITCODE-NEXT: fn1 v test.c:13 4 -BITCODE-NEXT: fn1 x test.c:3 13 -BITCODE-NEXT: fn1 y test.c:3 13 - -RUN: llvm-dwarfdump --show-variable-coverage --variable-coverage-bitcode-file=%S/Inputs/coverage.ll --coverage-baseline %t.o %t-opt.o | FileCheck %s --check-prefix=BASELINE-BITCODE - -BASELINE-BITCODE: Variable coverage statistics: -BASELINE-BITCODE-NEXT: Function InlChain Variable Decl LinesCovered Baseline CoveredRatio LinesPresent LinesPresentRatio -BASELINE-BITCODE-NEXT: f k test.c:20 2 2 1 2 1 -BASELINE-BITCODE-NEXT: f l test.c:20 3 3 1 3 1 -BASELINE-BITCODE-NEXT: fn1 a test.c:11 3 6 0.5 3 0.5 -BASELINE-BITCODE-NEXT: fn1 u test.c:4 1 12 0.0833 5 0.417 -BASELINE-BITCODE-NEXT: fn1 v test.c:13 0 4 0 2 0.5 -BASELINE-BITCODE-NEXT: fn1 x test.c:3 6 13 0.462 6 0.462 -BASELINE-BITCODE-NEXT: fn1 y test.c:3 6 13 0.462 6 0.462 diff --git a/llvm/tools/llvm-dwarfdump/Coverage.cpp b/llvm/tools/llvm-dwarfdump/Coverage.cpp index 8c525296a8c82..35ea9bc0a1deb 100644 --- a/llvm/tools/llvm-dwarfdump/Coverage.cpp +++ b/llvm/tools/llvm-dwarfdump/Coverage.cpp @@ -14,7 +14,6 @@ #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/IR/CFG.h" -#include "llvm/IR/DebugInfo.h" #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DebugProgramInstruction.h" #include "llvm/IR/Instructions.h" @@ -30,13 +29,6 @@ using namespace llvm::object; /// Pair of file index and line number representing a source location. typedef std::pair<uint16_t, size_t> SourceLocation; -/// Pair of subroutine name and variable name representing a local variable. -typedef std::pair<std::string, std::string> BitcodeVarKey; -/// Pair of file name and line number representing a source location. -typedef std::pair<StringRef, uint32_t> BitcodeSourceLocation; -/// Maps local variables found in the bitcode to a set of source locations. -typedef std::map<BitcodeVarKey, std::optional<DenseSet<BitcodeSourceLocation>>> - BitcodeLineMap; /// Adds source locations to the line set that correspond to an address range. static void addLines(const DWARFDebugLine::LineTable *LineTable, @@ -56,14 +48,14 @@ static void addLines(const DWARFDebugLine::LineTable *LineTable, } } -/// Converts the file index of each line in the set to use our own internal -/// file index. This is required for a reliable comparison as the DWARF index -/// may diff er across compilations. +// Converts the file index of each line in the set to use our own internal +// file index. This is required for a reliable comparison as the DWARF index may +// diff er across compilations. static DenseSet<SourceLocation> convertFileIndices(DenseSet<SourceLocation> Lines, const DWARFDebugLine::LineTable *const LineTable, DenseMap<uint16_t, uint16_t> &FileIndexMap, - StringMap<std::optional<uint16_t>> &FileNameMap) { + StringMap<uint16_t> &FileNameMap) { DenseSet<SourceLocation> ResultLines; for (const auto &L : Lines) { uint16_t Index; @@ -78,8 +70,8 @@ convertFileIndices(DenseSet<SourceLocation> Lines, assert(ValidIndex && "File index was not valid for its own line table"); auto NameIt = FileNameMap.find(Name); - if (NameIt != FileNameMap.end() && NameIt->second) { - Index = *NameIt->second; + if (NameIt != FileNameMap.end()) { + Index = NameIt->second; } else { Index = FileNameMap.size(); FileNameMap.insert({Name, Index}); @@ -101,8 +93,7 @@ static DenseSet<SourceLocation> computeVariableCoverage(DWARFDie VariableDIE, const DWARFDebugLine::LineTable *const LineTable, DenseMap<uint16_t, uint16_t> &FileIndexMap, - StringMap<std::optional<uint16_t>> &FileNameMap, - BitcodeLineMap::value_type *DefinedLines) { + StringMap<uint16_t> &FileNameMap) { // The optionals below will be empty if no address ranges were found, and // present (but containing an empty set) if ranges were found but contained no // source locations, in order to distinguish the two cases. @@ -141,46 +132,11 @@ computeVariableCoverage(DWARFDie VariableDIE, else if (ParentLines) set_intersect(*Lines, *ParentLines); - auto ResultLines = - convertFileIndices(Lines.value_or(DenseSet<SourceLocation>()), LineTable, - FileIndexMap, FileNameMap); - - if (DefinedLines) { - // Remove any lines where the variable does not have a defined value. - auto &DL = DefinedLines->second; - if (DL) { - DenseSet<SourceLocation> IndexLines; - for (const auto &L : *DL) { - auto NameIt = FileNameMap.find(L.first); - if (NameIt != FileNameMap.end()) { - if (NameIt->second) - IndexLines.insert({*NameIt->second, L.second}); - } else { - // LineTable::getFileNameByIndex can return absolute paths even when - // relative paths are requested, so search for keys that end with this - // path as well. - for (const auto &NameEntry : FileNameMap) { - auto Name = NameEntry.first(); - if (Name.find(L.first, Name.size() - L.first.size()) != - std::string_view::npos) { - FileNameMap.insert({L.first, NameEntry.second}); - IndexLines.insert({*NameEntry.second, L.second}); - } - } - if (FileNameMap.find(L.first) == FileNameMap.end()) { - assert(0 && "Files found in bitcode but not in DWARF"); - FileNameMap.insert({L.first, std::nullopt}); - } - } - } - if (!Lines) - assert(0 && "Source lines found in bitcode but not in DWARF"); - else - set_intersect(ResultLines, IndexLines); - } - } + if (!Lines) + return {}; - return ResultLines; + return convertFileIndices(Lines.value_or(DenseSet<SourceLocation>()), + LineTable, FileIndexMap, FileNameMap); } /// Adds source locations to the line set that are within an inlined subroutine. @@ -207,7 +163,7 @@ static DenseSet<SourceLocation> computeSubroutineCoverage(DWARFDie SubroutineDIE, const DWARFDebugLine::LineTable *const LineTable, DenseMap<uint16_t, uint16_t> &FileIndexMap, - StringMap<std::optional<uint16_t>> &FileNameMap) { + StringMap<uint16_t> &FileNameMap) { auto Ranges = SubroutineDIE.getAddressRanges(); DenseSet<SourceLocation> Lines; if (Ranges) { @@ -239,147 +195,6 @@ static const SmallVector<DWARFDie> getParentSubroutines(DWARFDie DIE) { return Parents; } -static bool isInScope(MDNode *Scope, const DebugLoc &Loc) { - MDNode *Parent = Loc.getScope(); - while (Parent != Scope) { - auto *S = dyn_cast_if_present<DIScope>(Parent); - if (!S) - return false; - Parent = S->getScope(); - } - return true; -} - -/// Determines whether an instruction stores to a location. For the purposes of -/// this analysis, we consider any call-like instruction with the location as an -/// argument to be a store to it. -static bool isStoreToLocation(const DataLayout &DL, Instruction &I, - Value *Loc) { - std::optional<at::AssignmentInfo> Info; - if (StoreInst *SI = dyn_cast<StoreInst>(&I)) { - if (SI->getPointerOperand() == Loc) - return true; - Info = at::getAssignmentInfo(DL, SI); - } else if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(&I)) { - if (MI->getDest() == Loc) - return true; - Info = at::getAssignmentInfo(DL, MI); - } else if (CallBase *CI = dyn_cast<CallBase>(&I)) { - return CI->hasArgument(Loc); - } - return Info && Info->Base == Loc; -} - -typedef SmallDenseMap<BasicBlock *, Instruction *, 8> VarDefinitionMap; - -struct VarState { - DbgVariableRecord &DVR; - VarDefinitionMap Definitions; -}; - -/// Adds source locations to the line set for instructions in a basic block, -/// starting with a specific instruction. -static void addModuleLines(Instruction *I, VarState &Var, - DenseSet<std::pair<StringRef, uint32_t>> &Lines) { - auto *VarScope = Var.DVR.getVariable()->getScope(); - do { - auto &Loc = I->getDebugLoc(); - DIScope *Scope; - if (Loc && isInScope(VarScope, Loc) && Loc.getLine() && - (Scope = dyn_cast_if_present<DIScope>(Loc.getScope()))) { - Lines.insert({Scope->getFilename(), Loc.getLine()}); - } - } while ((I = I->getNextNode())); -} - -/// Computes the defined lines of all variables in an IR module. -static BitcodeLineMap processModule(Module *Mod) { - BitcodeLineMap Result; - std::vector<VarState> Vars; - for (auto &F : Mod->functions()) { - Vars.clear(); - for (auto &BB : F) { - for (auto &I : BB) { - for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) { - if (DVR.isKillLocation()) { - assert(0 && "Variable in bitcode has been optimized out"); - continue; - } - if (DVR.isDbgDeclare()) { - // For #dbg_declare, don't treat the variable as live until we find - // a store to it. - Vars.push_back(VarState{DVR, VarDefinitionMap()}); - } else if (DVR.isDbgValue()) { - // For #dbg_value, the variable is live immediately from this point. - if (DVR.getDebugLoc().getInlinedAt() != nullptr) { - assert(0 && "Variable in bitcode has been inlined"); - continue; - } - auto Var = find_if(Vars, [&](auto &Var) { - return Var.DVR.getVariable() == DVR.getVariable(); - }); - if (Var != Vars.end()) - // If a basic block contains multiple stores to a variable, use - // the earliest one by allowing the insertion to silently fail if - // the basic block is already in the map. - Var->Definitions.insert({&BB, &I}); - else - Vars.push_back(VarState{DVR, {{&BB, &I}}}); - } - } - } - } - - for (auto &BB : F) { - for (auto &I : BB) { - for (auto &Var : Vars) { - if (isStoreToLocation(Mod->getDataLayout(), I, Var.DVR.getValue())) { - // The variable is live from the instruction after the store. As - // above, the earliest store in this basic block will be used. - Var.Definitions.insert({&BB, I.getNextNode()}); - } - } - } - } - - for (auto &Var : Vars) { - SmallPtrSet<BasicBlock *, 8> Visited; - DenseSet<std::pair<StringRef, uint32_t>> Lines; - - // Visit all basic blocks that are reachable from the entry block without - // going through a block that stores to the variable. - SmallVector<BasicBlock *> BlocksToVisit{&F.getEntryBlock()}; - while (!BlocksToVisit.empty()) { - BasicBlock *BB = BlocksToVisit.pop_back_val(); - if (!Visited.insert(BB).second) - continue; - - auto I = Var.Definitions.find(BB); - if (I != Var.Definitions.end()) { - // Block contains a definition: add all lines after it to the set - if (I->second != nullptr) - addModuleLines(I->second, Var, Lines); - } else { - // Block does not contain a definition: visit its successors - auto S = successors(BB); - BlocksToVisit.append(S.begin(), S.end()); - } - } - - // All unvisited basic blocks must only be reachable by going through a - // block that stores to the variable, so add lines to the set for all of - // their instructions. - for (auto &BB : F) - if (!Visited.count(&BB)) - addModuleLines(&*BB.begin(), Var, Lines); - - BitcodeVarKey Key(F.getName(), Var.DVR.getVariable()->getName()); - Result.emplace(Key, Lines); - } - } - return Result; -} - struct VarKey { const char *const SubprogramName; const char *const Name; @@ -480,21 +295,9 @@ static void displayVariableCoverage(const VarKey &Key, const VarCoverage &Var, bool dwarfdump::showVariableCoverage(ObjectFile &Obj, DWARFContext &DICtx, ObjectFile *BaselineObj, DWARFContext *BaselineCtx, - StringRef BitcodeFile, bool CombineInstances, raw_ostream &OS) { - BitcodeLineMap LM; - LLVMContext Context; - if (!BitcodeFile.empty()) { - SMDiagnostic Err; - std::unique_ptr<Module> Mod = parseIRFile(BitcodeFile, Err, Context); - if (!Err.getMessage().empty()) - Err.print("llvm-dwarfdump", OS); - else - LM = processModule(Mod.get()); - } - BaselineVarMap BaselineVars; - StringMap<std::optional<uint16_t>> FileNameMap; + StringMap<uint16_t> FileNameMap; if (BaselineCtx) { for (const auto &U : BaselineCtx->info_section_units()) { @@ -514,10 +317,8 @@ bool dwarfdump::showVariableCoverage(ObjectFile &Obj, DWARFContext &DICtx, if (!Key) continue; - const auto DefinedLines = LM.find({Key->SubprogramName, Key->Name}); - auto Cov = computeVariableCoverage( - VariableDIE, LT, FileIndexMap, FileNameMap, - DefinedLines != LM.end() ? &*DefinedLines : nullptr); + auto Cov = + computeVariableCoverage(VariableDIE, LT, FileIndexMap, FileNameMap); const auto SubroutineCov = computeSubroutineCoverage( SubroutineDIE, LT, FileIndexMap, FileNameMap); set_intersect(Cov, SubroutineCov); @@ -548,10 +349,8 @@ bool dwarfdump::showVariableCoverage(ObjectFile &Obj, DWARFContext &DICtx, if (!Key) continue; - const auto DefinedLines = LM.find({Key->SubprogramName, Key->Name}); - auto Cov = computeVariableCoverage( - VariableDIE, LT, FileIndexMap, FileNameMap, - DefinedLines != LM.end() ? &*DefinedLines : nullptr); + auto Cov = + computeVariableCoverage(VariableDIE, LT, FileIndexMap, FileNameMap); const auto SubroutineCov = computeSubroutineCoverage( SubroutineDIE, LT, FileIndexMap, FileNameMap); set_intersect(Cov, SubroutineCov); diff --git a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp index 4d7fc7e3108bf..a97a154e28080 100644 --- a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -343,12 +343,6 @@ static opt<std::string> desc("File to use as the baseline for variable coverage " "statistics (implies --show-variable-coverage)"), value_desc("filename"), cat(DwarfDumpCategory)); -static opt<std::string> - BitcodeFile("variable-coverage-bitcode-file", - desc("File containing LLVM IR (bitcode or textual) used for " - "calculating variable definedness in coverage statistics " - "(implies --show-variable-coverage)"), - value_desc("filename"), cat(DwarfDumpCategory)); static opt<bool> CombineInstances( "combine-inline-variable-instances", desc( @@ -927,7 +921,7 @@ int main(int argc, char **argv) { if (DumpAll) DumpType = DIDT_All; if (DumpType == DIDT_Null && !ShowVariableCoverage && - CoverageBaseline.empty() && BitcodeFile.empty()) { + CoverageBaseline.empty()) { if (Verbose || Verify) DumpType = DIDT_All; else @@ -986,17 +980,17 @@ int main(int argc, char **argv) { auto showCoverage = [&](ObjectFile &Obj, DWARFContext &DICtx, const Twine &Filename, raw_ostream &OS) { return showVariableCoverage(Obj, DICtx, &BaselineObj, &BaselineCtx, - BitcodeFile, CombineInstances, OS); + CombineInstances, OS); }; for (StringRef Object : Objects) Success &= handleFile(Object, showCoverage, OutputFile.os()); return true; }; Success &= handleFile(CoverageBaseline, handleBaseline, OutputFile.os()); - } else if (ShowVariableCoverage || !BitcodeFile.empty()) { + } else if (ShowVariableCoverage) { auto showCoverage = [&](ObjectFile &Obj, DWARFContext &DICtx, const Twine &Filename, raw_ostream &OS) { - return showVariableCoverage(Obj, DICtx, nullptr, nullptr, BitcodeFile, + return showVariableCoverage(Obj, DICtx, nullptr, nullptr, CombineInstances, OS); }; for (StringRef Object : Objects) diff --git a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.h b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.h index e9d0433cc3f49..90a49e8f75ffc 100644 --- a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.h +++ b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.h @@ -41,8 +41,8 @@ bool collectObjectSectionSizes(object::ObjectFile &Obj, DWARFContext &DICtx, bool showVariableCoverage(object::ObjectFile &Obj, DWARFContext &DICtx, object::ObjectFile *BaselineObj, - DWARFContext *BaselineCtx, StringRef BitcodeFile, - bool CombineInstances, raw_ostream &OS); + DWARFContext *BaselineCtx, bool CombineInstances, + raw_ostream &OS); } // namespace dwarfdump } // namespace llvm _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
