@@ -104,24 +104,18 @@ impl CoverageCounters {
104
104
BcbCounter :: Counter { id }
105
105
}
106
106
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.
109
108
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 } )
113
110
}
114
111
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.
117
113
fn make_phys_edge_counter (
118
114
& mut self ,
119
115
from_bcb : BasicCoverageBlock ,
120
116
to_bcb : BasicCoverageBlock ,
121
117
) -> 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 } )
125
119
}
126
120
127
121
fn make_expression ( & mut self , lhs : BcbCounter , op : Op , rhs : BcbCounter ) -> BcbCounter {
@@ -330,11 +324,21 @@ impl<'a> MakeBcbCounters<'a> {
330
324
return ;
331
325
}
332
326
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.
334
338
let candidate_successors = self . basic_coverage_blocks . successors [ from_bcb]
335
339
. iter ( )
336
340
. copied ( )
337
- . filter ( |& to_bcb| self . edge_has_no_counter ( from_bcb , to_bcb) )
341
+ . filter ( |& to_bcb| ! out_edge_has_counter ( to_bcb) )
338
342
. collect :: < Vec < _ > > ( ) ;
339
343
debug ! ( ?candidate_successors) ;
340
344
@@ -371,14 +375,7 @@ impl<'a> MakeBcbCounters<'a> {
371
375
) ;
372
376
373
377
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) ;
382
379
}
383
380
384
381
#[ instrument( level = "debug" , skip( self ) ) ]
@@ -389,6 +386,19 @@ impl<'a> MakeBcbCounters<'a> {
389
386
return counter_kind;
390
387
}
391
388
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
+
392
402
let predecessors = self . basic_coverage_blocks . predecessors [ bcb] . as_slice ( ) ;
393
403
394
404
// Handle cases where we can't compute a node's count from its in-edges:
@@ -398,7 +408,9 @@ impl<'a> MakeBcbCounters<'a> {
398
408
// leading to infinite recursion.
399
409
if predecessors. len ( ) <= 1 || predecessors. contains ( & bcb) {
400
410
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;
402
414
}
403
415
404
416
// A BCB with multiple incoming edges can compute its count by ensuring that counters
@@ -414,14 +426,31 @@ impl<'a> MakeBcbCounters<'a> {
414
426
. expect ( "there must be at least one in-edge" ) ;
415
427
416
428
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
418
430
}
419
431
420
432
#[ instrument( level = "debug" , skip( self ) ) ]
421
433
fn get_or_make_edge_counter (
422
434
& mut self ,
423
435
from_bcb : BasicCoverageBlock ,
424
436
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 ,
425
454
) -> BcbCounter {
426
455
// If the target node has exactly one in-edge (i.e. this one), then just
427
456
// use the node's counter, since it will have the same value.
@@ -439,16 +468,10 @@ impl<'a> MakeBcbCounters<'a> {
439
468
return self . get_or_make_node_counter ( from_bcb) ;
440
469
}
441
470
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
471
// 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
452
475
}
453
476
454
477
/// Given a set of candidate out-edges (represented by their successor node),
@@ -508,21 +531,4 @@ impl<'a> MakeBcbCounters<'a> {
508
531
509
532
None
510
533
}
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
534
}
0 commit comments