Skip to content

Commit 292dbc9

Browse files
committed
Auto merge of #132566 - saethlin:querify-mir-collection, r=<try>
Querify mir collection Factored out of #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
2 parents e3a918e + 7155c30 commit 292dbc9

File tree

9 files changed

+128
-63
lines changed

9 files changed

+128
-63
lines changed

compiler/rustc_middle/src/mir/mono.rs

+48-25
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use rustc_target::spec::SymbolVisibility;
1919
use tracing::debug;
2020

2121
use crate::dep_graph::{DepNode, WorkProduct, WorkProductId};
22+
use crate::query::Providers;
2223
use crate::ty::{GenericArgs, Instance, InstanceKind, SymbolName, TyCtxt};
2324

2425
/// Describes how a monomorphization will be instantiated in object files.
@@ -46,7 +47,7 @@ pub enum InstantiationMode {
4647
LocalCopy,
4748
}
4849

49-
#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash, HashStable)]
50+
#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash, HashStable, TyEncodable, TyDecodable)]
5051
pub enum MonoItem<'tcx> {
5152
Fn(Instance<'tcx>),
5253
Static(DefId),
@@ -62,30 +63,6 @@ impl<'tcx> MonoItem<'tcx> {
6263
}
6364
}
6465

65-
// Note: if you change how item size estimates work, you might need to
66-
// change NON_INCR_MIN_CGU_SIZE as well.
67-
pub fn size_estimate(&self, tcx: TyCtxt<'tcx>) -> usize {
68-
match *self {
69-
MonoItem::Fn(instance) => {
70-
match instance.def {
71-
// "Normal" functions size estimate: the number of
72-
// statements, plus one for the terminator.
73-
InstanceKind::Item(..)
74-
| InstanceKind::DropGlue(..)
75-
| InstanceKind::AsyncDropGlueCtorShim(..) => {
76-
let mir = tcx.instance_mir(instance.def);
77-
mir.basic_blocks.iter().map(|bb| bb.statements.len() + 1).sum()
78-
}
79-
// Other compiler-generated shims size estimate: 1
80-
_ => 1,
81-
}
82-
}
83-
// Conservatively estimate the size of a static declaration or
84-
// assembly item to be 1.
85-
MonoItem::Static(_) | MonoItem::GlobalAsm(_) => 1,
86-
}
87-
}
88-
8966
pub fn is_generic_fn(&self) -> bool {
9067
match self {
9168
MonoItem::Fn(instance) => instance.args.non_erasable_generics().next().is_some(),
@@ -556,3 +533,49 @@ impl<'tcx> CodegenUnitNameBuilder<'tcx> {
556533
Symbol::intern(&cgu_name)
557534
}
558535
}
536+
537+
/// See module-level docs on some contect for "mentioned" items.
538+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
539+
pub enum CollectionMode {
540+
/// Collect items that are used, i.e., actually needed for codegen.
541+
///
542+
/// Which items are used can depend on optimization levels, as MIR optimizations can remove
543+
/// uses.
544+
UsedItems,
545+
/// Collect items that are mentioned. The goal of this mode is that it is independent of
546+
/// optimizations: the set of "mentioned" items is computed before optimizations are run.
547+
///
548+
/// The exact contents of this set are *not* a stable guarantee. (For instance, it is currently
549+
/// computed after drop-elaboration. If we ever do some optimizations even in debug builds, we
550+
/// might decide to run them before computing mentioned items.) The key property of this set is
551+
/// that it is optimization-independent.
552+
MentionedItems,
553+
}
554+
555+
// Note: if you change how item size estimates work, you might need to
556+
// change NON_INCR_MIN_CGU_SIZE as well.
557+
fn size_estimate<'tcx>(tcx: TyCtxt<'tcx>, item: MonoItem<'tcx>) -> usize {
558+
match item {
559+
MonoItem::Fn(instance) => {
560+
match instance.def {
561+
// "Normal" functions size estimate: the number of
562+
// statements, plus one for the terminator.
563+
InstanceKind::Item(..)
564+
| InstanceKind::DropGlue(..)
565+
| InstanceKind::AsyncDropGlueCtorShim(..) => {
566+
let mir = tcx.instance_mir(instance.def);
567+
mir.basic_blocks.iter().map(|bb| bb.statements.len() + 1).sum()
568+
}
569+
// Other compiler-generated shims size estimate: 1
570+
_ => 1,
571+
}
572+
}
573+
// Conservatively estimate the size of a static declaration or
574+
// assembly item to be 1.
575+
MonoItem::Static(_) | MonoItem::GlobalAsm(_) => 1,
576+
}
577+
}
578+
579+
pub fn provide(providers: &mut Providers) {
580+
providers.size_estimate = size_estimate;
581+
}

compiler/rustc_middle/src/query/erase.rs

+4
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,10 @@ impl<T0, T1> EraseType for (&'_ T0, &'_ [T1]) {
218218
type Result = [u8; size_of::<(&'static (), &'static [()])>()];
219219
}
220220

221+
impl<T0, T1> EraseType for (&'_ [T0], &'_ [T1]) {
222+
type Result = [u8; size_of::<(&'static [()], &'static [()])>()];
223+
}
224+
221225
impl<T0> EraseType for (&'_ T0, Result<(), ErrorGuaranteed>) {
222226
type Result = [u8; size_of::<(&'static (), Result<(), ErrorGuaranteed>)>()];
223227
}

compiler/rustc_middle/src/query/keys.rs

+18
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ use rustc_span::{DUMMY_SP, Span};
88
use rustc_target::abi;
99

1010
use crate::infer::canonical::CanonicalQueryInput;
11+
use crate::mir::mono::CollectionMode;
12+
use crate::query::MonoItem;
1113
use crate::ty::fast_reject::SimplifiedType;
1214
use crate::ty::layout::{TyAndLayout, ValidityRequirement};
1315
use crate::ty::{self, GenericArg, GenericArgsRef, Ty, TyCtxt};
@@ -86,6 +88,14 @@ impl<'tcx> Key for ty::Instance<'tcx> {
8688
}
8789
}
8890

91+
impl<'tcx> Key for MonoItem<'tcx> {
92+
type Cache<V> = DefaultCache<Self, V>;
93+
94+
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
95+
tcx.def_span(self.def_id())
96+
}
97+
}
98+
8999
impl<'tcx> Key for mir::interpret::GlobalId<'tcx> {
90100
type Cache<V> = DefaultCache<Self, V>;
91101

@@ -591,3 +601,11 @@ impl<'tcx> Key for (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>) {
591601
}
592602
}
593603
}
604+
605+
impl<'tcx> Key for (ty::Instance<'tcx>, CollectionMode) {
606+
type Cache<V> = DefaultCache<Self, V>;
607+
608+
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
609+
self.0.default_span(tcx)
610+
}
611+
}

compiler/rustc_middle/src/query/mod.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ use rustc_session::cstore::{
4040
};
4141
use rustc_session::lint::LintExpectationId;
4242
use rustc_span::def_id::LOCAL_CRATE;
43+
use rustc_span::source_map::Spanned;
4344
use rustc_span::symbol::Symbol;
4445
use rustc_span::{DUMMY_SP, Span};
4546
use rustc_target::abi;
@@ -60,7 +61,7 @@ use crate::mir::interpret::{
6061
EvalStaticInitializerRawResult, EvalToAllocationRawResult, EvalToConstValueResult,
6162
EvalToValTreeResult, GlobalId, LitToConstError, LitToConstInput,
6263
};
63-
use crate::mir::mono::CodegenUnit;
64+
use crate::mir::mono::{CodegenUnit, CollectionMode, MonoItem};
6465
use crate::query::erase::{Erase, erase, restore};
6566
use crate::query::plumbing::{
6667
CyclePlaceholder, DynamicQuery, query_ensure, query_ensure_error_guaranteed, query_get_at,
@@ -2315,6 +2316,16 @@ rustc_queries! {
23152316
desc { "whether the item should be made inlinable across crates" }
23162317
separate_provide_extern
23172318
}
2319+
2320+
query items_of_instance(key: (ty::Instance<'tcx>, CollectionMode)) -> (&'tcx [Spanned<MonoItem<'tcx>>], &'tcx [Spanned<MonoItem<'tcx>>]) {
2321+
desc { "collecting items used by `{}`", key.0 }
2322+
cache_on_disk_if { true }
2323+
}
2324+
2325+
query size_estimate(key: MonoItem<'tcx>) -> usize {
2326+
desc { "estimating codegen size of `{}`", key }
2327+
cache_on_disk_if { true }
2328+
}
23182329
}
23192330

23202331
rustc_query_append! { define_callbacks! }

compiler/rustc_middle/src/query/on_disk_cache.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use rustc_index::{Idx, IndexVec};
1212
use rustc_macros::{Decodable, Encodable};
1313
use rustc_middle::dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
1414
use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
15+
use rustc_middle::mir::mono::MonoItem;
1516
use rustc_middle::mir::{self, interpret};
1617
use rustc_middle::ty::codec::{RefDecodable, TyDecoder, TyEncoder};
1718
use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -22,7 +23,7 @@ use rustc_session::Session;
2223
use rustc_span::hygiene::{
2324
ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextData,
2425
};
25-
use rustc_span::source_map::SourceMap;
26+
use rustc_span::source_map::{SourceMap, Spanned};
2627
use rustc_span::{
2728
BytePos, CachingSourceMapView, ExpnData, ExpnHash, Pos, RelativeBytePos, SourceFile, Span,
2829
SpanDecoder, SpanEncoder, StableSourceFileId, Symbol,
@@ -773,6 +774,13 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [rustc_ast::InlineAsm
773774
}
774775
}
775776

777+
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx [Spanned<MonoItem<'tcx>>] {
778+
#[inline]
779+
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
780+
RefDecodable::decode(d)
781+
}
782+
}
783+
776784
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>>
777785
for &'tcx crate::traits::specialization_graph::Graph
778786
{

compiler/rustc_middle/src/ty/codec.rs

+11
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ use std::marker::DiscriminantKind;
1212

1313
use rustc_data_structures::fx::FxHashMap;
1414
use rustc_hir::def_id::LocalDefId;
15+
use rustc_middle::mir::mono::MonoItem;
1516
use rustc_middle::ty::TyCtxt;
1617
use rustc_serialize::{Decodable, Encodable};
1718
use rustc_span::Span;
19+
use rustc_span::source_map::Spanned;
1820
use rustc_target::abi::{FieldIdx, VariantIdx};
1921
pub use rustc_type_ir::{TyDecoder, TyEncoder};
2022

@@ -397,6 +399,15 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
397399
}
398400
}
399401

402+
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for [Spanned<MonoItem<'tcx>>] {
403+
fn decode(decoder: &mut D) -> &'tcx Self {
404+
decoder
405+
.interner()
406+
.arena
407+
.alloc_from_iter((0..decoder.read_usize()).map(|_| Decodable::decode(decoder)))
408+
}
409+
}
410+
400411
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
401412
for ty::List<ty::BoundVariableKind>
402413
{

compiler/rustc_middle/src/ty/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2155,6 +2155,7 @@ pub fn provide(providers: &mut Providers) {
21552155
print::provide(providers);
21562156
super::util::bug::provide(providers);
21572157
super::middle::provide(providers);
2158+
super::mir::mono::provide(providers);
21582159
*providers = Providers {
21592160
trait_impls_of: trait_def::trait_impls_of_provider,
21602161
incoherent_impls: trait_def::incoherent_impls_provider,

compiler/rustc_monomorphize/src/collector.rs

+22-33
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
219219
use rustc_hir::lang_items::LangItem;
220220
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
221221
use rustc_middle::mir::interpret::{AllocId, ErrorHandled, GlobalAlloc, Scalar};
222-
use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
222+
use rustc_middle::mir::mono::{CollectionMode, InstantiationMode, MonoItem};
223223
use rustc_middle::mir::visit::Visitor as MirVisitor;
224224
use rustc_middle::mir::{self, Location, MentionedItem, traversal};
225225
use rustc_middle::query::TyCtxtAt;
@@ -268,24 +268,6 @@ struct SharedState<'tcx> {
268268
usage_map: MTLock<UsageMap<'tcx>>,
269269
}
270270

271-
/// See module-level docs on some contect for "mentioned" items.
272-
#[derive(Copy, Clone, Debug, PartialEq)]
273-
enum CollectionMode {
274-
/// Collect items that are used, i.e., actually needed for codegen.
275-
///
276-
/// Which items are used can depend on optimization levels, as MIR optimizations can remove
277-
/// uses.
278-
UsedItems,
279-
/// Collect items that are mentioned. The goal of this mode is that it is independent of
280-
/// optimizations: the set of "mentioned" items is computed before optimizations are run.
281-
///
282-
/// The exact contents of this set are *not* a stable guarantee. (For instance, it is currently
283-
/// computed after drop-elaboration. If we ever do some optimizations even in debug builds, we
284-
/// might decide to run them before computing mentioned items.) The key property of this set is
285-
/// that it is optimization-independent.
286-
MentionedItems,
287-
}
288-
289271
impl<'tcx> UsageMap<'tcx> {
290272
fn new() -> UsageMap<'tcx> {
291273
UsageMap { used_map: Default::default(), user_map: Default::default() }
@@ -447,13 +429,9 @@ fn collect_items_rec<'tcx>(
447429
));
448430

449431
rustc_data_structures::stack::ensure_sufficient_stack(|| {
450-
collect_items_of_instance(
451-
tcx,
452-
instance,
453-
&mut used_items,
454-
&mut mentioned_items,
455-
mode,
456-
)
432+
let (used, mentioned) = tcx.items_of_instance((instance, mode));
433+
used_items.extend(used);
434+
mentioned_items.extend(mentioned);
457435
});
458436
}
459437
MonoItem::GlobalAsm(item_id) => {
@@ -1199,14 +1177,12 @@ fn assoc_fn_of_type<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fn_ident: Ident) ->
11991177
/// Scans the MIR in order to find function calls, closures, and drop-glue.
12001178
///
12011179
/// Anything that's found is added to `output`. Furthermore the "mentioned items" of the MIR are returned.
1202-
#[instrument(skip(tcx, used_items, mentioned_items), level = "debug")]
1180+
#[instrument(skip(tcx), level = "debug")]
12031181
fn collect_items_of_instance<'tcx>(
12041182
tcx: TyCtxt<'tcx>,
12051183
instance: Instance<'tcx>,
1206-
used_items: &mut MonoItems<'tcx>,
1207-
mentioned_items: &mut MonoItems<'tcx>,
12081184
mode: CollectionMode,
1209-
) {
1185+
) -> (MonoItems<'tcx>, MonoItems<'tcx>) {
12101186
let body = tcx.instance_mir(instance.def);
12111187
// Naively, in "used" collection mode, all functions get added to *both* `used_items` and
12121188
// `mentioned_items`. Mentioned items processing will then notice that they have already been
@@ -1218,11 +1194,13 @@ fn collect_items_of_instance<'tcx>(
12181194
// mentioned item. So instead we collect all pre-monomorphized `MentionedItem` that were already
12191195
// added to `used_items` in a hash set, which can efficiently query in the
12201196
// `body.mentioned_items` loop below without even having to monomorphize the item.
1197+
let mut used_items = Default::default();
1198+
let mut mentioned_items = Default::default();
12211199
let mut used_mentioned_items = Default::default();
12221200
let mut collector = MirUsedCollector {
12231201
tcx,
12241202
body,
1225-
used_items,
1203+
used_items: &mut used_items,
12261204
used_mentioned_items: &mut used_mentioned_items,
12271205
instance,
12281206
visiting_call_terminator: false,
@@ -1239,7 +1217,7 @@ fn collect_items_of_instance<'tcx>(
12391217
// them errors.
12401218
for const_op in body.required_consts() {
12411219
if let Some(val) = collector.eval_constant(const_op) {
1242-
collect_const_value(tcx, val, mentioned_items);
1220+
collect_const_value(tcx, val, &mut mentioned_items);
12431221
}
12441222
}
12451223

@@ -1248,9 +1226,19 @@ fn collect_items_of_instance<'tcx>(
12481226
for item in body.mentioned_items() {
12491227
if !collector.used_mentioned_items.contains(&item.node) {
12501228
let item_mono = collector.monomorphize(item.node);
1251-
visit_mentioned_item(tcx, &item_mono, item.span, mentioned_items);
1229+
visit_mentioned_item(tcx, &item_mono, item.span, &mut mentioned_items);
12521230
}
12531231
}
1232+
1233+
(used_items, mentioned_items)
1234+
}
1235+
1236+
fn items_of_instance<'tcx>(
1237+
tcx: TyCtxt<'tcx>,
1238+
(instance, mode): (Instance<'tcx>, CollectionMode),
1239+
) -> (&'tcx [Spanned<MonoItem<'tcx>>], &'tcx [Spanned<MonoItem<'tcx>>]) {
1240+
let (used_items, mentioned_items) = collect_items_of_instance(tcx, instance, mode);
1241+
(tcx.arena.alloc_slice(&used_items), tcx.arena.alloc_slice(&mentioned_items))
12541242
}
12551243

12561244
/// `item` must be already monomorphized.
@@ -1623,4 +1611,5 @@ pub(crate) fn collect_crate_mono_items<'tcx>(
16231611

16241612
pub(crate) fn provide(providers: &mut Providers) {
16251613
providers.hooks.should_codegen_locally = should_codegen_locally;
1614+
providers.items_of_instance = items_of_instance;
16261615
}

compiler/rustc_monomorphize/src/partitioning.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ where
254254
if visibility == Visibility::Hidden && can_be_internalized {
255255
internalization_candidates.insert(mono_item);
256256
}
257-
let size_estimate = mono_item.size_estimate(cx.tcx);
257+
let size_estimate = cx.tcx.size_estimate(mono_item);
258258

259259
cgu.items_mut().insert(mono_item, MonoItemData {
260260
inlined: false,
@@ -279,7 +279,7 @@ where
279279
inlined: true,
280280
linkage: Linkage::Internal,
281281
visibility: Visibility::Default,
282-
size_estimate: inlined_item.size_estimate(cx.tcx),
282+
size_estimate: cx.tcx.size_estimate(inlined_item),
283283
});
284284
}
285285
}
@@ -1274,7 +1274,7 @@ fn dump_mono_items_stats<'tcx>(
12741274
.map(|(def_id, items)| {
12751275
let name = with_no_trimmed_paths!(tcx.def_path_str(def_id));
12761276
let instantiation_count = items.len();
1277-
let size_estimate = items[0].size_estimate(tcx);
1277+
let size_estimate = tcx.size_estimate(*items[0]);
12781278
let total_estimate = instantiation_count * size_estimate;
12791279
MonoItem { name, instantiation_count, size_estimate, total_estimate }
12801280
})

0 commit comments

Comments
 (0)