Skip to content

Commit ea3fb7b

Browse files
committed
coverage: Use a VecDeque for loop traversal worklists
The previous code was storing the worklist in a vector, and then selectively adding items to the start or end of the vector. That's a perfect use-case for a double-ended queue. This change also reveals that the existing code was a bit confused about which end of the worklist is the front or back. For now, items are always removed from the front of the queue (instead of the back), and code that adds items to the queue has been flipped, to preserve the existing behaviour.
1 parent d1920c5 commit ea3fb7b

File tree

1 file changed

+18
-31
lines changed
  • compiler/rustc_mir_transform/src/coverage

1 file changed

+18
-31
lines changed

compiler/rustc_mir_transform/src/coverage/graph.rs

Lines changed: 18 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_index::{IndexSlice, IndexVec};
66
use rustc_middle::mir::{self, BasicBlock, TerminatorKind};
77

88
use std::cmp::Ordering;
9+
use std::collections::VecDeque;
910
use std::ops::{Index, IndexMut};
1011

1112
/// A coverage-specific simplification of the MIR control flow graph (CFG). The `CoverageGraph`s
@@ -388,10 +389,8 @@ pub(super) struct TraversalContext {
388389
/// From one or more backedges returning to a loop header.
389390
loop_backedges: Option<(Vec<BasicCoverageBlock>, BasicCoverageBlock)>,
390391

391-
/// worklist, to be traversed, of CoverageGraph in the loop with the given loop
392-
/// backedges, such that the loop is the inner inner-most loop containing these
393-
/// CoverageGraph
394-
worklist: Vec<BasicCoverageBlock>,
392+
/// Worklist of BCBs to be processed in this context.
393+
worklist: VecDeque<BasicCoverageBlock>,
395394
}
396395

397396
pub(super) struct TraverseCoverageGraphWithLoops {
@@ -402,10 +401,11 @@ pub(super) struct TraverseCoverageGraphWithLoops {
402401

403402
impl TraverseCoverageGraphWithLoops {
404403
pub fn new(basic_coverage_blocks: &CoverageGraph) -> Self {
405-
let start_bcb = basic_coverage_blocks.start_node();
406404
let backedges = find_loop_backedges(basic_coverage_blocks);
407-
let context_stack =
408-
vec![TraversalContext { loop_backedges: None, worklist: vec![start_bcb] }];
405+
406+
let worklist = VecDeque::from([basic_coverage_blocks.start_node()]);
407+
let context_stack = vec![TraversalContext { loop_backedges: None, worklist }];
408+
409409
// `context_stack` starts with a `TraversalContext` for the main function context (beginning
410410
// with the `start` BasicCoverageBlock of the function). New worklists are pushed to the top
411411
// of the stack as loops are entered, and popped off of the stack when a loop's worklist is
@@ -431,7 +431,7 @@ impl TraverseCoverageGraphWithLoops {
431431
);
432432

433433
while let Some(context) = self.context_stack.last_mut() {
434-
if let Some(bcb) = context.worklist.pop() {
434+
if let Some(bcb) = context.worklist.pop_front() {
435435
if !self.visited.insert(bcb) {
436436
debug!("Already visited: {bcb:?}");
437437
continue;
@@ -442,7 +442,7 @@ impl TraverseCoverageGraphWithLoops {
442442
debug!("{bcb:?} is a loop header! Start a new TraversalContext...");
443443
self.context_stack.push(TraversalContext {
444444
loop_backedges: Some((self.backedges[bcb].clone(), bcb)),
445-
worklist: Vec::new(),
445+
worklist: VecDeque::new(),
446446
});
447447
}
448448
self.extend_worklist(basic_coverage_blocks, bcb);
@@ -484,7 +484,7 @@ impl TraverseCoverageGraphWithLoops {
484484
// blocks with only one successor, to prevent unnecessarily complicating
485485
// `Expression`s by creating a Counter in a `BasicCoverageBlock` that the
486486
// branching block would have given an `Expression` (or vice versa).
487-
let (some_successor_to_add, some_loop_header) =
487+
let (some_successor_to_add, _) =
488488
if let Some((_, loop_header)) = context.loop_backedges {
489489
if basic_coverage_blocks.dominates(loop_header, successor) {
490490
(Some(successor), Some(loop_header))
@@ -494,30 +494,17 @@ impl TraverseCoverageGraphWithLoops {
494494
} else {
495495
(Some(successor), None)
496496
};
497+
498+
// FIXME: The code below had debug messages claiming to add items to a
499+
// particular end of the worklist, but was confused about which end was
500+
// which. The existing behaviour has been preserved for now, but it's
501+
// unclear what the intended behaviour was.
502+
497503
if let Some(successor_to_add) = some_successor_to_add {
498504
if basic_coverage_blocks.successors[successor_to_add].len() > 1 {
499-
debug!(
500-
"{:?} successor is branching. Prioritize it at the beginning of \
501-
the {}",
502-
successor_to_add,
503-
if let Some(loop_header) = some_loop_header {
504-
format!("worklist for the loop headed by {loop_header:?}")
505-
} else {
506-
String::from("non-loop worklist")
507-
},
508-
);
509-
context.worklist.insert(0, successor_to_add);
505+
context.worklist.push_back(successor_to_add);
510506
} else {
511-
debug!(
512-
"{:?} successor is non-branching. Defer it to the end of the {}",
513-
successor_to_add,
514-
if let Some(loop_header) = some_loop_header {
515-
format!("worklist for the loop headed by {loop_header:?}")
516-
} else {
517-
String::from("non-loop worklist")
518-
},
519-
);
520-
context.worklist.push(successor_to_add);
507+
context.worklist.push_front(successor_to_add);
521508
}
522509
break;
523510
}

0 commit comments

Comments
 (0)