-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a new CoverageKind::Branch to MIR #115061
Conversation
…LLVM We compile each test file to LLVM IR assembly, and then pass that IR to a dedicated program that can decode LLVM coverage maps and print them in a more human-readable format. We can then check that output against known-good snapshots. This test suite has some advantages over the existing `run-coverage` tests: - We can test coverage instrumentation without needing to run target binaries. - We can observe subtle improvements/regressions in the underlying coverage mappings that don't make a visible difference to coverage reports.
The output of these tests is too complicated to comfortably verify by hand, but we can still use them to observe changes to the underlying mappings produced by codegen/LLVM.
After coverage instrumentation and MIR transformations, we can sometimes end up with coverage expressions that always have a value of zero. Any expression operand that refers to an always-zero expression can be replaced with a literal `Operand::Zero`, making the emitted coverage mapping data smaller and simpler. This simplification step is mostly redundant with the simplifications performed inline in `expressions_with_regions`, except that it does a slightly more thorough job in some cases (because it checks for always-zero expressions *after* other simplifications). However, adding this simplification step will then let us greatly simplify that code, without affecting the quality of the emitted coverage maps.
The LLVM API that we use to encode coverage mappings already has its own code for removing unused coverage expressions and renumbering the rest. This lets us get rid of our own complex renumbering code, making it easier to refactor our coverage code in other ways.
r? @davidtwco (rustbot has picked a reviewer for you, use r? to override) |
@rustbot label +A-code-coverage |
This removes quite a bit of indirection and duplicated code related to getting the `FunctionCoverage`.
This adds a couple intermediate types, and threads branch coverage from MIR through codegen.
fc52c47
to
4152c4d
Compare
Rebased on top of #114399 which makes the changes here a lot simpler. |
A first proof of concept seems to be functional and it outputs the following counters / mappings (see 7f985c4):
As well as
There are still a couple of problems with this POC that I will take a look at this week:
|
I was surprised to see changes to In the existing implementation, it prints the raw true/false counters inline, and then also expands expressions (if any) on separate lines as needed. |
/// Additionally, instrument branches and output branch overage | ||
Branch, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To save anyone else the trouble of checking whether this is accidentally stable (it's not):
New values of InstrumentCoverage
are automatically treated as nightly-only unless they are explicitly added to the check shown below on line 2674, so Branch
is correctly treated as a nightly-only value. 👍
rust/compiler/rustc_session/src/config.rs
Lines 2665 to 2685 in c6f5495
// Handle both `-Z instrument-coverage` and `-C instrument-coverage`; the latter takes | |
// precedence. | |
match (cg.instrument_coverage, unstable_opts.instrument_coverage) { | |
(Some(ic_c), Some(ic_z)) if ic_c != ic_z => { | |
handler.early_error( | |
"incompatible values passed for `-C instrument-coverage` \ | |
and `-Z instrument-coverage`", | |
); | |
} | |
(Some(InstrumentCoverage::Off | InstrumentCoverage::All), _) => {} | |
(Some(_), _) if !unstable_opts.unstable_options => { | |
handler.early_error("`-C instrument-coverage=except-*` requires `-Z unstable-options`"); | |
} | |
(None, None) => {} | |
(None, ic) => { | |
handler | |
.early_warn("`-Z instrument-coverage` is deprecated; use `-C instrument-coverage`"); | |
cg.instrument_coverage = ic; | |
} | |
_ => {} | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I haven’t yet hooked up the option, so it doesn’t do anything right now, yet.
I didn’t know this was intentional, as the inline |
In that case, I’ll switch over to How do you feel about only showing the resolved lines when the true/false counter is an expression, versus always showing them? I chose to hide them (to keep the output compact), but if you think always showing them is better overall, I can make that change in my branch too. |
IMO for |
This extends the current simplification code to not only replace operands by `Zero`, but also to remove trivial `Counter + Zero` expressions and replace those with just `Counter`.
e5662b6
to
f342569
Compare
Use |
…esleywiser Introduce `-C instrument-coverage=branch` to gate branch coverage This was extracted from rust-lang#115061 and can land independently from other coverage related work. The flag is unused for now, but is added in advance of adding branch coverage support. It is an unstable, nightly only flag that needs to be used in combination with `-Zunstable-options`, like so: `-Zunstable-options -C instrument-coverage=branch`. The goal is to develop branch coverage as an unstable opt-in feature first, before it matures and can be turned on by default.
…leywiser Introduce `-C instrument-coverage=branch` to gate branch coverage This was extracted from rust-lang#115061 and can land independently from other coverage related work. The flag is unused for now, but is added in advance of adding branch coverage support. It is an unstable, nightly only flag that needs to be used in combination with `-Zunstable-options`, like so: `-Zunstable-options -C instrument-coverage=branch`. The goal is to develop branch coverage as an unstable opt-in feature first, before it matures and can be turned on by default.
…esleywiser Introduce `-C instrument-coverage=branch` to gate branch coverage This was extracted from rust-lang#115061 and can land independently from other coverage related work. The flag is unused for now, but is added in advance of adding branch coverage support. It is an unstable, nightly only flag that needs to be used in combination with `-Zunstable-options`, like so: `-Zunstable-options -C instrument-coverage=branch`. The goal is to develop branch coverage as an unstable opt-in feature first, before it matures and can be turned on by default.
…esleywiser Introduce `-C instrument-coverage=branch` to gate branch coverage This was extracted from rust-lang#115061 and can land independently from other coverage related work. The flag is unused for now, but is added in advance of adding branch coverage support. It is an unstable, nightly only flag that needs to be used in combination with `-Zunstable-options`, like so: `-Zunstable-options -C instrument-coverage=branch`. The goal is to develop branch coverage as an unstable opt-in feature first, before it matures and can be turned on by default.
Rollup merge of rust-lang#116094 - Swatinem:coverage-branch-gate, r=wesleywiser Introduce `-C instrument-coverage=branch` to gate branch coverage This was extracted from rust-lang#115061 and can land independently from other coverage related work. The flag is unused for now, but is added in advance of adding branch coverage support. It is an unstable, nightly only flag that needs to be used in combination with `-Zunstable-options`, like so: `-Zunstable-options -C instrument-coverage=branch`. The goal is to develop branch coverage as an unstable opt-in feature first, before it matures and can be turned on by default.
@Swatinem any updates on this? thanks |
I will close this PR for now. |
This adds a couple intermediate types, and threads branch coverage from MIR through to codegen, and emits branch coverage regions via LLVM.
Based on top of #114399 and #115058, and so far untested, as we do not (yet) generate any branches in MIR.