From 5f40a4f7a0aa6552e615fe89a6018e36c93f672e Mon Sep 17 00:00:00 2001 From: Tomasz Miąsko Date: Mon, 25 Jul 2022 00:00:00 +0000 Subject: Remove reachable coverage without counters Remove reachable coverage without counters to maintain invariant that either there is no coverage at all or there is a live coverage counter left that provides the function source hash. The motivating example would be a following closure: ```rust let f = |x: bool| { debug_assert!(x); }; ``` Which, with span changes from #93967, with disabled debug assertions, after the final CFG simplifications but before removal of dead blocks, gives rise to MIR: ```rust fn main::{closure#0}(_1: &[closure@a.rs:2:13: 2:22], _2: bool) -> () { debug x => _2; let mut _0: (); bb0: { Coverage::Expression(4294967295) = 1 - 2; return; } ... } ``` --- compiler/rustc_mir_transform/src/simplify.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'compiler/rustc_mir_transform/src') diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index d305960b485..180f4c7dcd6 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -315,7 +315,7 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { /// with `0` executions. /// /// If there are no live `Counter` `Coverage` statements remaining, we remove -/// dead `Coverage` statements along with the dead blocks. Since at least one +/// `Coverage` statements along with the dead blocks. Since at least one /// counter per function is required by LLVM (and necessary, to add the /// `function_hash` to the counter's call to the LLVM intrinsic /// `instrprof.increment()`). @@ -342,6 +342,16 @@ fn save_unreachable_coverage( } } + for block in &mut basic_blocks.raw[..first_dead_block] { + for statement in &mut block.statements { + let StatementKind::Coverage(_) = &statement.kind else { continue }; + let instance = statement.source_info.scope.inlined_instance(source_scopes); + if !live.contains(&instance) { + statement.make_nop(); + } + } + } + if live.is_empty() { return; } -- cgit 1.4.1-3-g733a5