coverage: Change query codegened_and_inlined_items to a plain function

This query has a name that sounds general-purpose, but in fact it has
coverage-specific semantics, and (fortunately) is only used by coverage code.

Because it is only ever called once (from one designated CGU), it doesn't need
to be a query, and we can change it to a regular function instead.
This commit is contained in:
Zalathar 2023-09-28 15:37:44 +10:00
parent cdeeffde64
commit 6f1ca8d9eb
3 changed files with 34 additions and 40 deletions

View File

@ -13,6 +13,7 @@ use rustc_middle::bug;
use rustc_middle::mir; use rustc_middle::mir;
use rustc_middle::mir::coverage::CodeRegion; use rustc_middle::mir::coverage::CodeRegion;
use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{self, TyCtxt};
use rustc_span::def_id::DefIdSet;
use rustc_span::Symbol; use rustc_span::Symbol;
/// Generates and exports the Coverage Map. /// Generates and exports the Coverage Map.
@ -313,8 +314,7 @@ fn save_function_record(
/// `-Clink-dead-code` will not generate code for unused generic functions.) /// `-Clink-dead-code` will not generate code for unused generic functions.)
/// ///
/// We can find the unused functions (including generic functions) by the set difference of all MIR /// We can find the unused functions (including generic functions) by the set difference of all MIR
/// `DefId`s (`tcx` query `mir_keys`) minus the codegenned `DefId`s (`tcx` query /// `DefId`s (`tcx` query `mir_keys`) minus the codegenned `DefId`s (`codegenned_and_inlined_items`).
/// `codegened_and_inlined_items`).
/// ///
/// These unused functions don't need to be codegenned, but we do need to add them to the function /// These unused functions don't need to be codegenned, but we do need to add them to the function
/// coverage map (in a single designated CGU) so that we still emit coverage mappings for them. /// coverage map (in a single designated CGU) so that we still emit coverage mappings for them.
@ -350,7 +350,7 @@ fn add_unused_functions(cx: &CodegenCx<'_, '_>) {
}) })
.collect(); .collect();
let codegenned_def_ids = tcx.codegened_and_inlined_items(()); let codegenned_def_ids = codegenned_and_inlined_items(tcx);
// For each `DefId` that should have coverage instrumentation but wasn't // For each `DefId` that should have coverage instrumentation but wasn't
// codegenned, add it to the function coverage map as an unused function. // codegenned, add it to the function coverage map as an unused function.
@ -368,6 +368,37 @@ fn add_unused_functions(cx: &CodegenCx<'_, '_>) {
} }
} }
/// All items participating in code generation together with (instrumented)
/// items inlined into them.
fn codegenned_and_inlined_items(tcx: TyCtxt<'_>) -> DefIdSet {
let (items, cgus) = tcx.collect_and_partition_mono_items(());
let mut visited = DefIdSet::default();
let mut result = items.clone();
for cgu in cgus {
for item in cgu.items().keys() {
if let mir::mono::MonoItem::Fn(ref instance) = item {
let did = instance.def_id();
if !visited.insert(did) {
continue;
}
let body = tcx.instance_mir(instance.def);
for block in body.basic_blocks.iter() {
for statement in &block.statements {
let mir::StatementKind::Coverage(_) = statement.kind else { continue };
let scope = statement.source_info.scope;
if let Some(inlined) = scope.inlined_instance(&body.source_scopes) {
result.insert(inlined.def_id());
}
}
}
}
}
}
result
}
fn declare_unused_fn<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::Instance<'tcx> { fn declare_unused_fn<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::Instance<'tcx> {
ty::Instance::new( ty::Instance::new(
def_id, def_id,

View File

@ -1882,12 +1882,6 @@ rustc_queries! {
desc { |tcx| "determining whether `{}` needs codegen", tcx.def_path_str(def_id) } desc { |tcx| "determining whether `{}` needs codegen", tcx.def_path_str(def_id) }
} }
/// All items participating in code generation together with items inlined into them.
query codegened_and_inlined_items(_: ()) -> &'tcx DefIdSet {
eval_always
desc { "collecting codegened and inlined items" }
}
query codegen_unit(sym: Symbol) -> &'tcx CodegenUnit<'tcx> { query codegen_unit(sym: Symbol) -> &'tcx CodegenUnit<'tcx> {
desc { "getting codegen unit `{sym}`" } desc { "getting codegen unit `{sym}`" }
} }

View File

@ -105,7 +105,6 @@ use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE};
use rustc_hir::definitions::DefPathDataName; use rustc_hir::definitions::DefPathDataName;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel}; use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel};
use rustc_middle::mir;
use rustc_middle::mir::mono::{ use rustc_middle::mir::mono::{
CodegenUnit, CodegenUnitNameBuilder, InstantiationMode, Linkage, MonoItem, MonoItemData, CodegenUnit, CodegenUnitNameBuilder, InstantiationMode, Linkage, MonoItem, MonoItemData,
Visibility, Visibility,
@ -1279,38 +1278,8 @@ fn dump_mono_items_stats<'tcx>(
Ok(()) Ok(())
} }
fn codegened_and_inlined_items(tcx: TyCtxt<'_>, (): ()) -> &DefIdSet {
let (items, cgus) = tcx.collect_and_partition_mono_items(());
let mut visited = DefIdSet::default();
let mut result = items.clone();
for cgu in cgus {
for item in cgu.items().keys() {
if let MonoItem::Fn(ref instance) = item {
let did = instance.def_id();
if !visited.insert(did) {
continue;
}
let body = tcx.instance_mir(instance.def);
for block in body.basic_blocks.iter() {
for statement in &block.statements {
let mir::StatementKind::Coverage(_) = statement.kind else { continue };
let scope = statement.source_info.scope;
if let Some(inlined) = scope.inlined_instance(&body.source_scopes) {
result.insert(inlined.def_id());
}
}
}
}
}
}
tcx.arena.alloc(result)
}
pub fn provide(providers: &mut Providers) { pub fn provide(providers: &mut Providers) {
providers.collect_and_partition_mono_items = collect_and_partition_mono_items; providers.collect_and_partition_mono_items = collect_and_partition_mono_items;
providers.codegened_and_inlined_items = codegened_and_inlined_items;
providers.is_codegened_item = |tcx, def_id| { providers.is_codegened_item = |tcx, def_id| {
let (all_mono_items, _) = tcx.collect_and_partition_mono_items(()); let (all_mono_items, _) = tcx.collect_and_partition_mono_items(());