Skip to content

Commit 14e8ffb

Browse files
committed
coverage: Separately compute the set of BCBs with counter mappings
1 parent 6968123 commit 14e8ffb

File tree

2 files changed

+59
-46
lines changed

2 files changed

+59
-46
lines changed

compiler/rustc_mir_transform/src/coverage/mappings.rs

Lines changed: 47 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ pub(super) struct MCDCDecision {
5353
}
5454

5555
pub(super) struct CoverageSpans {
56-
bcb_has_mappings: BitSet<BasicCoverageBlock>,
5756
pub(super) code_mappings: Vec<CodeMapping>,
5857
pub(super) branch_pairs: Vec<BranchPair>,
5958
test_vector_bitmap_bytes: u32,
@@ -62,24 +61,18 @@ pub(super) struct CoverageSpans {
6261
}
6362

6463
impl CoverageSpans {
65-
pub(super) fn bcb_has_coverage_spans(&self, bcb: BasicCoverageBlock) -> bool {
66-
self.bcb_has_mappings.contains(bcb)
67-
}
68-
6964
pub(super) fn test_vector_bitmap_bytes(&self) -> u32 {
7065
self.test_vector_bitmap_bytes
7166
}
7267
}
7368

7469
/// Extracts coverage-relevant spans from MIR, and associates them with
7570
/// their corresponding BCBs.
76-
///
77-
/// Returns `None` if no coverage-relevant spans could be extracted.
7871
pub(super) fn generate_coverage_spans(
7972
mir_body: &mir::Body<'_>,
8073
hir_info: &ExtractedHirInfo,
8174
basic_coverage_blocks: &CoverageGraph,
82-
) -> Option<CoverageSpans> {
75+
) -> CoverageSpans {
8376
let mut code_mappings = vec![];
8477
let mut branch_pairs = vec![];
8578
let mut mcdc_branches = vec![];
@@ -107,32 +100,6 @@ pub(super) fn generate_coverage_spans(
107100
);
108101
}
109102

110-
if code_mappings.is_empty()
111-
&& branch_pairs.is_empty()
112-
&& mcdc_branches.is_empty()
113-
&& mcdc_decisions.is_empty()
114-
{
115-
return None;
116-
}
117-
118-
// Identify which BCBs have one or more mappings.
119-
let mut bcb_has_mappings = BitSet::new_empty(basic_coverage_blocks.num_nodes());
120-
let mut insert = |bcb| {
121-
bcb_has_mappings.insert(bcb);
122-
};
123-
124-
for &CodeMapping { span: _, bcb } in &code_mappings {
125-
insert(bcb);
126-
}
127-
for &BranchPair { true_bcb, false_bcb, .. } in &branch_pairs {
128-
insert(true_bcb);
129-
insert(false_bcb);
130-
}
131-
for &MCDCBranch { true_bcb, false_bcb, .. } in &mcdc_branches {
132-
insert(true_bcb);
133-
insert(false_bcb);
134-
}
135-
136103
// Determine the length of the test vector bitmap.
137104
let test_vector_bitmap_bytes = mcdc_decisions
138105
.iter()
@@ -142,14 +109,57 @@ pub(super) fn generate_coverage_spans(
142109
.max()
143110
.unwrap_or(0);
144111

145-
Some(CoverageSpans {
146-
bcb_has_mappings,
112+
CoverageSpans {
147113
code_mappings,
148114
branch_pairs,
149115
test_vector_bitmap_bytes,
150116
mcdc_branches,
151117
mcdc_decisions,
152-
})
118+
}
119+
}
120+
121+
impl CoverageSpans {
122+
pub(super) fn all_bcbs_with_counter_mappings(
123+
&self,
124+
basic_coverage_blocks: &CoverageGraph, // Only used for allocating a correctly-sized set
125+
) -> BitSet<BasicCoverageBlock> {
126+
// Fully destructure self to make sure we don't miss any fields that have mappings.
127+
let Self {
128+
code_mappings,
129+
branch_pairs,
130+
test_vector_bitmap_bytes: _,
131+
mcdc_branches,
132+
mcdc_decisions,
133+
} = self;
134+
135+
// Identify which BCBs have one or more mappings.
136+
let mut bcbs_with_counter_mappings = BitSet::new_empty(basic_coverage_blocks.num_nodes());
137+
let mut insert = |bcb| {
138+
bcbs_with_counter_mappings.insert(bcb);
139+
};
140+
141+
for &CodeMapping { span: _, bcb } in code_mappings {
142+
insert(bcb);
143+
}
144+
for &BranchPair { true_bcb, false_bcb, .. } in branch_pairs {
145+
insert(true_bcb);
146+
insert(false_bcb);
147+
}
148+
for &MCDCBranch { true_bcb, false_bcb, .. } in mcdc_branches {
149+
insert(true_bcb);
150+
insert(false_bcb);
151+
}
152+
153+
// MC/DC decisions refer to BCBs, but don't require those BCBs to have counters.
154+
if bcbs_with_counter_mappings.is_empty() {
155+
debug_assert!(
156+
mcdc_decisions.is_empty(),
157+
"A function with no counter mappings shouldn't have any decisions: {mcdc_decisions:?}",
158+
);
159+
}
160+
161+
bcbs_with_counter_mappings
162+
}
153163
}
154164

155165
fn resolve_block_markers(

compiler/rustc_mir_transform/src/coverage/mod.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -70,21 +70,24 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir:
7070

7171
////////////////////////////////////////////////////
7272
// Compute coverage spans from the `CoverageGraph`.
73-
let Some(coverage_spans) =
74-
mappings::generate_coverage_spans(mir_body, &hir_info, &basic_coverage_blocks)
75-
else {
76-
// No relevant spans were found in MIR, so skip instrumenting this function.
77-
return;
78-
};
73+
let coverage_spans =
74+
mappings::generate_coverage_spans(mir_body, &hir_info, &basic_coverage_blocks);
7975

8076
////////////////////////////////////////////////////
8177
// Create an optimized mix of `Counter`s and `Expression`s for the `CoverageGraph`. Ensure
8278
// every coverage span has a `Counter` or `Expression` assigned to its `BasicCoverageBlock`
8379
// and all `Expression` dependencies (operands) are also generated, for any other
8480
// `BasicCoverageBlock`s not already associated with a coverage span.
85-
let bcb_has_coverage_spans = |bcb| coverage_spans.bcb_has_coverage_spans(bcb);
81+
let bcbs_with_counter_mappings =
82+
coverage_spans.all_bcbs_with_counter_mappings(&basic_coverage_blocks);
83+
if bcbs_with_counter_mappings.is_empty() {
84+
// No relevant spans were found in MIR, so skip instrumenting this function.
85+
return;
86+
}
87+
88+
let bcb_has_counter_mappings = |bcb| bcbs_with_counter_mappings.contains(bcb);
8689
let coverage_counters =
87-
CoverageCounters::make_bcb_counters(&basic_coverage_blocks, bcb_has_coverage_spans);
90+
CoverageCounters::make_bcb_counters(&basic_coverage_blocks, bcb_has_counter_mappings);
8891

8992
let mappings = create_mappings(tcx, &hir_info, &coverage_spans, &coverage_counters);
9093
if mappings.is_empty() {
@@ -96,7 +99,7 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir:
9699
inject_coverage_statements(
97100
mir_body,
98101
&basic_coverage_blocks,
99-
bcb_has_coverage_spans,
102+
bcb_has_counter_mappings,
100103
&coverage_counters,
101104
);
102105

0 commit comments

Comments
 (0)