1- use  super :: graph; 
2- 
3- use  graph:: { BasicCoverageBlock ,  BcbBranch ,  CoverageGraph ,  TraverseCoverageGraphWithLoops } ; 
4- 
51use  rustc_data_structures:: fx:: FxHashMap ; 
62use  rustc_data_structures:: graph:: WithNumNodes ; 
73use  rustc_index:: bit_set:: BitSet ; 
84use  rustc_index:: IndexVec ; 
95use  rustc_middle:: mir:: coverage:: * ; 
106
7+ use  super :: graph:: { BasicCoverageBlock ,  CoverageGraph ,  TraverseCoverageGraphWithLoops } ; 
8+ 
119use  std:: fmt:: { self ,  Debug } ; 
1210
1311/// The coverage counter or counter expression associated with a particular 
@@ -257,49 +255,46 @@ impl<'a> MakeBcbCounters<'a> {
257255        // We might also use its term later to compute one of the branch counters. 
258256        let  from_bcb_operand = self . get_or_make_counter_operand ( from_bcb) ; 
259257
260-         let  branches  = self . bcb_branches ( from_bcb) ; 
258+         let  branch_target_bcbs  = self . basic_coverage_blocks . successors [ from_bcb] . as_slice ( ) ; 
261259
262260        // If this node doesn't have multiple out-edges, or all of its out-edges 
263261        // already have counters, then we don't need to create edge counters. 
264-         let  needs_branch_counters =
265-             branches. len ( )  > 1  && branches. iter ( ) . any ( |branch| self . branch_has_no_counter ( branch) ) ; 
262+         let  needs_branch_counters = branch_target_bcbs. len ( )  > 1 
263+             && branch_target_bcbs
264+                 . iter ( ) 
265+                 . any ( |& to_bcb| self . branch_has_no_counter ( from_bcb,  to_bcb) ) ; 
266266        if  !needs_branch_counters { 
267267            return ; 
268268        } 
269269
270270        debug ! ( 
271271            "{from_bcb:?} has some branch(es) without counters:\n   {}" , 
272-             branches 
272+             branch_target_bcbs 
273273                . iter( ) 
274-                 . map( |branch| {  format!( "{:?}: {:?}" ,  branch,  self . branch_counter( branch) )  } ) 
274+                 . map( |& to_bcb| { 
275+                     format!( "{from_bcb:?}->{to_bcb:?}: {:?}" ,  self . branch_counter( from_bcb,  to_bcb) ) 
276+                 } ) 
275277                . collect:: <Vec <_>>( ) 
276278                . join( "\n   " ) , 
277279        ) ; 
278280
279-         // Use the `traversal` state to decide if a subset of the branches exit a loop, making it 
280-         // likely that branch is executed less than branches that do not exit the same loop. In this 
281-         // case, any branch that does not exit the loop (and has not already been assigned a 
282-         // counter) should be counted by expression, if possible. (If a preferred expression branch 
283-         // is not selected based on the loop context, select any branch without an existing 
284-         // counter.) 
285-         let  expression_branch = self . choose_preferred_expression_branch ( traversal,  & branches) ; 
281+         // Of the branch edges that don't have counters yet, one can be given an expression 
282+         // (computed from the other edges) instead of a dedicated counter. 
283+         let  expression_to_bcb = self . choose_preferred_expression_branch ( traversal,  from_bcb) ; 
286284
287285        // For each branch arm other than the one that was chosen to get an expression, 
288286        // ensure that it has a counter (existing counter/expression or a new counter), 
289287        // and accumulate the corresponding terms into a single sum term. 
290288        let  sum_of_all_other_branches:  BcbCounter  = { 
291-             let  _span = debug_span ! ( "sum_of_all_other_branches" ,  ?expression_branch) . entered ( ) ; 
292-             branches
293-                 . into_iter ( ) 
289+             let  _span = debug_span ! ( "sum_of_all_other_branches" ,  ?expression_to_bcb) . entered ( ) ; 
290+             branch_target_bcbs
291+                 . iter ( ) 
292+                 . copied ( ) 
294293                // Skip the chosen branch, since we'll calculate it from the other branches. 
295-                 . filter ( |branch| branch != & expression_branch) 
296-                 . fold ( None ,  |accum,  branch| { 
297-                     let  _span = debug_span ! ( "branch" ,  ?accum,  ?branch) . entered ( ) ; 
298-                     let  branch_counter = if  branch. is_only_path_to_target ( )  { 
299-                         self . get_or_make_counter_operand ( branch. target_bcb ) 
300-                     }  else  { 
301-                         self . get_or_make_edge_counter_operand ( from_bcb,  branch. target_bcb ) 
302-                     } ; 
294+                 . filter ( |& to_bcb| to_bcb != expression_to_bcb) 
295+                 . fold ( None ,  |accum,  to_bcb| { 
296+                     let  _span = debug_span ! ( "to_bcb" ,  ?accum,  ?to_bcb) . entered ( ) ; 
297+                     let  branch_counter = self . get_or_make_edge_counter_operand ( from_bcb,  to_bcb) ; 
303298                    Some ( self . coverage_counters . make_sum_expression ( accum,  branch_counter) ) 
304299                } ) 
305300                . expect ( "there must be at least one other branch" ) 
@@ -309,22 +304,20 @@ impl<'a> MakeBcbCounters<'a> {
309304        // by taking the count of the node we're branching from, and subtracting the 
310305        // sum of all the other branches. 
311306        debug ! ( 
312-             "Making an expression for the selected expression_branch: {:?} \  
313- , 
314-             expression_branch, 
315-             self . bcb_predecessors( expression_branch. target_bcb) , 
307+             "Making an expression for the selected expression_branch: \  
308+ , 
309+             self . bcb_predecessors( expression_to_bcb) , 
316310        ) ; 
317311        let  expression = self . coverage_counters . make_expression ( 
318312            from_bcb_operand, 
319313            Op :: Subtract , 
320314            sum_of_all_other_branches, 
321315        ) ; 
322-         debug ! ( "{:?} gets an expression: {:?}" ,  expression_branch,  expression) ; 
323-         let  bcb = expression_branch. target_bcb ; 
324-         if  expression_branch. is_only_path_to_target ( )  { 
325-             self . coverage_counters . set_bcb_counter ( bcb,  expression) ; 
316+         debug ! ( "{expression_to_bcb:?} gets an expression: {expression:?}" ) ; 
317+         if  self . basic_coverage_blocks . bcb_has_multiple_in_edges ( expression_to_bcb)  { 
318+             self . coverage_counters . set_bcb_edge_counter ( from_bcb,  expression_to_bcb,  expression) ; 
326319        }  else  { 
327-             self . coverage_counters . set_bcb_edge_counter ( from_bcb ,  bcb ,  expression) ; 
320+             self . coverage_counters . set_bcb_counter ( expression_to_bcb ,  expression) ; 
328321        } 
329322    } 
330323
@@ -381,10 +374,16 @@ impl<'a> MakeBcbCounters<'a> {
381374        from_bcb :  BasicCoverageBlock , 
382375        to_bcb :  BasicCoverageBlock , 
383376    )  -> BcbCounter  { 
377+         // If the target BCB has only one in-edge (i.e. this one), then create 
378+         // a node counter instead, since it will have the same value. 
379+         if  !self . basic_coverage_blocks . bcb_has_multiple_in_edges ( to_bcb)  { 
380+             assert_eq ! ( [ from_bcb] . as_slice( ) ,  self . basic_coverage_blocks. predecessors[ to_bcb] ) ; 
381+             return  self . get_or_make_counter_operand ( to_bcb) ; 
382+         } 
383+ 
384384        // If the source BCB has only one successor (assumed to be the given target), an edge 
385385        // counter is unnecessary. Just get or make a counter for the source BCB. 
386-         let  successors = self . bcb_successors ( from_bcb) . iter ( ) ; 
387-         if  successors. len ( )  == 1  { 
386+         if  self . bcb_successors ( from_bcb) . len ( )  == 1  { 
388387            return  self . get_or_make_counter_operand ( from_bcb) ; 
389388        } 
390389
@@ -407,16 +406,19 @@ impl<'a> MakeBcbCounters<'a> {
407406fn  choose_preferred_expression_branch ( 
408407        & self , 
409408        traversal :  & TraverseCoverageGraphWithLoops < ' _ > , 
410-         branches :   & [ BcbBranch ] , 
411-     )  -> BcbBranch  { 
412-         let  good_reloop_branch = self . find_good_reloop_branch ( traversal,  & branches ) ; 
413-         if  let  Some ( reloop_branch )  = good_reloop_branch { 
414-             assert ! ( self . branch_has_no_counter( & reloop_branch ) ) ; 
415-             debug ! ( "Selecting reloop branch {reloop_branch :?} to get an expression" ) ; 
416-             reloop_branch 
409+         from_bcb :   BasicCoverageBlock , 
410+     )  -> BasicCoverageBlock  { 
411+         let  good_reloop_branch = self . find_good_reloop_branch ( traversal,  from_bcb ) ; 
412+         if  let  Some ( reloop_target )  = good_reloop_branch { 
413+             assert ! ( self . branch_has_no_counter( from_bcb ,  reloop_target ) ) ; 
414+             debug ! ( "Selecting reloop target {reloop_target :?} to get an expression" ) ; 
415+             reloop_target 
417416        }  else  { 
418-             let  & branch_without_counter =
419-                 branches. iter ( ) . find ( |& branch| self . branch_has_no_counter ( branch) ) . expect ( 
417+             let  & branch_without_counter = self 
418+                 . bcb_successors ( from_bcb) 
419+                 . iter ( ) 
420+                 . find ( |& & to_bcb| self . branch_has_no_counter ( from_bcb,  to_bcb) ) 
421+                 . expect ( 
420422                    "needs_branch_counters was `true` so there should be at least one \  
421423, 
422424                ) ; 
@@ -437,26 +439,28 @@ impl<'a> MakeBcbCounters<'a> {
437439fn  find_good_reloop_branch ( 
438440        & self , 
439441        traversal :  & TraverseCoverageGraphWithLoops < ' _ > , 
440-         branches :  & [ BcbBranch ] , 
441-     )  -> Option < BcbBranch >  { 
442+         from_bcb :  BasicCoverageBlock , 
443+     )  -> Option < BasicCoverageBlock >  { 
444+         let  branch_target_bcbs = self . bcb_successors ( from_bcb) ; 
445+ 
442446        // Consider each loop on the current traversal context stack, top-down. 
443447        for  reloop_bcbs in  traversal. reloop_bcbs_per_loop ( )  { 
444448            let  mut  all_branches_exit_this_loop = true ; 
445449
446450            // Try to find a branch that doesn't exit this loop and doesn't 
447451            // already have a counter. 
448-             for  & branch  in  branches  { 
452+             for  & branch_target_bcb  in  branch_target_bcbs  { 
449453                // A branch is a reloop branch if it dominates any BCB that has 
450454                // an edge back to the loop header. (Other branches are exits.) 
451455                let  is_reloop_branch = reloop_bcbs. iter ( ) . any ( |& reloop_bcb| { 
452-                     self . basic_coverage_blocks . dominates ( branch . target_bcb ,  reloop_bcb) 
456+                     self . basic_coverage_blocks . dominates ( branch_target_bcb ,  reloop_bcb) 
453457                } ) ; 
454458
455459                if  is_reloop_branch { 
456460                    all_branches_exit_this_loop = false ; 
457-                     if  self . branch_has_no_counter ( & branch )  { 
461+                     if  self . branch_has_no_counter ( from_bcb ,  branch_target_bcb )  { 
458462                        // We found a good branch to be given an expression. 
459-                         return  Some ( branch ) ; 
463+                         return  Some ( branch_target_bcb ) ; 
460464                    } 
461465                    // Keep looking for another reloop branch without a counter. 
462466                }  else  { 
@@ -489,20 +493,20 @@ impl<'a> MakeBcbCounters<'a> {
489493    } 
490494
491495    #[ inline]  
492-     fn  bcb_branches ( & self ,  from_bcb :  BasicCoverageBlock )  -> Vec < BcbBranch >  { 
493-         self . bcb_successors ( from_bcb) 
494-             . iter ( ) 
495-             . map ( |& to_bcb| BcbBranch :: from_to ( from_bcb,  to_bcb,  & self . basic_coverage_blocks ) ) 
496-             . collect :: < Vec < _ > > ( ) 
497-     } 
498- 
499-     fn  branch_has_no_counter ( & self ,  branch :  & BcbBranch )  -> bool  { 
500-         self . branch_counter ( branch) . is_none ( ) 
496+     fn  branch_has_no_counter ( 
497+         & self , 
498+         from_bcb :  BasicCoverageBlock , 
499+         to_bcb :  BasicCoverageBlock , 
500+     )  -> bool  { 
501+         self . branch_counter ( from_bcb,  to_bcb) . is_none ( ) 
501502    } 
502503
503-     fn  branch_counter ( & self ,  branch :  & BcbBranch )  -> Option < & BcbCounter >  { 
504-         let  to_bcb = branch. target_bcb ; 
505-         if  let  Some ( from_bcb)  = branch. edge_from_bcb  { 
504+     fn  branch_counter ( 
505+         & self , 
506+         from_bcb :  BasicCoverageBlock , 
507+         to_bcb :  BasicCoverageBlock , 
508+     )  -> Option < & BcbCounter >  { 
509+         if  self . basic_coverage_blocks . bcb_has_multiple_in_edges ( to_bcb)  { 
506510            self . coverage_counters . bcb_edge_counters . get ( & ( from_bcb,  to_bcb) ) 
507511        }  else  { 
508512            self . coverage_counters . bcb_counters [ to_bcb] . as_ref ( ) 
0 commit comments