Auto merge of #80718 - tmiasko:skip-opt-mir, r=oli-obk
Consistently avoid constructing optimized MIR when not doing codegen The optimized MIR for closures is being encoded unconditionally, while being unnecessary for cargo check. This turns out to be especially costly with MIR inlining enabled, since it triggers computation of optimized MIR for all callees that are being examined for inlining purposes https://github.com/rust-lang/rust/pull/77307#issuecomment-751915450. Skip encoding of optimized MIR for closures, enum constructors, struct constructors, and trait fns when not doing codegen, like it is already done for other items since 49433.
This commit is contained in:
commit
9bc8b00b4a
@ -66,6 +66,11 @@ pub(super) struct EncodeContext<'a, 'tcx> {
|
||||
required_source_files: Option<GrowableBitSet<usize>>,
|
||||
is_proc_macro: bool,
|
||||
hygiene_ctxt: &'a HygieneEncodeContext,
|
||||
|
||||
// Determines if MIR used for code generation will be included in the crate
|
||||
// metadata. When emitting only metadata (e.g., cargo check), we can avoid
|
||||
// generating optimized MIR altogether.
|
||||
emit_codegen_mir: bool,
|
||||
}
|
||||
|
||||
/// If the current crate is a proc-macro, returns early with `Lazy:empty()`.
|
||||
@ -787,9 +792,11 @@ fn encode_enum_variant_ctor(&mut self, def: &ty::AdtDef, index: VariantIdx) {
|
||||
self.encode_generics(def_id);
|
||||
self.encode_explicit_predicates(def_id);
|
||||
self.encode_inferred_outlives(def_id);
|
||||
let opt_mir = tcx.sess.opts.debugging_opts.always_encode_mir || self.emit_codegen_mir;
|
||||
if opt_mir {
|
||||
self.encode_optimized_mir(def_id.expect_local());
|
||||
}
|
||||
self.encode_mir_for_ctfe(def_id.expect_local());
|
||||
self.encode_optimized_mir(def_id.expect_local());
|
||||
self.encode_promoted_mir(def_id.expect_local());
|
||||
}
|
||||
|
||||
fn encode_info_for_mod(&mut self, id: hir::HirId, md: &hir::Mod<'_>, attrs: &[ast::Attribute]) {
|
||||
@ -895,9 +902,11 @@ fn encode_struct_ctor(&mut self, adt_def: &ty::AdtDef, def_id: DefId) {
|
||||
self.encode_generics(def_id);
|
||||
self.encode_explicit_predicates(def_id);
|
||||
self.encode_inferred_outlives(def_id);
|
||||
self.encode_optimized_mir(def_id.expect_local());
|
||||
let opt_mir = tcx.sess.opts.debugging_opts.always_encode_mir || self.emit_codegen_mir;
|
||||
if opt_mir {
|
||||
self.encode_optimized_mir(def_id.expect_local());
|
||||
}
|
||||
self.encode_mir_for_ctfe(def_id.expect_local());
|
||||
self.encode_promoted_mir(def_id.expect_local());
|
||||
}
|
||||
|
||||
fn encode_generics(&mut self, def_id: DefId) {
|
||||
@ -1024,17 +1033,23 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) {
|
||||
}
|
||||
}
|
||||
ty::AssocKind::Fn => {
|
||||
if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id.expect_local()) {
|
||||
self.encode_optimized_mir(def_id.expect_local());
|
||||
self.encode_promoted_mir(def_id.expect_local());
|
||||
let opt_mir =
|
||||
tcx.sess.opts.debugging_opts.always_encode_mir || self.emit_codegen_mir;
|
||||
if opt_mir {
|
||||
if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id.expect_local()) {
|
||||
self.encode_optimized_mir(def_id.expect_local());
|
||||
self.encode_promoted_mir(def_id.expect_local());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn metadata_output_only(&self) -> bool {
|
||||
// MIR optimisation can be skipped when we're just interested in the metadata.
|
||||
!self.tcx.sess.opts.output_types.should_codegen()
|
||||
fn should_encode_fn_opt_mir(&self, def_id: DefId) -> bool {
|
||||
self.tcx.sess.opts.debugging_opts.always_encode_mir
|
||||
|| (self.emit_codegen_mir
|
||||
&& (self.tcx.generics_of(def_id).requires_monomorphization(self.tcx)
|
||||
|| self.tcx.codegen_fn_attrs(def_id).requests_inline()))
|
||||
}
|
||||
|
||||
fn encode_info_for_impl_item(&mut self, def_id: DefId) {
|
||||
@ -1105,13 +1120,9 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) {
|
||||
let (mir, mir_const) = match ast_item.kind {
|
||||
hir::ImplItemKind::Const(..) => (false, true),
|
||||
hir::ImplItemKind::Fn(ref sig, _) => {
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
let needs_inline = (generics.requires_monomorphization(self.tcx)
|
||||
|| tcx.codegen_fn_attrs(def_id).requests_inline())
|
||||
&& !self.metadata_output_only();
|
||||
let opt_mir = self.should_encode_fn_opt_mir(def_id);
|
||||
let is_const_fn = sig.header.constness == hir::Constness::Const;
|
||||
let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
|
||||
(needs_inline || always_encode_mir, is_const_fn)
|
||||
(opt_mir, is_const_fn)
|
||||
}
|
||||
hir::ImplItemKind::TyAlias(..) => (false, false),
|
||||
};
|
||||
@ -1433,16 +1444,10 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item<'tcx>) {
|
||||
let (mir, const_mir) = match item.kind {
|
||||
hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => (false, true),
|
||||
hir::ItemKind::Fn(ref sig, ..) => {
|
||||
let generics = tcx.generics_of(def_id);
|
||||
let needs_inline = (generics.requires_monomorphization(tcx)
|
||||
|| tcx.codegen_fn_attrs(def_id).requests_inline())
|
||||
&& !self.metadata_output_only();
|
||||
|
||||
let opt_mir = self.should_encode_fn_opt_mir(def_id);
|
||||
let is_const_fn = sig.header.constness == hir::Constness::Const;
|
||||
let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
|
||||
let mir = needs_inline || always_encode_mir;
|
||||
// We don't need the optimized MIR for const fns.
|
||||
(mir, is_const_fn)
|
||||
(opt_mir, is_const_fn)
|
||||
}
|
||||
_ => (false, false),
|
||||
};
|
||||
@ -1502,8 +1507,11 @@ fn encode_info_for_closure(&mut self, def_id: LocalDefId) {
|
||||
record!(self.tables.fn_sig[def_id] <- substs.as_closure().sig());
|
||||
}
|
||||
self.encode_generics(def_id.to_def_id());
|
||||
self.encode_optimized_mir(def_id);
|
||||
self.encode_promoted_mir(def_id);
|
||||
let opt_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir || self.emit_codegen_mir;
|
||||
if opt_mir {
|
||||
self.encode_optimized_mir(def_id);
|
||||
self.encode_promoted_mir(def_id);
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_info_for_anon_const(&mut self, def_id: LocalDefId) {
|
||||
@ -2008,10 +2016,9 @@ fn visit_item(&self, item: &hir::Item<'_>) {
|
||||
}
|
||||
hir::ItemKind::Fn(ref sig, ..) => {
|
||||
let def_id = tcx.hir().local_def_id(item.hir_id);
|
||||
let generics = tcx.generics_of(def_id.to_def_id());
|
||||
let needs_inline = generics.requires_monomorphization(tcx)
|
||||
let opt_mir = tcx.generics_of(def_id.to_def_id()).requires_monomorphization(tcx)
|
||||
|| tcx.codegen_fn_attrs(def_id.to_def_id()).requests_inline();
|
||||
if needs_inline {
|
||||
if opt_mir {
|
||||
self.prefetch_mir(def_id)
|
||||
}
|
||||
if sig.header.constness == hir::Constness::Const {
|
||||
@ -2045,11 +2052,10 @@ fn visit_impl_item(&self, impl_item: &'v hir::ImplItem<'v>) {
|
||||
}
|
||||
hir::ImplItemKind::Fn(ref sig, _) => {
|
||||
let def_id = tcx.hir().local_def_id(impl_item.hir_id);
|
||||
let generics = tcx.generics_of(def_id.to_def_id());
|
||||
let needs_inline = generics.requires_monomorphization(tcx)
|
||||
let opt_mir = tcx.generics_of(def_id.to_def_id()).requires_monomorphization(tcx)
|
||||
|| tcx.codegen_fn_attrs(def_id.to_def_id()).requests_inline();
|
||||
let is_const_fn = sig.header.constness == hir::Constness::Const;
|
||||
if needs_inline {
|
||||
if opt_mir {
|
||||
self.prefetch_mir(def_id)
|
||||
}
|
||||
if is_const_fn {
|
||||
@ -2148,6 +2154,7 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata {
|
||||
required_source_files,
|
||||
is_proc_macro: tcx.sess.crate_types().contains(&CrateType::ProcMacro),
|
||||
hygiene_ctxt: &hygiene_ctxt,
|
||||
emit_codegen_mir: tcx.sess.opts.output_types.should_codegen(),
|
||||
};
|
||||
|
||||
// Encode the rustc version string in a predictable location.
|
||||
|
Loading…
Reference in New Issue
Block a user