[llvm] [Coverage] Fix quadratic propagation in RawCoverageMappingReader (PR #194996)

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 29 20:08:06 PDT 2026


https://github.com/MaskRay created https://github.com/llvm/llvm-project/pull/194996

```
llvm-cov export /tmp/Cov/bin/lld -instr-profile=/tmp/Cov/cov.profdata -format=lcov --sources lld/ELF/Arch/RISCV.cpp
```
does not finish after minutes.

Root cause: The expansion-region count propagation loop is bounded by
`VirtualFileMapping.size()`, the number of macro expansions.

In the TableGen-generated `RISCVGenDAGISel.inc` (depended on by
LLVMLTO), `NumFileMappings` is 74941 (largely due to the `TARGET_VAL`
macro). With 149887 mapping regions, the loop does not finish after more
than ten minutes.

Fix with an early break.


>From 08544396994265bd52882dd5dae9ff0684aaabd4 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Wed, 29 Apr 2026 19:22:18 -0700
Subject: [PATCH] [Coverage] Fix quadratic propagation in
 RawCoverageMappingReader

```
llvm-cov export /tmp/Cov/bin/lld -instr-profile=/tmp/Cov/cov.profdata -format=lcov --sources lld/ELF/Arch/RISCV.cpp
```
does not finish after minutes.

Root cause: The expansion-region count propagation loop is bounded by
`VirtualFileMapping.size()`, the number of macro expansions.

In the TableGen-generated `RISCVGenDAGISel.inc` (depended on by
LLVMLTO), `NumFileMappings` is 74941 (largely due to the `TARGET_VAL`
macro). With 149887 mapping regions, the loop does not finish after more
than ten minutes.

Fix with an early break.
---
 .../Coverage/CoverageMappingReader.cpp        | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
index 8ce0e9f62666c..e89efe09d49e8 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
@@ -440,23 +440,30 @@ Error RawCoverageMappingReader::read() {
   // Set the counters for the expansion regions.
   // i.e. Counter of expansion region = counter of the first region
   // from the expanded file.
-  // Perform multiple passes to correctly propagate the counters through
-  // all the nested expansion regions.
+  // Perform multiple passes to correctly propagate the counters through all the
+  // nested expansion regions. Iterate until no count changes.
   SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping;
   FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr);
-  for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) {
+  for (;;) {
     for (auto &R : MappingRegions) {
       if (R.Kind != CounterMappingRegion::ExpansionRegion)
         continue;
       assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]);
       FileIDExpansionRegionMapping[R.ExpandedFileID] = &R;
     }
+    bool Changed = false;
     for (auto &R : MappingRegions) {
-      if (FileIDExpansionRegionMapping[R.FileID]) {
-        FileIDExpansionRegionMapping[R.FileID]->Count = R.Count;
-        FileIDExpansionRegionMapping[R.FileID] = nullptr;
+      auto *&Slot = FileIDExpansionRegionMapping[R.FileID];
+      if (Slot) {
+        if (Slot->Count != R.Count) {
+          Slot->Count = R.Count;
+          Changed = true;
+        }
+        Slot = nullptr;
       }
     }
+    if (!Changed)
+      break;
   }
 
   return Error::success();



More information about the llvm-commits mailing list