Skip to content

Increase parallelism in various locations #115003

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
9 changes: 7 additions & 2 deletions compiler/rustc_hir_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand All @@ -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(());
Expand Down
104 changes: 62 additions & 42 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
},
Expand Down Expand Up @@ -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", || {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain why putting those in parallel is interesting?

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()) {
Expand All @@ -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
Expand Down Expand Up @@ -1026,26 +1054,18 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) {
sess.time("misc_checking_3", || {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise.

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", || {
Expand Down
28 changes: 22 additions & 6 deletions compiler/rustc_middle/src/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::*;
Expand Down Expand Up @@ -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> {
Expand Down
19 changes: 15 additions & 4 deletions compiler/rustc_monomorphize/src/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -1671,9 +1671,20 @@ pub(crate) fn collect_crate_mono_items<'tcx>(
) -> (Vec<MonoItem<'tcx>>, 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");

Expand Down
Original file line number Diff line number Diff line change
@@ -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
|
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/span/issue-35987.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ struct Foo<T: Clone>(T);
use std::ops::Add;

impl<T: Clone, Add> Add for Foo<T> {
//~^ ERROR expected trait, found type parameter
//~^ ERROR expected trait, found type parameter
type Output = usize;

fn add(self, rhs: Self) -> Self::Output {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
|
Expand All @@ -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.
Expand Down
Loading