[llvm] [llvm-dwarfdump][LineCov 3/3] Add IR analysis for variable coverage (PR #195342)

Stephen Tozer via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 3 07:16:54 PDT 2026


================
@@ -195,6 +221,143 @@ 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("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("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()});
----------------
SLTozer wrote:

Each of the `for`s and the `if` will need braces.

https://github.com/llvm/llvm-project/pull/195342


More information about the llvm-commits mailing list