@@ -510,18 +510,11 @@ impl<'a> MakeBcbCounters<'a> {
510
510
traversal: &TraverseCoverageGraphWithLoops,
511
511
branches: &[BcbBranch],
512
512
) -> BcbBranch {
513
- let branch_needs_a_counter = |branch: &BcbBranch| self.branch_has_no_counter(branch);
514
-
515
- let some_reloop_branch = self.find_some_reloop_branch(traversal, &branches);
516
- if let Some(reloop_branch_without_counter) =
517
- some_reloop_branch.filter(branch_needs_a_counter)
518
- {
519
- debug!(
520
- "Selecting reloop_branch={:?} that still needs a counter, to get the \
521
- `Expression`",
522
- reloop_branch_without_counter
523
- );
524
- reloop_branch_without_counter
513
+ let good_reloop_branch = self.find_good_reloop_branch(traversal, &branches);
514
+ if let Some(reloop_branch) = good_reloop_branch {
515
+ assert!(self.branch_has_no_counter(&reloop_branch));
516
+ debug!("Selecting reloop branch {reloop_branch:?} to get an expression");
517
+ reloop_branch
525
518
} else {
526
519
let &branch_without_counter =
527
520
branches.iter().find(|&branch| self.branch_has_no_counter(branch)).expect(
@@ -538,75 +531,52 @@ impl<'a> MakeBcbCounters<'a> {
538
531
}
539
532
}
540
533
541
- /// At most, one of the branches (or its edge, from the branching_bcb, if the branch has
542
- /// multiple incoming edges) can have a counter computed by expression.
543
- ///
544
- /// If at least one of the branches leads outside of a loop (`found_loop_exit` is
545
- /// true), and at least one other branch does not exit the loop (the first of which
546
- /// is captured in `some_reloop_branch`), it's likely any reloop branch will be
547
- /// executed far more often than loop exit branch, making the reloop branch a better
548
- /// candidate for an expression.
549
- fn find_some_reloop_branch(
534
+ /// Tries to find a branch that leads back to the top of a loop, and that
535
+ /// doesn't already have a counter. Such branches are good candidates to
536
+ /// be given an expression (instead of a physical counter), because they
537
+ /// will tend to be executed more times than a loop-exit branch.
538
+ fn find_good_reloop_branch(
550
539
&self,
551
540
traversal: &TraverseCoverageGraphWithLoops,
552
541
branches: &[BcbBranch],
553
542
) -> Option<BcbBranch> {
554
- let branch_needs_a_counter = |branch: &BcbBranch| self.branch_has_no_counter(branch);
555
-
556
- let mut some_reloop_branch: Option<BcbBranch> = None;
557
- for context in traversal.context_stack.iter().rev() {
558
- if let Some((backedge_from_bcbs, _)) = &context.loop_backedges {
559
- let mut found_loop_exit = false;
560
- for &branch in branches.iter() {
561
- if backedge_from_bcbs.iter().any(|&backedge_from_bcb| {
562
- self.bcb_dominates(branch.target_bcb, backedge_from_bcb)
563
- }) {
564
- if let Some(reloop_branch) = some_reloop_branch {
565
- if self.branch_has_no_counter(&reloop_branch) {
566
- // we already found a candidate reloop_branch that still
567
- // needs a counter
568
- continue;
569
- }
570
- }
571
- // The path from branch leads back to the top of the loop. Set this
572
- // branch as the `reloop_branch`. If this branch already has a
573
- // counter, and we find another reloop branch that doesn't have a
574
- // counter yet, that branch will be selected as the `reloop_branch`
575
- // instead.
576
- some_reloop_branch = Some(branch);
577
- } else {
578
- // The path from branch leads outside this loop
579
- found_loop_exit = true;
580
- }
581
- if found_loop_exit
582
- && some_reloop_branch.filter(branch_needs_a_counter).is_some()
583
- {
584
- // Found both a branch that exits the loop and a branch that returns
585
- // to the top of the loop (`reloop_branch`), and the `reloop_branch`
586
- // doesn't already have a counter.
587
- break;
543
+ // Consider each loop on the current traversal context stack, top-down.
544
+ for reloop_bcbs in traversal.reloop_bcbs_per_loop() {
545
+ let mut all_branches_exit_this_loop = true;
546
+
547
+ // Try to find a branch that doesn't exit this loop and doesn't
548
+ // already have a counter.
549
+ for &branch in branches {
550
+ // A branch is a reloop branch if it dominates any BCB that has
551
+ // an edge back to the loop header. (Other branches are exits.)
552
+ let is_reloop_branch = reloop_bcbs.iter().any(|&reloop_bcb| {
553
+ self.basic_coverage_blocks.dominates(branch.target_bcb, reloop_bcb)
554
+ });
555
+
556
+ if is_reloop_branch {
557
+ all_branches_exit_this_loop = false;
558
+ if self.branch_has_no_counter(&branch) {
559
+ // We found a good branch to be given an expression.
560
+ return Some(branch);
588
561
}
562
+ // Keep looking for another reloop branch without a counter.
563
+ } else {
564
+ // This branch exits the loop.
589
565
}
590
- if !found_loop_exit {
591
- debug!(
592
- "No branches exit the loop, so any branch without an existing \
593
- counter can have the `Expression`."
594
- );
595
- break;
596
- }
597
- if some_reloop_branch.is_some() {
598
- debug!(
599
- "Found a branch that exits the loop and a branch the loops back to \
600
- the top of the loop (`reloop_branch`). The `reloop_branch` will \
601
- get the `Expression`, as long as it still needs a counter."
602
- );
603
- break;
604
- }
605
- // else all branches exited this loop context, so run the same checks with
606
- // the outer loop(s)
607
566
}
567
+
568
+ if !all_branches_exit_this_loop {
569
+ // We found one or more reloop branches, but all of them already
570
+ // have counters. Let the caller choose one of the exit branches.
571
+ debug!("All reloop branches had counters; skip checking the other loops");
572
+ return None;
573
+ }
574
+
575
+ // All of the branches exit this loop, so keep looking for a good
576
+ // reloop branch for one of the outer loops.
608
577
}
609
- some_reloop_branch
578
+
579
+ None
610
580
}
611
581
612
582
#[inline]
@@ -652,9 +622,4 @@ impl<'a> MakeBcbCounters<'a> {
652
622
fn bcb_has_one_path_to_target(&self, bcb: BasicCoverageBlock) -> bool {
653
623
self.bcb_predecessors(bcb).len() <= 1
654
624
}
655
-
656
- #[inline]
657
- fn bcb_dominates(&self, dom: BasicCoverageBlock, node: BasicCoverageBlock) -> bool {
658
- self.basic_coverage_blocks.dominates(dom, node)
659
- }
660
625
}
0 commit comments