@@ -107,9 +107,7 @@ impl CoverageCounters {
107107 /// Creates a new physical counter attached a BCB node.
108108 /// The node must not already have a counter.
109109 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)
110+ self . make_counter_inner ( CounterIncrementSite :: Node { bcb } )
113111 }
114112
115113 /// Creates a new physical counter attached to a BCB edge.
@@ -119,9 +117,7 @@ impl CoverageCounters {
119117 from_bcb : BasicCoverageBlock ,
120118 to_bcb : BasicCoverageBlock ,
121119 ) -> 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)
120+ self . make_counter_inner ( CounterIncrementSite :: Edge { from_bcb, to_bcb } )
125121 }
126122
127123 fn make_expression ( & mut self , lhs : BcbCounter , op : Op , rhs : BcbCounter ) -> BcbCounter {
@@ -330,11 +326,21 @@ impl<'a> MakeBcbCounters<'a> {
330326 return ;
331327 }
332328
333- // Determine the set of out-edges that don't yet have edge counters.
329+ // When choosing which out-edge should be given a counter expression, ignore edges that
330+ // already have counters, or could use the existing counter of their target node.
331+ let out_edge_has_counter = |to_bcb| {
332+ if self . coverage_counters . bcb_edge_counters . contains_key ( & ( from_bcb, to_bcb) ) {
333+ return true ;
334+ }
335+ self . basic_coverage_blocks . sole_predecessor ( to_bcb) == Some ( from_bcb)
336+ && self . coverage_counters . bcb_counters [ to_bcb] . is_some ( )
337+ } ;
338+
339+ // Determine the set of out-edges that could benefit from being given an expression.
334340 let candidate_successors = self . basic_coverage_blocks . successors [ from_bcb]
335341 . iter ( )
336342 . copied ( )
337- . filter ( |& to_bcb| self . edge_has_no_counter ( from_bcb , to_bcb) )
343+ . filter ( |& to_bcb| ! out_edge_has_counter ( to_bcb) )
338344 . collect :: < Vec < _ > > ( ) ;
339345 debug ! ( ?candidate_successors) ;
340346
@@ -371,14 +377,7 @@ impl<'a> MakeBcbCounters<'a> {
371377 ) ;
372378
373379 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- }
380+ self . coverage_counters . set_bcb_edge_counter ( from_bcb, expression_to_bcb, expression) ;
382381 }
383382
384383 #[ instrument( level = "debug" , skip( self ) ) ]
@@ -389,6 +388,19 @@ impl<'a> MakeBcbCounters<'a> {
389388 return counter_kind;
390389 }
391390
391+ let counter = self . make_node_counter_inner ( bcb) ;
392+ self . coverage_counters . set_bcb_counter ( bcb, counter)
393+ }
394+
395+ fn make_node_counter_inner ( & mut self , bcb : BasicCoverageBlock ) -> BcbCounter {
396+ // If the node's sole in-edge already has a counter, use that.
397+ if let Some ( sole_pred) = self . basic_coverage_blocks . sole_predecessor ( bcb)
398+ && let Some ( & edge_counter) =
399+ self . coverage_counters . bcb_edge_counters . get ( & ( sole_pred, bcb) )
400+ {
401+ return edge_counter;
402+ }
403+
392404 let predecessors = self . basic_coverage_blocks . predecessors [ bcb] . as_slice ( ) ;
393405
394406 // Handle cases where we can't compute a node's count from its in-edges:
@@ -398,7 +410,9 @@ impl<'a> MakeBcbCounters<'a> {
398410 // leading to infinite recursion.
399411 if predecessors. len ( ) <= 1 || predecessors. contains ( & bcb) {
400412 debug ! ( ?bcb, ?predecessors, "node has <=1 predecessors or is its own predecessor" ) ;
401- return self . coverage_counters . make_phys_node_counter ( bcb) ;
413+ let counter = self . coverage_counters . make_phys_node_counter ( bcb) ;
414+ debug ! ( ?bcb, ?counter, "node gets a physical counter" ) ;
415+ return counter;
402416 }
403417
404418 // A BCB with multiple incoming edges can compute its count by ensuring that counters
@@ -414,14 +428,31 @@ impl<'a> MakeBcbCounters<'a> {
414428 . expect ( "there must be at least one in-edge" ) ;
415429
416430 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)
431+ sum_of_in_edges
418432 }
419433
420434 #[ instrument( level = "debug" , skip( self ) ) ]
421435 fn get_or_make_edge_counter (
422436 & mut self ,
423437 from_bcb : BasicCoverageBlock ,
424438 to_bcb : BasicCoverageBlock ,
439+ ) -> BcbCounter {
440+ // If the edge already has a counter, return it.
441+ if let Some ( & counter_kind) =
442+ self . coverage_counters . bcb_edge_counters . get ( & ( from_bcb, to_bcb) )
443+ {
444+ debug ! ( "Edge {from_bcb:?}->{to_bcb:?} already has a counter: {counter_kind:?}" ) ;
445+ return counter_kind;
446+ }
447+
448+ let counter = self . make_edge_counter_inner ( from_bcb, to_bcb) ;
449+ self . coverage_counters . set_bcb_edge_counter ( from_bcb, to_bcb, counter)
450+ }
451+
452+ fn make_edge_counter_inner (
453+ & mut self ,
454+ from_bcb : BasicCoverageBlock ,
455+ to_bcb : BasicCoverageBlock ,
425456 ) -> BcbCounter {
426457 // If the target node has exactly one in-edge (i.e. this one), then just
427458 // use the node's counter, since it will have the same value.
@@ -439,16 +470,10 @@ impl<'a> MakeBcbCounters<'a> {
439470 return self . get_or_make_node_counter ( from_bcb) ;
440471 }
441472
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-
450473 // Make a new counter to count this edge.
451- self . coverage_counters . make_phys_edge_counter ( from_bcb, to_bcb)
474+ let counter = self . coverage_counters . make_phys_edge_counter ( from_bcb, to_bcb) ;
475+ debug ! ( ?from_bcb, ?to_bcb, ?counter, "edge gets a physical counter" ) ;
476+ counter
452477 }
453478
454479 /// Given a set of candidate out-edges (represented by their successor node),
@@ -508,21 +533,4 @@ impl<'a> MakeBcbCounters<'a> {
508533
509534 None
510535 }
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- }
528536}
0 commit comments