diff --git a/src/librustc_middle/mir/mono.rs b/src/librustc_middle/mir/mono.rs index c889dbc0a4498..03b29deb56fdd 100644 --- a/src/librustc_middle/mir/mono.rs +++ b/src/librustc_middle/mir/mono.rs @@ -1,7 +1,9 @@ use crate::dep_graph::{DepConstructor, DepNode, WorkProduct, WorkProductId}; use crate::ich::{NodeIdHashingMode, StableHashingContext}; use crate::ty::print::obsolete::DefPathBasedNames; -use crate::ty::{subst::InternalSubsts, Instance, InstanceDef, SymbolName, TyCtxt}; +use crate::ty::{ + subst::GenericArgKind, subst::InternalSubsts, Instance, InstanceDef, SymbolName, TyCtxt, +}; use rustc_attr::InlineAttr; use rustc_data_structures::base_n; use rustc_data_structures::fingerprint::Fingerprint; @@ -48,6 +50,13 @@ pub enum MonoItem<'tcx> { } impl<'tcx> MonoItem<'tcx> { + pub fn def_id(&self) -> Option { + match self { + MonoItem::Fn(instance) => Some(instance.def_id()), + MonoItem::Static(def_id) => Some(*def_id), + MonoItem::GlobalAsm(..) => None, + } + } pub fn size_estimate(&self, tcx: TyCtxt<'tcx>) -> usize { match *self { MonoItem::Fn(instance) => { @@ -68,6 +77,18 @@ impl<'tcx> MonoItem<'tcx> { } } + pub fn has_closure_generic_argument(&self) -> bool { + match *self { + MonoItem::Fn(instance) => { + instance.substs.non_erasable_generics().any(|arg| match arg { + GenericArgKind::Type(ty) => ty.is_closure(), + GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false, + }) + } + MonoItem::Static(..) | MonoItem::GlobalAsm(..) => false, + } + } + pub fn symbol_name(&self, tcx: TyCtxt<'tcx>) -> SymbolName { match *self { MonoItem::Fn(instance) => tcx.symbol_name(instance), @@ -207,6 +228,14 @@ impl<'tcx> MonoItem<'tcx> { } .map(|hir_id| tcx.hir().span(hir_id)) } + + pub fn is_local(&self) -> bool { + match *self { + MonoItem::Fn(Instance { def, .. }) => def.def_id().is_local(), + MonoItem::Static(def_id) => def_id.is_local(), + MonoItem::GlobalAsm(..) => true, + } + } } impl<'a, 'tcx> HashStable> for MonoItem<'tcx> { diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index db1ea72c0a531..cae94975896a2 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -106,6 +106,7 @@ use rustc_middle::mir::mono::{InstantiationMode, MonoItem}; use rustc_middle::ty::print::characteristic_def_id_of_type; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, DefIdTree, InstanceDef, TyCtxt}; +use rustc_session::config::OptLevel; use rustc_span::symbol::{Symbol, SymbolStr}; use crate::monomorphize::collector::InliningMap; @@ -137,6 +138,8 @@ where initial_partitioning.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx)); + initial_partitioning.codegen_units.sort_by_key(|cgu| cgu.name().as_str()); + debug_dump(tcx, "INITIAL PARTITIONING:", initial_partitioning.codegen_units.iter()); // Merge until we have at most `max_cgu_count` codegen units. @@ -152,7 +155,9 @@ where // local functions the definition of which is marked with `#[inline]`. let mut post_inlining = { let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_inline_items"); - place_inlined_mono_items(initial_partitioning, inlining_map) + let is_debug_incremental = + tcx.sess.opts.optimize == OptLevel::No && tcx.sess.opts.incremental.is_some(); + place_inlined_mono_items(initial_partitioning, inlining_map, is_debug_incremental) }; post_inlining.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx)); @@ -206,6 +211,7 @@ where let mut roots = FxHashSet::default(); let mut codegen_units = FxHashMap::default(); let is_incremental_build = tcx.sess.opts.incremental.is_some(); + let is_debug_incremental = is_incremental_build && tcx.sess.opts.optimize == OptLevel::No; let mut internalization_candidates = FxHashSet::default(); // Determine if monomorphizations instantiated in this crate will be made @@ -223,18 +229,30 @@ where InstantiationMode::LocalCopy => continue, } - let characteristic_def_id = characteristic_def_id_of_mono_item(tcx, mono_item); + let characteristic_def_id = + characteristic_def_id_of_mono_item(tcx, mono_item, is_debug_incremental); let is_volatile = is_incremental_build && mono_item.is_generic_fn(); - let codegen_unit_name = match characteristic_def_id { - Some(def_id) => compute_codegen_unit_name( + let codegen_unit_name = match (characteristic_def_id, mono_item.is_local()) { + (Some(def_id), false) if is_debug_incremental => { + let crate_name = tcx.crate_name(def_id.krate); + cgu_name_builder.build_cgu_name( + LOCAL_CRATE, + &[ + &*crate_name.as_str(), + if mono_item.has_closure_generic_argument() { "has_closure" } else { "" }, + ], + Some("cgu"), + ) + } + (Some(def_id), _) => compute_codegen_unit_name( tcx, cgu_name_builder, def_id, is_volatile, cgu_name_cache, ), - None => fallback_cgu_name(cgu_name_builder), + (None, _) => fallback_cgu_name(cgu_name_builder), }; let codegen_unit = codegen_units @@ -459,7 +477,9 @@ fn merge_codegen_units<'tcx>( assert!(target_cgu_count >= 1); let codegen_units = &mut initial_partitioning.codegen_units; - if tcx.is_compiler_builtins(LOCAL_CRATE) { + if tcx.is_compiler_builtins(LOCAL_CRATE) + || (tcx.dep_graph.is_fully_enabled() && tcx.sess.opts.optimize == OptLevel::No) + { // Compiler builtins require some degree of control over how mono items // are partitioned into compilation units. Provide it by keeping the // original partitioning when compiling the compiler builtins crate. @@ -555,6 +575,7 @@ fn merge_codegen_units<'tcx>( fn place_inlined_mono_items<'tcx>( initial_partitioning: PreInliningPartitioning<'tcx>, inlining_map: &InliningMap<'tcx>, + is_debug_incremental: bool, ) -> PostInliningPartitioning<'tcx> { let mut new_partitioning = Vec::new(); let mut mono_item_placements = FxHashMap::default(); @@ -587,10 +608,14 @@ fn place_inlined_mono_items<'tcx>( ); } - // This is a CGU-private copy. - new_codegen_unit - .items_mut() - .insert(mono_item, (Linkage::Internal, Visibility::Default)); + // In debug-incremental, do not create CGU-private copies unless it's for an external symbol + // FIXME: put external symbols in a separate codegen unit + if !is_debug_incremental || !mono_item.is_local() { + // This is a CGU-private copy. + new_codegen_unit + .items_mut() + .insert(mono_item, (Linkage::Internal, Visibility::Default)); + } } if !single_codegen_unit { @@ -707,7 +732,12 @@ fn internalize_symbols<'tcx>( fn characteristic_def_id_of_mono_item<'tcx>( tcx: TyCtxt<'tcx>, mono_item: MonoItem<'tcx>, + is_debug_incremental: bool, ) -> Option { + if is_debug_incremental { + return mono_item.def_id(); + } + match mono_item { MonoItem::Fn(instance) => { let def_id = match instance.def { diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs index 1aa11a761c821..e0861e15fd39d 100644 --- a/src/librustc_ty/ty.rs +++ b/src/librustc_ty/ty.rs @@ -2,6 +2,7 @@ use rustc_data_structures::svh::Svh; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use rustc_middle::hir::map as hir_map; +use rustc_middle::mir::StatementKind; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; use rustc_session::CrateDisambiguator; @@ -299,7 +300,23 @@ fn instance_def_size_estimate<'tcx>( match instance_def { InstanceDef::Item(..) | InstanceDef::DropGlue(..) => { let mir = tcx.instance_mir(instance_def); - mir.basic_blocks().iter().map(|bb| bb.statements.len()).sum() + mir.basic_blocks() + .iter() + .map(|bb| { + bb.statements + .iter() + .filter(|stmt| match stmt.kind { + StatementKind::StorageLive(_) + | StatementKind::StorageDead(_) + | StatementKind::AscribeUserType(..) + | StatementKind::FakeRead(..) + | StatementKind::Retag(..) + | StatementKind::Nop => false, + _ => true, + }) + .count() + }) + .sum() } // Estimate the size of other compiler-generated shims to be 1. _ => 1,