1
Fork 0

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:
bors 2021-01-13 17:48:41 +00:00
commit 9bc8b00b4a

View file

@ -66,6 +66,11 @@ pub(super) struct EncodeContext<'a, 'tcx> {
required_source_files: Option<GrowableBitSet<usize>>, required_source_files: Option<GrowableBitSet<usize>>,
is_proc_macro: bool, is_proc_macro: bool,
hygiene_ctxt: &'a HygieneEncodeContext, 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()`. /// If the current crate is a proc-macro, returns early with `Lazy:empty()`.
@ -787,9 +792,11 @@ impl EncodeContext<'a, 'tcx> {
self.encode_generics(def_id); self.encode_generics(def_id);
self.encode_explicit_predicates(def_id); self.encode_explicit_predicates(def_id);
self.encode_inferred_outlives(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_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]) { fn encode_info_for_mod(&mut self, id: hir::HirId, md: &hir::Mod<'_>, attrs: &[ast::Attribute]) {
@ -895,9 +902,11 @@ impl EncodeContext<'a, 'tcx> {
self.encode_generics(def_id); self.encode_generics(def_id);
self.encode_explicit_predicates(def_id); self.encode_explicit_predicates(def_id);
self.encode_inferred_outlives(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_mir_for_ctfe(def_id.expect_local());
self.encode_promoted_mir(def_id.expect_local());
} }
fn encode_generics(&mut self, def_id: DefId) { fn encode_generics(&mut self, def_id: DefId) {
@ -1024,17 +1033,23 @@ impl EncodeContext<'a, 'tcx> {
} }
} }
ty::AssocKind::Fn => { ty::AssocKind::Fn => {
if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id.expect_local()) { let opt_mir =
self.encode_optimized_mir(def_id.expect_local()); tcx.sess.opts.debugging_opts.always_encode_mir || self.emit_codegen_mir;
self.encode_promoted_mir(def_id.expect_local()); 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 { fn should_encode_fn_opt_mir(&self, def_id: DefId) -> bool {
// MIR optimisation can be skipped when we're just interested in the metadata. self.tcx.sess.opts.debugging_opts.always_encode_mir
!self.tcx.sess.opts.output_types.should_codegen() || (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) { fn encode_info_for_impl_item(&mut self, def_id: DefId) {
@ -1105,13 +1120,9 @@ impl EncodeContext<'a, 'tcx> {
let (mir, mir_const) = match ast_item.kind { let (mir, mir_const) = match ast_item.kind {
hir::ImplItemKind::Const(..) => (false, true), hir::ImplItemKind::Const(..) => (false, true),
hir::ImplItemKind::Fn(ref sig, _) => { hir::ImplItemKind::Fn(ref sig, _) => {
let generics = self.tcx.generics_of(def_id); let opt_mir = self.should_encode_fn_opt_mir(def_id);
let needs_inline = (generics.requires_monomorphization(self.tcx)
|| tcx.codegen_fn_attrs(def_id).requests_inline())
&& !self.metadata_output_only();
let is_const_fn = sig.header.constness == hir::Constness::Const; let is_const_fn = sig.header.constness == hir::Constness::Const;
let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; (opt_mir, is_const_fn)
(needs_inline || always_encode_mir, is_const_fn)
} }
hir::ImplItemKind::TyAlias(..) => (false, false), hir::ImplItemKind::TyAlias(..) => (false, false),
}; };
@ -1433,16 +1444,10 @@ impl EncodeContext<'a, 'tcx> {
let (mir, const_mir) = match item.kind { let (mir, const_mir) = match item.kind {
hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => (false, true), hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => (false, true),
hir::ItemKind::Fn(ref sig, ..) => { hir::ItemKind::Fn(ref sig, ..) => {
let generics = tcx.generics_of(def_id); let opt_mir = self.should_encode_fn_opt_mir(def_id);
let needs_inline = (generics.requires_monomorphization(tcx)
|| tcx.codegen_fn_attrs(def_id).requests_inline())
&& !self.metadata_output_only();
let is_const_fn = sig.header.constness == hir::Constness::Const; 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. // We don't need the optimized MIR for const fns.
(mir, is_const_fn) (opt_mir, is_const_fn)
} }
_ => (false, false), _ => (false, false),
}; };
@ -1502,8 +1507,11 @@ impl EncodeContext<'a, 'tcx> {
record!(self.tables.fn_sig[def_id] <- substs.as_closure().sig()); record!(self.tables.fn_sig[def_id] <- substs.as_closure().sig());
} }
self.encode_generics(def_id.to_def_id()); self.encode_generics(def_id.to_def_id());
self.encode_optimized_mir(def_id); let opt_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir || self.emit_codegen_mir;
self.encode_promoted_mir(def_id); 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) { fn encode_info_for_anon_const(&mut self, def_id: LocalDefId) {
@ -2008,10 +2016,9 @@ impl<'tcx, 'v> ParItemLikeVisitor<'v> for PrefetchVisitor<'tcx> {
} }
hir::ItemKind::Fn(ref sig, ..) => { hir::ItemKind::Fn(ref sig, ..) => {
let def_id = tcx.hir().local_def_id(item.hir_id); let def_id = tcx.hir().local_def_id(item.hir_id);
let generics = tcx.generics_of(def_id.to_def_id()); let opt_mir = tcx.generics_of(def_id.to_def_id()).requires_monomorphization(tcx)
let needs_inline = generics.requires_monomorphization(tcx)
|| tcx.codegen_fn_attrs(def_id.to_def_id()).requests_inline(); || tcx.codegen_fn_attrs(def_id.to_def_id()).requests_inline();
if needs_inline { if opt_mir {
self.prefetch_mir(def_id) self.prefetch_mir(def_id)
} }
if sig.header.constness == hir::Constness::Const { if sig.header.constness == hir::Constness::Const {
@ -2045,11 +2052,10 @@ impl<'tcx, 'v> ParItemLikeVisitor<'v> for PrefetchVisitor<'tcx> {
} }
hir::ImplItemKind::Fn(ref sig, _) => { hir::ImplItemKind::Fn(ref sig, _) => {
let def_id = tcx.hir().local_def_id(impl_item.hir_id); let def_id = tcx.hir().local_def_id(impl_item.hir_id);
let generics = tcx.generics_of(def_id.to_def_id()); let opt_mir = tcx.generics_of(def_id.to_def_id()).requires_monomorphization(tcx)
let needs_inline = generics.requires_monomorphization(tcx)
|| tcx.codegen_fn_attrs(def_id.to_def_id()).requests_inline(); || tcx.codegen_fn_attrs(def_id.to_def_id()).requests_inline();
let is_const_fn = sig.header.constness == hir::Constness::Const; let is_const_fn = sig.header.constness == hir::Constness::Const;
if needs_inline { if opt_mir {
self.prefetch_mir(def_id) self.prefetch_mir(def_id)
} }
if is_const_fn { if is_const_fn {
@ -2148,6 +2154,7 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata {
required_source_files, required_source_files,
is_proc_macro: tcx.sess.crate_types().contains(&CrateType::ProcMacro), is_proc_macro: tcx.sess.crate_types().contains(&CrateType::ProcMacro),
hygiene_ctxt: &hygiene_ctxt, hygiene_ctxt: &hygiene_ctxt,
emit_codegen_mir: tcx.sess.opts.output_types.should_codegen(),
}; };
// Encode the rustc version string in a predictable location. // Encode the rustc version string in a predictable location.