Skip to content

Commit 4fcb6e6

Browse files
Auto merge of #149313 - osiewicz:upstream-monomorphizations-lean-and-mean, r=<try>
rustc_codegen_ssa: Make upstream monomorphizations representation sparse
2 parents 7934bbd + c6d54c7 commit 4fcb6e6

File tree

3 files changed

+84
-139
lines changed

3 files changed

+84
-139
lines changed

compiler/rustc_codegen_ssa/src/back/symbol_export.rs

Lines changed: 60 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
use std::collections::hash_map::Entry::*;
2-
31
use rustc_abi::{CanonAbi, X86Call};
42
use rustc_ast::expand::allocator::{
53
ALLOC_ERROR_HANDLER, ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE, global_fn_name,
64
};
7-
use rustc_data_structures::unord::UnordMap;
5+
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
6+
use rustc_hashes::Hash128;
87
use rustc_hir::def::DefKind;
98
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE, LocalDefId};
109
use rustc_middle::bug;
@@ -384,86 +383,75 @@ fn exported_generic_symbols_provider_local<'tcx>(
384383
tcx.arena.alloc_from_iter(symbols)
385384
}
386385

387-
fn upstream_monomorphizations_provider(
386+
fn upstream_monomorphizations_of_crate_provider(
388387
tcx: TyCtxt<'_>,
389-
(): (),
390-
) -> DefIdMap<UnordMap<GenericArgsRef<'_>, CrateNum>> {
391-
let cnums = tcx.crates(());
392-
393-
let mut instances: DefIdMap<UnordMap<_, _>> = Default::default();
394-
388+
cnum: CrateNum,
389+
) -> FxIndexSet<Hash128> {
390+
use rustc_data_structures::stable_hasher::HashStable;
395391
let drop_in_place_fn_def_id = tcx.lang_items().drop_in_place_fn();
396392
let async_drop_in_place_fn_def_id = tcx.lang_items().async_drop_in_place_fn();
397-
398-
for &cnum in cnums.iter() {
399-
for (exported_symbol, _) in tcx.exported_generic_symbols(cnum).iter() {
400-
let (def_id, args) = match *exported_symbol {
401-
ExportedSymbol::Generic(def_id, args) => (def_id, args),
402-
ExportedSymbol::DropGlue(ty) => {
403-
if let Some(drop_in_place_fn_def_id) = drop_in_place_fn_def_id {
404-
(drop_in_place_fn_def_id, tcx.mk_args(&[ty.into()]))
405-
} else {
406-
// `drop_in_place` in place does not exist, don't try
407-
// to use it.
408-
continue;
409-
}
410-
}
411-
ExportedSymbol::AsyncDropGlueCtorShim(ty) => {
412-
if let Some(async_drop_in_place_fn_def_id) = async_drop_in_place_fn_def_id {
413-
(async_drop_in_place_fn_def_id, tcx.mk_args(&[ty.into()]))
414-
} else {
415-
continue;
416-
}
417-
}
418-
ExportedSymbol::AsyncDropGlue(def_id, ty) => (def_id, tcx.mk_args(&[ty.into()])),
419-
ExportedSymbol::NonGeneric(..)
420-
| ExportedSymbol::ThreadLocalShim(..)
421-
| ExportedSymbol::NoDefId(..) => unreachable!("{exported_symbol:?}"),
422-
};
423-
424-
let args_map = instances.entry(def_id).or_default();
425-
426-
match args_map.entry(args) {
427-
Occupied(mut e) => {
428-
// If there are multiple monomorphizations available,
429-
// we select one deterministically.
430-
let other_cnum = *e.get();
431-
if tcx.stable_crate_id(other_cnum) > tcx.stable_crate_id(cnum) {
432-
e.insert(cnum);
433-
}
393+
let mut instances = FxIndexSet::default();
394+
for (exported_symbol, _) in tcx.exported_generic_symbols(cnum).iter() {
395+
let instance = match *exported_symbol {
396+
ExportedSymbol::Generic(def_id, args) => rustc_middle::ty::Instance {
397+
args,
398+
def: rustc_middle::ty::InstanceKind::Item(def_id),
399+
},
400+
ExportedSymbol::DropGlue(ty) => {
401+
let Some(drop_in_place_fn_def_id) = drop_in_place_fn_def_id else {
402+
// `drop_in_place` in place does not exist, don't try
403+
// to use it.
404+
continue;
405+
};
406+
let args = tcx.mk_args(&[ty.clone().into()]);
407+
rustc_middle::ty::Instance {
408+
args,
409+
def: rustc_middle::ty::InstanceKind::DropGlue(
410+
drop_in_place_fn_def_id,
411+
Some(ty),
412+
),
434413
}
435-
Vacant(e) => {
436-
e.insert(cnum);
414+
}
415+
ExportedSymbol::AsyncDropGlueCtorShim(ty) => {
416+
let Some(drop_in_place) = async_drop_in_place_fn_def_id else {
417+
continue;
418+
};
419+
let args = tcx.mk_args(&[ty.clone().into()]);
420+
rustc_middle::ty::Instance {
421+
args,
422+
def: rustc_middle::ty::InstanceKind::AsyncDropGlueCtorShim(drop_in_place, ty),
437423
}
438424
}
439-
}
440-
}
425+
ExportedSymbol::AsyncDropGlue(def_id, ty) => rustc_middle::ty::Instance {
426+
args: tcx.mk_args(&[ty.clone().into()]),
427+
def: rustc_middle::ty::InstanceKind::AsyncDropGlue(def_id, ty),
428+
},
429+
ExportedSymbol::NonGeneric(..)
430+
| ExportedSymbol::ThreadLocalShim(..)
431+
| ExportedSymbol::NoDefId(..) => unreachable!("{exported_symbol:?}"),
432+
};
441433

434+
tcx.with_stable_hashing_context(|mut tcx| {
435+
let mut hasher = rustc_data_structures::stable_hasher::StableHasher::new();
436+
instance.hash_stable(&mut tcx, &mut hasher);
437+
instances.insert(hasher.finish());
438+
});
439+
}
442440
instances
443441
}
444442

445-
fn upstream_monomorphizations_for_provider(
446-
tcx: TyCtxt<'_>,
447-
def_id: DefId,
448-
) -> Option<&UnordMap<GenericArgsRef<'_>, CrateNum>> {
449-
assert!(!def_id.is_local());
450-
tcx.upstream_monomorphizations(()).get(&def_id)
451-
}
443+
fn upstream_monomorphizations_provider(tcx: TyCtxt<'_>, _: ()) -> FxIndexMap<Hash128, CrateNum> {
444+
let cnums = tcx.crates(());
445+
let mut instances: FxIndexMap<Hash128, CrateNum> = Default::default();
452446

453-
fn upstream_drop_glue_for_provider<'tcx>(
454-
tcx: TyCtxt<'tcx>,
455-
args: GenericArgsRef<'tcx>,
456-
) -> Option<CrateNum> {
457-
let def_id = tcx.lang_items().drop_in_place_fn()?;
458-
tcx.upstream_monomorphizations_for(def_id)?.get(&args).cloned()
459-
}
447+
for cnum in cnums.iter() {
448+
let hashes = tcx.upstream_monomorphizations_of_crate(*cnum);
449+
for hash in hashes {
450+
instances.entry(*hash).or_insert(*cnum);
451+
}
452+
}
460453

461-
fn upstream_async_drop_glue_for_provider<'tcx>(
462-
tcx: TyCtxt<'tcx>,
463-
args: GenericArgsRef<'tcx>,
464-
) -> Option<CrateNum> {
465-
let def_id = tcx.lang_items().async_drop_in_place_fn()?;
466-
tcx.upstream_monomorphizations_for(def_id)?.get(&args).cloned()
454+
instances
467455
}
468456

469457
fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
@@ -477,12 +465,9 @@ pub(crate) fn provide(providers: &mut Providers) {
477465
providers.exported_generic_symbols = exported_generic_symbols_provider_local;
478466
providers.upstream_monomorphizations = upstream_monomorphizations_provider;
479467
providers.is_unreachable_local_definition = is_unreachable_local_definition_provider;
480-
providers.upstream_drop_glue_for = upstream_drop_glue_for_provider;
481-
providers.upstream_async_drop_glue_for = upstream_async_drop_glue_for_provider;
482468
providers.wasm_import_module_map = wasm_import_module_map;
483469
providers.extern_queries.is_reachable_non_generic = is_reachable_non_generic_provider_extern;
484-
providers.extern_queries.upstream_monomorphizations_for =
485-
upstream_monomorphizations_for_provider;
470+
providers.upstream_monomorphizations_of_crate = upstream_monomorphizations_of_crate_provider;
486471
}
487472

488473
pub(crate) fn allocator_shim_symbols(

compiler/rustc_middle/src/query/mod.rs

Lines changed: 6 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ use rustc_data_structures::steal::Steal;
7676
use rustc_data_structures::svh::Svh;
7777
use rustc_data_structures::unord::{UnordMap, UnordSet};
7878
use rustc_errors::ErrorGuaranteed;
79+
use rustc_hashes::Hash128;
7980
use rustc_hir::attrs::StrippedCfgItem;
8081
use rustc_hir::def::{DefKind, DocLinkResMap};
8182
use rustc_hir::def_id::{
@@ -1960,65 +1961,15 @@ rustc_queries! {
19601961
/// crate. Instead use the narrower `upstream_monomorphizations_for`,
19611962
/// `upstream_drop_glue_for`, `upstream_async_drop_glue_for`, or,
19621963
/// even better, `Instance::upstream_monomorphization()`.
1963-
query upstream_monomorphizations(_: ()) -> &'tcx DefIdMap<UnordMap<GenericArgsRef<'tcx>, CrateNum>> {
1964+
query upstream_monomorphizations(_: ()) -> &'tcx FxIndexMap<Hash128, CrateNum> {
19641965
arena_cache
19651966
desc { "collecting available upstream monomorphizations" }
19661967
}
19671968

1968-
/// Returns the set of upstream monomorphizations available for the
1969-
/// generic function identified by the given `def_id`. The query makes
1970-
/// sure to make a stable selection if the same monomorphization is
1971-
/// available in multiple upstream crates.
1972-
///
1973-
/// You likely want to call `Instance::upstream_monomorphization()`
1974-
/// instead of invoking this query directly.
1975-
query upstream_monomorphizations_for(def_id: DefId)
1976-
-> Option<&'tcx UnordMap<GenericArgsRef<'tcx>, CrateNum>>
1977-
{
1978-
desc { |tcx|
1979-
"collecting available upstream monomorphizations for `{}`",
1980-
tcx.def_path_str(def_id),
1981-
}
1982-
separate_provide_extern
1983-
}
1984-
1985-
/// Returns the upstream crate that exports drop-glue for the given
1986-
/// type (`args` is expected to be a single-item list containing the
1987-
/// type one wants drop-glue for).
1988-
///
1989-
/// This is a subset of `upstream_monomorphizations_for` in order to
1990-
/// increase dep-tracking granularity. Otherwise adding or removing any
1991-
/// type with drop-glue in any upstream crate would invalidate all
1992-
/// functions calling drop-glue of an upstream type.
1993-
///
1994-
/// You likely want to call `Instance::upstream_monomorphization()`
1995-
/// instead of invoking this query directly.
1996-
///
1997-
/// NOTE: This query could easily be extended to also support other
1998-
/// common functions that have are large set of monomorphizations
1999-
/// (like `Clone::clone` for example).
2000-
query upstream_drop_glue_for(args: GenericArgsRef<'tcx>) -> Option<CrateNum> {
2001-
desc { "available upstream drop-glue for `{:?}`", args }
2002-
}
2003-
2004-
/// Returns the upstream crate that exports async-drop-glue for
2005-
/// the given type (`args` is expected to be a single-item list
2006-
/// containing the type one wants async-drop-glue for).
2007-
///
2008-
/// This is a subset of `upstream_monomorphizations_for` in order
2009-
/// to increase dep-tracking granularity. Otherwise adding or
2010-
/// removing any type with async-drop-glue in any upstream crate
2011-
/// would invalidate all functions calling async-drop-glue of an
2012-
/// upstream type.
2013-
///
2014-
/// You likely want to call `Instance::upstream_monomorphization()`
2015-
/// instead of invoking this query directly.
2016-
///
2017-
/// NOTE: This query could easily be extended to also support other
2018-
/// common functions that have are large set of monomorphizations
2019-
/// (like `Clone::clone` for example).
2020-
query upstream_async_drop_glue_for(args: GenericArgsRef<'tcx>) -> Option<CrateNum> {
2021-
desc { "available upstream async-drop-glue for `{:?}`", args }
1969+
query upstream_monomorphizations_of_crate(_: CrateNum) -> &'tcx FxIndexSet<Hash128> {
1970+
arena_cache
1971+
cache_on_disk_if { true }
1972+
desc { "collecting available upstream monomorphizations for crate" }
20221973
}
20231974

20241975
/// Returns a list of all `extern` blocks of a crate.

compiler/rustc_middle/src/ty/instance.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ use std::assert_matches::assert_matches;
22
use std::fmt;
33

44
use rustc_data_structures::fx::FxHashMap;
5+
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
56
use rustc_errors::ErrorGuaranteed;
7+
use rustc_hashes::Hash128;
68
use rustc_hir as hir;
79
use rustc_hir::def::{CtorKind, DefKind, Namespace};
810
use rustc_hir::def_id::{CrateNum, DefId};
@@ -224,18 +226,25 @@ impl<'tcx> Instance<'tcx> {
224226
return None;
225227
}
226228

227-
match self.def {
228-
InstanceKind::Item(def) => tcx
229-
.upstream_monomorphizations_for(def)
230-
.and_then(|monos| monos.get(&self.args).cloned()),
231-
InstanceKind::DropGlue(_, Some(_)) => tcx.upstream_drop_glue_for(self.args),
229+
let defining_crates = match self.def {
230+
InstanceKind::Item(_)
231+
| InstanceKind::DropGlue(_, Some(_))
232+
| InstanceKind::AsyncDropGlueCtorShim(_, _) => {
233+
let hash: Hash128 = tcx.with_stable_hashing_context(|mut hcx| {
234+
let mut hasher = StableHasher::new();
235+
self.hash_stable(&mut hcx, &mut hasher);
236+
hasher.finish()
237+
});
238+
tcx.upstream_monomorphizations(()).get(&hash)
239+
}
240+
232241
InstanceKind::AsyncDropGlue(_, _) => None,
233242
InstanceKind::FutureDropPollShim(_, _, _) => None,
234-
InstanceKind::AsyncDropGlueCtorShim(_, _) => {
235-
tcx.upstream_async_drop_glue_for(self.args)
236-
}
243+
237244
_ => None,
238-
}
245+
}?;
246+
247+
Some(*defining_crates)
239248
}
240249
}
241250

0 commit comments

Comments
 (0)