diff options
Diffstat (limited to 'compiler/rustc_monomorphize/src')
| -rw-r--r-- | compiler/rustc_monomorphize/src/collector.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_monomorphize/src/errors.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_monomorphize/src/partitioning/mod.rs | 78 | ||||
| -rw-r--r-- | compiler/rustc_monomorphize/src/polymorphize.rs | 1 |
4 files changed, 91 insertions, 8 deletions
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index cf7226a129c..10ea4d29cfe 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -931,10 +931,13 @@ fn visit_fn_use<'tcx>( ) { if let ty::FnDef(def_id, substs) = *ty.kind() { let instance = if is_direct_call { - ty::Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap().unwrap() + ty::Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs) } else { - ty::Instance::resolve_for_fn_ptr(tcx, ty::ParamEnv::reveal_all(), def_id, substs) - .unwrap() + match ty::Instance::resolve_for_fn_ptr(tcx, ty::ParamEnv::reveal_all(), def_id, substs) + { + Some(instance) => instance, + _ => bug!("failed to resolve instance for {ty}"), + } }; visit_instance_use(tcx, instance, is_direct_call, source, output); } @@ -1369,9 +1372,8 @@ fn create_mono_items_for_default_impls<'tcx>( trait_ref.substs[param.index as usize] } }); - let instance = ty::Instance::resolve(tcx, param_env, method.def_id, substs) - .unwrap() - .unwrap(); + let instance = + ty::Instance::expect_resolve(tcx, param_env, method.def_id, substs); let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP); if mono_item.node.is_instantiable(tcx) && should_codegen_locally(tcx, &instance) diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index f1ca72de8db..f15cf54718e 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -77,3 +77,9 @@ pub struct SymbolAlreadyDefined { pub span: Option<Span>, pub symbol: String, } + +#[derive(Diagnostic)] +#[diag(monomorphize_couldnt_dump_mono_stats)] +pub struct CouldntDumpMonoStats { + pub error: String, +} diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs index 932edc6675f..38e1d98e44e 100644 --- a/compiler/rustc_monomorphize/src/partitioning/mod.rs +++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs @@ -95,6 +95,11 @@ mod default; mod merging; +use std::cmp; +use std::fs::{self, File}; +use std::io::{BufWriter, Write}; +use std::path::{Path, PathBuf}; + use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync; use rustc_hir::def_id::DefIdSet; @@ -104,11 +109,12 @@ use rustc_middle::mir::mono::{CodegenUnit, Linkage}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; +use rustc_session::config::SwitchWithOptPath; use rustc_span::symbol::Symbol; use crate::collector::InliningMap; use crate::collector::{self, MonoItemCollectionMode}; -use crate::errors::{SymbolAlreadyDefined, UnknownPartitionStrategy}; +use crate::errors::{CouldntDumpMonoStats, SymbolAlreadyDefined, UnknownPartitionStrategy}; pub struct PartitioningCx<'a, 'tcx> { tcx: TyCtxt<'tcx>, @@ -411,6 +417,15 @@ fn collect_and_partition_mono_items<'tcx>( }) .collect(); + // Output monomorphization stats per def_id + if let SwitchWithOptPath::Enabled(ref path) = tcx.sess.opts.unstable_opts.dump_mono_stats { + if let Err(err) = + dump_mono_items_stats(tcx, &codegen_units, path, tcx.sess.opts.crate_name.as_deref()) + { + tcx.sess.emit_fatal(CouldntDumpMonoStats { error: err.to_string() }); + } + } + if tcx.sess.opts.unstable_opts.print_mono_items.is_some() { let mut item_to_cgus: FxHashMap<_, Vec<_>> = Default::default(); @@ -465,6 +480,67 @@ fn collect_and_partition_mono_items<'tcx>( (tcx.arena.alloc(mono_items), codegen_units) } +/// Outputs stats about instantation counts and estimated size, per `MonoItem`'s +/// def, to a file in the given output directory. +fn dump_mono_items_stats<'tcx>( + tcx: TyCtxt<'tcx>, + codegen_units: &[CodegenUnit<'tcx>], + output_directory: &Option<PathBuf>, + crate_name: Option<&str>, +) -> Result<(), Box<dyn std::error::Error>> { + let output_directory = if let Some(ref directory) = output_directory { + fs::create_dir_all(directory)?; + directory + } else { + Path::new(".") + }; + + let filename = format!("{}.mono_items.md", crate_name.unwrap_or("unknown-crate")); + let output_path = output_directory.join(&filename); + let file = File::create(output_path)?; + let mut file = BufWriter::new(file); + + // Gather instantiated mono items grouped by def_id + let mut items_per_def_id: FxHashMap<_, Vec<_>> = Default::default(); + for cgu in codegen_units { + for (&mono_item, _) in cgu.items() { + // Avoid variable-sized compiler-generated shims + if mono_item.is_user_defined() { + items_per_def_id.entry(mono_item.def_id()).or_default().push(mono_item); + } + } + } + + // Output stats sorted by total instantiated size, from heaviest to lightest + let mut stats: Vec<_> = items_per_def_id + .into_iter() + .map(|(def_id, items)| { + let instantiation_count = items.len(); + let size_estimate = items[0].size_estimate(tcx); + let total_estimate = instantiation_count * size_estimate; + (def_id, instantiation_count, size_estimate, total_estimate) + }) + .collect(); + stats.sort_unstable_by_key(|(_, _, _, total_estimate)| cmp::Reverse(*total_estimate)); + + if !stats.is_empty() { + writeln!( + file, + "| Item | Instantiation count | Estimated Cost Per Instantiation | Total Estimated Cost |" + )?; + writeln!(file, "| --- | ---: | ---: | ---: |")?; + for (def_id, instantiation_count, size_estimate, total_estimate) in stats { + let item = with_no_trimmed_paths!(tcx.def_path_str(def_id)); + writeln!( + file, + "| {item} | {instantiation_count} | {size_estimate} | {total_estimate} |" + )?; + } + } + + Ok(()) +} + fn codegened_and_inlined_items<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> &'tcx DefIdSet { let (items, cgus) = tcx.collect_and_partition_mono_items(()); let mut visited = DefIdSet::default(); diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index 650076c2213..703ed09a254 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -20,7 +20,6 @@ use rustc_middle::ty::{ Const, Ty, TyCtxt, }; use rustc_span::symbol::sym; -use std::convert::TryInto; use std::ops::ControlFlow; use crate::errors::UnusedGenericParams; |
