coverage: Make counter creation handle nodes/edges more uniformly
This commit is contained in:
parent
b27f33a4d9
commit
a400d7fb76
@ -104,24 +104,18 @@ impl CoverageCounters {
|
|||||||
BcbCounter::Counter { id }
|
BcbCounter::Counter { id }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new physical counter attached a BCB node.
|
/// Creates a new physical counter for a BCB node.
|
||||||
/// The node must not already have a counter.
|
|
||||||
fn make_phys_node_counter(&mut self, bcb: BasicCoverageBlock) -> BcbCounter {
|
fn make_phys_node_counter(&mut self, bcb: BasicCoverageBlock) -> BcbCounter {
|
||||||
let counter = self.make_counter_inner(CounterIncrementSite::Node { bcb });
|
self.make_counter_inner(CounterIncrementSite::Node { bcb })
|
||||||
debug!(?bcb, ?counter, "node gets a physical counter");
|
|
||||||
self.set_bcb_counter(bcb, counter)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new physical counter attached to a BCB edge.
|
/// Creates a new physical counter for a BCB edge.
|
||||||
/// The edge must not already have a counter.
|
|
||||||
fn make_phys_edge_counter(
|
fn make_phys_edge_counter(
|
||||||
&mut self,
|
&mut self,
|
||||||
from_bcb: BasicCoverageBlock,
|
from_bcb: BasicCoverageBlock,
|
||||||
to_bcb: BasicCoverageBlock,
|
to_bcb: BasicCoverageBlock,
|
||||||
) -> BcbCounter {
|
) -> BcbCounter {
|
||||||
let counter = self.make_counter_inner(CounterIncrementSite::Edge { from_bcb, to_bcb });
|
self.make_counter_inner(CounterIncrementSite::Edge { from_bcb, to_bcb })
|
||||||
debug!(?from_bcb, ?to_bcb, ?counter, "edge gets a physical counter");
|
|
||||||
self.set_bcb_edge_counter(from_bcb, to_bcb, counter)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_expression(&mut self, lhs: BcbCounter, op: Op, rhs: BcbCounter) -> BcbCounter {
|
fn make_expression(&mut self, lhs: BcbCounter, op: Op, rhs: BcbCounter) -> BcbCounter {
|
||||||
@ -330,11 +324,21 @@ impl<'a> MakeBcbCounters<'a> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the set of out-edges that don't yet have edge counters.
|
// When choosing which out-edge should be given a counter expression, ignore edges that
|
||||||
|
// already have counters, or could use the existing counter of their target node.
|
||||||
|
let out_edge_has_counter = |to_bcb| {
|
||||||
|
if self.coverage_counters.bcb_edge_counters.contains_key(&(from_bcb, to_bcb)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
self.basic_coverage_blocks.sole_predecessor(to_bcb) == Some(from_bcb)
|
||||||
|
&& self.coverage_counters.bcb_counters[to_bcb].is_some()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Determine the set of out-edges that could benefit from being given an expression.
|
||||||
let candidate_successors = self.basic_coverage_blocks.successors[from_bcb]
|
let candidate_successors = self.basic_coverage_blocks.successors[from_bcb]
|
||||||
.iter()
|
.iter()
|
||||||
.copied()
|
.copied()
|
||||||
.filter(|&to_bcb| self.edge_has_no_counter(from_bcb, to_bcb))
|
.filter(|&to_bcb| !out_edge_has_counter(to_bcb))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
debug!(?candidate_successors);
|
debug!(?candidate_successors);
|
||||||
|
|
||||||
@ -371,14 +375,7 @@ impl<'a> MakeBcbCounters<'a> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
debug!("{expression_to_bcb:?} gets an expression: {expression:?}");
|
debug!("{expression_to_bcb:?} gets an expression: {expression:?}");
|
||||||
if let Some(sole_pred) = self.basic_coverage_blocks.sole_predecessor(expression_to_bcb) {
|
self.coverage_counters.set_bcb_edge_counter(from_bcb, expression_to_bcb, expression);
|
||||||
// This edge normally wouldn't get its own counter, so attach the expression
|
|
||||||
// to its target node instead, so that `edge_has_no_counter` can see it.
|
|
||||||
assert_eq!(sole_pred, from_bcb);
|
|
||||||
self.coverage_counters.set_bcb_counter(expression_to_bcb, expression);
|
|
||||||
} else {
|
|
||||||
self.coverage_counters.set_bcb_edge_counter(from_bcb, expression_to_bcb, expression);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
@ -389,6 +386,19 @@ impl<'a> MakeBcbCounters<'a> {
|
|||||||
return counter_kind;
|
return counter_kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let counter = self.make_node_counter_inner(bcb);
|
||||||
|
self.coverage_counters.set_bcb_counter(bcb, counter)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_node_counter_inner(&mut self, bcb: BasicCoverageBlock) -> BcbCounter {
|
||||||
|
// If the node's sole in-edge already has a counter, use that.
|
||||||
|
if let Some(sole_pred) = self.basic_coverage_blocks.sole_predecessor(bcb)
|
||||||
|
&& let Some(&edge_counter) =
|
||||||
|
self.coverage_counters.bcb_edge_counters.get(&(sole_pred, bcb))
|
||||||
|
{
|
||||||
|
return edge_counter;
|
||||||
|
}
|
||||||
|
|
||||||
let predecessors = self.basic_coverage_blocks.predecessors[bcb].as_slice();
|
let predecessors = self.basic_coverage_blocks.predecessors[bcb].as_slice();
|
||||||
|
|
||||||
// Handle cases where we can't compute a node's count from its in-edges:
|
// Handle cases where we can't compute a node's count from its in-edges:
|
||||||
@ -398,7 +408,9 @@ impl<'a> MakeBcbCounters<'a> {
|
|||||||
// leading to infinite recursion.
|
// leading to infinite recursion.
|
||||||
if predecessors.len() <= 1 || predecessors.contains(&bcb) {
|
if predecessors.len() <= 1 || predecessors.contains(&bcb) {
|
||||||
debug!(?bcb, ?predecessors, "node has <=1 predecessors or is its own predecessor");
|
debug!(?bcb, ?predecessors, "node has <=1 predecessors or is its own predecessor");
|
||||||
return self.coverage_counters.make_phys_node_counter(bcb);
|
let counter = self.coverage_counters.make_phys_node_counter(bcb);
|
||||||
|
debug!(?bcb, ?counter, "node gets a physical counter");
|
||||||
|
return counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A BCB with multiple incoming edges can compute its count by ensuring that counters
|
// A BCB with multiple incoming edges can compute its count by ensuring that counters
|
||||||
@ -414,7 +426,7 @@ impl<'a> MakeBcbCounters<'a> {
|
|||||||
.expect("there must be at least one in-edge");
|
.expect("there must be at least one in-edge");
|
||||||
|
|
||||||
debug!("{bcb:?} gets a new counter (sum of predecessor counters): {sum_of_in_edges:?}");
|
debug!("{bcb:?} gets a new counter (sum of predecessor counters): {sum_of_in_edges:?}");
|
||||||
self.coverage_counters.set_bcb_counter(bcb, sum_of_in_edges)
|
sum_of_in_edges
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
@ -422,6 +434,23 @@ impl<'a> MakeBcbCounters<'a> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
from_bcb: BasicCoverageBlock,
|
from_bcb: BasicCoverageBlock,
|
||||||
to_bcb: BasicCoverageBlock,
|
to_bcb: BasicCoverageBlock,
|
||||||
|
) -> BcbCounter {
|
||||||
|
// If the edge already has a counter, return it.
|
||||||
|
if let Some(&counter_kind) =
|
||||||
|
self.coverage_counters.bcb_edge_counters.get(&(from_bcb, to_bcb))
|
||||||
|
{
|
||||||
|
debug!("Edge {from_bcb:?}->{to_bcb:?} already has a counter: {counter_kind:?}");
|
||||||
|
return counter_kind;
|
||||||
|
}
|
||||||
|
|
||||||
|
let counter = self.make_edge_counter_inner(from_bcb, to_bcb);
|
||||||
|
self.coverage_counters.set_bcb_edge_counter(from_bcb, to_bcb, counter)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_edge_counter_inner(
|
||||||
|
&mut self,
|
||||||
|
from_bcb: BasicCoverageBlock,
|
||||||
|
to_bcb: BasicCoverageBlock,
|
||||||
) -> BcbCounter {
|
) -> BcbCounter {
|
||||||
// If the target node has exactly one in-edge (i.e. this one), then just
|
// If the target node has exactly one in-edge (i.e. this one), then just
|
||||||
// use the node's counter, since it will have the same value.
|
// use the node's counter, since it will have the same value.
|
||||||
@ -439,16 +468,10 @@ impl<'a> MakeBcbCounters<'a> {
|
|||||||
return self.get_or_make_node_counter(from_bcb);
|
return self.get_or_make_node_counter(from_bcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the edge already has a counter, return it.
|
|
||||||
if let Some(&counter_kind) =
|
|
||||||
self.coverage_counters.bcb_edge_counters.get(&(from_bcb, to_bcb))
|
|
||||||
{
|
|
||||||
debug!("Edge {from_bcb:?}->{to_bcb:?} already has a counter: {counter_kind:?}");
|
|
||||||
return counter_kind;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make a new counter to count this edge.
|
// Make a new counter to count this edge.
|
||||||
self.coverage_counters.make_phys_edge_counter(from_bcb, to_bcb)
|
let counter = self.coverage_counters.make_phys_edge_counter(from_bcb, to_bcb);
|
||||||
|
debug!(?from_bcb, ?to_bcb, ?counter, "edge gets a physical counter");
|
||||||
|
counter
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a set of candidate out-edges (represented by their successor node),
|
/// Given a set of candidate out-edges (represented by their successor node),
|
||||||
@ -508,21 +531,4 @@ impl<'a> MakeBcbCounters<'a> {
|
|||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn edge_has_no_counter(
|
|
||||||
&self,
|
|
||||||
from_bcb: BasicCoverageBlock,
|
|
||||||
to_bcb: BasicCoverageBlock,
|
|
||||||
) -> bool {
|
|
||||||
let edge_counter =
|
|
||||||
if let Some(sole_pred) = self.basic_coverage_blocks.sole_predecessor(to_bcb) {
|
|
||||||
assert_eq!(sole_pred, from_bcb);
|
|
||||||
self.coverage_counters.bcb_counters[to_bcb]
|
|
||||||
} else {
|
|
||||||
self.coverage_counters.bcb_edge_counters.get(&(from_bcb, to_bcb)).copied()
|
|
||||||
};
|
|
||||||
|
|
||||||
edge_counter.is_none()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user