coverage: Don't create counters for code that was removed by MIR opts
This commit is contained in:
parent
20d051ec87
commit
bf1f254b13
10 changed files with 103 additions and 134 deletions
|
@ -80,28 +80,30 @@ fn make_node_flow_priority_list(
|
|||
pub(crate) fn transcribe_counters(
|
||||
old: &NodeCounters<BasicCoverageBlock>,
|
||||
bcb_needs_counter: &DenseBitSet<BasicCoverageBlock>,
|
||||
bcbs_seen: &DenseBitSet<BasicCoverageBlock>,
|
||||
) -> CoverageCounters {
|
||||
let mut new = CoverageCounters::with_num_bcbs(bcb_needs_counter.domain_size());
|
||||
|
||||
for bcb in bcb_needs_counter.iter() {
|
||||
if !bcbs_seen.contains(bcb) {
|
||||
// This BCB's code was removed by MIR opts, so its counter is always zero.
|
||||
new.set_node_counter(bcb, CovTerm::Zero);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Our counter-creation algorithm doesn't guarantee that a node's list
|
||||
// of terms starts or ends with a positive term, so partition the
|
||||
// counters into "positive" and "negative" lists for easier handling.
|
||||
let (mut pos, mut neg): (Vec<_>, Vec<_>) =
|
||||
old.counter_terms[bcb].iter().partition_map(|&CounterTerm { node, op }| match op {
|
||||
let (mut pos, mut neg): (Vec<_>, Vec<_>) = old.counter_terms[bcb]
|
||||
.iter()
|
||||
// Filter out any BCBs that were removed by MIR opts;
|
||||
// this treats them as having an execution count of 0.
|
||||
.filter(|term| bcbs_seen.contains(term.node))
|
||||
.partition_map(|&CounterTerm { node, op }| match op {
|
||||
Op::Add => Either::Left(node),
|
||||
Op::Subtract => Either::Right(node),
|
||||
});
|
||||
|
||||
if pos.is_empty() {
|
||||
// If we somehow end up with no positive terms, fall back to
|
||||
// creating a physical counter. There's no known way for this
|
||||
// to happen, but we can avoid an ICE if it does.
|
||||
debug_assert!(false, "{bcb:?} has no positive counter terms");
|
||||
pos = vec![bcb];
|
||||
neg = vec![];
|
||||
}
|
||||
|
||||
// These intermediate sorts are not strictly necessary, but were helpful
|
||||
// in reducing churn when switching to the current counter-creation scheme.
|
||||
// They also help to slightly decrease the overall size of the expression
|
||||
|
@ -119,7 +121,7 @@ pub(crate) fn transcribe_counters(
|
|||
pos.sort();
|
||||
neg.sort();
|
||||
|
||||
let pos_counter = new.make_sum(&pos).expect("`pos` should not be empty");
|
||||
let pos_counter = new.make_sum(&pos).unwrap_or(CovTerm::Zero);
|
||||
let new_counter = new.make_subtracted_sum(pos_counter, &neg);
|
||||
new.set_node_counter(bcb, new_counter);
|
||||
}
|
||||
|
|
|
@ -127,8 +127,12 @@ fn coverage_ids_info<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME(Zalathar): It should be possible to sort `priority_list[1..]` by
|
||||
// `!bcbs_seen.contains(bcb)` to simplify the mappings even further, at the
|
||||
// expense of some churn in the tests. When doing so, also consider removing
|
||||
// the sorts in `transcribe_counters`.
|
||||
let node_counters = make_node_counters(&fn_cov_info.node_flow_data, &fn_cov_info.priority_list);
|
||||
let coverage_counters = transcribe_counters(&node_counters, &bcb_needs_counter);
|
||||
let coverage_counters = transcribe_counters(&node_counters, &bcb_needs_counter, &bcbs_seen);
|
||||
|
||||
let mut counters_seen = DenseBitSet::new_empty(coverage_counters.node_counters.len());
|
||||
let mut expressions_seen = DenseBitSet::new_filled(coverage_counters.expressions.len());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue