Skip to content

Revert "[MC/DC] Make covmap tolerant of nested Decisions (#125407)"#181069

Merged
gulfemsavrun merged 1 commit into
llvm:mainfrom
gulfemsavrun:revert-coverage-change
Feb 12, 2026
Merged

Revert "[MC/DC] Make covmap tolerant of nested Decisions (#125407)"#181069
gulfemsavrun merged 1 commit into
llvm:mainfrom
gulfemsavrun:revert-coverage-change

Conversation

@gulfemsavrun
Copy link
Copy Markdown
Contributor

@gulfemsavrun gulfemsavrun commented Feb 12, 2026

This reverts commit 8f690ec because it caused errors in collecting coverage.

@llvmbot llvmbot added the PGO Profile Guided Optimizations label Feb 12, 2026
@llvmbot llvmbot temporarily deployed to main-branch-only February 12, 2026 01:48 — with GitHub Actions Inactive
@llvmbot
Copy link
Copy Markdown
Member

llvmbot commented Feb 12, 2026

@llvm/pr-subscribers-pgo

Author: None (gulfemsavrun)

Changes

This reverts commit 8f690ec.


Full diff: https://github.com/llvm/llvm-project/pull/181069.diff

2 Files Affected:

  • (modified) llvm/lib/ProfileData/Coverage/CoverageMapping.cpp (+168-135)
  • (modified) llvm/test/tools/llvm-cov/mcdc-macro.test (+7-7)
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index b63f105e93513..40bbb9b194520 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -685,166 +685,154 @@ static unsigned getMaxBitmapSize(const CoverageMappingRecord &Record,
 
 namespace {
 
-/// Walk MappingRegions along Expansions and emit CountedRegions.
-struct CountedRegionEmitter {
-  /// A nestable Decision.
+/// Collect Decisions, Branchs, and Expansions and associate them.
+class MCDCDecisionRecorder {
+private:
+  /// This holds the DecisionRegion and MCDCBranches under it.
+  /// Also traverses Expansion(s).
+  /// The Decision has the number of MCDCBranches and will complete
+  /// when it is filled with unique ConditionID of MCDCBranches.
   struct DecisionRecord {
     const CounterMappingRegion *DecisionRegion;
-    unsigned NumConditions; ///< Copy of DecisionRegion.NumConditions
-    /// Pushed by traversal order.
+
+    /// They are reflected from DecisionRegion for convenience.
+    mcdc::DecisionParameters DecisionParams;
+    LineColPair DecisionStartLoc;
+    LineColPair DecisionEndLoc;
+
+    /// This is passed to `MCDCRecordProcessor`, so this should be compatible
+    /// to`ArrayRef<const CounterMappingRegion *>`.
     SmallVector<const CounterMappingRegion *> MCDCBranches;
-#ifndef NDEBUG
+
+    /// IDs that are stored in MCDCBranches
+    /// Complete when all IDs (1 to NumConditions) are met.
     DenseSet<mcdc::ConditionID> ConditionIDs;
-#endif
+
+    /// Set of IDs of Expansion(s) that are relevant to DecisionRegion
+    /// and its children (via expansions).
+    /// FileID  pointed by ExpandedFileID is dedicated to the expansion, so
+    /// the location in the expansion doesn't matter.
+    DenseSet<unsigned> ExpandedFileIDs;
 
     DecisionRecord(const CounterMappingRegion &Decision)
         : DecisionRegion(&Decision),
-          NumConditions(Decision.getDecisionParams().NumConditions) {
+          DecisionParams(Decision.getDecisionParams()),
+          DecisionStartLoc(Decision.startLoc()),
+          DecisionEndLoc(Decision.endLoc()) {
       assert(Decision.Kind == CounterMappingRegion::MCDCDecisionRegion);
     }
 
-    bool pushBranch(const CounterMappingRegion &B) {
-      assert(B.Kind == CounterMappingRegion::MCDCBranchRegion);
-      assert(ConditionIDs.insert(B.getBranchParams().ID).second &&
-             "Duplicate CondID");
-      MCDCBranches.push_back(&B);
-      assert(MCDCBranches.size() <= NumConditions &&
-             "MCDCBranch exceeds NumConds");
-      return (MCDCBranches.size() == NumConditions);
+    /// Determine whether DecisionRecord dominates `R`.
+    bool dominates(const CounterMappingRegion &R) const {
+      // Determine whether `R` is included in `DecisionRegion`.
+      if (R.FileID == DecisionRegion->FileID &&
+          R.startLoc() >= DecisionStartLoc && R.endLoc() <= DecisionEndLoc)
+        return true;
+
+      // Determine whether `R` is pointed by any of Expansions.
+      return ExpandedFileIDs.contains(R.FileID);
     }
-  };
 
-  const CoverageMappingRecord &Record;
-  CounterMappingContext &Ctx;
-  FunctionRecord &Function;
-  bool IsVersion11;
+    enum Result {
+      NotProcessed = 0, /// Irrelevant to this Decision
+      Processed,        /// Added to this Decision
+      Completed,        /// Added and filled this Decision
+    };
 
-  /// Evaluated Counters.
-  std::map<Counter, uint64_t> CounterValues;
+    /// Add Branch into the Decision
+    /// \param Branch expects MCDCBranchRegion
+    /// \returns NotProcessed/Processed/Completed
+    Result addBranch(const CounterMappingRegion &Branch) {
+      assert(Branch.Kind == CounterMappingRegion::MCDCBranchRegion);
 
-  /// Decisions are nestable.
-  SmallVector<DecisionRecord, 1> DecisionStack;
+      auto ConditionID = Branch.getBranchParams().ID;
 
-  /// A File pointed by Expansion
-  struct FileInfo {
-    /// The last index(+1) for each FileID in MappingRegions.
-    unsigned LastIndex = 0;
-    /// Mark Files pointed by Expansions.
-    /// Non-marked Files are root Files.
-    bool IsExpanded = false;
-  };
+      if (ConditionIDs.contains(ConditionID) ||
+          ConditionID >= DecisionParams.NumConditions)
+        return NotProcessed;
 
-  /// The last element is a sentinel with Index=NumRegions.
-  std::vector<FileInfo> Files;
-#ifndef NDEBUG
-  DenseSet<unsigned> Visited;
-#endif
+      if (!this->dominates(Branch))
+        return NotProcessed;
 
-  CountedRegionEmitter(const CoverageMappingRecord &Record,
-                       CounterMappingContext &Ctx, FunctionRecord &Function,
-                       bool IsVersion11)
-      : Record(Record), Ctx(Ctx), Function(Function), IsVersion11(IsVersion11),
-        Files(Record.Filenames.size()) {
-    // Scan MappingRegions and mark each last index by FileID.
-    for (auto [I, Region] : enumerate(Record.MappingRegions)) {
-      if (Region.FileID >= Files.size()) {
-        // Extend (only possible in CoverageMappingTests)
-        Files.resize(Region.FileID + 1);
-      }
-      Files[Region.FileID].LastIndex = I + 1;
-      if (Region.Kind == CounterMappingRegion::ExpansionRegion) {
-        if (Region.ExpandedFileID >= Files.size()) {
-          // Extend (only possible in CoverageMappingTests)
-          Files.resize(Region.ExpandedFileID + 1);
-        }
-        Files[Region.ExpandedFileID].IsExpanded = true;
-      }
-    }
-  }
+      assert(MCDCBranches.size() < DecisionParams.NumConditions);
 
-  /// Evaluate C and store its evaluated Value into CounterValues.
-  Error evaluateAndCacheCounter(Counter C) {
-    if (CounterValues.count(C) > 0)
-      return Error::success();
+      // Put `ID=0` in front of `MCDCBranches` for convenience
+      // even if `MCDCBranches` is not topological.
+      if (ConditionID == 0)
+        MCDCBranches.insert(MCDCBranches.begin(), &Branch);
+      else
+        MCDCBranches.push_back(&Branch);
 
-    auto ValueOrErr = Ctx.evaluate(C);
-    if (!ValueOrErr)
-      return ValueOrErr.takeError();
-    CounterValues[C] = *ValueOrErr;
-    return Error::success();
-  }
+      // Mark `ID` as `assigned`.
+      ConditionIDs.insert(ConditionID);
 
-  Error walk(unsigned Idx) {
-    assert(Idx < Files.size());
-    unsigned B = (Idx == 0 ? 0 : Files[Idx - 1].LastIndex);
-    unsigned E = Files[Idx].LastIndex;
-    assert(B != E && "Empty FileID");
-    assert(Visited.insert(Idx).second && "Duplicate Expansions");
-    for (unsigned I = B; I != E; ++I) {
-      const auto &Region = Record.MappingRegions[I];
-      if (Region.FileID != Idx)
-        break;
+      // `Completed` when `MCDCBranches` is full
+      return (MCDCBranches.size() == DecisionParams.NumConditions ? Completed
+                                                                  : Processed);
+    }
 
-      if (Region.Kind == CounterMappingRegion::ExpansionRegion)
-        if (auto E = walk(Region.ExpandedFileID))
-          return E;
+    /// Record Expansion if it is relevant to this Decision.
+    /// Each `Expansion` may nest.
+    /// \returns true if recorded.
+    bool recordExpansion(const CounterMappingRegion &Expansion) {
+      if (!this->dominates(Expansion))
+        return false;
 
-      if (auto E = evaluateAndCacheCounter(Region.Count))
-        return E;
+      ExpandedFileIDs.insert(Expansion.ExpandedFileID);
+      return true;
+    }
+  };
 
-      if (Region.Kind == CounterMappingRegion::MCDCDecisionRegion) {
-        // Start the new Decision on the stack.
-        DecisionStack.emplace_back(Region);
-      } else if (Region.Kind == CounterMappingRegion::MCDCBranchRegion) {
-        assert(!DecisionStack.empty() && "Orphan MCDCBranch");
-        auto &D = DecisionStack.back();
-
-        if (D.pushBranch(Region)) {
-          // All Branches have been found in the Decision.
-          auto RecordOrErr = Ctx.evaluateMCDCRegion(
-              *D.DecisionRegion, D.MCDCBranches, IsVersion11);
-          if (!RecordOrErr)
-            return RecordOrErr.takeError();
-
-          // Finish the stack.
-          Function.pushMCDCRecord(std::move(*RecordOrErr));
-          DecisionStack.pop_back();
-        }
-      }
+private:
+  /// Decisions in progress
+  /// DecisionRecord is added for each MCDCDecisionRegion.
+  /// DecisionRecord is removed when Decision is completed.
+  SmallVector<DecisionRecord> Decisions;
 
-      // Evaluate FalseCount
-      // It may have the Counter in Branches, or Zero.
-      if (auto E = evaluateAndCacheCounter(Region.FalseCount))
-        return E;
-    }
+public:
+  ~MCDCDecisionRecorder() {
+    assert(Decisions.empty() && "All Decisions have not been resolved");
+  }
 
-    assert((Idx != 0 || DecisionStack.empty()) && "Decision wasn't closed");
+  /// Register Region and start recording.
+  void registerDecision(const CounterMappingRegion &Decision) {
+    Decisions.emplace_back(Decision);
+  }
 
-    return Error::success();
+  void recordExpansion(const CounterMappingRegion &Expansion) {
+    any_of(Decisions, [&Expansion](auto &Decision) {
+      return Decision.recordExpansion(Expansion);
+    });
   }
 
-  Error emitCountedRegions() {
-    // Walk MappingRegions along Expansions.
-    // - Evaluate Counters
-    // - Emit MCDCRecords
-    for (auto [I, F] : enumerate(Files)) {
-      if (!F.IsExpanded)
-        if (auto E = walk(I))
-          return E;
-    }
-    assert(Visited.size() == Files.size() && "Dangling FileID");
-
-    // Emit CountedRegions in the same order as MappingRegions.
-    for (const auto &Region : Record.MappingRegions) {
-      if (Region.Kind == CounterMappingRegion::MCDCDecisionRegion)
-        continue; // Don't emit.
-      // Adopt values from the CounterValues.
-      // FalseCount may be Zero unless Branches.
-      Function.pushRegion(Region, CounterValues[Region.Count],
-                          CounterValues[Region.FalseCount]);
-    }
+  using DecisionAndBranches =
+      std::pair<const CounterMappingRegion *,             /// Decision
+                SmallVector<const CounterMappingRegion *> /// Branches
+                >;
+
+  /// Add MCDCBranchRegion to DecisionRecord.
+  /// \param Branch to be processed
+  /// \returns DecisionsAndBranches if DecisionRecord completed.
+  ///     Or returns nullopt.
+  std::optional<DecisionAndBranches>
+  processBranch(const CounterMappingRegion &Branch) {
+    // Seek each Decision and apply Region to it.
+    for (auto DecisionIter = Decisions.begin(), DecisionEnd = Decisions.end();
+         DecisionIter != DecisionEnd; ++DecisionIter)
+      switch (DecisionIter->addBranch(Branch)) {
+      case DecisionRecord::NotProcessed:
+        continue;
+      case DecisionRecord::Processed:
+        return std::nullopt;
+      case DecisionRecord::Completed:
+        DecisionAndBranches Result =
+            std::make_pair(DecisionIter->DecisionRegion,
+                           std::move(DecisionIter->MCDCBranches));
+        Decisions.erase(DecisionIter); // No longer used.
+        return Result;
+      }
 
-    return Error::success();
+    llvm_unreachable("Branch not found in Decisions");
   }
 };
 
@@ -919,12 +907,57 @@ Error CoverageMapping::loadFunctionRecord(
       Record.MappingRegions[0].Count.isZero() && Counts[0] > 0)
     return Error::success();
 
+  MCDCDecisionRecorder MCDCDecisions;
   FunctionRecord Function(OrigFuncName, Record.Filenames);
+  for (const auto &Region : Record.MappingRegions) {
+    // MCDCDecisionRegion should be handled first since it overlaps with
+    // others inside.
+    if (Region.Kind == CounterMappingRegion::MCDCDecisionRegion) {
+      MCDCDecisions.registerDecision(Region);
+      continue;
+    }
+    Expected<int64_t> ExecutionCount = Ctx.evaluate(Region.Count);
+    if (auto E = ExecutionCount.takeError()) {
+      consumeError(std::move(E));
+      return Error::success();
+    }
+    Expected<int64_t> AltExecutionCount = Ctx.evaluate(Region.FalseCount);
+    if (auto E = AltExecutionCount.takeError()) {
+      consumeError(std::move(E));
+      return Error::success();
+    }
+    Function.pushRegion(Region, *ExecutionCount, *AltExecutionCount);
 
-  // Emit CountedRegions into FunctionRecord.
-  if (auto E = CountedRegionEmitter(Record, Ctx, Function, IsVersion11)
-                   .emitCountedRegions())
-    return E;
+    // Record ExpansionRegion.
+    if (Region.Kind == CounterMappingRegion::ExpansionRegion) {
+      MCDCDecisions.recordExpansion(Region);
+      continue;
+    }
+
+    // Do nothing unless MCDCBranchRegion.
+    if (Region.Kind != CounterMappingRegion::MCDCBranchRegion)
+      continue;
+
+    auto Result = MCDCDecisions.processBranch(Region);
+    if (!Result) // Any Decision doesn't complete.
+      continue;
+
+    auto MCDCDecision = Result->first;
+    auto &MCDCBranches = Result->second;
+
+    // Since the bitmap identifies the executed test vectors for an MC/DC
+    // DecisionRegion, all of the information is now available to process.
+    // This is where the bulk of the MC/DC progressing takes place.
+    Expected<MCDCRecord> Record =
+        Ctx.evaluateMCDCRegion(*MCDCDecision, MCDCBranches, IsVersion11);
+    if (auto E = Record.takeError()) {
+      consumeError(std::move(E));
+      return Error::success();
+    }
+
+    // Save the MC/DC Record so that it can be visualized later.
+    Function.pushMCDCRecord(std::move(*Record));
+  }
 
   // Don't create records for (filenames, function) pairs we've already seen.
   auto FilenamesHash = hash_combine_range(Record.Filenames);
diff --git a/llvm/test/tools/llvm-cov/mcdc-macro.test b/llvm/test/tools/llvm-cov/mcdc-macro.test
index d68f4aeb67bcb..14dd5ebd68eb1 100644
--- a/llvm/test/tools/llvm-cov/mcdc-macro.test
+++ b/llvm/test/tools/llvm-cov/mcdc-macro.test
@@ -13,19 +13,19 @@
 // CHECK-NEXT:  |
 // CHECK-NEXT:  |  Number of Conditions: 5
 // CHECK-NEXT:  |     Condition C1 --> (9:7)
-// CHECK-NEXT:  |     Condition C2 --> (2:11)
-// CHECK-NEXT:  |     Condition C3 --> (3:11)
-// CHECK-NEXT:  |     Condition C4 --> (3:23)
-// CHECK-NEXT:  |     Condition C5 --> (9:22)
+// CHECK-NEXT:  |     Condition C2 --> (9:22)
+// CHECK-NEXT:  |     Condition C3 --> (2:11)
+// CHECK-NEXT:  |     Condition C4 --> (3:11)
+// CHECK-NEXT:  |     Condition C5 --> (3:23)
 // CHECK-NEXT:  |
 // CHECK-NEXT:  |  Executed MC/DC Test Vectors:
 // CHECK-NEXT:  |
 // CHECK-NEXT:  |     C1, C2, C3, C4, C5    Result
-// CHECK-NEXT:  |  1 { T,  C,  T,  T,  -  = T      }
+// CHECK-NEXT:  |  1 { T,  -,  C,  T,  T  = T      }
 // CHECK-NEXT:  |
 // CHECK-NEXT:  |  C1-Pair: not covered
-// CHECK-NEXT:  |  C2-Pair: constant folded
-// CHECK-NEXT:  |  C3-Pair: not covered
+// CHECK-NEXT:  |  C2-Pair: not covered
+// CHECK-NEXT:  |  C3-Pair: constant folded
 // CHECK-NEXT:  |  C4-Pair: not covered
 // CHECK-NEXT:  |  C5-Pair: not covered
 // CHECK-NEXT:  |  MC/DC Coverage for Decision: 0.00%

@gulfemsavrun gulfemsavrun merged commit 0319d8d into llvm:main Feb 12, 2026
12 checks passed
@llvm-ci
Copy link
Copy Markdown

llvm-ci commented Feb 12, 2026

LLVM Buildbot has detected a new failure on builder lldb-aarch64-ubuntu running on linaro-lldb-aarch64-ubuntu while building llvm at step 6 "test".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/59/builds/31683

Here is the relevant piece of the build log for the reference
Step 6 (test) failure: build (failure)
...
PASS: lldb-api :: commands/platform/basic/TestPlatformPython.py (197 of 2474)
PASS: lldb-api :: commands/platform/basic/TestPlatformCommand.py (198 of 2474)
PASS: lldb-api :: commands/platform/file/close/TestPlatformFileClose.py (199 of 2474)
PASS: lldb-api :: commands/platform/file/read/TestPlatformFileRead.py (200 of 2474)
PASS: lldb-api :: commands/memory/read/TestMemoryRead.py (201 of 2474)
PASS: lldb-api :: commands/platform/connect/TestPlatformConnect.py (202 of 2474)
PASS: lldb-api :: commands/platform/process/launch/TestPlatformProcessLaunch.py (203 of 2474)
UNSUPPORTED: lldb-api :: commands/platform/sdk/TestPlatformSDK.py (204 of 2474)
PASS: lldb-api :: commands/plugin/TestPlugin.py (205 of 2474)
UNRESOLVED: lldb-api :: commands/gui/spawn-threads/TestGuiSpawnThreads.py (206 of 2474)
******************** TEST 'lldb-api :: commands/gui/spawn-threads/TestGuiSpawnThreads.py' FAILED ********************
Script:
--
/usr/bin/python3.10 /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./lib --env LLVM_INCLUDE_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/include --env LLVM_TOOLS_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin --arch aarch64 --build-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex --lldb-module-cache-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/lldb --compiler /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/clang --dsymutil /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/dsymutil --make /usr/bin/gmake --llvm-tools-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin --lldb-obj-root /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/tools/lldb --lldb-libs-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./lib --cmake-build-type Release /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/llvm-project/lldb/test/API/commands/gui/spawn-threads -p TestGuiSpawnThreads.py
--
Exit Code: 1

Command Output (stdout):
--
lldb version 23.0.0git (https://github.com/llvm/llvm-project.git revision 0319d8ddbefcb578f2358e99a59d5af471b09e31)
  clang revision 0319d8ddbefcb578f2358e99a59d5af471b09e31
  llvm revision 0319d8ddbefcb578f2358e99a59d5af471b09e31
Skipping the following test categories: libc++, msvcstl, dsym, pdb, gmodules, debugserver, objc

--
Command Output (stderr):
--
FAIL: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_gui (TestGuiSpawnThreads.TestGuiSpawnThreadsTest)
======================================================================
ERROR: test_gui (TestGuiSpawnThreads.TestGuiSpawnThreadsTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/llvm-project/lldb/packages/Python/lldbsuite/test/decorators.py", line 160, in wrapper
    return func(*args, **kwargs)
  File "/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/llvm-project/lldb/test/API/commands/gui/spawn-threads/TestGuiSpawnThreads.py", line 44, in test_gui
    self.child.expect_exact(f"thread #{i + 2}: tid =")
  File "/usr/local/lib/python3.10/dist-packages/pexpect/spawnbase.py", line 432, in expect_exact
    return exp.expect_loop(timeout)
  File "/usr/local/lib/python3.10/dist-packages/pexpect/expect.py", line 179, in expect_loop
    return self.eof(e)
  File "/usr/local/lib/python3.10/dist-packages/pexpect/expect.py", line 122, in eof
    raise exc
pexpect.exceptions.EOF: End Of File (EOF). Exception style platform.
<pexpect.pty_spawn.spawn object at 0xea3fbd3bc790>
command: /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/lldb
args: ['/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/lldb', '--no-lldbinit', '--no-use-colors', '-O', 'settings clear --all', '-O', 'settings set symbols.enable-external-lookup false', '-O', 'settings set target.inherit-tcc true', '-O', 'settings set target.disable-aslr false', '-O', 'settings set target.detach-on-error false', '-O', 'settings set target.auto-apply-fixits false', '-O', 'settings set plugin.process.gdb-remote.packet-timeout 60', '-O', 'settings set symbols.clang-modules-cache-path "/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/module-cache-lldb/lldb-api"', '-O', 'settings set use-color false', '-O', 'settings set show-statusline false', '--file', '/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/commands/gui/spawn-threads/TestGuiSpawnThreads.test_gui/a.out']
buffer (last 100 chars): b''
before (last 100 chars): b'thread_create.c:442:8\n#28 0x0000f08952b79e9c ./misc/../sysdeps/unix/sysv/linux/aarch64/clone.S:82:0\n'
after: <class 'pexpect.exceptions.EOF'>

@chapuni
Copy link
Copy Markdown
Contributor

chapuni commented Feb 12, 2026

@gulfemsavrun
Could you elaborate? What did you resolve and what haven't you resolved? Is #180277 relevant?

@gulfemsavrun
Copy link
Copy Markdown
Contributor Author

gulfemsavrun commented Feb 12, 2026

@gulfemsavrun Could you elaborate? What did you resolve and what haven't you resolved? Is #180277 relevant?

PR #180277 is not relevant; the issue we are seeing is a specific regression introduced by PR #125407.

In Fuchsia, we perform end-to-end coverage collection across a large codebase (C++ and Rust). This makes us sensitive to edge cases in coverage mapping logic.

The failure is triggered by this line in CoverageMapping.cpp.

if (auto E = evaluateAndCacheCounter(Region.FalseCount))
  return E;

I think we should only evaluate FalseCount at this stage if it is an actual expression. Can we guard the evaluation as follows?

if (Region.FalseCount.isExpression()) {
    if (auto E = evaluateAndCacheCounter(Region.FalseCount))
      return E;
}

Copy link
Copy Markdown
Contributor

@chapuni chapuni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gulfemsavrun
Let me confirm. Does llvm-cov process non-clang-generated covmaps as well? It'd be helpful if you could provide the actual covmap that triggers the issue.

I haven't encountered this issue while testing llvm-cov with the LLVM tree.

Comment on lines +924 to +929
Expected<int64_t> AltExecutionCount = Ctx.evaluate(Region.FalseCount);
if (auto E = AltExecutionCount.takeError()) {
consumeError(std::move(E));
return Error::success();
}
Function.pushRegion(Region, *ExecutionCount, *AltExecutionCount);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the corresponding impl. This discards the error and terminates the evaluation of Function coverage at that point.

Is this the desired behavior? I can consider relaxing error handling in evaluate() as a workaround if preferred.

@gulfemsavrun
Copy link
Copy Markdown
Contributor Author

gulfemsavrun commented Feb 13, 2026

@gulfemsavrun Let me confirm. Does llvm-cov process non-clang-generated covmaps as well? It'd be helpful if you could provide the actual covmap that triggers the issue.

I haven't encountered this issue while testing llvm-cov with the LLVM tree.

The reproducer files have been uploaded to:
https://cas-viewer.appspot.com/projects/chromium-swarm/instances/default_instance/blobs/365f29d10c08e159e9b70dd8395d74c3f3dc6c63f5ea31c16069902476d014ad/833/tree

Please use the following command to reproduce the failure:

llvm-cov show -format html \
-instr-profile merged.profdata \
debuginfod/llvmcache-12624623701927073583

Just a heads-up that I'll be OOO all next week.

kevinwkt pushed a commit to kevinwkt/llvm-project that referenced this pull request Feb 16, 2026
…" (llvm#181069)

This reverts commit 8f690ec because it
caused errors in collecting coverage.
@chapuni
Copy link
Copy Markdown
Contributor

chapuni commented Feb 17, 2026

@gulfemsavrun I cannot download two files in the URL (500). Seems small files could be downloaded.

I can wait, for a few days, for the content server would get back better but I'd be happy if you (or anyone else) would send me files via other paths.

This revert has broken functionality of "MC/DC nested expressions".

@gulfemsavrun
Copy link
Copy Markdown
Contributor Author

@gulfemsavrun I cannot download two files in the URL (500). Seems small files could be downloaded.

I can wait, for a few days, for the content server would get back better but I'd be happy if you (or anyone else) would send me files via other paths.

This revert has broken functionality of "MC/DC nested expressions".

I have attached the file in split chunks, as the individual file size exceeds the 25MB upload limit.

cat merged.profdata.tar.gz.part_* | tar -xvzOf - > mergedprofile.profdata
cat binary.tar.gz.part_* | tar -xvzOf - > binary

Run the following command using the provided files:

llvm-cov show -format html \
-instr-profile mergedprofile.profdata \
-show-directory-coverage -output-dir coverage \
binary

The command fails with the following error:

error: failed to load coverage: 'llvmcache-12624623701927073583': Numerical argument out of domain

merged.profdata.tar.gz.part_aa.gz
merged.profdata.tar.gz.part_ab.gz
merged.profdata.tar.gz.part_ac.gz
merged.profdata.tar.gz.part_ad.gz
merged.profdata.tar.gz.part_ae.gz
binary.tar.gz.part_aa.gz
binary.tar.gz.part_ab.gz

@chapuni
Copy link
Copy Markdown
Contributor

chapuni commented Feb 24, 2026

@gulfemsavrun Thanks for files to be provided.

I can see what happens but I could not investigate what would actually be happening. Just guess, "profile correlation".

I have created #183073. It loosens errors.

@chapuni
Copy link
Copy Markdown
Contributor

chapuni commented Feb 28, 2026

I have restored in #183073.
Please inform me (hopefully with testcases) when you would find any further issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

PGO Profile Guided Optimizations

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants