Skip to content

Commit

Permalink
Auto merge of rust-lang#132566 - saethlin:querify-mir-collection, r=
Browse files Browse the repository at this point in the history
Querify mir collection

Factored out of rust-lang#131650, these changes are required for post-mono MIR opts but I want to benchmark them on their own so that I can tune the implementation.

r? ghost
  • Loading branch information
bors committed Nov 3, 2024
2 parents 7028d93 + 785a96b commit 2c06ca1
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 54 deletions.
71 changes: 47 additions & 24 deletions compiler/rustc_middle/src/mir/mono.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use rustc_target::spec::SymbolVisibility;
use tracing::debug;

use crate::dep_graph::{DepNode, WorkProduct, WorkProductId};
use crate::query::Providers;
use crate::ty::{GenericArgs, Instance, InstanceKind, SymbolName, TyCtxt};

/// Describes how a monomorphization will be instantiated in object files.
Expand Down Expand Up @@ -62,30 +63,6 @@ impl<'tcx> MonoItem<'tcx> {
}
}

// Note: if you change how item size estimates work, you might need to
// change NON_INCR_MIN_CGU_SIZE as well.
pub fn size_estimate(&self, tcx: TyCtxt<'tcx>) -> usize {
match *self {
MonoItem::Fn(instance) => {
match instance.def {
// "Normal" functions size estimate: the number of
// statements, plus one for the terminator.
InstanceKind::Item(..)
| InstanceKind::DropGlue(..)
| InstanceKind::AsyncDropGlueCtorShim(..) => {
let mir = tcx.instance_mir(instance.def);
mir.basic_blocks.iter().map(|bb| bb.statements.len() + 1).sum()
}
// Other compiler-generated shims size estimate: 1
_ => 1,
}
}
// Conservatively estimate the size of a static declaration or
// assembly item to be 1.
MonoItem::Static(_) | MonoItem::GlobalAsm(_) => 1,
}
}

pub fn is_generic_fn(&self) -> bool {
match self {
MonoItem::Fn(instance) => instance.args.non_erasable_generics().next().is_some(),
Expand Down Expand Up @@ -556,3 +533,49 @@ impl<'tcx> CodegenUnitNameBuilder<'tcx> {
Symbol::intern(&cgu_name)
}
}

/// See module-level docs on some contect for "mentioned" items.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
pub enum CollectionMode {
/// Collect items that are used, i.e., actually needed for codegen.
///
/// Which items are used can depend on optimization levels, as MIR optimizations can remove
/// uses.
UsedItems,
/// Collect items that are mentioned. The goal of this mode is that it is independent of
/// optimizations: the set of "mentioned" items is computed before optimizations are run.
///
/// The exact contents of this set are *not* a stable guarantee. (For instance, it is currently
/// computed after drop-elaboration. If we ever do some optimizations even in debug builds, we
/// might decide to run them before computing mentioned items.) The key property of this set is
/// that it is optimization-independent.
MentionedItems,
}

// Note: if you change how item size estimates work, you might need to
// change NON_INCR_MIN_CGU_SIZE as well.
fn size_estimate<'tcx>(tcx: TyCtxt<'tcx>, item: MonoItem<'tcx>) -> usize {
match item {
MonoItem::Fn(instance) => {
match instance.def {
// "Normal" functions size estimate: the number of
// statements, plus one for the terminator.
InstanceKind::Item(..)
| InstanceKind::DropGlue(..)
| InstanceKind::AsyncDropGlueCtorShim(..) => {
let mir = tcx.instance_mir(instance.def);
mir.basic_blocks.iter().map(|bb| bb.statements.len() + 1).sum()
}
// Other compiler-generated shims size estimate: 1
_ => 1,
}
}
// Conservatively estimate the size of a static declaration or
// assembly item to be 1.
MonoItem::Static(_) | MonoItem::GlobalAsm(_) => 1,
}
}

pub fn provide(providers: &mut Providers) {
providers.size_estimate = size_estimate;
}
4 changes: 4 additions & 0 deletions compiler/rustc_middle/src/query/erase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,10 @@ impl<T0, T1> EraseType for (&'_ T0, &'_ [T1]) {
type Result = [u8; size_of::<(&'static (), &'static [()])>()];
}

impl<T0, T1> EraseType for (&'_ [T0], &'_ [T1]) {
type Result = [u8; size_of::<(&'static [()], &'static [()])>()];
}

impl<T0> EraseType for (&'_ T0, Result<(), ErrorGuaranteed>) {
type Result = [u8; size_of::<(&'static (), Result<(), ErrorGuaranteed>)>()];
}
Expand Down
18 changes: 18 additions & 0 deletions compiler/rustc_middle/src/query/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use rustc_span::{DUMMY_SP, Span};
use rustc_target::abi;

use crate::infer::canonical::CanonicalQueryInput;
use crate::mir::mono::CollectionMode;
use crate::query::MonoItem;
use crate::ty::fast_reject::SimplifiedType;
use crate::ty::layout::{TyAndLayout, ValidityRequirement};
use crate::ty::{self, GenericArg, GenericArgsRef, Ty, TyCtxt};
Expand Down Expand Up @@ -86,6 +88,14 @@ impl<'tcx> Key for ty::Instance<'tcx> {
}
}

impl<'tcx> Key for MonoItem<'tcx> {
type Cache<V> = DefaultCache<Self, V>;

fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
tcx.def_span(self.def_id())
}
}

impl<'tcx> Key for mir::interpret::GlobalId<'tcx> {
type Cache<V> = DefaultCache<Self, V>;

Expand Down Expand Up @@ -591,3 +601,11 @@ impl<'tcx> Key for (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>) {
}
}
}

impl<'tcx> Key for (ty::Instance<'tcx>, CollectionMode) {
type Cache<V> = DefaultCache<Self, V>;

fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
}
13 changes: 12 additions & 1 deletion compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ use rustc_session::cstore::{
};
use rustc_session::lint::LintExpectationId;
use rustc_span::def_id::LOCAL_CRATE;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::Symbol;
use rustc_span::{DUMMY_SP, Span};
use rustc_target::abi;
Expand All @@ -60,7 +61,7 @@ use crate::mir::interpret::{
EvalStaticInitializerRawResult, EvalToAllocationRawResult, EvalToConstValueResult,
EvalToValTreeResult, GlobalId, LitToConstError, LitToConstInput,
};
use crate::mir::mono::CodegenUnit;
use crate::mir::mono::{CodegenUnit, CollectionMode, MonoItem};
use crate::query::erase::{Erase, erase, restore};
use crate::query::plumbing::{
CyclePlaceholder, DynamicQuery, query_ensure, query_ensure_error_guaranteed, query_get_at,
Expand Down Expand Up @@ -2315,6 +2316,16 @@ rustc_queries! {
desc { "whether the item should be made inlinable across crates" }
separate_provide_extern
}

query items_of_instance(key: (ty::Instance<'tcx>, CollectionMode)) -> (&'tcx [Spanned<MonoItem<'tcx>>], &'tcx [Spanned<MonoItem<'tcx>>]) {
desc { "collecting used items" }
cache_on_disk_if { true }
}

query size_estimate(key: MonoItem<'tcx>) -> usize {
desc { "estimating codegen size" }
cache_on_disk_if { true }
}
}

rustc_query_append! { define_callbacks! }
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2155,6 +2155,7 @@ pub fn provide(providers: &mut Providers) {
print::provide(providers);
super::util::bug::provide(providers);
super::middle::provide(providers);
super::mir::mono::provide(providers);
*providers = Providers {
trait_impls_of: trait_def::trait_impls_of_provider,
incoherent_impls: trait_def::incoherent_impls_provider,
Expand Down
41 changes: 15 additions & 26 deletions compiler/rustc_monomorphize/src/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
use rustc_hir::lang_items::LangItem;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::interpret::{AllocId, ErrorHandled, GlobalAlloc, Scalar};
use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
use rustc_middle::mir::mono::{CollectionMode, InstantiationMode, MonoItem};
use rustc_middle::mir::visit::Visitor as MirVisitor;
use rustc_middle::mir::{self, Location, MentionedItem, traversal};
use rustc_middle::query::TyCtxtAt;
Expand Down Expand Up @@ -268,24 +268,6 @@ struct SharedState<'tcx> {
usage_map: MTLock<UsageMap<'tcx>>,
}

/// See module-level docs on some contect for "mentioned" items.
#[derive(Copy, Clone, Debug, PartialEq)]
enum CollectionMode {
/// Collect items that are used, i.e., actually needed for codegen.
///
/// Which items are used can depend on optimization levels, as MIR optimizations can remove
/// uses.
UsedItems,
/// Collect items that are mentioned. The goal of this mode is that it is independent of
/// optimizations: the set of "mentioned" items is computed before optimizations are run.
///
/// The exact contents of this set are *not* a stable guarantee. (For instance, it is currently
/// computed after drop-elaboration. If we ever do some optimizations even in debug builds, we
/// might decide to run them before computing mentioned items.) The key property of this set is
/// that it is optimization-independent.
MentionedItems,
}

impl<'tcx> UsageMap<'tcx> {
fn new() -> UsageMap<'tcx> {
UsageMap { used_map: Default::default(), user_map: Default::default() }
Expand Down Expand Up @@ -447,13 +429,9 @@ fn collect_items_rec<'tcx>(
));

rustc_data_structures::stack::ensure_sufficient_stack(|| {
collect_items_of_instance(
tcx,
instance,
&mut used_items,
&mut mentioned_items,
mode,
)
let (used, mentioned) = tcx.items_of_instance((instance, mode));
used_items.extend(used);
mentioned_items.extend(mentioned);
});
}
MonoItem::GlobalAsm(item_id) => {
Expand Down Expand Up @@ -1253,6 +1231,16 @@ fn collect_items_of_instance<'tcx>(
}
}

fn items_of_instance<'tcx>(
tcx: TyCtxt<'tcx>,
(instance, mode): (Instance<'tcx>, CollectionMode),
) -> (&'tcx [Spanned<MonoItem<'tcx>>], &'tcx [Spanned<MonoItem<'tcx>>]) {
let mut used_items = MonoItems::default();
let mut mentioned_items = MonoItems::default();
collect_items_of_instance(tcx, instance, &mut used_items, &mut mentioned_items, mode);
(tcx.arena.alloc_slice(&used_items), tcx.arena.alloc_slice(&mentioned_items))
}

/// `item` must be already monomorphized.
#[instrument(skip(tcx, span, output), level = "debug")]
fn visit_mentioned_item<'tcx>(
Expand Down Expand Up @@ -1623,4 +1611,5 @@ pub(crate) fn collect_crate_mono_items<'tcx>(

pub(crate) fn provide(providers: &mut Providers) {
providers.hooks.should_codegen_locally = should_codegen_locally;
providers.items_of_instance = items_of_instance;
}
6 changes: 3 additions & 3 deletions compiler/rustc_monomorphize/src/partitioning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ where
if visibility == Visibility::Hidden && can_be_internalized {
internalization_candidates.insert(mono_item);
}
let size_estimate = mono_item.size_estimate(cx.tcx);
let size_estimate = cx.tcx.size_estimate(mono_item);

cgu.items_mut().insert(mono_item, MonoItemData {
inlined: false,
Expand All @@ -279,7 +279,7 @@ where
inlined: true,
linkage: Linkage::Internal,
visibility: Visibility::Default,
size_estimate: inlined_item.size_estimate(cx.tcx),
size_estimate: cx.tcx.size_estimate(inlined_item),
});
}
}
Expand Down Expand Up @@ -1274,7 +1274,7 @@ fn dump_mono_items_stats<'tcx>(
.map(|(def_id, items)| {
let name = with_no_trimmed_paths!(tcx.def_path_str(def_id));
let instantiation_count = items.len();
let size_estimate = items[0].size_estimate(tcx);
let size_estimate = tcx.size_estimate(*items[0]);
let total_estimate = instantiation_count * size_estimate;
MonoItem { name, instantiation_count, size_estimate, total_estimate }
})
Expand Down

0 comments on commit 2c06ca1

Please sign in to comment.