diff options
Diffstat (limited to 'compiler/rustc_mir/src/transform/simplify.rs')
| -rw-r--r-- | compiler/rustc_mir/src/transform/simplify.rs | 42 | 
1 files changed, 37 insertions, 5 deletions
| diff --git a/compiler/rustc_mir/src/transform/simplify.rs b/compiler/rustc_mir/src/transform/simplify.rs index 65e2d096b20..63373b0cffb 100644 --- a/compiler/rustc_mir/src/transform/simplify.rs +++ b/compiler/rustc_mir/src/transform/simplify.rs @@ -29,6 +29,7 @@ use crate::transform::MirPass; use rustc_index::vec::{Idx, IndexVec}; +use rustc_middle::mir::coverage::*; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; @@ -46,9 +47,9 @@ impl SimplifyCfg { } } -pub fn simplify_cfg(body: &mut Body<'_>) { +pub fn simplify_cfg(tcx: TyCtxt<'tcx>, body: &mut Body<'_>) { CfgSimplifier::new(body).simplify(); - remove_dead_blocks(body); + remove_dead_blocks(tcx, body); // FIXME: Should probably be moved into some kind of pass manager body.basic_blocks_mut().raw.shrink_to_fit(); @@ -59,9 +60,9 @@ impl<'tcx> MirPass<'tcx> for SimplifyCfg { Cow::Borrowed(&self.label) } - fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body.source); - simplify_cfg(body); + simplify_cfg(tcx, body); } } @@ -286,7 +287,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { } } -pub fn remove_dead_blocks(body: &mut Body<'_>) { +pub fn remove_dead_blocks(tcx: TyCtxt<'tcx>, body: &mut Body<'_>) { let reachable = traversal::reachable_as_bitset(body); let num_blocks = body.basic_blocks().len(); if num_blocks == reachable.count() { @@ -306,6 +307,11 @@ pub fn remove_dead_blocks(body: &mut Body<'_>) { } used_blocks += 1; } + + if tcx.sess.instrument_coverage() { + save_unreachable_coverage(basic_blocks, used_blocks); + } + basic_blocks.raw.truncate(used_blocks); for block in basic_blocks { @@ -315,6 +321,32 @@ pub fn remove_dead_blocks(body: &mut Body<'_>) { } } +fn save_unreachable_coverage( + basic_blocks: &mut IndexVec<BasicBlock, BasicBlockData<'_>>, + first_dead_block: usize, +) { + // retain coverage info for dead blocks, so coverage reports will still + // report `0` executions for the uncovered code regions. + let mut dropped_coverage = Vec::new(); + for dead_block in first_dead_block..basic_blocks.len() { + for statement in basic_blocks[BasicBlock::new(dead_block)].statements.iter() { + if let StatementKind::Coverage(coverage) = &statement.kind { + if let Some(code_region) = &coverage.code_region { + dropped_coverage.push((statement.source_info, code_region.clone())); + } + } + } + } + for (source_info, code_region) in dropped_coverage { + basic_blocks[START_BLOCK].statements.push(Statement { + source_info, + kind: StatementKind::Coverage(box Coverage { + kind: CoverageKind::Unreachable, + code_region: Some(code_region), + }), + }) + } +} pub struct SimplifyLocals; impl<'tcx> MirPass<'tcx> for SimplifyLocals { | 
