Skip to content

Commit 669327f

Browse files
committed
coverage: Replace bcb_has_multiple_in_edges with sole_predecessor
This does a better job of expressing the special cases that occur when a node in the coverage graph has exactly one in-edge.
1 parent e24310b commit 669327f

File tree

2 files changed

+30
-35
lines changed

2 files changed

+30
-35
lines changed

compiler/rustc_mir_transform/src/coverage/counters.rs

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -364,10 +364,13 @@ impl<'a> MakeBcbCounters<'a> {
364364
);
365365

366366
debug!("{expression_to_bcb:?} gets an expression: {expression:?}");
367-
if self.basic_coverage_blocks.bcb_has_multiple_in_edges(expression_to_bcb) {
368-
self.coverage_counters.set_bcb_edge_counter(from_bcb, expression_to_bcb, expression);
369-
} else {
367+
if let Some(sole_pred) = self.basic_coverage_blocks.sole_predecessor(expression_to_bcb) {
368+
// This edge normally wouldn't get its own counter, so attach the expression
369+
// to its target node instead, so that `edge_has_no_counter` can see it.
370+
assert_eq!(sole_pred, from_bcb);
370371
self.coverage_counters.set_bcb_counter(expression_to_bcb, expression);
372+
} else {
373+
self.coverage_counters.set_bcb_edge_counter(from_bcb, expression_to_bcb, expression);
371374
}
372375
}
373376

@@ -413,10 +416,12 @@ impl<'a> MakeBcbCounters<'a> {
413416
from_bcb: BasicCoverageBlock,
414417
to_bcb: BasicCoverageBlock,
415418
) -> BcbCounter {
416-
// If the target BCB has only one in-edge (i.e. this one), then create
417-
// a node counter instead, since it will have the same value.
418-
if !self.basic_coverage_blocks.bcb_has_multiple_in_edges(to_bcb) {
419-
assert_eq!([from_bcb].as_slice(), self.basic_coverage_blocks.predecessors[to_bcb]);
419+
// If the target node has exactly one in-edge (i.e. this one), then just
420+
// use the node's counter, since it will have the same value.
421+
if let Some(sole_pred) = self.basic_coverage_blocks.sole_predecessor(to_bcb) {
422+
assert_eq!(sole_pred, from_bcb);
423+
// This call must take care not to invoke `get_or_make_edge` for
424+
// this edge, since that would result in infinite recursion!
420425
return self.get_or_make_node_counter(to_bcb);
421426
}
422427

@@ -508,18 +513,14 @@ impl<'a> MakeBcbCounters<'a> {
508513
from_bcb: BasicCoverageBlock,
509514
to_bcb: BasicCoverageBlock,
510515
) -> bool {
511-
self.edge_counter(from_bcb, to_bcb).is_none()
512-
}
513-
514-
fn edge_counter(
515-
&self,
516-
from_bcb: BasicCoverageBlock,
517-
to_bcb: BasicCoverageBlock,
518-
) -> Option<&BcbCounter> {
519-
if self.basic_coverage_blocks.bcb_has_multiple_in_edges(to_bcb) {
520-
self.coverage_counters.bcb_edge_counters.get(&(from_bcb, to_bcb))
521-
} else {
522-
self.coverage_counters.bcb_counters[to_bcb].as_ref()
523-
}
516+
let edge_counter =
517+
if let Some(sole_pred) = self.basic_coverage_blocks.sole_predecessor(to_bcb) {
518+
assert_eq!(sole_pred, from_bcb);
519+
self.coverage_counters.bcb_counters[to_bcb]
520+
} else {
521+
self.coverage_counters.bcb_edge_counters.get(&(from_bcb, to_bcb)).copied()
522+
};
523+
524+
edge_counter.is_none()
524525
}
525526
}

compiler/rustc_mir_transform/src/coverage/graph.rs

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -165,21 +165,15 @@ impl CoverageGraph {
165165
self.dominators.as_ref().unwrap().cmp_in_dominator_order(a, b)
166166
}
167167

168-
/// Returns true if the given node has 2 or more in-edges, i.e. 2 or more
169-
/// predecessors.
170-
///
171-
/// This property is interesting to code that assigns counters to nodes and
172-
/// edges, because if a node _doesn't_ have multiple in-edges, then there's
173-
/// no benefit in having a separate counter for its in-edge, because it
174-
/// would have the same value as the node's own counter.
175-
#[inline(always)]
176-
pub(crate) fn bcb_has_multiple_in_edges(&self, bcb: BasicCoverageBlock) -> bool {
177-
// Even though bcb0 conceptually has an extra virtual in-edge due to
178-
// being the entry point, we've already asserted that it has no _other_
179-
// in-edges, so there's no possibility of it having _multiple_ in-edges.
180-
// (And since its virtual in-edge doesn't exist in the graph, that edge
181-
// can't have a separate counter anyway.)
182-
self.predecessors[bcb].len() > 1
168+
/// Returns the source of this node's sole in-edge, if it has exactly one.
169+
/// That edge can be assumed to have the same execution count as the node
170+
/// itself (in the absence of panics).
171+
pub(crate) fn sole_predecessor(
172+
&self,
173+
to_bcb: BasicCoverageBlock,
174+
) -> Option<BasicCoverageBlock> {
175+
// Unlike `simple_successor`, there is no need for extra checks here.
176+
if let &[from_bcb] = self.predecessors[to_bcb].as_slice() { Some(from_bcb) } else { None }
183177
}
184178

185179
/// Returns the target of this node's sole out-edge, if it has exactly

0 commit comments

Comments
 (0)