Skip to content

Commit 2ebe9c3

Browse files
committed
coverage: Simplify the loop that combines blocks into BCBs
1 parent 31fd3d2 commit 2ebe9c3

File tree

1 file changed

+33
-57
lines changed
  • compiler/rustc_mir_transform/src/coverage

1 file changed

+33
-57
lines changed

compiler/rustc_mir_transform/src/coverage/graph.rs

+33-57
Original file line numberDiff line numberDiff line change
@@ -91,74 +91,41 @@ impl CoverageGraph {
9191
// FIXME(#78544): MIR InstrumentCoverage: Improve coverage of `#[should_panic]` tests and
9292
// `catch_unwind()` handlers.
9393

94+
// Accumulates a chain of blocks that will be combined into one BCB.
9495
let mut basic_blocks = Vec::new();
96+
9597
let filtered_successors = |bb| bcb_filtered_successors(mir_body[bb].terminator());
9698
for bb in short_circuit_preorder(mir_body, filtered_successors)
9799
.filter(|&bb| mir_body[bb].terminator().kind != TerminatorKind::Unreachable)
98100
{
99-
if let Some(last) = basic_blocks.last() {
100-
let predecessors = &mir_body.basic_blocks.predecessors()[bb];
101-
if predecessors.len() > 1 || !predecessors.contains(last) {
102-
// The `bb` has more than one _incoming_ edge, and should start its own
103-
// `BasicCoverageBlockData`. (Note, the `basic_blocks` vector does not yet
104-
// include `bb`; it contains a sequence of one or more sequential basic_blocks
105-
// with no intermediate branches in or out. Save these as a new
106-
// `BasicCoverageBlockData` before starting the new one.)
107-
Self::add_basic_coverage_block(
108-
&mut bcbs,
109-
&mut bb_to_bcb,
110-
basic_blocks.split_off(0),
111-
);
112-
debug!(
113-
" because {}",
114-
if predecessors.len() > 1 {
115-
"predecessors.len() > 1".to_owned()
116-
} else {
117-
format!("bb {} is not in predecessors: {:?}", bb.index(), predecessors)
118-
}
119-
);
120-
}
101+
// If the previous block can't be chained into `bb`, flush the accumulated
102+
// blocks into a new BCB, then start building the next chain.
103+
if let Some(&prev) = basic_blocks.last()
104+
&& (!filtered_successors(prev).is_chainable() || {
105+
// If `bb` has multiple predecessor blocks, or `prev` isn't
106+
// one of its predecessors, we can't chain and must flush.
107+
let predecessors = &mir_body.basic_blocks.predecessors()[bb];
108+
predecessors.len() > 1 || !predecessors.contains(&prev)
109+
})
110+
{
111+
debug!(
112+
terminator_kind = ?mir_body[prev].terminator().kind,
113+
predecessors = ?&mir_body.basic_blocks.predecessors()[bb],
114+
"can't chain from {prev:?} to {bb:?}"
115+
);
116+
Self::add_basic_coverage_block(
117+
&mut bcbs,
118+
&mut bb_to_bcb,
119+
basic_blocks.split_off(0),
120+
);
121121
}
122-
basic_blocks.push(bb);
123-
124-
let term = mir_body[bb].terminator();
125-
126-
match bcb_filtered_successors(term) {
127-
CoverageSuccessors::NotChainable(_) => {
128-
// The `bb` has more than one _outgoing_ edge, or exits the function. Save the
129-
// current sequence of `basic_blocks` gathered to this point, as a new
130-
// `BasicCoverageBlockData`.
131-
Self::add_basic_coverage_block(
132-
&mut bcbs,
133-
&mut bb_to_bcb,
134-
basic_blocks.split_off(0),
135-
);
136-
debug!(" because term.kind = {:?}", term.kind);
137-
// Note that this condition is based on `TerminatorKind`, even though it
138-
// theoretically boils down to `successors().len() != 1`; that is, either zero
139-
// (e.g., `Return`, `Terminate`) or multiple successors (e.g., `SwitchInt`), but
140-
// since the BCB CFG ignores things like unwind branches (which exist in the
141-
// `Terminator`s `successors()` list) checking the number of successors won't
142-
// work.
143-
}
144122

145-
// The following `TerminatorKind`s are either not expected outside an unwind branch,
146-
// or they should not (under normal circumstances) branch. Coverage graphs are
147-
// simplified by assuring coverage results are accurate for program executions that
148-
// don't panic.
149-
//
150-
// Programs that panic and unwind may record slightly inaccurate coverage results
151-
// for a coverage region containing the `Terminator` that began the panic. This
152-
// is as intended. (See Issue #78544 for a possible future option to support
153-
// coverage in test programs that panic.)
154-
CoverageSuccessors::Chainable(_) => {}
155-
}
123+
basic_blocks.push(bb);
156124
}
157125

158126
if !basic_blocks.is_empty() {
159-
// process any remaining basic_blocks into a final `BasicCoverageBlockData`
127+
debug!("flushing accumulated blocks into one last BCB");
160128
Self::add_basic_coverage_block(&mut bcbs, &mut bb_to_bcb, basic_blocks.split_off(0));
161-
debug!(" because the end of the MIR CFG was reached while traversing");
162129
}
163130

164131
(bcbs, bb_to_bcb)
@@ -350,6 +317,15 @@ enum CoverageSuccessors<'a> {
350317
NotChainable(&'a [BasicBlock]),
351318
}
352319

320+
impl CoverageSuccessors<'_> {
321+
fn is_chainable(&self) -> bool {
322+
match self {
323+
Self::Chainable(_) => true,
324+
Self::NotChainable(_) => false,
325+
}
326+
}
327+
}
328+
353329
impl IntoIterator for CoverageSuccessors<'_> {
354330
type Item = BasicBlock;
355331
type IntoIter = impl DoubleEndedIterator<Item = Self::Item>;

0 commit comments

Comments
 (0)