Rollup merge of #136957 - Zalathar:counters, r=oli-obk
coverage: Eliminate more counters by giving them to unreachable nodes When preparing a function's coverage counters and metadata during codegen, any part of the original coverage graph that was removed by MIR optimizations can be treated as having an execution count of zero. Somewhat counter-intuitively, if we give those unreachable nodes a _higher_ priority for receiving physical counters (instead of counter expressions), that ends up reducing the total number of physical counters needed. This works because if a node is unreachable, we don't actually create a physical counter for it. Instead that node gets a fixed zero counter, and any other node that would have relied on that physical counter in its counter expression can just ignore that term completely.
This commit is contained in:
commit
d82ec95083
11 changed files with 237 additions and 229 deletions
|
@ -114,12 +114,8 @@ pub(crate) fn transcribe_counters(
|
|||
let mut new_counters_for_sites = |sites: Vec<BasicCoverageBlock>| {
|
||||
sites.into_iter().map(|node| new.ensure_phys_counter(node)).collect::<Vec<_>>()
|
||||
};
|
||||
let mut pos = new_counters_for_sites(pos);
|
||||
let mut neg = new_counters_for_sites(neg);
|
||||
|
||||
// These sorts are also not strictly necessary; see above.
|
||||
pos.sort();
|
||||
neg.sort();
|
||||
let pos = new_counters_for_sites(pos);
|
||||
let neg = new_counters_for_sites(neg);
|
||||
|
||||
let pos_counter = new.make_sum(&pos).unwrap_or(CovTerm::Zero);
|
||||
let new_counter = new.make_subtracted_sum(pos_counter, &neg);
|
||||
|
|
|
@ -123,11 +123,20 @@ 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);
|
||||
// Clone the priority list so that we can re-sort it.
|
||||
let mut priority_list = fn_cov_info.priority_list.clone();
|
||||
// The first ID in the priority list represents the synthetic "sink" node,
|
||||
// and must remain first so that it _never_ gets a physical counter.
|
||||
debug_assert_eq!(priority_list[0], priority_list.iter().copied().max().unwrap());
|
||||
assert!(!bcbs_seen.contains(priority_list[0]));
|
||||
// Partition the priority list, so that unreachable nodes (removed by MIR opts)
|
||||
// are sorted later and therefore are _more_ likely to get a physical counter.
|
||||
// This is counter-intuitive, but it means that `transcribe_counters` can
|
||||
// easily skip those unused physical counters and replace them with zero.
|
||||
// (The original ordering remains in effect within both partitions.)
|
||||
priority_list[1..].sort_by_key(|&bcb| !bcbs_seen.contains(bcb));
|
||||
|
||||
let node_counters = make_node_counters(&fn_cov_info.node_flow_data, &priority_list);
|
||||
let coverage_counters = transcribe_counters(&node_counters, &bcb_needs_counter, &bcbs_seen);
|
||||
|
||||
let CoverageCounters {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue