Skip to content
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

MCDC coverage: support nested decision coverage #124255

Merged
merged 4 commits into from
Apr 29, 2024

Conversation

RenjiSann
Copy link
Contributor

#123409 provided the initial MCDC coverage implementation.

As referenced in #124144, it does not currently support "nested" decisions, like the following example :

fn nested_if_in_condition(a: bool, b: bool, c: bool) {
    if a && if b || c { true } else { false } {
        say("yes");
    } else {
        say("no");
    }
}

Note that there is an if-expression (if b || c ...) embedded inside a boolean expression in the decision of an outer if-expression.

This PR proposes a workaround for this cases, by introducing a Decision context stack, and by handing several temporary condition bitmaps instead of just one.
When instrumenting boolean expressions, if the current node is a leaf condition (i.e. not a ||/&& logical operator nor a ! not operator), we insert a new decision context, such that if there are more boolean expressions inside the condition, they are handled as separate expressions.

On the codegen LLVM side, we allocate as many temp_cond_bitmaps as necessary to handle the maximum encountered decision depth.

@rustbot
Copy link
Collaborator

rustbot commented Apr 22, 2024

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @cjgillot (or someone else) some time within the next two weeks.

Please see the contribution instructions for more information. Namely, in order to ensure the minimum review times lag, PR authors and assigned reviewers should ensure that the review label (S-waiting-on-review and S-waiting-on-author) stays updated, invoking these commands when appropriate:

  • @rustbot author: the review is finished, PR author should check the comments and take action accordingly
  • @rustbot review: the author is ready for a review, this PR will be queued again in the reviewer's queue

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Apr 22, 2024
@rustbot
Copy link
Collaborator

rustbot commented Apr 22, 2024

Some changes occurred in coverage instrumentation.

cc @Zalathar

Some changes occurred in match lowering

cc @Nadrieril

Some changes occurred to MIR optimizations

cc @rust-lang/wg-mir-opt

Some changes occurred in coverage tests.

cc @Zalathar

Some changes occurred in coverage instrumentation.

cc @Zalathar

Some changes occurred in coverage instrumentation.

cc @Zalathar

Some changes occurred in coverage instrumentation.

cc @Zalathar

@RenjiSann
Copy link
Contributor Author

@rustbot label +A-code-coverage

@rustbot rustbot added the A-code-coverage Area: Source-based code coverage (-Cinstrument-coverage) label Apr 22, 2024
@oli-obk oli-obk assigned oli-obk and unassigned cjgillot Apr 22, 2024
@oli-obk
Copy link
Contributor

oli-obk commented Apr 22, 2024

@bors delegate=Zalathar

@bors
Copy link
Contributor

bors commented Apr 22, 2024

✌️ @Zalathar, you can now approve this pull request!

If @oli-obk told you to "r=me" after making some further change, please make that change, then do @bors r=@oli-obk

@rust-log-analyzer

This comment has been minimized.

@RenjiSann RenjiSann force-pushed the renji/mcdc-nested-expressions branch 2 times, most recently from 7c1bedb to 67b59f8 Compare April 22, 2024 12:55
@RenjiSann
Copy link
Contributor Author

force pushed formatting

@bors
Copy link
Contributor

bors commented Apr 23, 2024

☔ The latest upstream changes (presumably #124271) made this pull request unmergeable. Please resolve the merge conflicts.

@RenjiSann RenjiSann force-pushed the renji/mcdc-nested-expressions branch from 67b59f8 to b231d4a Compare April 23, 2024 09:03
@RenjiSann
Copy link
Contributor Author

r? @Zalathar

@rustbot
Copy link
Collaborator

rustbot commented Apr 23, 2024

Failed to set assignee to Zalathar: invalid assignee

Note: Only org members with at least the repository "read" role, users with write permissions, or people who have commented on the PR may be assigned.

@RenjiSann RenjiSann force-pushed the renji/mcdc-nested-expressions branch from b231d4a to 074938a Compare April 23, 2024 13:16
@RenjiSann
Copy link
Contributor Author

rebased on top of #124217

@rust-log-analyzer

This comment has been minimized.

@RenjiSann RenjiSann force-pushed the renji/mcdc-nested-expressions branch from 074938a to 37cb490 Compare April 23, 2024 13:33
@Lambdaris
Copy link

The assignee has announced Zalathar as his delegate. So you could @ him once you prepared and he has full authority to approve this pr.

@RenjiSann RenjiSann force-pushed the renji/mcdc-nested-expressions branch from 4c59f9d to eb422d5 Compare April 29, 2024 09:14
@RenjiSann
Copy link
Contributor Author

I have rebased #124399 to this and fixed known issues in compiler/rustc_mir_build/src/build/coverageinfo.rs. Still you can choose your way to fix that and I will follow it at that pr.

Thank you !
If it is going to be refactored anyway, I'd prefer to let it like this for now.

@Zalathar
Copy link
Contributor

@RenjiSann Do you still have more tweaks to make, or are you ready for me to have another look at this?

@RenjiSann
Copy link
Contributor Author

@RenjiSann Do you still have more tweaks to make, or are you ready for me to have another look at this?

@Zalathar Nothing to add for now, you can take another look :)

@@ -195,7 +206,7 @@ fn ensure_mcdc_parameters<'ll, 'tcx>(
let fn_name = bx.get_pgo_func_name_var(instance);
let hash = bx.const_u64(function_coverage_info.function_source_hash);
let bitmap_bytes = bx.const_u32(function_coverage_info.mcdc_bitmap_bytes);
let cond_bitmap = bx.mcdc_parameters(fn_name, hash, bitmap_bytes);
let cond_bitmap = bx.mcdc_parameters(fn_name, hash, bitmap_bytes, 1_u32);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this should actually be 0, not 1. But since this is temporary code anyway, and the only effect is an extra unused bitmap, it's OK to not worry about it.

@Zalathar
Copy link
Contributor

There are a couple of things I would like to see improved (e.g. in the handling of max_decision_depth) ,but they're all minor enough that I think it's better to move forwards and get this merged as-is, and then consider some follow-up changes later.

@Zalathar
Copy link
Contributor

(Just be aware that I have a few follow-up things planned after #123409 and this, and #124399 is also waiting on this. So I think any major changes after this one should wait until after we've had a chance to do some cleanup steps.)

@Zalathar
Copy link
Contributor

@bors r=@oli-obk

@bors
Copy link
Contributor

bors commented Apr 29, 2024

📌 Commit eb422d5 has been approved by oli-obk

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 29, 2024
@Zalathar
Copy link
Contributor

@RenjiSann Oh, another thing I want to mention is that if you're adding tests for changed behaviour, it's often a good idea to add and bless the tests before making the changes, and then bless them again in later commits, so that it's easy to see the exact before/after changes in test output.

(In some cases this doesn't work, because the compiler would error or crash before the changes are made. But it's a good habit to get into.)

bors added a commit to rust-lang-ci/rust that referenced this pull request Apr 29, 2024
…ons, r=oli-obk

MCDC coverage: support nested decision coverage

rust-lang#123409 provided the initial MCDC coverage implementation.

As referenced in rust-lang#124144, it does not currently support "nested" decisions, like the following example :

```rust
fn nested_if_in_condition(a: bool, b: bool, c: bool) {
    if a && if b || c { true } else { false } {
        say("yes");
    } else {
        say("no");
    }
}
```

Note that there is an if-expression (`if b || c ...`) embedded inside a boolean expression in the decision of an outer if-expression.

This PR proposes a workaround for this cases, by introducing a Decision context stack, and by handing several `temporary condition bitmaps` instead of just one.
When instrumenting boolean expressions, if the current node is a leaf condition (i.e. not a `||`/`&&` logical operator nor a `!` not operator), we insert a new decision context, such that if there are more boolean expressions inside the condition, they are handled as separate expressions.

On the codegen LLVM side, we allocate as many `temp_cond_bitmap`s as necessary to handle the maximum encountered decision depth.
@bors
Copy link
Contributor

bors commented Apr 29, 2024

⌛ Testing commit eb422d5 with merge 56e04c5...

@oli-obk
Copy link
Contributor

oli-obk commented Apr 29, 2024

@bors r=Zalathar

@bors
Copy link
Contributor

bors commented Apr 29, 2024

💡 This pull request was already approved, no need to approve it again.

  • This pull request is currently being tested. If there's no response from the continuous integration service, you may use retry to trigger a build again.

@bors
Copy link
Contributor

bors commented Apr 29, 2024

📌 Commit eb422d5 has been approved by Zalathar

It is now in the queue for this repository.

@bors
Copy link
Contributor

bors commented Apr 29, 2024

⌛ Testing commit eb422d5 with merge 7a58674...

@rust-log-analyzer
Copy link
Collaborator

A job failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)

@RenjiSann
Copy link
Contributor Author

@RenjiSann Oh, another thing I want to mention is that if you're adding tests for changed behaviour, it's often a good idea to add and bless the tests before making the changes, and then bless them again in later commits, so that it's easy to see the exact before/after changes in test output.

(In some cases this doesn't work, because the compiler would error or crash before the changes are made. But it's a good habit to get into.)

Will do ! thanks !

@bors
Copy link
Contributor

bors commented Apr 29, 2024

☀️ Test successful - checks-actions
Approved by: Zalathar
Pushing 7a58674 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Apr 29, 2024
@bors bors merged commit 7a58674 into rust-lang:master Apr 29, 2024
11 checks passed
@rustbot rustbot added this to the 1.80.0 milestone Apr 29, 2024
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (7a58674): comparison URL.

Overall result: no relevant changes - no action needed

@rustbot label: -perf-regression

Instruction count

This benchmark run did not return any relevant results for this metric.

Max RSS (memory usage)

Results

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

mean range count
Regressions ❌
(primary)
2.0% [2.0%, 2.0%] 1
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) 2.0% [2.0%, 2.0%] 1

Cycles

This benchmark run did not return any relevant results for this metric.

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 672.94s -> 671.855s (-0.16%)
Artifact size: 315.94 MiB -> 315.98 MiB (0.01%)

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request May 3, 2024
coverage: Clean up creation of MC/DC condition bitmaps

This PR improves the code for creating and initializing [MC/DC](https://en.wikipedia.org/wiki/Modified_condition/decision_coverage) condition bitmap variables, as introduced by rust-lang#123409 and modified by rust-lang#124255.

- The condition bitmap variables are now created eagerly at the start of per-function codegen, via a new `init_coverage` method in `CoverageInfoBuilderMethods`. This avoids having to retroactively create the bitmaps while doing codegen for an individual coverage statement.
- As a result, we can now create and initialize those bitmaps using existing safe APIs, instead of having to perform our own unsafe call to `llvm::LLVMBuildAlloca`.
- This PR also tweaks the way we count the number of condition bitmaps needed, by tracking the total number of bitmaps needed (max depth + 1), instead of only tracking the maximum depth. This reduces the potential for subtle off-by-one confusion.
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request May 3, 2024
Rollup merge of rust-lang#124555 - Zalathar:init-coverage, r=nnethercote

coverage: Clean up creation of MC/DC condition bitmaps

This PR improves the code for creating and initializing [MC/DC](https://en.wikipedia.org/wiki/Modified_condition/decision_coverage) condition bitmap variables, as introduced by rust-lang#123409 and modified by rust-lang#124255.

- The condition bitmap variables are now created eagerly at the start of per-function codegen, via a new `init_coverage` method in `CoverageInfoBuilderMethods`. This avoids having to retroactively create the bitmaps while doing codegen for an individual coverage statement.
- As a result, we can now create and initialize those bitmaps using existing safe APIs, instead of having to perform our own unsafe call to `llvm::LLVMBuildAlloca`.
- This PR also tweaks the way we count the number of condition bitmaps needed, by tracking the total number of bitmaps needed (max depth + 1), instead of only tracking the maximum depth. This reduces the potential for subtle off-by-one confusion.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-code-coverage Area: Source-based code coverage (-Cinstrument-coverage) merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants