Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 01ae9a3

Browse files
committedFeb 29, 2024
Increase parallelism in various locations
1 parent 1a1876c commit 01ae9a3

16 files changed

+297
-132
lines changed
 

‎compiler/rustc_hir_analysis/src/check/wfcheck.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -1973,10 +1973,11 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
19731973

19741974
fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), ErrorGuaranteed> {
19751975
let items = tcx.hir_module_items(module);
1976-
let mut res = items.par_items(|item| tcx.ensure().check_well_formed(item.owner_id));
1977-
res = res.and(items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id)));
1978-
res = res.and(items.par_trait_items(|item| tcx.ensure().check_well_formed(item.owner_id)));
1979-
res = res.and(items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id)));
1976+
let mut res = items.try_par_items(|item| tcx.ensure().check_well_formed(item.owner_id));
1977+
res = res.and(items.try_par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id)));
1978+
res = res.and(items.try_par_trait_items(|item| tcx.ensure().check_well_formed(item.owner_id)));
1979+
res =
1980+
res.and(items.try_par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id)));
19801981
if module == LocalModDefId::CRATE_DEF_ID {
19811982
super::entry::check_for_entry_fn(tcx);
19821983
}

‎compiler/rustc_hir_analysis/src/collect.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ mod type_of;
5555
// Main entry point
5656

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

6161
pub fn provide(providers: &mut Providers) {

‎compiler/rustc_hir_analysis/src/lib.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ mod outlives;
9898
pub mod structured_errors;
9999
mod variance;
100100

101+
use rustc_data_structures::sync::par_for_each_in;
101102
use rustc_errors::ErrorGuaranteed;
102103
use rustc_hir as hir;
103104
use rustc_middle::middle;
@@ -163,7 +164,11 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
163164
// this ensures that later parts of type checking can assume that items
164165
// have valid types and not error
165166
tcx.sess.time("type_collecting", || {
166-
tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module))
167+
// Run dependencies of type collecting before entering the loop
168+
tcx.ensure_with_value().inferred_outlives_crate(());
169+
170+
let _prof_timer = tcx.sess.timer("type_collecting_loop");
171+
tcx.hir().par_for_each_module(|module| tcx.ensure().collect_mod_item_types(module));
167172
});
168173

169174
if tcx.features().rustc_attrs {
@@ -175,9 +180,10 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
175180
let res =
176181
tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_impl_wf(module));
177182

178-
for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
183+
par_for_each_in(tcx.all_local_trait_impls(()), |(trait_def_id, _)| {
179184
let _ = tcx.ensure().coherent_trait(trait_def_id);
180-
}
185+
});
186+
181187
// these queries are executed for side-effects (error reporting):
182188
let _ = tcx.ensure().crate_inherent_impls(());
183189
let _ = tcx.ensure().crate_inherent_impls_overlap_check(());

‎compiler/rustc_interface/src/passes.rs

+67-47
Original file line numberDiff line numberDiff line change
@@ -702,14 +702,28 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
702702
CStore::from_tcx(tcx).report_unused_deps(tcx);
703703
},
704704
{
705+
// Prefetch this as it is used later by the loop below
706+
// to prevent multiple threads from blocking on it.
707+
tcx.ensure_with_value().get_lang_items(());
708+
709+
let _timer = tcx.sess.timer("misc_module_passes");
705710
tcx.hir().par_for_each_module(|module| {
706711
tcx.ensure().check_mod_loops(module);
707712
tcx.ensure().check_mod_attrs(module);
708713
tcx.ensure().check_mod_naked_functions(module);
709-
tcx.ensure().check_mod_unstable_api_usage(module);
710714
tcx.ensure().check_mod_const_bodies(module);
711715
});
712716
},
717+
{
718+
// Prefetch this as it is used later by the loop below
719+
// to prevent multiple threads from blocking on it.
720+
tcx.ensure_with_value().stability_index(());
721+
722+
let _timer = tcx.sess.timer("check_unstable_api_usage");
723+
tcx.hir().par_for_each_module(|module| {
724+
tcx.ensure().check_mod_unstable_api_usage(module);
725+
});
726+
},
713727
{
714728
sess.time("unused_lib_feature_checking", || {
715729
rustc_passes::stability::check_unused_or_stable_features(tcx)
@@ -729,32 +743,48 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
729743
// passes are timed inside typeck
730744
rustc_hir_analysis::check_crate(tcx)?;
731745

732-
sess.time("MIR_borrow_checking", || {
733-
tcx.hir().par_body_owners(|def_id| {
734-
// Run unsafety check because it's responsible for stealing and
735-
// deallocating THIR.
736-
tcx.ensure().check_unsafety(def_id);
737-
tcx.ensure().mir_borrowck(def_id)
738-
});
739-
});
740-
741-
sess.time("MIR_effect_checking", || {
742-
for def_id in tcx.hir().body_owners() {
743-
if !tcx.sess.opts.unstable_opts.thir_unsafeck {
744-
rustc_mir_transform::check_unsafety::check_unsafety(tcx, def_id);
745-
}
746-
tcx.ensure().has_ffi_unwind_calls(def_id);
747-
748-
// If we need to codegen, ensure that we emit all errors from
749-
// `mir_drops_elaborated_and_const_checked` now, to avoid discovering
750-
// them later during codegen.
751-
if tcx.sess.opts.output_types.should_codegen()
752-
|| tcx.hir().body_const_context(def_id).is_some()
746+
sess.time("misc_checking_2", || {
747+
parallel!(
753748
{
754-
tcx.ensure().mir_drops_elaborated_and_const_checked(def_id);
755-
tcx.ensure().unused_generic_params(ty::InstanceDef::Item(def_id.to_def_id()));
749+
// Prefetch this as it is used later by lint checking and privacy checking.
750+
tcx.ensure_with_value().effective_visibilities(());
751+
},
752+
{
753+
sess.time("MIR_borrow_checking", || {
754+
tcx.hir().par_body_owners(|def_id| {
755+
// Run unsafety check because it's responsible for stealing and
756+
// deallocating THIR.
757+
tcx.ensure().check_unsafety(def_id);
758+
tcx.ensure().mir_borrowck(def_id)
759+
});
760+
});
761+
},
762+
{
763+
sess.time("MIR_effect_checking", || {
764+
for def_id in tcx.hir().body_owners() {
765+
if !tcx.sess.opts.unstable_opts.thir_unsafeck {
766+
rustc_mir_transform::check_unsafety::check_unsafety(tcx, def_id);
767+
}
768+
tcx.ensure().has_ffi_unwind_calls(def_id);
769+
770+
// If we need to codegen, ensure that we emit all errors from
771+
// `mir_drops_elaborated_and_const_checked` now, to avoid discovering
772+
// them later during codegen.
773+
if tcx.sess.opts.output_types.should_codegen()
774+
|| tcx.hir().body_const_context(def_id).is_some()
775+
{
776+
tcx.ensure().mir_drops_elaborated_and_const_checked(def_id);
777+
tcx.ensure()
778+
.unused_generic_params(ty::InstanceDef::Item(def_id.to_def_id()));
779+
}
780+
}
781+
});
782+
},
783+
{
784+
sess.time("layout_testing", || layout_test::test_layout(tcx));
785+
sess.time("abi_testing", || abi_test::test_abi(tcx));
756786
}
757-
}
787+
)
758788
});
759789

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

767-
sess.time("layout_testing", || layout_test::test_layout(tcx));
768-
sess.time("abi_testing", || abi_test::test_abi(tcx));
769-
770797
// Avoid overwhelming user with errors if borrow checking failed.
771798
// I'm not sure how helpful this is, to be honest, but it avoids a
772799
// lot of annoying errors in the ui tests (basically,
@@ -782,25 +809,18 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
782809
sess.time("misc_checking_3", || {
783810
parallel!(
784811
{
785-
tcx.ensure().effective_visibilities(());
786-
787-
parallel!(
788-
{
789-
tcx.ensure().check_private_in_public(());
790-
},
791-
{
792-
tcx.hir()
793-
.par_for_each_module(|module| tcx.ensure().check_mod_deathness(module));
794-
},
795-
{
796-
sess.time("lint_checking", || {
797-
rustc_lint::check_crate(tcx);
798-
});
799-
},
800-
{
801-
tcx.ensure().clashing_extern_declarations(());
802-
}
803-
);
812+
tcx.ensure().check_private_in_public(());
813+
},
814+
{
815+
tcx.hir().par_for_each_module(|module| tcx.ensure().check_mod_deathness(module));
816+
},
817+
{
818+
sess.time("lint_checking", || {
819+
rustc_lint::check_crate(tcx);
820+
});
821+
},
822+
{
823+
tcx.ensure().clashing_extern_declarations(());
804824
},
805825
{
806826
sess.time("privacy_checking_modules", || {

‎compiler/rustc_middle/src/hir/map/mod.rs

+34
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,40 @@ impl<'hir> Map<'hir> {
501501
V::Result::output()
502502
}
503503

504+
/// A parallel version of `visit_item_likes_in_module`.
505+
pub fn par_visit_item_likes_in_module<V>(
506+
&self,
507+
module: LocalModDefId,
508+
make_visitor: impl Fn() -> V + DynSync,
509+
) where
510+
V: Visitor<'hir>,
511+
{
512+
let module = self.tcx.hir_module_items(module);
513+
514+
parallel!(
515+
{
516+
module.par_items(|id| {
517+
make_visitor().visit_item(self.item(id));
518+
});
519+
},
520+
{
521+
module.par_trait_items(|id| {
522+
make_visitor().visit_trait_item(self.trait_item(id));
523+
});
524+
},
525+
{
526+
module.par_impl_items(|id| {
527+
make_visitor().visit_impl_item(self.impl_item(id));
528+
});
529+
},
530+
{
531+
module.par_foreign_items(|id| {
532+
make_visitor().visit_foreign_item(self.foreign_item(id));
533+
});
534+
}
535+
);
536+
}
537+
504538
pub fn for_each_module(self, mut f: impl FnMut(LocalModDefId)) {
505539
let crate_items = self.tcx.hir_crate_items(());
506540
for module in crate_items.submodules.iter() {

‎compiler/rustc_middle/src/hir/mod.rs

+21-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ pub mod place;
88

99
use crate::query::Providers;
1010
use crate::ty::{EarlyBinder, ImplSubject, TyCtxt};
11-
use rustc_data_structures::sync::{try_par_for_each_in, DynSend, DynSync};
11+
use rustc_data_structures::sync::{par_for_each_in, try_par_for_each_in, DynSend, DynSync};
1212
use rustc_hir::def::DefKind;
1313
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
1414
use rustc_hir::*;
@@ -56,33 +56,49 @@ impl ModuleItems {
5656
self.owners().map(|id| id.def_id)
5757
}
5858

59-
pub fn par_items(
59+
pub fn try_par_items(
6060
&self,
6161
f: impl Fn(ItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
6262
) -> Result<(), ErrorGuaranteed> {
6363
try_par_for_each_in(&self.items[..], |&id| f(id))
6464
}
6565

66-
pub fn par_trait_items(
66+
pub fn try_par_trait_items(
6767
&self,
6868
f: impl Fn(TraitItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
6969
) -> Result<(), ErrorGuaranteed> {
7070
try_par_for_each_in(&self.trait_items[..], |&id| f(id))
7171
}
7272

73-
pub fn par_impl_items(
73+
pub fn try_par_impl_items(
7474
&self,
7575
f: impl Fn(ImplItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
7676
) -> Result<(), ErrorGuaranteed> {
7777
try_par_for_each_in(&self.impl_items[..], |&id| f(id))
7878
}
7979

80-
pub fn par_foreign_items(
80+
pub fn try_par_foreign_items(
8181
&self,
8282
f: impl Fn(ForeignItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
8383
) -> Result<(), ErrorGuaranteed> {
8484
try_par_for_each_in(&self.foreign_items[..], |&id| f(id))
8585
}
86+
87+
pub fn par_items(&self, f: impl Fn(ItemId) + DynSend + DynSync) {
88+
par_for_each_in(&self.items[..], |&id| f(id))
89+
}
90+
91+
pub fn par_trait_items(&self, f: impl Fn(TraitItemId) + DynSend + DynSync) {
92+
par_for_each_in(&self.trait_items[..], |&id| f(id))
93+
}
94+
95+
pub fn par_impl_items(&self, f: impl Fn(ImplItemId) + DynSend + DynSync) {
96+
par_for_each_in(&self.impl_items[..], |&id| f(id))
97+
}
98+
99+
pub fn par_foreign_items(&self, f: impl Fn(ForeignItemId) + DynSend + DynSync) {
100+
par_for_each_in(&self.foreign_items[..], |&id| f(id))
101+
}
86102
}
87103

88104
impl<'tcx> TyCtxt<'tcx> {

‎compiler/rustc_monomorphize/src/collector.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@
165165
//! regardless of whether it is actually needed or not.
166166
167167
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
168-
use rustc_data_structures::sync::{par_for_each_in, MTLock, MTLockRef};
168+
use rustc_data_structures::sync::{join, par_for_each_in, MTLock, MTLockRef};
169169
use rustc_hir as hir;
170170
use rustc_hir::def::DefKind;
171171
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
@@ -260,8 +260,19 @@ pub fn collect_crate_mono_items(
260260
) -> (FxHashSet<MonoItem<'_>>, UsageMap<'_>) {
261261
let _prof_timer = tcx.prof.generic_activity("monomorphization_collector");
262262

263-
let roots =
264-
tcx.sess.time("monomorphization_collector_root_collections", || collect_roots(tcx, mode));
263+
let (roots, _) = join(
264+
|| {
265+
tcx.sess
266+
.time("monomorphization_collector_root_collections", || collect_roots(tcx, mode))
267+
},
268+
|| {
269+
if tcx.sess.opts.share_generics() {
270+
// Prefetch upstream_monomorphizations as it's very likely to be used in
271+
// code generation later and this is decent spot to compute it.
272+
tcx.ensure().upstream_monomorphizations(());
273+
}
274+
},
275+
);
265276

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

‎tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr

+12-22
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,32 @@
1-
error[E0391]: cycle detected when computing predicates of `Foo`
1+
error[E0391]: cycle detected when computing the inferred outlives predicates for items in this crate
2+
|
3+
note: ...which requires computing type of `Foo::bar`...
4+
--> $DIR/cycle-iat-inside-of-adt.rs:8:5
5+
|
6+
LL | bar: Self::Bar,
7+
| ^^^^^^^^^^^^^^
8+
note: ...which requires computing normalized predicates of `Foo`...
29
--> $DIR/cycle-iat-inside-of-adt.rs:7:1
310
|
411
LL | struct Foo {
512
| ^^^^^^^^^^
6-
|
713
note: ...which requires computing predicates of `Foo`...
814
--> $DIR/cycle-iat-inside-of-adt.rs:7:1
915
|
1016
LL | struct Foo {
1117
| ^^^^^^^^^^
12-
note: ...which requires computing inferred outlives predicates of `Foo`...
18+
note: ...which requires computing predicates of `Foo`...
1319
--> $DIR/cycle-iat-inside-of-adt.rs:7:1
1420
|
1521
LL | struct Foo {
1622
| ^^^^^^^^^^
17-
= note: ...which requires computing the inferred outlives predicates for items in this crate...
18-
note: ...which requires computing type of `Foo::bar`...
19-
--> $DIR/cycle-iat-inside-of-adt.rs:8:5
20-
|
21-
LL | bar: Self::Bar,
22-
| ^^^^^^^^^^^^^^
23-
note: ...which requires computing normalized predicates of `Foo`...
23+
note: ...which requires computing inferred outlives predicates of `Foo`...
2424
--> $DIR/cycle-iat-inside-of-adt.rs:7:1
2525
|
2626
LL | struct Foo {
2727
| ^^^^^^^^^^
28-
= note: ...which again requires computing predicates of `Foo`, completing the cycle
29-
note: cycle used when collecting item types in top-level module
30-
--> $DIR/cycle-iat-inside-of-adt.rs:3:1
31-
|
32-
LL | / #![feature(inherent_associated_types)]
33-
LL | | #![allow(incomplete_features)]
34-
LL | | // FIXME(inherent_associated_types): This should pass.
35-
LL | |
36-
... |
37-
LL | |
38-
LL | | fn main() {}
39-
| |____________^
28+
= note: ...which again requires computing the inferred outlives predicates for items in this crate, completing the cycle
29+
= note: cycle used when running analysis passes on this crate
4030
= 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
4131

4232
error: aborting due to 1 previous error
There was a problem loading the remainder of the diff.

0 commit comments

Comments
 (0)
Failed to load comments.