2828//! return.
2929
3030use crate :: MirPass ;
31- use rustc_data_structures:: fx:: { FxHashSet , FxIndexSet } ;
31+ use rustc_data_structures:: fx:: FxIndexSet ;
3232use rustc_index:: { Idx , IndexSlice , IndexVec } ;
33- use rustc_middle:: mir:: coverage:: * ;
3433use rustc_middle:: mir:: visit:: { MutVisitor , MutatingUseContext , PlaceContext , Visitor } ;
3534use rustc_middle:: mir:: * ;
3635use rustc_middle:: ty:: TyCtxt ;
@@ -336,15 +335,14 @@ pub fn remove_duplicate_unreachable_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut B
336335 }
337336}
338337
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 > ) {
340339 let reachable = traversal:: reachable_as_bitset ( body) ;
341340 let num_blocks = body. basic_blocks . len ( ) ;
342341 if num_blocks == reachable. count ( ) {
343342 return ;
344343 }
345344
346345 let basic_blocks = body. basic_blocks . as_mut ( ) ;
347- let source_scopes = & body. source_scopes ;
348346 let mut replacements: Vec < _ > = ( 0 ..num_blocks) . map ( BasicBlock :: new) . collect ( ) ;
349347 let mut used_blocks = 0 ;
350348 for alive_index in reachable. iter ( ) {
@@ -358,10 +356,6 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
358356 used_blocks += 1 ;
359357 }
360358
361- if tcx. sess . instrument_coverage ( ) {
362- save_unreachable_coverage ( basic_blocks, source_scopes, used_blocks) ;
363- }
364-
365359 basic_blocks. raw . truncate ( used_blocks) ;
366360
367361 for block in basic_blocks {
@@ -371,93 +365,6 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
371365 }
372366}
373367
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-
461368pub enum SimplifyLocals {
462369 BeforeConstProp ,
463370 Final ,
0 commit comments