coverage: Simplify sorting of coverage spans extracted from MIR

Switching to `Ordering::then_with` makes control-flow less complicated, and
there is no need to use `partial_cmp` here.
This commit is contained in:
Zalathar 2023-09-17 14:21:19 +10:00
parent a4cb31bb58
commit 01b67f4b26
3 changed files with 19 additions and 36 deletions

View File

@ -51,7 +51,7 @@ pub fn dominators<G: ControlFlowGraph>(graph: &G) -> Dominators<G::Node> {
// Traverse the graph, collecting a number of things: // Traverse the graph, collecting a number of things:
// //
// * Preorder mapping (to it, and back to the actual ordering) // * Preorder mapping (to it, and back to the actual ordering)
// * Postorder mapping (used exclusively for rank_partial_cmp on the final product) // * Postorder mapping (used exclusively for `cmp_in_dominator_order` on the final product)
// * Parents for each vertex in the preorder tree // * Parents for each vertex in the preorder tree
// //
// These are all done here rather than through one of the 'standard' // These are all done here rather than through one of the 'standard'
@ -342,8 +342,8 @@ impl<Node: Idx> Dominators<Node> {
/// relationship, the dominator will always precede the dominated. (The relative ordering /// relationship, the dominator will always precede the dominated. (The relative ordering
/// of two unrelated nodes will also be consistent, but otherwise the order has no /// of two unrelated nodes will also be consistent, but otherwise the order has no
/// meaning.) This method cannot be used to determine if either Node dominates the other. /// meaning.) This method cannot be used to determine if either Node dominates the other.
pub fn rank_partial_cmp(&self, lhs: Node, rhs: Node) -> Option<Ordering> { pub fn cmp_in_dominator_order(&self, lhs: Node, rhs: Node) -> Ordering {
self.post_order_rank[rhs].partial_cmp(&self.post_order_rank[lhs]) self.post_order_rank[rhs].cmp(&self.post_order_rank[lhs])
} }
/// Returns true if `a` dominates `b`. /// Returns true if `a` dominates `b`.

View File

@ -199,12 +199,8 @@ impl CoverageGraph {
} }
#[inline(always)] #[inline(always)]
pub fn rank_partial_cmp( pub fn cmp_in_dominator_order(&self, a: BasicCoverageBlock, b: BasicCoverageBlock) -> Ordering {
&self, self.dominators.as_ref().unwrap().cmp_in_dominator_order(a, b)
a: BasicCoverageBlock,
b: BasicCoverageBlock,
) -> Option<Ordering> {
self.dominators.as_ref().unwrap().rank_partial_cmp(a, b)
} }
} }

View File

@ -12,7 +12,6 @@ use rustc_span::source_map::original_sp;
use rustc_span::{BytePos, ExpnKind, MacroKind, Span, Symbol}; use rustc_span::{BytePos, ExpnKind, MacroKind, Span, Symbol};
use std::cell::OnceCell; use std::cell::OnceCell;
use std::cmp::Ordering;
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub(super) enum CoverageStatement { pub(super) enum CoverageStatement {
@ -334,32 +333,20 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
initial_spans.push(CoverageSpan::for_fn_sig(self.fn_sig_span)); initial_spans.push(CoverageSpan::for_fn_sig(self.fn_sig_span));
initial_spans.sort_by(|a, b| { initial_spans.sort_by(|a, b| {
if a.span.lo() == b.span.lo() { // First sort by span start.
if a.span.hi() == b.span.hi() { Ord::cmp(&a.span.lo(), &b.span.lo())
if a.is_in_same_bcb(b) { // If span starts are the same, sort by span end in reverse order.
Some(Ordering::Equal) // This ensures that if spans A and B are adjacent in the list,
} else { // and they overlap but are not equal, then either:
// Sort equal spans by dominator relationship (so dominators always come // - Span A extends further left, or
// before the dominated equal spans). When later comparing two spans in // - Both have the same start and span A extends further right
// order, the first will either dominate the second, or they will have no .then_with(|| Ord::cmp(&a.span.hi(), &b.span.hi()).reverse())
// dominator relationship. // If both spans are equal, sort the BCBs in dominator order,
self.basic_coverage_blocks.rank_partial_cmp(a.bcb, b.bcb) // so that dominating BCBs come before other BCBs they dominate.
} .then_with(|| self.basic_coverage_blocks.cmp_in_dominator_order(a.bcb, b.bcb))
} else { // If two spans are otherwise identical, put closure spans first,
// Sort hi() in reverse order so shorter spans are attempted after longer spans. // as this seems to be what the refinement step expects.
// This guarantees that, if a `prev` span overlaps, and is not equal to, a .then_with(|| Ord::cmp(&a.is_closure, &b.is_closure).reverse())
// `curr` span, the prev span either extends further left of the curr span, or
// they start at the same position and the prev span extends further right of
// the end of the curr span.
b.span.hi().partial_cmp(&a.span.hi())
}
} else {
a.span.lo().partial_cmp(&b.span.lo())
}
.unwrap()
// If two spans are otherwise identical, put closure spans first,
// as this seems to be what the refinement step expects.
.then_with(|| Ord::cmp(&a.is_closure, &b.is_closure).reverse())
}); });
initial_spans initial_spans