From e7036069f865a696fc9815a2aa04c5cc9cfea510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 2 Jan 2020 15:35:38 +0100 Subject: [PATCH] Increase parallelism in various locations --- .../rustc_hir_analysis/src/check/wfcheck.rs | 23 ++-- compiler/rustc_hir_analysis/src/lib.rs | 9 +- compiler/rustc_interface/src/passes.rs | 104 +++++++++++------- compiler/rustc_middle/src/hir/mod.rs | 28 ++++- compiler/rustc_monomorphize/src/collector.rs | 19 +++- .../bugs/cycle-iat-inside-of-adt.stderr | 22 ++-- tests/ui/span/issue-35987.rs | 2 +- ...uggestion-trait-object-issue-139174.stderr | 12 +- 8 files changed, 137 insertions(+), 82 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 83d095ab72e82..e18353e113bcc 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -2323,14 +2323,21 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), ErrorGuaranteed> { let items = tcx.hir_module_items(module); - let res = items - .par_items(|item| tcx.ensure_ok().check_well_formed(item.owner_id.def_id)) - .and(items.par_impl_items(|item| tcx.ensure_ok().check_well_formed(item.owner_id.def_id))) - .and(items.par_trait_items(|item| tcx.ensure_ok().check_well_formed(item.owner_id.def_id))) - .and( - items.par_foreign_items(|item| tcx.ensure_ok().check_well_formed(item.owner_id.def_id)), - ) - .and(items.par_opaques(|item| tcx.ensure_ok().check_well_formed(item))); + let res = + items + .try_par_items(|item| tcx.ensure_ok().check_well_formed(item.owner_id.def_id)) + .and( + items.try_par_impl_items(|item| { + tcx.ensure_ok().check_well_formed(item.owner_id.def_id) + }), + ) + .and(items.try_par_trait_items(|item| { + tcx.ensure_ok().check_well_formed(item.owner_id.def_id) + })) + .and(items.try_par_foreign_items(|item| { + tcx.ensure_ok().check_well_formed(item.owner_id.def_id) + })) + .and(items.try_par_opaques(|item| tcx.ensure_ok().check_well_formed(item))); if module == LocalModDefId::CRATE_DEF_ID { super::entry::check_for_entry_fn(tcx); } diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index e7ecd727a852f..cc7c16780625e 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -94,6 +94,7 @@ mod variance; pub use errors::NoVariantNamed; use rustc_abi::ExternAbi; +use rustc_data_structures::sync::par_for_each_in; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_middle::middle; @@ -179,6 +180,9 @@ pub fn provide(providers: &mut Providers) { pub fn check_crate(tcx: TyCtxt<'_>) { let _prof_timer = tcx.sess.timer("type_check_crate"); + // Run dependencies of type checking before entering the loops below + tcx.ensure_done().inferred_outlives_crate(()); + tcx.sess.time("coherence_checking", || { // When discarding query call results, use an explicit type to indicate // what we are intending to discard, to help future type-based refactoring. @@ -188,9 +192,10 @@ pub fn check_crate(tcx: TyCtxt<'_>) { let _: R = tcx.ensure_ok().check_mod_type_wf(module); }); - for &trait_def_id in tcx.all_local_trait_impls(()).keys() { + par_for_each_in(tcx.all_local_trait_impls(()), |(trait_def_id, _)| { let _: R = tcx.ensure_ok().coherent_trait(trait_def_id); - } + }); + // these queries are executed for side-effects (error reporting): let _: R = tcx.ensure_ok().crate_inherent_impls_validity_check(()); let _: R = tcx.ensure_ok().crate_inherent_impls_overlap_check(()); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 93013c8b3f612..719cb73616fd8 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -912,10 +912,24 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { CStore::from_tcx(tcx).report_unused_deps(tcx); }, { + // Prefetch this as it is used later by the loop below + // to prevent multiple threads from blocking on it. + tcx.ensure_done().get_lang_items(()); + + let _timer = tcx.sess.timer("misc_module_passes"); tcx.par_hir_for_each_module(|module| { tcx.ensure_ok().check_mod_loops(module); tcx.ensure_ok().check_mod_attrs(module); tcx.ensure_ok().check_mod_naked_functions(module); + }); + }, + { + // Prefetch this as it is used later by the loop below + // to prevent multiple threads from blocking on it. + tcx.ensure_done().stability_index(()); + + let _timer = tcx.sess.timer("check_unstable_api_usage"); + tcx.par_hir_for_each_module(|module| { tcx.ensure_ok().check_mod_unstable_api_usage(module); }); }, @@ -950,28 +964,45 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { // This improves performance by allowing lock-free access to them. tcx.untracked().definitions.freeze(); - sess.time("MIR_borrow_checking", || { - tcx.par_hir_body_owners(|def_id| { - // Run unsafety check because it's responsible for stealing and - // deallocating THIR. - tcx.ensure_ok().check_unsafety(def_id); - tcx.ensure_ok().mir_borrowck(def_id) - }); - }); - sess.time("MIR_effect_checking", || { - tcx.par_hir_body_owners(|def_id| { - tcx.ensure_ok().has_ffi_unwind_calls(def_id); - - // If we need to codegen, ensure that we emit all errors from - // `mir_drops_elaborated_and_const_checked` now, to avoid discovering - // them later during codegen. - if tcx.sess.opts.output_types.should_codegen() - || tcx.hir_body_const_context(def_id).is_some() + sess.time("misc_checking_2", || { + parallel!( + { + // Prefetch this as it is used later by lint checking and privacy checking. + tcx.ensure_done().effective_visibilities(()); + }, + { + sess.time("MIR_borrow_checking", || { + tcx.par_hir_body_owners(|def_id| { + // Run unsafety check because it's responsible for stealing and + // deallocating THIR. + tcx.ensure_ok().check_unsafety(def_id); + tcx.ensure_ok().mir_borrowck(def_id) + }); + }); + }, { - tcx.ensure_ok().mir_drops_elaborated_and_const_checked(def_id); + sess.time("MIR_effect_checking", || { + tcx.par_hir_body_owners(|def_id| { + tcx.ensure_ok().has_ffi_unwind_calls(def_id); + + // If we need to codegen, ensure that we emit all errors from + // `mir_drops_elaborated_and_const_checked` now, to avoid discovering + // them later during codegen. + if tcx.sess.opts.output_types.should_codegen() + || tcx.hir_body_const_context(def_id).is_some() + { + tcx.ensure_ok().mir_drops_elaborated_and_const_checked(def_id); + } + }); + }); + }, + { + sess.time("layout_testing", || layout_test::test_layout(tcx)); + sess.time("abi_testing", || abi_test::test_abi(tcx)); } - }); + ) }); + sess.time("coroutine_obligations", || { tcx.par_hir_body_owners(|def_id| { if tcx.is_coroutine(def_id.to_def_id()) { @@ -988,9 +1019,6 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { }); }); - sess.time("layout_testing", || layout_test::test_layout(tcx)); - sess.time("abi_testing", || abi_test::test_abi(tcx)); - // If `-Zvalidate-mir` is set, we also want to compute the final MIR for each item // (either its `mir_for_ctfe` or `optimized_mir`) since that helps uncover any bugs // in MIR optimizations that may only be reachable through codegen, or other codepaths @@ -1026,26 +1054,18 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) { sess.time("misc_checking_3", || { parallel!( { - tcx.ensure_ok().effective_visibilities(()); - - parallel!( - { - tcx.ensure_ok().check_private_in_public(()); - }, - { - tcx.par_hir_for_each_module(|module| { - tcx.ensure_ok().check_mod_deathness(module) - }); - }, - { - sess.time("lint_checking", || { - rustc_lint::check_crate(tcx); - }); - }, - { - tcx.ensure_ok().clashing_extern_declarations(()); - } - ); + tcx.ensure_ok().check_private_in_public(()); + }, + { + tcx.par_hir_for_each_module(|module| tcx.ensure_ok().check_mod_deathness(module)); + }, + { + sess.time("lint_checking", || { + rustc_lint::check_crate(tcx); + }); + }, + { + tcx.ensure_ok().clashing_extern_declarations(()); }, { sess.time("privacy_checking_modules", || { diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index cae9b2fb5448c..ebac666c3ccab 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -9,7 +9,7 @@ pub mod place; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_data_structures::sync::{DynSend, DynSync, try_par_for_each_in}; +use rustc_data_structures::sync::{DynSend, DynSync, par_for_each_in, try_par_for_each_in}; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::*; @@ -79,40 +79,56 @@ impl ModuleItems { self.owners().map(|id| id.def_id) } - pub fn par_items( + pub fn try_par_items( &self, f: impl Fn(ItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync, ) -> Result<(), ErrorGuaranteed> { try_par_for_each_in(&self.free_items[..], |&id| f(id)) } - pub fn par_trait_items( + pub fn try_par_trait_items( &self, f: impl Fn(TraitItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync, ) -> Result<(), ErrorGuaranteed> { try_par_for_each_in(&self.trait_items[..], |&id| f(id)) } - pub fn par_impl_items( + pub fn try_par_impl_items( &self, f: impl Fn(ImplItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync, ) -> Result<(), ErrorGuaranteed> { try_par_for_each_in(&self.impl_items[..], |&id| f(id)) } - pub fn par_foreign_items( + pub fn try_par_foreign_items( &self, f: impl Fn(ForeignItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync, ) -> Result<(), ErrorGuaranteed> { try_par_for_each_in(&self.foreign_items[..], |&id| f(id)) } - pub fn par_opaques( + pub fn try_par_opaques( &self, f: impl Fn(LocalDefId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync, ) -> Result<(), ErrorGuaranteed> { try_par_for_each_in(&self.opaques[..], |&id| f(id)) } + + pub fn par_items(&self, f: impl Fn(ItemId) + DynSend + DynSync) { + par_for_each_in(&self.free_items[..], |&id| f(id)) + } + + pub fn par_trait_items(&self, f: impl Fn(TraitItemId) + DynSend + DynSync) { + par_for_each_in(&self.trait_items[..], |&id| f(id)) + } + + pub fn par_impl_items(&self, f: impl Fn(ImplItemId) + DynSend + DynSync) { + par_for_each_in(&self.impl_items[..], |&id| f(id)) + } + + pub fn par_foreign_items(&self, f: impl Fn(ForeignItemId) + DynSend + DynSync) { + par_for_each_in(&self.foreign_items[..], |&id| f(id)) + } } impl<'tcx> TyCtxt<'tcx> { diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 6e676ac6b8d53..0c840caceff33 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -209,7 +209,7 @@ use std::path::PathBuf; use rustc_attr_parsing::InlineAttr; use rustc_data_structures::fx::FxIndexMap; -use rustc_data_structures::sync::{MTLock, par_for_each_in}; +use rustc_data_structures::sync::{MTLock, join, par_for_each_in}; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_hir as hir; use rustc_hir::def::DefKind; @@ -1671,9 +1671,20 @@ pub(crate) fn collect_crate_mono_items<'tcx>( ) -> (Vec>, UsageMap<'tcx>) { let _prof_timer = tcx.prof.generic_activity("monomorphization_collector"); - let roots = tcx - .sess - .time("monomorphization_collector_root_collections", || collect_roots(tcx, strategy)); + let (roots, _) = join( + || { + tcx.sess.time("monomorphization_collector_root_collections", || { + collect_roots(tcx, strategy) + }) + }, + || { + if tcx.sess.opts.share_generics() { + // Prefetch upstream_monomorphizations as it's very likely to be used in + // code generation later and this is decent spot to compute it. + tcx.ensure_ok().upstream_monomorphizations(()); + } + }, + ); debug!("building mono item graph, beginning at roots"); diff --git a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr index 7f8ed89852522..847d864417893 100644 --- a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr +++ b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr @@ -1,15 +1,5 @@ -error[E0391]: cycle detected when computing predicates of `Foo` - --> $DIR/cycle-iat-inside-of-adt.rs:7:1 - | -LL | struct Foo { - | ^^^^^^^^^^ - | -note: ...which requires computing inferred outlives-predicates of `Foo`... - --> $DIR/cycle-iat-inside-of-adt.rs:7:1 +error[E0391]: cycle detected when computing the inferred outlives-predicates for items in this crate | -LL | struct Foo { - | ^^^^^^^^^^ - = note: ...which requires computing the inferred outlives-predicates for items in this crate... note: ...which requires computing type of `Foo::bar`... --> $DIR/cycle-iat-inside-of-adt.rs:8:5 | @@ -20,12 +10,18 @@ note: ...which requires computing normalized predicates of `Foo`... | LL | struct Foo { | ^^^^^^^^^^ - = note: ...which again requires computing predicates of `Foo`, completing the cycle -note: cycle used when checking that `Foo` is well-formed +note: ...which requires computing predicates of `Foo`... + --> $DIR/cycle-iat-inside-of-adt.rs:7:1 + | +LL | struct Foo { + | ^^^^^^^^^^ +note: ...which requires computing inferred outlives-predicates of `Foo`... --> $DIR/cycle-iat-inside-of-adt.rs:7:1 | LL | struct Foo { | ^^^^^^^^^^ + = note: ...which again requires computing the inferred outlives-predicates for items in this crate, completing the cycle + = note: cycle used when running analysis passes on this crate = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: aborting due to 1 previous error diff --git a/tests/ui/span/issue-35987.rs b/tests/ui/span/issue-35987.rs index d52a3793af971..7fa1a33ac84c1 100644 --- a/tests/ui/span/issue-35987.rs +++ b/tests/ui/span/issue-35987.rs @@ -3,7 +3,7 @@ struct Foo(T); use std::ops::Add; impl Add for Foo { -//~^ ERROR expected trait, found type parameter + //~^ ERROR expected trait, found type parameter type Output = usize; fn add(self, rhs: Self) -> Self::Output { diff --git a/tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr b/tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr index 0d1ce85fc2888..80f91076ffc14 100644 --- a/tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr +++ b/tests/ui/traits/object/suggestion-trait-object-issue-139174.stderr @@ -16,6 +16,12 @@ error[E0404]: expected trait, found builtin type `usize` LL | x: usize + 'a, | ^^^^^ not a trait +error[E0782]: expected a type, found a trait + --> $DIR/suggestion-trait-object-issue-139174.rs:16:8 + | +LL | x: usize + 'a, + | ^^^^^^^^^^ + error[E0782]: expected a type, found a trait --> $DIR/suggestion-trait-object-issue-139174.rs:3:36 | @@ -28,12 +34,6 @@ error[E0782]: expected a type, found a trait LL | fn create_adder<'a>(x: i32) -> usize + 'a { | ^^^^^^^^^^ -error[E0782]: expected a type, found a trait - --> $DIR/suggestion-trait-object-issue-139174.rs:16:8 - | -LL | x: usize + 'a, - | ^^^^^^^^^^ - error: aborting due to 6 previous errors Some errors have detailed explanations: E0404, E0782.