@@ -104,24 +104,18 @@ impl CoverageCounters {
104104 BcbCounter :: Counter { id }
105105 }
106106
107- /// Creates a new physical counter attached a BCB node.
108- /// The node must not already have a counter.
107+ /// Creates a new physical counter for a BCB node.
109108 fn make_phys_node_counter ( & mut self , bcb : BasicCoverageBlock ) -> BcbCounter {
110- let counter = self . make_counter_inner ( CounterIncrementSite :: Node { bcb } ) ;
111- debug ! ( ?bcb, ?counter, "node gets a physical counter" ) ;
112- self . set_bcb_counter ( bcb, counter)
109+ self . make_counter_inner ( CounterIncrementSite :: Node { bcb } )
113110 }
114111
115- /// Creates a new physical counter attached to a BCB edge.
116- /// The edge must not already have a counter.
112+ /// Creates a new physical counter for a BCB edge.
117113 fn make_phys_edge_counter (
118114 & mut self ,
119115 from_bcb : BasicCoverageBlock ,
120116 to_bcb : BasicCoverageBlock ,
121117 ) -> BcbCounter {
122- let counter = self . make_counter_inner ( CounterIncrementSite :: Edge { from_bcb, to_bcb } ) ;
123- debug ! ( ?from_bcb, ?to_bcb, ?counter, "edge gets a physical counter" ) ;
124- self . set_bcb_edge_counter ( from_bcb, to_bcb, counter)
118+ self . make_counter_inner ( CounterIncrementSite :: Edge { from_bcb, to_bcb } )
125119 }
126120
127121 fn make_expression ( & mut self , lhs : BcbCounter , op : Op , rhs : BcbCounter ) -> BcbCounter {
@@ -330,11 +324,21 @@ impl<'a> MakeBcbCounters<'a> {
330324 return ;
331325 }
332326
333- // Determine the set of out-edges that don't yet have edge counters.
327+ // When choosing which out-edge should be given a counter expression, ignore edges that
328+ // already have counters, or could use the existing counter of their target node.
329+ let out_edge_has_counter = |to_bcb| {
330+ if self . coverage_counters . bcb_edge_counters . contains_key ( & ( from_bcb, to_bcb) ) {
331+ return true ;
332+ }
333+ self . basic_coverage_blocks . sole_predecessor ( to_bcb) == Some ( from_bcb)
334+ && self . coverage_counters . bcb_counters [ to_bcb] . is_some ( )
335+ } ;
336+
337+ // Determine the set of out-edges that could benefit from being given an expression.
334338 let candidate_successors = self . basic_coverage_blocks . successors [ from_bcb]
335339 . iter ( )
336340 . copied ( )
337- . filter ( |& to_bcb| self . edge_has_no_counter ( from_bcb , to_bcb) )
341+ . filter ( |& to_bcb| ! out_edge_has_counter ( to_bcb) )
338342 . collect :: < Vec < _ > > ( ) ;
339343 debug ! ( ?candidate_successors) ;
340344
@@ -371,14 +375,7 @@ impl<'a> MakeBcbCounters<'a> {
371375 ) ;
372376
373377 debug ! ( "{expression_to_bcb:?} gets an expression: {expression:?}" ) ;
374- if let Some ( sole_pred) = self . basic_coverage_blocks . sole_predecessor ( expression_to_bcb) {
375- // This edge normally wouldn't get its own counter, so attach the expression
376- // to its target node instead, so that `edge_has_no_counter` can see it.
377- assert_eq ! ( sole_pred, from_bcb) ;
378- self . coverage_counters . set_bcb_counter ( expression_to_bcb, expression) ;
379- } else {
380- self . coverage_counters . set_bcb_edge_counter ( from_bcb, expression_to_bcb, expression) ;
381- }
378+ self . coverage_counters . set_bcb_edge_counter ( from_bcb, expression_to_bcb, expression) ;
382379 }
383380
384381 #[ instrument( level = "debug" , skip( self ) ) ]
@@ -389,6 +386,19 @@ impl<'a> MakeBcbCounters<'a> {
389386 return counter_kind;
390387 }
391388
389+ let counter = self . make_node_counter_inner ( bcb) ;
390+ self . coverage_counters . set_bcb_counter ( bcb, counter)
391+ }
392+
393+ fn make_node_counter_inner ( & mut self , bcb : BasicCoverageBlock ) -> BcbCounter {
394+ // If the node's sole in-edge already has a counter, use that.
395+ if let Some ( sole_pred) = self . basic_coverage_blocks . sole_predecessor ( bcb)
396+ && let Some ( & edge_counter) =
397+ self . coverage_counters . bcb_edge_counters . get ( & ( sole_pred, bcb) )
398+ {
399+ return edge_counter;
400+ }
401+
392402 let predecessors = self . basic_coverage_blocks . predecessors [ bcb] . as_slice ( ) ;
393403
394404 // Handle cases where we can't compute a node's count from its in-edges:
@@ -398,7 +408,9 @@ impl<'a> MakeBcbCounters<'a> {
398408 // leading to infinite recursion.
399409 if predecessors. len ( ) <= 1 || predecessors. contains ( & bcb) {
400410 debug ! ( ?bcb, ?predecessors, "node has <=1 predecessors or is its own predecessor" ) ;
401- return self . coverage_counters . make_phys_node_counter ( bcb) ;
411+ let counter = self . coverage_counters . make_phys_node_counter ( bcb) ;
412+ debug ! ( ?bcb, ?counter, "node gets a physical counter" ) ;
413+ return counter;
402414 }
403415
404416 // A BCB with multiple incoming edges can compute its count by ensuring that counters
@@ -414,14 +426,31 @@ impl<'a> MakeBcbCounters<'a> {
414426 . expect ( "there must be at least one in-edge" ) ;
415427
416428 debug ! ( "{bcb:?} gets a new counter (sum of predecessor counters): {sum_of_in_edges:?}" ) ;
417- self . coverage_counters . set_bcb_counter ( bcb , sum_of_in_edges)
429+ sum_of_in_edges
418430 }
419431
420432 #[ instrument( level = "debug" , skip( self ) ) ]
421433 fn get_or_make_edge_counter (
422434 & mut self ,
423435 from_bcb : BasicCoverageBlock ,
424436 to_bcb : BasicCoverageBlock ,
437+ ) -> BcbCounter {
438+ // If the edge already has a counter, return it.
439+ if let Some ( & counter_kind) =
440+ self . coverage_counters . bcb_edge_counters . get ( & ( from_bcb, to_bcb) )
441+ {
442+ debug ! ( "Edge {from_bcb:?}->{to_bcb:?} already has a counter: {counter_kind:?}" ) ;
443+ return counter_kind;
444+ }
445+
446+ let counter = self . make_edge_counter_inner ( from_bcb, to_bcb) ;
447+ self . coverage_counters . set_bcb_edge_counter ( from_bcb, to_bcb, counter)
448+ }
449+
450+ fn make_edge_counter_inner (
451+ & mut self ,
452+ from_bcb : BasicCoverageBlock ,
453+ to_bcb : BasicCoverageBlock ,
425454 ) -> BcbCounter {
426455 // If the target node has exactly one in-edge (i.e. this one), then just
427456 // use the node's counter, since it will have the same value.
@@ -439,16 +468,10 @@ impl<'a> MakeBcbCounters<'a> {
439468 return self . get_or_make_node_counter ( from_bcb) ;
440469 }
441470
442- // If the edge already has a counter, return it.
443- if let Some ( & counter_kind) =
444- self . coverage_counters . bcb_edge_counters . get ( & ( from_bcb, to_bcb) )
445- {
446- debug ! ( "Edge {from_bcb:?}->{to_bcb:?} already has a counter: {counter_kind:?}" ) ;
447- return counter_kind;
448- }
449-
450471 // Make a new counter to count this edge.
451- self . coverage_counters . make_phys_edge_counter ( from_bcb, to_bcb)
472+ let counter = self . coverage_counters . make_phys_edge_counter ( from_bcb, to_bcb) ;
473+ debug ! ( ?from_bcb, ?to_bcb, ?counter, "edge gets a physical counter" ) ;
474+ counter
452475 }
453476
454477 /// Given a set of candidate out-edges (represented by their successor node),
@@ -508,21 +531,4 @@ impl<'a> MakeBcbCounters<'a> {
508531
509532 None
510533 }
511-
512- #[ inline]
513- fn edge_has_no_counter (
514- & self ,
515- from_bcb : BasicCoverageBlock ,
516- to_bcb : BasicCoverageBlock ,
517- ) -> bool {
518- let edge_counter =
519- if let Some ( sole_pred) = self . basic_coverage_blocks . sole_predecessor ( to_bcb) {
520- assert_eq ! ( sole_pred, from_bcb) ;
521- self . coverage_counters . bcb_counters [ to_bcb]
522- } else {
523- self . coverage_counters . bcb_edge_counters . get ( & ( from_bcb, to_bcb) ) . copied ( )
524- } ;
525-
526- edge_counter. is_none ( )
527- }
528534}
0 commit comments