Unverified Commit 0135cf99 authored by Fangrui Song's avatar Fangrui Song Committed by GitHub
Browse files

[Coverage] Fix quadratic propagation in RawCoverageMappingReader (#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.
parent e3533648
Loading
Loading
Loading
Loading
+13 −6
Original line number Diff line number Diff line
@@ -440,24 +440,31 @@ 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();
}