Skip to content

Commit 8834b5a

Browse files
committed
coverage: Make CoverageSuccessors a struct
1 parent 75eff9a commit 8834b5a

File tree

1 file changed

+27
-44
lines changed
  • compiler/rustc_mir_transform/src/coverage

1 file changed

+27
-44
lines changed

compiler/rustc_mir_transform/src/coverage/graph.rs

+27-44
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::cmp::Ordering;
22
use std::collections::VecDeque;
3-
use std::iter;
43
use std::ops::{Index, IndexMut};
4+
use std::{iter, slice};
55

66
use rustc_data_structures::captures::Captures;
77
use rustc_data_structures::fx::FxHashSet;
@@ -389,34 +389,26 @@ impl BasicCoverageBlockData {
389389
/// indicates whether that block can potentially be combined into the same BCB
390390
/// as its sole successor.
391391
#[derive(Clone, Copy, Debug)]
392-
enum CoverageSuccessors<'a> {
393-
/// The terminator has exactly one straight-line successor, so its block can
394-
/// potentially be combined into the same BCB as that successor.
395-
Chainable(BasicBlock),
396-
/// The block cannot be combined into the same BCB as its successor(s).
397-
NotChainable(&'a [BasicBlock]),
398-
/// Yield terminators are not chainable, and their execution count can also
399-
/// differ from the execution count of their out-edge.
400-
Yield(BasicBlock),
392+
struct CoverageSuccessors<'a> {
393+
/// Coverage-relevant successors of the corresponding terminator.
394+
/// There might be 0, 1, or multiple targets.
395+
targets: &'a [BasicBlock],
396+
/// `Yield` terminators are not chainable, because their sole out-edge is
397+
/// only followed if/when the generator is resumed after the yield.
398+
is_yield: bool,
401399
}
402400

403401
impl CoverageSuccessors<'_> {
404402
fn is_chainable(&self) -> bool {
405-
match self {
406-
Self::Chainable(_) => true,
407-
Self::NotChainable(_) => false,
408-
Self::Yield(_) => false,
409-
}
403+
// If a terminator is out-summable and has exactly one out-edge, then
404+
// it is eligible to be chained into its successor block.
405+
self.is_out_summable() && self.targets.len() == 1
410406
}
411407

412408
/// Returns true if the terminator itself is assumed to have the same
413409
/// execution count as the sum of its out-edges (assuming no panics).
414410
fn is_out_summable(&self) -> bool {
415-
match self {
416-
Self::Chainable(_) => true,
417-
Self::NotChainable(_) => true,
418-
Self::Yield(_) => false,
419-
}
411+
!self.is_yield && !self.targets.is_empty()
420412
}
421413
}
422414

@@ -425,12 +417,7 @@ impl IntoIterator for CoverageSuccessors<'_> {
425417
type IntoIter = impl DoubleEndedIterator<Item = Self::Item>;
426418

427419
fn into_iter(self) -> Self::IntoIter {
428-
match self {
429-
Self::Chainable(bb) | Self::Yield(bb) => {
430-
Some(bb).into_iter().chain((&[]).iter().copied())
431-
}
432-
Self::NotChainable(bbs) => None.into_iter().chain(bbs.iter().copied()),
433-
}
420+
self.targets.iter().copied()
434421
}
435422
}
436423

@@ -440,48 +427,44 @@ impl IntoIterator for CoverageSuccessors<'_> {
440427
// `catch_unwind()` handlers.
441428
fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>) -> CoverageSuccessors<'a> {
442429
use TerminatorKind::*;
443-
match terminator.kind {
430+
let mut is_yield = false;
431+
let targets = match &terminator.kind {
444432
// A switch terminator can have many coverage-relevant successors.
445-
// (If there is exactly one successor, we still treat it as not chainable.)
446-
SwitchInt { ref targets, .. } => CoverageSuccessors::NotChainable(targets.all_targets()),
433+
SwitchInt { targets, .. } => targets.all_targets(),
447434

448435
// A yield terminator has exactly 1 successor, but should not be chained,
449436
// because its resume edge has a different execution count.
450-
Yield { resume, .. } => CoverageSuccessors::Yield(resume),
437+
Yield { resume, .. } => {
438+
is_yield = true;
439+
slice::from_ref(resume)
440+
}
451441

452442
// These terminators have exactly one coverage-relevant successor,
453443
// and can be chained into it.
454444
Assert { target, .. }
455445
| Drop { target, .. }
456446
| FalseEdge { real_target: target, .. }
457447
| FalseUnwind { real_target: target, .. }
458-
| Goto { target } => CoverageSuccessors::Chainable(target),
448+
| Goto { target } => slice::from_ref(target),
459449

460450
// A call terminator can normally be chained, except when it has no
461451
// successor because it is known to diverge.
462-
Call { target: maybe_target, .. } => match maybe_target {
463-
Some(target) => CoverageSuccessors::Chainable(target),
464-
None => CoverageSuccessors::NotChainable(&[]),
465-
},
452+
Call { target: maybe_target, .. } => maybe_target.as_slice(),
466453

467454
// An inline asm terminator can normally be chained, except when it
468455
// diverges or uses asm goto.
469-
InlineAsm { ref targets, .. } => {
470-
if let [target] = targets[..] {
471-
CoverageSuccessors::Chainable(target)
472-
} else {
473-
CoverageSuccessors::NotChainable(targets)
474-
}
475-
}
456+
InlineAsm { targets, .. } => &targets,
476457

477458
// These terminators have no coverage-relevant successors.
478459
CoroutineDrop
479460
| Return
480461
| TailCall { .. }
481462
| Unreachable
482463
| UnwindResume
483-
| UnwindTerminate(_) => CoverageSuccessors::NotChainable(&[]),
484-
}
464+
| UnwindTerminate(_) => &[],
465+
};
466+
467+
CoverageSuccessors { targets, is_yield }
485468
}
486469

487470
/// Maintains separate worklists for each loop in the BasicCoverageBlock CFG, plus one for the

0 commit comments

Comments
 (0)