153 Commits

Author SHA1 Message Date
Zile Xiong
d917027334
[llvm-cov] Guard against empty CountedRegions in findMainViewFileID (#189270)
When processing coverage generated from branch coverage mode, some
functions can reach findMainViewFileID with an empty CountedRegions
list. In that case the current logic still proceeds to infer the main
view file, even though there is no regular counted region available to
do so.

Return std::nullopt early when CountedRegions is empty.

This was observed when reproducing issue #189169 with:
  cargo llvm-cov --lib --branch

The issue appears related to branch-only coverage information being
recorded separately in CountedBranchRegions, while
findMainViewFileID currently only consults CountedRegions.
This patch is a defensive fix for the empty-region case; further
investigation may still be needed to determine whether branch regions
should participate in main view file selection.

Co-authored-by: Zile Xiong <xiongzile99@gmail.com>
2026-04-06 15:58:31 -05:00
NAKAMURA Takumi
245621408d
Restore #125407, Make covmap tolerant of nested Decisions (#183073)
Change(s):

- Suppress range errors in CounterExpr
2026-02-28 20:13:29 +09:00
gulfemsavrun
0319d8ddbe
Revert "[MC/DC] Make covmap tolerant of nested Decisions (#125407)" (#181069)
This reverts commit 8f690ec7ffd8d435a0212a191634b544b0741c4f because it
caused errors in collecting coverage.
2026-02-11 20:19:31 -08:00
NAKAMURA Takumi
8f690ec7ff
[MC/DC] Make covmap tolerant of nested Decisions (#125407)
CoverageMappingWriter reorders `Region`s by `endLoc DESC` to prioritize
wider `Decision` with the same `startLoc`.

In `llvm-cov`, tweak seeking Decisions by reversal order to find smaller
Decision first.
2026-01-31 12:05:10 +09:00
NAKAMURA Takumi
6c35a89dc6
[Coverage] Sort MCDCRecord::ExecVectors order by Bitmap index (#121195)
This makes easier to merge `MCDCRecord`s in later stages.

Depends on: #110966, #121188, #121190
2026-01-10 10:56:39 +09:00
NAKAMURA Takumi
fea69aa19f
LLVMCoverage: Unify getCoverageForFile and getCoverageForFunction. NFC (#120842)
Since #119952, `getCoverageForFile` and `getCoverageForFunction` have
similar structure each other. Ther merged method `addFunctionRegions`
has two lambda subfunctions.

* `getCoverageForFile`
  - `MainFileID` may be `nullopt`.
- `shouldProcess` picks up relevant records along `FileIDs` that is
scanned based on `MainFileID`. They may have expanded source files.
  - `shouldExpand` takes the presense of `MainFileID` into account.
* `getCoverageForFunction`
  - This assumes the presense of `MainFileID`.
  - `shouldProcess` picks up records that belong only to `MainFileID`.
  - `shouldExpand` assumes the presense of `MainFileID`.

This change introduces a wrapper class `MergeableCoverageData` for
further merging instances. At the moment, this returns `CoverageData`
including `buildSegments()`.

This change itself is NFC.
2026-01-10 10:29:52 +09:00
NAKAMURA Takumi
8a7d8c1690
[Coverage] Make additional counters available for BranchRegion. NFC. (#120930)
`getBranchCounterPair()` allocates an additional Counter to SkipPath in
`SingleByteCoverage`.

`IsCounterEqual()` calculates the comparison with rewinding counter
replacements.

`NumRegionCounters` is updated to take additional counters in account.

`incrementProfileCounter()` has a few additiona arguments.

- `UseSkipPath=true`, to specify setting counters for SkipPath. It
assumes `UseSkipPath=false` is used together.

- `UseBoth` may be specified for marking another path. It introduces the
same effect as issueing `markStmtAsUsed(!SkipPath, S)`.

`llvm-cov` discovers counters in `FalseCount` to allocate `MaxCounterID`
for empty profile data.


https://discourse.llvm.org/t/rfc-integrating-singlebytecoverage-with-branch-coverage/82492

Resumes: #112730 
Depends on: #112698 #112702 #112724
2026-01-10 09:56:15 +09:00
Fabian Meumertzheim
83f215b035
Reland "[llvm-cov] Add support for baseline coverage" (#144130)
When no profile is provided, but the new --empty-profile option is
specified, the export/report/show commands now emit coverage data
equivalent to that obtained from a profile with all zero counters
("baseline coverage").

This is useful for build systems (e.g. Bazel) that can track coverage
information for each build target, even those that are never linked into
tests and thus don't have runtime coverage data recorded. By merging in
baseline coverage, lines in files that aren't linked into tests are
correctly reported as uncovered.

Reland with fixes to `CoverageMappingTest.cpp`.

Reverts llvm/llvm-project#144121
2025-06-13 12:09:58 -07:00
Keith Smiley
65d88d31ea
Revert "[llvm-cov] Add support for baseline coverage" (#144121)
Reverts llvm/llvm-project#117910

```
/home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/llvm/unittests/ProfileData/CoverageMappingTest.cpp
/home/buildbots/llvm-external-buildbots/workers/ppc64le-lld-multistage-test/ppc64le-lld-multistage-test/llvm-project/llvm/unittests/ProfileData/CoverageMappingTest.cpp:281:28: error: 'std::reference_wrapper' may not intend to support class template argument deduction [-Werror,-Wctad-maybe-unsupported]
  281 |         std::make_optional(std::reference_wrapper(*ProfileReader));
      |                            ^
/usr/lib/gcc/ppc64le-redhat-linux/8/../../../../include/c++/8/bits/refwrap.h:289:11: note: add a deduction guide to suppress this warning
  289 |     class reference_wrapper
      |           ^
```
2025-06-13 10:04:45 -07:00
Fabian Meumertzheim
dc9e300f12
[llvm-cov] Add support for baseline coverage (#117910)
When no profile is provided, but the new --empty-profile option is
specifed, the export/report/show commands now emit coverage data
equivalent to that obtained from a profile with all zero counters
("baseline coverage").

This is useful for build systems (e.g. Bazel) that can track coverage
information for each build target, even those that are never linked into
tests and thus don't have runtime coverage data recorded. By merging in
baseline coverage, lines in files that aren't linked into tests are
correctly reported as uncovered.
2025-06-13 08:49:30 -07:00
Kazu Hirata
510c8a23e6
[llvm] Use llvm::find_if (NFC) (#139654) 2025-05-12 22:58:30 -07:00
Kazu Hirata
1f56716a7e
[llvm] Use hash_combine_range with ranges (NFC) (#137530) 2025-04-27 12:31:28 -07:00
Mike Hommey
e8999309f1
[Coverage] Speed up function record iteration (#122050)
When iterating over function records, filtered by file name, currently,
the iteration goes over all the function records, repeatedly for each
source file, essentially giving quadratic behavior.

413647d730972eac9675f695c2ea63fb393a5531 sped up some cases by keeping
track of the indices of the function records corresponding to each file
name. This change expands the use of that map to FunctionRecordIterator.

On a test case with Firefox's libxul.so and a 2.5MB profile, this brings
down the runtime of `llvm-cov export $lib --instr-profile $prof -t lcov`
from 12 minutes with 90% spent in skipOtherFiles to 19 seconds with no
samples in skipOtherFiles at all under a sampling profiler (with a
sampling interval of 1ms).

Fixes #62079
2025-01-17 07:56:12 +01:00
NAKAMURA Takumi
61b294aa15
Introduce CounterExpressionBuilder::subst(C, Map) (#112698)
This return a counter for each term in the expression replaced by
ReplaceMap.

At the moment, this doesn't update the Map, so Map is marked as `const`.
2025-01-09 16:27:35 +09:00
NAKAMURA Takumi
97097958fd
[Coverage] MCDC: Move findIndependencePairs deferred into MCDCRecord (#121188)
The result of "Independence pairs" is not mergeable. This change makes
defers re-calculation of "Independence pairs" after merging test
vectors.

No apparent behavior changes.
2025-01-07 08:52:04 +09:00
NAKAMURA Takumi
ee6f10d372
[Coverage] Make MCDCRecord::Folded as [false/true] with BitVector. NFC. (#121190)
For merging `MCDCRecord`s, `Folded` is expected to be promoted as
"Non-folded".
2024-12-28 17:48:30 +09:00
NAKAMURA Takumi
aa2fdc69d3
[Coverage] Move SingleByteCoverage out of CountedRegion (#110966)
`SingleByteCoverage` is not per-region attribute at least.
Move it into `CoverageData` since it comes from `profdata`.

Depends on: #120841
2024-12-27 20:42:26 +09:00
NAKAMURA Takumi
275a27703e
[Coverage][Single] Round Counters to boolean after evaluation (#110972)
Rounding in merging segments has been done after #75425.

Depends on: #113114
2024-12-24 08:01:01 +09:00
NAKAMURA Takumi
e698079658
Allow CoverageMapping::getCoverageForFile() to show Branches also outside functions (#120416)
Fixes #119952
2024-12-19 08:41:28 +09:00
NAKAMURA Takumi
4a011ac84f
[Coverage] Introduce "partial fold" on BranchRegion (#112694)
Currently both True/False counts were folded. It lost the information,
"It is True or False before folding." It prevented recalling branch
counts in merging template instantiations.

In `llvm-cov`, a folded branch is shown as:

- `[True: n, Folded]`
- `[Folded, False n]`

In the case If `n` is zero, a branch is reported as "uncovered". This is
distinguished from "folded" branch. When folded branches are merged,
`Folded` may be dissolved.

In the coverage map, either `Counter` is `Zero`. Currently both were
`Zero`.

Since "partial fold" has been introduced, either case in `switch` is
omitted as `Folded`.

Each `case:` in `switch` is reported as `[True: n, Folded]`, since
`False` count doesn't show meaningful value.

When `switch` doesn't have `default:`, `switch (Cond)` is reported as
`[Folded, False: n]`, since `True` count was just the sum of `case`(s).
`switch` with `default` can be considered as "the statement that doesn't
have any `False`(s)".
2024-10-20 12:30:35 +09:00
Kazu Hirata
0089f39e0f
[ProfileData] Avoid repeated hash lookups (NFC) (#110619) 2024-10-01 00:30:04 -07:00
Zequan Wu
a7c26aaf2e
Revert "[Coverage] Ignore unused functions if the count is 0." (#107901)
Reverts llvm/llvm-project#107661

Breaks llvm-project/llvm/unittests/ProfileData/CoverageMappingTest.cpp
2024-09-09 14:34:13 -04:00
Zequan Wu
6850410562
[Coverage] Ignore unused functions if the count is 0. (#107661)
Relax the condition to ignore the case when count is 0. 

This fixes a bug on
381e9d2386.
This was reported at
https://discourse.llvm.org/t/coverage-from-multiple-test-executables/81024/.
2024-09-09 14:14:21 -04:00
Kazu Hirata
dca820951c
[llvm] Use llvm::any_of (NFC) (#104443) 2024-08-15 17:59:10 -07:00
Nikita Popov
48ef912e2b [VFS] Avoid <stack> include (NFC)
Directly use a vector instead of wrapping it in a stack, like we
do in most places.
2024-06-21 15:17:41 +02:00
Kazu Hirata
7c6d0d26b1
[llvm] Use llvm::unique (NFC) (#95628) 2024-06-14 22:49:36 -07:00
NAKAMURA Takumi
71f8b441ed Reapply: [MC/DC][Coverage] Loosen the limit of NumConds from 6 (#82448)
By storing possible test vectors instead of combinations of conditions,
the restriction is dramatically relaxed.

This introduces two options to `cc1`:

* `-fmcdc-max-conditions=32767`
* `-fmcdc-max-test-vectors=2147483646`

This change makes coverage mapping, profraw, and profdata incompatible
with Clang-18.

- Bitmap semantics changed. It is incompatible with previous format.
- `BitmapIdx` in `Decision` points to the end of the bitmap.
- Bitmap is packed per function.
- `llvm-cov` can understand `profdata` generated by `llvm-profdata-18`.

RFC:
https://discourse.llvm.org/t/rfc-coverage-new-algorithm-and-file-format-for-mc-dc/76798

--
Change(s) since llvmorg-19-init-14288-g7ead2d8c7e91

- Update compiler-rt/test/profile/ContinuousSyncMode/image-with-mcdc.c
2024-06-14 19:31:56 +09:00
Hans Wennborg
b422fa6b62 Revert "[MC/DC][Coverage] Loosen the limit of NumConds from 6 (#82448)"
This broke the lit tests on Mac:
https://green.lab.llvm.org/job/llvm.org/job/clang-stage1-RA/1096/

> By storing possible test vectors instead of combinations of conditions,
> the restriction is dramatically relaxed.
>
> This introduces two options to `cc1`:
>
> * `-fmcdc-max-conditions=32767`
> * `-fmcdc-max-test-vectors=2147483646`
>
> This change makes coverage mapping, profraw, and profdata incompatible
> with Clang-18.
>
> - Bitmap semantics changed. It is incompatible with previous format.
> - `BitmapIdx` in `Decision` points to the end of the bitmap.
> - Bitmap is packed per function.
> - `llvm-cov` can understand `profdata` generated by `llvm-profdata-18`.
>
> RFC:
> https://discourse.llvm.org/t/rfc-coverage-new-algorithm-and-file-format-for-mc-dc/76798

This reverts commit 7ead2d8c7e9114b3f23666209a1654939987cb30.
2024-06-14 10:47:41 +02:00
NAKAMURA Takumi
7ead2d8c7e
[MC/DC][Coverage] Loosen the limit of NumConds from 6 (#82448)
By storing possible test vectors instead of combinations of conditions,
the restriction is dramatically relaxed.

This introduces two options to `cc1`:

* `-fmcdc-max-conditions=32767`
* `-fmcdc-max-test-vectors=2147483646`

This change makes coverage mapping, profraw, and profdata incompatible
with Clang-18.

- Bitmap semantics changed. It is incompatible with previous format.
- `BitmapIdx` in `Decision` points to the end of the bitmap.
- Bitmap is packed per function.
- `llvm-cov` can understand `profdata` generated by `llvm-profdata-18`.

RFC:
https://discourse.llvm.org/t/rfc-coverage-new-algorithm-and-file-format-for-mc-dc/76798
2024-06-13 20:09:02 +09:00
NAKAMURA Takumi
2a61eebc66 Cleanup asserts in BranchParameters and DecisionParameters 2024-05-10 16:00:16 +09:00
NAKAMURA Takumi
512a8a78a7
[MC/DC] Introduce class TestVector with a pair of BitVector (#82174)
This replaces `SmallVector<CondState>` and emulates it.

- -------- True  False DontCare
- Values:  True  False False
- Visited: True  True  False

`findIndependencePairs()` can be optimized with logical ops.

FIXME: Specialize `findIndependencePairs()` for the single word.
2024-02-27 16:46:49 +09:00
NAKAMURA Takumi
0ed61db6fd
[MC/DC] Refactor: Isolate the final result out of TestVector (#82282)
To reduce conditional judges in the loop in `findIndependencePairs()`, I
have tried a couple of tweaks.

* Isolate the final result in `TestVectors`

`using TestVectors = llvm::SmallVector<std::pair<TestVector,
CondState>>;`
The final result was just piggybacked on `TestVector`, so it has been
isolated.

* Filter out and sort `ExecVectors` by the final result

It will cost more in constructing `ExecVectors`, but it can reduce at
least one conditional judgement in the loop.
2024-02-27 15:31:04 +09:00
gulfemsavrun
23f895f656
[InstrProf] Single byte counters in coverage (#75425)
This patch inserts 1-byte counters instead of an 8-byte counters into
llvm profiles for source-based code coverage. The origial idea was
proposed as block-cov for PGO, and this patch repurposes that idea for
coverage: https://groups.google.com/g/llvm-dev/c/r03Z6JoN7d4

The current 8-byte counters mechanism add counters to minimal regions,
and infer the counters in the remaining regions via adding or
subtracting counters. For example, it infers the counter in the if.else
region by subtracting the counters between if.entry and if.then regions
in an if statement. Whenever there is a control-flow merge, it adds the
counters from all the incoming regions. However, we are not going to be
able to infer counters by subtracting two execution counts when using
single-byte counters. Therefore, this patch conservatively inserts
additional counters for the cases where we need to add or subtract
counters.

RFC:
https://discourse.llvm.org/t/rfc-single-byte-counters-for-source-based-code-coverage/75685
2024-02-26 14:44:55 -08:00
NAKAMURA Takumi
c087bebb02
Introduce mcdc::TVIdxBuilder (LLVM side, NFC) (#80676)
This is a preparation of incoming Clang changes (#82448) and just checks
`TVIdx` is calculated correctly. NFC.

`TVIdxBuilder` calculates deterministic Indices for each Condition Node.
It is used for `clang` to emit `TestVector` indices (aka ID) and for
`llvm-cov` to reconstruct `TestVectors`.

This includes the unittest `CoverageMappingTest.TVIdxBuilder`.

See also
https://discourse.llvm.org/t/rfc-coverage-new-algorithm-and-file-format-for-mc-dc/76798
2024-02-26 13:23:43 +09:00
NAKAMURA Takumi
1f6a347c8a Refactor: Let MCDC::State have DecisionByStmt and BranchByStmt
- Prune `RegionMCDCBitmapMap` and `RegionCondIDMap`. They are handled
  by `MCDCState`.
- Rename `s/BitmapMap/DecisionByStmt/`. It can handle Decision stuff.
- Rename `s/CondIDMap/BranchByStmt/`. It can be handle Branch stuff.
- `MCDCRecordProcessor`: Use `DecisionParams.BitmapIdx` directly.
2024-02-25 18:33:53 +09:00
NAKAMURA Takumi
ab76e48ac2
[MC/DC] Refactor: Let MCDCConditionID int16_t with zero-origin (#81257)
Also, Let `NumConditions` `uint16_t`.

It is smarter to handle the ID as signed.
Narrowing to `int16_t` will reduce costs of handling byvalue. (See also
#81221 and #81227)

External behavior doesn't change. They below handle values as internal
values plus 1.
* `-dump-coverage-mapping`
* `CoverageMappingReader.cpp`
* `CoverageMappingWriter.cpp`
2024-02-15 16:24:37 +09:00
NAKAMURA Takumi
1a1fcacbce
[MC/DC] Refactor: Introduce ConditionIDs as std::array<2> (#81221)
Its 0th element corresponds to `FalseID` and 1st to `TrueID`.

CoverageMappingGen.cpp: `DecisionIDPair` is replaced with `ConditionIDs`
2024-02-14 23:17:00 +09:00
NAKAMURA Takumi
a17a3e9d9a
[MC/DC] Refactor: Make MCDCParams as std::variant (#81227)
Introduce `mcdc::DecisionParameters` and `mcdc::BranchParameters` and make
sure them not initialized as zero.

FIXME: Could we make `CoverageMappingRegion` as a smart tagged union?
2024-02-13 22:43:46 +09:00
NAKAMURA Takumi
05ad0d4632
CoverageMapping.cpp: Apply std::move to MCDCRecord (#81220) 2024-02-13 17:45:28 +09:00
NAKAMURA Takumi
f0db35b93f
[MC/DC] Refactor: Introduce MCDCTypes.h for coverage::mcdc (#81459)
They can be also used in `clang`.
Introduce the lightweight header instead of `CoverageMapping.h`.

This includes for now:
* `mcdc::ConditionID`
* `mcdc::Parameters`
2024-02-13 17:40:51 +09:00
NAKAMURA Takumi
3f9d8d892e
[Coverage] MCDCRecordProcessor: Find ExecVectors directly (#80816)
Deprecate `TestVectors`, since no one uses it.

This affects the output order of ExecVectors.
The current impl emits sorted by binary value of ExecVector. This impl
emits along the traversal of `buildTestVector()`.
2024-02-09 06:11:20 +09:00
NAKAMURA Takumi
0b62218110 Anonymize MCDCRecordProcessor 2024-02-06 17:18:19 +09:00
NAKAMURA Takumi
47a12cca44 CoverageMapping.cpp: s/MaxBitmapID/MaxBitmapIdx/ in getMaxBitmapSize() 2024-02-06 16:13:02 +09:00
NAKAMURA Takumi
4926f12ff5
[Coverage] ProfileData: Handle MC/DC Bitmap as BitVector. NFC. (#80608)
* `getFunctionBitmap()` stores not `std::vector<uint8_t>` but
`BitVector`.
* `CounterMappingContext` holds `Bitmap` (instead of the ref of bytes)
* `Bitmap` and `BitmapIdx` are used instead of `evaluateBitmap()`.

FIXME: `InstrProfRecord` itself should handle `Bitmap` as `BitVector`.
2024-02-05 12:42:08 +09:00
NAKAMURA Takumi
d912f1f0cb
[Coverage] Let Decision take account of expansions (#78969)
The current implementation (D138849) assumes `Branch`(es) would follow
after the corresponding `Decision`. It is not true if `Branch`(es) are
forwarded to expanded file ID. As a result, consecutive `Decision`(s)
would be confused with insufficient number of `Branch`(es).

`Expansion` will point `Branch`(es) in other file IDs if `Expansion` is
included in the range of `Decision`.

Fixes #77871

---------

Co-authored-by: Alan Phipps <a-phipps@ti.com>
2024-02-02 20:34:12 +09:00
Fangrui Song
3d0a689eb7
[llvm-cov] Simplify and optimize MC/DC computation (#79727)
Update code from https://reviews.llvm.org/D138847

`buildTestVector` is a standard DFS (walking a reduced ordered binary
decision diagram). Avoid shouldCopyOffTestVectorFor{True,False}Path
complexity and redundant `Map[ID]` lookups.

`findIndependencePairs` unnecessarily uses four nested loops (n<=6) to
find independence pairs. Instead, enumerate the two execution vectors
and find the number of mismatches. This algorithm can be optimized using
the marking function technique described in _Efficient Test Coverage
Measurement for MC/DC,  2013_, but this may be overkill.
2024-01-29 12:07:13 -08:00
NAKAMURA Takumi
c193bb7e9e
[Coverage] getMaxBitmapSize: Scan max(BitmapIdx) instead of the last Decision (#78963)
In `CoverageMapping.cpp:getMaxBitmapSize()`, 
this assumed that the last `Decision` has the maxmum `BitmapIdx`.

Let it scan `max(BitmapIdx)`.

Note that `<=` is used insted of `<`, because `BitmapIdx == 0` is valid
and `MaxBitmapID` is `unsigned`. `BitmapIdx` is unique in the record.

Fixes #78922
2024-01-23 17:59:44 +09:00
NAKAMURA Takumi
fe0ec2c91c
[Coverage] Const-ize MCDCRecordProcessor stuff (#78918)
The life of `MCDCRecordProcessor`'s instance is short. It may accept
`const` objects to process.

On the other hand, the life of `MCDCBranches` is shorter than `Record`.
It may be rewritten with reference, rather than copying.
2024-01-23 07:28:10 +09:00
Hana Dusíková
865e4a1f33
[coverage] skipping code coverage for 'if constexpr' and 'if consteval' (#78033)
`if constexpr` and `if consteval` conditional statements code coverage
should behave more like a preprocesor `#if`-s than normal
ConditionalStmt. This PR should fix that.

---------

Co-authored-by: cor3ntin <corentinjabot@gmail.com>
2024-01-22 12:50:20 +01:00
Alan Phipps
47b0052f31
[CoverageMapping] Avoid use of pow() resulting in solaris build fail (#75559)
Fixes a build failure introduced by
commit 8ecbb0404d74 ("Reland [Coverage][llvm-cov]
Enable MC/DC Support in LLVM Source-based Code Coverage (2/3)")

Use of pow() is not necessary.
2023-12-14 23:49:35 -06:00