[llvm-branch-commits] [llvm] 7f7c7cd - Revert "[llvm-dwarfdump][LineCov 3/3] Add IR analysis for variable coverage (…"
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Jul 6 03:59:54 PDT 2026
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
More information about the llvm-branch-commits
mailing list