Skip to content

Commit

Permalink
coverage: Detect functions that have lost all their coverage statements
Browse files Browse the repository at this point in the history
If a function was instrumented for coverage, but all of its coverage statements
have been removed by later MIR transforms, it should be treated as "unused"
even if the compiler generates an unreachable stub for it.
  • Loading branch information
Zalathar committed Mar 23, 2024
1 parent 1bae074 commit 07808c4
Showing 1 changed file with 18 additions and 4 deletions.
22 changes: 18 additions & 4 deletions compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
Expand Up @@ -353,10 +353,11 @@ fn add_unused_functions(cx: &CodegenCx<'_, '_>) {

// To be eligible for "unused function" mappings, a definition must:
// - Be function-like
// - Not participate directly in codegen
// - Not participate directly in codegen (or have lost all its coverage statements)
// - Not have any coverage statements inlined into codegenned functions
tcx.def_kind(def_id).is_fn_like()
&& !usage.all_mono_items.contains(&def_id)
&& (!usage.all_mono_items.contains(&def_id)
|| usage.missing_own_coverage.contains(&def_id))
&& !usage.used_via_inlining.contains(&def_id)
};

Expand All @@ -379,6 +380,7 @@ fn add_unused_functions(cx: &CodegenCx<'_, '_>) {
struct UsageSets<'tcx> {
all_mono_items: &'tcx DefIdSet,
used_via_inlining: FxHashSet<DefId>,
missing_own_coverage: FxHashSet<DefId>,
}

/// Prepare sets of definitions that are relevant to deciding whether something
Expand Down Expand Up @@ -408,8 +410,13 @@ fn prepare_usage_sets<'tcx>(tcx: TyCtxt<'tcx>) -> UsageSets<'tcx> {

// Functions whose coverage statments were found inlined into other functions.
let mut used_via_inlining = FxHashSet::default();
// Functions that were instrumented, but had all of their coverage statements
// removed by later MIR transforms (e.g. UnreachablePropagation).
let mut missing_own_coverage = FxHashSet::default();

for (def_id, body) in def_and_mir_for_all_mono_fns {
let mut saw_own_coverage = false;

for (_def_id, body) in def_and_mir_for_all_mono_fns {
// Inspect every coverage statement in the function's MIR.
for stmt in body
.basic_blocks
Expand All @@ -420,11 +427,18 @@ fn prepare_usage_sets<'tcx>(tcx: TyCtxt<'tcx>) -> UsageSets<'tcx> {
if let Some(inlined) = stmt.source_info.scope.inlined_instance(&body.source_scopes) {
// This coverage statement was inlined from another function.
used_via_inlining.insert(inlined.def_id());
} else {
// Non-inlined coverage statements belong to the enclosing function.
saw_own_coverage = true;
}
}

if !saw_own_coverage && body.function_coverage_info.is_some() {
missing_own_coverage.insert(def_id);
}
}

UsageSets { all_mono_items, used_via_inlining }
UsageSets { all_mono_items, used_via_inlining, missing_own_coverage }
}

fn add_unused_function_coverage<'tcx>(
Expand Down

0 comments on commit 07808c4

Please sign in to comment.