@@ -107,9 +107,7 @@ impl CoverageCounters {
107
107
/// Creates a new physical counter attached a BCB node.
108
108
/// The node must not already have a counter.
109
109
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 } )
113
111
}
114
112
115
113
/// Creates a new physical counter attached to a BCB edge.
@@ -119,9 +117,7 @@ impl CoverageCounters {
119
117
from_bcb : BasicCoverageBlock ,
120
118
to_bcb : BasicCoverageBlock ,
121
119
) -> 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 } )
125
121
}
126
122
127
123
fn make_expression ( & mut self , lhs : BcbCounter , op : Op , rhs : BcbCounter ) -> BcbCounter {
@@ -330,11 +326,21 @@ impl<'a> MakeBcbCounters<'a> {
330
326
return ;
331
327
}
332
328
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.
334
340
let candidate_successors = self . basic_coverage_blocks . successors [ from_bcb]
335
341
. iter ( )
336
342
. copied ( )
337
- . filter ( |& to_bcb| self . edge_has_no_counter ( from_bcb , to_bcb) )
343
+ . filter ( |& to_bcb| ! out_edge_has_counter ( to_bcb) )
338
344
. collect :: < Vec < _ > > ( ) ;
339
345
debug ! ( ?candidate_successors) ;
340
346
@@ -371,14 +377,7 @@ impl<'a> MakeBcbCounters<'a> {
371
377
) ;
372
378
373
379
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) ;
382
381
}
383
382
384
383
#[ instrument( level = "debug" , skip( self ) ) ]
@@ -389,6 +388,19 @@ impl<'a> MakeBcbCounters<'a> {
389
388
return counter_kind;
390
389
}
391
390
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
+
392
404
let predecessors = self . basic_coverage_blocks . predecessors [ bcb] . as_slice ( ) ;
393
405
394
406
// Handle cases where we can't compute a node's count from its in-edges:
@@ -398,7 +410,9 @@ impl<'a> MakeBcbCounters<'a> {
398
410
// leading to infinite recursion.
399
411
if predecessors. len ( ) <= 1 || predecessors. contains ( & bcb) {
400
412
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;
402
416
}
403
417
404
418
// A BCB with multiple incoming edges can compute its count by ensuring that counters
@@ -414,14 +428,31 @@ impl<'a> MakeBcbCounters<'a> {
414
428
. expect ( "there must be at least one in-edge" ) ;
415
429
416
430
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
418
432
}
419
433
420
434
#[ instrument( level = "debug" , skip( self ) ) ]
421
435
fn get_or_make_edge_counter (
422
436
& mut self ,
423
437
from_bcb : BasicCoverageBlock ,
424
438
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 ,
425
456
) -> BcbCounter {
426
457
// If the target node has exactly one in-edge (i.e. this one), then just
427
458
// use the node's counter, since it will have the same value.
@@ -439,16 +470,10 @@ impl<'a> MakeBcbCounters<'a> {
439
470
return self . get_or_make_node_counter ( from_bcb) ;
440
471
}
441
472
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
-
450
473
// 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
452
477
}
453
478
454
479
/// Given a set of candidate out-edges (represented by their successor node),
@@ -508,21 +533,4 @@ impl<'a> MakeBcbCounters<'a> {
508
533
509
534
None
510
535
}
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
- }
528
536
}
0 commit comments