28
28
//! return.
29
29
30
30
use crate :: MirPass ;
31
- use rustc_data_structures:: fx:: { FxHashSet , FxIndexSet } ;
31
+ use rustc_data_structures:: fx:: FxIndexSet ;
32
32
use rustc_index:: { Idx , IndexSlice , IndexVec } ;
33
- use rustc_middle:: mir:: coverage:: * ;
34
33
use rustc_middle:: mir:: visit:: { MutVisitor , MutatingUseContext , PlaceContext , Visitor } ;
35
34
use rustc_middle:: mir:: * ;
36
35
use rustc_middle:: ty:: TyCtxt ;
@@ -336,15 +335,14 @@ pub fn remove_duplicate_unreachable_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut B
336
335
}
337
336
}
338
337
339
- pub fn remove_dead_blocks < ' tcx > ( tcx : TyCtxt < ' tcx > , body : & mut Body < ' tcx > ) {
338
+ pub fn remove_dead_blocks < ' tcx > ( _tcx : TyCtxt < ' tcx > , body : & mut Body < ' tcx > ) {
340
339
let reachable = traversal:: reachable_as_bitset ( body) ;
341
340
let num_blocks = body. basic_blocks . len ( ) ;
342
341
if num_blocks == reachable. count ( ) {
343
342
return ;
344
343
}
345
344
346
345
let basic_blocks = body. basic_blocks . as_mut ( ) ;
347
- let source_scopes = & body. source_scopes ;
348
346
let mut replacements: Vec < _ > = ( 0 ..num_blocks) . map ( BasicBlock :: new) . collect ( ) ;
349
347
let mut used_blocks = 0 ;
350
348
for alive_index in reachable. iter ( ) {
@@ -358,10 +356,6 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
358
356
used_blocks += 1 ;
359
357
}
360
358
361
- if tcx. sess . instrument_coverage ( ) {
362
- save_unreachable_coverage ( basic_blocks, source_scopes, used_blocks) ;
363
- }
364
-
365
359
basic_blocks. raw . truncate ( used_blocks) ;
366
360
367
361
for block in basic_blocks {
@@ -371,93 +365,6 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
371
365
}
372
366
}
373
367
374
- /// Some MIR transforms can determine at compile time that a sequences of
375
- /// statements will never be executed, so they can be dropped from the MIR.
376
- /// For example, an `if` or `else` block that is guaranteed to never be executed
377
- /// because its condition can be evaluated at compile time, such as by const
378
- /// evaluation: `if false { ... }`.
379
- ///
380
- /// Those statements are bypassed by redirecting paths in the CFG around the
381
- /// `dead blocks`; but with `-C instrument-coverage`, the dead blocks usually
382
- /// include `Coverage` statements representing the Rust source code regions to
383
- /// be counted at runtime. Without these `Coverage` statements, the regions are
384
- /// lost, and the Rust source code will show no coverage information.
385
- ///
386
- /// What we want to show in a coverage report is the dead code with coverage
387
- /// counts of `0`. To do this, we need to save the code regions, by injecting
388
- /// `Unreachable` coverage statements. These are non-executable statements whose
389
- /// code regions are still recorded in the coverage map, representing regions
390
- /// with `0` executions.
391
- ///
392
- /// If there are no live `Counter` `Coverage` statements remaining, we remove
393
- /// `Coverage` statements along with the dead blocks. Since at least one
394
- /// counter per function is required by LLVM (and necessary, to add the
395
- /// `function_hash` to the counter's call to the LLVM intrinsic
396
- /// `instrprof.increment()`).
397
- ///
398
- /// The `generator::StateTransform` MIR pass and MIR inlining can create
399
- /// atypical conditions, where all live `Counter`s are dropped from the MIR.
400
- ///
401
- /// With MIR inlining we can have coverage counters belonging to different
402
- /// instances in a single body, so the strategy described above is applied to
403
- /// coverage counters from each instance individually.
404
- fn save_unreachable_coverage (
405
- basic_blocks : & mut IndexSlice < BasicBlock , BasicBlockData < ' _ > > ,
406
- source_scopes : & IndexSlice < SourceScope , SourceScopeData < ' _ > > ,
407
- first_dead_block : usize ,
408
- ) {
409
- // Identify instances that still have some live coverage counters left.
410
- let mut live = FxHashSet :: default ( ) ;
411
- for basic_block in & basic_blocks. raw [ 0 ..first_dead_block] {
412
- for statement in & basic_block. statements {
413
- let StatementKind :: Coverage ( coverage) = & statement. kind else { continue } ;
414
- let CoverageKind :: Counter { .. } = coverage. kind else { continue } ;
415
- let instance = statement. source_info . scope . inlined_instance ( source_scopes) ;
416
- live. insert ( instance) ;
417
- }
418
- }
419
-
420
- for block in & mut basic_blocks. raw [ ..first_dead_block] {
421
- for statement in & mut block. statements {
422
- let StatementKind :: Coverage ( _) = & statement. kind else { continue } ;
423
- let instance = statement. source_info . scope . inlined_instance ( source_scopes) ;
424
- if !live. contains ( & instance) {
425
- statement. make_nop ( ) ;
426
- }
427
- }
428
- }
429
-
430
- if live. is_empty ( ) {
431
- return ;
432
- }
433
-
434
- // Retain coverage for instances that still have some live counters left.
435
- let mut retained_coverage = Vec :: new ( ) ;
436
- for dead_block in & basic_blocks. raw [ first_dead_block..] {
437
- for statement in & dead_block. statements {
438
- let StatementKind :: Coverage ( coverage) = & statement. kind else { continue } ;
439
- if coverage. code_regions . is_empty ( ) {
440
- continue ;
441
- } ;
442
- let instance = statement. source_info . scope . inlined_instance ( source_scopes) ;
443
- if live. contains ( & instance) {
444
- retained_coverage. push ( ( statement. source_info , coverage. code_regions . clone ( ) ) ) ;
445
- }
446
- }
447
- }
448
-
449
- let start_block = & mut basic_blocks[ START_BLOCK ] ;
450
- start_block. statements . extend ( retained_coverage. into_iter ( ) . map (
451
- |( source_info, code_regions) | Statement {
452
- source_info,
453
- kind : StatementKind :: Coverage ( Box :: new ( Coverage {
454
- kind : CoverageKind :: Unreachable ,
455
- code_regions,
456
- } ) ) ,
457
- } ,
458
- ) ) ;
459
- }
460
-
461
368
pub enum SimplifyLocals {
462
369
BeforeConstProp ,
463
370
Final ,
0 commit comments