Skip to content

Commit a400d7f

Browse files
committed
coverage: Make counter creation handle nodes/edges more uniformly
1 parent b27f33a commit a400d7f

File tree

1 file changed

+54
-48
lines changed

1 file changed

+54
-48
lines changed

compiler/rustc_mir_transform/src/coverage/counters.rs

Lines changed: 54 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -104,24 +104,18 @@ impl CoverageCounters {
104104
BcbCounter::Counter { id }
105105
}
106106

107-
/// Creates a new physical counter attached a BCB node.
108-
/// The node must not already have a counter.
107+
/// Creates a new physical counter for a BCB node.
109108
fn make_phys_node_counter(&mut self, bcb: BasicCoverageBlock) -> BcbCounter {
110-
let counter = self.make_counter_inner(CounterIncrementSite::Node { bcb });
111-
debug!(?bcb, ?counter, "node gets a physical counter");
112-
self.set_bcb_counter(bcb, counter)
109+
self.make_counter_inner(CounterIncrementSite::Node { bcb })
113110
}
114111

115-
/// Creates a new physical counter attached to a BCB edge.
116-
/// The edge must not already have a counter.
112+
/// Creates a new physical counter for a BCB edge.
117113
fn make_phys_edge_counter(
118114
&mut self,
119115
from_bcb: BasicCoverageBlock,
120116
to_bcb: BasicCoverageBlock,
121117
) -> BcbCounter {
122-
let counter = self.make_counter_inner(CounterIncrementSite::Edge { from_bcb, to_bcb });
123-
debug!(?from_bcb, ?to_bcb, ?counter, "edge gets a physical counter");
124-
self.set_bcb_edge_counter(from_bcb, to_bcb, counter)
118+
self.make_counter_inner(CounterIncrementSite::Edge { from_bcb, to_bcb })
125119
}
126120

127121
fn make_expression(&mut self, lhs: BcbCounter, op: Op, rhs: BcbCounter) -> BcbCounter {
@@ -330,11 +324,21 @@ impl<'a> MakeBcbCounters<'a> {
330324
return;
331325
}
332326

333-
// Determine the set of out-edges that don't yet have edge counters.
327+
// When choosing which out-edge should be given a counter expression, ignore edges that
328+
// already have counters, or could use the existing counter of their target node.
329+
let out_edge_has_counter = |to_bcb| {
330+
if self.coverage_counters.bcb_edge_counters.contains_key(&(from_bcb, to_bcb)) {
331+
return true;
332+
}
333+
self.basic_coverage_blocks.sole_predecessor(to_bcb) == Some(from_bcb)
334+
&& self.coverage_counters.bcb_counters[to_bcb].is_some()
335+
};
336+
337+
// Determine the set of out-edges that could benefit from being given an expression.
334338
let candidate_successors = self.basic_coverage_blocks.successors[from_bcb]
335339
.iter()
336340
.copied()
337-
.filter(|&to_bcb| self.edge_has_no_counter(from_bcb, to_bcb))
341+
.filter(|&to_bcb| !out_edge_has_counter(to_bcb))
338342
.collect::<Vec<_>>();
339343
debug!(?candidate_successors);
340344

@@ -371,14 +375,7 @@ impl<'a> MakeBcbCounters<'a> {
371375
);
372376

373377
debug!("{expression_to_bcb:?} gets an expression: {expression:?}");
374-
if let Some(sole_pred) = self.basic_coverage_blocks.sole_predecessor(expression_to_bcb) {
375-
// This edge normally wouldn't get its own counter, so attach the expression
376-
// to its target node instead, so that `edge_has_no_counter` can see it.
377-
assert_eq!(sole_pred, from_bcb);
378-
self.coverage_counters.set_bcb_counter(expression_to_bcb, expression);
379-
} else {
380-
self.coverage_counters.set_bcb_edge_counter(from_bcb, expression_to_bcb, expression);
381-
}
378+
self.coverage_counters.set_bcb_edge_counter(from_bcb, expression_to_bcb, expression);
382379
}
383380

384381
#[instrument(level = "debug", skip(self))]
@@ -389,6 +386,19 @@ impl<'a> MakeBcbCounters<'a> {
389386
return counter_kind;
390387
}
391388

389+
let counter = self.make_node_counter_inner(bcb);
390+
self.coverage_counters.set_bcb_counter(bcb, counter)
391+
}
392+
393+
fn make_node_counter_inner(&mut self, bcb: BasicCoverageBlock) -> BcbCounter {
394+
// If the node's sole in-edge already has a counter, use that.
395+
if let Some(sole_pred) = self.basic_coverage_blocks.sole_predecessor(bcb)
396+
&& let Some(&edge_counter) =
397+
self.coverage_counters.bcb_edge_counters.get(&(sole_pred, bcb))
398+
{
399+
return edge_counter;
400+
}
401+
392402
let predecessors = self.basic_coverage_blocks.predecessors[bcb].as_slice();
393403

394404
// Handle cases where we can't compute a node's count from its in-edges:
@@ -398,7 +408,9 @@ impl<'a> MakeBcbCounters<'a> {
398408
// leading to infinite recursion.
399409
if predecessors.len() <= 1 || predecessors.contains(&bcb) {
400410
debug!(?bcb, ?predecessors, "node has <=1 predecessors or is its own predecessor");
401-
return self.coverage_counters.make_phys_node_counter(bcb);
411+
let counter = self.coverage_counters.make_phys_node_counter(bcb);
412+
debug!(?bcb, ?counter, "node gets a physical counter");
413+
return counter;
402414
}
403415

404416
// A BCB with multiple incoming edges can compute its count by ensuring that counters
@@ -414,14 +426,31 @@ impl<'a> MakeBcbCounters<'a> {
414426
.expect("there must be at least one in-edge");
415427

416428
debug!("{bcb:?} gets a new counter (sum of predecessor counters): {sum_of_in_edges:?}");
417-
self.coverage_counters.set_bcb_counter(bcb, sum_of_in_edges)
429+
sum_of_in_edges
418430
}
419431

420432
#[instrument(level = "debug", skip(self))]
421433
fn get_or_make_edge_counter(
422434
&mut self,
423435
from_bcb: BasicCoverageBlock,
424436
to_bcb: BasicCoverageBlock,
437+
) -> BcbCounter {
438+
// If the edge already has a counter, return it.
439+
if let Some(&counter_kind) =
440+
self.coverage_counters.bcb_edge_counters.get(&(from_bcb, to_bcb))
441+
{
442+
debug!("Edge {from_bcb:?}->{to_bcb:?} already has a counter: {counter_kind:?}");
443+
return counter_kind;
444+
}
445+
446+
let counter = self.make_edge_counter_inner(from_bcb, to_bcb);
447+
self.coverage_counters.set_bcb_edge_counter(from_bcb, to_bcb, counter)
448+
}
449+
450+
fn make_edge_counter_inner(
451+
&mut self,
452+
from_bcb: BasicCoverageBlock,
453+
to_bcb: BasicCoverageBlock,
425454
) -> BcbCounter {
426455
// If the target node has exactly one in-edge (i.e. this one), then just
427456
// use the node's counter, since it will have the same value.
@@ -439,16 +468,10 @@ impl<'a> MakeBcbCounters<'a> {
439468
return self.get_or_make_node_counter(from_bcb);
440469
}
441470

442-
// If the edge already has a counter, return it.
443-
if let Some(&counter_kind) =
444-
self.coverage_counters.bcb_edge_counters.get(&(from_bcb, to_bcb))
445-
{
446-
debug!("Edge {from_bcb:?}->{to_bcb:?} already has a counter: {counter_kind:?}");
447-
return counter_kind;
448-
}
449-
450471
// Make a new counter to count this edge.
451-
self.coverage_counters.make_phys_edge_counter(from_bcb, to_bcb)
472+
let counter = self.coverage_counters.make_phys_edge_counter(from_bcb, to_bcb);
473+
debug!(?from_bcb, ?to_bcb, ?counter, "edge gets a physical counter");
474+
counter
452475
}
453476

454477
/// Given a set of candidate out-edges (represented by their successor node),
@@ -508,21 +531,4 @@ impl<'a> MakeBcbCounters<'a> {
508531

509532
None
510533
}
511-
512-
#[inline]
513-
fn edge_has_no_counter(
514-
&self,
515-
from_bcb: BasicCoverageBlock,
516-
to_bcb: BasicCoverageBlock,
517-
) -> bool {
518-
let edge_counter =
519-
if let Some(sole_pred) = self.basic_coverage_blocks.sole_predecessor(to_bcb) {
520-
assert_eq!(sole_pred, from_bcb);
521-
self.coverage_counters.bcb_counters[to_bcb]
522-
} else {
523-
self.coverage_counters.bcb_edge_counters.get(&(from_bcb, to_bcb)).copied()
524-
};
525-
526-
edge_counter.is_none()
527-
}
528534
}

0 commit comments

Comments
 (0)