about summary refs log tree commit diff
path: root/compiler/rustc_data_structures/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-10-05 19:34:44 +0000
committerbors <bors@rust-lang.org>2020-10-05 19:34:44 +0000
commita1dfd2490a6cb456b92e469fa550dc217e20ad6d (patch)
treed54841b8f697d8c9d1225c6bfcd6a7fd629af1f2 /compiler/rustc_data_structures/src
parentea7e131435a960d154e9a5d6a9297039574ffd7d (diff)
parent6f627663a755fb1795a725c1b89d2d83be5096f9 (diff)
downloadrust-a1dfd2490a6cb456b92e469fa550dc217e20ad6d.tar.gz
rust-a1dfd2490a6cb456b92e469fa550dc217e20ad6d.zip
Auto merge of #77080 - richkadel:llvm-coverage-counters-2, r=tmandry
Working branch-level code coverage

Add a generalized implementation for computing branch-level coverage spans.

This iteration resolves some of the challenges I had identified a few weeks ago.

I've tried to implement a solution that is general enough to work for a lot of different graphs/patterns. It's encouraging to see the results on fairly large and complex crates seem to meet my expectations. This may be a "functionally complete" implementation.

Except for bug fixes or edge cases I haven't run into yet, the next and essentially final step, I think, is to replace some Counters with CounterExpressions (where their counter values can be computed by adding or subtracting other counters/expressions).

Examples of branch-level coverage support enabled in this PR:

* https://github.com/richkadel/rust/blob/llvm-coverage-counters-2/src/test/run-make-fulldeps/instrument-coverage-cov-reports-base/expected_show_coverage.coverage_of_drop_trait.txt
* https://github.com/richkadel/rust/blob/llvm-coverage-counters-2/src/test/run-make-fulldeps/instrument-coverage-cov-reports-base/expected_show_coverage.coverage_of_if.txt
* https://github.com/richkadel/rust/blob/llvm-coverage-counters-2/src/test/run-make-fulldeps/instrument-coverage-cov-reports-base/expected_show_coverage.coverage_of_if_else.txt
* https://github.com/richkadel/rust/blob/llvm-coverage-counters-2/src/test/run-make-fulldeps/instrument-coverage-cov-reports-base/expected_show_coverage.coverage_of_simple_loop.txt
* https://github.com/richkadel/rust/blob/llvm-coverage-counters-2/src/test/run-make-fulldeps/instrument-coverage-cov-reports-base/expected_show_coverage.coverage_of_simple_match.txt
* ... _and others in the same directory_

Examples of coverage analysis results (MIR spanview files) used to inject counters in the right `BasicBlocks`:

* https://htmlpreview.github.io/?https://github.com/richkadel/rust/blob/llvm-coverage-counters-2/src/test/run-make-fulldeps/instrument-coverage-mir-cov-html-base/expected_mir_dump.coverage_of_drop_trait/coverage_of_drop_trait.main.-------.InstrumentCoverage.0.html
* https://htmlpreview.github.io/?https://github.com/richkadel/rust/blob/llvm-coverage-counters-2/src/test/run-make-fulldeps/instrument-coverage-mir-cov-html-base/expected_mir_dump.coverage_of_if/coverage_of_if.main.-------.InstrumentCoverage.0.html
* https://htmlpreview.github.io/?https://github.com/richkadel/rust/blob/llvm-coverage-counters-2/src/test/run-make-fulldeps/instrument-coverage-mir-cov-html-base/expected_mir_dump.coverage_of_if_else/coverage_of_if_else.main.-------.InstrumentCoverage.0.html
* https://htmlpreview.github.io/?https://github.com/richkadel/rust/blob/llvm-coverage-counters-2/src/test/run-make-fulldeps/instrument-coverage-mir-cov-html-base/expected_mir_dump.coverage_of_simple_loop/coverage_of_simple_loop.main.-------.InstrumentCoverage.0.html
* https://htmlpreview.github.io/?https://github.com/richkadel/rust/blob/llvm-coverage-counters-2/src/test/run-make-fulldeps/instrument-coverage-mir-cov-html-base/expected_mir_dump.coverage_of_simple_match/coverage_of_simple_match.main.-------.InstrumentCoverage.0.html
* ... _and others in the same directory_

Here is some sample coverage output after compiling a few real-world crates with the new branch-level coverage features:

<img width="801" alt="Screen Shot 2020-09-25 at 1 03 11 PM" src="https://user-images.githubusercontent.com/3827298/94316848-fd882c00-ff39-11ea-9cff-0402d3abd1e7.png">
<img width="721" alt="Screen Shot 2020-09-25 at 1 00 36 PM" src="https://user-images.githubusercontent.com/3827298/94316886-11cc2900-ff3a-11ea-9d03-80b26c8a5173.png">
<img width="889" alt="Screen Shot 2020-09-25 at 12 54 57 PM" src="https://user-images.githubusercontent.com/3827298/94316900-18f33700-ff3a-11ea-8a80-58f67d84b8de.png">

r? `@tmandry`
FYI: `@wesleywiser`
Diffstat (limited to 'compiler/rustc_data_structures/src')
-rw-r--r--compiler/rustc_data_structures/src/graph/dominators/mod.rs9
1 files changed, 9 insertions, 0 deletions
diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
index 438a0d0c6ff..1cfbce2355e 100644
--- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs
@@ -9,6 +9,7 @@ use super::iterate::reverse_post_order;
 use super::ControlFlowGraph;
 use rustc_index::vec::{Idx, IndexVec};
 use std::borrow::BorrowMut;
+use std::cmp::Ordering;
 
 #[cfg(test)]
 mod tests;
@@ -108,6 +109,14 @@ impl<Node: Idx> Dominators<Node> {
         // FIXME -- could be optimized by using post-order-rank
         self.dominators(node).any(|n| n == dom)
     }
+
+    /// Provide deterministic ordering of nodes such that, if any two nodes have a dominator
+    /// relationship, the dominator will always precede the dominated. (The relative ordering
+    /// of two unrelated nodes will also be consistent, but otherwise the order has no
+    /// meaning.) This method cannot be used to determine if either Node dominates the other.
+    pub fn rank_partial_cmp(&self, lhs: Node, rhs: Node) -> Option<Ordering> {
+        self.post_order_rank[lhs].partial_cmp(&self.post_order_rank[rhs])
+    }
 }
 
 pub struct Iter<'dom, Node: Idx> {