Skip to content

Commit 341881f

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

File tree

1 file changed

+52
-44
lines changed

1 file changed

+52
-44
lines changed

compiler/rustc_mir_transform/src/coverage/counters.rs

+52-44
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,7 @@ impl CoverageCounters {
107107
/// Creates a new physical counter attached a BCB node.
108108
/// The node must not already have a counter.
109109
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)
110+
self.make_counter_inner(CounterIncrementSite::Node { bcb })
113111
}
114112

115113
/// Creates a new physical counter attached to a BCB edge.
@@ -119,9 +117,7 @@ impl CoverageCounters {
119117
from_bcb: BasicCoverageBlock,
120118
to_bcb: BasicCoverageBlock,
121119
) -> 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)
120+
self.make_counter_inner(CounterIncrementSite::Edge { from_bcb, to_bcb })
125121
}
126122

127123
fn make_expression(&mut self, lhs: BcbCounter, op: Op, rhs: BcbCounter) -> BcbCounter {
@@ -330,11 +326,21 @@ impl<'a> MakeBcbCounters<'a> {
330326
return;
331327
}
332328

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

@@ -371,14 +377,7 @@ impl<'a> MakeBcbCounters<'a> {
371377
);
372378

373379
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-
}
380+
self.coverage_counters.set_bcb_edge_counter(from_bcb, expression_to_bcb, expression);
382381
}
383382

384383
#[instrument(level = "debug", skip(self))]
@@ -389,6 +388,19 @@ impl<'a> MakeBcbCounters<'a> {
389388
return counter_kind;
390389
}
391390

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

394406
// Handle cases where we can't compute a node's count from its in-edges:
@@ -398,7 +410,9 @@ impl<'a> MakeBcbCounters<'a> {
398410
// leading to infinite recursion.
399411
if predecessors.len() <= 1 || predecessors.contains(&bcb) {
400412
debug!(?bcb, ?predecessors, "node has <=1 predecessors or is its own predecessor");
401-
return self.coverage_counters.make_phys_node_counter(bcb);
413+
let counter = self.coverage_counters.make_phys_node_counter(bcb);
414+
debug!(?bcb, ?counter, "node gets a physical counter");
415+
return counter;
402416
}
403417

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

416430
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)
431+
sum_of_in_edges
418432
}
419433

420434
#[instrument(level = "debug", skip(self))]
421435
fn get_or_make_edge_counter(
422436
&mut self,
423437
from_bcb: BasicCoverageBlock,
424438
to_bcb: BasicCoverageBlock,
439+
) -> BcbCounter {
440+
// If the edge already has a counter, return it.
441+
if let Some(&counter_kind) =
442+
self.coverage_counters.bcb_edge_counters.get(&(from_bcb, to_bcb))
443+
{
444+
debug!("Edge {from_bcb:?}->{to_bcb:?} already has a counter: {counter_kind:?}");
445+
return counter_kind;
446+
}
447+
448+
let counter = self.make_edge_counter_inner(from_bcb, to_bcb);
449+
self.coverage_counters.set_bcb_edge_counter(from_bcb, to_bcb, counter)
450+
}
451+
452+
fn make_edge_counter_inner(
453+
&mut self,
454+
from_bcb: BasicCoverageBlock,
455+
to_bcb: BasicCoverageBlock,
425456
) -> BcbCounter {
426457
// If the target node has exactly one in-edge (i.e. this one), then just
427458
// use the node's counter, since it will have the same value.
@@ -439,16 +470,10 @@ impl<'a> MakeBcbCounters<'a> {
439470
return self.get_or_make_node_counter(from_bcb);
440471
}
441472

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-
450473
// Make a new counter to count this edge.
451-
self.coverage_counters.make_phys_edge_counter(from_bcb, to_bcb)
474+
let counter = self.coverage_counters.make_phys_edge_counter(from_bcb, to_bcb);
475+
debug!(?from_bcb, ?to_bcb, ?counter, "edge gets a physical counter");
476+
counter
452477
}
453478

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

509534
None
510535
}
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-
}
528536
}

0 commit comments

Comments
 (0)