Skip to content

Commit

Permalink
Increase parallelism in various locations
Browse files Browse the repository at this point in the history
  • Loading branch information
Zoxc committed Feb 29, 2024
1 parent 1a1876c commit 01ae9a3
Show file tree
Hide file tree
Showing 16 changed files with 297 additions and 132 deletions.
9 changes: 5 additions & 4 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1973,10 +1973,11 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {

fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), ErrorGuaranteed> {
let items = tcx.hir_module_items(module);
let mut res = items.par_items(|item| tcx.ensure().check_well_formed(item.owner_id));
res = res.and(items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id)));
res = res.and(items.par_trait_items(|item| tcx.ensure().check_well_formed(item.owner_id)));
res = res.and(items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id)));
let mut res = items.try_par_items(|item| tcx.ensure().check_well_formed(item.owner_id));
res = res.and(items.try_par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id)));
res = res.and(items.try_par_trait_items(|item| tcx.ensure().check_well_formed(item.owner_id)));
res =
res.and(items.try_par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id)));
if module == LocalModDefId::CRATE_DEF_ID {
super::entry::check_for_entry_fn(tcx);
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ mod type_of;
// Main entry point

fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
tcx.hir().visit_item_likes_in_module(module_def_id, &mut CollectItemTypesVisitor { tcx });
tcx.hir().par_visit_item_likes_in_module(module_def_id, || CollectItemTypesVisitor { tcx });
}

pub fn provide(providers: &mut Providers) {
Expand Down
12 changes: 9 additions & 3 deletions compiler/rustc_hir_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ mod outlives;
pub mod structured_errors;
mod variance;

use rustc_data_structures::sync::par_for_each_in;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_middle::middle;
Expand Down Expand Up @@ -163,7 +164,11 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
// this ensures that later parts of type checking can assume that items
// have valid types and not error
tcx.sess.time("type_collecting", || {
tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module))
// Run dependencies of type collecting before entering the loop
tcx.ensure_with_value().inferred_outlives_crate(());

let _prof_timer = tcx.sess.timer("type_collecting_loop");
tcx.hir().par_for_each_module(|module| tcx.ensure().collect_mod_item_types(module));
});

if tcx.features().rustc_attrs {
Expand All @@ -175,9 +180,10 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
let res =
tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_impl_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 _ = tcx.ensure().coherent_trait(trait_def_id);
}
});

// these queries are executed for side-effects (error reporting):
let _ = tcx.ensure().crate_inherent_impls(());
let _ = tcx.ensure().crate_inherent_impls_overlap_check(());
Expand Down
114 changes: 67 additions & 47 deletions compiler/rustc_interface/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -702,14 +702,28 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
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_with_value().get_lang_items(());

let _timer = tcx.sess.timer("misc_module_passes");
tcx.hir().par_for_each_module(|module| {
tcx.ensure().check_mod_loops(module);
tcx.ensure().check_mod_attrs(module);
tcx.ensure().check_mod_naked_functions(module);
tcx.ensure().check_mod_unstable_api_usage(module);
tcx.ensure().check_mod_const_bodies(module);
});
},
{
// Prefetch this as it is used later by the loop below
// to prevent multiple threads from blocking on it.
tcx.ensure_with_value().stability_index(());

let _timer = tcx.sess.timer("check_unstable_api_usage");
tcx.hir().par_for_each_module(|module| {
tcx.ensure().check_mod_unstable_api_usage(module);
});
},
{
sess.time("unused_lib_feature_checking", || {
rustc_passes::stability::check_unused_or_stable_features(tcx)
Expand All @@ -729,32 +743,48 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
// passes are timed inside typeck
rustc_hir_analysis::check_crate(tcx)?;

sess.time("MIR_borrow_checking", || {
tcx.hir().par_body_owners(|def_id| {
// Run unsafety check because it's responsible for stealing and
// deallocating THIR.
tcx.ensure().check_unsafety(def_id);
tcx.ensure().mir_borrowck(def_id)
});
});

sess.time("MIR_effect_checking", || {
for def_id in tcx.hir().body_owners() {
if !tcx.sess.opts.unstable_opts.thir_unsafeck {
rustc_mir_transform::check_unsafety::check_unsafety(tcx, def_id);
}
tcx.ensure().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!(
{
tcx.ensure().mir_drops_elaborated_and_const_checked(def_id);
tcx.ensure().unused_generic_params(ty::InstanceDef::Item(def_id.to_def_id()));
// Prefetch this as it is used later by lint checking and privacy checking.
tcx.ensure_with_value().effective_visibilities(());
},
{
sess.time("MIR_borrow_checking", || {
tcx.hir().par_body_owners(|def_id| {
// Run unsafety check because it's responsible for stealing and
// deallocating THIR.
tcx.ensure().check_unsafety(def_id);
tcx.ensure().mir_borrowck(def_id)
});
});
},
{
sess.time("MIR_effect_checking", || {
for def_id in tcx.hir().body_owners() {
if !tcx.sess.opts.unstable_opts.thir_unsafeck {
rustc_mir_transform::check_unsafety::check_unsafety(tcx, def_id);
}
tcx.ensure().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().mir_drops_elaborated_and_const_checked(def_id);
tcx.ensure()
.unused_generic_params(ty::InstanceDef::Item(def_id.to_def_id()));
}
}
});
},
{
sess.time("layout_testing", || layout_test::test_layout(tcx));
sess.time("abi_testing", || abi_test::test_abi(tcx));
}
}
)
});

tcx.hir().par_body_owners(|def_id| {
Expand All @@ -764,9 +794,6 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
}
});

sess.time("layout_testing", || layout_test::test_layout(tcx));
sess.time("abi_testing", || abi_test::test_abi(tcx));

// Avoid overwhelming user with errors if borrow checking failed.
// I'm not sure how helpful this is, to be honest, but it avoids a
// lot of annoying errors in the ui tests (basically,
Expand All @@ -782,25 +809,18 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
sess.time("misc_checking_3", || {
parallel!(
{
tcx.ensure().effective_visibilities(());

parallel!(
{
tcx.ensure().check_private_in_public(());
},
{
tcx.hir()
.par_for_each_module(|module| tcx.ensure().check_mod_deathness(module));
},
{
sess.time("lint_checking", || {
rustc_lint::check_crate(tcx);
});
},
{
tcx.ensure().clashing_extern_declarations(());
}
);
tcx.ensure().check_private_in_public(());
},
{
tcx.hir().par_for_each_module(|module| tcx.ensure().check_mod_deathness(module));
},
{
sess.time("lint_checking", || {
rustc_lint::check_crate(tcx);
});
},
{
tcx.ensure().clashing_extern_declarations(());
},
{
sess.time("privacy_checking_modules", || {
Expand Down
34 changes: 34 additions & 0 deletions compiler/rustc_middle/src/hir/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,40 @@ impl<'hir> Map<'hir> {
V::Result::output()
}

/// A parallel version of `visit_item_likes_in_module`.
pub fn par_visit_item_likes_in_module<V>(
&self,
module: LocalModDefId,
make_visitor: impl Fn() -> V + DynSync,
) where
V: Visitor<'hir>,
{
let module = self.tcx.hir_module_items(module);

parallel!(
{
module.par_items(|id| {
make_visitor().visit_item(self.item(id));
});
},
{
module.par_trait_items(|id| {
make_visitor().visit_trait_item(self.trait_item(id));
});
},
{
module.par_impl_items(|id| {
make_visitor().visit_impl_item(self.impl_item(id));
});
},
{
module.par_foreign_items(|id| {
make_visitor().visit_foreign_item(self.foreign_item(id));
});
}
);
}

pub fn for_each_module(self, mut f: impl FnMut(LocalModDefId)) {
let crate_items = self.tcx.hir_crate_items(());
for module in crate_items.submodules.iter() {
Expand Down
26 changes: 21 additions & 5 deletions compiler/rustc_middle/src/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub mod place;

use crate::query::Providers;
use crate::ty::{EarlyBinder, ImplSubject, TyCtxt};
use rustc_data_structures::sync::{try_par_for_each_in, DynSend, DynSync};
use rustc_data_structures::sync::{par_for_each_in, try_par_for_each_in, DynSend, DynSync};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
use rustc_hir::*;
Expand Down Expand Up @@ -56,33 +56,49 @@ 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.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_items(&self, f: impl Fn(ItemId) + DynSend + DynSync) {
par_for_each_in(&self.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
17 changes: 14 additions & 3 deletions compiler/rustc_monomorphize/src/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@
//! regardless of whether it is actually needed or not.

use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::sync::{par_for_each_in, MTLock, MTLockRef};
use rustc_data_structures::sync::{join, par_for_each_in, MTLock, MTLockRef};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
Expand Down Expand Up @@ -260,8 +260,19 @@ pub fn collect_crate_mono_items(
) -> (FxHashSet<MonoItem<'_>>, UsageMap<'_>) {
let _prof_timer = tcx.prof.generic_activity("monomorphization_collector");

let roots =
tcx.sess.time("monomorphization_collector_root_collections", || collect_roots(tcx, mode));
let (roots, _) = join(
|| {
tcx.sess
.time("monomorphization_collector_root_collections", || collect_roots(tcx, mode))
},
|| {
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().upstream_monomorphizations(());
}
},
);

debug!("building mono item graph, beginning at roots");

Expand Down
Original file line number Diff line number Diff line change
@@ -1,42 +1,32 @@
error[E0391]: cycle detected when computing predicates of `Foo`
error[E0391]: cycle detected when 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
|
LL | bar: Self::Bar,
| ^^^^^^^^^^^^^^
note: ...which requires computing normalized predicates of `Foo`...
--> $DIR/cycle-iat-inside-of-adt.rs:7:1
|
LL | struct Foo {
| ^^^^^^^^^^
|
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`...
note: ...which requires computing predicates of `Foo`...
--> $DIR/cycle-iat-inside-of-adt.rs:7:1
|
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
|
LL | bar: Self::Bar,
| ^^^^^^^^^^^^^^
note: ...which requires computing normalized predicates of `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 predicates of `Foo`, completing the cycle
note: cycle used when collecting item types in top-level module
--> $DIR/cycle-iat-inside-of-adt.rs:3:1
|
LL | / #![feature(inherent_associated_types)]
LL | | #![allow(incomplete_features)]
LL | | // FIXME(inherent_associated_types): This should pass.
LL | |
... |
LL | |
LL | | fn main() {}
| |____________^
= 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
Loading

0 comments on commit 01ae9a3

Please sign in to comment.