Skip to content

Commit 306a768

Browse files
Auto merge of #149849 - zetanumbers:deterministic_cycles, r=<try>
Deterministic query cycles for parallel front-end
2 parents 377656d + 0a5000f commit 306a768

File tree

24 files changed

+644
-526
lines changed

24 files changed

+644
-526
lines changed

‎Cargo.lock‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4258,6 +4258,7 @@ dependencies = [
42584258
"bitflags",
42594259
"either",
42604260
"gsgdt",
4261+
"parking_lot",
42614262
"polonius-engine",
42624263
"rustc_abi",
42634264
"rustc_apfloat",

‎compiler/rustc_codegen_ssa/src/base.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use rustc_ast::expand::allocator::{
1010
};
1111
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
1212
use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
13-
use rustc_data_structures::sync::{IntoDynSyncSend, par_map};
1413
use rustc_data_structures::unord::UnordMap;
1514
use rustc_hir::attrs::{AttributeKind, DebuggerVisualizerType, OptimizeAttr};
1615
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE};
@@ -25,6 +24,7 @@ use rustc_middle::mir::BinOp;
2524
use rustc_middle::mir::interpret::ErrorHandled;
2625
use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem, MonoItemPartitions};
2726
use rustc_middle::query::Providers;
27+
use rustc_middle::sync::{IntoDynSyncSend, par_map};
2828
use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
2929
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
3030
use rustc_middle::{bug, span_bug};

‎compiler/rustc_data_structures/src/marker.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ impl_dyn_send!(
7575
[std::sync::Mutex<T> where T: ?Sized+ DynSend]
7676
[std::sync::mpsc::Sender<T> where T: DynSend]
7777
[std::sync::Arc<T> where T: ?Sized + DynSync + DynSend]
78+
[std::sync::Weak<T> where T: ?Sized + DynSync + DynSend]
7879
[std::sync::LazyLock<T, F> where T: DynSend, F: DynSend]
7980
[std::collections::HashSet<K, S> where K: DynSend, S: DynSend]
8081
[std::collections::HashMap<K, V, S> where K: DynSend, V: DynSend, S: DynSend]

‎compiler/rustc_data_structures/src/sync.rs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,17 @@ pub use parking_lot::{
3636
};
3737

3838
pub use self::atomic::AtomicU64;
39+
pub use self::branch_key::BranchKey;
3940
pub use self::freeze::{FreezeLock, FreezeReadGuard, FreezeWriteGuard};
4041
#[doc(no_inline)]
4142
pub use self::lock::{Lock, LockGuard, Mode};
4243
pub use self::mode::{is_dyn_thread_safe, set_dyn_thread_safe_mode};
43-
pub use self::parallel::{
44-
broadcast, join, par_for_each_in, par_map, parallel_guard, scope, spawn, try_par_for_each_in,
45-
};
44+
pub use self::parallel::{ParallelGuard, broadcast, parallel_guard, spawn};
4645
pub use self::vec::{AppendOnlyIndexVec, AppendOnlyVec};
4746
pub use self::worker_local::{Registry, WorkerLocal};
4847
pub use crate::marker::*;
4948

49+
mod branch_key;
5050
mod freeze;
5151
mod lock;
5252
mod parallel;
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use std::cmp;
2+
3+
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
4+
pub struct BranchKey(u128);
5+
6+
impl BranchKey {
7+
pub const fn root() -> Self {
8+
Self(0x80000000_00000000_00000000_00000000)
9+
}
10+
11+
fn bits_branch(self, branch_num: u128, bits: u32) -> Result<Self, BranchNestingError> {
12+
let trailing_zeros = self.0.trailing_zeros();
13+
let allocated_shift = trailing_zeros.checked_sub(bits).ok_or(BranchNestingError(()))?;
14+
Ok(BranchKey(
15+
self.0 & !(1 << trailing_zeros)
16+
| (1 << allocated_shift)
17+
| (branch_num << (allocated_shift + 1)),
18+
))
19+
}
20+
21+
pub fn branch(self, branch_num: u128, branch_space: u128) -> BranchKey {
22+
debug_assert!(
23+
branch_num < branch_space,
24+
"branch_num = {branch_num} should be less than branch_space = {branch_space}"
25+
);
26+
// floor(log2(n - 1)) + 1 == ceil(log2(n))
27+
self.bits_branch(branch_num, (branch_space - 1).checked_ilog2().map_or(0, |b| b + 1))
28+
.expect("query branch space is exhausted")
29+
}
30+
31+
pub fn disjoint_cmp(self, other: Self) -> cmp::Ordering {
32+
self.0.cmp(&other.0)
33+
}
34+
35+
pub fn nest(self, then: Self) -> Result<Self, BranchNestingError> {
36+
let trailing_zeros = then.0.trailing_zeros();
37+
let branch_num = then.0.wrapping_shr(trailing_zeros + 1);
38+
let bits = u128::BITS - trailing_zeros;
39+
self.bits_branch(branch_num, bits)
40+
}
41+
}
42+
43+
#[derive(Debug)]
44+
pub struct BranchNestingError(());
45+
46+
impl Default for BranchKey {
47+
fn default() -> Self {
48+
BranchKey::root()
49+
}
50+
}

‎compiler/rustc_data_structures/src/sync/parallel.rs‎

Lines changed: 0 additions & 182 deletions
Original file line numberDiff line numberDiff line change
@@ -43,54 +43,6 @@ pub fn parallel_guard<R>(f: impl FnOnce(&ParallelGuard) -> R) -> R {
4343
ret
4444
}
4545

46-
fn serial_join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
47-
where
48-
A: FnOnce() -> RA,
49-
B: FnOnce() -> RB,
50-
{
51-
let (a, b) = parallel_guard(|guard| {
52-
let a = guard.run(oper_a);
53-
let b = guard.run(oper_b);
54-
(a, b)
55-
});
56-
(a.unwrap(), b.unwrap())
57-
}
58-
59-
/// Runs a list of blocks in parallel. The first block is executed immediately on
60-
/// the current thread. Use that for the longest running block.
61-
#[macro_export]
62-
macro_rules! parallel {
63-
(impl $fblock:block [$($c:expr,)*] [$block:expr $(, $rest:expr)*]) => {
64-
parallel!(impl $fblock [$block, $($c,)*] [$($rest),*])
65-
};
66-
(impl $fblock:block [$($blocks:expr,)*] []) => {
67-
$crate::sync::parallel_guard(|guard| {
68-
$crate::sync::scope(|s| {
69-
$(
70-
let block = $crate::sync::FromDyn::from(|| $blocks);
71-
s.spawn(move |_| {
72-
guard.run(move || block.into_inner()());
73-
});
74-
)*
75-
guard.run(|| $fblock);
76-
});
77-
});
78-
};
79-
($fblock:block, $($blocks:block),*) => {
80-
if $crate::sync::is_dyn_thread_safe() {
81-
// Reverse the order of the later blocks since Rayon executes them in reverse order
82-
// when using a single thread. This ensures the execution order matches that
83-
// of a single threaded rustc.
84-
parallel!(impl $fblock [] [$($blocks),*]);
85-
} else {
86-
$crate::sync::parallel_guard(|guard| {
87-
guard.run(|| $fblock);
88-
$(guard.run(|| $blocks);)*
89-
});
90-
}
91-
};
92-
}
93-
9446
pub fn spawn(func: impl FnOnce() + DynSend + 'static) {
9547
if mode::is_dyn_thread_safe() {
9648
let func = FromDyn::from(func);
@@ -102,140 +54,6 @@ pub fn spawn(func: impl FnOnce() + DynSend + 'static) {
10254
}
10355
}
10456

105-
// This function only works when `mode::is_dyn_thread_safe()`.
106-
pub fn scope<'scope, OP, R>(op: OP) -> R
107-
where
108-
OP: FnOnce(&rustc_thread_pool::Scope<'scope>) -> R + DynSend,
109-
R: DynSend,
110-
{
111-
let op = FromDyn::from(op);
112-
rustc_thread_pool::scope(|s| FromDyn::from(op.into_inner()(s))).into_inner()
113-
}
114-
115-
#[inline]
116-
pub fn join<A, B, RA: DynSend, RB: DynSend>(oper_a: A, oper_b: B) -> (RA, RB)
117-
where
118-
A: FnOnce() -> RA + DynSend,
119-
B: FnOnce() -> RB + DynSend,
120-
{
121-
if mode::is_dyn_thread_safe() {
122-
let oper_a = FromDyn::from(oper_a);
123-
let oper_b = FromDyn::from(oper_b);
124-
let (a, b) = parallel_guard(|guard| {
125-
rustc_thread_pool::join(
126-
move || guard.run(move || FromDyn::from(oper_a.into_inner()())),
127-
move || guard.run(move || FromDyn::from(oper_b.into_inner()())),
128-
)
129-
});
130-
(a.unwrap().into_inner(), b.unwrap().into_inner())
131-
} else {
132-
serial_join(oper_a, oper_b)
133-
}
134-
}
135-
136-
fn par_slice<I: DynSend>(
137-
items: &mut [I],
138-
guard: &ParallelGuard,
139-
for_each: impl Fn(&mut I) + DynSync + DynSend,
140-
) {
141-
struct State<'a, F> {
142-
for_each: FromDyn<F>,
143-
guard: &'a ParallelGuard,
144-
group: usize,
145-
}
146-
147-
fn par_rec<I: DynSend, F: Fn(&mut I) + DynSync + DynSend>(
148-
items: &mut [I],
149-
state: &State<'_, F>,
150-
) {
151-
if items.len() <= state.group {
152-
for item in items {
153-
state.guard.run(|| (state.for_each)(item));
154-
}
155-
} else {
156-
let (left, right) = items.split_at_mut(items.len() / 2);
157-
let mut left = state.for_each.derive(left);
158-
let mut right = state.for_each.derive(right);
159-
rustc_thread_pool::join(move || par_rec(*left, state), move || par_rec(*right, state));
160-
}
161-
}
162-
163-
let state = State {
164-
for_each: FromDyn::from(for_each),
165-
guard,
166-
group: std::cmp::max(items.len() / 128, 1),
167-
};
168-
par_rec(items, &state)
169-
}
170-
171-
pub fn par_for_each_in<I: DynSend, T: IntoIterator<Item = I>>(
172-
t: T,
173-
for_each: impl Fn(&I) + DynSync + DynSend,
174-
) {
175-
parallel_guard(|guard| {
176-
if mode::is_dyn_thread_safe() {
177-
let mut items: Vec<_> = t.into_iter().collect();
178-
par_slice(&mut items, guard, |i| for_each(&*i))
179-
} else {
180-
t.into_iter().for_each(|i| {
181-
guard.run(|| for_each(&i));
182-
});
183-
}
184-
});
185-
}
186-
187-
/// This runs `for_each` in parallel for each iterator item. If one or more of the
188-
/// `for_each` calls returns `Err`, the function will also return `Err`. The error returned
189-
/// will be non-deterministic, but this is expected to be used with `ErrorGuaranteed` which
190-
/// are all equivalent.
191-
pub fn try_par_for_each_in<T: IntoIterator, E: DynSend>(
192-
t: T,
193-
for_each: impl Fn(&<T as IntoIterator>::Item) -> Result<(), E> + DynSync + DynSend,
194-
) -> Result<(), E>
195-
where
196-
<T as IntoIterator>::Item: DynSend,
197-
{
198-
parallel_guard(|guard| {
199-
if mode::is_dyn_thread_safe() {
200-
let mut items: Vec<_> = t.into_iter().collect();
201-
202-
let error = Mutex::new(None);
203-
204-
par_slice(&mut items, guard, |i| {
205-
if let Err(err) = for_each(&*i) {
206-
*error.lock() = Some(err);
207-
}
208-
});
209-
210-
if let Some(err) = error.into_inner() { Err(err) } else { Ok(()) }
211-
} else {
212-
t.into_iter().filter_map(|i| guard.run(|| for_each(&i))).fold(Ok(()), Result::and)
213-
}
214-
})
215-
}
216-
217-
pub fn par_map<I: DynSend, T: IntoIterator<Item = I>, R: DynSend, C: FromIterator<R>>(
218-
t: T,
219-
map: impl Fn(I) -> R + DynSync + DynSend,
220-
) -> C {
221-
parallel_guard(|guard| {
222-
if mode::is_dyn_thread_safe() {
223-
let map = FromDyn::from(map);
224-
225-
let mut items: Vec<(Option<I>, Option<R>)> =
226-
t.into_iter().map(|i| (Some(i), None)).collect();
227-
228-
par_slice(&mut items, guard, |i| {
229-
i.1 = Some(map(i.0.take().unwrap()));
230-
});
231-
232-
items.into_iter().filter_map(|i| i.1).collect()
233-
} else {
234-
t.into_iter().filter_map(|i| guard.run(|| map(i))).collect()
235-
}
236-
})
237-
}
238-
23957
pub fn broadcast<R: DynSend>(op: impl Fn(usize) -> R + DynSync) -> Vec<R> {
24058
if mode::is_dyn_thread_safe() {
24159
let op = FromDyn::from(op);

‎compiler/rustc_incremental/src/persist/save.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ use std::fs;
22
use std::sync::Arc;
33

44
use rustc_data_structures::fx::FxIndexMap;
5-
use rustc_data_structures::sync::join;
65
use rustc_middle::dep_graph::{
76
DepGraph, SerializedDepGraph, WorkProduct, WorkProductId, WorkProductMap,
87
};
8+
use rustc_middle::sync::join;
99
use rustc_middle::ty::TyCtxt;
1010
use rustc_serialize::Encodable as RustcEncodable;
1111
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};

‎compiler/rustc_interface/src/interface.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,7 @@ pub fn try_print_query_stack(
589589
if let Some(icx) = icx {
590590
ty::print::with_no_queries!(print_query_stack(
591591
QueryCtxt::new(icx.tcx),
592-
icx.query,
592+
icx.query.map(|i| i.id),
593593
dcx,
594594
limit_frames,
595595
file,

‎compiler/rustc_interface/src/passes.rs‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_codegen_ssa::{CodegenResults, CrateInfo};
1212
use rustc_data_structures::jobserver::Proxy;
1313
use rustc_data_structures::steal::Steal;
1414
use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, WorkerLocal};
15-
use rustc_data_structures::{parallel, thousands};
15+
use rustc_data_structures::thousands;
1616
use rustc_errors::timings::TimingSection;
1717
use rustc_expand::base::{ExtCtxt, LintStoreExpand};
1818
use rustc_feature::Features;
@@ -27,6 +27,7 @@ use rustc_metadata::EncodedMetadata;
2727
use rustc_metadata::creader::CStore;
2828
use rustc_middle::arena::Arena;
2929
use rustc_middle::dep_graph::DepsType;
30+
use rustc_middle::parallel;
3031
use rustc_middle::ty::{self, CurrentGcx, GlobalCtxt, RegisteredTools, TyCtxt};
3132
use rustc_middle::util::Providers;
3233
use rustc_parse::lexer::StripTokens;

‎compiler/rustc_lint/src/late.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ use std::any::Any;
77
use std::cell::Cell;
88

99
use rustc_data_structures::stack::ensure_sufficient_stack;
10-
use rustc_data_structures::sync::join;
1110
use rustc_hir::def_id::{LocalDefId, LocalModDefId};
1211
use rustc_hir::{self as hir, AmbigArg, HirId, intravisit as hir_visit};
1312
use rustc_middle::hir::nested_filter;
13+
use rustc_middle::sync::join;
1414
use rustc_middle::ty::{self, TyCtxt};
1515
use rustc_session::Session;
1616
use rustc_session::lint::LintPass;

0 commit comments

Comments
 (0)