From 1bf3949398797dd499a18eb06953a7601b8eb146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Tue, 5 Jan 2021 00:00:00 +0000 Subject: [PATCH 1/3] Reorder MIR encoding checks Start from least expensive checks when deciding whether to encode MIR or not. No functional changes intended. --- compiler/rustc_metadata/src/rmeta/encoder.rs | 45 +++++++++----------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index ccaee8608b61..fd9908771072 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -66,6 +66,11 @@ pub(super) struct EncodeContext<'a, 'tcx> { required_source_files: Option>, 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()`. @@ -1032,11 +1037,6 @@ impl EncodeContext<'a, 'tcx> { } } - 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 encode_info_for_impl_item(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_impl_item({:?})", def_id); let tcx = self.tcx; @@ -1105,13 +1105,12 @@ impl EncodeContext<'a, 'tcx> { 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 = tcx.sess.opts.debugging_opts.always_encode_mir + || (self.emit_codegen_mir + && (tcx.generics_of(def_id).requires_monomorphization(tcx) + || tcx.codegen_fn_attrs(def_id).requests_inline())); 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 +1432,13 @@ impl EncodeContext<'a, '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.tcx.sess.opts.debugging_opts.always_encode_mir + || (self.emit_codegen_mir + && (tcx.generics_of(def_id).requires_monomorphization(tcx) + || tcx.codegen_fn_attrs(def_id).requests_inline())); 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), }; @@ -2008,10 +2004,9 @@ impl<'tcx, 'v> ParItemLikeVisitor<'v> for PrefetchVisitor<'tcx> { } 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 +2040,10 @@ impl<'tcx, 'v> ParItemLikeVisitor<'v> for PrefetchVisitor<'tcx> { } 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 +2142,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. From a6dd7b505615620a9181891db06d39b1b1043f30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Tue, 12 Jan 2021 00:00:00 +0000 Subject: [PATCH 2/3] 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. 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. --- compiler/rustc_metadata/src/rmeta/encoder.rs | 46 +++++++++++++------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index fd9908771072..f71233c9472c 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -792,9 +792,12 @@ impl EncodeContext<'a, 'tcx> { self.encode_generics(def_id); self.encode_explicit_predicates(def_id); self.encode_inferred_outlives(def_id); - self.encode_mir_for_ctfe(def_id.expect_local()); - 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_promoted_mir(def_id.expect_local()); + self.encode_mir_for_ctfe(def_id.expect_local()); } fn encode_info_for_mod(&mut self, id: hir::HirId, md: &hir::Mod<'_>, attrs: &[ast::Attribute]) { @@ -900,7 +903,10 @@ impl EncodeContext<'a, 'tcx> { 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()); } @@ -1029,14 +1035,25 @@ impl EncodeContext<'a, 'tcx> { } } 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 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) { debug!("EncodeContext::encode_info_for_impl_item({:?})", def_id); let tcx = self.tcx; @@ -1105,10 +1122,7 @@ impl EncodeContext<'a, 'tcx> { let (mir, mir_const) = match ast_item.kind { hir::ImplItemKind::Const(..) => (false, true), hir::ImplItemKind::Fn(ref sig, _) => { - let opt_mir = tcx.sess.opts.debugging_opts.always_encode_mir - || (self.emit_codegen_mir - && (tcx.generics_of(def_id).requires_monomorphization(tcx) - || tcx.codegen_fn_attrs(def_id).requests_inline())); + let opt_mir = self.should_encode_fn_opt_mir(def_id); let is_const_fn = sig.header.constness == hir::Constness::Const; (opt_mir, is_const_fn) } @@ -1432,10 +1446,7 @@ impl EncodeContext<'a, 'tcx> { let (mir, const_mir) = match item.kind { hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => (false, true), hir::ItemKind::Fn(ref sig, ..) => { - let opt_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir - || (self.emit_codegen_mir - && (tcx.generics_of(def_id).requires_monomorphization(tcx) - || tcx.codegen_fn_attrs(def_id).requests_inline())); + let opt_mir = self.should_encode_fn_opt_mir(def_id); let is_const_fn = sig.header.constness == hir::Constness::Const; // We don't need the optimized MIR for const fns. (opt_mir, is_const_fn) @@ -1498,8 +1509,11 @@ impl EncodeContext<'a, 'tcx> { 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) { From 16857317a6fb5bc966a0840c21d8000c2cd052ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Wed, 13 Jan 2021 00:00:00 +0000 Subject: [PATCH 3/3] Skip promoted mir of struct constructors & enum constructors --- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index f71233c9472c..6bf3336bd2f9 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -796,7 +796,6 @@ impl EncodeContext<'a, 'tcx> { if opt_mir { self.encode_optimized_mir(def_id.expect_local()); } - self.encode_promoted_mir(def_id.expect_local()); self.encode_mir_for_ctfe(def_id.expect_local()); } @@ -908,7 +907,6 @@ impl EncodeContext<'a, 'tcx> { 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) {